[Pkg-electronics-commits] [gplcver] 01/18: Imported Upstream version 2.11a

أحمد المحمودي (Ahmed El-Mahmoudy) aelmahmoudy at sabily.org
Thu Mar 26 12:16:17 UTC 2015


This is an automated email from the git hooks/post-receive script.

aelmahmoudy-guest pushed a commit to branch master
in repository gplcver.

commit 8dec7120da72482dbccbf3f0fb896bdc4a2e9534
Author: أحمد المحمودي (Ahmed El-Mahmoudy) <aelmahmoudy at users.sourceforge.net>
Date:   Thu Mar 26 11:50:41 2015 +0200

    Imported Upstream version 2.11a
---
 COPYING                                            |  340 +
 Changelog                                          |  210 +
 INSTALL                                            |   83 +
 LICENSE                                            |   17 +
 NEW.CVER.2001.RELEASE.NOTES                        |   80 +
 OUR_PHILOSOPHY                                     |   54 +
 README                                             |   89 +
 dinotrace.dir/README.dinotrace                     |   24 +
 dinotrace.dir/examples.dino/README                 |   20 +
 dinotrace.dir/examples.dino/dino_tst.sh            |   44 +
 dinotrace.dir/examples.dino/dmp.v                  |  245 +
 dinotrace.dir/examples.dino/dmp2.v                 |  246 +
 doc/README                                         |   30 +
 doc/cver-extensions.txt                            |   86 +
 doc/cver.FAQ                                       |  536 ++
 doc/cver.faq.htm                                   |  646 ++
 doc/cver.hlp                                       |  347 +
 doc/dbg.hlp                                        |  560 ++
 doc/systasks.1                                     | 1249 +++
 doc/systasks.pdf                                   |  Bin 0 -> 90731 bytes
 doc/systasks.ps                                    | 2256 +++++
 objs/makefile.dll                                  |   24 +
 pli_incs/acc_user.h                                |  538 ++
 pli_incs/cv_acc_user.h                             |   62 +
 pli_incs/cv_veriuser.h                             |  103 +
 pli_incs/cv_vpi_user.h                             |  127 +
 pli_incs/veriuser.h                                |  317 +
 pli_incs/vpi_user.h                                |  807 ++
 pli_src/README                                     |    8 +
 pli_src/infodmp.inc                                |  176 +
 src/INSTALL.README                                 |    5 +
 src/README                                         |   80 +
 src/cver.c                                         | 6002 +++++++++++++
 src/cvmacros.h                                     |  328 +
 src/dig_main.c                                     |   16 +
 src/makefile.amd64                                 |  153 +
 src/makefile.cygwin                                |  153 +
 src/makefile.freebsd                               |  147 +
 src/makefile.lnx                                   |  153 +
 src/makefile.osx                                   |  147 +
 src/makefile.sparc-gcc                             |  145 +
 src/systsks.h                                      |  246 +
 src/v.h                                            | 3671 ++++++++
 src/v_acc.c                                        | 8709 +++++++++++++++++++
 src/v_cnv.c                                        | 6221 ++++++++++++++
 src/v_dbg.c                                        | 3576 ++++++++
 src/v_dbg2.c                                       | 3955 +++++++++
 src/v_del.c                                        | 2861 +++++++
 src/v_ex.c                                         | 8470 +++++++++++++++++++
 src/v_ex2.c                                        | 6974 +++++++++++++++
 src/v_ex3.c                                        | 6670 +++++++++++++++
 src/v_ex4.c                                        | 5641 +++++++++++++
 src/v_fx.c                                         | 7745 +++++++++++++++++
 src/v_fx2.c                                        | 8854 ++++++++++++++++++++
 src/v_fx3.c                                        | 6730 +++++++++++++++
 src/v_ms.c                                         | 7263 ++++++++++++++++
 src/v_prp.c                                        | 4803 +++++++++++
 src/v_prp2.c                                       | 7206 ++++++++++++++++
 src/v_sdf.c                                        | 7342 ++++++++++++++++
 src/v_sim.c                                        | 7137 ++++++++++++++++
 src/v_src.c                                        | 6175 ++++++++++++++
 src/v_src2.c                                       | 4967 +++++++++++
 src/v_src3.c                                       | 6620 +++++++++++++++
 src/v_tf.c                                         | 5404 ++++++++++++
 src/v_trch.c                                       | 4747 +++++++++++
 src/v_vpi.c                                        | 6145 ++++++++++++++
 src/v_vpi2.c                                       | 6892 +++++++++++++++
 src/v_vpi3.c                                       | 7505 +++++++++++++++++
 src/veriuser.c                                     |   12 +
 src/vpiuser.c                                      |   18 +
 tests_and_examples/README                          |   39 +
 tests_and_examples/capacity.tst/README             |   21 +
 tests_and_examples/capacity.tst/lca100kgate/AN2.v  |    8 +
 tests_and_examples/capacity.tst/lca100kgate/AN3.v  |    8 +
 tests_and_examples/capacity.tst/lca100kgate/AN4.v  |    8 +
 tests_and_examples/capacity.tst/lca100kgate/AN5.v  |    8 +
 .../capacity.tst/lca100kgate/BUF8A.v               |    8 +
 tests_and_examples/capacity.tst/lca100kgate/EN.v   |    8 +
 tests_and_examples/capacity.tst/lca100kgate/FA1A.v |   12 +
 .../capacity.tst/lca100kgate/FD2.fix               |   20 +
 tests_and_examples/capacity.tst/lca100kgate/FD2.v  |   21 +
 .../capacity.tst/lca100kgate/FD2v.orig             |   19 +
 tests_and_examples/capacity.tst/lca100kgate/OR2.v  |    8 +
 tests_and_examples/capacity.tst/lca100kgate/OR3.v  |    8 +
 tests_and_examples/capacity.tst/lca100kgate/OR4.v  |    8 +
 tests_and_examples/capacity.tst/lca100kgate/OR5.v  |    8 +
 tests_and_examples/capacity.tst/lca100kgate/zero.v |   13 +
 tests_and_examples/capacity.tst/lfsr.plg           |   87 +
 tests_and_examples/capacity.tst/lfsr.sdf           |   24 +
 tests_and_examples/capacity.tst/lfsr.vc            |    3 +
 tests_and_examples/capacity.tst/lfsr32000.v        |  169 +
 tests_and_examples/capacity.tst/lfsr5udp.plg       |  109 +
 tests_and_examples/capacity.tst/lfsr5udp.v         |  178 +
 tests_and_examples/capacity.tst/lfsr_udp.vc        |    1 +
 tests_and_examples/examples.acc/README             |   66 +
 tests_and_examples/examples.acc/acc_nxtchld.c      |   74 +
 tests_and_examples/examples.acc/acc_nxtchld.plg    |   88 +
 tests_and_examples/examples.acc/acc_probe.c        |  210 +
 tests_and_examples/examples.acc/acc_probe.plg      |   69 +
 tests_and_examples/examples.acc/acc_prtchg.c       |  288 +
 tests_and_examples/examples.acc/accxl_drvld.c      |  181 +
 tests_and_examples/examples.acc/accxldrvtst.plg    |  263 +
 tests_and_examples/examples.acc/accxldrvtst.v      |   52 +
 tests_and_examples/examples.acc/clean.sh           |    1 +
 tests_and_examples/examples.acc/inst_pli.osx.sh    |   39 +
 tests_and_examples/examples.acc/inst_pli.sh        |   49 +
 tests_and_examples/examples.acc/makefile.lnx       |   37 +
 tests_and_examples/examples.acc/makefile.osx       |   38 +
 tests_and_examples/examples.acc/makefile.sparc-gcc |   37 +
 tests_and_examples/examples.acc/nc_fdsp.v          |  140 +
 tests_and_examples/examples.acc/pchg_fdsp.plg      |  320 +
 tests_and_examples/examples.acc/pchg_fdsp.v        |  140 +
 tests_and_examples/examples.acc/probe.v            |   20 +
 tests_and_examples/examples.acc/rmlic.pl           |   25 +
 tests_and_examples/examples.tf/README              |   70 +
 tests_and_examples/examples.tf/clean.sh            |    1 +
 tests_and_examples/examples.tf/inst_pli.osx.sh     |   40 +
 tests_and_examples/examples.tf/inst_pli.sh         |   50 +
 tests_and_examples/examples.tf/makefile.lnx        |   37 +
 tests_and_examples/examples.tf/makefile.osx        |   37 +
 tests_and_examples/examples.tf/makefile.sparc-gcc  |   43 +
 tests_and_examples/examples.tf/plimfil.c           |  151 +
 tests_and_examples/examples.tf/plimfil.plg         |   12 +
 tests_and_examples/examples.tf/plimfil.v           |   33 +
 tests_and_examples/examples.tf/plimfil2.c          |  158 +
 tests_and_examples/examples.tf/plimfil2.plg        |    7 +
 tests_and_examples/examples.tf/plimfil2.v          |   32 +
 tests_and_examples/examples.tf/probe.c             |  122 +
 tests_and_examples/examples.tf/probe.plg           |   92 +
 tests_and_examples/examples.tf/probe.v             |   20 +
 tests_and_examples/examples.tf/rmlic.pl            |   25 +
 tests_and_examples/examples.tf/testmem.dat         |   10 +
 tests_and_examples/examples.tf/testmem2.dat        |    5 +
 tests_and_examples/examples.tf/tfclk.c             |  144 +
 tests_and_examples/examples.tf/tfclk.plg           |   22 +
 tests_and_examples/examples.tf/tfclk.v             |   21 +
 tests_and_examples/examples.vpi/README             |  168 +
 tests_and_examples/examples.vpi/async.c            |  195 +
 tests_and_examples/examples.vpi/async.plg          |    8 +
 tests_and_examples/examples.vpi/async.v            |   21 +
 tests_and_examples/examples.vpi/cacatmd1.v         |   21 +
 tests_and_examples/examples.vpi/clean.sh           |    1 +
 tests_and_examples/examples.vpi/dfpsetd.c          |  167 +
 tests_and_examples/examples.vpi/dfpsetd.plg        |   10 +
 tests_and_examples/examples.vpi/dfpsetd.v          |   31 +
 tests_and_examples/examples.vpi/fdspec01.v         |  139 +
 tests_and_examples/examples.vpi/fff9               |  118 +
 tests_and_examples/examples.vpi/fff9.exp           |  118 +
 tests_and_examples/examples.vpi/findcaus.c         |  201 +
 tests_and_examples/examples.vpi/findcaus.plg       |   45 +
 tests_and_examples/examples.vpi/inst_pli.osx.sh    |  149 +
 tests_and_examples/examples.vpi/inst_pli.sh        |  160 +
 tests_and_examples/examples.vpi/makefile.cygwin    |   22 +
 tests_and_examples/examples.vpi/makefile.lnx       |  144 +
 tests_and_examples/examples.vpi/makefile.osx       |  144 +
 tests_and_examples/examples.vpi/makefile.sparc-gcc |  144 +
 tests_and_examples/examples.vpi/opt_vacbtst.inp    |   13 +
 tests_and_examples/examples.vpi/opt_vacbtst.plg    |   15 +
 tests_and_examples/examples.vpi/prtbg09.v          |   95 +
 tests_and_examples/examples.vpi/rmlic.pl           |   25 +
 tests_and_examples/examples.vpi/sparc.old          |  181 +
 tests_and_examples/examples.vpi/task10.v           |   58 +
 tests_and_examples/examples.vpi/timtst03.v         |   15 +
 tests_and_examples/examples.vpi/vacbtst.c          |  443 +
 tests_and_examples/examples.vpi/vacbtst.inp        |   20 +
 tests_and_examples/examples.vpi/vacbtst.plg        |  441 +
 tests_and_examples/examples.vpi/vchkprt1.c         |  519 ++
 tests_and_examples/examples.vpi/vconta1.c          |  322 +
 tests_and_examples/examples.vpi/vconta1.plg        |   31 +
 tests_and_examples/examples.vpi/vdrvld1.c          |  325 +
 tests_and_examples/examples.vpi/vdrvld1.plg        |  278 +
 tests_and_examples/examples.vpi/vdrvld2.c          |  341 +
 tests_and_examples/examples.vpi/vdrvld2.plg        |  250 +
 tests_and_examples/examples.vpi/vfopen1.c          |  162 +
 tests_and_examples/examples.vpi/vfopen1.plg        |    2 +
 tests_and_examples/examples.vpi/vfopen1.v          |   25 +
 tests_and_examples/examples.vpi/vfopen2.c          |  161 +
 tests_and_examples/examples.vpi/vfopen2.plg        |    2 +
 tests_and_examples/examples.vpi/vfopen2.v          |   25 +
 tests_and_examples/examples.vpi/vhelbad.c          |  174 +
 tests_and_examples/examples.vpi/vhelbad.plg        |    8 +
 tests_and_examples/examples.vpi/vhelbad.v          |   12 +
 tests_and_examples/examples.vpi/vhello1.c          |  110 +
 tests_and_examples/examples.vpi/vhello1.plg        |    3 +
 tests_and_examples/examples.vpi/vhello1.v          |   12 +
 tests_and_examples/examples.vpi/vhello2.c          |  210 +
 tests_and_examples/examples.vpi/vhello2.plg        |    7 +
 tests_and_examples/examples.vpi/vhello2.v          |   12 +
 tests_and_examples/examples.vpi/vpifout.fil        |    1 +
 tests_and_examples/examples.vpi/vpifout.xfl        |    1 +
 tests_and_examples/examples.vpi/vpiret.m01         |   29 +
 tests_and_examples/examples.vpi/vpitout.fil        |    1 +
 tests_and_examples/examples.vpi/vpitout.xfl        |    1 +
 tests_and_examples/examples.vpi/vprtchg.c          |  273 +
 tests_and_examples/examples.vpi/vprtchg.plg        |   37 +
 tests_and_examples/examples.vpi/vprtchg2.c         |  341 +
 tests_and_examples/examples.vpi/vprtchg2.plg       |   37 +
 tests_and_examples/examples.vpi/vprtchg3.c         |  397 +
 tests_and_examples/examples.vpi/vprtchg3.plg       |   37 +
 tests_and_examples/examples.vpi/vprtdel2.c         |  283 +
 tests_and_examples/examples.vpi/vprtdel2.plg       |    4 +
 tests_and_examples/examples.vpi/vprtdels.c         |  324 +
 tests_and_examples/examples.vpi/vprtdels.plg       |   46 +
 tests_and_examples/examples.vpi/vsetdels.c         |  335 +
 tests_and_examples/examples.vpi/vsetdels.plg       |   52 +
 tests_and_examples/examples.vpi/vsetval1.c         |  363 +
 tests_and_examples/examples.vpi/vsetval1.col       |  332 +
 tests_and_examples/examples.vpi/vsetval1.plg       |   12 +
 tests_and_examples/examples.vpi/vsetval1.v         |   62 +
 tests_and_examples/examples.vpi/vsetval2.c         |  446 +
 tests_and_examples/examples.vpi/vsetval2.plg       |   10 +
 tests_and_examples/examples.vpi/vsetval2.v         |   33 +
 tests_and_examples/examples.vpi/vtimcbs.c          |  261 +
 tests_and_examples/examples.vpi/vtimcbs.plg        |  142 +
 tests_and_examples/install.tst/JK_Q.v              |   69 +
 tests_and_examples/install.tst/JK_QBAR.v           |   71 +
 tests_and_examples/install.tst/README              |  176 +
 tests_and_examples/install.tst/arms.plg            |   20 +
 tests_and_examples/install.tst/arms_sim.v          |  395 +
 tests_and_examples/install.tst/armscnt.v           |  158 +
 tests_and_examples/install.tst/aspike1.plg         |   12 +
 tests_and_examples/install.tst/aspike1.v           |   17 +
 tests_and_examples/install.tst/aspike1a.plg        |   13 +
 tests_and_examples/install.tst/aspike1b.plg        |   12 +
 tests_and_examples/install.tst/aspike1c.plg        |   11 +
 tests_and_examples/install.tst/aspike1d.plg        |  111 +
 tests_and_examples/install.tst/c880.plg            |    8 +
 tests_and_examples/install.tst/c880.v              |  740 ++
 tests_and_examples/install.tst/defsplt1.plg        |    1 +
 tests_and_examples/install.tst/defsplt1.v          |   38 +
 tests_and_examples/install.tst/dffn.plg            |   66 +
 tests_and_examples/install.tst/dffn.v              |   72 +
 tests_and_examples/install.tst/dfpsetd.plg         |   10 +
 tests_and_examples/install.tst/dfpsetd.v           |   31 +
 tests_and_examples/install.tst/dfpsetd.vc          |    6 +
 tests_and_examples/install.tst/dfpsetd1.sdf        |    8 +
 tests_and_examples/install.tst/dfpsetd2.sdf        |   20 +
 tests_and_examples/install.tst/force01.inp         |   10 +
 tests_and_examples/install.tst/force01.plg         |   13 +
 tests_and_examples/install.tst/force01.v           |   20 +
 tests_and_examples/install.tst/gatenots.plg        |   21 +
 tests_and_examples/install.tst/gatenots.v          |  367 +
 tests_and_examples/install.tst/gn.mem              |   11 +
 tests_and_examples/install.tst/inst_tst.sh         |   96 +
 tests_and_examples/install.tst/instid.plg          |   16 +
 tests_and_examples/install.tst/instid.v            |   64 +
 tests_and_examples/install.tst/instpnd3.plg        |   46 +
 tests_and_examples/install.tst/instpnd3.v          |   89 +
 tests_and_examples/install.tst/jkff.v              |   14 +
 tests_and_examples/install.tst/mem.dat             |    9 +
 tests_and_examples/install.tst/minisim.plg         |   43 +
 tests_and_examples/install.tst/minisim.v           |  489 ++
 tests_and_examples/install.tst/mipdnot1.plg        |   29 +
 tests_and_examples/install.tst/mipdnot1.sdf        |    9 +
 tests_and_examples/install.tst/mipdnot1.v          |   40 +
 tests_and_examples/install.tst/mipdnot1.vc         |    2 +
 tests_and_examples/install.tst/patt.mem            |    8 +
 tests_and_examples/install.tst/rmlic.pl            |   25 +
 tests_and_examples/install.tst/sdfia04.plg         |   11 +
 tests_and_examples/install.tst/sdfia04.sdf         |   13 +
 tests_and_examples/install.tst/sdfia04.v           |   26 +
 tests_and_examples/install.tst/sdfia04.vc          |    2 +
 tests_and_examples/install.tst/smrd04.plg          |    2 +
 tests_and_examples/install.tst/smrd04.v            |   22 +
 tests_and_examples/install.tst/smrd04.vc           |    2 +
 tests_and_examples/install.tst/testmem.dat         |   10 +
 tests_and_examples/install.tst/udpjkff.plg         |   35 +
 tests_and_examples/install.tst/udpjkff.v           |   69 +
 tests_and_examples/install.tst/xplipnd.plg         |   16 +
 tests_and_examples/install.tst/xplipnd.v           |   67 +
 tests_and_examples/install.tst/xx2bdel.plg         |   33 +
 tests_and_examples/install.tst/xx2bdel.v           |   77 +
 tests_and_examples/install.tst/xx2bpth.plg         |   40 +
 tests_and_examples/install.tst/xx2bpth.v           |   87 +
 tests_and_examples/install.tst/xx2bpth2.plg        |   37 +
 tests_and_examples/install.tst/xx2bpth2.v          |   87 +
 tests_and_examples/install.tst/xxdel.tst           |    0
 tests_and_examples/v2001/README                    |   25 +
 tests_and_examples/v2001/arithtest.plg             |    5 +
 tests_and_examples/v2001/arithtest.v               |   25 +
 tests_and_examples/v2001/comparetest.plg           |    6 +
 tests_and_examples/v2001/comparetest.v             |   44 +
 tests_and_examples/v2001/config/README             |   33 +
 tests_and_examples/v2001/config/config1.map        |    7 +
 tests_and_examples/v2001/config/config1.plg        |    4 +
 tests_and_examples/v2001/config/config2.map        |    9 +
 tests_and_examples/v2001/config/config2.plg        |    4 +
 tests_and_examples/v2001/config/config3.map        |   10 +
 tests_and_examples/v2001/config/config3.plg        |    4 +
 tests_and_examples/v2001/config/config4.map        |    9 +
 tests_and_examples/v2001/config/config4.plg        |    4 +
 tests_and_examples/v2001/config/config5.map        |    9 +
 tests_and_examples/v2001/config/config5.plg        |    4 +
 tests_and_examples/v2001/config/config_tst.sh      |   34 +
 tests_and_examples/v2001/config/foo/foo.v          |    5 +
 tests_and_examples/v2001/config/foo/foo1.v         |    5 +
 tests_and_examples/v2001/config/foo/foo2.v         |    5 +
 tests_and_examples/v2001/config/lib/adder.v        |   11 +
 tests_and_examples/v2001/config/lib/bar.v          |    5 +
 tests_and_examples/v2001/config/test.v             |   15 +
 tests_and_examples/v2001/config/verilog.log        |    9 +
 tests_and_examples/v2001/dsign.plg                 |    4 +
 tests_and_examples/v2001/dsign.v                   |   12 +
 tests_and_examples/v2001/dsignedtest.plg           |    2 +
 tests_and_examples/v2001/dsignedtest.v             |   14 +
 tests_and_examples/v2001/fgets1.plg                |    6 +
 tests_and_examples/v2001/fgets1.v                  |   34 +
 tests_and_examples/v2001/getc1.plg                 |    6 +
 tests_and_examples/v2001/getc1.v                   |   34 +
 tests_and_examples/v2001/getc2.plg                 |    6 +
 tests_and_examples/v2001/getc2.v                   |   44 +
 tests_and_examples/v2001/infil.txt                 |    6 +
 tests_and_examples/v2001/inst_tst.sh               |   49 +
 tests_and_examples/v2001/lofptst.plg               |    1 +
 tests_and_examples/v2001/lofptst.v                 |   18 +
 tests_and_examples/v2001/verilog.log               |   14 +
 vcddiff.dir/Changelog                              |   23 +
 vcddiff.dir/README.vcddiff                         |  108 +
 vcddiff.dir/examples.vcddiff/README                |   24 +
 vcddiff.dir/examples.vcddiff/example.dump          |   69 +
 vcddiff.dir/examples.vcddiff/example2.dump         |   68 +
 .../examples.vcddiff/example_map_nochg.dump        |   69 +
 vcddiff.dir/examples.vcddiff/vcddiff_test.sh       |   28 +
 vcddiff.dir/src/INSTALL                            |    6 +
 vcddiff.dir/src/README                             |  108 +
 vcddiff.dir/src/makefile.lnx                       |   17 +
 vcddiff.dir/src/makefile.osx                       |   17 +
 vcddiff.dir/src/makefile.sparc                     |   17 +
 vcddiff.dir/src/vcddiff.c                          | 1543 ++++
 vcddiff.dir/src/vcddiff.h                          |   85 +
 ver_src/README                                     |   13 +
 ver_src/gatenots.v                                 |  367 +
 ver_src/hello.v                                    |    3 +
 ver_src/helpgen.inp                                |    7 +
 ver_src/helpgen2.inp                               |   30 +
 ver_src/helpgen3.inp                               |   65 +
 ver_src/simb.mem                                   |  224 +
 337 files changed, 200994 insertions(+)

diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+

+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+

+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+

+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+

+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+

+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Changelog b/Changelog
new file mode 100644
index 0000000..67bcc80
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,210 @@
+Tue Jun  1 15:42:34 CDT 2004
+
+  Initial release 200a of Cver with Verilog 2001 Support.  
+
+  This is a beta release.  See file NEW.CVER.2001.RELEASE.NOTES
+  for more information.  All bug fixes in 110i of Thu May 27 16:06:09
+  CDT 2004 are in 200a.
+
+Fri Jun 18 13:30:16 CDT 2004
+
+  Release 200b made with fixes to compiler directives to allow correct
+  compilation on all supported platforms.  200a contained some incorrectly 
+  placed compiler directives. Cygwin's lack of support for d_type in 
+  dirent structs was corrected using stat().
+
+Wed Aug 18 12:32:10 CDT 2004
+
+  Bug fix Release 2.00c.  2.00c is much more stable than 2.00b.
+
+1. Fixed wrong syntax error when @* was used instead of @(*).
+
+2. Changed port declaration code for both new ansii style port headers
+   and old style port headers to add the completed port definition concept,
+   i.e. new style port declarations are completed in the header.  Now,
+   for old style declarations, once the range and/or net type are given, the
+   port's definition is completed, and it is a syntax error to redeclare
+   the port.
+
+   There is still a possible minor problem because the wire declaration
+   continous assignment form can't be used with new ansii style port
+   declarations as specified in LRM.  Only assign keyword is allowed for
+   port wire continuous assigns.
+
+3. Fixed problem with tf_strgetp.  It was wrongly trimmming the input
+   string's leading zeros.       
+
+4. Removed incorrect bit and part select warning when @(*) was used and
+   the implicit event list needs to build bit part select elements where
+   ranges where not <high>:0 form.
+
+5. Fixed problem with both delay controls and event controls in modules
+   that require splitting because of per instance pound or def params.
+   The new implicit event control and event control list code would
+   sometimes overwrite the delay or event control expression with a 
+   different wrong expression.  Main symptom was that delays controls
+   delayed for the wrong amount of time in 200b.
+
+6. Fixed incorrect handling of the new Verilog 2001 file descriptors
+   in the vpi_ file I/O routines. 
+
+Thu Sep 16 09:50:08 CDT 2004
+
+  Bug fix Release 2.00d.  Some bugs in signed wide arithmetic fixed.
+
+1. Fixed bug in wide signed operations when one operand was signed
+   and another was unsigned (or 0).  The wide negate routines were
+   incorrectly setting bits higher than 32.
+
+2. Fixed bug in hold and hold part of setuphold.  Was wrongly
+   emitting timing check for 0 width pulse.
+
+3. Fixed bug in printing of signed values.  Smallest negative number
+   was printing as "-0" instead of its negative value.
+
+4. Fixed bug that caused "./[file]" form when used in `include directives 
+   to be treated as absolute path.  It is now correctly treated as
+   a relative path.
+ 
+Tue Oct 12 14:52:37 CDT 2004
+
+  Major release that adds more Verilog 2001 features, fixes problems
+related to new FPGA libraries that use Verilog 2001 features, and changes
+to explicitly sized C types so compile and run in 32 bit mode works
+on 64 bit Linux systems.
+
+1. Added support for initializing variable declaration assignments (see 2001
+   LRM section 6.2.1).  Example is: "integer i = 3;".   Following the LRM
+   the assignment is made at the beginning of time 0, so the initial value
+   will not be passed to declaration constructs until time 0.
+
+2. Fixed bug in wider than 32 bit arithmetic right shift.  This bug was
+   causing new FPGA designs using wide signed libraries to get wrong answers.
+
+3. Changed so that all types used in Cver source contain their explicit
+   size, i.e. int32, word32, word64 etc.  Change allows Cver to compile
+   and run in 32 bit mode on 64 bit Linux systems.
+
+4. Changed behavior of unsized number widening to follow Verilog 2001.
+   Now instead of widening unsized and unsigned constants where the high
+   order bit is x/z to 32 bits of x/z and then zeroing any high bits,
+   the number is x/z extended to the size of the expression containing
+   the number.  See Note at the bottom of the first page of section 2.5.1.
+   for discussion of the change.  This change is not backward compatible
+   with Verilog 1995 so if needed, we could put in a switch to turn it off.
+
+5. Fixed bug in signed mult and add and other binary operators whose
+   result width is determined by the operands.  The operation was wrongly
+   being evaluated as unsigned.
+
+6. Constant folding was wrongly removing signs.
+
+7. Multi-word widing was sometimes not sign extending or wrongly setting
+   some bits to x/z.  For very wide vector sign extends, the widening
+   would also sometimes core dump.  This happened for both signed and
+   unsigned widening.
+
+8. Fix bug in timing checks that was causing spurious and wrong extra 
+   timing violations to be detected and printed.  Problem was that
+   sometimes the data event was being recorded as the reference event.
+   It happened when a second data event edge occured within on time tick.
+
+9. Fixed parameter problem when a per instance value was set by a pound
+   or defparam and a design contained many constants.  The symptom was
+   a core dump during the second elaboration pass.
+
+Thu Feb  3 14:30:50 CST 2005
+
+  Minor release that fixes a a few problems involving not matching the LRM
+  (and other simulators).  Also a few changes to simplify code.
+
+1. Rewrote acc_next_load PLI routine algorithm to better match XL.  This
+   acc_ PLI routines requires matching XL port collapsing algorithm.  The new
+   version handles vectors and part selects better.
+
+2. Added support for function and task references that are upward relative,
+   but do not have any module name qualifier.  This is required by the LRM.
+   Result is that using a function or task name before declaration
+   causes searching both declarations later in the given module and
+   all function declarations in every declared module.  The scope rules are
+   then used to select the declaration in the current scope if declared later
+   or the the first declaration in a module above the current instance in the
+   instance tree.
+
+3. Fixed bug in $dumpvars.  When the scope form of $dumpvars was used,
+   an extra $upscope was generated at the end.
+
+4. Fixed problem with pound parameter over-rides for parameters that
+   were assigned values of other parameters in the parameter definition 
+   statement.  The over-riding parameter was not inhibiting assignments
+   when a right hand side parameter was changed.
+
+5. Fixed bug that sometimes caused internal error when printing hierarchical
+   part select names using PLI print routines.
+
+6. Fixed wrong error message when complex edge expressions were used
+   in modules that were resolved from library or config processing.
+
+Mon Feb 28 12:47:20 CST 2005
+
+  Minor release that mainly fixes a problem that caused some designs
+using Xilinx libraries to leak memory. 
+
+1. Fixed problem with shared constant table that caused non blocking 
+   assignments with left hand side variable indices to continually
+   allocate new constant indices during simulation.  Unfortunately,
+   this problem occurs in Xilinx libraries.  Memory leak would eventually
+   cause correct designs to run out of memory.
+
+2. Fixed some memory allocation and variable initialization problems that
+   caused configs to incorrectly fail.
+
+3. Fixed bug in vpi_ that results in incorrect error messages (and 
+   incorrect behavior) when bits of a vector were forced or released using 
+   vpi_.  Problem was a wrong error when vpi_ is used to force or release
+   anything but an entire vector.
+
+4. Fixed problem with unary not (~) not propagating left hand side
+   width down to operands of unary not following LRM rule.  This example
+   was previously not evaluating the ~ operator using left hand side
+   context "cg = ~(a << b);" 
+
+Tue Jul  5 13:53:17 CDT 2005
+
+  Major release 2.11a that hopefully fixes the problems simulating Xilinx
+libraries.  A number of problems that resulted in core dumps involving the
+combination of pound params and defparams are fixed.  Arrays of instances
+and gates had a significant problem that is fixed.  The non blocking
+scheduling algorithm has been changed to process non blocking events
+after all #0 events are processed following XL.  
+
+1. Changed the non blocking assignment algorithm to process all non blocking
+   assignments only after all #0 events have been processed.  Use the
+   new +no_separate_nb_queue to match old Cver behavior that combined
+   #0 and non blocking events into the same queue.
+
+2. Combinations of defparams and pound params often did not work but instead 
+   core dumped.  The Xilinx library used the pattern that caused the error.
+   Cver parameter handling should now be more solid.
+
+3. Fixed a number of signed arithmetic bugs.   Most bugs involved signed
+   shift or multiply.
+
+4. Implicit event control (@*) sometimes core dumped when there were
+   no implicit events to add to the event control list in the guarded block.
+
+5. Cver now recognizes and emits an error for generate keyword, but generate
+   is not supported still.  Elaboration syncs to the endgenerate keyword
+   so at least the rest of a design can be checked for syntax errors. 
+
+6. Arrays of instances core dumped when instances of the module containing
+   arrays of instances or gates were used in hierarchical references. 
+   The core dump did not occur if realloc did not move the memory area.
+   Arrays of instances and gates should now work.
+
+7. Declaration of local events in tasks and named blocks did not work.
+
+8. Continuous assigns with right hand side concatenates that needed widening
+   resulted in widening to z instead of 0.
+
+9. `include `[macro] now works.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..0fc8dc1
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,83 @@
+
+          INSTRUCTIONS FOR BUILDING AND TESTING GPL CVER
+
+
+  Building Cver is very easy because it is a self contained application
+program with very little dependence on any OS environment.  Currently,
+Cver is build using pre-made make files for X86 Linux, Sparc Solaris
+and Apple Mac OSX, but we are working on changing build process to using
+GNU configure command.
+
+A. MAKING CVER BINARY
+
+  To make GPL Cver,  change directory to src directory and type:
+
+   make -f [name of makefile] all
+
+Where [name of makefile] is one of makefile.lnx, makefile.sparc-gcc,
+or makefile.osx.  
+
+    A number of warning messages will be output by gcc. The warning are
+expected because the -Wall option in turned on in the make files by
+default.  You can eliminate the warnings by removing -Wall from the
+CFLAGS option list.
+
+    Because GPL Cver uses dymamic linking of user PLI routines
+(+loadpli1= and +loadvpi= option), GPL Cver consists of only one executable
+called cver.
+
+    The files in the pli_incs directory are the files supplied as part
+of the IEEE P1364 standard and are required for compiling GPL Cver and
+for building user dynamic link libraries.  The pre-built make files
+access the pli_inc include files by using relative path references (-I
+gcc and ld options).   In order to develop user PLI dynamic libraries,
+either copy the include files in the pli_incs directory to /usr/include
+or provide a -I<path name to pli_incs directory> as part of CFLAGS
+argument lists passed to gcc and ld.
+
+    When make completes, the cver binary will be in the bin
+directory.  You should copy cver into a directory that is on your PATH OS
+environment variable list such as /usr/local/bin.
+
+    See the README file in the src directory for instructions on how to make
+a debugging version of cver (compiled with -g flag) and for hints on
+modifying make files for other platforms and operating systems.
+
+B. CLEANING UP THE SRC DIRECTORY
+
+   If you make a mistake or want to re-make GPL cver, you can always run
+
+     make -f [name of makefile] clean
+
+This erases all files made by "make all" including the cver binary
+in the "bin" directory and the object files in the "objs" directory.
+
+B. RUNNING INSTALLATION TESTS
+
+    We recommend that you next run the various installation tests in
+the "tests_and_examples" directory.   You should always run the
+basic functionality test in the install.tst directory by executing
+the "inst_tst.sh" script.  There should be no diff output messages
+printed.  See the README file in the install.tst directory for
+more information.  If you plan to use any of the PLI interfaces,
+the dinotrace wave form viewer or the vcddiff VCD output file compare
+program, you should run the tests in the appropriate directory in
+the "tests_and_examples" directory.  The shell scripts in the installation
+directories have relative paths names built in, so you must not change
+the GPL cver release directory structure before running the test shell
+scripts.  In particular, you must leave cver binary in the "bin" directory.
+
+     See the README files in each of the install directories for detailed
+instructions on running the tests.  The "capacity.tst" directory contains
+very large gate level designs.  If you think you have hardware problems,
+we suggest you run the large tests in that directory.
+
+     If you are not sure what version of cver you are running.  Execute
+the cver command with no arguments and it will print out its version.
+Type "cver -h" for a help page of cver options and features.
+
+C. OBTAINING PRECOMPILED CVER BINARY
+
+     Precompiled cver binaries for X86 Linux, Sparc Solaris and Apple
+MacOS are available from the GPL cver home page at
+http://www.pragmatic-c.com/gpl-cver
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..e4b5cad
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,17 @@
+  The files in the src, lib, toolbin, examples, doc and man
+  directories and any subdirectories thereof are part of GPL Cver.
+
+  GPL Cver is free software; you can redistribute it and/or
+  modify it under the terms of version 2 of the GNU General Public
+  License as published by the Free Software Foundation.
+
+  GPL Cver is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program so you can know your rights and responsibilities.
+  It should be in a file named doc/COPYING. If not, write to the
+  Free Software Foundation, Inc., 59 Temple Place Suite 330, Boston, MA
+  02111-1307, USA.
diff --git a/NEW.CVER.2001.RELEASE.NOTES b/NEW.CVER.2001.RELEASE.NOTES
new file mode 100644
index 0000000..a23288b
--- /dev/null
+++ b/NEW.CVER.2001.RELEASE.NOTES
@@ -0,0 +1,80 @@
+
+RELEASE NOTES FOR VERILOG 2001 BETA FOR PEOPLE TO TRY 
+
+  This directory contains release of a new code base that supports many
+  of the Verilog 2001 features as described in IEEE P1364 Verilog 2001
+  Language Reference Manual.  We also have just released gplcver-1.10i
+  that fixes quite a few bugs.  We suggest you use that release for 
+  production.  There are no known bugs in 110i other than some limitations
+  that will be fixed in this gplcver-2.xx source base.
+
+  To our knowledge this new 2.0 release produces identical result to 110i
+  for Verilog 1995 designs.  2.0 supports the following Verilog
+  2001 features:
+
+    1) Implements Verilog 2001 signed evaluation algorithm.  Supports signed
+       keyword and signed constants plus handles sign extension during
+       expression evaluation.
+
+    2) Support for Verilog 2001 config.  Use the +config [config file name] 
+       option to specify the library mapping file.  You can place a file
+       named lib.map in your current directory, but that is not recommended
+       since it will always silently use that file for configuring your
+       design. See tests_and_examples/v2001/config for some small examples.
+
+    3) Supports new file io Unix Stdlib stream file input and output
+       operations.
+   
+    5) Supports new module and task port and module parameter header  
+       declarations.  Here is an example:
+
+
+            module test
+             #(parameter integer p1 = 5,
+               parameter p2 = 7,
+               parameter r1 = 7.3
+              )
+
+             (
+              input [7:0] a,
+              input signed [7:0] b, c, d,
+              output [7:0] e,
+              output signed [7:0] f,g,
+              output signed [7:0] h
+             ) ;
+
+             task my_task(input a, b, inout c, output signed [15:0] d, e);
+              begin
+               c = a;
+               d = f;
+               e= 2*f;
+              end
+             endtask
+            endmodule
+
+    6) Supports Verilog 2001 implicit event calculation forms @(*) and
+       @*.  Also supports events lists with comma as substitute for
+       event or.  Now (a, b, c) and (a or b or c) are both legal.
+       You can see the result of @(*) by running cver with the -c and -d
+       options (-c means compile only and -d means dump internal net list).
+
+  The new 2.0 version of Cver is beta code and we know there are many
+  problems still, but it runs basic examples of all the new features. 
+  We are releasing it because we think we can now fix bugs quickly and
+  because we need more test cases.  Please report any bugs.  We think
+  we can provide bug fixes (or work arounds) within a few days.
+
+  Our current main problem areas are that we do not understand the
+  config and @(*) sensitivity list algorithms.  We think file io and
+  signed evaluation follow the LRM.  There are some known memory leaks 
+  in this release that we will once the code is more stable.  We are
+  releasing 2.0 because we think we can make faster progress if we have bug
+  reports to work from.
+
+  Main Verilog 2001 features that are multi-dimensional arrays and
+  generate.  We also think we can add whatever other minor Verilog 2001
+  features are still missing quickly.
+
+  See tests_and_example/v2001 for a growing directory of verilog 2001 test
+  files. 
+  
diff --git a/OUR_PHILOSOPHY b/OUR_PHILOSOPHY
new file mode 100644
index 0000000..4c6c4bc
--- /dev/null
+++ b/OUR_PHILOSOPHY
@@ -0,0 +1,54 @@
+
+                 PHILOSOPHICAL JUSTIFICATION OF GPL CVE
+
+  We believe strongly that software should be distributed with source. 
+  This allows users to study and understand Verilog algorithms as part
+  of the circuit verification process. 
+
+  However, since Pragmatic C is a commercial enterprise with salaries
+  to pay, it does not make sense to release our software using only
+  the open source model.  We have decided to follow the method used
+  to distribute Ghostscript.  Namely, we are releasing an older version
+  called GPL Cver under the GNU General Public License (GPL) and a newer
+  version under a commercial license.  We have chosen to release the
+  older GPL Cver version using the GNU GPL license because it is currently
+  the most popular free software license and because it allows the
+  widest distribution. 
+
+  We are not sure if the GNU development model will work with Ecad software
+  tools such as Verilog simulators so we have not yet set up a formal system
+  for user contributions.  One problem is that much of the current Cver
+  behavior is the result of commercial users reporting mismatches with
+  the de facto standard Cadence Verilog XL (TM) simulator.
+
+  We think that the combination of GPL and commercial higher speed version
+  is particularly good for Ecad software.  The GPL version allows 
+  archiving the exact simulator source used for circuit sign off  
+  along with design data so if there is a need for future changes, 
+  the full set of design data (i.e. including the simulator used to process
+  the data) can be retrieved to recreate the exact sign off conditions. 
+  The commercial version facilitates running more regression tests during
+  commercial circuit development.
+
+  Since we are concerned about the high unemployment rate among programmers
+  and design engineers, we want to encourage people to write their own
+  commercial Ecad programs that communicate with Cver using the IEEE P1364
+  Verilog HDL standard PLI API.  We believe that whoever wrote the PLI
+  program should be able to select the type of license for software for
+  which they hold the copyright.  Also, we believe that the GPL does not
+  prohibit commercial programs (or any non GPL licensed programs for that
+  matter) from being dynamically loaded and run by GPL Cver using the PLI API.
+  We think the Linux operating system analogy applies.  Namely, it is
+  acceptable to have Linux load executable programs (such as dynamically
+  linked .so PLI programs) not licensed under GPL or LGPL.  We believe GPL
+  Cver loading and execution of commercial programs is the same as Linux OS
+  executing commercial programs that communicate through the standardized
+  system call API.  However, we are not lawyers so you should consult a lawyer
+  to help you decide how to license your PLI programs.
+
+  We would like to hear your problems and suggestions (seen email to
+  avanvick at pragmatic-c.com)
+
+--
+  TM - Verilog XL is a trademark of Cadence Design Systems, Inc.
+  to GNU type group software development.
diff --git a/README b/README
new file mode 100644
index 0000000..7972347
--- /dev/null
+++ b/README
@@ -0,0 +1,89 @@
+GPL Cver  
+
+  ------------------------------------------------------------------------
+Cver is a full 1995 IEEE P1364 standard Verilog simulator.  It also
+implements some of the 2001 P1364 standard features.  All three
+PLI interfaces (tf_, acc_, and vpi_) are implemented as defined
+in the IEEE 2001 P1364 LRM.
+
+
+A. OBTAINING GPL CVER
+
+GPL Cver is a copyrighted work (Pragmatic C Software Corp. owns the
+copyright); it is not shareware or in the public domain.
+
+Versions of Cver entitled "GPL Cver" are distributed with the GNU General
+Public License, which allows free use, and free copying and redistribution
+under certain conditions (including, in some cases, commercial
+distribution).  The home page for GPL Cver is:
+
+     http://www.pragmatic-c.com/gpl-cver
+
+You can always download the latest GPL Cver release from that site.
+
+GPL Cver is an older version of Cver that is released under the GNU
+General Public License.  A newer and faster commercial version of Cver
+is available from Pragmatic C Software Corp.
+
+
+B. WHAT PLATFORMS DOES GPL CVER RUN ON?
+
+Pre-compiled binaries and pre-built make files are available for
+X86 Linux, Sparc Solaris, Apple Mac OSX, and Cygwin (a Linux-like 
+envirnoment for Windows, make file only).  Because Cver is an interpreter, 
+it should easily port to any system that supports the gcc GNU C compiler.  The 
+main porting complication is usually related to Cver's use of dlsym/dlopen 
+programming dynamic library linking. 
+
+
+C. WHICH GPL CVER FILE SHOULD I DOWNLOAD? 
+
+After clicking on the source or binaries (for now the links to to the
+same download instructions), select which bzipped tar file to download.
+If you intend to run GPL CVER on one of the platforms for which pre-built
+binaries exist, download that file.   If you intend to run on another
+platform or want to make your own binary, click on the source bzipped
+tar file.  After bunzipping and untarring, the four files are identical
+except the binary files contain cver compiled for the given platform
+in the bin directory.
+
+D. WHAT OTHER PROGRAMS ARE INCLUDED IN THE GPL CVER RELEASE
+
+Vcddiff
+   Current GPL Cver release includes a program similar to the Unix
+   diff command called vcddiff.  It is a specialized diff that understands
+   Verilog VCD files.  It is also distributed with the GNU General Public
+   License, which allows free use, and free copying and redistribution.
+   Vcddiff is a copyrighted work (Pragmatic C Software Corp. owns the
+   copyright); it is not shareware or in the public domain.
+
+   vcddiff is contained in the vcddiff.dir directory at the top level
+   of the directory produced when the release tarball is untarred.
+   The src directory contains instructions and pre-build make files
+   for the normal three platforms (X86 Linux, Sparc Solaris, and Mac OSX).
+   Run the tests in the examples.vcddiff directory in the vcddiff.dir
+   directory.  For more information see th README files each of those
+   directories.
+   
+Dinotrace
+   Dinotrace binary is included in the platform specific release bzipped
+   tar files.  It is an open source wave form viewer that was
+   originally developed by DEC.  You can download source from 
+   http://www.veripool.com/dinotrace.  The linux binary dinotrace was
+   built on Red Hat Linux using GLIBC_3.2.  If you are running an older
+   linux release, you may need to download dinotrace source from the
+   dinotrace home page and make a dinotrace binary for your system.
+
+
+E. WHERE TO GO NEXT
+
+   After obtaining the GPL Cver tar ball, start by reading the README file.
+Instructions for building a new GPL Cver binary from source are in
+the INSTALL file.  There are various README and LICENSE files contained
+in the top level of the GPL Cver release directory tree.  Cver documentation
+is in the "doc" directory.
+
+
+F. GETTING HELP OR REPORTING BUGS
+
+  Send email to avanvick at pragmatic-c.com.
diff --git a/dinotrace.dir/README.dinotrace b/dinotrace.dir/README.dinotrace
new file mode 100644
index 0000000..ce4340c
--- /dev/null
+++ b/dinotrace.dir/README.dinotrace
@@ -0,0 +1,24 @@
+
+NOTE SJM: I will add the licensing boiler plate
+
+Dinotrace is a free software waveform viewer that reads verilog value change 
+dump files. It has been included in the dinotrace.dir directory, and the 
+executable is included in the bin directory. There is a shell script that
+runs Cver, creates a dump file and loads it into Dinotrace in 
+tests_and_examples/examples.dino.
+
+Dinotrace runs on all platforms currently supported by Cver.  Dinotrace needs
+both, Motif or LessTIF (www.lesstif.org), and a X11 server (www.xfree86.org). 
+If it doesn't run properly on your system, cd to the dinotrace-*, and run 
+'./configure'. This builds a make file for a particular system, next type 'make' or 'make install'. There is Dinotrace documentation in the directory, or 
+you can go to www.veripool.com/dinotrace for the latest information or release.
+ 
+Dinotrace reads the 'verilog.dump' file which Cver creates, when $dumpvars is
+called.  See tests_and_examples/examples.dino/dmp.v or the LRM for different
+calls to create a dump file. Dinotrace can take a dumpfile from the command 
+line or can load them from the GUI.  It loads all signals which can be
+deleted from the display by chosing either 'Delete' or 'Select' from the 
+'Signals' menu.  An easier method would be to give the signal names to 
+$dumpvars(sig1, sig2, ....), which writes only these variables to the dump
+file, which can then be loaded into Dinotrace.
+  
diff --git a/dinotrace.dir/examples.dino/README b/dinotrace.dir/examples.dino/README
new file mode 100644
index 0000000..99ba20e
--- /dev/null
+++ b/dinotrace.dir/examples.dino/README
@@ -0,0 +1,20 @@
+To test the Dinotrace waveform viewer:
+
+BEFORE STARTING:
+   Make a binary Cver (see INSTALL or README file in src directory) and
+   run the shell script in install.tst directory to verify correct build.
+   
+   You must also have a dinotrace in the top level bin directory as well.
+
+
+To run the Dinotrace waveform viewer run 'dino_tst.sh' in this directory.  
+If the shell script is passed no arguments, it will run dmp.v by default 
+creating a file called verilog.dump, which is then passed to dinotrace to 
+view the waveform.  If 'dino_tst.sh dmp2.v', it will create xx.dmp, and run
+dinotrace on this file as well. Cver creates verilog.dump by default when
+$dumpvars is called, otherise $dumpfile can be called to rename the dump file
+as is the case with dmp2.v, renaming the file to xx.dmp.
+
+Different types of $dumpvar calls are commented out in dmp.v, view the file to 
+see various dump calls, or consult the LRM for more information. If dinotrace 
+doesn't load, or for more infomation see  the README.dinotrace on level up.
diff --git a/dinotrace.dir/examples.dino/dino_tst.sh b/dinotrace.dir/examples.dino/dino_tst.sh
new file mode 100755
index 0000000..2c9ff6c
--- /dev/null
+++ b/dinotrace.dir/examples.dino/dino_tst.sh
@@ -0,0 +1,44 @@
+#!/bin/sh 
+# install test procedures
+
+CVER="../../bin/cver" 
+DINO="../../bin/dinotrace"
+
+
+if test ! -f $CVER
+then
+  echo "There is no cver in ../../bin/"
+  echo "Make a cver in ../../src" 
+  exit;
+fi
+
+if test ! -f $DINO
+then
+  echo "There is no dinotrace"
+  echo "Make a dinotrace in ../../dinotrace.dir" 
+  exit;
+fi
+
+if test $1 
+then
+  NAME=$1
+else
+  NAME="dmp.v"
+fi
+
+if test ! -f $NAME
+then
+  echo "no such file: $NAME"
+  exit;
+fi
+
+if test $NAME = dmp2.v 
+then 
+  DUMP="xx.dmp"
+else
+  DUMP="verilog.dump"
+fi
+
+$CVER -q $NAME >/dev/null
+$DINO $DUMP
+rm $DUMP
diff --git a/dinotrace.dir/examples.dino/dmp.v b/dinotrace.dir/examples.dino/dmp.v
new file mode 100644
index 0000000..d71211a
--- /dev/null
+++ b/dinotrace.dir/examples.dino/dmp.v
@@ -0,0 +1,245 @@
+module GCD_sim;
+ reg Reset;
+ reg [7:0] X;
+ reg [7:0] Y;
+ wire [7:0] gcd_output;
+ GCD GCD_1(X, Y, Reset, gcd_output);
+ initial
+  begin
+   #8
+   // $dumpvars(0, GCD_1.compare_var);
+   // $dumpvars(1, GCD_sim, GCD_1, GCD_1.compare_var);
+ //  $dumplimit(10000);
+   $dumpvars;
+   #1;
+   // $dumpall;
+   // $dumpon;
+   // $dumpoff;
+   
+  end
+ initial 
+  begin
+   // $dumpfile("xx.dmp");
+   // $dumpvars(1, GCD_sim, GCD_1.COMPARE, GCD_1.compare_var);
+//    $dumpvars(0, GCD_1.compare_var);
+
+   // repeat (5) 
+   repeat (50) 
+    begin
+     #10 ;
+     X = 8'b1;
+     Y = 8'b1;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b1) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000001", gcd_output);
+     X = 8'b10;
+     Y = 8'b1;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b1) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000001", gcd_output);
+     // $finish(2);
+     X = 8'b110;
+     Y = 8'b11;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b1100;
+     Y = 8'b11;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b1;
+     Y = 8'b10;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b1) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000001", gcd_output);
+     X = 8'b11;
+     Y = 8'b110;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b11;
+     Y = 8'b1100;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b1100;
+     Y = 8'b110;
+     Reset = 1'b1;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     X = 8'b11100;
+     Y = 8'b101;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b1) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000001", gcd_output);
+     X = 8'b101;
+     Y = 8'b11100;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b1) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000001", gcd_output);
+     X = 8'b11100;
+     Y = 8'b111;
+     Reset = 1'b1;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     X = 8'b11100;
+     Y = 8'b11100;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11100) $display($stime, , 
+      "gcd_output(%b) !== 8'b00011100", gcd_output);
+     X = 8'b11100;
+     Y = 8'b11100;
+     Reset = 1'b1;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     X = 8'b11;
+     Y = 8'b11000000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b11;
+     Y = 8'b11000000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b1000000;
+     Y = 8'b11010000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b10000) $display($stime, , 
+      "gcd_output(%b) !== 8'b00010000", gcd_output);
+     X = 8'b100110;
+     Y = 8'b10011110;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b10) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000010", gcd_output);
+     X = 8'b10011110;
+     Y = 8'b100110;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b10) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000010", gcd_output);
+     X = 8'b10011110;
+     Y = 8'b11000000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b10) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000010", gcd_output);
+     X = 8'b10011110;
+     Y = 8'b11000000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b10) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000010", gcd_output);
+     X = 8'b0;
+     Y = 8'b11000000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     X = 8'b11000000;
+     Y = 8'b0;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     X = 8'b0;
+     Y = 8'b0;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output !== 8'b00000000");
+     X = 8'b0;
+     Y = 8'b0;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     // dump all variables each time through loop
+     $dumpall;
+     $dumpflush;
+    end
+   $finish(3);
+  end
+
+endmodule
+
+module GCD(X, Y, Reset, gcd_output);
+ input X;
+ input Y;
+ input Reset;
+ output gcd_output;
+ wire [7:0] X;
+ wire [7:0] Y;
+ reg [1:0] compare_var;
+ reg [7:0] gcd_output;
+ reg resetvar;
+ reg [7:0] xvar;
+ reg [7:0] yvar;
+
+function [1:0] COMPARE;
+ input[7:0] x1;
+ input[7:0] x2;
+ integer i;
+  begin : flag
+   i = 7;
+   while (i >= 0) 
+    begin
+     if ((x1[i] == 1'b1) && (x2[i] == 1'b0)) 
+      begin
+       COMPARE = 2'b10;
+       disable flag;
+      end
+     else if ((x1[i] == 1'b0) && (x2[i] == 1'b1)) 
+      begin
+       COMPARE = 2'b1;
+       disable flag;
+      end
+     i = i - 1;
+    end
+   COMPARE = 2'b11;
+  end
+endfunction
+
+ always @(X or Y or Reset) 
+  begin
+   xvar = X;
+   yvar = Y;
+   resetvar = Reset;
+   if (xvar == 8'b0) gcd_output = 8'b0;
+   if (yvar == 8'b0) gcd_output = 8'b0;
+   if (((resetvar == 1'b0) && (xvar !== 8'b0)) && (yvar !== 8'b0)) 
+    begin
+     compare_var = COMPARE(xvar, yvar);
+     while (compare_var !== 2'b11) 
+      begin
+       if (compare_var == 2'b1) yvar = yvar - xvar;
+       else xvar = xvar - yvar;
+       compare_var = COMPARE(xvar, yvar);
+      end
+     gcd_output = xvar;
+    end
+   else 
+    begin
+     gcd_output = 8'b0;
+    end
+  end
+
+endmodule
diff --git a/dinotrace.dir/examples.dino/dmp2.v b/dinotrace.dir/examples.dino/dmp2.v
new file mode 100644
index 0000000..08c7da3
--- /dev/null
+++ b/dinotrace.dir/examples.dino/dmp2.v
@@ -0,0 +1,246 @@
+module GCD_sim;
+ reg Reset;
+ reg [7:0] X;
+ reg [7:0] Y;
+ wire [7:0] gcd_output;
+ GCD GCD_1(X, Y, Reset, gcd_output);
+ initial
+  begin
+   #8
+    $dumpfile("xx.dmp");
+    $dumpvars(0, GCD_1.compare_var, GCD_1.gcd_output);
+  //$dumpvars(1, GCD_sim, GCD_1, GCD_1.compare_var);
+ //  $dumplimit(10000);
+  // $dumpvars;
+   #1;
+   // $dumpall;
+   // $dumpon;
+   // $dumpoff;
+   
+  end
+ initial 
+  begin
+    //$dumpfile("xx.dmp");
+   // $dumpvars(1, GCD_sim, GCD_1.COMPARE, GCD_1.compare_var);
+//    $dumpvars(0, GCD_1.compare_var);
+
+   // repeat (5) 
+   repeat (50) 
+    begin
+     #10 ;
+     X = 8'b1;
+     Y = 8'b1;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b1) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000001", gcd_output);
+     X = 8'b10;
+     Y = 8'b1;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b1) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000001", gcd_output);
+     // $finish(2);
+     X = 8'b110;
+     Y = 8'b11;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b1100;
+     Y = 8'b11;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b1;
+     Y = 8'b10;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b1) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000001", gcd_output);
+     X = 8'b11;
+     Y = 8'b110;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b11;
+     Y = 8'b1100;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b1100;
+     Y = 8'b110;
+     Reset = 1'b1;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     X = 8'b11100;
+     Y = 8'b101;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b1) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000001", gcd_output);
+     X = 8'b101;
+     Y = 8'b11100;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b1) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000001", gcd_output);
+     X = 8'b11100;
+     Y = 8'b111;
+     Reset = 1'b1;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     X = 8'b11100;
+     Y = 8'b11100;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11100) $display($stime, , 
+      "gcd_output(%b) !== 8'b00011100", gcd_output);
+     X = 8'b11100;
+     Y = 8'b11100;
+     Reset = 1'b1;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     X = 8'b11;
+     Y = 8'b11000000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b11;
+     Y = 8'b11000000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b11) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000011", gcd_output);
+     X = 8'b1000000;
+     Y = 8'b11010000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b10000) $display($stime, , 
+      "gcd_output(%b) !== 8'b00010000", gcd_output);
+     X = 8'b100110;
+     Y = 8'b10011110;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b10) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000010", gcd_output);
+     X = 8'b10011110;
+     Y = 8'b100110;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b10) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000010", gcd_output);
+     X = 8'b10011110;
+     Y = 8'b11000000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b10) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000010", gcd_output);
+     X = 8'b10011110;
+     Y = 8'b11000000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b10) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000010", gcd_output);
+     X = 8'b0;
+     Y = 8'b11000000;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     X = 8'b11000000;
+     Y = 8'b0;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     X = 8'b0;
+     Y = 8'b0;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output !== 8'b00000000");
+     X = 8'b0;
+     Y = 8'b0;
+     Reset = 1'b0;
+     #10 ;
+     if (gcd_output !== 8'b0) $display($stime, , 
+      "gcd_output(%b) !== 8'b00000000", gcd_output);
+     // dump all variables each time through loop
+     $dumpall;
+     $dumpflush;
+    end
+   $finish(3);
+  end
+
+endmodule
+
+module GCD(X, Y, Reset, gcd_output);
+ input X;
+ input Y;
+ input Reset;
+ output gcd_output;
+ wire [7:0] X;
+ wire [7:0] Y;
+ reg [1:0] compare_var;
+ reg [7:0] gcd_output;
+ reg resetvar;
+ reg [7:0] xvar;
+ reg [7:0] yvar;
+
+function [1:0] COMPARE;
+ input[7:0] x1;
+ input[7:0] x2;
+ integer i;
+  begin : flag
+   i = 7;
+   while (i >= 0) 
+    begin
+     if ((x1[i] == 1'b1) && (x2[i] == 1'b0)) 
+      begin
+       COMPARE = 2'b10;
+       disable flag;
+      end
+     else if ((x1[i] == 1'b0) && (x2[i] == 1'b1)) 
+      begin
+       COMPARE = 2'b1;
+       disable flag;
+      end
+     i = i - 1;
+    end
+   COMPARE = 2'b11;
+  end
+endfunction
+
+ always @(X or Y or Reset) 
+  begin
+   xvar = X;
+   yvar = Y;
+   resetvar = Reset;
+   if (xvar == 8'b0) gcd_output = 8'b0;
+   if (yvar == 8'b0) gcd_output = 8'b0;
+   if (((resetvar == 1'b0) && (xvar !== 8'b0)) && (yvar !== 8'b0)) 
+    begin
+     compare_var = COMPARE(xvar, yvar);
+     while (compare_var !== 2'b11) 
+      begin
+       if (compare_var == 2'b1) yvar = yvar - xvar;
+       else xvar = xvar - yvar;
+       compare_var = COMPARE(xvar, yvar);
+      end
+     gcd_output = xvar;
+    end
+   else 
+    begin
+     gcd_output = 8'b0;
+    end
+  end
+
+endmodule
diff --git a/doc/README b/doc/README
new file mode 100644
index 0000000..8509000
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,30 @@
+
+                   DOUMENTATION DIRECTORY CONTENTS
+
+See either the IEEE P1364 Verilog standard LRM that can be purchased from
+IEEE or a book on Verilog to learn Verilog syntax and usage.
+
+The documentation directory contains the following files.
+
+cver.faq -            File containing answers to frequently asked question.    
+
+cver.hlp -            File containing help screen that is printed by cver 
+                      when "cver -h" is typed.  This is main source of
+                      instructions for using new +loadpli1= and +loadvpi=
+                      features but also see examples in the PLI
+                      tests_and_examples directories that contain running
+                      PLI models with make files and c compiler and linker
+                      options.
+
+dbg.hlp               All the gdb style debugger help screens combined into
+                      one file. see the helpgen.inp and README file in
+                      ver_srcs directory for debugger -i script that will
+                      generate the dbg.hlp file.
+
+cver-extensions.txt   Document describes new Verilog 2001 features and other
+                      enhancements in Cver.
+
+systasks.1            Man page giving all system task and functions
+
+systasks.ps           implemented by Cver in both man troff format and
+                      postscript.
diff --git a/doc/cver-extensions.txt b/doc/cver-extensions.txt
new file mode 100644
index 0000000..49360d9
--- /dev/null
+++ b/doc/cver-extensions.txt
@@ -0,0 +1,86 @@
+
+          DISCUSSION OF CVER EXTENSIONS AND IMPLEMENTION 
+
+
+1. Cver PLI include files and vpi_ interface follows Verilog IEEE P1364 2001
+   LRM not 1995 LRM.
+
+2. Cver has preliminary support for Verilog 2000 attributes.
+
+   Verilog 2000 (* .. *) attributes are now partially supported.  They
+   can be added to variables, ports and instances/modules.  They can
+   not yet be attached to any other HDL object including statements and
+   expressions.  If you try to attach an attribute to an object that is not
+   supported, a syntax error will be emitted.  vpi_ access to attributes is
+   supported following Verilog 2000 LRM.  Attribute values can be previously
+   defined parameters.
+
+3. Cver uses fast relaxation algorithm for switch channel simulation.
+
+   Loading and initialization (full relaxation so incremental algorithm
+   can be used during simulation) for large tran and inout switch
+   channels is now much faster.  New +switchverbose option can be turned to
+   identify large switch channels and monitor switch channel elaboration.
+
+4. Cver supports Verilog 2001 macros 
+
+   `undef and `ifndef pare supported.  Also, macros with parameters
+   are supported.  Following other simulators, argument macros require no
+   white space between macro name and argument list so non argument macro
+   values can be surrounded by parentheses.  `define constants __cver__,
+   __CVER__, __P1364__, and __p1364__ are automatically defined.
+
+5. Cver supports explicitly named pound parameters.
+
+   New Verilog 2000 named pound parameters are supported so that not
+   all parameters in pound parameter list need be given.  Example of new
+   syntax is:
+
+     level1 #(.p2(501)) x1(i);
+     
+6. Cver implements a number of new system tasks and functions.  See
+   the systasks.1 man page for definitions of all system task and functions
+   supported by Cver.
+
+7. Cver implements a number of vpi_ PLI 2.0 enhancements
+
+   a) Added ability for PLI to dynamically add and remove additional
+      drivers to nets and after adding a driver, vpi_put_value can be
+      used to drive values (including hiz for tri-stating) onto nets.  
+      This provides a better way for PLI to drive wires compared to
+      soft force that disappears on next net change as defined in P1364 LRM.
+      This addition allows vpi_ to contribute drivers to nets where actual
+      net value is determined using normal strength competition rules.
+      It is not in Verilog 2000 because proposal was voted down by committee.
+
+      See async.c, vsetval1.c and vsetval2.c tests in examples.vpi directory
+      for examples of how new capability is used.  Driving a new using
+      PLI involves two steps.  First use vpi_put_value with delay mode
+      vpiNetDriver (for entire net) or vpiNetBitDriver for one bit of vector.
+      The object returned by the call is then used as handle passed to
+      vpi_put_value to add a driver.  Removing driver is accomplished by
+      putting hiz value to net driver object.  File cv_vpi_user.h must be
+      included to use this enhancement.
+
+   b) Added vpiOneOfEachMod iterator.  Iterator returned contains one
+      instance of each module in design.  It also was not accepted as part
+      of Verilog 2000 PLI standard.  It is used for source processing
+      where only one instance of each module need be processed.  It is
+      much faster than traversing entire instance tree to find module types
+      uses in design for large designs.
+
+   c) Added vpiPoundParam 1 to 1 access method.  Given a handle to a pound
+      parameter, the expression object passed to the instance is returned.
+      The expression can be evaluated to get pound parameter value.  The
+      value may differ from the final value of the parameter if he value
+      is over-ridden by a defparam. 
+
+7. Cver also supports pulse checking for Gates
+
+   P1364 pulse checking options (such as +show_cancele) work in Cver
+   for both path delays and gates.  This allows using SDF (DEVICE
+   delays to implement distributed delay macro cell modules.
+   Cver does not support pathpulse precentages because it is not  
+   pessimistic enough.  Default is normal inertial delay rescheduling.
+   Use +show_cancele to cause insertion of x for any width glitch.
+
diff --git a/doc/cver.FAQ b/doc/cver.FAQ
new file mode 100644
index 0000000..62a4d24
--- /dev/null
+++ b/doc/cver.FAQ
@@ -0,0 +1,536 @@
+Frequently Asked Questions
+==========================
+
+    * 1. What is Verilog and what is Verilog Simulation?
+    * 2. What is the history of Cver?
+    * 3. What Computers has Cver been ported to?
+    * 4. How can I tell if I have misspelled a command line option?
+    * 5. Why doesn't Cver mimic XL style port collapsing? i.e. why are some
+         nets multiply driven in XL but not in Cver?
+    * 6. What is the difference between a reg and a wire?
+    * 7. Why is Cver inform and warning suppression system so complicated?
+         How do I use it?
+    * 8. Why can't I use ` defined preprocessor values to define numbers?
+    * 9. Where are the instructions for the complicated compilation and
+         linking steps needed before simulation?
+    * 10. Why does optimizer (-O) option sometimes slow down my simulation?
+    * 11. Why is the OS dynamic loader unable to find my .so PLI program
+          libraries? 
+    * 12. Why won't gdb let me set break points in my user PLI code?
+    * 13. How do I use gdb in conjunction with Cver ':' debugger to debug my
+          PLI code?
+    * 14. Why does value assigned by vpi_put_value to a wire disappear?  What
+          is this vpiAddDriver non standard feature anyway?
+    * 15. How does glitch (pulse) checking work in Cver?
+    * 16. Why doesn't Cver support $save/$restart?
+    * 17. Why doesn't Cver support new Verilog 2001 generate feature?
+    * 18. Why can't I set debugger statement breakpoints when I use -O?
+    * 19. Why are Cver's debugger breakpoints so complicated?
+    * 20. Why does the Cvlic license manager complain when I quit from gdb?
+    * 21. Why aren't more Verilog 2001 features implemented?
+    * 22. Why can't I use $dumpvars to dump all vars with dinotrace for large
+           design?
+    * 23. What is vcddiff for?
+    * 24. Why doesn't Cver support separate assertion and test languages?
+    * 25. How do I report bugs?
+    * 26. How do I purchase support or commercial Cver from Pragmatic C
+
+  ----------------------------------------------------------------------
+1. What is Verilog and what is Verilog Simulation?
+
+    Verilog is the name for both a language for describing electronic
+    hardware called a hardware description language (HDL) and the name 
+    of the program that simulates HDL circuit descriptions to verify
+    that described circuits will function correctly when the are constructed.
+    Verilog is used only for describing digital logic circuits.  Other
+    HDLs such as Spice are used for describing analog circuits. 
+
+    There is an IEEE standard named P1364 that standardizes the Verilog HDL
+    and the behavior of Verilog simulators.  Verilog is officially defined
+    in the IEEE P1364 Language Reference Manual (LRM) that can be purchased
+    from IEEE.  There are many good books for learning that teach the
+    Verilog HDL and/or that teach digital circuit design using Verilog.
+    See the Comp.lang.verilog usenet news group for information on Verilog
+    web resources.
+
+2. What is the history of Cver?
+
+   Pragmatic C started by developing the Vcmp Valid to Verilog translator
+   and the Tdlver Tegas to Verilog net list translators that were marketed
+   by Gateway Design Systems.  When Cadence Design purchased both Gateway
+   Design and Valid Logic, the market for those programs disappeared.
+
+   Pragmatic C then worked with Chronologic and wrote the first
+   front end elaborator for VCS but due to personality conflicts, the joint
+   development project did not work out.  After parting company with
+   Chronologic, Pragmatic C decided to develop a Verilog simulator
+   since the front end was already written.
+
+   Cver was used as the digital engine for the Antrim Design Systems
+   Verilog-AMS (analog and mixed signal) simulator in the late 1990s until
+   last year when Cadence Design purchased Antrim Design Systems. 
+   We have decided to release Cver as it existed at the time of the last
+   Antrim release under GNU Public License (GPL) because we realized that we
+   could not compete with the branding power of the large Ecad vendors.
+
+   We currently are working on improving simulation speed using a compiler
+   which compiles Verilog to virtual machine instructions (called byte codes)
+   which are then interpreted (paper ver-vm.pdf on the www.pragmatic-c.com
+   web site describes the method).  The commercial version of Cver contains
+   the new VM compiler.  Pragmatic C is applying for research grants and
+   hopes to diversify to become both a simulator vendor and and a research
+   company. 
+
+  ----------------------------------------------------------------------
+3. What Computers has Cver been ported to?
+
+   Cver has been ported to Linux X86, Sparc Solaris, Apple Mac OSX, 
+   Cygwin (a Linux-like envirnoment for Windows),  and Hewlett Packard 
+   PA-Risc HPUX systems.  The release comes with tested make files for 
+   Linux, Sparc, Apple, and Cygwin (contact Pragmatic C for the HPUX make 
+   file).  Since Cver is primarily an interpreter, it will usually just 
+   compile and run on any system that has a GNU C compiler available.  
+   The one possible problem area is that user PLI programs are dynamically 
+   linked using dlopen/dlsym program dynamic library linking system calls.  
+   It will probably be difficult to port Cver to systems that do not support 
+   dynamic linking.  See the README file in the source directory for more 
+   details.
+
+  ----------------------------------------------------------------------
+4.  How can I tell if I have misspelled a command line option?
+
+    Run Cver with the -informs command line option.  It will print a
+    message for every unrecognized option.  It will print an inform
+    message for every unrecognized + option and a warning for every
+    unrecognized - option.  Unrecognized + options may also be options
+    that are needed by PLI programs.
+
+  ----------------------------------------------------------------------
+5.  Why doesn't Cver mimic XL style port collapsing? i.e. why are some
+    nets multiply driven in XL but not in Cver?
+
+    Cver follows the P1364 LRM and treats input and output ports as no delay
+    continuous assignments and inout ports as non strength reducing
+    "virtual" tran gates.  This has the advantage that there is no need  
+    for changing wire types when wires with different types are collapsed 
+    into the same net and allows warnings to be emitted for incorrectly
+    declared ports.  A port is incorrectly declared if an input port has
+    a driver on the lowconn side or if an output port has a driver on
+    the highconn side.
+
+    Because many older designs depend on the XL port collapsing algorithm
+    which silently changes port type depending on pattern of net drivers,
+    Cver supports the +change_port_type command option that causes Cver
+    to change ports according to driving pattern to mimic the XL port 
+    collapsing algorithm.  Cver always emits a warning message if there
+    is a possibility that a port may be changed to inout by XL port
+    collapsing algorithm (messages is an inform if +change_port_type option
+    is selected).  Use +suppress_warnings+3107+3108+ to suppress the
+    warning if you intend backward direction signal flow to be blocked
+    by a port.
+
+    There are many advantages to avoiding the XL algorithm such as:
+    fewer multi driver nets, no need to distinguish simulated nets
+    in PLI and in system task output, etc.
+
+  ----------------------------------------------------------------------
+6.  What is the difference between a reg and a wire?
+
+    This distinction is a difficult one for beginners to grasp but
+    it is important for distinguishing between computer programs and
+    hardware models.  See a Verilog circuit design text book or the IEEE
+    P1364 Verilog Standard LRM.
+
+    But briefly, a reg is like a programming language value.  Once a value
+    is assigned to a reg, which can only occur in procedural Verilog
+    constructs, its value is retained until another procedural assignment
+    is made.  A wire corresponds to a circuit wire.  It has declarative
+    constructs such as gates and continuous assignments driving it and
+    has loads which are input to other declarative Verilog constructs.
+    If a wire has more than one driver, whenever a driver changes value,
+    all drivers are evaluated to determine the winning value (strongest
+    0 component and 1 component strengths).  When all driving value
+    of a wire are removed (called tristating), the value of a wire reverts
+    to the high impedance (z) value, i.e. the value does not persist.
+  
+    Reg and wire are sometimes lumped together and called nets.  Regs
+    can only be assigned to using procedural assignments.  A procedural
+    assignment can only occur in initial or always blocks, in tasks,
+    or in functions.
+
+    Also, wires are scalared (unless declaration prevents scalaring) so
+    that each bit changes and is scheduled separately.  Regs are always
+    vectored, so that changing one bit is the same as changing the entire
+    reg and events are always scheduled for an entire reg. 
+
+  ----------------------------------------------------------------------
+7.  Why is Cver inform and warning suppression system so complicated?
+    How do I use it?
+
+    There are constant bug reports complaining either that some minor
+    problem should be flagged or that some minor problem is too minor
+    to be flagged.  Cver has 3 command line options that allow user
+    customization of error message output.
+
+    By default, warning messages are enabled (printing is enabled) and 
+    inform level messages are disabled (counted but not printed).
+    Use the -informs message to enable all inform level messages.  Use the
+    -w message to turn off warning message printing (option names mimic
+    those originally used in XL).
+    
+    A finer grained messages system allows suppressing specific warning
+    and inform level messages.  Error messages are always printed and
+    if simulation has not yet started, inhibit simulation.
+
+    Easiest way to customize messages that you want to have printed is to
+    start by running with -informs option.  Then look at the printed
+    inform and warning messages. For messages that you see as tiny lint
+    particles, record the number (in square brackets) and add it to
+    a +suppress_warns+ option list.  You can use as many different
+    +suppress_warns+ messages as desired.  I normally run without -informs
+    but use "+suppress_warns+3107+3108+".
+
+    The SDF reader uses separate command options but you can still suppress
+    individual message numbers with a +suppress_warns+ message number list.
+    The SDF reader options are +sdf_log_file [file name] that directs all
+    output to a separate log file with name [file name].  If option is not
+    used, SDF reader messages go to normal log file (usually verilog.log). 
+    +sdf_noerrors inhibits emitting SDF reader error messages.  +sdf_nowarns
+    inhibits printing of SDF reader warning messages.  -informs turns on
+    printing of SDF reader informs unless +sdf_nowarns options is used.
+    SDF errors do not inhibit simulation.
+
+    There are also options to print out more verbose record of elaboration
+    and simulation progress.  +verbose prints run progress messages.
+    +libverbose prints trace of exactly how and in which order
+    unresolved symbols are resolved during -v/-y library reading.
+    +sdfverbose prints trace of exactly what delay is assigned during
+    SDF input to each object.  +switchverbose prints trace of switch 
+    (tran, tranif, inout port, etc.) channel construction needed 
+    for the undocumented (I think) XL style relaxation switch channel
+    algorithm.
+
+  ----------------------------------------------------------------------
+8.  Why can't I use ` defined preprocessor values to define numbers?
+
+    Verilog preprocessor differs from programming language (such as C)
+    preprocessor in that only tokens can be substituted not characters.
+    Therefore because sized numbers are defined as [bit width][base value],
+    it is only legal to define a number as "`WID 'd44" or "`WID `BASEVAL".
+    Assuming the following ` definitions are made:
+
+    `define NWID 32
+    `define PWID 'd3
+    `define QWID 3
+    `define RWID 32'd
+
+    The following assignments are legal: 
+      i = `NWID `PWID;
+      j = `NWID'd3;
+      k = `NWID`PWID;
+
+    But these two are illegal:
+     // l = `NWID 'd`QWID; 
+     // m = `RWID `QWID
+
+  ----------------------------------------------------------------------
+9.  Where are the instructions for the complicated compilation and
+    linking steps needed before simulation?
+
+    Cver follows XL in using a different turbo loading approach so there
+    is no separate compilation and linking phases.  No limitations
+    on when SDF files can be read and no limitations on PLI usage. 
+    No compiled simulation needed for separate elaboration and simulation
+    PLI loading.  No long (sometimes up to 30 minutes) compilation times.
+    Cver has very fast turbo compiler to byte codes for a Verilog virtual
+    that is interpreted.  SDF annotation, PLI registration, and debugger
+    commands invoked during simulation cause incremental compilation to
+    update the byte code simulation model.
+
+  ----------------------------------------------------------------------
+10.  Why does optimizer (-O) option sometimes slow down my simulation?
+    ** NOTE: only applies to commercial Cver **
+
+    Interpreted simulation speed had reached a point where no more
+    speed improvement was possible.  The new byte code virtual machine (VM)
+    interpreter now allows future speed improvements as more sophisticated
+    compiler algorithms and optimizations are added.  Current
+    weakest parts of compiled VM byte code quality are simulation of
+    gates and path and timing check event recording.  Completely flattened
+    gate simulations currently show small or no speed improvement over
+    interpreted Cver.  Also because compiled simulators must preserve
+    module port interfaces, much of the speed gain from compilation
+    is lost for designs with complicated ports.  This is why XL is sometimes
+    much faster than VCS.
+
+  ----------------------------------------------------------------------
+11.  Why is the OS dynamic loader unable to find my .so PLI program
+    libraries? 
+
+
+    When Cver is unable to find dynamic libraries that needed to be loaded
+    because they are coded as the +loadvpi=[library]:[boostrap routine]
+    or +loadpli1=[library][boostrap routine] library field, error 
+    message 1803 is emitted.  The error messages contains the reason 
+    for dynamic library load failure.  The most common reason is 
+    "No such file or directory".  The most common cause of this error 
+    is that you forgot to set the OS LD_LIBRARY_PATH environment variable.
+    Even if you keep your dynamic libraries in the same directory in which
+    you run your simulation, you must set the LD_LIBRARY_PATH environment 
+    variable to '.' (current directory).  You do not need to include
+    the .so suffix on your library name since Cver first tries name as it
+    appears and then try again with .so suffix appended.
+
+  ----------------------------------------------------------------------
+12.  Why won't gdb let me set break points in my user PLI code?
+
+    Because Cver loads user PLI libraries as dynamic (usually suffix .so)
+    libraries using +load_pii1= and +load_vpi= options, the libraries are
+    not loaded until just before start of simulation.  Therefore start cver
+    by typing "gdb cver".  Then set a break at routine __pv_sim.  All user
+    PLI libraries will have been loaded by the time that breakpoint is hit.
+    In the breakpoint you will be able to set breakpoints in user PLI code.
+    Then continue from breakpoint to start simulation and to begin debugging
+    user PLI code.  See installation directory tree, 3 PLI
+    directories in tests_and_examples directory for instructions and
+    examples of how to compile and create user PLI program dynamic libraries.
+
+  ----------------------------------------------------------------------
+13.  How do I use gdb in conjunction with Cver ':' debugger to debug my
+     PLI code?
+
+     Follow the instructions in question 9 except before starting
+     simulation type gdb command "handle 2 pass".  Then you can enter
+     gdb by pressing interrupt (usually ctrl-c) key.  You can even
+     press interrupt key within the debugger to enter gdb.  Continue
+     from gdb will return to debugger command input mode, so you will
+     need to use Verilog debugger continue ('.') command to continue
+     simulation.
+
+  ----------------------------------------------------------------------
+14.  Why does value assigned by vpi_put_value to a wire disappear?  What
+     is this vpiAddDriver non standard feature anyway?
+
+     One result of current dominance of compiled to machine code Verilog
+     simulators over flexible interpreted simulators is lack of flexibility
+     in what can be modeled using the PLI, especially the new vpi_ interface.
+     Worst problem is that there is no way to drive wires using PLI calls.
+     Using vpi_put_value to assign to a wire just creates what is
+     called a soft force, i.e. the wire is changed to vpi_put_value
+     value until next time a driver changes.
+
+     Cver supports a much better way for assigning values to wires.
+     Namely vpi_put_value can be called with reason flag vpiAddDriver.
+     The object returned is a new driver of a wire.  Then whenever
+     vpi_put_value is used to put a value to the added driver object,
+     the driving value changes.  Any assignment can be removed by
+     putting a z (high impedance) value to the driver.  Any number
+     of drivers can be added so different PLI application will not
+     conflict.  Although, final value will be determined by combining
+     all drivers using normal Verilog strength competition algorithm.
+
+     This enhancement was proposed to P1364 committee but was voted
+     down so it is currently a non standard enhancement.
+
+  ----------------------------------------------------------------------
+15.  How does glitch (pulse) checking work in Cver?
+
+     Cver pulse detection uses the normal +show_cancel_e option to
+     turn on insertion of x when a pulse occurs.  If the option is not
+     used standard Verilog inertial (latest occurring) scheduling is used.
+
+     Because Cver is intended as an accurate gate level simulator and
+     because glitch problems are the most common reason that designs
+     can not be moved between circuit type and feature sizes, the following 
+     very pessimistic pulse detection algorithm is used if the
+     +show_cancel_e option is selected: 1) if option is select, every 
+     possible pulse is detected and x's are injected. 2) Pulse checking 
+     is also used for gates as well as paths in Cver, 3) if
+     +pulse_e_style_ondetect option is used output wire stays in unknown (x)
+     state until a driver that doesn't have a glitch problem changes.  4) No
+     PATHPULSE option or specify section percentage parameters are used, i.e.
+     any pulse causes x injection. 
+
+     This algorithm was used by Tegas simulator with good results
+     in freeing designs from dependence on one particular IC type or
+     manufacturing process. 
+
+  ----------------------------------------------------------------------
+16.  Why doesn't Cver support $save/$restart?
+
+     Operating system level programs and system calls exist in modern
+     operating systems so it is better to simply stop a process and
+     restart it.  There is no need for Cver to even know it was
+     stopped and its process image saved to disk.
+
+  ----------------------------------------------------------------------
+17.  Why doesn't Cver support new Verilog 2001 generate feature?
+
+     Cver is intended to be an accurate and close to actual hardware
+     models gate level simulator.  The new Verilog generate is a feature
+     that is not preprocess Verilog into HDL source but becomes an integral
+     part of simulation data structure.  For that reason and because it is so
+     complicated that other implementations by simulators with larger
+     market share will almost certainly differ, there are no plans
+     to implement Verilog generate as currently defined.  There are
+     good Verilog source preprocessors available that provide a better
+     method (using superior Unix filter paradigm) to simplify
+     coding of regular Verilog HDL source.
+
+  ----------------------------------------------------------------------
+18.  Why can't I set debugger statement breakpoints when I use -O?
+    ** NOTE: only applies to commercial Cver **
+
+     The byte code compiler separates procedural Verilog into delay
+     control free regions.  This process removes statement boundaries.
+     Therefore there is no place to set breakpoints in the byte code
+     program.  Verilog statement delay and edge control breakpoints
+     can still be set even when -O option is selected.  If you
+     need to debug procedural RTL statements, run without optimization.
+
+  ----------------------------------------------------------------------
+19.  Why are Cver's debugger statement breakpoints so complicated?
+
+     Cver supports all of the statement break point control capabilities
+     in gdb plus some additional features needed because circuits are
+     represented as instance trees.  The following types of breakpoints
+     are supported (see dbg.hlp file in doc directory or use the Cver
+     :help commands for more details): 
+ 
+     1) :breakpoint [statement ref] - break set at statement for every instance
+    
+     2) :ibreakpoint [scope reference][,statement ref] - break set at statement
+        in only the one instance determined by the [scope reference].
+ 
+     3) :tbreakpoint [statement ref] - same as :breakpoint but removed
+        after hit one time.
+ 
+     4) :tibreakpoint [statement ref] - same as :ibreakpoint but removed
+        after hit one time.
+ 
+     5) :nextb - set a :tibreak at next line in source and execute '.'
+        command to continue execution.  Because of hardware parallelism,
+        a number of different threads may execute and block on delay or
+        event controls before the next statement in source order is
+        executed.
+
+
+     The following commands take a break point number as argument and
+     modify behavior of the breakpoint.
+ 
+     a) :disable [num] and :enable [num] - disable a breakpoint from
+        triggering until :enable command re-enables the breakpoint.
+ 
+     b) :ignore [num] [count] - ignore the breakpoint until it is hit
+        exactly [count] times.  Useful for breaking after a certain number
+        of edges when the edges are controlled by procedural RTL.
+
+     c) :cond [num] [Verilog expressions] - ignore breakpoint unless
+        expression evaluates to true.  To stop after a given time use 
+        "($time > [number])" for the cond expression.  :cond command
+        expression are level not edge sensitive.
+
+     The complicated break point mechanism is needed because it is
+     quite common for wrong procedural edges to occur only in one of
+     a number of repeated instance and then only when a number of
+     different other conditions are met.
+
+  ----------------------------------------------------------------------
+20. Why does the Cvlic license manager complain when I quit from gdb?
+    ** NOTE: only applies to commercial Cver **
+
+    Cver normally uses Pragmatic C developed node locked single job
+    lock license manager.  It works by writing a file "/tmp/.CVERRUN.LCK" 
+    into the /tmp directory.  When a Cver run completes, the file is removed.
+    However if you exit from gdb with the quit command, control is never
+    returned to Cver so it can not remove the /tmp/.CVERRUN.LCK file.
+    If you run Cver and get the following message: 
+
+      **FATAL: a job is running - limit exceeded for SJL license.
+
+    Remove the single job lock file by typing: "rm /tmp/.CVERRUN.LCK". 
+    It is also possible for a core dump termination to die in such a way
+    that the lock file is not removed.  Again if Cver emits the above
+    message remove the lock file.  We put the following lines in our 
+    .gdbinit file (usually placed in your home directory):
+
+define cvrun
+she rm /tmp/.CVER*
+run
+end
+define cvquit
+she rm /tmp/.CVER*
+quit
+end
+    
+    Then to start a simulation to debug your user PLI code type "cvrun"
+    instead of run and cvquit instead of quit.
+
+    We also can support FlexLM license manager but we prefer not to use it
+    because it adds considerably to our costs and since Verilog simulations
+    are compute cycle intensive, there is no reason to run more than
+    one simulation on one computer.
+
+  ----------------------------------------------------------------------
+21.  Why aren't more Verilog 2001 features added?
+
+     A number of new features are under development such as new file I/O
+     mechanism, configurations alternative to -y/-v options, and new signed
+     and unsigned keywords and algorithm.  Cver can't be first simulator to
+     implement new features because our interpretation of the LRM will
+     probably not match the interpretation of the simulators with larger
+     market share.  Since Cver is intended to be an accurate gate level
+     simulator, multi dimensional wire and regs will probably not be
+     implemented since they do not correspond to real hardware.  Multiple
+     dimensional arrays (formerly called memories) make sense but if only
+     multi dimensional arrays are implemented, simulator will not match
+     either 1995 or 2001 standard.
+
+     We are also working on other minor new Verilog 2001 features.
+
+  ----------------------------------------------------------------------
+22.  Why can't I use $dumpvars to dump all vars with dinotrace for large
+     design?
+
+     This is a Dinotrace limitation.  Namely, current Dinotrace algorithm
+     requires very large area of memory for every signal.  Work around
+     is to use $dumpvars form that only dumps nets of interest.
+
+  ----------------------------------------------------------------------
+23. What is vcddiff for?
+
+    vcddiff is program we have developed to assist in making sure
+    that when changes are made to a design,  the changes can be  
+    regressed back to original design.  We think that the diff style
+    output is a better way to look at changes in wide bus based designs.
+    See README file for vcddiff for more instructions.
+
+  ----------------------------------------------------------------------
+24. Why does not Cver support separate assertion and test languages?
+
+    The idea behind Cver is provide an interpreter that is so flexible
+    that whatever assertions need to be checked can be accomplished by
+    coding the checks in the Verilog HDL itself and that test scripts can
+    either be coded in Verilog or in a standard script language such as Perl,
+    Tcl, or Ruby and connected using PLI interface.  Cver follows the Unix
+    paradigm in which specialized tools are connected to construct more 
+    complex tools.
+
+  ----------------------------------------------------------------------
+25. How do I report bugs?
+
+    Send email to support at pragmatic-c.com.  Before reporting a bug check
+    the known-problems.txt file to see if the problem is already known.
+    Also, make sure you are running the latest version of Cver by checking
+    the http://www.pragmatic-c.com/gplcver web site if you are running
+    open source Cver or the http://www.pragmatic-c.com/commercial-cver
+    web site if you have licensed commercial Cver.  Bug reports should
+    include a small failing example if possible.
+
+  ----------------------------------------------------------------------
+26. How do I purchase support or commercial Cver from Pragmatic C
+
+    For more information on commercial Cver, either visit the
+    http://www.pragmatic-c.com/commericial-cver web site or contact Pragmatic
+    C Software by sending email to sales at pragmatic-c.com.
+
diff --git a/doc/cver.faq.htm b/doc/cver.faq.htm
new file mode 100644
index 0000000..af7316b
--- /dev/null
+++ b/doc/cver.faq.htm
@@ -0,0 +1,646 @@
+<html>
+<head>
+<title>Cver Frequently Asked Questions</title>
+
+<!-- <body bgcolor="white" link="#915520" vlink="red"> -->
+<body bgcolor="white">
+<br>
+<h1> <center>
+Cver Frequently Asked Questions
+</h1>
+</center>
+
+<hr width="95%">
+<ol>
+<li>
+<a href = "#1">What is Verilog and what is Verilog Simulation?</a>
+<li>
+<a href = "#2">What is the history of Cver?</a>
+<li>
+<a href = "#3">What Computers has Cver been ported to?</a>
+<li>
+<a href = "#4">How can I tell if I have misspelled a command line option?</a>
+<li>
+<a href = "#5">Why doesn't Cver mimic XL style port collapsing? i.e. why are some nets multiply driven in XL but not in Cver?</a>
+<li>
+<a href = "#6">What is the difference between a reg and a wire?</a>
+<li>
+<a href = "#7">Why is Cver inform and warning suppression system so complicated? How do I use it?</a>
+<li>
+<a href = "#8">Why can't I use ` defined preprocessor values to define numbers?</a>
+<li>
+<a href = "#9">Where are the instructions for the complicated compilation and
+         linking steps needed before simulation?</a>
+<li>
+<a href = "#10">Why does optimizer (-O) option sometimes slow down my simulation?</a>
+<li>
+<a href = "#11">Why is the OS dynamic loader unable to find my .so PLI program
+          libraries? </a>
+<li>
+<a href = "#12">Why won't gdb let me set break points in my user PLI code?</a>
+<li>
+<a href = "#13">How do I use gdb in conjunction with Cver ':' debugger to debug my
+          PLI code?</a>
+<li>
+<a href = "#14">Why does value assigned by vpi_put_value to a wire disappear?  What
+          is this vpiAddDriver non standard feature anyway?</a>
+<li>
+<a href = "#15">How does glitch (pulse) checking work in Cver?</a>
+<li>
+<a href = "#16">Why doesn't Cver support $save/$restart?</a>
+<li>
+<a href = "#17">Why doesn't Cver support new Verilog 2001 generate feature?</a>
+<li>
+<a href = "#18">Why can't I set debugger statement breakpoints when I use -O?</a>
+<li>
+<a href = "#19">Why are Cver's debugger breakpoints so complicated?</a>
+<li>
+<a href = "#20">Why does the Cvlic license manager complain when I quit from gdb?</a>
+<li>
+<a href = "#21">Why aren't more Verilog 2001 features implemented?</a>
+<li>
+<a href = "#22">Why can't I use $dumpvars to dump all vars with dinotrace for large
+           design?</a>
+<li>
+<a href = "#23">What is vcddiff for?</a>
+<li>
+<a href = "#24">Why doesn't Cver support separate assertion and test languages?</a>
+<li>
+<a href = "#25">How do I report bugs?</a>
+<li>
+<a href = "#26">How do I purchase support or commercial Cver from Pragmatic C</a>
+<li>
+<a href = "#27">Where is "dlfcn.h" for OS X?</a>
+
+</ol>
+<hr width="95%">
+
+<a name="1">
+<ol>
+<li>
+ <h3>   What is Verilog and what is Verilog Simulation?</h3> 
+
+    Verilog is the name for both a language for describing electronic
+    hardware called a hardware description language (HDL) and the name 
+    of the program that simulates HDL circuit descriptions to verify
+    that described circuits will function correctly when the are constructed.
+    Verilog is used only for describing digital logic circuits.  Other
+    HDLs such as Spice are used for describing analog circuits. 
+
+    There is an IEEE standard named P1364 that standardizes the Verilog HDL
+    and the behavior of Verilog simulators.  Verilog is officially defined
+    in the IEEE P1364 Language Reference Manual (LRM) that can be purchased
+    from IEEE.  There are many good books for learning that teach the
+    Verilog HDL and/or that teach digital circuit design using Verilog.
+    See the Comp.lang.verilog usenet news group for information on Verilog
+    web resources.
+<a name="2">
+<p>
+<li>
+<h3>What is the history of Cver?</h3>
+
+   Pragmatic C started by developing the Vcmp Valid to Verilog translator
+   and the Tdlver Tegas to Verilog net list translators that were marketed
+   by Gateway Design Systems.  When Cadence Design purchased both Gateway
+   Design and Valid Logic, the market for those programs disappeared.
+
+   Pragmatic C then worked with Chronologic and wrote the first
+   front end elaborator for VCS but due to personality conflicts, the joint
+   development project did not work out.  After parting company with
+   Chronologic, Pragmatic C decided to develop a Verilog simulator
+   since the front end was already written.
+
+   Cver was used as the digital engine for the Antrim Design Systems
+   Verilog-AMS (analog and mixed signal) simulator in the late 1990s until
+   last year when Cadence Design purchased Antrim Design Systems. 
+   We have decided to release Cver as it existed at the time of the last
+   Antrim release under GNU Public License (GPL) because we realized that we
+   could not compete with the branding power of the large Ecad vendors.
+
+   We currently are working on improving simulation speed using a compiler
+   which compiles Verilog to virtual machine instructions (called byte codes)
+   which are then interpreted (paper ver-vm.pdf on the www.pragmatic-c.com
+   web site describes the method).  The commercial version of Cver contains
+   the new VM compiler.  Pragmatic C is applying for research grants and
+   hopes to diversify to become both a simulator vendor and and a research
+   company. 
+
+<p>
+<a name="3">
+<li>
+<h3>What Computers has Cver been ported to?</h3>
+
+   Cver has been ported to Linux X86, Sparc Solaris, Apple Mac OSX, 
+   Cygwin (a Linux-like envirnoment for Windows),  and Hewlett Packard 
+   PA-Risc HPUX systems.  The release comes with tested make files for 
+   Linux, Sparc, Apple, and Cygwin (contact Pragmatic C for the HPUX make 
+   file).  Since Cver is primarily an interpreter, it will usually just 
+   compile and run on any system that has a GNU C compiler available.  
+   The one possible problem area is that user PLI programs are dynamically 
+   linked using dlopen/dlsym program dynamic library linking system calls.  
+   It will probably be difficult to port Cver to systems that do not support 
+   dynamic linking.  See the README file in the source directory for more 
+   details.
+
+<p>
+<a name="4">
+<li>
+<h3>How can I tell if I have misspelled a command line option?</h3>
+
+    Run Cver with the -informs command line option.  It will print a
+    message for every unrecognized option.  It will print an inform
+    message for every unrecognized + option and a warning for every
+    unrecognized - option.  Unrecognized + options may also be options
+    that are needed by PLI programs.
+
+<p>
+<a name="5">
+<li>
+<h3>Why doesn't Cver mimic XL style port collapsing? i.e. why are some
+    nets multiply driven in XL but not in Cver?</h3>
+
+    Cver follows the P1364 LRM and treats input and output ports as no delay
+    continuous assignments and inout ports as non strength reducing
+    "virtual" tran gates.  This has the advantage that there is no need  
+    for changing wire types when wires with different types are collapsed 
+    into the same net and allows warnings to be emitted for incorrectly
+    declared ports.  A port is incorrectly declared if an input port has
+    a driver on the lowconn side or if an output port has a driver on
+    the highconn side.
+
+    Because many older designs depend on the XL port collapsing algorithm
+    which silently changes port type depending on pattern of net drivers,
+    Cver supports the +change_port_type command option that causes Cver
+    to change ports according to driving pattern to mimic the XL port 
+    collapsing algorithm.  Cver always emits a warning message if there
+    is a possibility that a port may be changed to inout by XL port
+    collapsing algorithm (messages is an inform if +change_port_type option
+    is selected).  Use +suppress_warnings+3107+3108+ to suppress the
+    warning if you intend backward direction signal flow to be blocked
+    by a port.
+
+    There are many advantages to avoiding the XL algorithm such as:
+    fewer multi driver nets, no need to distinguish simulated nets
+    in PLI and in system task output, etc.
+
+<p>
+<a name="6">
+<li>
+<h3>What is the difference between a reg and a wire?</h3>
+
+    This distinction is a difficult one for beginners to grasp but
+    it is important for distinguishing between computer programs and
+    hardware models.  See a Verilog circuit design text book or the IEEE
+    P1364 Verilog Standard LRM.
+
+    But briefly, a reg is like a programming language value.  Once a value
+    is assigned to a reg, which can only occur in procedural Verilog
+    constructs, its value is retained until another procedural assignment
+    is made.  A wire corresponds to a circuit wire.  It has declarative
+    constructs such as gates and continuous assignments driving it and
+    has loads which are input to other declarative Verilog constructs.
+    If a wire has more than one driver, whenever a driver changes value,
+    all drivers are evaluated to determine the winning value (strongest
+    0 component and 1 component strengths).  When all driving value
+    of a wire are removed (called tristating), the value of a wire reverts
+    to the high impedance (z) value, i.e. the value does not persist.
+  
+    Reg and wire are sometimes lumped together and called nets.  Regs
+    can only be assigned to using procedural assignments.  A procedural
+    assignment can only occur in initial or always blocks, in tasks,
+    or in functions.
+
+    Also, wires are scalared (unless declaration prevents scalaring) so
+    that each bit changes and is scheduled separately.  Regs are always
+    vectored, so that changing one bit is the same as changing the entire
+    reg and events are always scheduled for an entire reg. 
+
+<p>
+<a name="7">
+<li>
+<h3>Why is Cver inform and warning suppression system so complicated?
+    How do I use it?</h3>
+
+    There are constant bug reports complaining either that some minor
+    problem should be flagged or that some minor problem is too minor
+    to be flagged.  Cver has 3 command line options that allow user
+    customization of error message output.
+
+    By default, warning messages are enabled (printing is enabled) and 
+    inform level messages are disabled (counted but not printed).
+    Use the -informs message to enable all inform level messages.  Use the
+    -w message to turn off warning message printing (option names mimic
+    those originally used in XL).
+    
+    A finer grained messages system allows suppressing specific warning
+    and inform level messages.  Error messages are always printed and
+    if simulation has not yet started, inhibit simulation.
+
+    Easiest way to customize messages that you want to have printed is to
+    start by running with -informs option.  Then look at the printed
+    inform and warning messages. For messages that you see as tiny lint
+    particles, record the number (in square brackets) and add it to
+    a +suppress_warns+ option list.  You can use as many different
+    +suppress_warns+ messages as desired.  I normally run without -informs
+    but use "+suppress_warns+3107+3108+".
+
+    The SDF reader uses separate command options but you can still suppress
+    individual message numbers with a +suppress_warns+ message number list.
+    The SDF reader options are +sdf_log_file [file name] that directs all
+    output to a separate log file with name [file name].  If option is not
+    used, SDF reader messages go to normal log file (usually verilog.log). 
+    +sdf_noerrors inhibits emitting SDF reader error messages.  +sdf_nowarns
+    inhibits printing of SDF reader warning messages.  -informs turns on
+    printing of SDF reader informs unless +sdf_nowarns options is used.
+    SDF errors do not inhibit simulation.
+
+    There are also options to print out more verbose record of elaboration
+    and simulation progress.  +verbose prints run progress messages.
+    +libverbose prints trace of exactly how and in which order
+    unresolved symbols are resolved during -v/-y library reading.
+    +sdfverbose prints trace of exactly what delay is assigned during
+    SDF input to each object.  +switchverbose prints trace of switch 
+    (tran, tranif, inout port, etc.) channel construction needed 
+    for the undocumented (I think) XL style relaxation switch channel
+    algorithm.
+
+<p>
+<a name="8">
+<li>
+<h3>Why can't I use ` defined preprocessor values to define numbers?</h3>
+
+    Verilog preprocessor differs from programming language (such as C)
+    preprocessor in that only tokens can be substituted not characters.
+    Therefore because sized numbers are defined as [bit width][base value],
+    it is only legal to define a number as "`WID 'd44" or "`WID `BASEVAL".
+    Assuming the following ` definitions are made:
+
+    `define NWID 32
+    `define PWID 'd3
+    `define QWID 3
+    `define RWID 32'd
+
+    The following assignments are legal: 
+      i = `NWID `PWID;
+      j = `NWID'd3;
+      k = `NWID`PWID;
+
+    But these two are illegal:
+     // l = `NWID 'd`QWID; 
+     // m = `RWID `QWID
+
+<p>
+<a name="9">
+<li>
+<h3>Where are the instructions for the complicated compilation and
+    linking steps needed before simulation?</h3>
+
+    Cver follows XL in using a different turbo loading approach so there
+    is no separate compilation and linking phases.  No limitations
+    on when SDF files can be read and no limitations on PLI usage. 
+    No compiled simulation needed for separate elaboration and simulation
+    PLI loading.  No long (sometimes up to 30 minutes) compilation times.
+    Cver has very fast turbo compiler to byte codes for a Verilog virtual
+    that is interpreted.  SDF annotation, PLI registration, and debugger
+    commands invoked during simulation cause incremental compilation to
+    update the byte code simulation model.
+
+<p>
+<a name="10">
+<li>
+<h3>Why does optimizer (-O) option sometimes slow down my simulation?</h3>
+    ** NOTE: only applies to commercial Cver **
+
+    Interpreted simulation speed had reached a point where no more
+    speed improvement was possible.  The new byte code virtual machine (VM)
+    interpreter now allows future speed improvements as more sophisticated
+    compiler algorithms and optimizations are added.  Current
+    weakest parts of compiled VM byte code quality are simulation of
+    gates and path and timing check event recording.  Completely flattened
+    gate simulations currently show small or no speed improvement over
+    interpreted Cver.  Also because compiled simulators must preserve
+    module port interfaces, much of the speed gain from compilation
+    is lost for designs with complicated ports.  This is why XL is sometimes
+    much faster than VCS.
+
+<p>
+<a name="11">
+<li>
+<h3>Why is the OS dynamic loader unable to find my .so PLI program
+    libraries? </h3>
+
+
+    When Cver is unable to find dynamic libraries that needed to be loaded
+    because they are coded as the +loadvpi=[library]:[boostrap routine]
+    or +loadpli1=[library][boostrap routine] library field, error 
+    message 1803 is emitted.  The error messages contains the reason 
+    for dynamic library load failure.  The most common reason is 
+    "No such file or directory".  The most common cause of this error 
+    is that you forgot to set the OS LD_LIBRARY_PATH environment variable.
+    Even if you keep your dynamic libraries in the same directory in which
+    you run your simulation, you must set the LD_LIBRARY_PATH environment 
+    variable to '.' (current directory).  You do not need to include
+    the .so suffix on your library name since Cver first tries name as it
+    appears and then try again with .so suffix appended.
+
+<p>
+<a name="12">
+<li>
+<h3>Why won't gdb let me set break points in my user PLI code?</h3>
+
+    Because Cver loads user PLI libraries as dynamic (usually suffix .so)
+    libraries using +load_pii1= and +load_vpi= options, the libraries are
+    not loaded until just before start of simulation.  Therefore start cver
+    by typing "gdb cver".  Then set a break at routine __pv_sim.  All user
+    PLI libraries will have been loaded by the time that breakpoint is hit.
+    In the breakpoint you will be able to set breakpoints in user PLI code.
+    Then continue from breakpoint to start simulation and to begin debugging
+    user PLI code.  See installation directory tree, 3 PLI
+    directories in tests_and_examples directory for instructions and
+    examples of how to compile and create user PLI program dynamic libraries.
+
+<p>
+<a name="13">
+<li>
+<h3>How do I use gdb in conjunction with Cver ':' debugger to debug my
+     PLI code?</h3>
+
+     Follow the instructions in question 9 except before starting
+     simulation type gdb command "handle 2 pass".  Then you can enter
+     gdb by pressing interrupt (usually ctrl-c) key.  You can even
+     press interrupt key within the debugger to enter gdb.  Continue
+     from gdb will return to debugger command input mode, so you will
+     need to use Verilog debugger continue ('.') command to continue
+     simulation.
+
+<p>
+<a name="14">
+<li>
+<h3>Why does value assigned by vpi_put_value to a wire disappear?  What
+     is this vpiAddDriver non standard feature anyway?</h3>
+
+     One result of current dominance of compiled to machine code Verilog
+     simulators over flexible interpreted simulators is lack of flexibility
+     in what can be modeled using the PLI, especially the new vpi_ interface.
+     Worst problem is that there is no way to drive wires using PLI calls.
+     Using vpi_put_value to assign to a wire just creates what is
+     called a soft force, i.e. the wire is changed to vpi_put_value
+     value until next time a driver changes.
+
+     Cver supports a much better way for assigning values to wires.
+     Namely vpi_put_value can be called with reason flag vpiAddDriver.
+     The object returned is a new driver of a wire.  Then whenever
+     vpi_put_value is used to put a value to the added driver object,
+     the driving value changes.  Any assignment can be removed by
+     putting a z (high impedance) value to the driver.  Any number
+     of drivers can be added so different PLI application will not
+     conflict.  Although, final value will be determined by combining
+     all drivers using normal Verilog strength competition algorithm.
+
+     This enhancement was proposed to P1364 committee but was voted
+     down so it is currently a non standard enhancement.
+
+<p>
+<a name="15">
+<li>
+<h3>How does glitch (pulse) checking work in Cver?</h3>
+
+     Cver pulse detection uses the normal +show_cancel_e option to
+     turn on insertion of x when a pulse occurs.  If the option is not
+     used standard Verilog inertial (latest occurring) scheduling is used.
+
+     Because Cver is intended as an accurate gate level simulator and
+     because glitch problems are the most common reason that designs
+     can not be moved between circuit type and feature sizes, the following 
+     very pessimistic pulse detection algorithm is used if the
+     +show_cancel_e option is selected: 1) if option is select, every 
+     possible pulse is detected and x's are injected. 2) Pulse checking 
+     is also used for gates as well as paths in Cver, 3) if
+     +pulse_e_style_ondetect option is used output wire stays in unknown (x)
+     state until a driver that doesn't have a glitch problem changes.  4) No
+     PATHPULSE option or specify section percentage parameters are used, i.e.
+     any pulse causes x injection. 
+
+     This algorithm was used by Tegas simulator with good results
+     in freeing designs from dependence on one particular IC type or
+     manufacturing process. 
+
+<p>
+<a name="16">
+<li>
+<h3>Why doesn't Cver support $save/$restart?</h3>
+
+     Operating system level programs and system calls exist in modern
+     operating systems so it is better to simply stop a process and
+     restart it.  There is no need for Cver to even know it was
+     stopped and its process image saved to disk.
+
+<p>
+<a name="17">
+<li>
+<h3>Why doesn't Cver support new Verilog 2001 generate feature?</h3>
+
+     Cver is intended to be an accurate and close to actual hardware
+     models gate level simulator.  The new Verilog generate is a feature
+     that is not preprocess Verilog into HDL source but becomes an integral
+     part of simulation data structure.  For that reason and because it is so
+     complicated that other implementations by simulators with larger
+     market share will almost certainly differ, there are no plans
+     to implement Verilog generate as currently defined.  There are
+     good Verilog source preprocessors available that provide a better
+     method (using superior Unix filter paradigm) to simplify
+     coding of regular Verilog HDL source.
+
+<p>
+<a name="18">
+<li>
+<h3>Why can't I set debugger statement breakpoints when I use -O?</h3>
+    ** NOTE: only applies to commercial Cver **
+
+     The byte code compiler separates procedural Verilog into delay
+     control free regions.  This process removes statement boundaries.
+     Therefore there is no place to set breakpoints in the byte code
+     program.  Verilog statement delay and edge control breakpoints
+     can still be set even when -O option is selected.  If you
+     need to debug procedural RTL statements, run without optimization.
+
+<p>
+<a name="19">
+<li>
+<h3>Why are Cver's debugger statement breakpoints so complicated?</h3>
+
+     Cver supports all of the statement break point control capabilities
+     in gdb plus some additional features needed because circuits are
+     represented as instance trees.  The following types of breakpoints
+     are supported (see dbg.hlp file in doc directory or use the Cver
+     :help commands for more details): 
+ 
+     1) :breakpoint [statement ref] - break set at statement for every instance
+    
+     2) :ibreakpoint [scope reference][,statement ref] - break set at statement
+        in only the one instance determined by the [scope reference].
+ 
+     3) :tbreakpoint [statement ref] - same as :breakpoint but removed
+        after hit one time.
+ 
+     4) :tibreakpoint [statement ref] - same as :ibreakpoint but removed
+        after hit one time.
+ 
+     5) :nextb - set a :tibreak at next line in source and execute '.'
+        command to continue execution.  Because of hardware parallelism,
+        a number of different threads may execute and block on delay or
+        event controls before the next statement in source order is
+        executed.
+
+
+     The following commands take a break point number as argument and
+     modify behavior of the breakpoint.
+ 
+     a) :disable [num] and :enable [num] - disable a breakpoint from
+        triggering until :enable command re-enables the breakpoint.
+ 
+     b) :ignore [num] [count] - ignore the breakpoint until it is hit
+        exactly [count] times.  Useful for breaking after a certain number
+        of edges when the edges are controlled by procedural RTL.
+
+     c) :cond [num] [Verilog expressions] - ignore breakpoint unless
+        expression evaluates to true.  To stop after a given time use 
+        "($time &gt [number])" for the cond expression.  :cond command
+        expression are level not edge sensitive.
+
+     The complicated break point mechanism is needed because it is
+     quite common for wrong procedural edges to occur only in one of
+     a number of repeated instance and then only when a number of
+     different other conditions are met.
+
+<p>
+<a name="20">
+<li>
+<h3>Why does the Cvlic license manager complain when I quit from gdb?</h3>
+    ** NOTE: only applies to commercial Cver **
+
+    Cver normally uses Pragmatic C developed node locked single job
+    lock license manager.  It works by writing a file "/tmp/.CVERRUN.LCK" 
+    into the /tmp directory.  When a Cver run completes, the file is removed.
+    However if you exit from gdb with the quit command, control is never
+    returned to Cver so it can not remove the /tmp/.CVERRUN.LCK file.
+    If you run Cver and get the following message: 
+
+      **FATAL: a job is running - limit exceeded for SJL license.
+
+    Remove the single job lock file by typing: "rm /tmp/.CVERRUN.LCK". 
+    It is also possible for a core dump termination to die in such a way
+    that the lock file is not removed.  Again if Cver emits the above
+    message remove the lock file.  We put the following lines in our 
+    .gdbinit file (usually placed in your home directory):
+
+define cvrun
+she rm /tmp/.CVER*
+run
+end
+define cvquit
+she rm /tmp/.CVER*
+quit
+end
+    
+    Then to start a simulation to debug your user PLI code type "cvrun"
+    instead of run and cvquit instead of quit.
+
+    We also can support FlexLM license manager but we prefer not to use it
+    because it adds considerably to our costs and since Verilog simulations
+    are compute cycle intensive, there is no reason to run more than
+    one simulation on one computer.
+
+<p>
+<a name="21">
+<li>
+<h3>Why aren't more Verilog 2001 features added?</h3>
+
+     A number of new features are under development such as new file I/O
+     mechanism, configurations alternative to -y/-v options, and new signed
+     and unsigned keywords and algorithm.  Cver can't be first simulator to
+     implement new features because our interpretation of the LRM will
+     probably not match the interpretation of the simulators with larger
+     market share.  Since Cver is intended to be an accurate gate level
+     simulator, multi dimensional wire and regs will probably not be
+     implemented since they do not correspond to real hardware.  Multiple
+     dimensional arrays (formerly called memories) make sense but if only
+     multi dimensional arrays are implemented, simulator will not match
+     either 1995 or 2001 standard.
+
+     We are also working on other minor new Verilog 2001 features.
+
+<p>
+<a name="22">
+<li>
+<h3>Why can't I use $dumpvars to dump all vars with dinotrace for large
+     design?</h3>
+
+     This is a Dinotrace limitation.  Namely, current Dinotrace algorithm
+     requires very large area of memory for every signal.  Work around
+     is to use $dumpvars form that only dumps nets of interest.
+
+<p>
+<a name="23">
+<li>
+<h3>What is vcddiff for?</h3>
+
+    vcddiff is program we have developed to assist in making sure
+    that when changes are made to a design,  the changes can be  
+    regressed back to original design.  We think that the diff style
+    output is a better way to look at changes in wide bus based designs.
+    See README file for vcddiff for more instructions.
+
+<p>
+<a name="24">
+<li>
+<h3>Why does not Cver support separate assertion and test languages?</h3>
+
+    The idea behind Cver is provide an interpreter that is so flexible
+    that whatever assertions need to be checked can be accomplished by
+    coding the checks in the Verilog HDL itself and that test scripts can
+    either be coded in Verilog or in a standard script language such as Perl,
+    Tcl, or Ruby and connected using PLI interface.  Cver follows the Unix
+    paradigm in which specialized tools are connected to construct more 
+    complex tools.
+
+<p>
+<a name="25">
+<li>
+<h3>How do I report bugs?</h3>
+
+    Send email to support at pragmatic-c.com.  Before reporting a bug check
+    the known-problems.txt file to see if the problem is already known.
+    Also, make sure you are running the latest version of Cver by checking
+    the http://www.pragmatic-c.com/gplcver web site if you are running
+    open source Cver or the http://www.pragmatic-c.com/commercial-cver
+    web site if you have licensed commercial Cver.  Bug reports should
+    include a small failing example if possible.
+
+<p>
+<a name="26">
+<li>
+<h3>How do I purchase support or commercial Cver from Pragmatic C?</h3>
+
+    For more information on commercial Cver, either visit the
+    http://www.pragmatic-c.com/commericial-cver web site or contact Pragmatic
+    C Software by sending email to sales at pragmatic-c.com.
+
+<a name="27">
+<li>
+<h3>Where is "dlfcn.h" for OS X?</h3>
+   Prior to running/compiling GPL Cver for the Mac OS X you must download
+   and install the tar ball found 
+   <a href="http://www.opendarwin.org/projects/dlcompat/" target="_TOP">here</a>. This will
+   enable Cver to use dynamic loading in OS X. 
+
+</ol>
+
+<p>
+<hr>
+<br>
+<small>Copyright &copy 1991-2004 Pragmatic C Software Corp.</small>
+<br>
+<small>Last updated 2004-03-02.</small>
+</body>
+</html>
diff --git a/doc/cver.hlp b/doc/cver.hlp
new file mode 100644
index 0000000..168efc2
--- /dev/null
+++ b/doc/cver.hlp
@@ -0,0 +1,347 @@
+GPLCVER_1.10a of 07/29/03 (Linux-elf).
+Copyright (c) 1991-2003 Pragmatic C Software Corp.
+  All Rights reserved.  Licensed under the GNU General Public License (GPL).
+  See the 'COPYING' file for details.  NO WARRANTY provided.
+Today is Thu Jul 31 03:02:02 2003.
+             ** CVER VERILOG SIMULATOR HELP MESSAGE **
+ 
+  Cver is a Verilog HDL simulator following the 1995 IEEE P1364 standard
+  with some 2001 P1364 LRM features added and some modifications to match
+  actual behavior of de facto standard XL simulator.  Modeling in C/C++ and
+  Verilog using PLI 1 and PLI 2 interfaces is supported.  PLI implementation
+  follows 2001 P1364 LRM.  Cver now supports faster compiled to byte code
+  simulation selected using -O (optimize on) option, but optimizer is still
+  only in beta release state.  If you detect different results running with
+  and without -O, submit bug report.  See release notes in doc directory of
+  your release for list of P1364 2001 supported features and list of known
+  compiler problems.
+ 
+  Usage:  cver [intermixed options and Verilog source files].
+ 
+  Command line and -f command file options must be in lower case and must
+  begin with a - or +.  Each option requires a separate - or +.  Type
+  'cver -?' or 'cver -h' to generate this help message.  To enter the
+  Verilog statement interactive debugger (press interrupt (^c) or execute
+  $stop), then type :help' for interactive debugger help.
+ 
+  It is assumed that you already know Verilog and have access to a P1364 LRM
+  or other Verilog documentation.  Cver supports both PLI (Programming
+  Language Interface) 1 tf_ and acc_ and PLI 2 vpi_ utility, design object
+  and callback routines using +loadpli1= and +load_vpi= dynamic PLI load
+  options defined below.  Both old PLI 1 and new PLI 2 libraries can be
+  dynamically loaded during one run.  See examples in examples.vpi,
+  examples.tf and examples.acc release directories for examples showing how
+  to link and run PLI models.  If you need to statically link PLI models, you
+  must obtain different Cver binary and cverobj.o library.  Cver contains a
+  number of new system tasks and functions.  See systasks.1 man page in the
+  doc directory for definition of every system task and system function
+  supported by Cver.
+ 
+  Cver generally produces results matching other simulators even when other
+  simulators differ from P1364 standard up to differences in event order.
+  However, Cver does not change port direction because of net connection
+  direction (i.e. treat nets with wrong side of port drivers as inouts)
+  unless the +change_port_type option is selected.  It is suggested that
+  you change your designs so port type changing is not needed, but for full
+  compatibility with other simulators always run with +change_port_type
+  option.  Cver implements pulse (glitch) detection for gates as well as
+  paths.  This may cause some simulation result differences.  This more
+  stringent pulse analysis is consistent with Cver's intended use as
+  accurate gate level simulator.
+ 
+  Since all options are collected before processing, if any options are
+  duplicated, the rightmost (last) will be used.  All Cver options are
+  listed in this help message.  Any other option will be ignored by Cver
+  although it may be scanned and used by a user PLI routine.  All options
+  not listed in this help message will have warning 506 emitted for minus
+  options and inform 410 for plus options.
+ 
+  Options defined in the IEEE P1364 reference manual are supported and have
+  the following effect:
+ 
+   -f [file]  Read options and source file names from [file] until it is
+         exhausted at which point continue reading from command line.  May
+         be nested.
+   -l [file]  By default all output is written to stdout and to log file
+         verilog.log.  -l changes to log file [file].  System task
+         $log([file]) changes to log file [file] during simulation, $nolog
+         turns off log file output.  Added system task $flushlog calls OS
+         fflush on log file.  $reset does not reset log file.
+   -s    Stop just before starting simulation and enter interactive debugger.
+   -i [file]  Read interactive debugger commands from file [file] the first
+         time interactive mode is entered (usually with -s but possibly by
+         $stop or interrupt signal (^c)).  Nested -i [file] options are
+         chained not nested.
+   -c    Translate source and all referenced library models only.  Ends just
+         before loading the translated model into memory.
+   -w    Suppress all warning messages.  See +suppress_warns added option for
+         suppression of warnings and informs by message number.
+   -d    Dump source that is constructed from internal representation.  All
+         parameters are replaced by their constant value in the
+         reconstructed source output.  Debugger source listing lists lines
+         from source files instead of reconstructing source.
+   -q    Quiet mode.  Do not print normal progress messages.  Opposite
+         of -q is +verbose that prints even more progress messages than normal.
+   +mindelays, +typdelays, +maxdelays  Choose either minimum, typical or
+         maximum value from any constant (min:typ:max) forms in source.
+         Selection is made during input scanning so min:typ:max forms
+         become constant numbers at translation time.
+   -t    Trace procedural statement execution.  Use -et to trace event
+         processing.  In other simulators, -t means both -t and -et.
+         $settrace,  $setevtrace, $cleartrace, $clearevtrace to control
+         tracing during simulation.
+   +libnocell  Ignore `celldefine directives in source and libraries.  This
+         should not be used if delay back annotation is used since it will
+         probably cause annotation to fail.
+   +notimingchecks  After checking for correct syntax, ignore timing checks.
+   -u    Ignored.  For all upper case, use an OS filter command to convert
+         source to all upper case.
+ 
+  Only default and +librescan library scanning order supported.  By default
+  all library files from -v [file] and all directories of library elements
+  from -y [directory] are scanned from first to last according to input option
+  order.  If unresolved names remain after completion of a pass, the list is
+  rescanned from the beginning.  If +librescan option is selected, unresolved
+  names are resolved one at a time in order they are first seen.  After a
+  name has been resolved, the next name in order is resolved by rescanning
+  from the beginning of library list.  Options to control order dependent
+  resolution and +libnamehide are not implemented.  Library options are:
+ 
+   -v [file]   Treat [file] as a library containing module and UDP
+         definitions.  File is sequentially searched for definitions that
+         resolve unresolved names.  Within a -v file, if a name if defined
+         before use, it is resolved before moving to next library element.
+   -y [directory]  Treat every file in [directory] as a -v library although
+         usually each file will only contain one definition.  File name in
+         directory along with +libext+ option used to find unresolved name.
+   +libext+  In -y directory files, name resolution uses file names.  If
+         no +libext+ option is present only files whose name exactly
+         matches an unresolved module or primitive will be read.  There can
+         be no extension.  Normally, each -y file will contain the
+         definition for exactly one element but if more elements are present
+         they will be used to resolve other unresolved elements.  Use
+         +libext+[extension with dot]+[extension with dot]+...  to cause
+         file name extensions to be removed before matching file names to
+         unresolved element names.  Only one +libext+ option may appear and
+         matching is in order when library extensions do not follow the
+         simple .[suffix name] convention.  If all files in -y directories
+         end with either .v or .V (a common case), use +libext+.v+.V+
+   +librescan  Rescan to beginning of library file and directory list after
+         every unresolved name is resolved.  At most one name resolved per
+         library pass.
+   +libverbose  Emit detailed trace messages giving resolution order and
+         reason a particular element was resolved at the particular place.
+   +show_canceled_e  Path and gate (1 bit continuous assignments implemented
+         as gates) outputs set to X when pulses occur that cause scheduled
+         but not matured events to be canceled because second input edge
+         occurs before output has changed (switched).  The output
+         remains at X until another input edge causes an output change
+         because it is unknown if a pulse (glitch) will cause output
+         switching.  Some other simulators use a less pessimistic algorithm
+         that assumes pulses never cause switching and schedule a change
+         from X back to original output value on trailing edge of pulse.  If
+         your model will not run, use the +warn_canceled_e instead of this
+         option and examine warnings.  Cver does not allow only some
+         paths and gates to use pulse X showing using specify section
+         directives because X showing does not slow down simulation.
+         Normally X from a pulse is shown on leading edge of glitch.  Use
+         +pulse_e_style_ondetect to cause X to be shown(driven) when pulse
+         detected from input change.  Option is standardized replacement for
+         previous +spikes option.
+   +noshow_canceled_e  Path and gate outputs not driven (shown) as X when
+         pulses occur (second input change earlier than selected delay).
+         This is the default (normally it is not needed).  It selects normal
+         Verilog inertial delay algorithm where the latest input change
+         causes the previously scheduled but unmatured event to be canceled.
+   +pulse_e_style_ondetect  If +show_canceled_e option selected, this option
+         causes output to be set to X (shown) when the pulse (glitch) is
+         detected.  If this option is not selected, output is set to X
+         (shown) when the pulse propagates to an output.  This option
+         selects a more pessimistic (starting earlier) X region.
+   +pulse_e_style_onevent  If +show_canceled_e option selected, this option
+         selects the default output setting to X (showing) option that sets
+         output to X when glitch propagates to output (leading edge is time
+         at which the event scheduled latest matures).  There is no reason
+         to use this option since it is default.  Control of X showing for
+         individual gates and paths is not supported.
+   +warn_canceled_e  Emit warning for every gate (including UDP) or path event
+         cancel (inertial cancel and reschedule).  This option may cause
+         voluminous output so the $suppress_warns and $allow_warns system
+         tasks can be used to select particular time periods when warnings
+         are emitted.  This option and +show_canceled_e are unrelated so both
+         error messages and x showing (injection) may be enabled.
+   +nowarn_canceled_e  Because this option is the default it is never needed
+         Last of all +warn_canceled_e and +nowarn_canceled_e is used.
+ 
+  The following two options for dynamically loading user PLI libraries are
+  not explicitly defined in IEEE P1364 reference manual but are supported
+  by all modern simulators.  If you need to statically link your PLI models
+  you must request a different Cver binary and cverobj.o static PLI library,
+  but we strongly encourage use of dynamic PLI loading:
+ 
+   +loadpli1=[.so library]:[boostrap routines]  Load [.so library] dynamic
+         library containing user PLI 1 model and execute each bootstrap
+         routine.  [bootstrap routines] is a comma separated list of C
+         routines.  List may be empty but : is still required.  No spaces
+         are allowed around the equal sign, the colon or commas separating
+         bootstrap C routine names.  All dynamic libraries defined by
+         +loadpli1= options are first loaded using OS dlopen mechanism and
+         then all bootstrap routines are executed before elaboration begins.
+         The OS specific dynamic library suffix (.so on Linux) may be
+         omitted.  If omitted and the [.so library] is not found in any
+         LD_LIBRARY_PATH directory, the dynamic library suffix is added and
+         the LD_LIBRARY_PATH directories are searched again.
+ 
+         Each [bootstrap routines] list routine must return a pointer to a
+         s_tfcell veriusertfs table that ends with zero value type field.
+         Multiple +loadpli1= options are allowed and just before elaboration
+         all [bootstrap routines] for every +loadpli1= option are executed.
+         Each s_tfcell returned table is added to one design wide master
+         s_tfcell table in option and routine in list order.  The master
+         table defines all PLI 1 system functions and tasks used during a
+         simulation run.  The [bootstrap routines] must not call any PLI
+         routines.  Any C file containing [bootstrap routines] list must
+         include both veriuser.h and cv_veriuser.h files.  Some OS shells
+         may require quoting and escaping option separators and file names
+         within the +loadpli1= option string.  Problem can be avoided by
+         coding +loadpli1= option in a -f command argument file. See release
+         examples.tf directory in tests_and_examples directory for example
+         PLI 1 programs and make files specific to your operating system.
+   +load_vpi=[.so library]:[boostrap routines]  Load [.so library] dynamic
+         library containing user PLI 2 vpi model and execute each bootstrap
+         routine.  [bootstrap routines] is a comma separated list of C/C++
+         routines.  List may be empty but : is still required.  No spaces
+         are allowed around the equal sign, the colon or commas separating
+         bootstrap C routine names.  All dynamic libraries defined by
+         +load_vpi= options are first loaded using OS dlopen mechanism and
+         then all bootstrap routines are executed before elaboration begins.
+         The OS specific dynamic library suffix (.so on Linux) may be
+         omitted.  If omitted and the [.so library] is not found in any
+         LD_LIBRARY_PATH directory, the dynamic library suffix is added and
+         the LD_LIBRARY_PATH directories are searched again.
+ 
+         Each [bootstrap routines] is saved on an ordered list and executed
+         in order before elaboration begins.  Normally [bootstrap routines]
+         will execute routines in vlog_startup_routines table, but any PLI 2
+         vpi routines callable before elaboration may be called including
+         vpi_register_systf and vpi_register_cb PLI 2 routines.  Some OS
+         shells may require quoting and escaping option separators and file
+         names within the +loadvpi= option string.  Problem can be avoided by
+         coding +loadvpi= option in a -f command argument file. See release
+         examples.vpi directory for example PLI 1 programs and make files
+         specific to your operating system.
+ 
+  The following other options not defined in the IEEE P1364 reference manual
+  are supported:
+   +verbose  Print various simulation progress messages and design component
+         counts.  Memory sizes do not count memory used by udp tables.
+   +maxerrors [number]  Normally translation terminates after 32
+         errors.  Use this option to change the number. 0 means no limit.
+         Option applies to translation only, simulation is never stopped.
+   -e    Turn off printing of non fatal error messages.
+   -informs  Turn on printing of informatory messages.  Off by default.
+         Informs may be emitted during translation and during simulation.
+         Enable this option to determine if a plus option is misspelled and
+         to cause OS error message description strings to be printed.
+         Option will probably produce voluminous output unless
+         +suppress_warns+[+ separated list] option(s) also used.
+   -O    Turn on compilation to byte codes faster simulation.  This option
+         currently turns off interactive debugger.
+   -et   Turn on event tracing.  Option is similar to the -t (or $settrace)
+         option but -t only traces procedural execution.  To dynamically
+         control event tracing use $setevtrace and $clearevtrace system
+         tasks.  Option produces voluminous output. Use -t and -et to
+         duplicate other simulator -t tracing.
+   +tracefile [name]  Set the output file for any trace output (either
+         statement or event).  Use $settracefile system task to change
+         trace file during execution.  Name can be stdout and if no option
+         or $tracefile, defaults to stdout and log file.  $flushlog system
+         task flushes this file during simulation.
+   +printstats  Print tables of design contents.  Primitives, instances,
+         and wires that will use silicon area are tabulated.  More
+         detailed alternative to $showallinstances.
+   +printallstats  Option equivalent to +printstats but additionally prints
+         the declarative content of every module.
+   +suppress_warns+  Individual warning and informatory messages can be
+         suppressed (not errors) by including a + separated list. i.e.
+         +suppress_warns+403+502+507+564+.  All such options are combined.
+         The $suppress_warns([comma separated list]) and $allow_warns
+         system tasks can be used during simulation for the same effect.
+   +remove_gate_0delays  Change all gates with #0 or #(0, 0, 0) delay to no
+         delay (1 bit continuous assigns implemented as gates).  Option can
+         significantly speed up simulation but in very rare situation cause
+         simulation to fail (#0 delays used to mask races).  If you see a
+         large simulation speed up from option, you can probably speed up
+         simulation even more by recoding most common cells as udps.  Option
+         needed because some simulators only allow delay annotation if gate
+         has a delay coded in source.
+   +nokeepcommands  Do not save interactive commands to history list.  By
+         default,  Interactive commands are saved to history list.  The
+         $keepcommands; and $nokeepcommands; system tasks enable and disable
+         saving of of history during simulation.  Option should be used when
+         interactive input comes from $input or from shell pipe to stdin.
+   +define+[symbol] or +define+[symbol]=[string]   Define back quote macro
+         symbol [symbol] with an empty text string (first form) for use with
+         `ifdef and `ifndef macro facility.  [symbol] does not include back
+         quote.  Second form defines symbol with value [string].  [String]
+         must not contain white space but can contain anything else including
+         surrounding quotes.  Escaped surrounding quotes are converted to
+         normal quotes while non escaped will probably be removed
+         by your shell.  The $scan$plusargs system task is an alternative
+         for setting preprocessor values into variables.
+   +incdir+[path]+[path]+...+  Define paths that are searched for `include
+         files when `include file not found in current directory.  Only
+         `include files that are non absolute paths (not staring with '/'
+         or '.' or '..' or '~') are searched for using +incdir paths.
+         Paths that do not end with '/' have a '/' path separator appended
+         to end.  For file included in different directory, files included
+         from it are still searched for in original (not include file)
+         directory.  Multiple +incdir+ options may be specified.  Paths
+         directories are searched in order of +incdir+ options.
+   +sdf_log_file [file]  File is used for SDF annotation instead of default
+         writing of SDF messages and errors to Verilog log file.
+   +sdf_annotate [file] or +sdf_annotate [file]+[scope reference]  File must
+         be in IEEE P1497 standard delay file format.  File is read and used
+         to set delay and specify values.  +mindelays, +typdelays or
+         +maxdelays setting used to select rtriple value.  Multiple
+         +sdf_annotate options (and files) allowed.  If +[scope reference]
+         provided, SDF path references relative to scope.  Otherwise, SDF
+         paths rooted (context is entire design).  Annotation files processed
+         in option order.  Alternatively, $sdf_annotate system task can be
+         used to annotate delays.  See systsks.1 man page for documentation.
+         Large designs that require large SDF files load somewhat faster if
+         command line option instead of system task is used.
+   +sdfverbose  Emit trace messages giving new delay value for every delay
+         changed during +sdf_annotate delay annotation.  Option can generate
+         voluminous output.
+   +sdf_noerrors  Do not emit SDF annotation error messages.  SDF errors do
+         not stop simulation but cause SDF object delay setting to be skipped
+         so +maxerrors error limit does not apply.  Use this option to turn
+         off printing of SDF error messages.
+   +sdf_nowarns  Do not emit warning messages during SDF annotation.  SDF
+         warnings and informs can also be suppressed by message number
+         using +suppress_warns+ option.
+   +switchverbose  Emit trace and size messages for inout and tran gate
+         switch channels elaboration. Use this option to print progress
+         messages when simulating models with very large switch channels.
+   +change_port_type  Some designs require ports that are not declared as
+         inout but are connected as inouts and require bidirectional signal
+         flow for correct simulation have their port type changes to inout.
+         Use this option to cause port direction to be changed to inout for
+         input ports with loconn drivers and for output ports with highconn
+         drivers.  WARNING: Use of this option may be required to match
+         results of other simulators that use port collapsing algorithm.
+   +nospecify  Simulation run with specify section ignored.  This option
+         causes specify section to be read and parsed but it is discarded
+         before simulation.  +nospecify of course implies +notimingchecks.
+   +nointeractive  Option turns off interactive environment, interrupt signal
+         (^c) causes immediate termination.  $stop causes a warning to be
+         printed without stopping.  Suppress warning 560 to silently ignore
+         stops.  If machine code simulation option +compiled_sim is selected,
+          this option is automatically turned on.
+   +snapshot  If +nointeractive option is selected, if interrupt signal
+         (^c) is generated, this option causes a port mortem activity
+         snapshot to be printed before program termination.  Debugger
+         :where and $snapshot system task produces same output without
+         ending simulation.
+**Special help mode successfully completed.
diff --git a/doc/dbg.hlp b/doc/dbg.hlp
new file mode 100644
index 0000000..c85048a
--- /dev/null
+++ b/doc/dbg.hlp
@@ -0,0 +1,560 @@
+CVER_2.51e of 02/03/03 (Linux-elf).
+Copyright (c) 1991-2003 Pragmatic C Software Corp.
+  All Rights reserved.  Licensed software subject to applicable
+  prohibitions and restrictions as to redistribution and/or use.
+Today is Mon Feb  3 01:00:22 2003.
+  LIC: Licensed to: "Linux 3490 development - Rh 7.1 and Rh 7.3"
+Compiling source file "hello.v"
+Highest level modules:
+xx
+
+C1 > /* file to generate debugger help */
+C1 > $nokeepcommands;
+C2 > :set nologecho
+interactive input command echo to log file off
+.. printing basic help message
+Type ':help [topic]' or ':help :[debugger command]' to print specific help
+message.  Any name can be abbreviated by a unique prefix within : debugger.
+Colon is required for command name help but not allowed for help topics.
+ 
+Help topics:
+  debugging:  Entering and supplying input for interactive debugging.
+  optimizer: debugging limitations when -O optimized simulation selected
+  tracing:  Separate batch tracing system for debugging.
+  differences:  Debugger differences from Verilog standard.
+  statements:  Using traditional interactive Verilog statement debugger.
+  data:  Examining variables and expressions.
+  source:  Listing source and navigating between files.
+  scope:  Setting and navigating between instance and task scopes.
+  break points:  Behavioral statement breakpoints and single stepping.
+  changes breaking:  Breaking on net changes and edges.
+  history:  Command history and history number command enable/disable.
+  info:  Determining and setting debugger status and settings.
+  tasks:  System task and functions useful for interactive debugging.
+  commands:  A list of :[command] debugger commands.
+
+... printing help topic messages
+Debugging:
+  Both the standard Verilog statement debugger and a command based debugger
+  are supported.  Input is typed from the terminal or read from a file.
+  Input is terminated with a new line.  For multi-line commands, all
+  but the last line ends with a back slash escaped new line.  The new
+  command debugger commands begin with a colon as part of the name and
+  cannot be executed from Verilog source.  All interactive commands are
+  echoed to the log file unless ':set noecholog' is used to to suppress log
+  file command echoing (':set echolog' re-enables).
+ 
+  The debugger is entered by pressing the interrupt key (^c), by calling
+  the $stop system task, by the -s command line option, by completing a
+  step command, or by hitting a breakpoint.
+ 
+  The $input("[file]") system task causes debugger commands to be read
+  from [file] the first time interactive mode is entered (by -s?).  $input
+  files do not nest, instead $input in a file causes $input to chain to the
+  new file.  Output is written to the screen and the log file.  stderr is
+  not used.  All typed user input including command prompts and $input
+  commands is written to the log file.  $nolog and $log plus
+  $nokeepcommands and $keepcommands can minimize $input script output.
+  +nokeepcommands option disables history saving.  It is useful if
+  simulation is run from a shell script.
+
+Optimizer:
+  When -O optimized simulation (compiled byte code simulation) is used,
+  breakpoints and single stepping is not possible because statements
+  are converted to basic blocks, i.e. statement separation is lost.
+  Even when optimizatin is on, you still can use the debugger because
+  the byte code compiler is incremental and recompiles code required
+  by debugger Verilog statements.  The debugger can be entered by executing
+  $stop system task either from Verilog source or from statements
+  entered as debugger commands, i.e. debugger can be entered by $stop
+  system task, -s command option, or $stop entered as debugger command
+  (such as '@(posedge clk) $stop;' statement), or by pressing ^c (interrupt
+  key).  All printing, scope and info commands work.  Also, $input
+  system task and -i command line options to load commands into debugger
+  are legal when debugger is used with optimized simulation.
+ 
+  For designs that do not move time (mostly procedural without time
+  movement and event scheduling), there may be a delay after interrupt
+  key is pressed before interactive debugger is entered.
+ 
+  Debugger can only be exited by the dot ('.') continue command when used
+  with optimized simulation.  Use of step (';' or ',') and all break point
+  commands are illegal.  Error message is emitted and command is ignored.
+  Also, $dumpvars can not be called from interactive mode during optimized
+  simulation.
+
+Debugging using the tracing mechanism:
+  An alternative non interactive tracing mechanism is supported.
+  Behavioral statement tracing is started with the -t option or $settrace
+  system task and stopped by calling $cleartrace.  Event tracing is started
+  with the -et option or $setevtrace system task and stopped by calling
+  $clearevtrace.  The -et option allows pre time 0 initialization events
+  to be traced.  Trace output is written to stdout and the log file unless
+  the +tracefile [file name] option or $settracefile([string]) system task
+  are used to direct trace output to a separate file.  The trace mechanism
+  is intended to allow debugging of parallel activity by searching trace
+  output with a debugger.
+ 
+  Trace statements and gates are reconstructed source with parameters
+  replaced by numeric values.  Interactive debugger breakpoint and step
+  tracing also emit source lines.  To avoid duplicate output if tracing
+  and the interactive debugger are used, redirect trace output.
+
+Debugger differences from standard:
+  1) Multiple line interactive debugger commands must end with escaped new
+  lines.  Verilog statements still require the ending semicolon.
+  2) The standard $settrace system task (also -t) are divided into the two
+  tracing classes: $settrace and $setevtrace (-t and -et).
+  3) By default when interactive mode is entered the $scope interactive
+  scope is set to the current scope.  This allows examination of local
+  variables on step or break but may require entering $scope command on
+  every interactive entry to run standard scripts.  In functions, named
+  blocks do not have scope so function scope remains.  Interactivbe variable
+  access in function named block must use qualified reference from function
+  scope.  To duplicate standard behavior in which interactive scope can only
+  be changed by $scope system task, type: ':set noscopechange' inside the
+  interactive debugger.  When re-enabling commands from the history list,
+  either the command must use rooted names or the scope must be the same
+  as the scope when the command was originally entered.
+  4) Delay back annotation by specparam assignments not supported, and
+  $updatetiming, but similar standard SDF (LABEL form and PLI 2.0 assignment
+  to defparams and specparam before delay elaboration supported.
+
+Interactive Verilog statement execution:
+  Any Verilog statement can be entered at the interactive mode prompt (or
+  in an $input file) except named blocks and initial or always statements.
+  No new variables can be declared and all identifiers are accessed using
+  the current scope (entry scope or change $scope location).  Compound
+  statements and statements with delay or event controls are legal.
+  Commands are:
+ 
+   '.'   Exit the debugger and continue execution (event processing).
+   ':'   Print the current instance and possibly task scope plus location
+         of scope and current :list current location.  Prints scope and
+         listing location, use :where for procedural execution location.
+   ';'   Silently step through next procedural statement and process all
+         events and time movement up to the next procedural statement. The
+         current location for the :list command is not changed.  Tasks and
+         functions are stepped into.
+   ','   Step through next statement and print next source statement.  Same
+         as ';' except the next source line to execute is printed.
+   -[number]  Disable history command [number] if it has not yet completed.
+         The $history task indicates commands that are active with a '*'
+   [number]  Re-execute command [number] from the history list only if the
+         command has finished (no '*' mark when printed with $history).
+         Commands are re-executed in the current scope so if a command sets
+         a change or edge breakpoint, it must contain rooted names or be
+         executed from the same scope as it's original entry.
+
+Displaying internal circuit values:
+  In addition to the normal $display (or $write) system tasks to display
+  values use :print to override declared expression base or width (type
+  ':help :print' for legal values). Use :display to define expressions that
+  are printed whenever interactive mode is entered.  :display and :print
+  take same format and width modifiers.  :expris [expr] to determine the
+  width and type of an expression.  Use :varis [var.] to determine type,
+  width and declaration keywords of a variable.  Use :whatis [name] to
+  determine all uses of an identifier name.  Entire qualified path from
+  function scope required for accessing variables in named blocks in
+  functions.
+
+Listing source statements:
+  The normal $list([scope]) system task can list all of any task or module.
+  The :list command lists 10 lines from a selected location that can be
+  a scope or a [file:][line] reference or argument relative to last listed
+  line.  Type ':set listsize [number]' to change the number of lines listed.
+  The current listing location is independent of current scope except when
+  :scope or $scope is executed, the current list line is set to the first
+  line of the scope.  Also since ',' and :[i]step and hitting a breakpoint
+  print a source line, those commands change the current list line.
+  The explicit [file:][line] list command lists in a new file and :list ++
+  lists the beginning of the next source file (:list -- the previous end).
+  Only these three commands can change listing file.  Type ':help :list'
+  for the format of the various :list command options.
+
+Setting interactive scope:
+  The $scope([scope xmr]) system task changes interactive scope.  The :scope
+  command also changes scope but allows a more general reference.  The
+  :breakpoint command takes a scope reference argument.  Format is:
+ 
+  [file:][line] - first instance of scope determined by [file:][line].
+       [file] can be source file, -y or -v path or any path tail if it is
+       unique.  [line] must be between module - endmodule.  Any ':' in
+       [file] name must be escaped with a back slash.  Scope set to type or
+       first instance but other command argument may select instance for
+       :breakpoint.  Scope list line set to first line of scope not [line].
+       [line] is same as [file:][line] where [file] is current file.
+ .. or .u - upward scope first line - if scope in task - one up task or
+       instance containing task (not up instance).
+ .d - first line of scope of first contained instance (not contained task).
+ [module name]  - first instance of module unless name declared as instance
+       in current scope, then normal downward hierarchical reference.
+ [hierarchical ref.] - first line of instance - same as $scope argument.
+
+Behavioral statement breakpoints:
+  Use the :breakpoint or :ibreakpoint commands to set a breakpoint at a
+  specific source statement.  The break occurs before statement execution.
+  :breakpoint breaks in all instances and :ibreakpoint breaks only in the
+  specified instance.  The :breakpoint argument can be any scope or line
+  reference.  If no line reference is given the break is at the first
+  initial, always or task statement of the scope.  For :ibreakpoint the
+  argument must be an instance reference that may optionally be followed by
+  a ',' and a line reference.  For a line reference, the breakpoint is set
+  at the first procedural statement at or following the line in the scope.
+ 
+  Type ':help :breakpoint' or ':help :ibreakpoint' for other options and
+  argument format.  Use ':info breakpoints' to print a list of breakpoints
+  ':delete [number]' to delete breakpoint [number] (no argument deletes all),
+  ':disabl [number]' to temporarily disable breakpoint and ':enable [number]'
+  to re-enable.  :tbreakpoint and :tibreakpoint are identical to :ibreak
+  and :break except breakpoint removed when hit.  :cond adds expression to
+  breakpoint that must be true to cause stop. :ignore adds count of how many
+  hits to ignore before halting.
+
+Breaking on net changes:
+  Enter a delay or event control followed by the $stop system task to
+  enter interactive mode on value change.  Normally the event control
+  statement will be in a loop (probably a forever) because otherwise the
+  break is disabled after each trigger.  Also when interactive mode is
+  entered from an interactive $stop, a step (',', ':', :step, or :istep)
+  command must be entered before using [number] to re-enable a history
+  statement.  For example: 'forever @(posedge clock) $stop;' is usually
+  better than '@(posedge clock) $stop;'
+
+History mechanism:
+  A command is re-executed by entering its history number.  A uncompleted
+  command (such as a Verilog wait or delay control) is disabled by entering
+  -[number] where [number] is command's assigned number in history list.
+ 
+  The $history system task prints the most recent 20 (or histlistsize if
+  different) history entries.  The debugger :history [optional number]
+  command is more flexible because if an optional number argument appears,
+  that many elements are printed (0 for all).  The interactive command
+  prompt is 'C[number] >' where [number] is a command's history number.
+  The one character, [number] to execute, [-][number] to disable and
+  incorrect (such as mistyped Verilog statement entered interactively)
+  commands are not added to the history list.
+ 
+  All commands input during a run are retained.  Use $nokeepcommands to
+  suppress history accumulation and $keepcommands to re-enable in $input
+  scripts.  +nokeepcomands command line option disables history saving for
+  programs that run a simulation by supplying command input through a pipe.
+  :emptyhistory command discards all retained history commands and resets
+  command number to one.  If any history commands are enabled (have not yet
+  completed or been disabled), :emptyhistory will fail.  When an interactive
+  Verilog statement is executed, if it can be executed immediately (no
+  delays, events or tasks enables), it is executed from inside debugger and
+  control remains in interactive mode.  Non immediate statements are
+  scheduled after already scheduled events and resumes.  $stop or the
+  interrupt signal (^c) must then be used to reenter interactive mode.  Use
+  ':set histlistsize' to set default number of history commands to list and
+ ':info histlistsize' to see current number.
+
+Determining and setting internal debugger state values:
+  The ':info [debugger value name]' command prints the current value of
+  a debugger value.  The ':set [debugger value name] [value]' command
+  changes a debugger value.  Type ':help :info' or ':help :set' for the list
+  of debugger info value names.
+
+The following system tasks may be useful during interactive debugging:
+   $finish;  Terminate simulation.
+   $list([scope reference]);  list source lines of scope (:list is
+      alternative).  $list does not print variables values, use $showvars
+      or :print <expr> for that.  Also $list does not mark source lines
+      with pending events.
+   $system("[OS command string]");  Escape to a sub shell and execute the
+      command string (alternative is :shell [command string]).  Use empty
+      string ("") to invoke an interactive sub-shell.
+   $flushlog;  Call OS flush of buffers for log file and trace file.  Can
+      then use :shell to invoke your editor to inspect output.
+   $history;  Print history list to stdout and log file.  Contrary to XL,
+      '$history;' prints last 20 (or histlistsize) commands.  Use
+      ':history <num>' to print <num> commands.  <num> 0 prints all. :set
+      sets and :info prints debugger histlistsize parameter that determines
+      number of commands to list.
+ $keepcommands;, $nokeepcommands;  Enable (or disable) saving of commands
+      entered interactively to history list.  Default is $keepcommands.
+      Use the +nokeepcommands command line option to disable saving of
+      commands to the history list unless '$keepcommands;' is executed.
+   $input([string]);  Process interactive commands from [string] file.
+   $nolog;, $log;  All commands in $input scripts will be copied to the
+      log file unless $nolog is used.  To re-enable log file output, use
+      $log; with no argument.  To change log file use $log([string]).
+   $reset;, $reset_count;, $reset_value;  During debugging reset to start
+      of simulation.  :reset command is better during debugging since it
+      returns to time 0 leaving the reset count unaffected and allows stop.
+   $scope;  Change interactive environment scope to avoid a need to type
+      full paths for variable names.  :scope and automatic scope tracking
+      are intended to lessen need to set explicit interactive scopes.
+      $scope can set scope to function named block but next ineractive entry
+      (from step?) will change scope to function body scope.
+   $showallinstances;  Print all instances in design with source file and
+      line location.  Useful to find module whose name is forgotten.
+      +printstats and +printallstats give more detailed information.
+      If no other window is available, use $flushlog; and :shell to view.
+   $showscopes;  Used to show scopes in current interactive scope.  Can be
+      called with non zero argument to list entire design scope map.
+   $showvariables;, $showvars  Print all variables in current scope. :print
+      is more terse but $showvars prints more for multiple fan-in wires.
+   $shapshot; print up to 5 pending procedural and 5 pending declarative
+      events and status of every interactive thread.  Same as :snapshot.
+   $display, $write  Write values.  Alternative :print is more flexible but
+      these tasks allow formatted output.
+
+:[command] debugger commands:  :help, :shell, :quit, :where, :print, 
+ :reset, :expris, :varis, :whatis, :list, :set, :info, :scope, 
+ :breakpoint, :ibreakpoint, :delete, :enable, :disabl, :step, :istep, 
+ :history, :emptyhistory, :display, :undisplay, :tbreakpoint, 
+ :tibreakpoint, :ignore, :cond, :snapshot, :nextb
+
+... printing : debugger help command messages
+:help [optional topic or :[command] name prefix]
+   Print help message.
+
+:shell [rest of line is OS command]
+   Execute rest of line as OS command in sub-shell.  Notice no quotes needed.
+   Empty rest of line to spawn interactive shell.  Equivalent to
+   '$system([quotes OS command string]);' system task.
+
+:where
+   Print back trace of most recently suspended control thread including all
+   upward thread enables with source and scope locations.  To see a listing
+   of all pending scheduled event activity and thread states use $snapshot;
+   or :snapshot.  :where corresponds as closely as possible to normal
+   call stack trace back.  ':' prints instance scope and last source
+   listing location.  If :where fails, suspension was from declarative code.
+   Try single step and entering :where again.
+
+:quit
+   Exit.  Equivalent to $finish;
+
+:print [/format][#width] [expression]
+   Evaluate and print expression.  If [/format] is present, interpret the
+   value according to format.  Formats are:  'd' (decimal), 'u' (unsigned),
+   'b' (binary), 'h' or 'x' (hex), 's' (string), or 'c' (1 character).  If
+   the [/format] is omitted, use current default unless the expression is a
+   string or real.  Starting default base is hex, but use ':set printbase'
+   to set different default base.  /u format prints bit pattern as unsigned.
+   If [#width] value is present, interpret as [width] wide, instead of width
+   computed from operator width rules.  Any format or width are ignored for
+   reals, use $realtobits to view bit pattern.
+
+:reset [stop]
+   Reset simulation back to time 0 and restart simulation.  Interactive mode
+   must be explicitly entered by interrupt (^c), calling $stop or [stop]
+   option.  If a -i startup file was given it is executed on interactive
+   entry.  $reset_count and $reset_value are not changed.  If optional
+   :reset stop argument is present, stop just before simulation, else rerun
+   without stopping even if -s option was given on command line.  Equivalent
+   to $reset system task but can be used to restart for debugging models
+   that use the $reset system task.  The $reset system task uses the -s
+   option unless the first argument is non zero and stops before simulation.
+   All uncompleted interactive statements are disabled by either :reset
+   or $reset.  They are re-enabled by typing history command number or
+   running -i start up interactive file.  Debugger state : breakpoints
+   (left enabled) and history are preserved.
+
+:expris [expression]
+   Print type and width of expression.  Use to determine Verilog width and
+   property rules for complex expressions.
+
+:varis [variable]
+   Print type and width and declaration keywords of variable.
+
+:whatis [identifier]
+   Print symbol information for every use of identifier.  Also, emits one
+   instance reference for each use, so a breakpoint can be set.
+
+:list [range]
+   List source within [range] lines.  Some [range]s are relative to last
+   printed line.  Any scope change or $list or previous :list command
+   changes the last printed line.  Legal [range]s are:
+ 
+     + or [empty]             10 lines starting with last printed.
+     +0                       10 lines around current line.
+     -                        10 lines ending 1 before previous first line.
+     ++                       First 10 lines of next file.
+     --                       Last 10 lines of previous file.
+     [file]:[number]          10 lines around [number] in file [file].
+     [number]                 10 lines around [number] in current file.
+     [+/-][offset]            10 lines starting [offset] from current.
+     [+/-][num1],[+/-][num2]  Range, if [+/-] offset from current line.
+     [scope reference]        First 10 lines starting at [scope].
+ 
+   By default 10 lines are list, use ':set listsize [number]' to change
+   number of printed lines to [number].  Notice stepping with ';' does not
+   change last printed line.  Use [file]:[number] to list inside `include
+   files.  ++ and -- exit to file and line of first inclusion of file.
+   Read library files are same as source files.
+
+:set [debugger parameter] [value]
+   Set debugger internal parameter to [value].  Legal set parameters are:
+ 
+   :set listsize [number]     Default is 10 lines to list.
+   :set histlistsize [number] Default is 20 history commands to list.
+   :set noscopechange         Disable automatic scope setting on entry to
+                              interactive mode.
+   :set scopechange           Re-enable automatic scope setting on.  Scope
+                              not set to named blocks in functions.
+   :set printbase [base]      Set default :print command base, values: hex
+                              (default), decimal, octal binary.
+   :set nologecho             Turn off writing of input interactive commands
+                              the log file (default).
+   :set logecho               Turn on writing of input commands.
+
+:info [debugger parameter]
+   Show value of debugger state or parameter setting.  Legal info parameters
+   are: listsize, histlistsize, scopechange, breakpoints, displays,
+   printbase and logecho.  For breakpoints and auto-display expressions
+   prints status information for each.
+
+:scope [scope reference]
+   Change interactive scope to [scope reference] location.  Type
+   ':help scope' for list of legal scope selection forms.  Any [line] is
+   used only to determine surrounding scope.  Scope only applies to
+   interactive mode and system tasks that explicitly are defined to use the
+   interactive scope.   Extended version of $scope system task.  If scope
+   set to function named block scope, next interactive entry will change
+   scope to function body scope (assuming scopechange mode active).
+
+:breakpoint [scope reference] or none
+   Set statement breakpoint at all instances of [scope reference].  Type
+   ':help scope' for a list of legal [scope reference] forms.  If the
+   reference selects an instance, only the type of the instance is used.
+   If the [scope reference] is not a [file:][line] reference, use first
+   initial, always or task statement of scope.  If no argument, set at
+   last :list argument (first if range, closest if backward) that must be
+   within task, function or initial or always block.  Setting a breakpoint
+   at a line means the first procedural statement at or after the line (but
+   must be within scope).  Type ':help breakpoints' for discussion of other
+   breakpoint commands.
+
+:ibreakpoint [scope reference][,[file:][line]] or none
+   Set statement breakpoint at instances of [scope reference] file [file]
+   and [line] line.  Type ':help scope' for a list of legal [scope ref.]s,
+   but here only explicit instance scope references are legal.  If the
+   ',[file:][line]' argument is omitted, use first statement of first
+   initial, always, or task (for task scope).  If ',[line]' but no [file]
+   is given, use first or only file of scope.  If no scope reference and
+   only ',[file:][line]' is given, use current scope.  No argument means
+   set at last :list argument (first if range, closest if backward)
+   that must be within task, function, or initial or always block.
+   Type ':help breakpoints' for discussion of other breakpoint commands.
+
+:delete [optional type] [number]
+   Delete breakpoint or display expression with number [number] or all if
+   number is omitted.  [optional type] is breakpoints or displays (default
+   if omitted is breakpoints).  Type 'info breakpoints' or 'info displays'
+   to determine breakpoint or auto-display number.  If [number] is omitted,
+   delete all breakpoints or auto-display expressions.
+
+:enable [optional type] [number]
+   Enable breakpoint or display with number [number].  [optional type]
+   is either breakpoints or displays (breakpoints is default if omitted) and
+   can be abbreviated to first letter.  Type 'info breakpoints' or
+   'info displays' to determine breakpoint or auto-display expression
+   number and enable state.
+
+:disabl [optional type] [number]
+   Temporarily disable breakpoint or display with number [number].
+   [optional type] is breakpoints or displays (breakpoints is default if
+   omitted) and can be abbreviated to first letter. Type 'info breakpoints'
+   or 'info displays' to determine breakpoint or auto-display number and
+   enable state.  Notice final e must not appear to avoid conflict with
+   Verilog disable keyword (any unique prefix such as 'disa' works).  Also
+   notice that :disabl disables an added : debugger breakpoint, but disable
+   statement or -[number] disables simulation of a Verilog statement.
+
+:step [optional repeat count]
+   Step to next procedural line.  Execute one statement or statements on
+   current line, stop before first statement of next line.  May process
+   pending declarative events before stepping.  Execution steps into any
+   task or function.  Equivalent to ',' interactive Verilog command.
+   Always prints location after stopping.  if optional repeat count, step
+   that many times before stopping and printing message.  If interrupt (^c)
+   or breakpoint hit during stepping, stop stepping and enter interactive
+   mode.
+
+:istep [optional repeat count]
+   Step to next procedural statement that is in same instance tree location.
+   Otherwise identical to :step.  If debugger entered by interrupt, use one
+   :step before :istep since scope may have been in module without any
+   procedural statements.  :istep uses currently executing instance not
+   interactive scope set by $scope.
+
+:history [optional number]
+   Print 20 (or value of histlistsize info debugger parameter) commands.
+   If [number] appears, print [number] (0 means all) history commands.
+   Pauses and prompts for CR every histlistsize lines.
+
+:emptyhistory
+   If all history commands have completed or are disabled with (-[number]
+   command), discard retained history and set next history command to 1.
+
+:display [/format][#width] [expression]
+   Set up [expression] in display table so that it is displayed on every
+   entry to interactive mode.  Arguments are identical to :print command.
+   Use ':delete display' or ':undisplay' to delete all auto-display
+   expressions.  If either is followed by a number, delete that numbered
+   display only.  Use ':info display' to list current displays.  ':display'
+   with no arguments displays all current auto-display expressions.
+   Use 'enable display' and 'disabl display' to temporarily turn off or on
+   an auto-display expression.
+
+:undisplay [optional number]
+   Delete [number] auto-display expression or all current if [number] is
+   not present.  Same as ':delete display' command.
+
+:tbreakpoint [scope reference] or none
+   Command identical to :breakpoint except breakpoint is temporary and
+   removed after it is hit the first time.  To avoid tracing in task or
+   function (approximate DBX/GDB next command), use the :nextb command.
+   It sets a :tibreak at the next line and executes a '.' command.  Because
+   of delay and event controls, other threads may be executed before break
+   is hit.  The :ignore command can be used with :tbreakpoint.  After
+   ignore count hits, the break point is taken and then removed.
+
+:tibreakpoint [scope reference][,[file:][line]] or none
+   Command identical to :ibreakpoint except breakpoint is temporary and
+   removed after it his the first time (see :tbreakpoint help).  Only
+   stops in instance that is same as scope reference instance.
+
+:ignore [breakpoint number] [ignore count]
+   Do not stop at break point [number] until [ignore count] hits of the
+   break point have occurred.  Ignore count assumes last hit was 0th.
+   To remove an :ignore count, use 'ignore [break number] 0'.  Use
+   ':info breakpoints' to determine number of hits and any pending ignore
+   count.
+
+:cond [breakpoint number] [optional condition expression]
+   Do not stop at break point [number] unless [expression] evaluates to
+   a positive non x/z value (i.e. true).  Expression will be checked and
+   evaluated in instance and task/function or named block scope of break
+   point.  Since Verilog variables persist, :cond expression variable always
+   have values.  Conditions are evaluated before ignore counts so if
+   condition is false hit count does not rise.  Use ':cond [break number]'
+   to remove condition.
+
+:snapshot
+   Print snapshot of current procedural location and list of statement at
+   which each procedural (per instance) thread suspended at.  Also lists
+   pending events on head of event list.  May be long so one way to view it
+   is to type: $flushlog; then ':sh [evoke editor on verilog.log file]'.
+
+:nextb
+   Abbreviation for :tibreak [line number of next thread statement]
+   followed by '.'.  Analog of DBX/GDB next command steps over current
+   statement.  Break point is visible and can be removed before it is hit.
+   If no next statement in thread, temporary break point not set and error
+   message emitted.  :nextb over task enable may execute other threads
+   before stopping if the task contains event or delay controls.  :nextb
+   and for that matter any temporary break point do not use up a break
+   point number unless a new break point is set before temporary break
+   point is hit.  See ':help :tbreakpoint' and ':help statements' for
+   more information.
+
+C3 > $finish(2);
+Halted at location **helpgen3.inp(65) time 0 from call to $finish.
+0 simulation events and 0 declarative immediate assigns processed.
+Partial optimized sim - 51 behavioral statements (0 procedural suspends).
+  Times (in sec.):  Translate 0.0, load/optimize 0.1, simulation 0.2.
diff --git a/doc/systasks.1 b/doc/systasks.1
new file mode 100644
index 0000000..5a84a8c
--- /dev/null
+++ b/doc/systasks.1
@@ -0,0 +1,1249 @@
+.\" $Cver: systasks,man,v 2.4 11/25/02 $
+.TH Systasks 1 "Release 2.5" "Pragmatic C Software" "" 
+.de LN
+.sp
+.ti -1.0i
+------------------------------------------------------------------------------
+.fi
+.br
+..
+.ce
+\s+3All Cver System tasks and Functions\s-3
+.SP
+.SH INTRO
+These man pages document every system task and system
+function recognized by Cver including those not implemented.
+System tasks and functions are mixed together and 
+appear in alphabetical order.
+Similar tasks and system functions are intermixed.
+Functionally similar tasks and functions are combined into
+one section and alphabetized according to main task or function.
+.PP
+For system functions, the SYNOPSIS section contains
+normal user function declaration notation to define return type
+and argument type even though system functions are never really declared.
+There is no concept of separate function header in Verilog.
+In the P1364 LRM most system function are indicated as returning
+integer, but since they rarely can return a negative value they
+really return reg [31:0].
+.PP
+System tasks appear in the SYNOPSIS section using
+the task invocation form (i.e. task keyword omitted)
+and usually with meta descriptions of parameters.
+In Verilog system tasks, unlike user defined tasks,
+can always take a variable number of arguments and
+optional but not required arguments can be omitted
+either with ",," or by ending the argument list.
+Some system functions also have optional arguments that
+can be omitted.
+.PP
+In Verilog all strings except $display type format specifiers can be
+either expressions that are interpreted as strings (high 0 bits trimmed
+off and then interpret each byte as a character) or literal strings
+(enclosed by double quotation marks).  Any [file name] can be either
+type of string.
+.PP
+P1364 LRM timing checks are not documented here because they do
+not vary between simulators.  See P1364 LRM section 14.5 for
+documentation of timing checks, edge control specifiers, and notifiers.
+.LN
+.SH NAME
+$bitstoreal \- convert 64 bit register to real
+.br
+$realtobits \- convert real to 64 bit register
+.br
+$itor \- convert integer to real
+.br
+$rtoi \- convert real to integer by rounding
+.SH SYNOPSIS
+function real $bitstoreal;
+.br
+.ti +0.1i
+input [63:0] bit_val;
+.br
+function [63:0] $realtobits; 
+.br
+.ti +0.1i
+input real real_val;
+.br
+function real $itor;
+.br
+.ti +0.1i
+input integer int_val;
+.br
+function integer $rtoi;
+.br
+.ti +0.1i
+input real real_val;
+.SH DESCRIPTION
+System functions to convert to and from reals.  Use $realtobits and 
+$bitstoreal to pass reals across module ports.  Use $itor and $rtoi
+to convert between integer and real by rounding.  In Verilog, assignments
+also implicitly convert to or from a real depending on the left hand
+side Lvalue type.  Cver conversion to real from wider than 32 bit
+values attempts to preserve as many bits as possible (usually 51 or 52
+depending on hardware platform).
+.SH REFERENCE
+Defined in P1364 LRM section 14.9.
+.LN
+.SH NAME
+$cleartrace \- turn off statement tracing
+.br
+$settrace \- turn on statement tracing
+.br
+$clearevtrace \- turn off declarative event tracing
+.br
+$setevtrace \- turn on declarative event tracing
+.br
+$tracefile \-  set separate output file for trace output
+.SH SYNOPSIS
+$cleartrace;
+.br
+$settrace;
+.br
+$clearevtrace;
+.br
+$setevtrace;
+.br
+$tracefile([file name]);
+.SH DESCRIPTION
+Cver supports separate control of statement
+and declarative event tracing.
+The options -t starts simulation with statement tracing on.
+The option minus -et start simulation with event tracing on.
+The -t option and $settrace and $cleartrace in
+some other simulators enable and disable both types of tracing.
+To approximate full tracing in other simulators use both -t and -et
+options or call both $settrace and $setevtrace.
+.PP
+The $tracefile system task set the output file
+for tracing (both types) to [file].
+The $tracefile argument can be a variable
+that is treated as a string with high 0 bits removed. 
+An alternative way to set a separate trace output file is with
+the +tracefile [file] command line option.  Executing $tracefile
+replaces any +tracefile set file.
+If $tracefile is not used, trace output is written to STDOUT and
+the log file (if it exists).  The tracefile can be the string "stdout"
+that has the effect of restoring trace output to default STDOUT and
+the log file.  If a trace file is set, trace output is not written to
+stdout.
+.SH "REFERENCE"
+These system tasks are not mentioned in the P1364 LRM because they apply
+to the interactive environment not addressed by the standard.
+.LN
+.SH NAME
+$cos \- compute cosine of real input
+.br
+$sin \- compute sin of real input
+.br
+$tan \- compute tangent of real input
+.br
+$acos \- compute arc cosine of real input
+.br
+$asin \- compute arc sin of real input
+.br
+$atan \- compute arc tangent of real input
+.br
+$acosh \- compute hyperbolic arc cosine of real input
+.br
+$asinh \- compute hyperbolic arc sine of real input
+.br
+$atanh \- compute hyperbolic arc tangent of real input
+.br
+$sgn \- compute sign of real input (returns integer)
+.br
+$int \- convert real input to 32 bit integer (uses C not Verilog conversion)
+.br
+$ln \- compute nature logarithm of real input
+.br
+$log10 \- compute base 10 logarithm of real input
+.br
+$abs \- compute absolute value of real input
+.br
+$pow \- compute exponent of first real input to second real argument power
+.br
+$sqrt \- compute square root real input
+.br
+$exp \- compute e raised to power of real input
+.br
+$min \- compute minimum of 2 real inputs
+.br
+$min \- compute maximum of 2 real inputs
+.SH SYNOPSIS
+ System function identical to IEEE math functions except for added $ prefix
+.SH DESCRIPTION
+This is non digital P1364 Cver enhancement that is available in digital
+Cver because it is required for Verilog-AMS version of Cver.
+Functions are defined in Verilog-AMS 2.0 OVI LRM.  Behavior is identical
+to behavior documented by Unix math function man pages.
+.PP
+Cver also allows use of system functions with constant arguments in
+constant expressions so parameter definitions such
+as "parameter cos2 = $cos(2.0);" are legal in Cver and are part of
+new Verilog 2001 standard.  Cver does not yet support constant argument
+user functions in constant expressions.
+.PP
+The following Hspice math library variants are also supported: 
+$hsqrt, $hpow, $hpwr, $hlog, $hlog10 $hdb, and $hsign.  See
+Hspice documentation for behavior and required arguments.
+.SH REFERENCE
+See Verilog-AMS 2.0 OVI standard LRM.  Standard IEEE math functions.
+See any Hspice documentation.
+.LN
+.SH NAME
+$countdrivers \- return 1 if bus contention because more than one driver
+.SH SYNOPSIS
+function [31:0] $countdrivers;
+.br
+.ti +0.1i
+// must be wire
+.ti +0.1i
+input net;
+.br
+.ti +0.1i
+output [31:0] net_is_forced;
+.br
+.ti +0.1i
+output [31:0] number_of_01x_drivers;
+.br
+.ti +0.1i
+output [31:0] number_of_0_drivers; 
+.br
+.ti +0.1i
+output [31:0] number_of_1_drivers; 
+.br
+.ti +0.1i
+output [31:0] number_of_x_drivers; 
+.SH DESCRIPTION
+System function return 0 if there is no more than one driver
+(all wire fan-in is tri-stated (in hiZ state) or a most one fan-in
+wire (or select of wire) is non tri-stated).  Returns 1 if there
+is more than one non-tri-stated fan-in.  The first net argument is
+required.  If a second argument is given, it must be a reg lvalue
+expression that is set to the total number of fan-in any state other
+than hiZ.  If a third argument is given, it must be a reg lvalue
+expression that is set to the total number of fan-in that drives 0.
+If a fourth argument is given, it must be a reg lvalue
+expression that is set to the total number of fan-in that drives 1.
+If a fifth argument is given, it must be a reg lvalue
+expression that is set to the total number of fan-in that drives x.
+If an argument is omitted, but an argument to its right is needed,
+use ",,".  Notice a statement:  "always @w numdriv = $countdrivers(w);" 
+does not work since the number of drivers may change without the wire's
+value changing especially for strength wires.
+Notice that in the LRM, driver usually means non tri-stated fan-in.
+Sometimes driver means instead any fan-in whether or not it is tri-stated.
+.SH REFERENCE
+Mentioned in P1364 LRM section F.1 but detailed definition in OVI LRM
+section B.10.
+.LN
+.SH NAME
+$display, $displayb, $displayh, $displayo \- write formatted value to stdout
+.br
+$write, $writeb, $writeh, $writeo \- write formatted value to stdout
+.br
+.SH SYNOPSIS
+$display([intermixed list of format strings and expressions]);
+.br
+$display[bho]([intermixed list of format strings and expressions]);
+.br
+$write([intermixed list of format strings and expressions]);
+.br
+$write[bho]([intermixed list of format strings and expressions]);
+.br
+.SH DESCRIPTION
+Write formatted values to standard out (and the log file).  The format is
+similar to C language printf format except the format string must be
+literal, more than one format string can appear followed by values to replace
+format references with, only qualifier is 0 that causes trimming of the
+value to narrowest field possible.  The %g format for reals is identical
+to C language printf %g format.
+$display always appends a new line to the end of the displayed string.
+For $write, any new line must be explicitly written.  By default, variable
+that do not match any format specifier are written in decimal.
+Use $displayb and $writeb to change the default to binary, $displayh
+and $writeh to change default to hex, and $displayo and $writeo to change
+to octal.
+.SH "REFERENCE"
+Defined in P1364 LRM section 14.1.1.
+.SH "SEE ALSO"
+The same format is used by the $fdisplay and $fwrite tasks which write
+to file(s), the $monitor and $fmonitor tasks that write changed expressions
+at the end of a time slot, and $strobe and $fstrobe that always write
+value of an expression at the end of a time slot.
+.LN
+.SH NAME
+$dist_chi_square \- return random 32 bit value in Chi Square distribution
+.br
+$dist_erlang \- return random 32 bit value in Erlangian distribution
+.br
+$dist_exponential \- return random 32 bit value in Exponential distribution
+.br
+$dist_normal \- return random 32 bit value in Standard Normal distribution
+.br
+$dist_poisson \- return random 32 bit value in Poisson distribution
+.br
+$dist_t \- return random 32 bit value in Standard T distribution
+.br
+$dist_uniform \- return random 32 bit value uniformly distributed in range
+.SH SYNOPSIS
+function [31:0] $dist_chi_square;
+.br
+.ti +0.1i
+inout [31:0] seed;
+.br
+.ti +0.1i
+input [31:0] degree_of_freedom;
+.br
+function [31:0] $dist_erlang;
+.br
+.ti +0.1i
+inout [31:0] seed;
+.br
+.ti +0.1i
+input integer k_stage;
+.br
+.ti +0.1i
+input integer mean;
+.br
+function [31:0] $dist_exponential;
+.br
+.ti +0.1i
+inout [31:0] seed;
+.br
+.ti +0.1i
+input integer mean;
+.br
+function [31:0] $dist_normal;
+.br
+.ti +0.1i
+inout [31:0] seed;
+.br
+.ti +0.1i
+input integer mean;
+.br
+.ti +0.1i
+input integer standard_deviation;  
+.br
+function [31:0] $dist_poisson;
+.br
+.ti +0.1i
+inout [31:0] seed;
+.br
+.ti +0.1i
+input integer mean;
+.br
+function [31:0] $dist_t;
+.br
+.ti +0.1i
+inout [31:0] seed;
+.br
+.ti +0.1i
+input integer degree_of_freedom;
+.br
+function [31:0] $dist_uniform;
+.br
+.ti +0.1i
+inout [31:0] seed;
+.br
+.ti +0.1i
+input integer start;
+.br
+.ti +0.1i
+input integer end;
+.SH DESCRIPTION
+These are the random deviate generation functions defined in
+P1364 LRM.  Algorithm follow "Numerical Recipes in C".  However  
+they are somewhat unusual in taking integer arguments and producing
+scaled integer outputs rather than the more normal real number inputs
+and outputs between 0.0 (sometimes -1.0) and 1.0.
+Each distribution function takes a
+first argument that is a seed that sets cyclical starting point in the
+distribution sequence.
+Each function returns a random value according to
+the distribution type and updates the seed so that if a passed seed is
+saved and reused, both the same value will be returned, and the same new
+seed will be set.  This properly allows repeatability for debugging.
+.PP
+The $dist_chi_square and $dist_t degree_of_freedom values determine the
+shape of the distribution (larger values widen the distribution).
+The mean parameter used in $dist_erlang, $dist_exponential,
+$dist_normal and $disp_poisson cause the average value
+returned to converge to the passed mean.
+The $dist_normal function standard deviation input parameter determines
+shape of the standard normal distribution (larger value widens
+the distribution).
+The $dist_uniform start and end determine the range within which the
+uniformly distributed random number fits.  Start and end may be negative 
+but start must be less than end.  The mean, k_stage and degree_of_freedom
+parameters must be positive
+.SH REFERENCE
+Defined in P1364 LRM section 14.10.2.
+.SH "SEE ALSO"
+See any statistics textbook or CRC Handbook of Standard Math Tables 
+for definitions of the formulas.
+Also see "Numerical Recipes in C" for algorithms.
+.LN
+.SH NAME
+$dumpvars \- set up variables that are written to VCD file
+.br
+$dumpall \- dump current value of all variables set up for dumpvaring
+.br
+$dumpflush \- make OS call to flush VCD file buffer to file
+.br
+$dumplimit \- set maximum size of VCD file
+.br
+$dumpoff \- turn off dumping to VCD file on variable changes
+.br
+$dumpon \- turn on dumping to VCD file on variable changes
+.SH SYNOPSIS
+$dumpvars([level], [list of scopes and/or variables to dump]);
+.br
+$dumpall;
+.br
+$dumpfile([file name]);
+.br
+$dumpflush;
+.br
+$dumplimit([limit number of bytes]);
+.br
+$dumpoff;
+.br
+$dumpon;
+.SH DESCRIPTION
+The $dumpvars system task causes first a header to be written to the
+VCD (value change dump) file that defines a short code for each variables.
+Then whenever a variable changes, the variable's code and value are
+written to the VCD file.  When $dumpvars is first called the value
+of all variables is written to the VCD file.
+.PP
+$dumpvars must be called before any writing of changed variable 
+values to the VCD dump file can occur to set up the variables that are
+dumped.  The $dumpfile system task can change the name of the VCD dump
+file from the default verilog.dump.  It must be called before or at the
+same time as $dumpvars.  When $dumpvars is called actual dumping is set
+up at the end of that time slot. 
+It is an error for $dumpvars to be called more than once.
+.PP
+$dumpvars takes either scopes or variable names as arguments.
+A Variable name (or hierarchical reference) causes just that variable
+to be written to the VCD file.  a Scope causes all variables in the
+scope and all variables in [level] scopes down to be written to the
+VCD file on change.  [level] value 0 means descend to the bottom of the
+hierarchy.  If $dumpvars is called with no arguments, all variables in
+the design are written to the VCD file.
+.PP
+$dump limits set the maximum size of the VCD dump file to [limit].  Once
+[limit] bytes have been written, no more writing to the dumpvars file occurs.
+$dumpoff stop dumping of variables and writes every dumped variable to 
+the VCD dump file with unknown (x) value.  $dumpon restarts dumping of
+variable changes and starts by writing the current value of every variable
+to the VCD dump file.  
+.PP
+The +dumpvarsextended added Cver option writes a non standard VCD file but
+allows strengths (not just the value part) to be written and uses hex
+format instead of binary where possible to reduce the VCD file size.
+.SH "REFERENCE"
+Defined in P1364 LRM section 15.
+.LN
+.SH NAME
+$fdisplay, $fdisplayb, $fdisplayh, $fdisplayo \- write formatted value to file(s)
+.br
+$fwrite, $fwriteb, $fwriteh, $fwriteo \- write formatted value to file(s)
+.SH SYNOPSIS
+$fdisplay([multi-channel], [intermixed list of format strings and expressions]);
+.br
+$fdisplay[bho]([multi-channel], [intermixed list of format strings and expressions]);
+.br
+$fwrite([multi-channel], [intermixed list of format strings and expressions]);
+.br
+$fdisplay[bho]([multi-channel], [intermixed list of format strings and expressions]);
+.SH DESCRIPTION
+Same as $display and $write but writes to all file streams
+selected by on bits in passed 32 bit multi-channel descriptor.
+If bit is on but file corresponding to bit position if not opened
+with $fopen system function, no write occurs.
+The idea of multi-channel descriptors allows one $fdisplay to write
+to more than one file as opposed to requiring multiple writes.
+.SH REFERENCE
+Defined in P1364 LRM section 14.2.2.
+.SH "SEE ALSO"
+See related $display and $write system tasks.  See $fopen and $fclose
+for opening and closing file streams and assigning multi-channel descriptors.
+.LN
+.SH NAME
+$finish \- exit Cver
+.SH SYNOPSIS
+$finish;
+.br
+$finish([message level]);
+.SH DESCRIPTION
+Exit Cver and return control to the host operating system.
+if a value is passed, if it is 0 (same as no argument) prints nothing,
+if 1 is passed prints normal exit message, and if 1 prints message as
+if +verbose option were selected.
+.SH REFERENCE
+Defined in P1364 LRM section 14.4.1.
+.LN
+.SH NAME
+$flushlog \- flush log and trace file internal OS buffers
+.SH SYNOPSIS
+$flushlog;
+.SH DESCRIPTION
+Flush the log file OS buffers.  If the $tracefile system task has
+been used to set a separate trace output file, that stream also is flushed.
+.SH REFERENCE
+Not defined in P1364 LRM but commonly implemented.
+.LN
+.SH NAME
+$fmonitor, $fmonitorb, $fmonitorh, $fmonitoro \- write changed formatted value to file(s)
+.SH SYNOPSIS
+$fmonitor([multi-channel], [intermixed list of format strings and expressions]);
+.br
+$fmonitor[bho]([multi-channel], [intermixed list of format strings and expressions]);
+.SH DESCRIPTION
+If any expression in the format variable list changes, format and write the
+value to a multi-channel descriptor file list at the
+end of the simulation time slot.
+If a time returning system functions such as $time appears in the list,
+it does not cause a change.  Format is same as $fdisplay.
+Any number of $fmonitors may be used and if more than one changed the
+format list for each changed $fmonitor is written at time slot end.
+.br
+.SH "REFERENCE"
+Defined in P1364 LRM section 14.2.2.
+.SH "SEE ALSO"
+$monitor is same but writes to stdout.  See $display for format definition.
+.LN
+.SH NAME
+$fopen \- open a file and assign a multi-descriptor channel bit 
+.br
+$fclose \- close a file and free for reuse a multi-descriptor bit
+.SH SYNOPSIS
+function [31:0] $fopen([file name]); 
+.br
+$fclose([multi-channel descriptor]);
+.SH DESCRIPTION
+Verilog allows writing to multiple open files at once
+using a multi-channel file descriptor.
+Bit 0 (least significant bit) is associated with stdout and is always open.
+The $fclose call closes the file associated with any on bit in the
+passed 32 bit multi-channel value.
+The $fopen system function is passed a file name (can be any length
+and need not be a literal string) and returns a multi-channel descriptor
+with the next available bit (bit corresponding to
+un-opened descriptor channel) set.
+$fopen reuses multi-channel bits freed by $fclose.
+.SH REFERENCE
+Defined in P1364 LRM section 14.2.1.
+.SH "SEE ALSO"
+See $fdisplay, $fwrite, $fmonitor, and $fstrobe routines that write to
+multi-channel descriptors.
+.LN
+.SH NAME
+$fstrobe, $fstrobeb, $fstrobeh, $fstrobeo \- write formatted value to file at end of time slot
+.SH SYNOPSIS
+$fstrobe([multi-channel], [intermixed list of format strings and expressions]);
+.br
+$fstrobe[bho]([multi-channel], [intermixed list of format strings and expressions]);
+.SH DESCRIPTION
+Same as $fdisplay but formats and writes value at the end of time
+time slot rather than when the $fstrobe statement is executed. 
+Format is identical to $fdisplay and [bho] suffix letter changes
+default for expression that appears outside of any format as with $display.
+One format is written for every $fstrobe and $strobe executed during
+the time slot.
+.SH REFERENCE
+Defined in P1364 LRM section 14.2.2.
+.SH "SEE ALSO"
+$strobe is same except writes to stdout.
+.LN
+.SH NAME
+$getpattern \- function for rapid assignment of memory bits to concatenate of scalars
+.SH SYNOPSIS
+assign {<list of scalars or selects>]} = $getpattern(<memory>[<index>];
+.SH DESCRIPTION
+This function must be used on the right hand side of a continuous assignment
+where the left hand side is a concatenate of scalars or constant bit selects.
+The argument must be a select of memory (normally loaded using $reaadmem)
+that is a variable.  When the variable select index is changed the new
+memory value determined by the select index will be rapidly (i.e. with
+no need for expression evaluation) assigned to the scalars.
+Normally the assignment process will be driven by a for loop that increments
+the index.  No other use of $getpattern is allowed.
+.SH REFERENCE
+Defined in P1364 LRM section F.2.
+.SH "SEE ALSO"
+See P1364 LRM section F.2 for a module that uses $getpattern or see the
+ver_srcs directory from your release for example use.
+.LN
+.SH NAME
+$history \- print list previously executed interactive commands
+.br
+$nokeepcommands \- do not add executed interactive commands to history list
+.br
+$keepcommands \- add executed interactive commands to history list 
+.SH SYNOPSIS
+$history([number of commands to list]);
+.br
+$keepcommands;
+.br
+$nokeepcommands;
+.SH DESCRIPTION
+$history lists either all or [number] of most recently executed interactive
+commands.  All commands except history enable, disable, and one character
+abbreviation commands are entered in the history list.
+Added : debugger commands are also added to the history list.
+.PP
+Each command is numbered so it can be re-executed by entering [number]
+at the interactive prompt and, for scheduled and uncompleted commands,
+disabled by typing -[history command number].
+$nokeepcommands disables collection of interactive commands
+into the history list and $keepcommands enables collection.
+Cver keeps all commands entered on the history list until
+a :emptyhistory added debugger command is entered at which point the
+history list is made empty.
+$input command scripts should begin with $nokeepcommands and end with
+$keepcommands to minimize history list size.  The added debugger
+:history command is more flexible than $history.  Multiple line commands
+(end with escaped new line in Cver) are printed as one command. 
+.SH REFERENCE
+Not defined in P1364 LRM.  OVI LRM 1.0 section D.8.
+.SH "SEE ALSO"
+See added debugger online ":help history" command for more detailed 
+description of Cver's history mechanism.
+.LN
+.SH NAME
+$input \- enter interactive commands from a file
+.SH SYNOPSIS
+$input([file]);
+.SH DESCRIPTION
+$input and the -i [file] Cver command argument cause interactive
+commands to be read from [file].  It can contain added debugger
+: commands.  If an $input script file contains a $input call,
+command reading continues in the new script.  The new script replaces
+the old and any un-executed interactive commands after the $input are not
+called.  The new script is chained to not called.
+Interactive mode must be entered before commands can
+be read from the $input file so both -i and $input do nothing unless
+interactive mode is entered.  $input should not appear in Verilog source. 
+.SH REFERENCE
+Defined in P1364 LRM section F.3.
+.SH "SEE ALSO"
+See added debugger online ":help debugging" for additional documentation.
+.LN
+.SH NAME (NOT SUPPORTED BY CVER)
+$key \- save every press key stroke to a file
+.br
+$nokey \- disable saving of key strokes
+.SH DESCRIPTION
+Cver does not support $key because it depends on the original XL scheme
+for tracking asynchronous interrupts and is not compatible with Cver's
+added : debugger and line continuation scheme. 
+.PP
+There are two better ways to allow restarting and simulating to a particular
+problem statement at a particular problem time.
+First, prepare a $input script and use -s with -i command
+options to rerun the script.  Second, use the added :ibreak or :break
+breakpoint command with the :ignore [count] command to skip [count]
+break points to return to the problem time.  Use :info breakpoint to
+determine the number of times a break point was hit.  Alternative
+use the :breakpoint command :cond [expression] command to attach a
+condition to a statement break point.
+.SH REFERENCE
+See P1364 LRM section F.4.
+.SH "SEE ALSO"
+See added debugger :help online help system messages.
+.LN
+.SH NAME
+$list \- list source reconstructed from internal data base for scope
+.SH SYNOPSIS
+$list([scope]);
+.SH DESCRIPTION
+List scope to stdout and the log file by reconstructing source from
+Cver's internal representation.  All parameters and specparams are
+displayed as numeric constants.  If no argument is given, list the current
+scope.  If the -d command line option is used, reconstructed source
+for an entire design is output.  If $list is executed from interactive
+mode, the current interactive scope (maybe set with the $scope system
+task is used).  It is better from interactive mode to use the :list
+added debugger command that prints source lines exactly as they appear
+in the source input and allows more control of lines to list.
+.SH REFERENCE
+See P1364 LRM section F.5.
+.SH "SEE ALSO"
+Type ":help :list" in interactive mode for
+documentation of :list range specification.
+.LN
+.SH NAME
+$log \- set new log output file or re-enable writing to log file
+.br
+$nolog \- disable writing to the log file
+.SH SYNOPSIS
+$log;
+.br
+$log([file name]);
+.br
+$nolog;
+.SH DESCRIPTION
+Normally all terminal (stdout) output is written to the log file that
+has name verilog.log and is over-written for each new run of Cver
+command option set the log file to [file].  Another
+way to disable writing to the log file is to use file name /dev/null on
+Unix and nul on OS2/DOS.
+.SH REFERENCE
+See P1364 LRM section F.6.
+.LN
+.SH "NAME (CVER EXTENSION)"
+$memuse \- print message giving dynamically allocated memory.
+.SH SYNOPSIS
+$memuse;
+.SH DESCRIPTION
+System task that can be called to output to stdout and the log file
+the number of bytes of dynamically allocated memory.
+Rather useless added system task since it is better to use the +verbose
+option.
+.SH REFERENCE
+Cver extension not mentioned in the P1364 LRM.
+.LN
+.SH NAME
+$monitor, $monitorb, $monitorh, $monitoro \- write changed formatted value to file(s)
+.br
+$monitoroff- disable display of monitor changes
+.br
+$monitoron- re-enable display of monitor changes
+.SH SYNOPSIS
+$monitor([multi-channel], [intermixed list of format strings and expressions]);
+.br
+$monitor[bho]([multi-channel], [intermixed list of format strings and expressions]);
+.br
+$monitoron;
+.br
+$monitoroff;
+.SH DESCRIPTION
+If any expression in the format variable list changes, format and write the
+value to stdout and the log file at the end of the simulation time slot. 
+Only one $monitor can be active at a time.  Execution of a new monitor
+replaces the previous (see $fmonitor if multiple active monitors are
+needed, use multi-channel channel 0 to write to stdout and log file).
+If a time returning system functions such as $time appears in the list, it
+does not cause a change.  Format is same as $fdisplay. $monitoroff turns
+off display of changed monitor values and $monitoron re-enables writing
+of changed formatted values.
+.SH "REFERENCE"
+Defined in P1364 LRM section 14.1.
+.SH "SEE ALSO"
+$fmonitor is same but writes to file using multi-channel descriptor,
+See $display for format documentation.
+.LN
+.SH NAME
+$q_add \- place an entry on a queue
+.br
+$q_exam \- get selected queue status information
+.br
+$q_initialize \- create a new queue
+.br
+$q_remove \- get an entry from a queue
+.br
+$q_full \- return 1 if a queue if full else 0
+.SH SYNOPSIS
+$q_add;
+.br
+.ti +0.1i
+input integer q_id; // unique number to identify queue
+.br
+.ti +0.1i
+input integer job_id; // unique number to identify job
+.br
+.ti +0.1i
+input integer inform_id; // user defined value added to queue
+.br
+.ti +0.1i
+output integer status; // completion status
+.br
+$q_exam;
+.br
+.ti +0.1i
+input integer q_id; // unique number to identify queue
+.br
+.ti +0.1i
+input integer q_stat_code; // what to return in q_stat_value
+.br
+.ti +0.1i
+output integer q_stat_value;// returned value selected by q_stat_code  
+.br
+.ti +0.1i
+output integer status; // completion status
+.br
+$q_initialize
+.br
+.ti +0.1i
+input integer q_id; // unique number to identify queue
+.br
+.ti +0.1i
+input integer q_type; // type, 1=fifo, 2=lifo 
+.br
+.ti +0.1i
+input max_length; // maximum number of elements allowed in queue
+.br
+.ti +0.1i
+output integer status; // completion status
+.br
+$q_remove;
+.br
+.ti +0.1i
+input integer q_id; // unique number to identify queue
+.br
+.ti +0.1i
+input integer job_id; // unique number to identify job
+.br
+.ti +0.1i
+input integer inform_id; // user defined value removed from queue
+.br
+.ti +0.1i
+output integer status; // completion status
+.br
+function [31:0] $q_full;
+.br
+.ti +0.1i
+input integer q_id; // unique number to identify queue
+.br
+.ti +0.1i
+output integer status; // completion status
+.SH DESCRIPTION
+In combination with stochastic random distribution (deviate) generators,
+these routines provide routines to model statistical queue for driving designs.
+Use the PLI routines for queues that must contain values more complicated
+that 32 bit integers (or regs).
+.PP
+for $q_exam, the possible request types are: 1=current queue length,
+2=mean inter-arrival time, 3=maximum queue length, 4=shortest wait time
+ever, 5=longest wait time for jobs still in queue, and 6=average wait time
+in the queue.  Any queue routine may set the status output parameter to:
+1=OK, 2=queue full, cannot add, 3=undefined q_id, 4=unsupported queue type,
+cannot create queue, 5=specified length <=0, cannot create, 
+6=duplicate q_id, cannot create, not enough memory, cannot create.
+.SH "REFERENCE"
+Defined in P1364 LRM section 14.7.
+.LN
+.SH NAME
+$random \- generate signed random 32 bit value
+.SH SYNOPSIS
+function integer $random; 
+.br
+.ti +0.1i
+inout [31:0] seed;
+.ti +0.1i
+integer seed;
+.SH DESCRIPTION
+Cver uses good BSD random number generator that produces values
+with almost 32 pseudo random bits, but the sequence of generated
+number will probably not match the one returned by other simulators.
+If the the optional seed variable lvalue is given, the starting location
+in the 2**32 (almost) element sequence of pseudo random values is altered.
+Because the random generator only used 32 bit arithmetic the low
+bit is unrandom.
+.SH REFERENCE
+See P1364 LRM section 14.10.1.
+.LN
+.SH NAME
+$readmemb \- read binary number from memory stored in file
+.br
+$readmemh \- read hex number from memory stored in file
+.br
+$sreadmemb \- read binary number from memory stored in string
+.br
+$sreadmemh \- read hex number from memory stored in string
+.SH SYNOPSIS
+$readmemb([file name], [memory name], [start_addr], [finish_addr]);
+.br
+$readmemh([file name], [memory name], [start_addr], [finish_addr]);
+.br
+$sreadmemb([memory name], [start_address], [finish_addr], [list of strings]);
+.br
+sreadmemb([memory name], [start_address], [finish_addr], [list of strings]);
+.SH DESCRIPTION
+These system tasks read values from either a file or a string (the
+$smemread[bh] routines).  The format of the file or string, from which to
+the memory is filled, is a list of white space separated values.  The
+values can contain digits, '_', x and z but no width specification.
+For $readmemb and $sreadmemb the values must be binary.  For $readmemh
+and $sreadmemh, the values must be hex.
+.PP
+The basic memory filling algorithm is to read a word from the file or string,
+fill the current memory location, then increment the memory counter 
+(decrement if [start_addr] is larger than [finish_addr]). 
+The special value @[hexadecimal number] in the file or string
+changes the next address to write the memory data word into. 
+If @[value] form changes to an address outside the range, memory
+filling stops.
+Memory address outside the range or outside the number of elements in
+the file or string are not changed.
+For $smemread routines, a list of strings is legal.  The arguments may
+be arbitrary run time expressions that are converted to strings.  The
+list of strings is concatenated into one long string and read exactly
+as if a file read of the string happened.  The list of strings is required
+because Verilog does not allow strings to span line boundaries.
+.PP
+For $readmemb and $readmemh the [file] as a string (possibly an expression
+that is converted to a string) and the memory identifier are required.
+For $sreadmemb and $sreadmemh the memory identifier and at least one string
+are required.  The [start_addr] and [finish_addr] are optional (must be
+indicated by ,, for $sreadmem functions) and give the first address in
+the memory to use to write the first data word from the file or string into.
+If the [finish_addr] is present, when that memory address is reached, filling
+of the memory is stopped.  It is legal for [start_address] to be larger than
+[finish_addr] in which case the memory if filled from high to low word.
+If only [start_address] is given, [finish_addr] is the last (second)
+memory declaration range.  If only [finish_addr] is given, [start_addr]
+is the start (first) memory declaration range.
+.SH "REFERENCE"
+See P1364 LRM sections and 14.2.3 and F.13.
+.LN
+.SH NAME
+$reset \- reset time to 0 and restart the simulation
+.br
+$reset_value \- returns value passed by most recent call of $reset
+.br
+$reset_count \- returns the number of times $reset has been executed
+.SH SYNOPSIS
+$reset([stop_value], [reset_value], [diagnostics_value]); 
+.br
+function integer $reset_value;
+.br
+function integer $reset_count;
+.SH DESCRIPTION
+$reset allows rerunning a simulation from time 0 without re-translating
+a model.  It can have up to 3 optional arguments.  If [stop_value] is   
+omitted or value 0, interactive mode is entered after reset.  If [reset_value]
+is present, it is preserved across the reset and can be read with the
+the #reset_value system function after completing the reset. The optional
+[diagnostic value] argument determines the amount of diagnostic information
+printed after reset but prior to starting again at time 0.  Value 0 causes
+no information to be emitted, 1 some information, and 2 is equivalent to
+the +verbose option.  The $reset_count system function returns the number
+of times the $reset system task has been executed during the current run.
+.PP
+Cver also supports the :reset [option stop] added command debugger.
+It does not effect either the [reset_value] or the number of times
+$reset has been called so models that rely on $reset values can be debugged.
+In Cver, all : added debugger setting are preserved except break
+points and display expressions are disabled but not removed.
+Either type of reset removes all quasi-continuous forces and assigns.
+If a simulation is started with -s and -i [file], $reset will cause
+simulation to start over in interactive mode running the first command
+in [file].  Cver will never stop unless $reset_count is checked and
+used to cause end of simulation.
+.SH REFERENCE
+See P1364 LRM section F.7.
+.SH "SEE ALSO"
+See debugger online help for :reset added debugger command.
+.LN
+.SH NAME (NOT YET IMPLEMENTED)
+$save \- save state of simulation to a file for later restart
+.br
+$incsave \- save only changed values from last $save to a file
+.br
+$restart \- restart simulation from a $save file
+.SH SYNOPSIS
+$save([file]);
+.br
+$incsave([file]);
+.br
+$restart([file]);
+.SH DESCRIPTION
+Cver does not yet support simulation check pointing that is needed for long
+simulations especially in cases where power or hardware failures occur.
+Cver design translation from source is fast enough that at least
+so far loading the binary data structure does not reduce load time.
+$incsave will probably not be supported since Cver already packs to the
+bit in order to support it, extra simulation event are needed.
+.SH REFERENCE
+See P1364 LRM section F.7.
+.LN
+.SH NAME
+$scale \- convert a time value from one module's time scale to another as real
+.SH SYNOPSIS
+function real $scale;
+.br
+.ti +0.1i
+input [time hierarchical value as either real or reg];
+.SH DESCRIPTION
+Given a time value as an hierarchical reference, convert to the time scale
+in which the $scale system task is executed.  Usage: r = $scale(top.i1.i2.t1);
+.SH REFERENCE
+See P1364 LRM section F.7.
+.LN
+.SH NAME
+$scope \- change scope for use by interactive commands
+.SH SYNOPSIS
+$scope([hierarchal name]);
+.SH DESCRIPTION
+Use scope to change interactive scope from the default first top module
+for use after entering the interactive debugger.  $scope is not very
+useful in Cver because, unless turned off by a debugger :set command,
+upon debugger entry (by $stop or interrupt) the interactive scope is
+set to the entering simulation scope.  Also Cver supports an extended
+:scope command that allow relative movement between scopes and general
+reference for new scopes such as line numbers.
+.SH REFERENCE
+See P1364 LRM section F.7.
+.SH "SEE ALSO"
+See the added debugger ":help :scope" help screen.
+.LN
+.SH NAME
+$sdf_annotate \- XL compatible sdf annotation system task
+.SH SYNPOSIS
+$sdf_annotate([required name of sdf file], [optional annotation scope],
+[optional ignored - no config files yet],
+[optional ignored - no separate sdf log file],
+[optional mintypmax SDF override], [optional ignored - no scale factor], 
+[optional ignored - no scale type]); 
+.SH DESCRIPTION
+System function alternative to +sdf_annotate command line option.
+Function identical to XL $sdf_annotate system task so Verilog source that
+in XL can be run without change in Cver.  $sdf_annotate system task  
+also allows conditional choice of sdf annotation file.
+Third optional configuration file argument is ignored because Configurations
+are not yet supported in Cver.  Optional fourth argument name of separate log
+file is ignored because Cver writes all sdf messages to normal log file.
+Sdf annotation has also been changed to match XL so simulation continues
+even if SDF contains errors.  As much annotation as possible is made if
+SDF contains errors.  Fourth optional mintypmax override argument is supported.
+Legal values are one of MINIMUM, TYPICAL, or MAXIMUM.  Optional sixth
+scale factor and seventh scale factor type arguments are ignored.
+Extra scaling of SDF values in Cver is not supported.
+.SH REFERENCE
+De facto standardized routine.  See document for any of the other
+Verilog simulators such as XL.
+.LN
+.SH NAME
+$showallinstances
+.SH SYNOPSIS
+$showallinstances;
+.SH DESCRIPTION
+For every module in design, print its instance and gate usage in tabular
+form.  This system tasks prints at run time the instance design statistics
+table printed by the +printstats command argument.
+.SH REFERENCE
+Not in P1364 LRM but commonly part of interactive environments. 
+.LN
+.LN
+.SH NAME
+$showscopes \- display list of all scopes inside the current scope
+.SH SYNOPSIS
+$showscopes([value]);
+.SH DESCRIPTION
+List all scope objects in current scope.
+If invoked from interactive mode,
+the scope is the current interactive scope. 
+If called during simulation, scope is current simulation scope.
+If value is present and non zero, print all scopes in or below the
+current scope to be output to stdout and the log file.
+.SH REFERENCE
+See P1364 LRM section F.11.
+.LN
+.SH NAME
+$showvars \- show information about variables
+.br
+$showvariables \- alternative name for $showvars task 
+.SH SYNOPSIS
+$showvars([optional list of variables]);
+.SH DESCRIPTION
+Display information about variables.  If no argument is given, display
+information about all variables in current scope.  If a list of variables
+is given display information about each variable.  Hierarchical references
+are allowed.  Cver's added interactive debugger supports additional commands
+for examining variable values and information.  Use the :help data debugger
+command for more information.
+.SH REFERENCE
+See P1364 LRM section F.12.
+.SH "SEE ALSO"
+See :print, :whatis, :expris, :varis added debugger commands.
+.LN
+.SH NAME (CVER EXTENSION)
+$snapshot \- display active procedural thread tree and pending events
+.SH SYNOPSIS
+$snapshot;
+.SH DESCRIPTION
+Mechanism to print a snapshot of procedural
+location, pending events and thread execution status.
+If interactive debugger is disabled interrupt (^c)
+causes $snapshot to be called.
+Most information also generated by :where added debugger command.
+If you think some tasks or initial/always blocks should be
+active but they are not, or you think they should have completed but
+they have not, put $snapshot in your source or invoke from interactive
+mode to see the procedural active tree.
+.SH REFERENCE
+Not in P1364 LRM. 
+.LN
+.SH NAME
+$stop \- enter interactive debugger
+.SH SYNOPSIS
+$stop;
+.br
+$stop([message level]);
+.SH DESCRIPTION
+Enter interactive debugger and if [message level] is 1 or 2,
+print a message.  1 prints simulation time and 2 prints +verbose  
+simulation statistics.  Interactive debugger can also be entered by
+pressing interrupt key (usually ^c) or from the -s option.
+.SH REFERENCE
+Defined in P1364 LRM section 14.4.2.
+.LN
+.SH NAME
+$strobe, $strobeb, $strobeh, $strobeo \- write formatted value to terminal at end of time slot
+.SH SYNOPSIS
+$strobe([intermixed list of format strings and expressions]);
+.br
+$strobe[bho]([intermixed list of format strings and expressions]);
+.SH DESCRIPTION
+Same as $display but formats and writes value at the end of time
+time slot rather than when the $strobe statement is executed. 
+Format is identical to $display and [bho] suffix letter changes
+default for expression that appears outside of any format as with $display.
+One format is written to stdout and log file for every $strobe executed during
+the time slot.
+.SH REFERENCE
+Defined in P1364 LRM section 14.2.
+.SH "SEE ALSO"
+$fstrobe is same except writes to multi-channel file(s).
+.LN
+.SH NAME
+$suppress_warns
+.br
+$allow_warns
+.SH SYNOPSIS
+$suppress_warns([comma separated list of warning or inform numbers]);
+.br
+$allow_warns([comma separated list of warning or inform numbers]);
+.SH DESCRIPTION
+It is possible to suppress writing of run time warning and inform messages
+by calling the $suppress_warns system task with a list of numbers that
+are printed when a warning or inform message is printed. 
+Messages of class ERROR and FATAL ERROR can not be suppressed.
+The +suppress_warns+[list of + separated numbers] command line option
+also suppresses printing of messages and is the only way to suppers.
+translation time messages.  $allow_warns re-enables printing of run
+time messages.
+.SH "REFERENCE"
+These system tasks are a Cver extension.
+.SH "SEE ALSO"
+See +suppress_warns+[num]+[num]+... option. 
+.LN
+.SH NAME
+$system \- execute operating system command from within Cver
+.SH SYNOPSIS
+$system([OS command line]);
+.SH DESCRIPTION
+Execute some operating system command string by means of a shell escape.
+$system; with no arguments or an empty argument runs an interactive shell
+if one is supported for the system you are running Cver on.
+The semantics of this task is slightly different on Unix based and non
+Unix systems.
+If you are running with multiple shell windows, it is better to execute
+commands in another window because a core dump will probably also cause
+Cver to core dump.
+.SH REFERENCE
+Not defined in P1364 LRM but commonly implemented.
+.LN
+.SH NAME
+$test$plusargs \- test Cver for existence of command argument
+.br
+$scan$plusargs \- scan Cver command arguments to match prefix 
+.SH SYNOPSIS
+function [31:0] $test$plusargs([string]); 
+.br
+function $scan$plusargs([plus option prefix as string], [string lvalue]);
+.SH DESCRIPTION
+$test$plusargs returns 1 if the argument appeared in the Cver command
+invocation argument list.
+The string expression argument must not include the leading + and must
+match an entire argument.  Only Cver command arguments that begin with +
+are checked for a match.
+.P
+The $scan$plusargs system function is equivalent
+to PLI tf_ mc_scan_plusargs function.
+The first argument is plus option (without +) prefix as string expression.
+Second argument is lvalue expression that is assigned the remainder
+of the string to the right of the matched prefix.
+Returns 1 if match and assign tail, 0 if no match and no assign.  
+In -f files, tokenization is by white space only so file=xx is legal,
+but depending on your shell the option
+may need to be quoted if given on the command line.
+Standard $test$plusargs supported and return
+1 if entire string matches (no leading +) else 0.
+.SH REFERENCE
+Not defined in P1364 LRM. $test$plusargs is commonly implemented.
+$scan$plusargs allows use of PLI tf_ mc_scan_plusargs without linking
+in the PLI.
+.LN
+.SH NAME
+$time \- return time scaled to module as 64 bit time value
+.br
+$realtime  \- return time scaled scaled to module as real 
+.br
+$stime \- return time scaled to module as 32 bit value
+.br
+$tickstime \- return time in internal simulation ticks as 64 bit value
+.br
+$stickstime \- return time in internal simulation ticks as 32 bit value
+.SH SYNOPSIS
+function time $time;
+.br
+function real $realtime;
+.br
+function [31:0] $stime;
+.br
+function time $tickstime;
+.br
+function [31:0] $stickstime;
+.SH DESCRIPTION
+$time returns current time as 64 bit unsigned time value.
+It is scaled to time units of the module the $time task is invoked from.
+$realtime is the same as $time except the value
+returned is real and the $timeformat scale values
+are used to determine real value fraction accuracy.
+$stime is the same as $time except value is truncated to 32 bits.
+$tickstime returns current time in internal simulation ticks
+(smallest module time scale in design) in a 64 bit value.
+$stickstime is the same as $tickstime
+except it is truncated to fit in 32 bits.
+Simulation ticks are the minimum time scale unit in
+any module and is the value used internally during simulation.
+.SH REFERENCE
+Defined in P1364 LRM section 14.8.
+$tickstime and $stickstime are Cver extensions.
+.LN
+.SH NAME
+$printtimescale \- display time unit and precision for a module
+.br
+$timeformat \- specify format for the %t $display format specifier
+.SH SYNOPSIS
+$printtimescale([hierarchical_name]);
+.br
+$timeformat([units_number], [precision number], [suffix_string], [minimum_field_width]);
+.SH DESCRIPTION
+The $printtimescale system task displays
+time unit and precision for a particular module.
+If the argument is omitted,
+the information for the current module is printed.
+.PP
+The $timeformat system task sets the format for the %t format specifier.
+.SH REFERENCE
+See P1364 LRM section 14.3 and the `timescale directive discussion 
+section 16.7.
+.LN
+.SH "TRADEMARKS AND COPYRIGHT"
+Verilog is a Trademark of Cadence Design Systems Licensed to
+Open Verilog International.
+.br
+Cver and Vcmp are Trademarks of Pragmatic C Software Corporation.
+.sp
+Copyright (c) 1991-2002 Pragmatic C Software.  All Rights Reserved.
+.br
+This document contains confidential and proprietary information
+.br
+belonging to Pragmatic C Software Corp.
diff --git a/doc/systasks.pdf b/doc/systasks.pdf
new file mode 100644
index 0000000..e3e875c
Binary files /dev/null and b/doc/systasks.pdf differ
diff --git a/doc/systasks.ps b/doc/systasks.ps
new file mode 100644
index 0000000..5066887
--- /dev/null
+++ b/doc/systasks.ps
@@ -0,0 +1,2256 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.18.1
+%%CreationDate: Fri Nov 21 11:54:25 2003
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%DocumentSuppliedResources: procset grops 1.18 1
+%%Pages: 18
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.18 1
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/MANUAL{
+statusdict begin/manualfeed true store end
+}bind def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/Fr{
+setrgbcolor fill
+}bind def
+/Fk{
+setcmykcolor fill
+}bind def
+/Fg{
+setgray fill
+}bind def
+/FL/fill load def
+/LW/setlinewidth load def
+/Cr/setrgbcolor load def
+/Ck/setcmykcolor load def
+/Cg/setgray load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL 841.89 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron
+/Zcaron/scaron/zcaron/Ydieresis/trademark/quotesingle/Euro/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Times-Bold at 0 ENC0/Times-Bold RE/Times-Roman at 0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 13
+/Times-Roman at 0 SF<416c6c204376>209.858 84 Q
+<65722053797374656d207461736b7320616e642046756e6374696f6e73>-.195 E/F2
+10.95/Times-Bold at 0 SF<494e5452>72 100.8 Q<4f>-.329 E F0 .341
+<5468657365206d616e20706167657320646f63756d656e742065>108 112.8 R -.15
+<7665>-.25 G .341<72792073797374656d207461736b20616e642073797374656d2066
+756e6374696f6e207265636f676e697a6564206279204376>.15 F .34
+<657220696e636c7564696e672074686f7365206e6f74>-.15 F 3.973
+<696d706c656d656e7465642e2053797374656d>108 124.8 R 1.473
+<7461736b7320616e642066756e6374696f6e7320617265206d6978>3.973 F 1.473<65
+6420746f67657468657220616e642061707065617220696e20616c706861626574696361
+6c206f72646572>-.15 F 6.474<2e53>-.55 G<696d696c6172>-6.474 E .395<7461
+736b7320616e642073797374656d2066756e6374696f6e732061726520696e7465726d69
+78>108 136.8 R 2.894<65642e2046756e6374696f6e616c6c79>-.15 F .394<73696d
+696c6172207461736b7320616e642066756e6374696f6e732061726520636f6d62696e65
+6420696e746f206f6e65>2.894 F<73656374696f6e20616e6420616c70686162657469
+7a6564206163636f7264696e6720746f206d61696e207461736b206f722066756e637469
+6f6e2e>108 148.8 Q -.15<466f>108 165.6 S 3.223<7273>.15 G .723<79737465
+6d2066756e6374696f6e732c207468652053594e4f505349532073656374696f6e20636f
+6e7461696e73206e6f726d616c20757365722066756e6374696f6e206465636c61726174
+696f6e206e6f746174696f6e20746f2064658c6e65>-3.223 F .228
+<72657475726e207479706520616e64206172>108 177.6 R .228
+<67756d656e7420747970652065>-.18 F -.15<7665>-.25 G 2.728<6e74>.15 G
+.228<686f7567682073797374656d2066756e6374696f6e7320617265206e65>-2.728 F
+-.15<7665>-.25 G 2.727<7272>.15 G .227<65616c6c79206465636c617265642e>
+-2.727 F .227<5468657265206973206e6f20636f6e63657074>5.227 F .407
+<6f662073657061726174652066756e6374696f6e2068656164657220696e2056>108
+189.6 R 2.907<6572696c6f672e20496e>-1.11 F .407<746865205031333634204c52
+4d206d6f73742073797374656d2066756e6374696f6e2061726520696e64696361746564
+2061732072657475726e696e67>2.907 F<696e7465>108 201.6 Q<676572>-.15 E
+2.5<2c62>-.4 G<75742073696e636520746865>-2.7 E 2.5<7972>-.15 G
+<6172656c792063616e2072657475726e2061206e65>-2.5 E -.05<6761>-.15 G
+<7469>.05 E .3 -.15<76652076>-.25 H<616c756520746865>-.1 E 2.5<7972>-.15
+G<65616c6c792072657475726e207265>-2.5 E 2.5<675b>-.15 G<33313a305d2e>
+-2.5 E .773<53797374656d207461736b732061707065617220696e207468652053594e
+4f505349532073656374696f6e207573696e6720746865207461736b20696e>108 218.4
+R -.2<766f>-.4 G .772<636174696f6e20666f726d2028692e652e207461736b206b>
+.2 F -.15<6579>-.1 G -.1<776f>.15 G .772<7264206f6d697474656429>.1 F
+.866<616e6420757375616c6c792077697468206d657461206465736372697074696f6e
+73206f6620706172616d65746572732e>108 230.4 R .866<496e2056>5.866 F .866
+<6572696c6f672073797374656d207461736b732c20756e6c696b>-1.11 F 3.366
+<6575>-.1 G .866<7365722064658c6e6564207461736b732c2063616e>-3.366 F
+<616c>108 242.4 Q -.1<7761>-.1 G .443<79732074616b>.1 F 2.943<656176>-.1
+G .443<61726961626c65206e756d626572206f66206172>-3.193 F .443
+<67756d656e747320616e64206f7074696f6e616c2062>-.18 F .442
+<7574206e6f74207265717569726564206172>-.2 F .442
+<67756d656e74732063616e206265206f6d697474656420656974686572>-.18 F .645
+<7769746820222c2c22206f7220627920656e64696e6720746865206172>108 254.4 R
+.645<67756d656e74206c6973742e>-.18 F .645
+<536f6d652073797374656d2066756e6374696f6e7320616c736f206861>5.645 F .946
+-.15<7665206f>-.2 H .646<7074696f6e616c206172>.15 F .646
+<67756d656e747320746861742063616e206265>-.18 F<6f6d69747465642e>108
+266.4 Q .289<496e2056>108 283.2 R .288
+<6572696c6f6720616c6c20737472696e67732065>-1.11 F .288<7863657074202464
+6973706c6179207479706520666f726d61742073706563698c6572732063616e20626520
+6569746865722065>-.15 F .288
+<787072657373696f6e7320746861742061726520696e746572707265746564206173>
+-.15 F .777
+<737472696e677320286869676820302062697473207472696d6d6564206f66>108
+295.2 R 3.278<6661>-.25 G .778<6e64207468656e20696e74657270726574206561
+6368206279746520617320612063686172616374657229206f72206c69746572616c2073
+7472696e67732028656e636c6f736564206279>-3.278 F
+<646f75626c652071756f746174696f6e206d61726b73292e>108 307.2 Q<416e>5 E
+2.5<795b>-.15 G<8c6c65206e616d655d2063616e206265206569746865722074797065
+206f6620737472696e672e>-2.5 E 1.294<5031333634204c524d2074696d696e672063
+6865636b7320617265206e6f7420646f63756d656e746564206865726520626563617573
+6520746865>108 324 R 3.794<7964>-.15 G 3.794<6f6e>-3.794 G 1.294
+<6f742076>-3.794 F 1.294<617279206265747765656e2073696d756c61746f72732e>
+-.25 F<536565>6.294 E<5031333634204c524d2073656374696f6e2031342e3520666f
+7220646f63756d656e746174696f6e206f662074696d696e6720636865636b732c206564
+676520636f6e74726f6c2073706563698c6572732c20616e64206e6f74698c6572732e>
+108 336 Q<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d>72 360 Q F2 -.219<4e41>72 376.8 S<4d45>.219 E F0
+<2462697473746f7265616c20ad20636f6e>108 388.8 Q -.15<7665>-.4 G
+<727420363420626974207265>.15 E<67697374657220746f207265616c>-.15 E
+<247265616c746f6269747320ad20636f6e>108 400.8 Q -.15<7665>-.4 G
+<7274207265616c20746f20363420626974207265>.15 E<676973746572>-.15 E
+<2469746f7220ad20636f6e>108 412.8 Q -.15<7665>-.4 G<727420696e7465>.15 E
+<67657220746f207265616c>-.15 E<2472746f6920ad20636f6e>108 424.8 Q -.15
+<7665>-.4 G<7274207265616c20746f20696e7465>.15 E
+<67657220627920726f756e64696e67>-.15 E F2<53594e4f50534953>72 441.6 Q F0
+<66756e6374696f6e207265616c202462697473746f7265616c3b>108 453.6 Q
+<696e707574205b36333a305d206269745f76>115.2 465.6 Q<616c3b>-.25 E
+<66756e6374696f6e205b36333a305d20247265616c746f626974733b>108 477.6 Q
+<696e707574207265616c207265616c5f76>115.2 489.6 Q<616c3b>-.25 E
+<66756e6374696f6e207265616c202469746f723b>108 501.6 Q
+<696e70757420696e7465>115.2 513.6 Q<67657220696e745f76>-.15 E<616c3b>
+-.25 E<66756e6374696f6e20696e7465>108 525.6 Q<676572202472746f693b>-.15
+E<696e707574207265616c207265616c5f76>115.2 537.6 Q<616c3b>-.25 E F2
+<4445534352495054494f4e>72 554.4 Q F0 .579
+<53797374656d2066756e6374696f6e7320746f20636f6e>108 566.4 R -.15<7665>
+-.4 G .579<727420746f20616e642066726f6d207265616c732e>.15 F .58<55736520
+247265616c746f6269747320616e64202462697473746f7265616c20746f207061737320
+7265616c73206163726f7373206d6f64756c65>5.579 F 3.454
+<706f7274732e20557365>108 578.4 R .954
+<2469746f7220616e64202472746f6920746f20636f6e>3.454 F -.15<7665>-.4 G
+.954<7274206265747765656e20696e7465>.15 F .954
+<67657220616e64207265616c20627920726f756e64696e672e>-.15 F .953
+<496e2056>5.953 F .953<6572696c6f672c2061737369676e6d656e747320616c736f>
+-1.11 F .877<696d706c696369746c7920636f6e>108 590.4 R -.15<7665>-.4 G
+.877<727420746f206f722066726f6d2061207265616c20646570656e64696e67206f6e
+20746865206c6566742068616e642073696465204c76>.15 F .877
+<616c756520747970652e>-.25 F<4376>5.878 E .878<657220636f6e>-.15 F -.15
+<7665>-.4 G .878<7273696f6e20746f207265616c>.15 F .298
+<66726f6d207769646572207468616e203332206269742076>108 602.4 R .298
+<616c75657320617474656d70747320746f2070726573657276>-.25 F 2.797<6561>
+-.15 G 2.797<736d>-2.797 G<616e>-2.797 E 2.797<7962>-.15 G .297<69747320
+617320706f737369626c652028757375616c6c79203531206f7220353220646570656e64
+696e67206f6e>-2.797 F<6861726477>108 614.4 Q
+<61726520706c6174666f726d292e>-.1 E F2<5245464552454e4345>72 631.2 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e392e>108
+643.2 Q<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d>72 667.2 Q F2 -.219<4e41>72 684 S<4d45>.219 E F0
+<24636c656172747261636520ad207475726e206f66>108 696 Q 2.5<6673>-.25 G
+<746174656d656e742074726163696e67>-2.5 E<24736574747261636520ad20747572
+6e206f6e2073746174656d656e742074726163696e67>108 708 Q<24636c65617265>
+108 720 Q<76747261636520ad207475726e206f66>-.25 E 2.5<6664>-.25 G
+<65636c6172617469>-2.5 E .3 -.15<76652065>-.25 H -.15<7665>-.1 G
+<6e742074726163696e67>.15 E<507261676d61746963204320536f667477>72 768 Q
+120.23<6172652052656c65617365>-.1 F 203.45<322e352031>2.5 F 0 Cg EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R<2473657465>108
+84 Q<76747261636520ad207475726e206f6e206465636c6172617469>-.25 E .3 -.15
+<76652065>-.25 H -.15<7665>-.1 G<6e742074726163696e67>.15 E
+<2474726163658c6c6520ad>108 96 Q<736574207365706172617465206f7574707574
+208c6c6520666f72207472616365206f7574707574>5 E/F1 10.95/Times-Bold at 0 SF
+<53594e4f50534953>72 112.8 Q F0<24636c65617274726163653b>108 124.8 Q
+<2473657474726163653b>108 136.8 Q<24636c65617265>108 148.8 Q
+<7674726163653b>-.25 E<2473657465>108 160.8 Q<7674726163653b>-.25 E
+<2474726163658c6c65285b8c6c65206e616d655d293b>108 172.8 Q F1
+<4445534352495054494f4e>72 189.6 Q F0<4376>108 201.6 Q .691<657220737570
+706f72747320736570617261746520636f6e74726f6c206f662073746174656d656e7420
+616e64206465636c6172617469>-.15 F .991 -.15<76652065>-.25 H -.15<7665>
+-.1 G .692<6e742074726163696e672e>.15 F .692
+<546865206f7074696f6e73202d74207374617274732073696d756c6174696f6e>5.692
+F .682<776974682073746174656d656e742074726163696e67206f6e2e>108 213.6 R
+.682<546865206f7074696f6e206d696e7573202d65742073746172742073696d756c61
+74696f6e20776974682065>5.682 F -.15<7665>-.25 G .682
+<6e742074726163696e67206f6e2e>.15 F .681
+<546865202d74206f7074696f6e20616e64>5.681 F .026<2473657474726163652061
+6e642024636c656172747261636520696e20736f6d65206f746865722073696d756c6174
+6f727320656e61626c6520616e642064697361626c6520626f7468207479706573206f66
+2074726163696e672e>108 225.6 R 1.626 -.8<546f2061>5.026 H
+<7070726f78696d617465>.8 E<66756c6c2074726163696e6720696e206f7468657220
+73696d756c61746f72732075736520626f7468202d7420616e64202d6574206f7074696f
+6e73206f722063616c6c20626f74682024736574747261636520616e64202473657465>
+108 237.6 Q<7674726163652e>-.25 E .574<546865202474726163658c6c65207379
+7374656d207461736b2073657420746865206f7574707574208c6c6520666f7220747261
+63696e672028626f74682074797065732920746f205b8c6c655d2e>108 254.4 R .573
+<546865202474726163658c6c65206172>5.573 F .573<67756d656e742063616e>-.18
+F .4<626520612076>108 266.4 R .401<61726961626c652074686174206973207472
+6561746564206173206120737472696e6720776974682068696768203020626974732072
+656d6f>-.25 F -.15<7665>-.15 G 2.901<642e20416e>.15 F
+<616c7465726e617469>2.901 E .701 -.15<76652077>-.25 H .401
+<617920746f207365742061207365706172617465207472616365>.05 F .239<6f7574
+707574208c6c65206973207769746820746865202b74726163658c6c65205b8c6c655d20
+636f6d6d616e64206c696e65206f7074696f6e2e>108 278.4 R<4578>5.239 E .238
+<65637574696e67202474726163658c6c65207265706c6163657320616e>-.15 F 2.738
+<792b>-.15 G .238<74726163658c6c6520736574>-2.738 F 2.846
+<8c6c652e204966>108 290.4 R .346<2474726163658c6c65206973206e6f74207573
+65642c207472616365206f7574707574206973207772697474656e20746f205354444f55
+5420616e6420746865206c6f67208c6c65202869662069742065>2.846 F 2.846
+<7869737473292e20546865>-.15 F<74726163658c6c65>2.846 E .019<63616e2062
+652074686520737472696e6720227374646f757422207468617420686173207468652065
+66>108 302.4 R .018<66656374206f6620726573746f72696e67207472616365206f75
+7470757420746f20646566>-.25 F .018
+<61756c74205354444f555420616e6420746865206c6f67208c6c652e>-.1 F<4966>
+5.018 E 2.5<6174>108 314.4 S<72616365208c6c65206973207365742c2074726163
+65206f7574707574206973206e6f74207772697474656e20746f207374646f75742e>
+-2.5 E F1<5245464552454e4345>72 331.2 Q F0 .187<54686573652073797374656d
+207461736b7320617265206e6f74206d656e74696f6e656420696e207468652050313336
+34204c524d206265636175736520746865>108 343.2 R 2.688<7961>-.15 G .188
+<70706c7920746f2074686520696e74657261637469>-2.688 F .488 -.15<76652065>
+-.25 H -.4<6e76>.15 G<69726f6e6d656e74>.4 E
+<6e6f742061646472657373656420627920746865207374616e646172642e>108 355.2
+Q<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d>72 379.2 Q F1 -.219<4e41>72 396 S<4d45>.219 E F0
+<24636f7320ad20636f6d7075746520636f73696e65206f66207265616c20696e707574>
+108 408 Q
+<2473696e20ad20636f6d707574652073696e206f66207265616c20696e707574>108
+420 Q<2474616e20ad20636f6d707574652074616e67656e74206f66207265616c20696e
+707574>108 432 Q<2461636f7320ad20636f6d707574652061726320636f73696e6520
+6f66207265616c20696e707574>108 444 Q<246173696e20ad20636f6d707574652061
+72632073696e206f66207265616c20696e707574>108 456 Q<246174616e20ad20636f
+6d70757465206172632074616e67656e74206f66207265616c20696e707574>108 468 Q
+<2461636f736820ad20636f6d707574652068>108 480 Q
+<79706572626f6c69632061726320636f73696e65206f66207265616c20696e707574>
+-.05 E<246173696e6820ad20636f6d707574652068>108 492 Q
+<79706572626f6c6963206172632073696e65206f66207265616c20696e707574>-.05 E
+<246174616e6820ad20636f6d707574652068>108 504 Q
+<79706572626f6c6963206172632074616e67656e74206f66207265616c20696e707574>
+-.05 E<2473676e20ad20636f6d70757465207369676e206f66207265616c20696e7075
+74202872657475726e7320696e7465>108 516 Q<67657229>-.15 E
+<24696e7420ad20636f6e>108 528 Q -.15<7665>-.4 G
+<7274207265616c20696e70757420746f2033322062697420696e7465>.15 E
+<6765722028757365732043206e6f742056>-.15 E<6572696c6f6720636f6e>-1.11 E
+-.15<7665>-.4 G<7273696f6e29>.15 E
+<246c6e20ad20636f6d70757465206e6174757265206c6f67>108 540 Q
+<61726974686d206f66207265616c20696e707574>-.05 E
+<246c6f67313020ad20636f6d707574652062617365203130206c6f67>108 552 Q
+<61726974686d206f66207265616c20696e707574>-.05 E
+<2461627320ad20636f6d70757465206162736f6c7574652076>108 564 Q
+<616c7565206f66207265616c20696e707574>-.25 E<24706f>108 576 Q 2.5
+<77ad63>-.25 G<6f6d707574652065>-2.5 E<78706f6e656e74206f66208c72737420
+7265616c20696e70757420746f207365636f6e64207265616c206172>-.15 E
+<67756d656e7420706f>-.18 E<776572>-.25 E<247371727420ad20636f6d70757465
+2073717561726520726f6f74207265616c20696e707574>108 588 Q<2465>108 600 Q
+<787020ad20636f6d7075746520652072616973656420746f20706f>-.15 E
+<776572206f66207265616c20696e707574>-.25 E<246d696e20ad20636f6d70757465
+206d696e696d756d206f662032207265616c20696e70757473>108 612 Q<246d696e20
+ad20636f6d70757465206d6178696d756d206f662032207265616c20696e70757473>108
+624 Q F1<53594e4f50534953>72 640.8 Q F0<53797374656d2066756e6374696f6e20
+6964656e746963616c20746f2049454545206d6174682066756e6374696f6e732065>
+110.5 652.8 Q<786365707420666f722061646465642024207072658c78>-.15 E F1
+<4445534352495054494f4e>72 669.6 Q F0 .476
+<54686973206973206e6f6e206469676974616c205031333634204376>108 681.6 R
+.476<657220656e68616e63656d656e7420746861742069732061>-.15 F -.25<7661>
+-.2 G .475<696c61626c6520696e206469676974616c204376>.25 F .475
+<6572206265636175736520697420697320726571756972656420666f722056>-.15 F
+<6572>-1.11 E<2d>-.2 E .498<696c6f672d414d532076>108 693.6 R .498
+<657273696f6e206f66204376>-.15 F<6572>-.15 E 5.498<2e46>-.55 G .498
+<756e6374696f6e73206172652064658c6e656420696e2056>-5.498 F .498
+<6572696c6f672d414d5320322e30204f>-1.11 F .498<5649204c524d2e>-.5 F
+<42656861>5.498 E .498<76696f72206973206964656e746963616c20746f>-.2 F
+<62656861>108 705.6 Q<76696f7220646f63756d656e74656420627920556e6978206d
+6174682066756e6374696f6e206d616e2070616765732e>-.2 E<4376>108 722.4 Q
+1.429<657220616c736f20616c6c6f>-.15 F 1.429<777320757365206f662073797374
+656d2066756e6374696f6e73207769746820636f6e7374616e74206172>-.25 F 1.428
+<67756d656e747320696e20636f6e7374616e742065>-.18 F 1.428
+<787072657373696f6e7320736f20706172616d65746572>-.15 F
+<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 203.45<322e352032>2.5 F 0 Cg EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R .632<64658c6e69
+74696f6e7320737563682061732022706172616d6574657220636f7332203d2024636f73
+28322e30293b2220617265206c65>108 84 R -.05<6761>-.15 G 3.133<6c69>.05 G
+3.133<6e43>-3.133 G -.15<7665>-3.133 G 3.133<7261>.15 G .633
+<6e64206172652070617274206f66206e65>-3.133 F 3.133<7756>-.25 G .633
+<6572696c6f672032303031207374616e2d>-4.243 F 2.5<646172642e204376>108 96
+R
+<657220646f6573206e6f742079657420737570706f727420636f6e7374616e74206172>
+-.15 E
+<67756d656e7420757365722066756e6374696f6e7320696e20636f6e7374616e742065>
+-.18 E<787072657373696f6e732e>-.15 E .136<54686520666f6c6c6f>108 112.8 R
+.136<77696e6720487370696365206d617468206c6962726172792076>-.25 F .136<61
+7269616e74732061726520616c736f20737570706f727465643a202468737172742c2024
+68706f>-.25 F 1.435 -.65<772c2024>-.25 H<68707772>.65 E 2.635<2c24>-.4 G
+.135<686c6f672c2024686c6f67313020246864622c>-2.635 F
+<616e642024687369676e2e>108 124.8 Q
+<5365652048737069636520646f63756d656e746174696f6e20666f722062656861>5 E
+<76696f7220616e64207265717569726564206172>-.2 E<67756d656e74732e>-.18 E
+/F1 10.95/Times-Bold at 0 SF<5245464552454e4345>72 141.6 Q F0 .186
+<5365652056>108 153.6 R .187<6572696c6f672d414d5320322e30204f>-1.11 F
+.187<5649207374616e64617264204c524d2e>-.5 F .187
+<5374616e646172642049454545206d6174682066756e6374696f6e732e>5.187 F .187
+<53656520616e>5.187 F 2.687<7948>-.15 G .187
+<737069636520646f63756d656e746174696f6e2e>-2.687 F<2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72
+177.6 Q F1 -.219<4e41>72 194.4 S<4d45>.219 E F0<24636f756e74647269>108
+206.4 Q -.15<7665>-.25 G<727320ad2072657475726e20312069662062>.15 E<7573
+20636f6e74656e74696f6e2062656361757365206d6f7265207468616e206f6e65206472
+69>-.2 E -.15<7665>-.25 G<72>.15 E F1<53594e4f50534953>72 223.2 Q F0
+<66756e6374696f6e205b33313a305d2024636f756e74647269>108 235.2 Q -.15
+<7665>-.25 G<72733b>.15 E<2f2f206d7573742062652077697265>115.2 247.2 Q
+<696e707574206e65743b>115.2 259.2 Q
+<6f7574707574205b33313a305d206e65745f69735f666f726365643b>115.2 271.2 Q
+<6f7574707574205b33313a305d206e756d6265725f6f665f3031785f647269>115.2
+283.2 Q -.15<7665>-.25 G<72733b>.15 E
+<6f7574707574205b33313a305d206e756d6265725f6f665f305f647269>115.2 295.2
+Q -.15<7665>-.25 G<72733b>.15 E
+<6f7574707574205b33313a305d206e756d6265725f6f665f315f647269>115.2 307.2
+Q -.15<7665>-.25 G<72733b>.15 E
+<6f7574707574205b33313a305d206e756d6265725f6f665f785f647269>115.2 319.2
+Q -.15<7665>-.25 G<72733b>.15 E F1<4445534352495054494f4e>72 336 Q F0
+.612<53797374656d2066756e6374696f6e2072657475726e2030206966207468657265
+206973206e6f206d6f7265207468616e206f6e6520647269>108 348 R -.15<7665>
+-.25 G 3.112<7228>.15 G .612<616c6c20776972652066>-3.112 F .612<616e2d69
+6e206973207472692d7374617465642028696e2068695a20737461746529206f722061>
+-.1 F .246<6d6f7374206f6e652066>108 360 R .246<616e2d696e20776972652028
+6f722073656c656374206f66207769726529206973206e6f6e207472692d737461746564
+292e>-.1 F .247<52657475726e732031206966207468657265206973206d6f72652074
+68616e206f6e65206e6f6e2d7472692d737461746564>5.246 F -.1<6661>108 372 S
+2.713<6e2d696e2e20546865>.1 F .213<8c727374206e6574206172>2.713 F .213
+<67756d656e742069732072657175697265642e>-.18 F .213
+<49662061207365636f6e64206172>5.213 F .213<67756d656e74206973206769>-.18
+F -.15<7665>-.25 G .212<6e2c206974206d7573742062652061207265>.15 F 2.712
+<676c>-.15 G -.25<7661>-2.712 G .212<6c75652065>.25 F
+<787072657373696f6e>-.15 E .632<746861742069732073657420746f207468652074
+6f74616c206e756d626572206f662066>108 384 R .632<616e2d696e20616e>-.1 F
+3.132<7973>-.15 G .632<74617465206f74686572207468616e2068695a2e>-3.132 F
+.632<49662061207468697264206172>5.632 F .632<67756d656e74206973206769>
+-.18 F -.15<7665>-.25 G .633<6e2c206974206d7573742062652061>.15 F<7265>
+108 396 Q 2.888<676c>-.15 G -.25<7661>-2.888 G .388<6c75652065>.25 F
+.387<787072657373696f6e20746861742069732073657420746f2074686520746f7461
+6c206e756d626572206f662066>-.15 F .387<616e2d696e207468617420647269>-.1
+F -.15<7665>-.25 G 2.887<7330>.15 G 5.387<2e49>-2.887 G 2.887<666166>
+-5.387 G .387<6f75727468206172>-2.887 F .387<67756d656e74206973206769>
+-.18 F -.15<7665>-.25 G .387<6e2c206974>.15 F .452
+<6d7573742062652061207265>108 408 R 2.952<676c>-.15 G -.25<7661>-2.952 G
+.452<6c75652065>.25 F .452<787072657373696f6e20746861742069732073657420
+746f2074686520746f74616c206e756d626572206f662066>-.15 F .452
+<616e2d696e207468617420647269>-.1 F -.15<7665>-.25 G 2.953<7331>.15 G
+5.453<2e49>-2.953 G 2.953<66618c>-5.453 G .453<667468206172>-2.953 F
+.453<67756d656e74206973>-.18 F<6769>108 420 Q -.15<7665>-.25 G .686
+<6e2c206974206d7573742062652061207265>.15 F 3.186<676c>-.15 G -.25<7661>
+-3.186 G .686<6c75652065>.25 F .685<787072657373696f6e207468617420697320
+73657420746f2074686520746f74616c206e756d626572206f662066>-.15 F .685
+<616e2d696e207468617420647269>-.1 F -.15<7665>-.25 G 3.185<7378>.15 G
+5.685<2e49>-3.185 G 3.185<6661>-5.685 G 3.185<6e61>-3.185 G -.18<7267>
+-3.185 G<752d>.18 E .34<6d656e74206973206f6d69747465642c2062>108 432 R
+.34<757420616e206172>-.2 F .341<67756d656e7420746f2069747320726967687420
+6973206e65656465642c2075736520222c2c222e>-.18 F .341
+<4e6f7469636520612073746174656d656e743a>5.341 F<22616c>5.341 E -.1<7761>
+-.1 G .341<7973204077206e756d647269>.1 F<76>-.25 E 4.419<3d24>108 444 S
+<636f756e74647269>-4.419 E -.15<7665>-.25 G 1.919
+<72732877293b2220646f6573206e6f742077>.15 F 1.919
+<6f726b2073696e636520746865206e756d626572206f6620647269>-.1 F -.15<7665>
+-.25 G 1.918
+<7273206d6179206368616e676520776974686f757420746865207769726527>.15 F
+4.418<7376>-.55 G<616c7565>-4.668 E .448<6368616e67696e6720657370656369
+616c6c7920666f7220737472656e6774682077697265732e>108 456 R .449
+<4e6f74696365207468617420696e20746865204c524d2c20647269>5.448 F -.15
+<7665>-.25 G 2.949<7275>.15 G .449
+<7375616c6c79206d65616e73206e6f6e207472692d7374617465642066>-2.949 F
+<616e2d696e2e>-.1 E<536f6d6574696d657320647269>108 468 Q -.15<7665>-.25
+G 2.5<726d>.15 G<65616e7320696e737465616420616e>-2.5 E 2.5<7966>-.15 G<
+616e2d696e2077686574686572206f72206e6f74206974206973207472692d7374617465
+642e>-2.6 E F1<5245464552454e4345>72 484.8 Q F0
+<4d656e74696f6e656420696e205031333634204c524d2073656374696f6e2046>108
+496.8 Q<2e312062>-.8 E
+<75742064657461696c65642064658c6e6974696f6e20696e204f>-.2 E
+<5649204c524d2073656374696f6e20422e31302e>-.5 E<2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72 520.8 Q
+F1 -.219<4e41>72 537.6 S<4d45>.219 E F0<24646973706c6179>108 549.6 Q 2.5
+<2c24>-.65 G<646973706c6179622c2024646973706c6179682c2024646973706c6179
+6f20ad20777269746520666f726d61747465642076>-2.5 E
+<616c756520746f207374646f7574>-.25 E<2477726974652c20247772697465622c20
+247772697465682c202477726974656f20ad20777269746520666f726d61747465642076>
+108 561.6 Q<616c756520746f207374646f7574>-.25 E F1<53594e4f50534953>72
+578.4 Q F0<24646973706c6179285b696e7465726d6978>108 590.4 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E
+<24646973706c61795b62686f5d285b696e7465726d6978>108 602.4 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E<247772697465285b696e7465726d6978>108
+614.4 Q<6564206c697374206f6620666f726d617420737472696e677320616e642065>
+-.15 E<787072657373696f6e735d293b>-.15 E
+<2477726974655b62686f5d285b696e7465726d6978>108 626.4 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E F1<4445534352495054494f4e>72 643.2 Q
+F0 .314<577269746520666f726d61747465642076>108 655.2 R .314<616c75657320
+746f207374616e64617264206f75742028616e6420746865206c6f67208c6c65292e>
+-.25 F .313<54686520666f726d61742069732073696d696c617220746f2043206c616e
+6775616765207072696e746620666f726d6174>5.313 F -.15<6578>108 667.2 S
+1.565<636570742074686520666f726d617420737472696e67206d757374206265206c69
+746572616c2c206d6f7265207468616e206f6e6520666f726d617420737472696e672063
+616e2061707065617220666f6c6c6f>.15 F 1.566<7765642062792076>-.25 F 1.566
+<616c75657320746f>-.25 F .054<7265706c61636520666f726d617420726566657265
+6e63657320776974682c206f6e6c79207175616c698c6572206973203020746861742063
+6175736573207472696d6d696e67206f66207468652076>108 679.2 R .053
+<616c756520746f206e6172726f>-.25 F .053
+<77657374208c656c6420706f7373692d>-.25 F 3.041<626c652e20546865>108
+691.2 R .542<256720666f726d617420666f72207265616c73206973206964656e7469
+63616c20746f2043206c616e6775616765207072696e746620256720666f726d61742e>
+3.041 F .542<24646973706c617920616c>5.542 F -.1<7761>-.1 G .542
+<797320617070656e64732061206e65>.1 F<77>-.25 E .031<6c696e6520746f207468
+6520656e64206f662074686520646973706c6179656420737472696e672e>108 703.2 R
+-.15<466f>5.031 G 2.531<7224>.15 G .031<77726974652c20616e>-2.531 F
+2.531<796e>-.15 G .531 -.25<6577206c>-2.531 H .031
+<696e65206d7573742062652065>.25 F .031
+<78706c696369746c79207772697474656e2e>-.15 F .031<427920646566>5.031 F
+.031<61756c742c2076>-.1 F<6172692d>-.25 E .031
+<61626c65207468617420646f206e6f74206d6174636820616e>108 715.2 R 2.531
+<7966>-.15 G .031<6f726d61742073706563698c657220617265207772697474656e20
+696e20646563696d616c2e>-2.531 F .031<5573652024646973706c61796220616e64
+202477726974656220746f206368616e676520746865>5.031 F<646566>108 727.2 Q
+.72<61756c7420746f2062696e617279>-.1 F 3.22<2c24>-.65 G .72
+<646973706c61796820616e64202477726974656820746f206368616e676520646566>
+-3.22 F .719<61756c7420746f206865>-.1 F .719<782c20616e642024646973706c
+61796f20616e64202477726974656f20746f206368616e676520746f>-.15 F
+<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 203.45<322e352033>2.5 F 0 Cg EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R<6f6374616c2e>108
+84 Q/F1 10.95/Times-Bold at 0 SF<5245464552454e4345>72 100.8 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e312e312e>
+108 112.8 Q F1<53454520414c534f>72 129.6 Q F0 .129<5468652073616d652066
+6f726d6174206973207573656420627920746865202466646973706c617920616e642024
+667772697465207461736b7320776869636820777269746520746f208c6c652873292c20
+74686520246d6f6e69746f7220616e642024666d6f6e692d>108 141.6 R .128
+<746f72207461736b732074686174207772697465206368616e6765642065>108 153.6
+R .127<787072657373696f6e732061742074686520656e64206f6620612074696d6520
+736c6f742c20616e6420247374726f626520616e642024667374726f6265207468617420
+616c>-.15 F -.1<7761>-.1 G .127<7973207772697465>.1 F -.25<7661>108
+165.6 S<6c7565206f6620616e2065>.25 E<787072657373696f6e2061742074686520
+656e64206f6620612074696d6520736c6f742e>-.15 E<2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72 189.6 Q F1
+-.219<4e41>72 206.4 S<4d45>.219 E F0<24646973745f6368695f73717561726520
+ad2072657475726e2072616e646f6d203332206269742076>108 218.4 Q
+<616c756520696e20436869205371756172652064697374726962>-.25 E<7574696f6e>
+-.2 E<24646973745f65726c616e6720ad2072657475726e2072616e646f6d2033322062
+69742076>108 230.4 Q<616c756520696e2045726c616e6769616e2064697374726962>
+-.25 E<7574696f6e>-.2 E<24646973745f65>108 242.4 Q
+<78706f6e656e7469616c20ad2072657475726e2072616e646f6d203332206269742076>
+-.15 E<616c756520696e204578706f6e656e7469616c2064697374726962>-.25 E
+<7574696f6e>-.2 E<24646973745f6e6f726d616c20ad2072657475726e2072616e646f
+6d203332206269742076>108 254.4 Q
+<616c756520696e205374616e64617264204e6f726d616c2064697374726962>-.25 E
+<7574696f6e>-.2 E<24646973745f706f6973736f6e20ad2072657475726e2072616e64
+6f6d203332206269742076>108 266.4 Q
+<616c756520696e20506f6973736f6e2064697374726962>-.25 E<7574696f6e>-.2 E
+<24646973745f7420ad2072657475726e2072616e646f6d203332206269742076>108
+278.4 Q<616c756520696e205374616e6461726420542064697374726962>-.25 E
+<7574696f6e>-.2 E<24646973745f756e69666f726d20ad2072657475726e2072616e64
+6f6d203332206269742076>108 290.4 Q
+<616c756520756e69666f726d6c792064697374726962>-.25 E
+<7574656420696e2072616e6765>-.2 E F1<53594e4f50534953>72 307.2 Q F0
+<66756e6374696f6e205b33313a305d2024646973745f6368695f7371756172653b>108
+319.2 Q<696e6f7574205b33313a305d20736565643b>115.2 331.2 Q
+<696e707574205b33313a305d206465>115.2 343.2 Q
+<677265655f6f665f66726565646f6d3b>-.15 E
+<66756e6374696f6e205b33313a305d2024646973745f65726c616e673b>108 355.2 Q
+<696e6f7574205b33313a305d20736565643b>115.2 367.2 Q
+<696e70757420696e7465>115.2 379.2 Q<676572206b5f73746167653b>-.15 E
+<696e70757420696e7465>115.2 391.2 Q<676572206d65616e3b>-.15 E
+<66756e6374696f6e205b33313a305d2024646973745f65>108 403.2 Q
+<78706f6e656e7469616c3b>-.15 E<696e6f7574205b33313a305d20736565643b>
+115.2 415.2 Q<696e70757420696e7465>115.2 427.2 Q<676572206d65616e3b>-.15
+E<66756e6374696f6e205b33313a305d2024646973745f6e6f726d616c3b>108 439.2 Q
+<696e6f7574205b33313a305d20736565643b>115.2 451.2 Q
+<696e70757420696e7465>115.2 463.2 Q<676572206d65616e3b>-.15 E
+<696e70757420696e7465>115.2 475.2 Q<676572207374616e646172645f6465>-.15
+E<76696174696f6e3b>-.25 E
+<66756e6374696f6e205b33313a305d2024646973745f706f6973736f6e3b>108 487.2
+Q<696e6f7574205b33313a305d20736565643b>115.2 499.2 Q
+<696e70757420696e7465>115.2 511.2 Q<676572206d65616e3b>-.15 E
+<66756e6374696f6e205b33313a305d2024646973745f743b>108 523.2 Q
+<696e6f7574205b33313a305d20736565643b>115.2 535.2 Q
+<696e70757420696e7465>115.2 547.2 Q<676572206465>-.15 E
+<677265655f6f665f66726565646f6d3b>-.15 E
+<66756e6374696f6e205b33313a305d2024646973745f756e69666f726d3b>108 559.2
+Q<696e6f7574205b33313a305d20736565643b>115.2 571.2 Q
+<696e70757420696e7465>115.2 583.2 Q<6765722073746172743b>-.15 E
+<696e70757420696e7465>115.2 595.2 Q<67657220656e643b>-.15 E F1
+<4445534352495054494f4e>72 612 Q F0 .716
+<546865736520617265207468652072616e646f6d206465>108 624 R .716<76696174
+652067656e65726174696f6e2066756e6374696f6e732064658c6e656420696e20503133
+3634204c524d2e>-.25 F .717<416c676f726974686d20666f6c6c6f>5.716 F 3.217
+<7722>-.25 G<4e756d65726963616c>-3.217 E .162
+<5265636970657320696e2043222e>108 636 R<486f>5.162 E<7765>-.25 E -.15
+<7665>-.25 G 2.662<7274>.15 G<6865>-2.662 E 2.662<7961>-.15 G .162
+<726520736f6d65>-2.662 F .162
+<7768617420756e757375616c20696e2074616b696e6720696e7465>-.25 F .162
+<676572206172>-.15 F .162
+<67756d656e747320616e642070726f647563696e67207363616c656420696e74652d>
+-.18 F .546<676572206f75747075747320726174686572207468616e20746865206d6f
+7265206e6f726d616c207265616c206e756d62657220696e7075747320616e64206f7574
+70757473206265747765656e20302e302028736f6d6574696d6573202d312e302920616e
+64>108 648 R 3.435<312e302e2045616368>108 660 R<64697374726962>3.435 E
+.935<7574696f6e2066756e6374696f6e2074616b>-.2 F .935
+<65732061208c727374206172>-.1 F .935
+<67756d656e74207468617420697320612073656564207468617420736574732063>-.18
+F .935<79636c6963616c207374617274696e6720706f696e7420696e20746865>-.15 F
+<64697374726962>108 672 Q .312<7574696f6e2073657175656e63652e>-.2 F .313
+<456163682066756e6374696f6e2072657475726e7320612072616e646f6d2076>5.312
+F .313<616c7565206163636f7264696e6720746f207468652064697374726962>-.25 F
+.313<7574696f6e207479706520616e642075706461746573>-.2 F .882<7468652073
+65656420736f20746861742069662061207061737365642073656564206973207361>108
+684 R -.15<7665>-.2 G 3.382<6461>.15 G .882
+<6e64207265757365642c20626f7468207468652073616d652076>-3.382 F .882
+<616c75652077696c6c2062652072657475726e65642c20616e64207468652073616d65>
+-.25 F<6e65>108 696 Q 2.5<7773>-.25 G<6565642077696c6c206265207365742e>
+-2.5 E<546869732070726f7065726c7920616c6c6f>5 E
+<7773207265706561746162696c69747920666f7220646562>-.25 E<756767696e672e>
+-.2 E .47
+<5468652024646973745f6368695f73717561726520616e642024646973745f74206465>
+108 712.8 R .47<677265655f6f665f66726565646f6d2076>-.15 F .47<616c756573
+2064657465726d696e6520746865207368617065206f66207468652064697374726962>
+-.25 F .47<7574696f6e20286c6172>-.2 F<676572>-.18 E -.25<7661>108 724.8
+S .619<6c75657320776964656e207468652064697374726962>.25 F 3.119
+<7574696f6e292e20546865>-.2 F .619<6d65616e20706172616d6574657220757365
+6420696e2024646973745f65726c616e672c2024646973745f65>3.119 F .619
+<78706f6e656e7469616c2c2024646973745f6e6f726d616c>-.15 F
+<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 203.45<322e352034>2.5 F 0 Cg EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R 1.434
+<616e642024646973705f706f6973736f6e206361757365207468652061>108 84 R
+-.15<7665>-.2 G 1.434<726167652076>.15 F 1.434
+<616c75652072657475726e656420746f20636f6e>-.25 F -.15<7665>-.4 G -.18
+<7267>.15 G 3.934<6574>.18 G 3.934<6f74>-3.934 G 1.435
+<686520706173736564206d65616e2e>-3.934 F 1.435
+<5468652024646973745f6e6f726d616c>6.435 F 1.29
+<66756e6374696f6e207374616e64617264206465>108 96 R 1.29<76696174696f6e20
+696e70757420706172616d657465722064657465726d696e6573207368617065206f6620
+746865207374616e64617264206e6f726d616c2064697374726962>-.25 F 1.29
+<7574696f6e20286c6172>-.2 F<676572>-.18 E -.25<7661>108 108 S .481
+<6c756520776964656e73207468652064697374726962>.25 F 2.981
+<7574696f6e292e20546865>-.2 F .481<24646973745f756e69666f726d2073746172
+7420616e6420656e642064657465726d696e65207468652072616e67652077697468696e
+2077686963682074686520756e692d>2.981 F .293
+<666f726d6c792064697374726962>108 120 R .293
+<757465642072616e646f6d206e756d626572208c74732e>-.2 F .292
+<537461727420616e6420656e64206d6179206265206e65>5.292 F -.05<6761>-.15 G
+<7469>.05 E .592 -.15<76652062>-.25 H .292
+<7574207374617274206d757374206265206c657373207468616e20656e642e>-.05 F
+<546865>5.292 E<6d65616e2c206b5f737461676520616e64206465>108 132 Q<6772
+65655f6f665f66726565646f6d20706172616d6574657273206d75737420626520706f73
+697469>-.15 E -.15<7665>-.25 G/F1 10.95/Times-Bold at 0 SF
+<5245464552454e4345>72 148.8 Q F0<44658c6e656420696e205031333634204c524d
+2073656374696f6e2031342e31302e322e>108 160.8 Q F1<53454520414c534f>72
+177.6 Q F0 1.542<53656520616e>108 189.6 R 4.042<7973>-.15 G 1.542
+<746174697374696373207465>-4.042 F 1.542<7874626f6f6b206f72204352432048
+616e64626f6f6b206f66205374616e64617264204d6174682054>-.15 F 1.542<61626c
+657320666f722064658c6e6974696f6e73206f662074686520666f726d756c61732e>-.8
+F<416c736f2073656520224e756d65726963616c205265636970657320696e2043222066
+6f7220616c676f726974686d732e>108 201.6 Q<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72 225.6 Q F1
+-.219<4e41>72 242.4 S<4d45>.219 E F0<2464756d7076>108 254.4 Q
+<61727320ad207365742075702076>-.25 E<61726961626c6573207468617420617265
+207772697474656e20746f20564344208c6c65>-.25 E
+<2464756d70616c6c20ad2064756d702063757272656e742076>108 266.4 Q
+<616c7565206f6620616c6c2076>-.25 E
+<61726961626c65732073657420757020666f722064756d7076>-.25 E<6172696e67>
+-.25 E<2464756d708d75736820ad206d616b>108 278.4 Q 2.5<654f>-.1 G 2.5
+<5363>-2.5 G<616c6c20746f208d75736820564344208c6c652062>-2.5 E<7566>-.2
+E<66657220746f208c6c65>-.25 E<2464756d706c696d697420ad20736574206d617869
+6d756d2073697a65206f6620564344208c6c65>108 290.4 Q<2464756d706f66>108
+302.4 Q 2.5<66ad74>-.25 G<75726e206f66>-2.5 E 2.5<6664>-.25 G
+<756d70696e6720746f20564344208c6c65206f6e2076>-2.5 E
+<61726961626c65206368616e676573>-.25 E<2464756d706f6e20ad207475726e206f
+6e2064756d70696e6720746f20564344208c6c65206f6e2076>108 314.4 Q
+<61726961626c65206368616e676573>-.25 E F1<53594e4f50534953>72 331.2 Q F0
+<2464756d7076>108 343.2 Q<617273285b6c65>-.25 E -.15<7665>-.25 G
+<6c5d2c205b6c697374206f662073636f70657320616e642f6f722076>.15 E
+<61726961626c657320746f2064756d705d293b>-.25 E<2464756d70616c6c3b>108
+355.2 Q<2464756d708c6c65285b8c6c65206e616d655d293b>108 367.2 Q
+<2464756d708d7573683b>108 379.2 Q<2464756d706c696d6974285b6c696d6974206e
+756d626572206f662062797465735d293b>108 391.2 Q<2464756d706f66>108 403.2
+Q<663b>-.25 E<2464756d706f6e3b>108 415.2 Q F1<4445534352495054494f4e>72
+432 Q F0 .945<546865202464756d7076>108 444 R .945<6172732073797374656d20
+7461736b20636175736573208c72737420612068656164657220746f2062652077726974
+74656e20746f2074686520564344202876>-.25 F .945
+<616c7565206368616e67652064756d7029208c6c652074686174>-.25 F .863
+<64658c6e657320612073686f727420636f646520666f7220656163682076>108 456 R
+3.363<61726961626c65732e205468656e>-.25 F<7768656e65>3.363 E -.15<7665>
+-.25 G 3.363<726176>.15 G .863
+<61726961626c65206368616e6765732c207468652076>-3.613 F<61726961626c6527>
+-.25 E 3.363<7363>-.55 G .864<6f646520616e642076>-3.363 F<616c7565>-.25
+E .224<617265207772697474656e20746f2074686520564344208c6c652e>108 468 R
+.224<5768656e202464756d7076>5.224 F .224
+<617273206973208c7273742063616c6c6564207468652076>-.25 F .223
+<616c7565206f6620616c6c2076>-.25 F .223
+<61726961626c6573206973207772697474656e20746f2074686520564344>-.25 F
+<8c6c652e>108 480 Q<2464756d7076>108 496.8 Q .104
+<617273206d7573742062652063616c6c6564206265666f726520616e>-.25 F 2.604
+<7977>-.15 G .104<726974696e67206f66206368616e6765642076>-2.604 F .104
+<61726961626c652076>-.25 F .104<616c75657320746f20746865205643442064756d
+70208c6c652063616e206f6363757220746f>-.25 F .715
+<736574207570207468652076>108 508.8 R .715
+<61726961626c65732074686174206172652064756d7065642e>-.25 F .715<54686520
+2464756d708c6c652073797374656d207461736b2063616e206368616e67652074686520
+6e616d65206f6620746865205643442064756d70>5.715 F 1.588
+<8c6c652066726f6d2074686520646566>108 520.8 R 1.589<61756c742076>-.1 F
+4.089<6572696c6f672e64756d702e204974>-.15 F 1.589<6d7573742062652063616c
+6c6564206265666f7265206f72206174207468652073616d652074696d65206173202464
+756d7076>4.089 F 4.089<6172732e205768656e>-.25 F<2464756d7076>108 532.8
+Q .267<6172732069732063616c6c65642061637475616c2064756d70696e6720697320
+7365742075702061742074686520656e64206f6620746861742074696d6520736c6f742e>
+-.25 F .267<497420697320616e206572726f7220666f72202464756d7076>5.267 F
+.267<61727320746f206265>-.25 F
+<63616c6c6564206d6f7265207468616e206f6e63652e>108 544.8 Q<2464756d7076>
+108 561.6 Q .05<6172732074616b>-.25 F .05
+<6573206569746865722073636f706573206f722076>-.1 F .05
+<61726961626c65206e616d6573206173206172>-.25 F 2.55
+<67756d656e74732e2041>-.18 F -1.11<5661>2.55 G .05<726961626c65206e616d
+6520286f722068696572617263686963616c207265666572656e636529>1.11 F .042
+<636175736573206a75737420746861742076>108 573.6 R .042<61726961626c6520
+746f206265207772697474656e20746f2074686520564344208c6c652e>-.25 F 2.542
+<6153>5.042 G .042<636f70652063617573657320616c6c2076>-2.542 F .042
+<61726961626c657320696e207468652073636f706520616e6420616c6c2076>-.25 F
+<6172692d>-.25 E .335<61626c657320696e205b6c65>108 585.6 R -.15<7665>
+-.25 G .335<6c5d2073636f70657320646f>.15 F .335<776e20746f20626520777269
+7474656e20746f2074686520564344208c6c65206f6e206368616e67652e>-.25 F
+<5b6c65>5.336 E -.15<7665>-.25 G .336<6c5d2076>.15 F .336
+<616c75652030206d65616e732064657363656e6420746f20746865>-.25 F .145
+<626f74746f6d206f6620746865206869657261726368>108 597.6 R 3.945 -.65
+<792e2049>-.05 H 2.645<6624>.65 G<64756d7076>-2.645 E .145
+<6172732069732063616c6c65642077697468206e6f206172>-.25 F .145
+<67756d656e74732c20616c6c2076>-.18 F .145<61726961626c657320696e20746865
+2064657369676e20617265207772697474656e20746f>-.25 F
+<74686520564344208c6c652e>108 609.6 Q .301<2464756d70206c696d6974732073
+657420746865206d6178696d756d2073697a65206f6620746865205643442064756d7020
+8c6c6520746f205b6c696d69745d2e>108 626.4 R .301
+<4f6e6365205b6c696d69745d206279746573206861>5.301 F .602 -.15<76652062>
+-.2 H .302<65656e207772697474656e2c>.15 F .062
+<6e6f206d6f72652077726974696e6720746f207468652064756d7076>108 638.4 R
+.061<617273208c6c65206f63637572732e>-.25 F<2464756d706f66>5.061 E 2.561
+<6673>-.25 G .061<746f702064756d70696e67206f662076>-2.561 F .061
+<61726961626c657320616e64207772697465732065>-.25 F -.15<7665>-.25 G .061
+<72792064756d706564>.15 F -.25<7661>108 650.4 S .087<726961626c6520746f
+20746865205643442064756d70208c6c65207769746820756e6b6e6f>.25 F .087
+<776e202878292076>-.25 F 2.587<616c75652e202464756d706f6e>-.25 F .087
+<72657374617274732064756d70696e67206f662076>2.587 F .087
+<61726961626c65206368616e67657320616e64>-.25 F
+<7374617274732062792077726974696e67207468652063757272656e742076>108
+662.4 Q<616c7565206f662065>-.25 E -.15<7665>-.25 G<72792076>.15 E
+<61726961626c6520746f20746865205643442064756d70208c6c652e>-.25 E .846
+<546865202b64756d7076>108 679.2 R<61727365>-.25 E .846
+<7874656e646564206164646564204376>-.15 F .845<6572206f7074696f6e20777269
+7465732061206e6f6e207374616e6461726420564344208c6c652062>-.15 F .845
+<757420616c6c6f>-.2 F .845<777320737472656e6774687320286e6f74206a757374>
+-.25 F .73<7468652076>108 691.2 R .73<616c756520706172742920746f20626520
+7772697474656e20616e642075736573206865>-.25 F 3.23<7866>-.15 G .73<6f72
+6d617420696e7374656164206f662062696e61727920776865726520706f737369626c65
+20746f207265647563652074686520564344208c6c65>-3.23 F<73697a652e>108
+703.2 Q<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 203.45<322e352035>2.5 F 0 Cg EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF<5245464552454e4345>72 84 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031352e>108 96 Q
+<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d>72 120 Q F1 -.219<4e41>72 136.8 S<4d45>.219 E F0
+<2466646973706c6179>108 148.8 Q 2.5<2c24>-.65 G<66646973706c6179622c2024
+66646973706c6179682c202466646973706c61796f20ad20777269746520666f726d6174
+7465642076>-2.5 E<616c756520746f208c6c65287329>-.25 E<246677726974652c20
+24667772697465622c2024667772697465682c20246677726974656f20ad207772697465
+20666f726d61747465642076>108 160.8 Q<616c756520746f208c6c65287329>-.25 E
+F1<53594e4f50534953>72 177.6 Q F0<2466646973706c6179285b6d756c74692d6368
+616e6e656c5d2c205b696e7465726d6978>108 189.6 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E<2466646973706c61795b62686f5d285b6d75
+6c74692d6368616e6e656c5d2c205b696e7465726d6978>108 201.6 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E
+<24667772697465285b6d756c74692d6368616e6e656c5d2c205b696e7465726d6978>
+108 213.6 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E<2466646973706c61795b62686f5d285b6d75
+6c74692d6368616e6e656c5d2c205b696e7465726d6978>108 225.6 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E F1<4445534352495054494f4e>72 242.4 Q
+F0 .249<53616d652061732024646973706c617920616e64202477726974652062>108
+254.4 R .249<75742077726974657320746f20616c6c208c6c652073747265616d7320
+73656c6563746564206279206f6e206269747320696e2070617373656420333220626974
+206d756c74692d6368616e6e656c>-.2 F<64657363726970746f72>108 266.4 Q
+5.477<2e49>-.55 G 2.977<6662>-5.477 G .477<6974206973206f6e2062>-2.977 F
+.478<7574208c6c6520636f72726573706f6e64696e6720746f2062697420706f736974
+696f6e206966206e6f74206f70656e656420776974682024666f70656e2073797374656d
+2066756e6374696f6e2c206e6f>-.2 F .643<7772697465206f63637572732e>108
+278.4 R .643<5468652069646561206f66206d756c74692d6368616e6e656c20646573
+63726970746f727320616c6c6f>5.643 F .643<7773206f6e65202466646973706c6179
+20746f20777269746520746f206d6f7265207468616e206f6e65208c6c65206173>-.25
+F<6f70706f73656420746f20726571756972696e67206d756c7469706c65207772697465
+732e>108 290.4 Q F1<5245464552454e4345>72 307.2 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e322e322e>
+108 319.2 Q F1<53454520414c534f>72 336 Q F0 .476<5365652072656c61746564
+2024646973706c617920616e64202477726974652073797374656d207461736b732e>108
+348 R .476<5365652024666f70656e20616e64202466636c6f736520666f72206f7065
+6e696e6720616e6420636c6f73696e67208c6c652073747265616d73>5.476 F<616e64
+2061737369676e696e67206d756c74692d6368616e6e656c2064657363726970746f7273
+2e>108 360 Q<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d>72 384 Q F1 -.219<4e41>72 400.8 S<4d45>.219 E
+F0<248c6e69736820ad2065>108 412.8 Q<786974204376>-.15 E<6572>-.15 E F1
+<53594e4f50534953>72 429.6 Q F0<248c6e6973683b>108 441.6 Q
+<248c6e697368285b6d657373616765206c65>108 453.6 Q -.15<7665>-.25 G
+<6c5d293b>.15 E F1<4445534352495054494f4e>72 470.4 Q F0 .587
+<45786974204376>108 482.4 R .587<657220616e642072657475726e20636f6e7472
+6f6c20746f2074686520686f7374206f7065726174696e672073797374656d2e>-.15 F
+.587<696620612076>5.587 F .587<616c7565206973207061737365642c2069662069
+742069732030202873616d65206173206e6f206172>-.25 F<67752d>-.18 E 1.545<6d
+656e7429207072696e7473206e6f7468696e672c20696620312069732070617373656420
+7072696e7473206e6f726d616c2065>108 494.4 R 1.545<786974206d657373616765
+2c20616e642069662031207072696e7473206d657373616765206173206966202b76>
+-.15 F<6572626f7365>-.15 E<6f7074696f6e20776572652073656c65637465642e>
+108 506.4 Q F1<5245464552454e4345>72 523.2 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e342e312e>
+108 535.2 Q<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d>72 559.2 Q F1 -.219<4e41>72 576 S<4d45>.219 E
+F0<248d7573686c6f6720ad208d757368206c6f6720616e64207472616365208c6c6520
+696e7465726e616c204f532062>108 588 Q<7566>-.2 E<66657273>-.25 E F1
+<53594e4f50534953>72 604.8 Q F0<248d7573686c6f673b>108 616.8 Q F1
+<4445534352495054494f4e>72 633.6 Q F0 .473
+<466c75736820746865206c6f67208c6c65204f532062>108 645.6 R<7566>-.2 E
+2.973<666572732e204966>-.25 F .473<746865202474726163658c6c652073797374
+656d207461736b20686173206265656e207573656420746f207365742061207365706172
+617465207472616365206f7574707574208c6c652c>2.973 F
+<746861742073747265616d20616c736f206973208d75736865642e>108 657.6 Q F1
+<5245464552454e4345>72 674.4 Q F0
+<4e6f742064658c6e656420696e205031333634204c524d2062>108 686.4 Q
+<757420636f6d6d6f6e6c7920696d706c656d656e7465642e>-.2 E<2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72
+710.4 Q<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 203.45<322e352036>2.5 F 0 Cg EP
+%%Page: 7 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF -.219<4e41>72 84 S<4d45>.219 E F0<24666d6f6e69746f72>
+108 96 Q 2.5<2c24>-.4 G<666d6f6e69746f72622c2024666d6f6e69746f72682c2024
+666d6f6e69746f726f20ad207772697465206368616e67656420666f726d617474656420
+76>-2.5 E<616c756520746f208c6c65287329>-.25 E F1<53594e4f50534953>72
+112.8 Q F0<24666d6f6e69746f72285b6d756c74692d6368616e6e656c5d2c205b696e
+7465726d6978>108 124.8 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E<24666d6f6e69746f725b62686f5d285b6d75
+6c74692d6368616e6e656c5d2c205b696e7465726d6978>108 136.8 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E F1<4445534352495054494f4e>72 153.6 Q
+F0 .3<496620616e>108 165.6 R 2.8<7965>-.15 G .3
+<787072657373696f6e20696e2074686520666f726d61742076>-2.95 F .301<617269
+61626c65206c697374206368616e6765732c20666f726d617420616e6420777269746520
+7468652076>-.25 F .301
+<616c756520746f2061206d756c74692d6368616e6e656c20646573637269702d>-.25 F
+.074<746f72208c6c65206c6973742061742074686520656e64206f6620746865207369
+6d756c6174696f6e2074696d6520736c6f742e>108 177.6 R .073<496620612074696d
+652072657475726e696e672073797374656d2066756e6374696f6e732073756368206173
+202474696d652061707065617273>5.073 F 1.093<696e20746865206c6973742c2069
+7420646f6573206e6f742063617573652061206368616e67652e>108 189.6 R -.15
+<466f>6.093 G 1.093<726d61742069732073616d65206173202466646973706c6179>
+.15 F 6.093<2e41>-.65 G 1.393 -.15<6e79206e>-6.093 H 1.094
+<756d626572206f662024666d6f6e69746f7273206d6179206265>.15 F<757365642061
+6e64206966206d6f7265207468616e206f6e65206368616e6765642074686520666f726d
+6174206c69737420666f722065616368206368616e6765642024666d6f6e69746f722069
+73207772697474656e2061742074696d6520736c6f7420656e642e>108 201.6 Q F1
+<5245464552454e4345>72 218.4 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e322e322e>
+108 230.4 Q F1<53454520414c534f>72 247.2 Q F0
+<246d6f6e69746f722069732073616d652062>108 259.2 Q
+<75742077726974657320746f207374646f75742e>-.2 E
+<5365652024646973706c617920666f7220666f726d61742064658c6e6974696f6e2e>5
+E<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d>72 283.2 Q F1 -.219<4e41>72 300 S<4d45>.219 E F0<24666f70
+656e20ad206f70656e2061208c6c6520616e642061737369676e2061206d756c74692d64
+657363726970746f72206368616e6e656c20626974>108 312 Q<2466636c6f736520ad
+20636c6f73652061208c6c6520616e64206672656520666f722072657573652061206d75
+6c74692d64657363726970746f7220626974>108 324 Q F1<53594e4f50534953>72
+340.8 Q F0
+<66756e6374696f6e205b33313a305d2024666f70656e285b8c6c65206e616d655d293b>
+108 352.8 Q<2466636c6f7365285b6d756c74692d6368616e6e656c2064657363726970
+746f725d293b>108 364.8 Q F1<4445534352495054494f4e>72 381.6 Q F0 -1.11
+<5665>108 393.6 S .542<72696c6f6720616c6c6f>1.11 F .542<7773207772697469
+6e6720746f206d756c7469706c65206f70656e208c6c6573206174206f6e636520757369
+6e672061206d756c74692d6368616e6e656c208c6c652064657363726970746f72>-.25
+F 5.541<2e42>-.55 G .541<6974203020286c65617374207369672d>-5.541 F .9<6e
+698c63616e742062697429206973206173736f6369617465642077697468207374646f75
+7420616e6420697320616c>108 405.6 R -.1<7761>-.1 G .9<7973206f70656e2e>.1
+F .9<546865202466636c6f73652063616c6c20636c6f73657320746865208c6c652061
+73736f6369617465642077697468>5.9 F<616e>108 417.6 Q 2.849<796f>-.15 G
+2.849<6e62>-2.849 G .349<697420696e207468652070617373656420333220626974
+206d756c74692d6368616e6e656c2076>-2.849 F 2.848<616c75652e20546865>-.25
+F .348<24666f70656e2073797374656d2066756e6374696f6e20697320706173736564
+2061208c6c65206e616d65202863616e>2.848 F .218<626520616e>108 429.6 R
+2.718<796c>-.15 G .219<656e67746820616e64206e656564206e6f74206265206120
+6c69746572616c20737472696e672920616e642072657475726e732061206d756c74692d
+6368616e6e656c2064657363726970746f72207769746820746865206e65>-2.718 F
+.219<78742061>-.15 F -.25<7661>-.2 G<696c61626c65>.25 E 1.848<6269742028
+62697420636f72726573706f6e64696e6720746f20756e2d6f70656e6564206465736372
+6970746f72206368616e6e656c29207365742e>108 441.6 R 1.847<24666f70656e20
+726575736573206d756c74692d6368616e6e656c2062697473206672656564206279>
+6.848 F<2466636c6f73652e>108 453.6 Q F1<5245464552454e4345>72 470.4 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e322e312e>
+108 482.4 Q F1<53454520414c534f>72 499.2 Q F0
+<536565202466646973706c6179>108 511.2 Q 2.5<2c24>-.65 G
+<6677726974652c2024666d6f6e69746f72>-2.5 E 2.5<2c61>-.4 G<6e642024667374
+726f626520726f7574696e6573207468617420777269746520746f206d756c74692d6368
+616e6e656c2064657363726970746f72732e>-2.5 E<2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72 535.2 Q F1
+-.219<4e41>72 552 S<4d45>.219 E F0<24667374726f62652c2024667374726f6265
+622c2024667374726f6265682c2024667374726f62656f20ad20777269746520666f726d
+61747465642076>108 564 Q
+<616c756520746f208c6c6520617420656e64206f662074696d6520736c6f74>-.25 E
+F1<53594e4f50534953>72 580.8 Q F0
+<24667374726f6265285b6d756c74692d6368616e6e656c5d2c205b696e7465726d6978>
+108 592.8 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E<24667374726f62655b62686f5d285b6d756c
+74692d6368616e6e656c5d2c205b696e7465726d6978>108 604.8 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E F1<4445534352495054494f4e>72 621.6 Q
+F0 .731<53616d65206173202466646973706c61792062>108 633.6 R .731
+<757420666f726d61747320616e64207772697465732076>-.2 F .732<616c75652061
+742074686520656e64206f662074696d652074696d6520736c6f74207261746865722074
+68616e207768656e207468652024667374726f6265>-.25 F .072
+<73746174656d656e742069732065>108 645.6 R -.15<7865>-.15 G 2.572
+<63757465642e2046>.15 F .071<6f726d6174206973206964656e746963616c20746f
+202466646973706c617920616e64205b62686f5d20737566>-.15 F .071
+<8c78206c6574746572206368616e67657320646566>-.25 F .071
+<61756c7420666f722065>-.1 F<787072657373696f6e>-.15 E .764
+<746861742061707065617273206f757473696465206f6620616e>108 657.6 R 3.264
+<7966>-.15 G .765<6f726d617420617320776974682024646973706c6179>-3.264 F
+5.765<2e4f>-.65 G .765
+<6e6520666f726d6174206973207772697474656e20666f722065>-5.765 F -.15
+<7665>-.25 G .765<72792024667374726f626520616e6420247374726f6265>.15 F
+-.15<657865>108 669.6 S
+<637574656420647572696e67207468652074696d6520736c6f742e>.15 E F1
+<5245464552454e4345>72 686.4 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e322e322e>
+108 698.4 Q<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 203.45<322e352037>2.5 F 0 Cg EP
+%%Page: 8 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF<53454520414c534f>72 84 Q F0
+<247374726f62652069732073616d652065>108 96 Q
+<78636570742077726974657320746f207374646f75742e>-.15 E<2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72
+120 Q F1 -.219<4e41>72 136.8 S<4d45>.219 E F0<246765747061747465726e20ad
+2066756e6374696f6e20666f722072617069642061737369676e6d656e74206f66206d65
+6d6f7279206269747320746f20636f6e636174656e617465206f66207363616c617273>
+108 148.8 Q F1<53594e4f50534953>72 165.6 Q F0<61737369676e207b3c6c697374
+206f66207363616c617273206f722073656c656374733e5d7d203d202467657470617474
+65726e283c6d656d6f72793e5b3c696e6465>108 177.6 Q<783e5d3b>-.15 E F1
+<4445534352495054494f4e>72 194.4 Q F0 .436<546869732066756e6374696f6e20
+6d7573742062652075736564206f6e207468652072696768742068616e64207369646520
+6f66206120636f6e74696e756f75732061737369676e6d656e7420776865726520746865
+206c6566742068616e6420736964652069732061>108 206.4 R .523<636f6e63617465
+6e617465206f66207363616c617273206f7220636f6e7374616e74206269742073656c65
+6374732e>108 218.4 R .524<546865206172>5.524 F .524<67756d656e74206d7573
+7420626520612073656c656374206f66206d656d6f727920286e6f726d616c6c79206c6f
+61646564>-.18 F 1.314
+<7573696e67202472656161646d656d29207468617420697320612076>108 230.4 R
+3.814<61726961626c652e205768656e>-.25 F 1.314<7468652076>3.814 F 1.314
+<61726961626c652073656c65637420696e6465>-.25 F 3.814<7869>-.15 G 3.814
+<7363>-3.814 G 1.313<68616e67656420746865206e65>-3.814 F 3.813<776d>-.25
+G 1.313<656d6f72792076>-3.813 F<616c7565>-.25 E .511
+<64657465726d696e6564206279207468652073656c65637420696e6465>108 242.4 R
+3.012<7877>-.15 G .512<696c6c2062652072617069646c792028692e652e20776974
+68206e6f206e65656420666f722065>-3.012 F .512<787072657373696f6e2065>-.15
+F -.25<7661>-.25 G .512
+<6c756174696f6e292061737369676e656420746f20746865>.25 F 2.899
+<7363616c6172732e204e6f726d616c6c79>108 254.4 R .399
+<7468652061737369676e6d656e742070726f636573732077696c6c20626520647269>
+2.899 F -.15<7665>-.25 G 2.899<6e62>.15 G 2.899<796166>-2.899 G .399
+<6f72206c6f6f70207468617420696e6372656d656e74732074686520696e6465>-2.899
+F 2.898<782e204e6f>-.15 F<6f74686572>2.898 E
+<757365206f6620246765747061747465726e20697320616c6c6f>108 266.4 Q
+<7765642e>-.25 E F1<5245464552454e4345>72 283.2 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2046>108 295.2 Q
+<2e322e>-.8 E F1<53454520414c534f>72 312 Q F0 1.386
+<536565205031333634204c524d2073656374696f6e2046>108 324 R 1.386<2e322066
+6f722061206d6f64756c652074686174207573657320246765747061747465726e206f72
+20736565207468652076>-.8 F 1.387
+<65725f73726373206469726563746f72792066726f6d20796f7572>-.15 F
+<72656c6561736520666f722065>108 336 Q<78616d706c65207573652e>-.15 E<2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d>72 360 Q F1 -.219<4e41>72 376.8 S<4d45>.219 E F0
+<24686973746f727920ad207072696e74206c69737420707265>108 388.8 Q
+<76696f75736c792065>-.25 E -.15<7865>-.15 G
+<637574656420696e74657261637469>.15 E .3 -.15<76652063>-.25 H
+<6f6d6d616e6473>.15 E<246e6f6b>108 400.8 Q
+<656570636f6d6d616e647320ad20646f206e6f74206164642065>-.1 E -.15<7865>
+-.15 G<637574656420696e74657261637469>.15 E .3 -.15<76652063>-.25 H
+<6f6d6d616e647320746f20686973746f7279206c697374>.15 E<246b>108 412.8 Q
+<656570636f6d6d616e647320ad206164642065>-.1 E -.15<7865>-.15 G
+<637574656420696e74657261637469>.15 E .3 -.15<76652063>-.25 H
+<6f6d6d616e647320746f20686973746f7279206c697374>.15 E F1
+<53594e4f50534953>72 429.6 Q F0<24686973746f7279285b6e756d626572206f6620
+636f6d6d616e647320746f206c6973745d293b>108 441.6 Q<246b>108 453.6 Q
+<656570636f6d6d616e64733b>-.1 E<246e6f6b>108 465.6 Q
+<656570636f6d6d616e64733b>-.1 E F1<4445534352495054494f4e>72 482.4 Q F0
+.169<24686973746f7279206c697374732065697468657220616c6c206f72205b6e756d
+6265725d206f66206d6f737420726563656e746c792065>108 494.4 R -.15<7865>
+-.15 G .168<637574656420696e74657261637469>.15 F .468 -.15<76652063>-.25
+H 2.668<6f6d6d616e64732e20416c6c>.15 F .168<636f6d6d616e64732065>2.668 F
+<7863657074>-.15 E .84<686973746f727920656e61626c652c2064697361626c652c
+20616e64206f6e6520636861726163746572206162627265>108 506.4 R .841<766961
+74696f6e20636f6d6d616e64732061726520656e746572656420696e2074686520686973
+746f7279206c6973742e>-.25 F .841<4164646564203a>5.841 F<646562>108 518.4
+Q<756767657220636f6d6d616e64732061726520616c736f20616464656420746f207468
+6520686973746f7279206c6973742e>-.2 E .034<4561636820636f6d6d616e64206973
+206e756d626572656420736f2069742063616e2062652072652d65>108 535.2 R -.15
+<7865>-.15 G .034<637574656420627920656e746572696e67205b6e756d6265725d20
+61742074686520696e74657261637469>.15 F .334 -.15<76652070>-.25 H .034
+<726f6d707420616e642c20666f72>.15 F 1.91<7363686564756c656420616e642075
+6e636f6d706c6574656420636f6d6d616e64732c2064697361626c656420627920747970
+696e67202d5b686973746f727920636f6d6d616e64206e756d6265725d2e>108 547.2 R
+<246e6f6b>6.91 E<656570636f6d2d>-.1 E .133<6d616e64732064697361626c6573
+20636f6c6c656374696f6e206f6620696e74657261637469>108 559.2 R .432 -.15
+<76652063>-.25 H .132<6f6d6d616e647320696e746f2074686520686973746f727920
+6c69737420616e6420246b>.15 F .132
+<656570636f6d6d616e647320656e61626c657320636f6c6c65632d>-.1 F 3.054
+<74696f6e2e204376>108 571.2 R .554<6572206b>-.15 F .555<6565707320616c6c
+20636f6d6d616e647320656e7465726564206f6e2074686520686973746f7279206c6973
+7420756e74696c2061203a656d707479686973746f727920616464656420646562>-.1 F
+.555<756767657220636f6d6d616e64>-.2 F 2.259<697320656e746572656420617420
+776869636820706f696e742074686520686973746f7279206c697374206973206d616465
+20656d707479>108 583.2 R 7.259<2e24>-.65 G 2.258
+<696e70757420636f6d6d616e6420736372697074732073686f756c64206265>-7.259 F
+2.258<67696e2077697468>-.15 F<246e6f6b>108 595.2 Q .637
+<656570636f6d6d616e647320616e6420656e64207769746820246b>-.1 F .637<6565
+70636f6d6d616e647320746f206d696e696d697a6520686973746f7279206c6973742073
+697a652e>-.1 F .637<54686520616464656420646562>5.637 F .637
+<7567676572203a6869732d>-.2 F .203
+<746f727920636f6d6d616e64206973206d6f7265208d65>108 607.2 R .203
+<7869626c65207468616e2024686973746f7279>-.15 F 5.203<2e4d>-.65 G .202<75
+6c7469706c65206c696e6520636f6d6d616e64732028656e642077697468206573636170
+6564206e65>-5.203 F 2.702<776c>-.25 G .202<696e6520696e204376>-2.702 F
+<657229>-.15 E<617265207072696e746564206173206f6e6520636f6d6d616e642e>
+108 619.2 Q F1<5245464552454e4345>72 636 Q F0
+<4e6f742064658c6e656420696e205031333634204c524d2e>108 648 Q -.5<4f56>5 G
+2.5<494c>.5 G<524d20312e302073656374696f6e20442e382e>-2.5 E F1
+<53454520414c534f>72 664.8 Q F0 .105<53656520616464656420646562>108
+676.8 R .106<7567676572206f6e6c696e6520223a68656c7020686973746f72792220
+636f6d6d616e6420666f72206d6f72652064657461696c6564206465736372697074696f
+6e206f66204376>-.2 F<657227>-.15 E 2.606<7368>-.55 G .106
+<6973746f7279206d656368612d>-2.606 F<6e69736d2e>108 688.8 Q<2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>
+72 712.8 Q<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 203.45<322e352038>2.5 F 0 Cg EP
+%%Page: 9 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF -.219<4e41>72 84 S<4d45>.219 E F0
+<24696e70757420ad20656e74657220696e74657261637469>108 96 Q .3 -.15
+<76652063>-.25 H<6f6d6d616e64732066726f6d2061208c6c65>.15 E F1
+<53594e4f50534953>72 112.8 Q F0<24696e707574285b8c6c655d293b>108 124.8 Q
+F1<4445534352495054494f4e>72 141.6 Q F0 .574
+<24696e70757420616e6420746865202d69205b8c6c655d204376>108 153.6 R .574
+<657220636f6d6d616e64206172>-.15 F .574
+<67756d656e7420636175736520696e74657261637469>-.18 F .874 -.15<76652063>
+-.25 H .574
+<6f6d6d616e647320746f20626520726561642066726f6d205b8c6c655d2e>.15 F .574
+<49742063616e>5.574 F .401<636f6e7461696e20616464656420646562>108 165.6
+R .402<7567676572203a20636f6d6d616e64732e>-.2 F .402<496620616e2024696e
+70757420736372697074208c6c6520636f6e7461696e7320612024696e7075742063616c
+6c2c20636f6d6d616e642072656164696e6720636f6e2d>5.402 F .737
+<74696e75657320696e20746865206e65>108 177.6 R 3.237<7773>-.25 G 3.236
+<63726970742e20546865>-3.237 F<6e65>3.236 E 3.236<7773>-.25 G .736
+<6372697074207265706c6163657320746865206f6c6420616e6420616e>-3.236 F
+3.236<7975>-.15 G<6e2d65>-3.236 E -.15<7865>-.15 G .736
+<637574656420696e74657261637469>.15 F 1.036 -.15<76652063>-.25 H .736
+<6f6d6d616e6473206166746572>.15 F .306
+<7468652024696e70757420617265206e6f742063616c6c65642e>108 189.6 R .306
+<546865206e65>5.306 F 2.807<7773>-.25 G .307
+<637269707420697320636861696e656420746f206e6f742063616c6c65642e>-2.807 F
+<496e74657261637469>5.307 E .607 -.15<7665206d>-.25 H .307
+<6f6465206d75737420626520656e7465726564206265666f7265>.15 F 1.339<636f6d
+6d616e64732063616e20626520726561642066726f6d207468652024696e707574208c6c
+6520736f20626f7468202d6920616e642024696e70757420646f206e6f7468696e672075
+6e6c65737320696e74657261637469>108 201.6 R 1.638 -.15<7665206d>-.25 H
+1.338<6f6465206973>.15 F 2.5<656e74657265642e2024696e707574>108 213.6 R
+<73686f756c64206e6f742061707065617220696e2056>2.5 E
+<6572696c6f6720736f757263652e>-1.11 E F1<5245464552454e4345>72 230.4 Q
+F0<44658c6e656420696e205031333634204c524d2073656374696f6e2046>108 242.4
+Q<2e332e>-.8 E F1<53454520414c534f>72 259.2 Q F0
+<53656520616464656420646562>108 271.2 Q
+<7567676572206f6e6c696e6520223a68656c7020646562>-.2 E<756767696e67222066
+6f72206164646974696f6e616c20646f63756d656e746174696f6e2e>-.2 E<2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d>72 295.2 Q F1 -.219<4e41>72 312 S<4d4520284e4f>.219 E 2.738<5453>
+-.438 G<5550504f52>-2.738 E<544544204259204356455229>-.438 E F0<246b>108
+324 Q .3 -.15<657920ad2073>-.1 H -2.25 -.2<61762065>.15 H -2.15 -.25
+<65762065>2.7 H<7279207072657373206b>.25 E .3 -.15<65792073>-.1 H
+<74726f6b>.15 E 2.5<6574>-.1 G 2.5<6f618c>-2.5 G<6c65>-2.5 E<246e6f6b>
+108 336 Q .3 -.15<657920ad2064>-.1 H<697361626c65207361>.15 E
+<76696e67206f66206b>-.2 E .3 -.15<65792073>-.1 H<74726f6b>.15 E<6573>-.1
+E F1<4445534352495054494f4e>72 352.8 Q F0<4376>108 364.8 Q .306
+<657220646f6573206e6f7420737570706f727420246b>-.15 F .606 -.15<65792062>
+-.1 H .306<65636175736520697420646570656e6473206f6e20746865206f72696769
+6e616c20584c20736368656d6520666f7220747261636b696e67206173796e6368726f6e
+6f757320696e746572>.15 F<2d>-.2 E
+<727570747320616e64206973206e6f7420636f6d70617469626c652077697468204376>
+108 376.8 Q<657227>-.15 E 2.5<7361>-.55 G<64646564203a20646562>-2.5 E
+<756767657220616e64206c696e6520636f6e74696e756174696f6e20736368656d652e>
+-.2 E .395<546865726520617265207477>108 393.6 R 2.894<6f62>-.1 G .394
+<65747465722077>-2.894 F .394<61797320746f20616c6c6f>-.1 F 2.894<7772>
+-.25 G .394<657374617274696e6720616e642073696d756c6174696e6720746f206120
+706172746963756c61722070726f626c656d2073746174656d656e742061742061207061
+72746963752d>-2.894 F .049<6c61722070726f626c656d2074696d652e>108 405.6
+R .05<46697273742c207072657061726520612024696e7075742073637269707420616e
+6420757365202d732077697468202d6920636f6d6d616e64206f7074696f6e7320746f20
+726572756e20746865207363726970742e>5.049 F<5365632d>5.05 E .112<6f6e642c
+2075736520746865206164646564203a69627265616b206f72203a627265616b20627265
+616b706f696e7420636f6d6d616e64207769746820746865203a69676e6f7265205b636f
+756e745d20636f6d6d616e6420746f20736b6970205b636f756e745d>108 417.6 R
+.454<627265616b20706f696e747320746f2072657475726e20746f207468652070726f
+626c656d2074696d652e>108 429.6 R .454<557365203a696e666f20627265616b706f
+696e7420746f2064657465726d696e6520746865206e756d626572206f662074696d6573
+206120627265616b>5.454 F .392<706f696e742077>108 441.6 R .392
+<6173206869742e>-.1 F<416c7465726e617469>5.392 E .692 -.15<76652075>-.25
+H .391
+<736520746865203a627265616b706f696e7420636f6d6d616e64203a636f6e64205b65>
+.15 F .391<787072657373696f6e5d20636f6d6d616e6420746f206174746163682061
+20636f6e646974696f6e>-.15 F
+<746f20612073746174656d656e7420627265616b20706f696e742e>108 453.6 Q F1
+<5245464552454e4345>72 470.4 Q F0
+<536565205031333634204c524d2073656374696f6e2046>108 482.4 Q<2e342e>-.8 E
+F1<53454520414c534f>72 499.2 Q F0<53656520616464656420646562>108 511.2 Q
+<7567676572203a68656c70206f6e6c696e652068656c702073797374656d206d657373
+616765732e>-.2 E<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72 535.2 Q F1 -.219<4e41>72 552 S<4d45>
+.219 E F0<246c69737420ad206c69737420736f75726365207265636f6e737472756374
+65642066726f6d20696e7465726e616c2064617461206261736520666f722073636f7065>
+108 564 Q F1<53594e4f50534953>72 580.8 Q F0
+<246c697374285b73636f70655d293b>108 592.8 Q F1<4445534352495054494f4e>72
+609.6 Q F0 1.869<4c6973742073636f706520746f207374646f757420616e64207468
+65206c6f67208c6c65206279207265636f6e737472756374696e6720736f757263652066
+726f6d204376>108 621.6 R<657227>-.15 E 4.369<7369>-.55 G 1.869
+<6e7465726e616c20726570726573656e746174696f6e2e>-4.369 F<416c6c>6.869 E
+1.178<706172616d657465727320616e642073706563706172616d732061726520646973
+706c61796564206173206e756d6572696320636f6e7374616e74732e>108 633.6 R
+1.178<4966206e6f206172>6.178 F 1.178<67756d656e74206973206769>-.18 F
+-.15<7665>-.25 G 1.178<6e2c206c697374207468652063757272656e74>.15 F
+2.725<73636f70652e204966>108 645.6 R .225<746865202d6420636f6d6d616e6420
+6c696e65206f7074696f6e20697320757365642c207265636f6e73747275637465642073
+6f7572636520666f7220616e20656e746972652064657369676e206973206f7574707574
+2e>2.725 F .226<496620246c697374206973>5.226 F -.15<657865>108 657.6 S
+1.25<63757465642066726f6d20696e74657261637469>.15 F 1.55 -.15<7665206d>
+-.25 H 1.25<6f64652c207468652063757272656e7420696e74657261637469>.15 F
+1.549 -.15<76652073>-.25 H 1.249<636f706520286d617962652073657420776974
+6820746865202473636f70652073797374656d207461736b206973>.15 F 3.228
+<75736564292e204974>108 669.6 R .728
+<6973206265747465722066726f6d20696e74657261637469>3.228 F 1.028 -.15
+<7665206d>-.25 H .728
+<6f646520746f2075736520746865203a6c69737420616464656420646562>.15 F .729
+<756767657220636f6d6d616e642074686174207072696e747320736f75726365206c69
+6e6573>-.2 F -.15<6578>108 681.6 S<6163746c7920617320746865>.15 E 2.5
+<7961>-.15 G
+<707065617220696e2074686520736f7572636520696e70757420616e6420616c6c6f>
+-2.5 E
+<7773206d6f726520636f6e74726f6c206f66206c696e657320746f206c6973742e>-.25
+E F1<5245464552454e4345>72 698.4 Q F0
+<536565205031333634204c524d2073656374696f6e2046>108 710.4 Q<2e352e>-.8 E
+<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 203.45<322e352039>2.5 F 0 Cg EP
+%%Page: 10 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF<53454520414c534f>72 84 Q F0 -.8<5479>108 96 S
+<706520223a68656c70203a6c6973742220696e20696e74657261637469>.8 E .3 -.15
+<7665206d>-.25 H<6f646520666f7220646f63756d656e746174696f6e206f66203a6c
+6973742072616e67652073706563698c636174696f6e2e>.15 E<2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72
+120 Q F1 -.219<4e41>72 136.8 S<4d45>.219 E F0
+<246c6f6720ad20736574206e65>108 148.8 Q 2.5<776c>-.25 G<6f67206f75747075
+74208c6c65206f722072652d656e61626c652077726974696e6720746f206c6f67208c6c
+65>-2.5 E<246e6f6c6f6720ad2064697361626c652077726974696e6720746f20746865
+206c6f67208c6c65>108 160.8 Q F1<53594e4f50534953>72 177.6 Q F0
+<246c6f673b>108 189.6 Q<246c6f67285b8c6c65206e616d655d293b>108 201.6 Q
+<246e6f6c6f673b>108 213.6 Q F1<4445534352495054494f4e>72 230.4 Q F0 .419
+<4e6f726d616c6c7920616c6c207465726d696e616c20287374646f757429206f757470
+7574206973207772697474656e20746f20746865206c6f67208c6c652074686174206861
+73206e616d652076>108 242.4 R .418
+<6572696c6f672e6c6f6720616e64206973206f>-.15 F -.15<7665>-.15 G -.2
+<722d>.15 G<7772697474656e>.2 E .711<666f722065616368206e65>108 254.4 R
+3.211<7772>-.25 G .711<756e206f66204376>-3.211 F .711<657220636f6d6d616e
+64206f7074696f6e2073657420746865206c6f67208c6c6520746f205b8c6c655d2e>
+-.15 F .711<416e6f746865722077>5.711 F .711
+<617920746f2064697361626c652077726974696e6720746f20746865>-.1 F
+<6c6f67208c6c6520697320746f20757365208c6c65206e616d65202f6465>108 266.4
+Q<762f6e756c6c206f6e20556e697820616e64206e756c206f6e204f53322f444f532e>
+-.25 E F1<5245464552454e4345>72 283.2 Q F0
+<536565205031333634204c524d2073656374696f6e2046>108 295.2 Q<2e362e>-.8 E
+<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d>72 319.2 Q F1 -.219<4e41>72 336 S
+<4d4520284356455220455854454e53494f4e29>.219 E F0
+<246d656d75736520ad207072696e74206d657373616765206769>108 348 Q
+<76696e672064796e616d6963616c6c7920616c6c6f6361746564206d656d6f7279>-.25
+E<2e>-.65 E F1<53594e4f50534953>72 364.8 Q F0<246d656d7573653b>108 376.8
+Q F1<4445534352495054494f4e>72 393.6 Q F0 .407<53797374656d207461736b20
+746861742063616e2062652063616c6c656420746f206f757470757420746f207374646f
+757420616e6420746865206c6f67208c6c6520746865206e756d626572206f6620627974
+6573206f662064796e616d6963616c6c7920616c6c6f2d>108 405.6 R
+<6361746564206d656d6f7279>108 417.6 Q 5<2e52>-.65 G<6174686572207573656c
+6573732061646465642073797374656d207461736b2073696e6365206974206973206265
+7474657220746f2075736520746865202b76>-5 E<6572626f7365206f7074696f6e2e>
+-.15 E F1<5245464552454e4345>72 434.4 Q F0<4376>108 446.4 Q<65722065>
+-.15 E<7874656e73696f6e206e6f74206d656e74696f6e656420696e20746865205031
+333634204c524d2e>-.15 E<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72 470.4 Q F1 -.219<4e41>72 487.2 S
+<4d45>.219 E F0<246d6f6e69746f72>108 499.2 Q 2.5<2c24>-.4 G<6d6f6e69746f
+72622c20246d6f6e69746f72682c20246d6f6e69746f726f20ad20777269746520636861
+6e67656420666f726d61747465642076>-2.5 E<616c756520746f208c6c65287329>
+-.25 E<246d6f6e69746f726f66>108 511.2 Q<662d2064697361626c6520646973706c
+6179206f66206d6f6e69746f72206368616e676573>-.25 E<246d6f6e69746f726f6e2d
+2072652d656e61626c6520646973706c6179206f66206d6f6e69746f72206368616e6765
+73>108 523.2 Q F1<53594e4f50534953>72 540 Q F0
+<246d6f6e69746f72285b6d756c74692d6368616e6e656c5d2c205b696e7465726d6978>
+108 552 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E<246d6f6e69746f725b62686f5d285b6d756c
+74692d6368616e6e656c5d2c205b696e7465726d6978>108 564 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E<246d6f6e69746f726f6e3b>108 576 Q
+<246d6f6e69746f726f66>108 588 Q<663b>-.25 E F1<4445534352495054494f4e>72
+604.8 Q F0 .296<496620616e>108 616.8 R 2.796<7965>-.15 G .296
+<787072657373696f6e20696e2074686520666f726d61742076>-2.946 F .296<617269
+61626c65206c697374206368616e6765732c20666f726d617420616e6420777269746520
+7468652076>-.25 F .296
+<616c756520746f207374646f757420616e6420746865206c6f67208c6c65206174>-.25
+F .087<74686520656e64206f66207468652073696d756c6174696f6e2074696d652073
+6c6f742e>108 628.8 R .087
+<4f6e6c79206f6e6520246d6f6e69746f722063616e2062652061637469>5.087 F .386
+-.15<76652061>-.25 H 2.586<746174>.15 G 2.586<696d652e204578>-2.586 F
+.086<65637574696f6e206f662061206e65>-.15 F 2.586<776d>-.25 G
+<6f6e69746f72>-2.586 E .33<7265706c616365732074686520707265>108 640.8 R
+.33<76696f757320287365652024666d6f6e69746f72206966206d756c7469706c652061
+637469>-.25 F .63 -.15<7665206d>-.25 H .33<6f6e69746f727320617265206e65
+656465642c20757365206d756c74692d6368616e6e656c206368616e6e656c203020746f>
+.15 F .588<777269746520746f207374646f757420616e64206c6f67208c6c65292e>
+108 652.8 R .587<496620612074696d652072657475726e696e672073797374656d20
+66756e6374696f6e732073756368206173202474696d65206170706561727320696e2074
+6865206c6973742c20697420646f6573>5.588 F .555
+<6e6f742063617573652061206368616e67652e>108 664.8 R -.15<466f>5.555 G
+.555<726d61742069732073616d65206173202466646973706c6179>.15 F 3.056
+<2e24>-.65 G<6d6f6e69746f726f66>-3.056 E 3.056<6674>-.25 G .556
+<75726e73206f66>-3.056 F 3.056<6664>-.25 G .556
+<6973706c6179206f66206368616e676564206d6f6e69746f722076>-3.056 F
+<616c756573>-.25 E<616e6420246d6f6e69746f726f6e2072652d656e61626c657320
+77726974696e67206f66206368616e67656420666f726d61747465642076>108 676.8 Q
+<616c7565732e>-.25 E F1<5245464552454e4345>72 693.6 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e312e>108
+705.6 Q<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 198.45<322e35203130>2.5 F 0 Cg EP
+%%Page: 11 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF<53454520414c534f>72 84 Q F0 .308
+<24666d6f6e69746f722069732073616d652062>108 96 R .307<757420777269746573
+20746f208c6c65207573696e67206d756c74692d6368616e6e656c206465736372697074
+6f72>-.2 F 2.807<2c53>-.4 G .307<65652024646973706c617920666f7220666f72
+6d617420646f63756d656e746174696f6e2e>-2.807 F<2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72 120 Q F1
+-.219<4e41>72 136.8 S<4d45>.219 E F0
+<24715f61646420ad20706c61636520616e20656e747279206f6e2061207175657565>
+108 148.8 Q<24715f65>108 160.8 Q<78616d20ad206765742073656c656374656420
+71756575652073746174757320696e666f726d6174696f6e>-.15 E
+<24715f696e697469616c697a6520ad206372656174652061206e65>108 172.8 Q 2.5
+<7771>-.25 G<75657565>-2.5 E<24715f72656d6f>108 184.8 Q .3 -.15
+<766520ad2067>-.15 H<657420616e20656e7472792066726f6d2061207175657565>
+.15 E<24715f66756c6c20ad2072657475726e2031206966206120717565756520696620
+66756c6c20656c73652030>108 196.8 Q F1<53594e4f50534953>72 213.6 Q F0
+<24715f6164643b>108 225.6 Q<696e70757420696e7465>115.2 237.6 Q<67657220
+715f69643b202f2f20756e69717565206e756d62657220746f206964656e746966792071
+75657565>-.15 E<696e70757420696e7465>115.2 249.6 Q<676572206a6f625f6964
+3b202f2f20756e69717565206e756d62657220746f206964656e74696679206a6f62>
+-.15 E<696e70757420696e7465>115.2 261.6 Q
+<67657220696e666f726d5f69643b202f2f20757365722064658c6e65642076>-.15 E
+<616c756520616464656420746f207175657565>-.25 E<6f757470757420696e7465>
+115.2 273.6 Q
+<676572207374617475733b202f2f20636f6d706c6574696f6e20737461747573>-.15 E
+<24715f65>108 285.6 Q<78616d3b>-.15 E<696e70757420696e7465>115.2 297.6 Q
+<67657220715f69643b202f2f20756e69717565206e756d62657220746f206964656e74
+696679207175657565>-.15 E<696e70757420696e7465>115.2 309.6 Q<6765722071
+5f737461745f636f64653b202f2f207768617420746f2072657475726e20696e20715f73
+7461745f76>-.15 E<616c7565>-.25 E<6f757470757420696e7465>115.2 321.6 Q
+<67657220715f737461745f76>-.15 E<616c75653b2f2f2072657475726e65642076>
+-.25 E<616c75652073656c656374656420627920715f737461745f636f6465>-.25 E
+<6f757470757420696e7465>115.2 333.6 Q
+<676572207374617475733b202f2f20636f6d706c6574696f6e20737461747573>-.15 E
+<24715f696e697469616c697a65>108 345.6 Q<696e70757420696e7465>115.2 357.6
+Q<67657220715f69643b202f2f20756e69717565206e756d62657220746f206964656e74
+696679207175657565>-.15 E<696e70757420696e7465>115.2 369.6 Q
+<67657220715f747970653b202f2f20747970652c20313d8c666f2c20323d6c69666f>
+-.15 E<696e707574206d61785f6c656e6774683b202f2f206d6178696d756d206e756d
+626572206f6620656c656d656e747320616c6c6f>115.2 381.6 Q
+<77656420696e207175657565>-.25 E<6f757470757420696e7465>115.2 393.6 Q
+<676572207374617475733b202f2f20636f6d706c6574696f6e20737461747573>-.15 E
+<24715f72656d6f>108 405.6 Q -.15<7665>-.15 G<3b>.15 E
+<696e70757420696e7465>115.2 417.6 Q<67657220715f69643b202f2f20756e697175
+65206e756d62657220746f206964656e74696679207175657565>-.15 E
+<696e70757420696e7465>115.2 429.6 Q<676572206a6f625f69643b202f2f20756e69
+717565206e756d62657220746f206964656e74696679206a6f62>-.15 E
+<696e70757420696e7465>115.2 441.6 Q
+<67657220696e666f726d5f69643b202f2f20757365722064658c6e65642076>-.15 E
+<616c75652072656d6f>-.25 E -.15<7665>-.15 G 2.5<6466>.15 G
+<726f6d207175657565>-2.5 E<6f757470757420696e7465>115.2 453.6 Q
+<676572207374617475733b202f2f20636f6d706c6574696f6e20737461747573>-.15 E
+<66756e6374696f6e205b33313a305d2024715f66756c6c3b>108 465.6 Q
+<696e70757420696e7465>115.2 477.6 Q<67657220715f69643b202f2f20756e697175
+65206e756d62657220746f206964656e74696679207175657565>-.15 E
+<6f757470757420696e7465>115.2 489.6 Q
+<676572207374617475733b202f2f20636f6d706c6574696f6e20737461747573>-.15 E
+F1<4445534352495054494f4e>72 506.4 Q F0 .614<496e20636f6d62696e6174696f
+6e20776974682073746f636861737469632072616e646f6d2064697374726962>108
+518.4 R .614<7574696f6e20286465>-.2 F .614<7669617465292067656e65726174
+6f72732c20746865736520726f7574696e65732070726f>-.25 F .615
+<7669646520726f7574696e657320746f>-.15 F .368
+<6d6f64656c20737461746973746963616c20717565756520666f7220647269>108
+530.4 R .368<76696e672064657369676e732e>-.25 F .367<5573652074686520504c
+4920726f7574696e657320666f72207175657565732074686174206d75737420636f6e74
+61696e2076>5.368 F .367<616c756573206d6f7265>-.25 F
+<636f6d706c69636174656420746861742033322062697420696e7465>108 542.4 Q
+<6765727320286f72207265>-.15 E<6773292e>-.15 E 1.146<666f722024715f65>
+108 559.2 R 1.146<78616d2c2074686520706f737369626c6520726571756573742074
+79706573206172653a20313d63757272656e74207175657565206c656e6774682c20323d
+6d65616e20696e746572>-.15 F<2d61727269>-.2 E -.25<7661>-.25 G 3.647
+<6c74>.25 G 1.147<696d652c20333d6d6178692d>-3.647 F 1.047
+<6d756d207175657565206c656e6774682c20343d73686f72746573742077>108 571.2
+R 1.047<6169742074696d652065>-.1 F -.15<7665>-.25 G 1.847 -.4<722c2035>
+.15 H 1.047<3d6c6f6e676573742077>.4 F 1.047<6169742074696d6520666f72206a
+6f6273207374696c6c20696e2071756575652c20616e6420363d61>-.1 F -.15<7665>
+-.2 G<72616765>.15 E -.1<7761>108 583.2 S 1.089
+<69742074696d6520696e207468652071756575652e>.1 F<416e>6.089 E 3.589
+<7971>-.15 G 1.09<7565756520726f7574696e65206d61792073657420746865207374
+61747573206f757470757420706172616d6574657220746f3a20313d4f4b2c20323d7175
+6575652066756c6c2c>-3.589 F 1.457<63616e6e6f74206164642c20333d756e64658c
+6e656420715f69642c20343d756e737570706f7274656420717565756520747970652c20
+63616e6e6f74206372656174652071756575652c20353d73706563698c6564206c656e67
+7468203c3d302c>108 595.2 R<63616e6e6f74206372656174652c20363d6475706c69
+6361746520715f69642c2063616e6e6f74206372656174652c206e6f7420656e6f756768
+206d656d6f7279>108 607.2 Q 2.5<2c63>-.65 G<616e6e6f74206372656174652e>
+-2.5 E F1<5245464552454e4345>72 624 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e372e>108
+636 Q<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d>72 660 Q F1 -.219<4e41>72 676.8 S<4d45>.219 E F0<2472
+616e646f6d20ad2067656e6572617465207369676e65642072616e646f6d203332206269
+742076>108 688.8 Q<616c7565>-.25 E F1<53594e4f50534953>72 705.6 Q F0
+<66756e6374696f6e20696e7465>108 717.6 Q<676572202472616e646f6d3b>-.15 E
+<696e6f7574205b33313a305d20736565643b>115.2 729.6 Q
+<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 198.45<322e35203131>2.5 F 0 Cg EP
+%%Page: 12 12
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R<696e7465>115.2
+84 Q<67657220736565643b>-.15 E/F1 10.95/Times-Bold at 0 SF
+<4445534352495054494f4e>72 100.8 Q F0<4376>108 112.8 Q .866<657220757365
+7320676f6f64204253442072616e646f6d206e756d6265722067656e657261746f722074
+6861742070726f64756365732076>-.15 F .867<616c756573207769746820616c6d6f
+73742033322070736575646f2072616e646f6d20626974732c>-.25 F -.2<6275>108
+124.8 S 2.847<7474>.2 G .347<68652073657175656e6365206f662067656e657261
+746564206e756d6265722077696c6c2070726f6261626c79206e6f74206d617463682074
+6865206f6e652072657475726e6564206279206f746865722073696d756c61746f72732e>
+-2.847 F .346<496620746865>5.346 F .792
+<746865206f7074696f6e616c20736565642076>108 136.8 R .792
+<61726961626c65206c76>-.25 F .792<616c7565206973206769>-.25 F -.15<7665>
+-.25 G .793<6e2c20746865207374617274696e67206c6f636174696f6e20696e207468
+6520322a2a33322028616c6d6f73742920656c656d656e742073657175656e6365206f66>
+.15 F .658<70736575646f2072616e646f6d2076>108 148.8 R .657
+<616c75657320697320616c74657265642e>-.25 F .657<426563617573652074686520
+72616e646f6d2067656e657261746f72206f6e6c79207573656420333220626974206172
+6974686d6574696320746865206c6f>5.657 F 3.157<7762>-.25 G .657
+<6974206973>-3.157 F<756e72616e646f6d2e>108 160.8 Q F1
+<5245464552454e4345>72 177.6 Q F0
+<536565205031333634204c524d2073656374696f6e2031342e31302e312e>108 189.6
+Q<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d>72 213.6 Q F1 -.219<4e41>72 230.4 S<4d45>.219 E F0<247265
+61646d656d6220ad20726561642062696e617279206e756d6265722066726f6d206d656d
+6f72792073746f72656420696e208c6c65>108 242.4 Q
+<24726561646d656d6820ad2072656164206865>108 254.4 Q 2.5<786e>-.15 G
+<756d6265722066726f6d206d656d6f72792073746f72656420696e208c6c65>-2.5 E<
+2473726561646d656d6220ad20726561642062696e617279206e756d6265722066726f6d
+206d656d6f72792073746f72656420696e20737472696e67>108 266.4 Q
+<2473726561646d656d6820ad2072656164206865>108 278.4 Q 2.5<786e>-.15 G
+<756d6265722066726f6d206d656d6f72792073746f72656420696e20737472696e67>
+-2.5 E F1<53594e4f50534953>72 295.2 Q F0<24726561646d656d62285b8c6c6520
+6e616d655d2c205b6d656d6f7279206e616d655d2c205b73746172745f616464725d2c20
+5b8c6e6973685f616464725d293b>108 307.2 Q<24726561646d656d68285b8c6c6520
+6e616d655d2c205b6d656d6f7279206e616d655d2c205b73746172745f616464725d2c20
+5b8c6e6973685f616464725d293b>108 319.2 Q<2473726561646d656d62285b6d656d
+6f7279206e616d655d2c205b73746172745f616464726573735d2c205b8c6e6973685f61
+6464725d2c205b6c697374206f6620737472696e67735d293b>108 331.2 Q<73726561
+646d656d62285b6d656d6f7279206e616d655d2c205b73746172745f616464726573735d
+2c205b8c6e6973685f616464725d2c205b6c697374206f6620737472696e67735d293b>
+108 343.2 Q F1<4445534352495054494f4e>72 360 Q F0 .644
+<54686573652073797374656d207461736b7320726561642076>108 372 R .644<616c
+7565732066726f6d206569746865722061208c6c65206f72206120737472696e67202874
+68652024736d656d726561645b62685d20726f7574696e6573292e>-.25 F .645
+<54686520666f726d6174206f66>5.644 F .572<746865208c6c65206f722073747269
+6e672c2066726f6d20776869636820746f20746865206d656d6f7279206973208c6c6c65
+642c2069732061206c697374206f66207768697465207370616365207365706172617465
+642076>108 384 R 3.072<616c7565732e20546865>-.25 F -.25<7661>3.072 G
+<6c756573>.25 E 1.312
+<63616e20636f6e7461696e206469676974732c20275f272c207820616e64207a2062>
+108 396 R 1.312<7574206e6f2077696474682073706563698c636174696f6e2e>-.2 F
+-.15<466f>6.312 G 3.812<7224>.15 G 1.312
+<726561646d656d6220616e64202473726561646d656d62207468652076>-3.812 F
+<616c756573>-.25 E<6d7573742062652062696e617279>108 408 Q 5<2e46>-.65 G
+<6f722024726561646d656d6820616e64202473726561646d656d682c207468652076>
+-5.15 E<616c756573206d757374206265206865>-.25 E<782e>-.15 E .669<546865
+206261736963206d656d6f7279208c6c6c696e6720616c676f726974686d20697320746f
+207265616420612077>108 424.8 R .668<6f72642066726f6d20746865208c6c65206f
+7220737472696e672c208c6c6c207468652063757272656e74206d656d6f7279206c6f63
+612d>-.1 F .658<74696f6e2c207468656e20696e6372656d656e7420746865206d656d
+6f727920636f756e746572202864656372656d656e74206966205b73746172745f616464
+725d206973206c6172>108 436.8 R .659
+<676572207468616e205b8c6e6973685f616464725d292e>-.18 F .659
+<546865207370652d>5.659 F .643<6369616c2076>108 448.8 R .643
+<616c756520405b6865>-.25 F .642<7861646563696d616c206e756d6265725d20696e
+20746865208c6c65206f7220737472696e67206368616e67657320746865206e65>-.15
+F .642
+<7874206164647265737320746f20777269746520746865206d656d6f72792064617461>
+-.15 F -.1<776f>108 460.8 S 1.842<726420696e746f2e>.1 F 1.842
+<496620405b76>6.842 F 1.843<616c75655d20666f726d206368616e67657320746f20
+616e2061646472657373206f757473696465207468652072616e67652c206d656d6f7279
+208c6c6c696e672073746f70732e>-.25 F<4d656d6f7279>6.843 E 1.604<61646472
+657373206f757473696465207468652072616e6765206f72206f75747369646520746865
+206e756d626572206f6620656c656d656e747320696e20746865208c6c65206f72207374
+72696e6720617265206e6f74206368616e6765642e>108 472.8 R -.15<466f>6.604 G
+<72>.15 E .185<24736d656d7265616420726f7574696e65732c2061206c697374206f
+6620737472696e6773206973206c65>108 484.8 R -.05<6761>-.15 G 2.685
+<6c2e20546865>.05 F<6172>2.685 E .185
+<67756d656e7473206d6179206265206172626974726172792072756e2074696d652065>
+-.18 F .186<787072657373696f6e73207468617420617265>-.15 F<636f6e>108
+496.8 Q -.15<7665>-.4 G .111<7274656420746f20737472696e67732e>.15 F .111
+<546865206c697374206f6620737472696e677320697320636f6e636174656e61746564
+20696e746f206f6e65206c6f6e6720737472696e6720616e6420726561642065>5.111 F
+.11<786163746c792061732069662061208c6c652072656164>-.15 F .868
+<6f662074686520737472696e672068617070656e65642e>108 508.8 R .868<546865
+206c697374206f6620737472696e67732069732072657175697265642062656361757365
+2056>5.868 F .869<6572696c6f6720646f6573206e6f7420616c6c6f>-1.11 F 3.369
+<7773>-.25 G .869<7472696e677320746f207370616e206c696e65>-3.369 F
+<626f756e6461726965732e>108 520.8 Q -.15<466f>108 537.6 S 3.211<7224>.15
+G .711<726561646d656d6220616e642024726561646d656d6820746865205b8c6c655d
+206173206120737472696e672028706f737369626c7920616e2065>-3.211 F .71
+<787072657373696f6e207468617420697320636f6e>-.15 F -.15<7665>-.4 G .71
+<7274656420746f206120737472696e6729>.15 F 1.19<616e6420746865206d656d6f
+7279206964656e74698c6572206172652072657175697265642e>108 549.6 R -.15
+<466f>6.191 G 3.691<7224>.15 G 1.191<73726561646d656d6220616e6420247372
+6561646d656d6820746865206d656d6f7279206964656e74698c657220616e64206174>
+-3.691 F 1.069
+<6c65617374206f6e6520737472696e67206172652072657175697265642e>108 561.6
+R 1.068<546865205b73746172745f616464725d20616e64205b8c6e6973685f61646472
+5d20617265206f7074696f6e616c20286d75737420626520696e64696361746564206279
+202c2c20666f72>6.068 F .5
+<2473726561646d656d2066756e6374696f6e732920616e64206769>108 573.6 R .8
+-.15<76652074>-.25 H .5<6865208c727374206164647265737320696e20746865206d
+656d6f727920746f2075736520746f20777269746520746865208c727374206461746120
+77>.15 F .5<6f72642066726f6d20746865>-.1 F .33
+<8c6c65206f7220737472696e6720696e746f2e>108 585.6 R .33<496620746865205b
+8c6e6973685f616464725d2069732070726573656e742c207768656e2074686174206d65
+6d6f7279206164647265737320697320726561636865642c208c6c6c696e67206f662074
+6865206d656d2d>5.33 F 1<6f72792069732073746f707065642e>108 597.6 R 1
+<4974206973206c65>6 F -.05<6761>-.15 G 3.5<6c66>.05 G 1
+<6f72205b73746172745f616464726573735d20746f206265206c6172>-3.5 F 1.001<
+676572207468616e205b8c6e6973685f616464725d20696e207768696368206361736520
+746865206d656d6f7279206966>-.18 F .002
+<8c6c6c65642066726f6d206869676820746f206c6f>108 609.6 R 2.502<7777>-.25
+G 2.502<6f72642e204966>-2.602 F .002
+<6f6e6c79205b73746172745f616464726573735d206973206769>2.502 F -.15<7665>
+-.25 G .001<6e2c205b8c6e6973685f616464725d20697320746865206c617374202873
+65636f6e6429206d656d6f7279206465632d>.15 F
+<6c61726174696f6e2072616e67652e>108 621.6 Q
+<4966206f6e6c79205b8c6e6973685f616464725d206973206769>5 E -.15<7665>-.25
+G<6e2c205b73746172745f616464725d2069732074686520737461727420288c72737429
+206d656d6f7279206465636c61726174696f6e2072616e67652e>.15 E F1
+<5245464552454e4345>72 638.4 Q F0<536565205031333634204c524d207365637469
+6f6e7320616e642031342e322e3320616e642046>108 650.4 Q<2e31332e>-.8 E<2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d>72 674.4 Q F1 -.219<4e41>72 691.2 S<4d45>.219 E F0<247265736574
+20ad2072657365742074696d6520746f203020616e642072657374617274207468652073
+696d756c6174696f6e>108 703.2 Q<2472657365745f76>108 715.2 Q
+<616c756520ad2072657475726e732076>-.25 E<616c75652070617373656420627920
+6d6f737420726563656e742063616c6c206f6620247265736574>-.25 E<247265736574
+5f636f756e7420ad2072657475726e7320746865206e756d626572206f662074696d6573
+2024726573657420686173206265656e2065>108 727.2 Q -.15<7865>-.15 G
+<6375746564>.15 E<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 198.45<322e35203132>2.5 F 0 Cg EP
+%%Page: 13 13
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF<53594e4f50534953>72 84 Q F0
+<247265736574285b73746f705f76>108 96 Q<616c75655d2c205b72657365745f76>
+-.25 E<616c75655d2c205b646961676e6f73746963735f76>-.25 E<616c75655d293b>
+-.25 E<66756e6374696f6e20696e7465>108 108 Q<676572202472657365745f76>
+-.15 E<616c75653b>-.25 E<66756e6374696f6e20696e7465>108 120 Q
+<676572202472657365745f636f756e743b>-.15 E F1<4445534352495054494f4e>72
+136.8 Q F0 1.904<24726573657420616c6c6f>108 148.8 R 1.904<77732072657275
+6e6e696e6720612073696d756c6174696f6e2066726f6d2074696d65203020776974686f
+75742072652d7472616e736c6174696e672061206d6f64656c2e>-.25 F 1.904
+<49742063616e206861>6.904 F 2.204 -.15<76652075>-.2 H 4.405<7074>.15 G
+4.405<6f33>-4.405 G 2.359<6f7074696f6e616c206172>108 160.8 R 4.859
+<67756d656e74732e204966>-.18 F<5b73746f705f76>4.859 E 2.359
+<616c75655d206973206f6d6974746564206f722076>-.25 F 2.359
+<616c756520302c20696e74657261637469>-.25 F 2.659 -.15<7665206d>-.25 H
+2.358<6f646520697320656e74657265642061667465722072657365742e>.15 F<4966>
+7.358 E<5b72657365745f76>108 172.8 Q 1.011
+<616c75655d2069732070726573656e742c2069742069732070726573657276>-.25 F
+1.012<6564206163726f73732074686520726573657420616e642063616e206265207265
+616420776974682074686520746865202372657365745f76>-.15 F 1.012
+<616c75652073797374656d>-.25 F 1.517<66756e6374696f6e20616674657220636f
+6d706c6574696e67207468652072657365742e20546865206f7074696f6e616c205b6469
+61676e6f737469632076>108 184.8 R 1.517<616c75655d206172>-.25 F 1.517
+<67756d656e742064657465726d696e65732074686520616d6f756e74206f66>-.18 F
+.61<646961676e6f7374696320696e666f726d6174696f6e207072696e74656420616674
+65722072657365742062>108 196.8 R .61
+<7574207072696f7220746f207374617274696e67206167>-.2 F .61
+<61696e2061742074696d6520302e>-.05 F -1.11<5661>5.61 G .61
+<6c7565203020636175736573206e6f20696e666f726d612d>1.11 F .66<74696f6e20
+746f20626520656d69747465642c203120736f6d6520696e666f726d6174696f6e2c2061
+6e6420322069732065717569>108 208.8 R -.25<7661>-.25 G .659
+<6c656e7420746f20746865202b76>.25 F .659<6572626f7365206f7074696f6e2e>
+-.15 F .659<546865202472657365745f636f756e74207379732d>5.659 F<74656d20
+66756e6374696f6e2072657475726e7320746865206e756d626572206f662074696d6573
+20746865202472657365742073797374656d207461736b20686173206265656e2065>108
+220.8 Q -.15<7865>-.15 G
+<637574656420647572696e67207468652063757272656e742072756e2e>.15 E<4376>
+108 237.6 Q 2.862<657220616c736f20737570706f72747320746865203a7265736574
+205b6f7074696f6e2073746f705d20616464656420636f6d6d616e6420646562>-.15 F
+<7567676572>-.2 E 7.863<2e49>-.55 G 5.363<7464>-7.863 G 2.863
+<6f6573206e6f74206566>-5.363 F 2.863<666563742065697468657220746865>-.25
+F<5b72657365745f76>108 249.6 Q 1.286<616c75655d206f7220746865206e756d62
+6572206f662074696d65732024726573657420686173206265656e2063616c6c65642073
+6f206d6f64656c7320746861742072656c79206f6e202472657365742076>-.25 F
+1.286<616c7565732063616e206265>-.25 F<646562>108 261.6 Q 2.992
+<75676765642e20496e>-.2 F<4376>2.992 E<6572>-.15 E 2.992<2c61>-.4 G .492
+<6c6c203a20616464656420646562>-2.992 F .492
+<75676765722073657474696e67206172652070726573657276>-.2 F .492<65642065>
+-.15 F .492
+<786365707420627265616b20706f696e747320616e6420646973706c61792065>-.15 F
+<787072657373696f6e73>-.15 E 1.049<6172652064697361626c65642062>108
+273.6 R 1.048<7574206e6f742072656d6f>-.2 F -.15<7665>-.15 G 3.548
+<642e20456974686572>.15 F 1.048<74797065206f662072657365742072656d6f>
+3.548 F -.15<7665>-.15 G 3.548<7361>.15 G 1.048<6c6c2071756173692d636f6e
+74696e756f757320666f7263657320616e642061737369676e732e>-3.548 F 1.048
+<49662061>6.048 F .507<73696d756c6174696f6e2069732073746172746564207769
+7468202d7320616e64202d69205b8c6c655d2c202472657365742077696c6c2063617573
+652073696d756c6174696f6e20746f207374617274206f>108 285.6 R -.15<7665>
+-.15 G 3.008<7269>.15 G 3.008<6e69>-3.008 G<6e74657261637469>-3.008 E
+.808 -.15<7665206d>-.25 H .508<6f64652072756e2d>.15 F .213
+<6e696e6720746865208c72737420636f6d6d616e6420696e205b8c6c655d2e>108
+297.6 R<4376>5.212 E .212<65722077696c6c206e65>-.15 F -.15<7665>-.25 G
+2.712<7273>.15 G .212
+<746f7020756e6c657373202472657365745f636f756e7420697320636865636b>-2.712
+F .212<656420616e64207573656420746f20636175736520656e64>-.1 F
+<6f662073696d756c6174696f6e2e>108 309.6 Q F1<5245464552454e4345>72 326.4
+Q F0<536565205031333634204c524d2073656374696f6e2046>108 338.4 Q<2e372e>
+-.8 E F1<53454520414c534f>72 355.2 Q F0<53656520646562>108 367.2 Q<7567
+676572206f6e6c696e652068656c7020666f72203a726573657420616464656420646562>
+-.2 E<756767657220636f6d6d616e642e>-.2 E<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72 391.2 Q F1
+-.219<4e41>72 408 S<4d4520284e4f>.219 E 2.738<5459>-.438 G
+<455420494d504c454d454e54454429>-2.738 E F0<247361>108 420 Q .3 -.15
+<766520ad2073>-.2 H -2.25 -.2<61762065>.15 H<7374617465206f662073696d75
+6c6174696f6e20746f2061208c6c6520666f72206c617465722072657374617274>2.7 E
+<24696e637361>108 432 Q .3 -.15<766520ad2073>-.2 H -2.25 -.2<61762065>
+.15 H<6f6e6c79206368616e6765642076>2.7 E
+<616c7565732066726f6d206c61737420247361>-.25 E .3 -.15<76652074>-.2 H
+2.5<6f618c>.15 G<6c65>-2.5 E<247265737461727420ad2072657374617274207369
+6d756c6174696f6e2066726f6d206120247361>108 444 Q .3 -.15<7665208c>-.2 H
+<6c65>.15 E F1<53594e4f50534953>72 460.8 Q F0<247361>108 472.8 Q -.15
+<7665>-.2 G<285b8c6c655d293b>.15 E<24696e637361>108 484.8 Q -.15<7665>
+-.2 G<285b8c6c655d293b>.15 E<2472657374617274285b8c6c655d293b>108 496.8
+Q F1<4445534352495054494f4e>72 513.6 Q F0<4376>108 525.6 Q .379<65722064
+6f6573206e6f742079657420737570706f72742073696d756c6174696f6e20636865636b
+20706f696e74696e672074686174206973206e656564656420666f72206c6f6e67207369
+6d756c6174696f6e7320657370656369616c6c7920696e206361736573>-.15 F .312
+<776865726520706f>108 537.6 R .312<776572206f72206861726477>-.25 F .312
+<6172652066>-.1 F .312<61696c75726573206f63637572>-.1 F 5.312<2e43>-.55
+G -.15<7665>-5.312 G 2.812<7264>.15 G .312
+<657369676e207472616e736c6174696f6e2066726f6d20736f757263652069732066>
+-2.812 F .311<61737420656e6f7567682074686174206174206c6561737420736f>-.1
+F -.1<6661>108 549.6 S 3.525<726c>.1 G 1.025<6f6164696e6720746865206269
+6e61727920646174612073747275637475726520646f6573206e6f742072656475636520
+6c6f61642074696d652e>-3.525 F<24696e637361>6.026 E 1.326 -.15<76652077>
+-.2 H 1.026<696c6c2070726f6261626c79206e6f7420626520737570706f72746564>
+.15 F<73696e6365204376>108 561.6 Q<657220616c7265616479207061636b732074
+6f207468652062697420696e206f7264657220746f20737570706f72742069742c2065>
+-.15 E<787472612073696d756c6174696f6e2065>-.15 E -.15<7665>-.25 G
+<6e7420617265206e65656465642e>.15 E F1<5245464552454e4345>72 578.4 Q F0
+<536565205031333634204c524d2073656374696f6e2046>108 590.4 Q<2e372e>-.8 E
+<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d>72 614.4 Q F1 -.219<4e41>72 631.2 S<4d45>.219 E F0
+<247363616c6520ad20636f6e>108 643.2 Q -.15<7665>-.4 G
+<727420612074696d652076>.15 E
+<616c75652066726f6d206f6e65206d6f64756c6527>-.25 E 2.5<7374>-.55 G
+<696d65207363616c6520746f20616e6f74686572206173207265616c>-2.5 E F1
+<53594e4f50534953>72 660 Q F0
+<66756e6374696f6e207265616c20247363616c653b>108 672 Q
+<696e707574205b74696d652068696572617263686963616c2076>115.2 684 Q
+<616c756520617320656974686572207265616c206f72207265>-.25 E<675d3b>-.15 E
+F1<4445534352495054494f4e>72 700.8 Q F0<4769>108 712.8 Q -.15<7665>-.25
+G 2.762<6e6174>.15 G .262<696d652076>-2.762 F .262<616c756520617320616e
+2068696572617263686963616c207265666572656e63652c20636f6e>-.25 F -.15
+<7665>-.4 G .261<727420746f207468652074696d65207363616c6520696e20776869
+63682074686520247363616c652073797374656d207461736b206973>.15 F -.15
+<657865>108 724.8 S 2.5<63757465642e2055736167653a>.15 F 2.5<723d24>2.5
+G<7363616c6528746f702e69312e69322e7431293b>-2.5 E
+<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 198.45<322e35203133>2.5 F 0 Cg EP
+%%Page: 14 14
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF<5245464552454e4345>72 84 Q F0
+<536565205031333634204c524d2073656374696f6e2046>108 96 Q<2e372e>-.8 E<2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d>72 120 Q F1 -.219<4e41>72 136.8 S<4d45>.219 E F0<2473636f7065
+20ad206368616e67652073636f706520666f722075736520627920696e74657261637469>
+108 148.8 Q .3 -.15<76652063>-.25 H<6f6d6d616e6473>.15 E F1
+<53594e4f50534953>72 165.6 Q F0
+<2473636f7065285b6869657261726368616c206e616d655d293b>108 177.6 Q F1
+<4445534352495054494f4e>72 194.4 Q F0 .16
+<5573652073636f706520746f206368616e676520696e74657261637469>108 206.4 R
+.46 -.15<76652073>-.25 H .16<636f70652066726f6d2074686520646566>.15 F
+.16<61756c74208c72737420746f70206d6f64756c6520666f7220757365206166746572
+20656e746572696e672074686520696e74657261637469>-.1 F -.15<7665>-.25 G
+<646562>108 218.4 Q<7567676572>-.2 E 5.489<2e24>-.55 G .489
+<73636f7065206973206e6f742076>-5.489 F .488
+<6572792075736566756c20696e204376>-.15 F .488
+<657220626563617573652c20756e6c657373207475726e6564206f66>-.15 F 2.988
+<6662>-.25 G 2.988<796164>-2.988 G<6562>-2.988 E .488
+<7567676572203a73657420636f6d6d616e642c2075706f6e>-.2 F<646562>108 230.4
+Q 1.068<756767657220656e74727920286279202473746f70206f7220696e7465727275
+7074292074686520696e74657261637469>-.2 F 1.369 -.15<76652073>-.25 H
+1.069<636f70652069732073657420746f2074686520656e746572696e672073696d756c
+6174696f6e2073636f70652e>.15 F<416c736f>6.069 E<4376>108 242.4 Q .478
+<657220737570706f72747320616e2065>-.15 F .477
+<7874656e646564203a73636f706520636f6d6d616e64207468617420616c6c6f>-.15 F
+2.977<7772>-.25 G<656c617469>-2.977 E .777 -.15<7665206d>-.25 H -.15
+<6f7665>.15 G .477<6d656e74206265747765656e2073636f70657320616e64206765
+6e6572616c207265662d>.15 F<6572656e636520666f72206e65>108 254.4 Q 2.5
+<7773>-.25 G<636f7065732073756368206173206c696e65206e756d626572732e>-2.5
+E F1<5245464552454e4345>72 271.2 Q F0
+<536565205031333634204c524d2073656374696f6e2046>108 283.2 Q<2e372e>-.8 E
+F1<53454520414c534f>72 300 Q F0<5365652074686520616464656420646562>108
+312 Q
+<756767657220223a68656c70203a73636f7065222068656c702073637265656e2e>-.2
+E<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d>72 336 Q F1 -.219<4e41>72 352.8 S<4d45>.219 E F0<24736466
+5f616e6e6f7461746520ad20584c20636f6d70617469626c652073646620616e6e6f7461
+74696f6e2073797374656d207461736b>108 364.8 Q F1<53594e504f534953>72
+381.6 Q F0 1.078<247364665f616e6e6f74617465285b7265717569726564206e616d
+65206f6620736466208c6c655d2c205b6f7074696f6e616c20616e6e6f746174696f6e20
+73636f70655d2c205b6f7074696f6e616c2069676e6f726564202d206e6f20636f6e8c67
+208c6c6573>108 393.6 R .749<7965745d2c205b6f7074696f6e616c2069676e6f7265
+64202d206e6f20736570617261746520736466206c6f67208c6c655d2c205b6f7074696f
+6e616c206d696e7479706d617820534446206f>108 405.6 R -.15<7665>-.15 G .749
+<72726964655d2c205b6f7074696f6e616c2069676e6f726564202d>.15 F
+<6e6f207363616c652066>108 417.6 Q<6163746f725d2c205b6f7074696f6e616c2069
+676e6f726564202d206e6f207363616c6520747970655d293b>-.1 E F1
+<4445534352495054494f4e>72 434.4 Q F0 .056
+<53797374656d2066756e6374696f6e20616c7465726e617469>108 446.4 R .356
+-.15<76652074>-.25 H 2.556<6f2b>.15 G .057
+<7364665f616e6e6f7461746520636f6d6d616e64206c696e65206f7074696f6e2e>
+-2.556 F .057<46756e6374696f6e206964656e746963616c20746f20584c2024736466
+5f616e6e6f74617465>5.057 F 1.061<73797374656d207461736b20736f2056>108
+458.4 R 1.061<6572696c6f6720736f75726365207468617420696e20584c2063616e20
+62652072756e20776974686f7574206368616e676520696e204376>-1.11 F<6572>-.15
+E 6.06<2e24>-.55 G 1.06
+<7364665f616e6e6f746174652073797374656d207461736b>-6.06 F .532
+<616c736f20616c6c6f>108 470.4 R .533<777320636f6e646974696f6e616c206368
+6f696365206f662073646620616e6e6f746174696f6e208c6c652e>-.25 F .533
+<5468697264206f7074696f6e616c20636f6e8c6775726174696f6e208c6c65206172>
+5.533 F .533<67756d656e742069732069676e6f726564>-.18 F .045<626563617573
+6520436f6e8c6775726174696f6e7320617265206e6f742079657420737570706f727465
+6420696e204376>108 482.4 R<6572>-.15 E 5.045<2e4f>-.55 G .045
+<7074696f6e616c20666f75727468206172>-5.045 F .045
+<67756d656e74206e616d65206f66207365706172617465206c6f67208c6c65206973>
+-.18 F .669<69676e6f7265642062656361757365204376>108 494.4 R .669<657220
+77726974657320616c6c20736466206d6573736167657320746f206e6f726d616c206c6f
+67208c6c652e>-.15 F .67<53646620616e6e6f746174696f6e2068617320616c736f20
+6265656e206368616e67656420746f>5.67 F .389
+<6d6174636820584c20736f2073696d756c6174696f6e20636f6e74696e7565732065>
+108 506.4 R -.15<7665>-.25 G 2.888<6e69>.15 G 2.888<6653>-2.888 G .388
+<444620636f6e7461696e73206572726f72732e>-2.888 F .388<4173206d7563682061
+6e6e6f746174696f6e20617320706f737369626c65206973206d616465206966>5.388 F
+.541<53444620636f6e7461696e73206572726f72732e>108 518.4 R -.15<466f>
+5.541 G .541<75727468206f7074696f6e616c206d696e7479706d6178206f>.15 F
+-.15<7665>-.15 G .541<7272696465206172>.15 F .541
+<67756d656e7420697320737570706f727465642e>-.18 F<4c65>5.542 E -.05<6761>
+-.15 G 3.042<6c76>.05 G .542<616c75657320617265206f6e65206f66>-3.292 F
+1.225<4d494e494d554d2c205459504943414c2c206f72204d4158494d554d2e>108
+530.4 R 1.225<4f7074696f6e616c207369787468207363616c652066>6.225 F 1.225
+<6163746f7220616e64207365>-.1 F -.15<7665>-.25 G 1.224
+<6e7468207363616c652066>.15 F 1.224<6163746f722074797065206172>-.1 F
+<67752d>-.18 E<6d656e7473206172652069676e6f7265642e>108 542.4 Q
+<4578747261207363616c696e67206f66205344462076>5 E
+<616c75657320696e204376>-.25 E<6572206973206e6f7420737570706f727465642e>
+-.15 E F1<5245464552454e4345>72 559.2 Q F0<44652066>108 571.2 Q
+<6163746f207374616e64617264697a656420726f7574696e652e>-.1 E
+<53656520646f63756d656e7420666f7220616e>5 E 2.5<796f>-.15 G 2.5<6674>
+-2.5 G<6865206f746865722056>-2.5 E
+<6572696c6f672073696d756c61746f7273207375636820617320584c2e>-1.11 E<2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d>72 595.2 Q F1 -.219<4e41>72 612 S<4d45>.219 E F0<2473686f>108
+624 Q -.1<7761>-.25 G<6c6c696e7374616e636573>.1 E F1<53594e4f50534953>72
+640.8 Q F0<2473686f>108 652.8 Q -.1<7761>-.25 G
+<6c6c696e7374616e6365733b>.1 E F1<4445534352495054494f4e>72 669.6 Q F0
+-.15<466f>108 681.6 S 3.321<7265>.15 G -.15<7665>-3.571 G .821<7279206d
+6f64756c6520696e2064657369676e2c207072696e742069747320696e7374616e636520
+616e642067>.15 F .821<61746520757361676520696e20746162>-.05 F .821
+<756c617220666f726d2e>-.2 F .821
+<546869732073797374656d207461736b73207072696e7473206174>5.821 F<72756e20
+74696d652074686520696e7374616e63652064657369676e207374617469737469637320
+7461626c65207072696e74656420627920746865202b7072696e74737461747320636f6d
+6d616e64206172>108 693.6 Q<67756d656e742e>-.18 E
+<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 198.45<322e35203134>2.5 F 0 Cg EP
+%%Page: 15 15
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF<5245464552454e4345>72 84 Q F0
+<4e6f7420696e205031333634204c524d2062>108 96 Q
+<757420636f6d6d6f6e6c792070617274206f6620696e74657261637469>-.2 E .3
+-.15<76652065>-.25 H -.4<6e76>.15 G<69726f6e6d656e74732e>.4 E<2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d>72 120 Q<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d>72 144 Q F1 -.219<4e41>72 160.8 S<4d45>.219 E
+F0<2473686f>108 172.8 Q<7773636f70657320ad20646973706c6179206c697374206f
+6620616c6c2073636f70657320696e73696465207468652063757272656e742073636f70
+65>-.25 E F1<53594e4f50534953>72 189.6 Q F0<2473686f>108 201.6 Q
+<7773636f706573285b76>-.25 E<616c75655d293b>-.25 E F1
+<4445534352495054494f4e>72 218.4 Q F0 .048<4c69737420616c6c2073636f7065
+206f626a6563747320696e2063757272656e742073636f70652e>108 230.4 R .048
+<496620696e>5.048 F -.2<766f>-.4 G -.1<6b65>.2 G 2.548<6466>.1 G .048
+<726f6d20696e74657261637469>-2.548 F .348 -.15<7665206d>-.25 H .047<6f64
+652c207468652073636f7065206973207468652063757272656e7420696e746572616374
+69>.15 F -.15<7665>-.25 G 2.554<73636f70652e204966>108 242.4 R .055<6361
+6c6c656420647572696e672073696d756c6174696f6e2c2073636f706520697320637572
+72656e742073696d756c6174696f6e2073636f70652e>2.554 F .055<49662076>5.055
+F .055
+<616c75652069732070726573656e7420616e64206e6f6e207a65726f2c207072696e74>
+-.25 F<616c6c2073636f70657320696e206f722062656c6f>108 254.4 Q 2.5<7774>
+-.25 G<68652063757272656e742073636f706520746f206265206f757470757420746f
+207374646f757420616e6420746865206c6f67208c6c652e>-2.5 E F1
+<5245464552454e4345>72 271.2 Q F0
+<536565205031333634204c524d2073656374696f6e2046>108 283.2 Q<2e31312e>-.8
+E<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d>72 307.2 Q F1 -.219<4e41>72 324 S<4d45>.219 E F0
+<2473686f>108 336 Q<7776>-.25 E<61727320ad2073686f>-.25 E 2.5<7769>-.25
+G<6e666f726d6174696f6e2061626f75742076>-2.5 E<61726961626c6573>-.25 E
+<2473686f>108 348 Q<7776>-.25 E
+<61726961626c657320ad20616c7465726e617469>-.25 E .3 -.15<7665206e>-.25 H
+<616d6520666f72202473686f>.15 E<7776>-.25 E<617273207461736b>-.25 E F1
+<53594e4f50534953>72 364.8 Q F0<2473686f>108 376.8 Q<7776>-.25 E
+<617273285b6f7074696f6e616c206c697374206f662076>-.25 E
+<61726961626c65735d293b>-.25 E F1<4445534352495054494f4e>72 393.6 Q F0
+<446973706c617920696e666f726d6174696f6e2061626f75742076>108 405.6 Q 2.5
+<61726961626c65732e204966>-.25 F<6e6f206172>2.5 E
+<67756d656e74206973206769>-.18 E -.15<7665>-.25 G
+<6e2c20646973706c617920696e666f726d6174696f6e2061626f757420616c6c2076>
+.15 E<61726961626c657320696e20637572>-.25 E<2d>-.2 E .738
+<72656e742073636f70652e>108 417.6 R .738<49662061206c697374206f662076>
+5.738 F .738<61726961626c6573206973206769>-.25 F -.15<7665>-.25 G 3.238
+<6e64>.15 G .738
+<6973706c617920696e666f726d6174696f6e2061626f757420656163682076>-3.238 F
+3.238<61726961626c652e2048696572617263686963616c>-.25 F
+<7265666572656e636573>3.238 E .543<61726520616c6c6f>108 429.6 R 3.043
+<7765642e204376>-.25 F<657227>-.15 E 3.043<7361>-.55 G .543
+<6464656420696e74657261637469>-3.043 F .843 -.15<76652064>-.25 H<6562>
+.15 E .542<756767657220737570706f727473206164646974696f6e616c20636f6d6d
+616e647320666f722065>-.2 F .542<78616d696e696e672076>-.15 F .542
+<61726961626c652076>-.25 F<616c2d>-.25 E
+<75657320616e6420696e666f726d6174696f6e2e>108 441.6 Q
+<55736520746865203a68656c70206461746120646562>5 E
+<756767657220636f6d6d616e6420666f72206d6f726520696e666f726d6174696f6e2e>
+-.2 E F1<5245464552454e4345>72 458.4 Q F0
+<536565205031333634204c524d2073656374696f6e2046>108 470.4 Q<2e31322e>-.8
+E F1<53454520414c534f>72 487.2 Q F0
+<536565203a7072696e742c203a7768617469732c203a65>108 499.2 Q
+<78707269732c203a76>-.15 E<6172697320616464656420646562>-.25 E
+<756767657220636f6d6d616e64732e>-.2 E<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72 523.2 Q F1 -.219
+<4e41>72 540 S<4d4520284356455220455854454e53494f4e29>.219 E F0
+<24736e617073686f7420ad20646973706c61792061637469>108 552 Q .3 -.15
+<76652070>-.25 H
+<726f6365647572616c20746872656164207472656520616e642070656e64696e672065>
+.15 E -.15<7665>-.25 G<6e7473>.15 E F1<53594e4f50534953>72 568.8 Q F0
+<24736e617073686f743b>108 580.8 Q F1<4445534352495054494f4e>72 597.6 Q
+F0 .309<4d656368616e69736d20746f207072696e74206120736e617073686f74206f66
+2070726f6365647572616c206c6f636174696f6e2c2070656e64696e672065>108 609.6
+R -.15<7665>-.25 G .31<6e747320616e64207468726561642065>.15 F -.15<7865>
+-.15 G .31<637574696f6e207374617475732e>.15 F .31<496620696e746572>5.31
+F<2d>-.2 E<61637469>108 621.6 Q .312 -.15<76652064>-.25 H<6562>.15 E
+.012<75676765722069732064697361626c656420696e7465727275707420285e632920
+6361757365732024736e617073686f7420746f2062652063616c6c65642e>-.2 F .012
+<4d6f737420696e666f726d6174696f6e20616c736f2067656e657261746564206279>
+5.012 F 1.222<3a776865726520616464656420646562>108 633.6 R 1.222
+<756767657220636f6d6d616e642e>-.2 F 1.222<496620796f75207468696e6b20736f
+6d65207461736b73206f7220696e697469616c2f616c>6.222 F -.1<7761>-.1 G
+1.222<797320626c6f636b732073686f756c642062652061637469>.1 F 1.522 -.15
+<76652062>-.25 H<7574>-.05 E<746865>108 645.6 Q 3.308<7961>-.15 G .808
+<7265206e6f742c206f7220796f75207468696e6b20746865>-3.308 F 3.308<7973>
+-.15 G .807<686f756c64206861>-3.308 F 1.107 -.15<76652063>-.2 H .807
+<6f6d706c657465642062>.15 F .807<757420746865>-.2 F 3.307<7968>-.15 G
+-2.25 -.2<61762065>-3.307 H .807<6e6f742c207075742024736e617073686f7420
+696e20796f757220736f75726365206f72>3.507 F<696e>108 657.6 Q -.2<766f>-.4
+G .2 -.1<6b652066>.2 H<726f6d20696e74657261637469>.1 E .3 -.15<7665206d>
+-.25 H<6f646520746f20736565207468652070726f6365647572616c2061637469>.15
+E .3 -.15<76652074>-.25 H<7265652e>.15 E F1<5245464552454e4345>72 674.4
+Q F0<4e6f7420696e205031333634204c524d2e>108 686.4 Q<2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72
+710.4 Q<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 198.45<322e35203135>2.5 F 0 Cg EP
+%%Page: 16 16
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF -.219<4e41>72 84 S<4d45>.219 E F0
+<2473746f7020ad20656e74657220696e74657261637469>108 96 Q .3 -.15
+<76652064>-.25 H<6562>.15 E<7567676572>-.2 E F1<53594e4f50534953>72
+112.8 Q F0<2473746f703b>108 124.8 Q<2473746f70285b6d657373616765206c65>
+108 136.8 Q -.15<7665>-.25 G<6c5d293b>.15 E F1<4445534352495054494f4e>72
+153.6 Q F0 .365<456e74657220696e74657261637469>108 165.6 R .665 -.15
+<76652064>-.25 H<6562>.15 E .365
+<756767657220616e64206966205b6d657373616765206c65>-.2 F -.15<7665>-.25 G
+.366<6c5d2069732031206f7220322c207072696e742061206d6573736167652e>.15 F
+2.866<3170>5.366 G .366
+<72696e74732073696d756c6174696f6e2074696d6520616e642032>-2.866 F 1.405
+<7072696e7473202b76>108 177.6 R 1.405
+<6572626f73652073696d756c6174696f6e20737461746973746963732e>-.15 F
+<496e74657261637469>6.405 E 1.705 -.15<76652064>-.25 H<6562>.15 E 1.404<
+75676765722063616e20616c736f20626520656e7465726564206279207072657373696e
+6720696e74657272757074206b>-.2 F -.15<6579>-.1 G
+<28757375616c6c79205e6329206f722066726f6d20746865202d73206f7074696f6e2e>
+108 189.6 Q F1<5245464552454e4345>72 206.4 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e342e322e>
+108 218.4 Q<2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d>72 242.4 Q F1 -.219<4e41>72 259.2 S<4d45>.219 E
+F0<247374726f62652c20247374726f6265622c20247374726f6265682c20247374726f
+62656f20ad20777269746520666f726d61747465642076>108 271.2 Q<616c75652074
+6f207465726d696e616c20617420656e64206f662074696d6520736c6f74>-.25 E F1
+<53594e4f50534953>72 288 Q F0<247374726f6265285b696e7465726d6978>108 300
+Q<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E
+<247374726f62655b62686f5d285b696e7465726d6978>108 312 Q
+<6564206c697374206f6620666f726d617420737472696e677320616e642065>-.15 E
+<787072657373696f6e735d293b>-.15 E F1<4445534352495054494f4e>72 328.8 Q
+F0 1.082<53616d652061732024646973706c61792062>108 340.8 R 1.082
+<757420666f726d61747320616e64207772697465732076>-.2 F 1.082<616c75652061
+742074686520656e64206f662074696d652074696d6520736c6f74207261746865722074
+68616e207768656e2074686520247374726f6265>-.25 F .294
+<73746174656d656e742069732065>108 352.8 R -.15<7865>-.15 G 2.794
+<63757465642e2046>.15 F .293<6f726d6174206973206964656e746963616c20746f
+2024646973706c617920616e64205b62686f5d20737566>-.15 F .293
+<8c78206c6574746572206368616e67657320646566>-.25 F .293
+<61756c7420666f722065>-.1 F<787072657373696f6e>-.15 E .653
+<746861742061707065617273206f757473696465206f6620616e>108 364.8 R 3.153
+<7966>-.15 G .654<6f726d617420617320776974682024646973706c6179>-3.153 F
+5.654<2e4f>-.65 G .654<6e6520666f726d6174206973207772697474656e20746f20
+7374646f757420616e64206c6f67208c6c6520666f722065>-5.654 F -.15<7665>-.25
+G<7279>.15 E<247374726f62652065>108 376.8 Q -.15<7865>-.15 G
+<637574656420647572696e67207468652074696d6520736c6f742e>.15 E F1
+<5245464552454e4345>72 393.6 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e322e>108
+405.6 Q F1<53454520414c534f>72 422.4 Q F0
+<24667374726f62652069732073616d652065>108 434.4 Q<7863657074207772697465
+7320746f206d756c74692d6368616e6e656c208c6c652873292e>-.15 E<2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>
+72 458.4 Q F1 -.219<4e41>72 475.2 S<4d45>.219 E F0
+<2473757070726573735f77>108 487.2 Q<61726e73>-.1 E<24616c6c6f>108 499.2
+Q<775f77>-.25 E<61726e73>-.1 E F1<53594e4f50534953>72 516 Q F0
+<2473757070726573735f77>108 528 Q
+<61726e73285b636f6d6d6120736570617261746564206c697374206f662077>-.1 E
+<61726e696e67206f7220696e666f726d206e756d626572735d293b>-.1 E
+<24616c6c6f>108 540 Q<775f77>-.25 E
+<61726e73285b636f6d6d6120736570617261746564206c697374206f662077>-.1 E
+<61726e696e67206f7220696e666f726d206e756d626572735d293b>-.1 E F1
+<4445534352495054494f4e>72 556.8 Q F0 .383<497420697320706f737369626c65
+20746f2073757070726573732077726974696e67206f662072756e2074696d652077>108
+568.8 R .383<61726e696e6720616e6420696e666f726d206d65737361676573206279
+2063616c6c696e6720746865202473757070726573735f77>-.1 F<61726e73>-.1 E
+.181<73797374656d207461736b20776974682061206c697374206f66206e756d626572
+73207468617420617265207072696e746564207768656e20612077>108 580.8 R .182<
+61726e696e67206f7220696e666f726d206d657373616765206973207072696e7465642e>
+-.1 F<4d65737361676573>5.182 E 1.225<6f6620636c61737320455252>108 592.8
+R 1.225<4f5220616e642046>-.4 F -1.21 -1.11<41542041>-.74 H 3.725<4c45>
+1.11 G<5252>-3.725 E 1.225
+<4f522063616e206e6f7420626520737570707265737365642e>-.4 F 1.225
+<546865202b73757070726573735f77>6.225 F 1.225
+<61726e732b5b6c697374206f66202b20736570617261746564>-.1 F .238<6e756d62
+6572735d20636f6d6d616e64206c696e65206f7074696f6e20616c736f20737570707265
+73736573207072696e74696e67206f66206d6573736167657320616e6420697320746865
+206f6e6c792077>108 604.8 R .238<617920746f20737570706572732e>-.1 F
+<7472616e732d>5.239 E<6c6174696f6e2074696d65206d657373616765732e>108
+616.8 Q<24616c6c6f>5 E<775f77>-.25 E<61726e732072652d656e61626c65732070
+72696e74696e67206f662072756e2074696d65206d657373616765732e>-.1 E F1
+<5245464552454e4345>72 633.6 Q F0
+<54686573652073797374656d207461736b73206172652061204376>108 645.6 Q
+<65722065>-.15 E<7874656e73696f6e2e>-.15 E F1<53454520414c534f>72 662.4
+Q F0<536565202b73757070726573735f77>108 674.4 Q
+<61726e732b5b6e756d5d2b5b6e756d5d2b2e2e2e206f7074696f6e2e>-.1 E<2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d>72 698.4 Q<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 198.45<322e35203136>2.5 F 0 Cg EP
+%%Page: 17 17
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R/F1 10.95
+/Times-Bold at 0 SF -.219<4e41>72 84 S<4d45>.219 E F0
+<2473797374656d20ad2065>108 96 Q -.15<7865>-.15 G<63757465206f7065726174
+696e672073797374656d20636f6d6d616e642066726f6d2077697468696e204376>.15 E
+<6572>-.15 E F1<53594e4f50534953>72 112.8 Q F0
+<2473797374656d285b4f5320636f6d6d616e64206c696e655d293b>108 124.8 Q F1
+<4445534352495054494f4e>72 141.6 Q F0<4578>108 153.6 Q .659<656375746520
+736f6d65206f7065726174696e672073797374656d20636f6d6d616e6420737472696e67
+206279206d65616e73206f662061207368656c6c206573636170652e>-.15 F .658
+<2473797374656d3b2077697468206e6f206172>5.658 F<67756d656e7473>-.18 E
+.439<6f7220616e20656d707479206172>108 165.6 R .439
+<67756d656e742072756e7320616e20696e74657261637469>-.18 F .739 -.15
+<76652073>-.25 H .44<68656c6c206966206f6e6520697320737570706f7274656420
+666f72207468652073797374656d20796f75206172652072756e6e696e67204376>.15 F
+.44<6572206f6e2e>-.15 F 1.023<5468652073656d616e74696373206f662074686973
+207461736b20697320736c696768746c7920646966>108 177.6 R 1.022<666572656e
+74206f6e20556e697820626173656420616e64206e6f6e20556e69782073797374656d73
+2e>-.25 F 1.022<496620796f75206172652072756e6e696e67>6.022 F .2
+<77697468206d756c7469706c65207368656c6c2077696e646f>108 189.6 R .2
+<77732c2069742069732062657474657220746f2065>-.25 F -.15<7865>-.15 G .2
+<6375746520636f6d6d616e647320696e20616e6f746865722077696e646f>.15 F 2.7
+<7762>-.25 G .2<656361757365206120636f72652064756d702077696c6c>-2.7 F
+<70726f6261626c7920616c736f206361757365204376>108 201.6 Q
+<657220746f20636f72652064756d702e>-.15 E F1<5245464552454e4345>72 218.4
+Q F0<4e6f742064658c6e656420696e205031333634204c524d2062>108 230.4 Q
+<757420636f6d6d6f6e6c7920696d706c656d656e7465642e>-.2 E<2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72
+254.4 Q F1 -.219<4e41>72 271.2 S<4d45>.219 E F0
+<247465737424706c75736172>108 283.2 Q<677320ad2074657374204376>-.18 E
+<657220666f722065>-.15 E<78697374656e6365206f6620636f6d6d616e64206172>
+-.15 E<67756d656e74>-.18 E<247363616e24706c75736172>108 295.2 Q
+<677320ad207363616e204376>-.18 E<657220636f6d6d616e64206172>-.15 E
+<67756d656e747320746f206d61746368207072658c78>-.18 E F1
+<53594e4f50534953>72 312 Q F0
+<66756e6374696f6e205b33313a305d20247465737424706c75736172>108 324 Q
+<6773285b737472696e675d293b>-.18 E
+<66756e6374696f6e20247363616e24706c75736172>108 336 Q<6773285b706c757320
+6f7074696f6e207072658c7820617320737472696e675d2c205b737472696e67206c76>
+-.18 E<616c75655d293b>-.25 E F1<4445534352495054494f4e>72 352.8 Q F0
+<247465737424706c75736172>108 364.8 Q 1.747
+<67732072657475726e73203120696620746865206172>-.18 F 1.747
+<67756d656e7420617070656172656420696e20746865204376>-.18 F 1.747
+<657220636f6d6d616e6420696e>-.15 F -.2<766f>-.4 G 1.747
+<636174696f6e206172>.2 F 1.747<67756d656e74206c6973742e>-.18 F<546865>
+6.747 E .476<737472696e672065>108 376.8 R .476<787072657373696f6e206172>
+-.15 F .476<67756d656e74206d757374206e6f7420696e636c75646520746865206c65
+6164696e67202b20616e64206d757374206d6174636820616e20656e74697265206172>
+-.18 F 2.977<67756d656e742e204f6e6c79>-.18 F<4376>2.977 E<6572>-.15 E
+<636f6d6d616e64206172>108 388.8 Q<67756d656e74732074686174206265>-.18 E
+<67696e2077697468202b2061726520636865636b>-.15 E
+<656420666f722061206d617463682e>-.1 E .003
+<54686520247363616e24706c75736172>108 405.6 R .003
+<67732073797374656d2066756e6374696f6e2069732065717569>-.18 F -.25<7661>
+-.25 G .002
+<6c656e7420746f20504c492074665f206d635f7363616e5f706c75736172>.25 F .002
+<67732066756e6374696f6e2e>-.18 F .002<546865208c727374206172>5.002 F
+<67756d656e74>-.18 E .097<697320706c7573206f7074696f6e2028776974686f7574
+202b29207072658c7820617320737472696e672065>108 417.6 R 2.598
+<787072657373696f6e2e205365636f6e64>-.15 F<6172>2.598 E .098
+<67756d656e74206973206c76>-.18 F .098<616c75652065>-.25 F .098
+<787072657373696f6e20746861742069732061737369676e6564>-.15 F .918<746865
+2072656d61696e646572206f662074686520737472696e6720746f207468652072696768
+74206f6620746865206d617463686564207072658c782e>108 429.6 R .917<52657475
+726e732031206966206d6174636820616e642061737369676e207461696c2c2030206966
+206e6f>5.918 F .699<6d6174636820616e64206e6f2061737369676e2e>108 441.6 R
+.699<496e202d66208c6c65732c20746f6b>5.699 F .699<656e697a6174696f6e2069
+73206279207768697465207370616365206f6e6c7920736f208c6c653d7878206973206c
+65>-.1 F -.05<6761>-.15 G .699<6c2c2062>.05 F .699
+<757420646570656e64696e67206f6e>-.2 F .857<796f7572207368656c6c20746865
+206f7074696f6e206d6179206e65656420746f2062652071756f746564206966206769>
+108 453.6 R -.15<7665>-.25 G 3.356<6e6f>.15 G 3.356<6e74>-3.356 G .856
+<686520636f6d6d616e64206c696e652e>-3.356 F .856
+<5374616e6461726420247465737424706c75736172>5.856 F .856<6773207375702d>
+-.18 F<706f7274656420616e642072657475726e203120696620656e74697265207374
+72696e67206d61746368657320286e6f206c656164696e67202b2920656c736520302e>
+108 465.6 Q F1<5245464552454e4345>72 482.4 Q F0 .8<4e6f742064658c6e6564
+20696e205031333634204c524d2e20247465737424706c75736172>108 494.4 R .8
+<677320697320636f6d6d6f6e6c7920696d706c656d656e7465642e>-.18 F
+<247363616e24706c75736172>5.8 E .8<677320616c6c6f>-.18 F .8
+<777320757365206f6620504c49>-.25 F<74665f206d635f7363616e5f706c75736172>
+108 506.4 Q
+<677320776974686f7574206c696e6b696e6720696e2074686520504c492e>-.18 E<2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d>72 530.4 Q F1 -.219<4e41>72 547.2 S<4d45>.219 E F0<2474696d65
+20ad2072657475726e2074696d65207363616c656420746f206d6f64756c652061732036
+34206269742074696d652076>108 559.2 Q<616c7565>-.25 E 2.5
+<247265616c74696d6520ad>108 571.2 R<72657475726e2074696d65207363616c6564
+207363616c656420746f206d6f64756c65206173207265616c>2.5 E<247374696d6520
+ad2072657475726e2074696d65207363616c656420746f206d6f64756c65206173203332
+206269742076>108 583.2 Q<616c7565>-.25 E<247469636b7374696d6520ad207265
+7475726e2074696d6520696e20696e7465726e616c2073696d756c6174696f6e20746963
+6b73206173203634206269742076>108 595.2 Q<616c7565>-.25 E<24737469636b73
+74696d6520ad2072657475726e2074696d6520696e20696e7465726e616c2073696d756c
+6174696f6e207469636b73206173203332206269742076>108 607.2 Q<616c7565>-.25
+E F1<53594e4f50534953>72 624 Q F0
+<66756e6374696f6e2074696d65202474696d653b>108 636 Q
+<66756e6374696f6e207265616c20247265616c74696d653b>108 648 Q
+<66756e6374696f6e205b33313a305d20247374696d653b>108 660 Q
+<66756e6374696f6e2074696d6520247469636b7374696d653b>108 672 Q
+<66756e6374696f6e205b33313a305d2024737469636b7374696d653b>108 684 Q F1
+<4445534352495054494f4e>72 700.8 Q F0 .392<2474696d652072657475726e7320
+63757272656e742074696d652061732036342062697420756e7369676e65642074696d65
+2076>108 712.8 R 2.892<616c75652e204974>-.25 F .391<6973207363616c656420
+746f2074696d6520756e697473206f6620746865206d6f64756c6520746865202474696d
+65>2.891 F .515<7461736b20697320696e>108 724.8 R -.2<766f>-.4 G -.1
+<6b65>.2 G 3.015<6466>.1 G 3.015<726f6d2e20247265616c74696d65>-3.015 F
+.515<6973207468652073616d65206173202474696d652065>3.015 F .516
+<7863657074207468652076>-.15 F .516<616c75652072657475726e65642069732072
+65616c20616e6420746865202474696d65666f726d6174>-.25 F
+<507261676d61746963204320536f667477>72 768 Q 120.23
+<6172652052656c65617365>-.1 F 198.45<322e35203137>2.5 F 0 Cg EP
+%%Page: 18 18
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 373.28
+<5379737461736b73283129205379737461736b73283129>72 48 R .274
+<7363616c652076>108 84 R .274
+<616c75657320617265207573656420746f2064657465726d696e65207265616c2076>
+-.25 F .273<616c7565206672616374696f6e2061636375726163>-.25 F 4.073 -.65
+<792e2024>-.15 H .273
+<7374696d65206973207468652073616d65206173202474696d652065>.65 F .273
+<78636570742076>-.15 F .273<616c7565206973>-.25 F .079
+<7472756e636174656420746f20333220626974732e>108 96 R .079<247469636b7374
+696d652072657475726e732063757272656e742074696d6520696e20696e7465726e616c
+2073696d756c6174696f6e207469636b732028736d616c6c657374206d6f64756c652074
+696d65207363616c65>5.079 F 1.041
+<696e2064657369676e2920696e2061203634206269742076>108 108 R 3.541
+<616c75652e2024737469636b7374696d65>-.25 F 1.04
+<6973207468652073616d6520617320247469636b7374696d652065>3.541 F 1.04<78
+63657074206974206973207472756e636174656420746f208c7420696e20333220626974
+732e>-.15 F .01<53696d756c6174696f6e207469636b732061726520746865206d696e
+696d756d2074696d65207363616c6520756e697420696e20616e>108 120 R 2.511
+<796d>-.15 G .011<6f64756c6520616e64206973207468652076>-2.511 F .011
+<616c7565207573656420696e7465726e616c6c7920647572696e672073696d2d>-.25 F
+<756c6174696f6e2e>108 132 Q/F1 10.95/Times-Bold at 0 SF<5245464552454e4345>
+72 148.8 Q F0
+<44658c6e656420696e205031333634204c524d2073656374696f6e2031342e382e>108
+160.8 Q
+<247469636b7374696d6520616e642024737469636b7374696d6520617265204376>5 E
+<65722065>-.15 E<7874656e73696f6e732e>-.15 E<2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72 184.8 Q F1
+-.219<4e41>72 201.6 S<4d45>.219 E F0<247072696e7474696d657363616c6520ad
+20646973706c61792074696d6520756e697420616e6420707265636973696f6e20666f72
+2061206d6f64756c65>108 213.6 Q<2474696d65666f726d617420ad20737065636966
+7920666f726d617420666f72207468652025742024646973706c617920666f726d617420
+73706563698c6572>108 225.6 Q F1<53594e4f50534953>72 242.4 Q F0<24707269
+6e7474696d657363616c65285b68696572617263686963616c5f6e616d655d293b>108
+254.4 Q<2474696d65666f726d6174285b756e6974735f6e756d6265725d2c205b707265
+636973696f6e206e756d6265725d2c205b737566>108 266.4 Q
+<8c785f737472696e675d2c205b6d696e696d756d5f8c656c645f77696474685d293b>
+-.25 E F1<4445534352495054494f4e>72 283.2 Q F0 .07<54686520247072696e74
+74696d657363616c652073797374656d207461736b20646973706c6179732074696d6520
+756e697420616e6420707265636973696f6e20666f72206120706172746963756c617220
+6d6f64756c652e>108 295.2 R .07<496620746865206172>5.07 F .07
+<67756d656e74206973>-.18 F<6f6d69747465642c2074686520696e666f726d617469
+6f6e20666f72207468652063757272656e74206d6f64756c65206973207072696e746564
+2e>108 307.2 Q<546865202474696d65666f726d61742073797374656d207461736b20
+736574732074686520666f726d617420666f722074686520257420666f726d6174207370
+6563698c6572>108 324 Q<2e>-.55 E F1<5245464552454e4345>72 340.8 Q F0<53
+6565205031333634204c524d2073656374696f6e2031342e3320616e6420746865206074
+696d657363616c652064697265637469>108 352.8 Q .3 -.15<76652064>-.25 H
+<697363757373696f6e2073656374696f6e2031362e372e>.15 E<2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
+2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d>72
+376.8 Q F1<54524144454d41524b5320414e4420434f50595249474854>72 393.6 Q
+F0 -1.11<5665>108 405.6 S<72696c6f6720697320612054>1.11 E<726164656d6172
+6b206f6620436164656e63652044657369676e2053797374656d73204c6963656e736564
+20746f204f70656e2056>-.35 E<6572696c6f6720496e7465726e6174696f6e616c2e>
+-1.11 E<4376>108 417.6 Q<657220616e642056636d70206172652054>-.15 E
+<726164656d61726b73206f6620507261676d61746963204320536f667477>-.35 E
+<61726520436f72706f726174696f6e2e>-.1 E<436f70>108 441.6 Q<797269676874
+2028632920313939312d3230303220507261676d61746963204320536f667477>-.1 E
+2.5<6172652e20416c6c>-.1 F<52696768747320526573657276>2.5 E<65642e>-.15
+E<5468697320646f63756d656e7420636f6e7461696e7320636f6e8c64656e7469616c20
+616e642070726f707269657461727920696e666f726d6174696f6e>108 453.6 Q
+<62656c6f6e67696e6720746f20507261676d61746963204320536f667477>108 465.6
+Q<61726520436f72702e>-.1 E<507261676d61746963204320536f667477>72 768 Q
+120.23<6172652052656c65617365>-.1 F 198.45<322e35203138>2.5 F 0 Cg EP
+%%Trailer
+end
+%%EOF
diff --git a/objs/makefile.dll b/objs/makefile.dll
new file mode 100644
index 0000000..36cda49
--- /dev/null
+++ b/objs/makefile.dll
@@ -0,0 +1,24 @@
+# Make file for creating a CVER DLL and create
+# an executable using the DLL
+#
+
+SHELL=/bin/bash
+
+CC=gcc
+
+DLLOBJS=cver.o v_acc.o v_cnv.o v_dbg.o v_dbg2.o v_del.o \
+			v_ex.o v_ex2.o v_ex3.o v_ex4.o v_fx.o v_fx2.o \
+			v_fx3.o v_ms.o v_prp.o v_prp2.o v_sdf.o v_sim.o \
+			v_src.o v_src2.o v_src3.o v_tf.o v_trch.o \
+			v_vpi.o v_vpi2.o v_vpi3.o
+
+EXEOBJS=dig_main.o
+
+
+dll: $(DLLOBJS)
+	$(CC) -shared -o libcver.dll -Wl,--out-implib=libcver.dll.a \
+		-Wl,--export-all -Wl,--enable-auto-image-base \
+		-Wl,--export-dynamic -Wl,--output-def=libcver.def $(DLLOBJS)
+
+exe: $(EXEOBJS)
+	$(CC) -o cver.exe $(EXEOBJS) -L./ -lcver -lm -lcygwin
diff --git a/pli_incs/acc_user.h b/pli_incs/acc_user.h
new file mode 100644
index 0000000..b00ca27
--- /dev/null
+++ b/pli_incs/acc_user.h
@@ -0,0 +1,538 @@
+/******************************************************************************
+* acc_user.h
+*
+* IEEE 1364 1995 Verilog HDL Programming Language Interface (PLI).
+*
+* This file contains the constant definitions, structure definitions, and
+* routine declarations used by the Verilog PLI procedural interface TF 
+* task/function routines. 
+*
+* The file should be included with all C routines that use the PLI ACC
+* routines.
+******************************************************************************/
+#ifndef ACC_USER_H
+#define ACC_USER_H
+
+/*---------------------------------------------------------------------------*/
+/*------------------------------- definitions -------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+/*----------------------------- general defines -----------------------------*/
+typedef int    *HANDLE;
+typedef int    *handle;
+
+#define bool   int
+#define true   1
+#define TRUE   1
+#define false  0
+#define FALSE  0
+
+#define glboal extern
+#define exfunc
+#define local  static
+#define null   0L
+
+/*------------------------------- object types ------------------------------*/
+#define    accModule               20
+#define    accScope                21
+#define    accNet                  25
+#define    accReg                  30
+#define    accRegister             accReg
+#define    accPort                 35
+#define    accTerminal             45
+#define    accInputTerminal        46
+#define    accOutputTerminal       47
+#define    accInoutTerminal        48
+#define    accCombPrim            140
+#define    accSeqPrim             142
+#define    accAndGate             144
+#define    accNandGate            146
+#define    accNorGate             148
+#define    accOrGate              150
+#define    accXorGate             152
+#define    accXnorGate            154
+#define    accBufGate             156
+#define    accNotGate             158
+#define    accBufif0Gate          160
+#define    accBufif1Gate          162
+#define    accNotif0Gate          164
+#define    accNotif1Gate          166
+#define    accNmosGate            168
+#define    accPmosGate            170
+#define    accCmosGate            172
+#define    accRnmosGate           174
+#define    accRpmosGate           176
+#define    accRcmosGate           178
+#define    accRtranGate           180
+#define    accRtranif0Gate        182
+#define    accRtranif1Gate        184
+#define    accTranGate            186
+#define    accTranif0Gate         188
+#define    accTranif1Gate         190
+#define    accPullupGate          192
+#define    accPulldownGate        194
+#define    accIntegerParam        200
+#define    accIntParam            accIntegerParam
+#define    accRealParam           202
+#define    accStringParam         204
+#define    accTchk                208
+#define    accPrimitive           210
+#define    accBit                 212
+#define    accPortBit             214
+#define    accNetBit              216
+#define    accRegBit              218
+#define    accParameter           220
+#define    accSpecparam           222
+#define    accTopModule           224
+#define    accModuleInstance      226
+#define    accCellInstance        228
+#define    accModPath             230
+#define    accWirePath            232
+#define    accInterModPath        236
+#define    accScalarPort          250
+#define    accBitSelectPort       252
+#define    accPartSelectPort      254
+#define    accVectorPort          256
+#define    accConcatPort          258
+#define    accWire                260
+#define    accWand                261
+#define    accWor                 262
+#define    accTri                 263
+#define    accTriand              264
+#define    accTrior               265
+#define    accTri0                266
+#define    accTri1                267
+#define    accTrireg              268
+#define    accSupply0             269
+#define    accSupply1             270
+#define    accNamedEvent          280
+#define    accEventVar            accNamedEvent
+#define    accIntegerVar          281
+#define    accIntVar              281
+#define    accRealVar             282
+#define    accTimeVar             283
+#define    accScalar              300
+#define    accVector              302
+#define    accCollapsedNet        304
+#define    accExpandedVector      306
+#define    accUnExpandedVector    307
+#define    accProtected           308
+#define    accSetup               366
+#define    accHold                367
+#define    accWidth               368
+#define    accPeriod              369
+#define    accRecovery            370
+#define    accSkew                371
+#define    accNochange            376
+#define    accNoChange            accNochange
+#define    accSetuphold           377
+#define    accInput               402
+#define    accOutput              404
+#define    accInout               406
+#define    accMixedIo             407
+#define    accPositive            408
+#define    accNegative            410
+#define    accUnknown             412
+#define    accPathTerminal        420
+#define    accPathInput           422
+#define    accPathOutput          424
+#define    accDataPath            426
+#define    accTchkTerminal        428
+#define    accBitSelect           500
+#define    accPartSelect          502
+#define    accTask                504
+#define    accFunction            506
+#define    accStatement           508
+#define    accTaskCall            510
+#define    accFunctionCall        512
+#define    accSystemTask          514
+#define    accSystemFunction      516
+#define    accSystemRealFunction  518
+#define    accUserTask            520
+#define    accUserFunction        522
+#define    accUserRealFunction    524
+#define    accNamedBeginStat      560
+#define    accNamedForkStat       564
+#define    accConstant            600
+#define    accConcat              610
+#define    accOperator            620
+#define    accMinTypMax           696
+#define    accModPathHasIfnone    715
+
+/*------------------ parameter values for acc_configure() -------------------*/
+#define    accPathDelayCount        1
+#define    accPathDelimStr          2
+#define    accDisplayErrors         3
+#define    accDefaultAttr0          4
+#define    accToHiZDelay            5
+#define    accEnableArgs            6
+#define    accDisplayWarnings       8
+#define    accDevelopmentVersion   11
+#define    accMapToMipd            17
+#define    accMinTypMaxDelays      19
+
+/*------------ edge information used by acc_handle_tchk(), etc.  ------------*/
+#define accNoedge                   0
+#define accNoEdge                   0
+#define accEdge01                   1
+#define accEdge10                   2
+#define accEdge0x                   4
+#define accEdgex1                   8
+#define accEdge1x                  16
+#define accEdgex0                  32
+#define accPosedge                 13
+#define accPosEdge                 accPosedge
+#define accNegedge                 50
+#define accNegEdge                 accNegedge
+
+/*------------------------------- delay modes -------------------------------*/
+#define accDelayModeNone            0
+#define accDelayModePath            1
+#define accDelayModeDistrib         2
+#define accDelayModeUnit            3
+#define accDelayModeZero            4
+#define accDelayModeVeritime        5
+
+/*------------ values for type field in t_setval_delay structure ------------*/
+#define accNoDelay                  0
+#define accInertialDelay            1
+#define accTransportDelay           2
+#define accPureTransportDelay       3
+#define accForceFlag                4
+#define accReleaseFlag              5
+#define accAssignFlag               6
+#define accDeassignFlag             7
+
+/*------------ values for type field in t_setval_value structure ------------*/
+#define accBinStrVal                1
+#define accOctStrVal                2
+#define accDecStrVal                3
+#define accHexStrVal                4
+#define accScalarVal                5
+#define accIntVal                   6
+#define accRealVal                  7
+#define accStringVal                8
+#define accVectorVal               10
+
+/*------------------------------ scalar values ------------------------------*/
+#define acc0                        0
+#define acc1                        1
+#define accX                        2
+#define accZ                        3
+
+/*---------------------------- VCL scalar values ----------------------------*/
+#define vcl0                        acc0
+#define vcl1                        acc1
+#define vclX                        accX
+#define vclZ                        accZ
+
+/*----------- values for vc_reason field in t_vc_record structure -----------*/
+#define logic_value_change          1
+#define strength_value_change       2
+#define real_value_change           3
+#define vector_value_change         4
+#define event_value_change          5
+#define integer_value_change        6
+#define time_value_change           7
+#define sregister_value_change      8
+#define vregister_value_change      9
+#define realtime_value_change      10
+
+
+/*--------------------------- VCL strength values ---------------------------*/
+#define vclSupply                   7
+#define vclStrong                   6
+#define vclPull                     5
+#define vclLarge                    4
+#define vclWeak                     3
+#define vclMedium                   2
+#define vclSmall                    1
+#define vclHighZ                    0
+
+
+/*----------------------- flags used with acc_vcl_add -----------------------*/
+#define vcl_verilog_logic           2
+#define VCL_VERILOG_LOGIC           vcl_verilog_logic
+#define vcl_verilog_strength        3
+#define VCL_VERILOG_STRENGTH        vcl_verilog_strength
+
+
+/*---------------------- flags used with acc_vcl_delete ---------------------*/
+#define vcl_verilog                 vcl_verilog_logic
+#define VCL_VERILOG                 vcl_verilog
+
+
+/*---------- values for the type field in the t_acc_time structure --------- */
+#define accTime                     1
+#define accSimTime                  2
+#define accRealTime                 3
+
+
+/*------------------------------ product types ------------------------------*/
+#define accSimulator                1
+#define accTimingAnalyzer           2
+#define accFaultSimulator           3
+#define accOther                    4
+
+/*---------------------------------------------------------------------------*/
+/*---------------------- global variable definitions ------------------------*/
+/*---------------------------------------------------------------------------*/
+extern bool acc_error_flag;
+typedef int (*consumer_function)();
+
+/*---------------------------------------------------------------------------*/
+/*-------------------------- structure definitions --------------------------*/
+/*---------------------------------------------------------------------------*/
+
+/*---------------- data structure used with acc_set_value() -----------------*/
+typedef struct t_acc_time
+{
+  int type;
+  int low, 
+      high;
+  double real;
+} s_acc_time, *p_acc_time;
+
+/*---------------- data structure used with acc_set_value() -----------------*/
+typedef struct t_setval_delay
+{
+  s_acc_time time;
+  int model;
+} s_setval_delay, *p_setval_delay;
+
+/*-------------------- data structure of vector values ----------------------*/
+typedef struct t_acc_vecval
+{
+  int aval;
+  int bval;                                    
+} s_acc_vecval, *p_acc_vecval;
+
+/*----- data structure used with acc_set_value() and acc_fetch_value() ------*/
+typedef struct t_setval_value
+{
+ int format;
+ union
+   {
+    char *str;
+    int scalar;
+    int integer;
+    double real;
+    p_acc_vecval vector;
+   } value;
+} s_setval_value, *p_setval_value, s_acc_value, *p_acc_value;
+
+/*---------------------- structure for VCL strengths ------------------------*/
+typedef struct t_strengths
+{
+  unsigned char logic_value;
+  unsigned char strength1;
+  unsigned char strength2;
+} s_strengths, *p_strengths;
+
+/*-------------- structure passed to callback routine for VCL ---------------*/
+typedef struct t_vc_record
+{
+ int vc_reason;
+ int vc_hightime;
+ int vc_lowtime;
+ char *user_data;
+ union
+   {
+    unsigned char logic_value;
+    double real_value;
+    handle vector_handle;
+    s_strengths strengths_s;
+   } out_value;
+} s_vc_record, *p_vc_record;
+
+/*------------ structure used with acc_fetch_location() ---------------------*/
+typedef struct t_location
+{
+ int line_no;
+ char *filename;
+} s_location, *p_location;
+
+/*--------- structure used with acc_fetch_timescale_info() routine ----------*/
+typedef struct t_timescale_info
+{
+ short unit;
+ short precision;
+} s_timescale_info, *p_timescale_info;
+
+/*---------------------------------------------------------------------------*/
+/*--------------------------- routine definitions ---------------------------*/
+/*---------------------------------------------------------------------------*/
+#if defined(__STDC__) || defined(__cplusplus)
+
+#ifndef PROTO_PARAMS
+#define PROTO_PARAMS(params) params
+#define DEFINED_PROTO_PARAMS
+#endif
+#ifndef EXTERN
+#define EXTERN
+#define DEFINED_EXTERN
+#endif
+
+#else
+
+#ifndef PROTO_PARAMS
+#define PROTO_PARAMS(params) (/* nothing */)
+#define DEFINED_PROTO_PARAMS
+#endif
+#ifndef EXTERN
+#define EXTERN extern
+#define DEFINED_EXTERN
+#endif
+
+#endif /* __STDC__ */
+
+EXTERN bool    acc_append_delays PROTO_PARAMS((handle object, ...));
+EXTERN bool    acc_append_pulsere PROTO_PARAMS((handle object, double val1,
+                   double val1x, ...));
+EXTERN void    acc_close PROTO_PARAMS((void));
+EXTERN handle *acc_collect PROTO_PARAMS((handle (*p_next_routine)(),
+                   handle scope_object, int *aof_count));
+EXTERN bool    acc_compare_handles PROTO_PARAMS((handle h1, handle h2));
+EXTERN int     acc_count PROTO_PARAMS((handle (*next_function)(),
+                   handle object_handle));
+EXTERN bool    acc_configure PROTO_PARAMS((int item, char *value));
+EXTERN int     acc_fetch_argc PROTO_PARAMS((void));
+EXTERN void  **acc_fetch_argv PROTO_PARAMS((void));
+EXTERN double  acc_fetch_attribute PROTO_PARAMS((handle object, ...));
+EXTERN int     acc_fetch_attribute_int PROTO_PARAMS((handle object, ...));
+EXTERN char   *acc_fetch_attribute_str PROTO_PARAMS((handle object, ...));
+EXTERN char   *acc_fetch_defname PROTO_PARAMS((handle object_handle));
+EXTERN int     acc_fetch_delay_mode PROTO_PARAMS((handle object_p));
+EXTERN bool    acc_fetch_delays PROTO_PARAMS((handle object, ...));
+EXTERN int     acc_fetch_direction PROTO_PARAMS((handle object_handle));
+EXTERN int     acc_fetch_edge PROTO_PARAMS((handle acc_object));
+EXTERN char   *acc_fetch_fullname PROTO_PARAMS((handle object_handle));
+EXTERN int     acc_fetch_fulltype PROTO_PARAMS((handle object_h));
+EXTERN int     acc_fetch_index PROTO_PARAMS((handle object_handle));
+EXTERN double  acc_fetch_itfarg PROTO_PARAMS((int n, handle tfinst));
+EXTERN int     acc_fetch_itfarg_int PROTO_PARAMS((int n, handle tfinst));
+EXTERN char   *acc_fetch_itfarg_str PROTO_PARAMS((int n, handle tfinst));
+EXTERN int     acc_fetch_location PROTO_PARAMS((p_location location_p,
+                   handle object));
+EXTERN char   *acc_fetch_name PROTO_PARAMS((handle object_handle));
+EXTERN int     acc_fetch_paramtype PROTO_PARAMS((handle param_p));
+EXTERN double  acc_fetch_paramval PROTO_PARAMS((handle param));
+EXTERN int     acc_fetch_polarity PROTO_PARAMS((handle path));
+EXTERN int     acc_fetch_precision PROTO_PARAMS((void));
+EXTERN bool    acc_fetch_pulsere PROTO_PARAMS((handle path_p, double *val1r,
+                   double *val1e, ...));
+EXTERN int     acc_fetch_range PROTO_PARAMS((handle node, int *msb,
+                   int *lsb));
+EXTERN int     acc_fetch_size PROTO_PARAMS((handle obj_h));
+EXTERN double  acc_fetch_tfarg PROTO_PARAMS((int n));
+EXTERN int     acc_fetch_tfarg_int PROTO_PARAMS((int n));
+EXTERN char   *acc_fetch_tfarg_str PROTO_PARAMS((int n));
+EXTERN void    acc_fetch_timescale_info PROTO_PARAMS((handle obj,
+                   p_timescale_info aof_timescale_info));
+EXTERN int     acc_fetch_type PROTO_PARAMS((handle object_handle));
+EXTERN char   *acc_fetch_type_str PROTO_PARAMS((int type));
+EXTERN char   *acc_fetch_value PROTO_PARAMS((handle object_handle,
+                   char *format_str, p_acc_value acc_value_p));
+EXTERN void    acc_free PROTO_PARAMS((handle *array_ptr));
+EXTERN handle  acc_handle_by_name PROTO_PARAMS((char *inst_name,
+                   handle scope_p));
+EXTERN handle  acc_handle_condition PROTO_PARAMS((handle obj));
+EXTERN handle  acc_handle_conn PROTO_PARAMS((handle term_p));
+EXTERN handle  acc_handle_datapath PROTO_PARAMS((handle path));
+EXTERN handle  acc_handle_hiconn PROTO_PARAMS((handle port_ref));
+EXTERN handle  acc_handle_interactive_scope PROTO_PARAMS((void));
+EXTERN handle  acc_handle_itfarg PROTO_PARAMS((int n, handle tfinst));
+EXTERN handle  acc_handle_loconn PROTO_PARAMS((handle port_ref));
+EXTERN handle  acc_handle_modpath PROTO_PARAMS((handle mod_p,
+                   char *pathin_name, char *pathout_name, ...));
+EXTERN handle  acc_handle_notifier PROTO_PARAMS((handle tchk));
+EXTERN handle  acc_handle_object PROTO_PARAMS((char *object_name));
+EXTERN handle  acc_handle_parent PROTO_PARAMS((handle object_p));
+EXTERN handle  acc_handle_path PROTO_PARAMS((handle source,
+                   handle destination));
+EXTERN handle  acc_handle_pathin PROTO_PARAMS((handle path_p));
+EXTERN handle  acc_handle_pathout PROTO_PARAMS((handle path_p));
+EXTERN handle  acc_handle_port PROTO_PARAMS((handle mod_handle,
+                   int port_num));
+EXTERN handle  acc_handle_scope PROTO_PARAMS((handle object));
+EXTERN handle  acc_handle_simulated_net PROTO_PARAMS((handle net_h));
+EXTERN handle  acc_handle_tchk PROTO_PARAMS((handle mod_p, int tchk_type,
+                   char *arg1_conn_name, int arg1_edgetype, ...));
+EXTERN handle  acc_handle_tchkarg1 PROTO_PARAMS((handle tchk));
+EXTERN handle  acc_handle_tchkarg2 PROTO_PARAMS((handle tchk));
+EXTERN handle  acc_handle_terminal PROTO_PARAMS((handle gate_handle,
+                   int terminal_index));
+EXTERN handle  acc_handle_tfarg PROTO_PARAMS((int n));
+EXTERN handle  acc_handle_tfinst PROTO_PARAMS((void));
+EXTERN bool    acc_initialize PROTO_PARAMS((void));
+EXTERN handle  acc_next PROTO_PARAMS((int *type_list, handle h_scope,
+                   handle h_object));
+EXTERN handle  acc_next_bit PROTO_PARAMS((handle vector, handle bit));
+EXTERN handle  acc_next_cell PROTO_PARAMS((handle scope, handle cell));
+EXTERN handle  acc_next_cell_load PROTO_PARAMS((handle net_handle,
+                   handle load));
+EXTERN handle  acc_next_child PROTO_PARAMS((handle mod_handle, handle child));
+EXTERN handle  acc_next_driver PROTO_PARAMS((handle net, handle driver));
+EXTERN handle  acc_next_hiconn PROTO_PARAMS((handle port, handle hiconn));
+EXTERN handle  acc_next_input PROTO_PARAMS((handle path, handle pathin));
+EXTERN handle  acc_next_load PROTO_PARAMS((handle net, handle load));
+EXTERN handle  acc_next_loconn PROTO_PARAMS((handle port, handle loconn));
+EXTERN handle  acc_next_modpath PROTO_PARAMS((handle mod_p, handle path));
+EXTERN handle  acc_next_net PROTO_PARAMS((handle mod_handle, handle net));
+EXTERN handle  acc_next_output PROTO_PARAMS((handle path, handle pathout));
+EXTERN handle  acc_next_parameter PROTO_PARAMS((handle module_p,
+                   handle param));
+EXTERN handle  acc_next_port PROTO_PARAMS((handle ref_obj_p, handle port));
+EXTERN handle  acc_next_portout PROTO_PARAMS((handle mod_p, handle port));
+EXTERN handle  acc_next_primitive PROTO_PARAMS((handle mod_handle,
+                   handle prim));
+EXTERN handle  acc_next_scope PROTO_PARAMS((handle ref_scope_p,
+                   handle scope));
+EXTERN handle  acc_next_specparam PROTO_PARAMS((handle module_p,
+                   handle sparam));
+EXTERN handle  acc_next_tchk PROTO_PARAMS((handle mod_p, handle tchk));
+EXTERN handle  acc_next_terminal PROTO_PARAMS((handle gate_handle,
+                   handle term));
+EXTERN handle  acc_next_topmod PROTO_PARAMS((handle topmod));
+EXTERN bool    acc_object_of_type PROTO_PARAMS((handle object, int type));
+EXTERN bool    acc_object_in_typelist PROTO_PARAMS((handle object,
+                   int *type_list));
+EXTERN int     acc_product_type PROTO_PARAMS((void));
+EXTERN char   *acc_product_version PROTO_PARAMS((void));
+EXTERN int     acc_release_object PROTO_PARAMS((handle obj));
+EXTERN bool    acc_replace_delays PROTO_PARAMS((handle object, ...));
+EXTERN bool    acc_replace_pulsere PROTO_PARAMS((handle object, double val1r,
+                   double val1x, ...));
+EXTERN void    acc_reset_buffer PROTO_PARAMS((void));
+EXTERN bool  acc_set_interactive_scope PROTO_PARAMS((handle scope,
+                   int callback_flag));
+EXTERN bool    acc_set_pulsere PROTO_PARAMS((handle path_p, double val1r,
+                   double val1e));
+EXTERN char  *acc_set_scope PROTO_PARAMS((handle object, ...));
+EXTERN int     acc_set_value PROTO_PARAMS((handle obj,
+                   p_setval_value setval_p, p_setval_delay delay_p));
+EXTERN void    acc_vcl_add PROTO_PARAMS((handle object_p, int (*consumer)(),
+                   char *user_data, int vcl_flags));
+EXTERN void    acc_vcl_delete PROTO_PARAMS((handle object_p,
+                   int (*consumer)(), char *user_data, int vcl_flags));
+EXTERN char   *acc_version PROTO_PARAMS((void));
+
+#ifdef DEFINED_PROTO_PARAMS
+#undef DEFINED_PROTO_PARAMS
+#undef  PROTO_PARAMS
+#endif
+
+#ifdef DEFINED_EXTERN
+#undef DEFINED_EXTERN
+#undef EXTERN
+#endif
+
+/*---------------------------------------------------------------------------*/
+/*------------------------------- definitions -------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* --- UNPORTABLE XL Specific code - must use acc routine 
+#define acc_handle_calling_mod_m acc_handle_parent((handle)tf_getinstance())
+--- */
+#define acc_handle_calling_mod_m acc_handle_parent(acc_handle_tfinst())
+
+#endif /* ACC_USER_H */
diff --git a/pli_incs/cv_acc_user.h b/pli_incs/cv_acc_user.h
new file mode 100644
index 0000000..e61c822
--- /dev/null
+++ b/pli_incs/cv_acc_user.h
@@ -0,0 +1,62 @@
+
+/******************************************************************************
+* cv_acc_user.h
+*
+* Simulator specific acc_user.h (acc_ routines) include file
+*
+* This file contains the constant definitions, structure definitions
+* used in IEEE P1364 LRM but not defined in acc_user.h file in appendix.
+*
+* It must be included after acc_user.h 
+*
+*
+* This file also contains the acc_ routines that are in common use but
+* not in the IEEE standard
+*
+* Copyright 1995-1999. Pragmatic C Software. All rights reserved.
+* Copyright 1995, IEEE. All rights reserved.
+******************************************************************************/
+#ifndef CVACCUSER_H
+#define CVACCUSER_H
+
+/*---------------------------------------------------------------------------*/
+/*--------------------------- routine definitions ---------------------------*/
+/*---------------------------------------------------------------------------*/
+#if defined(__STDC__) || defined(__cplusplus)
+
+#ifndef PROTO_PARAMS
+#define PROTO_PARAMS(params) params
+#define DEFINED_PROTO_PARAMS
+#endif
+#ifndef EXTERN
+#define EXTERN
+#define DEFINED_EXTERN
+#endif
+
+#else
+
+#ifndef PROTO_PARAMS
+#define PROTO_PARAMS(params) (/* nothing */)
+#define DEFINED_PROTO_PARAMS
+#endif
+#ifndef EXTERN
+#define EXTERN extern
+#define DEFINED_EXTERN
+#endif
+
+#endif /* __STDC__ */
+
+/* added routine for dumping internal acc_ handle contents */
+EXTERN int   __acc_show_object PROTO_PARAMS((handle obj));
+
+#ifdef DEFINED_PROTO_PARAMS
+#undef DEFINED_PROTO_PARAMS
+#undef  PROTO_PARAMS
+#endif
+
+#ifdef DEFINED_EXTERN
+#undef DEFINED_EXTERN
+#undef EXTERN
+#endif
+
+#endif /* CV_ACC_USER_H */
diff --git a/pli_incs/cv_veriuser.h b/pli_incs/cv_veriuser.h
new file mode 100644
index 0000000..2983382
--- /dev/null
+++ b/pli_incs/cv_veriuser.h
@@ -0,0 +1,103 @@
+/******************************************************************************
+* cv_veriuser.h
+*
+* Simulator specific veriuser (tf_ routine) include file
+*
+* This file contains the constant definitions, structure definitions
+* specific to Cver simulator specific tfcell call mechanism that follows
+* the original PLI LRM 1.0 calling mechanism
+*
+* It must be included after veriuser.h 
+*
+* This file also contains the tf_ routines that are enhancements not in
+* the IEEE standard
+*
+* Copyright 1995-1999. Pragmatic C Software. All rights reserved.
+* Copyright 1995, IEEE. All rights reserved.
+******************************************************************************/
+#ifndef PVTFUSER_H
+#define PVTFUSER_H
+
+/*---------------------------------------------------------------------------*/
+/*------------------------------- definitions -------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+/*-------------- tfcell interface structure type field constants ------------*/
+#define  usertask 1
+#define  USERTASK 1
+#define  userfunction 2
+#define  USERFUNCTION 2
+#define  userrealfunction 3
+#define  USERREALFUNCTION 3
+
+/*---- s_tfcell interface structure used in user code filled in by user ----*/
+typedef struct t_tfcell
+{
+ short type;         /* either usertask or userfunction */
+ short data;         /* parameter for the following routines */
+ int (*checktf)();   /* routine for checking parameters */
+ int (*sizetf)();    /* for providing size of function return value */
+ int (*calltf)();    /* routine called during simulation */
+ int (*misctf)();    /* miscellaneous routines (see below) */
+ char *tfname;       /* the name of the system task or function */
+ int forwref;        /* indicates special parameters allowed */
+ /* not part of standard but present in some user models */
+ char *tfveritool;   /* usually ignored */
+ char *tferrmessage; /* usually ignored */
+
+} s_tfcell, *p_tfcell;
+
+
+/*---------------------------------------------------------------------------*/
+/*--------------- Pver non standard routine definitions ---------------------*/
+/*---------------------------------------------------------------------------*/
+#if defined(__STDC__) || defined(__cplusplus)
+
+#ifndef PROTO_PARAMS
+#define PROTO_PARAMS(params) params
+#define DEFINED_PROTO_PARAMS
+#endif
+#ifndef EXTERN
+#define EXTERN
+#define DEFINED_EXTERN
+#endif
+
+#else
+
+#ifndef PROTO_PARAMS
+#define PROTO_PARAMS(params) (/* nothing */)
+#define DEFINED_PROTO_PARAMS
+#endif
+#ifndef EXTERN
+#define EXTERN extern
+#define DEFINED_EXTERN
+#endif
+
+#endif /* __STDC__ */
+
+/* added returns name of file as string and sets line number of call */
+EXTERN char *tf_getsourceloc PROTO_PARAMS((int *lineno));
+EXTERN char *tf_igetsourceloc PROTO_PARAMS((int *lineno, char *inst));
+
+/* added same as 0 delay strdelputp except immediate assign not #0 */ 
+EXTERN int tf_istrputp PROTO_PARAMS ((int nparam, int bitlength, int format_char, char *value_p, char *inst));
+EXTERN int tf_strputp PROTO_PARAMS ((int nparam, int bitlength, int format_char, char *value_p));
+
+/* get simulation time in ticks (lowest precicision in design) */
+/* not in LRM but supported by XL */
+EXTERN int tf_getsimtime PROTO_PARAMS((void));
+
+/* get simulation time in ticks - long 64 bit tim version */
+EXTERN int tf_getlongsimtime PROTO_PARAMS((int *aof_hightime));
+
+#ifdef DEFINED_PROTO_PARAMS
+#undef DEFINED_PROTO_PARAMS
+#undef  PROTO_PARAMS
+#endif
+
+#ifdef DEFINED_EXTERN
+#undef DEFINED_EXTERN
+#undef EXTERN
+#endif
+
+#endif /* PVTFUSER_H */
diff --git a/pli_incs/cv_vpi_user.h b/pli_incs/cv_vpi_user.h
new file mode 100644
index 0000000..d47c2d8
--- /dev/null
+++ b/pli_incs/cv_vpi_user.h
@@ -0,0 +1,127 @@
+/******************************************************************************
+* cv_vpi_user.h
+*
+* Simulator specific vpi_user (vpi_ routine) include file
+*
+* This file contains the constant definitions, structure definitions
+* used by the Cver simulator specific vpi mechanism that follows
+* the IEEE P1364 standard
+*
+* It must be included after vpi_user.h
+*
+* This file also contains the vpi_ routines that are enhancements not in
+* the IEEE standard
+*
+* Copyright 1995-2003. Pragmatic C Software. All rights reserved.
+******************************************************************************/
+#ifndef CV_VPI_USER_H
+#define CV_VPI_USER_H
+
+#include <stdarg.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*********** OBJECT TYPES **********/ 
+/* numbers not yet assigned - using 500s (unassigned) until P1364 assigns */
+#define vpiNetDriver    500        /* vpi_ added net driver */
+#define vpiNetBitDriver 501        /* vpi_ added net bit driver */
+#define vpiSchedBitEvent 502       /* vpi_ added wire driver per bit event */ 
+#define vpiParamArray   503        /* new parameter array object */
+#define vpiParamArrayWord 504      /* word of param array (same as memory) */
+
+/*********** METHODS **********/ 
+/*********** methods used to traverse 1 to 1 relationships **********/ 
+/* currently no access to pound parameter expressions - will move */
+#define vpiPoundParam 505
+
+/* iterator to get one instance (vpiModule object) of each type */
+/* 2nd argument to vpi_iterate must be NULL */
+#define vpiOneOfEachMod  506       /* one instance of each type (Cver ext.) */
+
+/* Cver start range (to not conflict with standard or other simulators */
+#define CV_START_ONUMS 500
+
+/*********** PROPERTIES ***********/ 
+/*********** Cver added properties types ***********/ 
+
+/*---------------------------------------------------------------------------*/
+/*------------------------------- definitions -------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* extra vpi_put_value 4th argument flag value to add driver terminal */
+#define vpiAddDriver 16
+
+/*********************** STRUCTURE DEFINITIONS ****************************/
+/* cbLanguageLine call back per line record */ 
+typedef struct t_vpi_languageline
+{
+    char *linep;
+    char *file;
+    int lineno;
+} s_vpi_languageline, *p_vpi_languageline;
+
+/* Cver specific call back record - starting at 500 to avoid conflicts */
+#define cbLanguageLine 500
+
+/* customer specific simulation control operations */
+#define cbCustomer1 501
+
+/* Cver extended vpi_control operations */
+#define vpiInsertSource 500
+#define vpiCustomer1 501
+#define vpiFlushLog 502
+#define vpiDumpVars 503
+#define vpiEnableCb 504
+#define vpiDisableCb 505
+
+/*---------------------------------------------------------------------------*/
+/*--------------- Cver non standard routine definitions ---------------------*/
+/*---------------------------------------------------------------------------*/
+#if defined(__STDC__) || defined(__cplusplus)
+
+#ifndef PROTO_PARAMS
+#define PROTO_PARAMS(params) params
+#define DEFINED_PROTO_PARAMS
+#endif
+#ifndef EXTERN
+#define EXTERN
+#define DEFINED_EXTERN
+#endif
+
+#else
+
+#ifndef PROTO_PARAMS
+#define PROTO_PARAMS(params) (/* nothing */)
+#define DEFINED_PROTO_PARAMS
+#endif
+#ifndef EXTERN
+#define EXTERN extern
+#define DEFINED_EXTERN
+#endif
+
+#endif /* __STDC__ */
+
+/* SJM 11/13/03 - for backward compatibility - old name of vpi control */
+#define vpi_sim_control vpi_control
+
+/* added routine for copying - submitted to committee for inclusion */
+EXTERN vpiHandle    vpi_copy_object     PROTO_PARAMS((vpiHandle obj));
+/* added routine for dumping internal vpi handle contents */
+EXTERN PLI_INT32    __vpi_show_object PROTO_PARAMS((vpiHandle obj));
+
+#ifdef DEFINED_PROTO_PARAMS
+#undef DEFINED_PROTO_PARAMS
+#undef  PROTO_PARAMS
+#endif
+
+#ifdef DEFINED_EXTERN
+#undef DEFINED_EXTERN
+#undef EXTERN
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* CV_VPI_USER_H */
diff --git a/pli_incs/veriuser.h b/pli_incs/veriuser.h
new file mode 100644
index 0000000..ff08ecc
--- /dev/null
+++ b/pli_incs/veriuser.h
@@ -0,0 +1,317 @@
+/******************************************************************************
+* veriuser.h
+*
+* IEEE 1364 1995 Verilog HDL Programming Language Interface (PLI).
+*
+* This file contains the constant definitions, structure definitions, and
+* routine declarations used by the Verilog PLI procedural interface TF 
+* task/function routines. 
+*
+* The file should be included with all C routines that use the PLI
+* task/function routines.
+******************************************************************************/
+#ifndef VERIUSER_H
+#define VERIUSER_H
+
+/*---------------------------------------------------------------------------*/
+/*------------------------------- definitions -------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+/*----------------------------- general defines -----------------------------*/
+#define bool                   int
+#define true                   1
+#define TRUE                   1
+#define false                  0
+#define FALSE                  0
+#define null                   0L
+
+/*---------------------- defines for error interception ---------------------*/
+#define ERR_MESSAGE            1
+#define ERR_WARNING            2
+#define ERR_ERROR              3
+#define ERR_INTERNAL           4
+#define ERR_SYSTEM             5
+
+/*-------------- values for reason parameter to misctf routines -------------*/
+
+#define reason_checktf         1
+#define REASON_CHECKTF         reason_checktf
+#define reason_sizetf          2
+#define REASON_SIZETF          reason_sizetf
+#define reason_calltf          3
+#define REASON_CALLTF          reason_calltf
+#define reason_save            4
+#define REASON_SAVE            reason_save
+#define reason_restart         5
+#define REASON_RESTART         reason_restart
+#define reason_disable         6
+#define REASON_DISABLE         reason_disable
+#define reason_paramvc         7
+#define REASON_PARAMVC         reason_paramvc
+#define reason_synch           8
+#define REASON_SYNCH           reason_synch
+#define reason_finish          9
+#define REASON_FINISH          reason_finish
+#define reason_reactivate     10
+#define REASON_REACTIVATE      reason_reactivate
+#define reason_rosynch        11
+#define REASON_ROSYNCH         reason_rosynch
+#define reason_paramdrc       15
+#define REASON_PARAMDRC        reason_paramdrc
+#define reason_endofcompile   16
+#define REASON_ENDOFCOMPILE    reason_endofcompile
+#define reason_scope          17
+#define REASON_SCOPE          reason_scope
+#define reason_interactive    18
+#define REASON_INTERACTIVE     reason_interactive
+#define reason_reset          19
+#define REASON_RESET           reason_reset
+#define reason_endofreset     20
+#define REASON_ENDOFRESET      reason_endofreset
+#define reason_force          21
+#define REASON_FORCE           reason_force
+#define reason_release        22
+#define REASON_RELEASE         reason_release
+#define reason_startofsave    27
+#define REASON_STARTOFSAVE reason_startofsave
+#define reason_startofrestart 28
+#define REASON_STARTOFRESTART reason_startofrestart
+#define REASON_MAX            28
+
+/*-- types used by tf_typep() and expr_type field in tf_exprinfo structure --*/
+#define tf_nullparam           0
+#define TF_NULLPARAM           tf_nullparam
+#define tf_string              1
+#define TF_STRING              tf_string
+#define tf_readonly           10
+#define TF_READONLY            tf_readonly
+#define tf_readwrite          11
+#define TF_READWRITE           tf_readwrite
+#define tf_rwbitselect        12
+#define TF_RWBITSELECT         tf_rwbitselect
+#define tf_rwpartselect       13
+#define TF_RWPARTSELECT        tf_rwpartselect
+#define tf_rwmemselect        14
+#define TF_RWMEMSELECT         tf_rwmemselect
+#define tf_readonlyreal       15
+#define TF_READONLYREAL        tf_readonlyreal
+#define tf_readwritereal      16
+#define TF_READWRITEREAL       tf_readwritereal
+
+/*---------- types used by node_type field in tf_nodeinfo structure ---------*/
+#define tf_null_node         100
+#define TF_NULL_NODE           tf_null_node
+#define tf_reg_node          101
+#define TF_REG_NODE            tf_reg_node
+#define tf_integer_node      102
+#define TF_INTEGER_NODE        tf_integer_node
+#define tf_time_node         103
+#define TF_TIME_NODE           tf_time_node
+#define tf_netvector_node    104
+#define TF_NETVECTOR_NODE      tf_netvector_node
+#define tf_netscalar_node    105
+#define TF_NETSCALAR_NODE      tf_netscalar_node
+#define tf_memory_node       106
+#define TF_MEMORY_NODE         tf_memory_node
+#define tf_real_node         107
+#define TF_REAL_NODE           tf_real_node
+
+/*---------------------------------------------------------------------------*/
+/*-------------------------- structure definitions --------------------------*/
+/*---------------------------------------------------------------------------*/
+
+/*----- structure used with tf_exprinfo() to get expression information -----*/
+typedef struct t_tfexprinfo
+{
+  short expr_type;
+  short padding;
+  struct t_vecval *expr_value_p;
+  double real_value;
+  char *expr_string;
+  int expr_ngroups;
+  int expr_vec_size;
+  int expr_sign;
+  int expr_lhs_select; 
+  int expr_rhs_select;
+} s_tfexprinfo, *p_tfexprinfo;
+
+/*------- structure for use with tf_nodeinfo() to get node information ------*/
+typedef struct t_tfnodeinfo
+{
+  short node_type;
+  short padding;
+  union
+    {
+      struct t_vecval *vecval_p;
+      struct t_strengthval *strengthval_p;
+      char *memoryval_p;
+      double *real_val_p;
+    } node_value;
+  char *node_symbol;
+  int node_ngroups;
+  int node_vec_size;
+  int node_sign;
+  int node_ms_index;
+  int node_ls_index;
+  int node_mem_size;
+  int node_lhs_element;
+  int node_rhs_element;
+  int *node_handle;
+} s_tfnodeinfo, *p_tfnodeinfo;
+
+/*--------------------- data structure of vector values ---------------------*/
+typedef struct t_vecval
+{
+  int avalbits;
+  int bvalbits;
+} s_vecval, *p_vecval;
+
+/*--------------- data structure of scalar net strength values --------------*/
+typedef struct t_strengthval
+{
+    int strength0;
+    int strength1;
+} s_strengthval, *p_strengthval;
+
+/*---------------------------------------------------------------------------*/
+/*--------------------------- routine definitions ---------------------------*/
+/*---------------------------------------------------------------------------*/
+#if defined(__STDC__) || defined(__cplusplus)
+
+#ifndef PROTO_PARAMS
+#define PROTO_PARAMS(params) params
+#define DEFINED_PROTO_PARAMS
+#endif
+#ifndef EXTERN
+#define EXTERN
+#define DEFINED_EXTERN
+#endif
+
+#else
+
+#ifndef PROTO_PARAMS
+#define PROTO_PARAMS(params) (/* nothing */)
+#define DEFINED_PROTO_PARAMS
+#endif
+#ifndef EXTERN
+#define EXTERN extern
+#define DEFINED_EXTERN
+#endif
+
+#endif /* __STDC__ */
+
+EXTERN void         io_mcdprintf PROTO_PARAMS((int mcd, char *format, ...));
+EXTERN void         io_printf PROTO_PARAMS((char *format, ...));
+EXTERN char        *mc_scan_plusargs PROTO_PARAMS((char *plusarg));
+EXTERN void         tf_add_long PROTO_PARAMS((int *aof_lowtime1, int *aof_hightime1, int lowtime2, int hightime2));
+EXTERN int          tf_asynchoff PROTO_PARAMS((void));
+EXTERN int          tf_asynchon PROTO_PARAMS((void));
+EXTERN int          tf_clearalldelays PROTO_PARAMS((void));
+EXTERN int          tf_compare_long PROTO_PARAMS((unsigned int low1, unsigned int high1, unsigned int low2, unsigned int high2));
+EXTERN int          tf_copypvc_flag PROTO_PARAMS((int nparam));
+EXTERN void         tf_divide_long PROTO_PARAMS((int *aof_low1, int *aof_high1, int low2, int high2));
+EXTERN int          tf_dofinish PROTO_PARAMS((void));
+EXTERN int          tf_dostop PROTO_PARAMS((void));
+EXTERN int          tf_error PROTO_PARAMS((char *fmt, ...));
+EXTERN int          tf_evaluatep PROTO_PARAMS((int pnum));
+EXTERN p_tfexprinfo tf_exprinfo PROTO_PARAMS((int pnum, p_tfexprinfo pinfo));
+EXTERN char        *tf_getcstringp PROTO_PARAMS((int nparam));
+EXTERN char        *tf_getinstance PROTO_PARAMS((void));
+EXTERN int          tf_getlongp PROTO_PARAMS((int *aof_highvalue, int pnum));
+EXTERN int          tf_getlongtime PROTO_PARAMS((int *aof_hightime));
+EXTERN int          tf_getnextlongtime PROTO_PARAMS((int *aof_lowtime, int *aof_hightime));
+EXTERN int          tf_getp PROTO_PARAMS((int pnum));
+EXTERN int          tf_getpchange PROTO_PARAMS((int nparam));
+EXTERN double       tf_getrealp PROTO_PARAMS((int pnum));
+EXTERN double       tf_getrealtime PROTO_PARAMS((void));
+EXTERN int          tf_gettime PROTO_PARAMS((void));
+EXTERN int          tf_gettimeprecision PROTO_PARAMS((void));
+EXTERN int          tf_gettimeunit PROTO_PARAMS((void));
+EXTERN char        *tf_getworkarea PROTO_PARAMS((void));
+EXTERN int          tf_iasynchoff PROTO_PARAMS((char *inst));
+EXTERN int          tf_iasynchon PROTO_PARAMS((char *inst));
+EXTERN int          tf_iclearalldelays PROTO_PARAMS((char *inst));
+EXTERN int          tf_icopypvc_flag PROTO_PARAMS((int nparam, char *inst));
+EXTERN int          tf_ievaluatep PROTO_PARAMS((int pnum, char *inst));
+EXTERN p_tfexprinfo tf_iexprinfo PROTO_PARAMS((int pnum, p_tfexprinfo pinfo, char *inst));
+EXTERN char        *tf_igetcstringp PROTO_PARAMS((int nparam, char *inst));
+EXTERN int          tf_igetlongp PROTO_PARAMS((int *aof_highvalue, int pnum, char *inst));
+EXTERN int          tf_igetlongtime PROTO_PARAMS((int *aof_hightime, char *inst));
+EXTERN int          tf_igetp PROTO_PARAMS((int pnum, char *inst));
+EXTERN int          tf_igetpchange PROTO_PARAMS((int nparam, char *inst));
+EXTERN double       tf_igetrealp PROTO_PARAMS((int pnum, char *inst));
+EXTERN double       tf_igetrealtime PROTO_PARAMS((char *inst));
+EXTERN int          tf_igettime PROTO_PARAMS((char *inst));
+EXTERN int          tf_igettimeprecision PROTO_PARAMS((char *inst));
+EXTERN int          tf_igettimeunit PROTO_PARAMS((char *inst));
+EXTERN char        *tf_igetworkarea PROTO_PARAMS((char *inst));
+EXTERN char        *tf_imipname PROTO_PARAMS((char *cell));
+EXTERN int          tf_imovepvc_flag PROTO_PARAMS((int nparam, char *inst));
+EXTERN p_tfnodeinfo tf_inodeinfo PROTO_PARAMS((int pnum, p_tfnodeinfo pinfo, char *inst));
+EXTERN int          tf_inump PROTO_PARAMS((char *inst));
+EXTERN int          tf_ipropagatep PROTO_PARAMS((int pnum, char *inst));
+EXTERN int          tf_iputlongp PROTO_PARAMS((int pnum, int lowvalue, int highvalue, char *inst));
+EXTERN int          tf_iputp PROTO_PARAMS((int pnum, int value, char *inst));
+EXTERN int          tf_iputrealp PROTO_PARAMS((int pnum, double value, char *inst));
+EXTERN int          tf_irosynchronize PROTO_PARAMS((char *inst));
+EXTERN int          tf_isetdelay PROTO_PARAMS((int delay, char *inst));
+EXTERN int          tf_isetlongdelay PROTO_PARAMS((int lowdelay, int highdelay, char *inst));
+EXTERN int          tf_isetrealdelay PROTO_PARAMS((double realdelay, char *inst));
+EXTERN int          tf_isizep PROTO_PARAMS((int pnum, char *inst));
+EXTERN char        *tf_ispname PROTO_PARAMS((char *cell));
+EXTERN int          tf_istrdelputp PROTO_PARAMS((int nparam, int bitlength, int format_char, char *value_p, int delay, int delaytype, char *inst));
+EXTERN char        *tf_istrgetp PROTO_PARAMS((int pnum, int format_char, char *inst));
+EXTERN int          tf_istrlongdelputp PROTO_PARAMS((int nparam, int bitlength, int format_char, char *value_p, int lowdelay, int highdelay, int delaytype, char *inst));
+EXTERN int          tf_istrrealdelputp PROTO_PARAMS((int nparam, int bitlength, int format_char, char *value_p, double realdelay, int delaytype, char *inst));
+EXTERN int          tf_isynchronize PROTO_PARAMS((char *inst));
+EXTERN int          tf_itestpvc_flag PROTO_PARAMS((int nparam, char *inst));
+EXTERN int          tf_itypep PROTO_PARAMS((int pnum, char *inst));
+EXTERN void         tf_long_to_real PROTO_PARAMS((int int_lo, int int_hi, double *aof_real));
+EXTERN char         *tf_longtime_tostr PROTO_PARAMS((int lowtime, int hightime));
+EXTERN int          tf_message PROTO_PARAMS((int level, char *facility, char *messno, char *message, ...));
+EXTERN char        *tf_mipname PROTO_PARAMS((void));
+EXTERN int          tf_movepvc_flag PROTO_PARAMS((int nparam));
+EXTERN void         tf_multiply_long PROTO_PARAMS((int *aof_low1, int *aof_high1, int low2, int high2));
+EXTERN p_tfnodeinfo tf_nodeinfo PROTO_PARAMS((int pnum, p_tfnodeinfo pinfo));
+EXTERN int          tf_nump PROTO_PARAMS((void));
+EXTERN int          tf_propagatep PROTO_PARAMS((int pnum));
+EXTERN int          tf_putlongp PROTO_PARAMS((int pnum, int lowvalue, int highvalue));
+EXTERN int          tf_putp PROTO_PARAMS((int pnum, int value));
+EXTERN int          tf_putrealp PROTO_PARAMS((int pnum, double value));
+EXTERN int          tf_read_restart PROTO_PARAMS((char *blockptr, int blocklen));
+EXTERN void         tf_real_to_long PROTO_PARAMS((double real, int *aof_int_lo, int *aof_int_hi));
+EXTERN int          tf_rosynchronize PROTO_PARAMS((void));
+EXTERN void         tf_scale_longdelay PROTO_PARAMS((char *cell, int delay_lo, int delay_hi, int *aof_delay_lo, int *aof_delay_hi));
+EXTERN void         tf_scale_realdelay PROTO_PARAMS((char *cell, double realdelay, double *aof_realdelay));
+EXTERN int          tf_setdelay PROTO_PARAMS((int delay));
+EXTERN int          tf_setlongdelay PROTO_PARAMS((int lowdelay, int highdelay));
+EXTERN int          tf_setrealdelay PROTO_PARAMS((double realdelay));
+EXTERN int          tf_setworkarea PROTO_PARAMS((char *workarea));
+EXTERN int          tf_sizep PROTO_PARAMS((int pnum));
+EXTERN char        *tf_spname PROTO_PARAMS((void));
+EXTERN int          tf_strdelputp PROTO_PARAMS((int nparam, int bitlength, int format_char, char *value_p, int delay, int delaytype));
+EXTERN char        *tf_strgetp PROTO_PARAMS((int pnum, int format_char));
+EXTERN char        *tf_strgettime PROTO_PARAMS((void));
+EXTERN int          tf_strlongdelputp PROTO_PARAMS((int nparam, int bitlength, int format_char, char *value_p, int lowdelay, int highdelay, int delaytype));
+EXTERN int          tf_strrealdelputp PROTO_PARAMS((int nparam, int bitlength, int format_char, char *value_p, double realdelay, int delaytype));
+EXTERN void         tf_subtract_long PROTO_PARAMS((int *aof_lowtime1, int *aof_hightime1, int lowtime2, int hightime2));
+EXTERN int          tf_synchronize PROTO_PARAMS((void));
+EXTERN int          tf_testpvc_flag PROTO_PARAMS((int nparam));
+EXTERN int          tf_text PROTO_PARAMS((char *fmt, ...));
+EXTERN int          tf_typep PROTO_PARAMS((int pnum));
+EXTERN void         tf_unscale_longdelay PROTO_PARAMS((char *cell, int delay_lo, int delay_hi, int *aof_delay_lo, int *aof_delay_hi));
+EXTERN void         tf_unscale_realdelay PROTO_PARAMS((char *cell, double realdelay, double *aof_realdelay));
+EXTERN int          tf_warning PROTO_PARAMS((char *fmt, ...));
+EXTERN int          tf_write_save PROTO_PARAMS((char *blockptr, int blocklen));
+
+#ifdef DEFINED_PROTO_PARAMS
+#undef DEFINED_PROTO_PARAMS
+#undef  PROTO_PARAMS
+#endif
+
+#ifdef DEFINED_EXTERN
+#undef DEFINED_EXTERN
+#undef EXTERN
+#endif
+
+#endif /* VERIUSER_H */
diff --git a/pli_incs/vpi_user.h b/pli_incs/vpi_user.h
new file mode 100644
index 0000000..8ae1886
--- /dev/null
+++ b/pli_incs/vpi_user.h
@@ -0,0 +1,807 @@
+/***************************************************************************
+* vpi_user.h
+*
+* IEEE 1364-2000 Verilog HDL Programming Language Interface (PLI).
+*
+* This file contains the constant definitions, structure definitions, and
+* routine declarations used by the Verilog PLI procedural interface VPI
+* access routines.
+*
+**************************************************************************/
+/***************************************************************************
+* NOTE: the constant values 1 through 299 are reserved for use in this
+* vpi_user.h file.
+**************************************************************************/
+#ifndef VPI_USER_H
+#define VPI_USER_H
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------*/
+/*-------------------------- Portability Help ----------------------------*/
+/*------------------------------------------------------------------------*/
+/* Sized variables */
+#ifndef PLI_TYPES
+#define PLI_TYPES
+typedef int PLI_INT32;
+typedef unsigned int PLI_UINT32;
+typedef short PLI_INT16;
+typedef unsigned short PLI_UINT16;
+typedef char PLI_BYTE8;
+typedef unsigned char PLI_UBYTE8;
+#endif
+/* Use to export a symbol */
+#if WIN32
+#ifndef PLI_DLLISPEC
+#define PLI_DLLISPEC __declspec(dllimport)
+#define VPI_USER_DEFINED_DLLISPEC 1
+#endif
+#else
+#ifndef PLI_DLLISPEC
+#define PLI_DLLISPEC
+#endif
+#endif
+
+/* Use to import a symbol */
+#if WIN32
+#ifndef PLI_DLLESPEC
+#define PLI_DLLESPEC __declspec(dllexport)
+#define VPI_USER_DEFINED_DLLESPEC 1
+#endif
+#else
+#ifndef PLI_DLLESPEC
+#define PLI_DLLESPEC
+#endif
+#endif
+
+/* Use to mark a function as external */
+#ifndef PLI_EXTERN
+#define PLI_EXTERN
+#endif
+/* Use to mark a variable as external */
+#ifndef PLI_VEXTERN
+#define PLI_VEXTERN extern
+#endif
+#ifndef PLI_PROTOTYPES
+#define PLI_PROTOTYPES
+#define PROTO_PARAMS(params) params
+/* object is defined imported by the application */
+#define XXTERN PLI_EXTERN PLI_DLLISPEC
+/* object is exported by the application */
+#define EETERN PLI_EXTERN PLI_DLLESPEC
+#endif
+
+/******************************** TYPEDEFS ********************************/
+typedef PLI_UINT32 *vpiHandle;
+/****************************** OBJECT TYPES ******************************/
+#define vpiAlways          1        /* always block */
+#define vpiAssignStmt      2        /* quasi-continuous assignment */
+#define vpiAssignment      3        /* procedural assignment */
+#define vpiBegin           4        /* block statement */
+#define vpiCase            5        /* case statement */
+#define vpiCaseItem        6        /* case statement item */
+#define vpiConstant        7        /* numerical constant or literal string */
+#define vpiContAssign      8        /* continuous assignment */
+#define vpiDeassign        9        /* deassignment statement */
+#define vpiDefParam       10        /* defparam */
+#define vpiDelayControl   11        /* delay statement (e.g. #10) */
+#define vpiDisable        12        /* named block disable statement */
+#define vpiEventControl   13        /* wait on event, e.g. @e */
+#define vpiEventStmt      14        /* event trigger, e.g. ->e */
+#define vpiFor            15        /* for statement */
+#define vpiForce          16        /* force statement */
+#define vpiForever        17        /* forever statement */
+#define vpiFork           18        /* fork-join block */
+#define vpiFuncCall       19        /* HDL function call */
+#define vpiFunction       20        /* HDL function */
+#define vpiGate           21        /* primitive gate */
+#define vpiIf             22        /* if statement */
+#define vpiIfElse         23        /* if-else statement */
+#define vpiInitial        24        /* initial block */
+#define vpiIntegerVar     25        /* integer variable */
+#define vpiInterModPath   26        /* intermodule wire delay */
+#define vpiIterator       27        /* iterator */
+#define vpiIODecl         28        /* input/output declaration */
+#define vpiMemory         29        /* behavioral memory */
+#define vpiMemoryWord     30        /* single word of memory */
+#define vpiModPath        31        /* module path for path delays */
+#define vpiModule         32        /* module instance */
+#define vpiNamedBegin     33        /* named block statement */
+#define vpiNamedEvent     34        /* event variable */
+#define vpiNamedFork      35        /* named fork-join block */
+#define vpiNet            36        /* scalar or vector net */
+#define vpiNetBit         37        /* bit of vector net */
+#define vpiNullStmt       38        /* a semicolon, Ie. #10 ; */
+#define vpiOperation      39        /* behavioral operation */
+#define vpiParamAssign    40        /* module parameter assignment */
+#define vpiParameter      41        /* module parameter */
+#define vpiPartSelect     42        /* part select */
+#define vpiPathTerm       43        /* terminal of module path */
+#define vpiPort           44        /* module port */
+#define vpiPortBit        45        /* bit of vector module port */
+#define vpiPrimTerm       46        /* primitive terminal */
+#define vpiRealVar        47        /* real variable */
+#define vpiReg            48        /* scalar or vector reg */
+#define vpiRegBit         49        /* bit of vector reg */
+#define vpiRelease        50        /* release statement */
+#define vpiRepeat         51        /* repeat statement */
+#define vpiRepeatControl  52        /* repeat control in an assign stmt */
+#define vpiSchedEvent     53        /* vpi_put_value() event */
+#define vpiSpecParam      54        /* specparam */
+#define vpiSwitch         55        /* transistor switch */
+#define vpiSysFuncCall    56        /* system function call */
+#define vpiSysTaskCall    57        /* system task call */
+#define vpiTableEntry     58        /* UDP state table entry */
+#define vpiTask           59        /* HDL task */
+#define vpiTaskCall       60        /* HDL task call */
+#define vpiTchk           61        /* timing check */
+#define vpiTchkTerm       62        /* terminal of timing check */
+#define vpiTimeVar        63        /* time variable */
+#define vpiTimeQueue      64        /* simulation event queue */
+#define vpiUdp            65        /* user-defined primitive */
+#define vpiUdpDefn        66        /* UDP definition */
+#define vpiUserSystf      67        /* user defined system task or function */
+#define vpiVarSelect      68        /* variable array selection */
+#define vpiWait           69        /* wait statement */
+#define vpiWhile          70        /* while statement */
+
+/****************** object types added with 1364-2000 *********************/
+#define vpiAttribute     105        /* attribute of an object */
+#define vpiBitSelect     106        /* Bit select of parameter, var select */
+#define vpiCallback      107        /* callback object */
+#define vpiDelayTerm     108        /* Delay term which is a load or driver */
+#define vpiDelayDevice   109        /* Delay object within a net */
+#define vpiFrame         110        /* reentrant task/func frame */
+#define vpiGateArray     111        /* gate instance array */
+#define vpiModuleArray   112        /* module instance array */
+#define vpiPrimitiveArray 113       /* vpiprimitiveArray type */
+#define vpiNetArray      114        /* multidimensional net */
+#define vpiRange         115        /* range declaration */
+#define vpiRegArray      116        /* multidimensional reg */
+#define vpiSwitchArray   117        /* switch instance array */
+#define vpiUdpArray      118        /* UDP instance array */
+#define vpiContAssignBit 128        /* Bit of a vector continuous assignment */
+#define vpiNamedEventArray 129 /* multidimensional named event */
+
+/******************************** METHODS *********************************/
+/************* methods used to traverse 1 to 1 relationships **************/
+#define vpiCondition      71        /* condition expression */
+#define vpiDelay          72        /* net or gate delay */
+#define vpiElseStmt       73        /* else statement */
+#define vpiForIncStmt     74        /* increment statement in for loop */
+#define vpiForInitStmt    75        /* initialization statement in for loop */
+#define vpiHighConn       76        /* higher connection to port */
+#define vpiLhs            77        /* left-hand side of assignment */
+#define vpiIndex          78        /* index of var select, bit select, etc. */
+#define vpiLeftRange      79        /* left range of vector or part select */
+#define vpiLowConn        80        /* lower connection to port */
+#define vpiParent         81        /* parent object */
+#define vpiRhs            82        /* right-hand side of assignment */
+#define vpiRightRange     83        /* right range of vector or part select */
+#define vpiScope          84        /* containing scope object */
+#define vpiSysTfCall      85        /* task function call */
+#define vpiTchkDataTerm   86        /* timing check data term */
+#define vpiTchkNotifier   87        /* timing check notifier */
+#define vpiTchkRefTerm    88        /* timing check reference term */
+
+/************ methods used to traverse 1 to many relationships ************/
+#define vpiArgument       89        /* argument to (system) task/function */
+#define vpiBit            90        /* bit of vector net or port */
+#define vpiDriver         91        /* driver for a net */
+#define vpiInternalScope  92        /* internal scope in module */
+#define vpiLoad           93        /* load on net or reg */
+#define vpiModDataPathIn  94        /* data terminal of a module path */
+#define vpiModPathIn      95        /* Input terminal of a module path */
+#define vpiModPathOut     96        /* output terminal of a module path */
+#define vpiOperand        97        /* operand of expression */
+#define vpiPortInst       98        /* connected port instance */
+#define vpiProcess        99        /* process in module */
+#define vpiVariables     100        /* variables in module */
+#define vpiUse           101        /* usage */
+
+/***** methods which can traverse 1 to 1, or 1 to many relationships ******/
+#define vpiExpr          102        /* connected expression */
+#define vpiPrimitive     103        /* primitive (gate, switch, UDP) */
+#define vpiStmt          104        /* statement in process or task */
+
+/********************* methods added with 1364-2000 ***********************/
+#define vpiActiveTimeFormat 119     /* active $timeformat() system task */
+#define vpiInTerm           120     /* To get to a delay device's drivers. */
+#define vpiInstanceArray    121     /* vpiInstance arrays */
+#define vpiLocalDriver      122     /* local drivers (within a module */
+#define vpiLocalLoad        123     /* local loads (within a module */
+#define vpiOutTerm          124     /* To get to a delay device's loads. */
+#define vpiPorts            125     /* Module port */
+#define vpiSimNet           126     /* simulated net after collapsing */
+#define vpiTaskFunc         127     /* HDL task or function */
+
+/******************************* PROPERTIES *******************************/
+/************************ generic object properties ***********************/
+#define vpiUndefined         -1     /* undefined property */
+#define vpiType               1     /* type of object */
+#define vpiName               2     /* local name of object */
+#define vpiFullName           3     /* full hierarchical name */
+#define vpiSize               4     /* size of gate, net, port, etc. */
+#define vpiFile               5     /* File name in which the object is used */
+#define vpiLineNo             6     /* line number where the object is used */
+
+/*************************** module properties ****************************/
+#define vpiTopModule          7     /* top-level module (boolean) */
+#define vpiCellInstance       8     /* cell (boolean) */
+#define vpiDefName            9     /* module definition name */
+#define vpiProtected         10     /* source protected module (boolean) */
+#define vpiTimeUnit          11     /* module time unit */
+#define vpiTimePrecision     12     /* module time precision */
+#define vpiDefNetType        13     /* default net type */
+#define vpiUnconnDrive       14     /* unconnected port drive strength */
+#define vpiHighZ              1     /* No default drive given */
+#define vpiPull1              2     /* default pull1 drive */
+#define vpiPull0              3     /* default pull0 drive */
+#define vpiDefFile           15     /* File name where the module is defined */
+#define vpiDefLineNo         16     /* line number for module definition */
+#define vpiDefDelayMode      47     /* Default delay mode for a module */
+#define vpiDelayModeNone      1     /* no delay mode specified */
+#define vpiDelayModePath      2     /* path delay mode */
+#define vpiDelayModeDistrib   3     /* distributed delay mode */
+#define vpiDelayModeUnit      4     /* unit delay mode */
+#define vpiDelayModeZero      5     /* zero delay mode */
+#define vpiDelayModeMTM       6     /* min:typ:max delay mode */
+#define vpiDefDecayTime      48     /* Default decay time for a module */
+
+/************************ port and net properties *************************/
+#define vpiScalar            17     /* scalar (boolean) */
+#define vpiVector            18     /* vector (boolean) */
+#define vpiExplicitName      19     /* port is explicitly named */
+#define vpiDirection         20     /* direction of port: */
+#define vpiInput              1     /* input */
+#define vpiOutput             2     /* output */
+#define vpiInout              3     /* inout */
+#define vpiMixedIO            4     /* mixed input-output */
+#define vpiNoDirection        5     /* no direction */
+#define vpiConnByName        21     /* connected by name (boolean) */
+#define vpiNetType           22     /* net subtypes: */
+#define vpiWire               1     /* wire net */
+#define vpiWand               2     /* wire-and net */
+#define vpiWor                3     /* wire-or net */
+#define vpiTri                4     /* three-state net */
+#define vpiTri0               5     /* pull-down net */
+#define vpiTri1               6     /* pull-up net */
+#define vpiTriReg             7     /* tri state reg net */
+#define vpiTriAnd             8     /* three-state wire-and net */
+#define vpiTriOr                                                                                                         9 /* three-state wire-or net */
+#define vpiSupply1           10     /* supply 1 net */
+#define vpiSupply0           11     /* supply zero net */
+#define vpiNone              12     /* no default net type (1364-2000) */
+#define vpiExplicitScalared  23     /* explicitly scalared (boolean) */
+#define vpiExplicitVectored  24     /* explicitly vectored (boolean) */
+#define vpiExpanded          25     /* expanded vector net (boolean) */
+#define vpiImplicitDecl      26     /* implicitly declared net (boolean) */
+#define vpiChargeStrength    27     /* charge decay strength of net */
+
+/* Defined as part of strengths section.
+#define vpiLargeCharge     0x10
+#define vpiMediumCharge    0x04
+#define vpiSmallCharge     0x02
+*/
+
+#define vpiArray             28     /* variable array (boolean) */
+#define vpiPortIndex         29     /* Port index */
+/********************** gate and terminal properties **********************/
+#define vpiTermIndex         30     /* Index of a primitive terminal */
+#define vpiStrength0         31     /* 0-strength of net or gate */
+#define vpiStrength1         32     /* 1-strength of net or gate */
+#define vpiPrimType          33     /* prmitive subtypes: */
+#define vpiAndPrim             1       /* and gate */
+#define vpiNandPrim            2       /* nand gate */
+#define vpiNorPrim             3       /* nor gate */
+#define vpiOrPrim              4       /* or gate */
+#define vpiXorPrim             5       /* xor gate */
+#define vpiXnorPrim            6       /* xnor gate */
+#define vpiBufPrim             7       /* buffer */
+#define vpiNotPrim             8       /* not gate */
+#define vpiBufif0Prim          9       /* zero-enabled buffer */
+#define vpiBufif1Prim         10       /* one-enabled buffer */
+#define vpiNotif0Prim         11       /* zero-enabled not gate */
+#define vpiNotif1Prim         12       /* one-enabled not gate */
+#define vpiNmosPrim           13       /* nmos switch */
+#define vpiPmosPrim           14       /* pmos switch */
+#define vpiCmosPrim           15       /* cmos switch */
+#define vpiRnmosPrim          16       /* resistive nmos switch */
+#define vpiRpmosPrim          17       /* resistive pmos switch */
+#define vpiRcmosPrim          18       /* resistive cmos switch */
+#define vpiRtranPrim          19       /* resistive bidirectional */
+#define vpiRtranif0Prim       20       /* zero-enable resistive bidirectional */
+#define vpiRtranif1Prim       21       /* one-enable resistive bidirectional */
+#define vpiTranPrim           22       /* bidirectional */
+#define vpiTranif0Prim        23       /* zero-enabled bidirectional */
+#define vpiTranif1Prim        24       /* one-enabled bidirectional */
+#define vpiPullupPrim         25       /* pullup */
+#define vpiPulldownPrim       26       /* pulldown */
+#define vpiSeqPrim            27       /* sequential UDP */
+#define vpiCombPrim           28       /* combinational UDP */
+
+/************** path, path terminal, timing check properties **************/
+#define vpiPolarity           34       /* polarity of module path... */
+#define vpiDataPolarity       35       /* ...or data path: */
+#define vpiPositive              1        /* positive */
+#define vpiNegative              2        /* negative */
+#define vpiUnknown               3        /* unknown (unspecified) */
+#define vpiEdge               36       /* edge type of module path: */
+#define vpiNoEdge     0x00000000       /* no edge */
+#define vpiEdge01     0x00000001       /* 0 -> 1 */
+#define vpiEdge10     0x00000002       /* 1 -> 0 */
+#define vpiEdge0x     0x00000004       /* 0 -> x */
+#define vpiEdgex1     0x00000008       /* x -> 1 */
+#define vpiEdge1x     0x00000010       /* 1 -> x */
+#define vpiEdgex0     0x00000020       /* x -> 0 */
+#define vpiPosEdge    (vpiEdgex1 | vpiEdge01 | vpiEdge0x)
+#define vpiNegEdge    (vpiEdgex0 | vpiEdge10 | vpiEdge1x)
+#define vpiAnyEdge    (vpiPosEdge | vpiNegEdge)
+
+#define vpiPathType           37    /* path delay connection subtypes: */
+#define vpiPathFull              1      /* ( a *> b ) */
+#define vpiPathParallel          2      /* ( a => b ) */
+#define vpiTchkType           38    /* timing check subtypes: */
+#define vpiSetup                 1   /* $setup */
+#define vpiHold                  2   /* $hold */
+#define vpiPeriod                3   /* $period */
+#define vpiWidth                 4   /* $width */
+#define vpiSkew                  5   /* $skew */
+#define vpiRecovery              6   /* $recovery */
+#define vpiNoChange              7   /* $nochange */
+#define vpiSetupHold             8   /* $setuphold */
+#define vpiFullskew              9   /* $fullskew -- added for 1364-2000 */
+#define vpiRecrem               10   /* $recrem -- added for 1364-2000 */
+#define vpiRemoval              11   /* $removal -- added for 1364-2000 */
+#define vpiTimeskew             12   /* $timeskew -- added for 1364-2000 */
+
+/************************* expression properties **************************/
+#define vpiOpType             39   /* operation subtypes: */
+#define vpiMinusOp               1 /* unary minus */
+#define vpiPlusOp                2 /* unary plus */
+#define vpiNotOp                 3 /* unary not */
+#define vpiBitNegOp              4 /* bitwise negation */
+#define vpiUnaryAndOp            5 /* bitwise reduction and */
+#define vpiUnaryNandOp           6 /* bitwise reduction nand */
+#define vpiUnaryOrOp             7 /* bitwise reduction or */
+#define vpiUnaryNorOp            8 /* bitwise reduction nor */
+#define vpiUnaryXorOp            9 /* bitwise reduction xor */
+#define vpiUnaryXNorOp          10 /* bitwise reduction xnor */
+#define vpiSubOp                11 /* binary subtraction */
+#define vpiDivOp                12 /* binary division */
+#define vpiModOp                13 /* binary modulus */
+#define vpiEqOp                 14 /* binary equality */
+#define vpiNeqOp                15 /* binary inequality */
+#define vpiCaseEqOp             16 /* case (x and z) equality */
+#define vpiCaseNeqOp            17 /* case inequality */
+#define vpiGtOp                 18 /* binary greater than */
+#define vpiGeOp                 19 /* binary greater than or equal */
+#define vpiLtOp                 20 /* binary less than */
+#define vpiLeOp                 21 /* binary less than or equal */
+#define vpiLShiftOp             22 /* binary left shift */
+#define vpiRShiftOp             23 /* binary right shift */
+#define vpiAddOp                24 /* binary addition */
+#define vpiMultOp               25 /* binary multiplication */
+#define vpiLogAndOp             26 /* binary logical and */
+#define vpiLogOrOp              27 /* binary logical or */
+#define vpiBitAndOp             28 /* binary bitwise and */
+#define vpiBitOrOp              29 /* binary bitwise or */
+#define vpiBitXorOp             30 /* binary bitwise xor */
+#define vpiBitXNorOp            31 /* binary bitwise xnor */
+#define vpiBitXnorOp            vpiBitXNorOp /* added with 1364-2000 */
+#define vpiConditionOp          32 /* ternary conditional */
+#define vpiConcatOp             33 /* n-ary concatenation */
+#define vpiMultiConcatOp        34 /* repeated concatenation */
+#define vpiEventOrOp            35 /* event or */
+#define vpiNullOp               36 /* null operation */
+#define vpiListOp               37 /* list of expressions */
+#define vpiMinTypMaxOp          38 /* min:typ:max: delay expression */
+#define vpiPosedgeOp            39 /* posedge */
+#define vpiNegedgeOp            40 /* negedge */
+#define vpiArithLShiftOp        41 /* arithmetic left shift (1364-2000) */
+#define vpiArithRShiftOp        42 /* arithmetic right shift (1364-2000) */
+#define vpiPowerOp              43 /* arithmetic power op (1364-2000) */
+
+#define vpiConstType           40 /* constant subtypes: */
+#define vpiDecConst              1 /* decimal integer */
+#define vpiRealConst             2 /* real */
+#define vpiBinaryConst           3 /* binary integer */
+#define vpiOctConst              4 /* octal integer */
+#define vpiHexConst              5 /* hexadecimal integer */
+#define vpiStringConst           6 /* string literal */
+#define vpiIntConst              7 /* HDL integer constant (1364-2000) */
+#define vpiBlocking            41 /* blocking assignment (boolean) */
+#define vpiCaseType            42 /* case statement subtypes: */
+#define vpiCaseExact             1 /* exact match */
+#define vpiCaseX                 2 /* ignore X's */
+#define vpiCaseZ                 3 /* ignore Z's */
+#define vpiNetDeclAssign       43 /* assign part of decl (boolean) */
+
+/************** task/function properties **************/
+#define vpiFuncType            44 /* HDL function and system function type */
+#define vpiIntFunc               1 /* returns integer */
+#define vpiRealFunc              2 /* returns real */
+#define vpiTimeFunc              3 /* returns time */
+#define vpiSizedFunc             4 /* returns an arbitrary size */
+#define vpiSizedSignedFunc       5 /* returns sized signed value */
+
+/* alias 1364-1995 system function subtypes to 1364-2000 function subtypes */
+#define vpiSysFuncType           vpiFuncType
+#define vpiSysFuncInt            vpiIntFunc
+#define vpiSysFuncReal           vpiRealFunc
+#define vpiSysFuncTime           vpiTimeFunc
+#define vpiSysFuncSized          vpiSizedFunc
+#define vpiUserDefn            45 /* user defined system task/func (boolean) */
+#define vpiScheduled           46 /* object still scheduled (boolean) */
+
+/*********************** properties added with 1364-2000 *******************/
+#define vpiActive              49 /* reentrant task/func frame is active */
+#define vpiAutomatic           50 /* task/func obj is automatic */
+#define vpiCell                51 /* configuration cell */
+#define vpiConfig              52 /* configuration config file */
+#define vpiConstantSelect      53 /* (boolean) bit or part select indices
+are constant expressions */
+#define vpiDecompile           54 /* decompile the object */
+#define vpiDefAttribute        55 /* Attribute defined for the obj */
+#define vpiDelayType           56 /* delay subtype */
+#define vpiModPathDelay          1 /* module path delay */
+#define vpiInterModPathDelay     2 /* intermodule path delay */
+#define vpiMIPDelay              3 /* module input port delay */
+#define vpiIteratorType        57 /* object type of an iterator */
+#define vpiLibrary             58 /* configuration library */
+#define vpiMultiArray          59 /* Object is a multidimensional array */
+#define vpiOffset              60 /* offset from LSB */
+#define vpiResolvedNetType     61 /* net subtype after resolution, returns
+                                     same subtypes as vpiNetType */
+#define vpiSaveRestartID       62 /* unique ID for save/restart data */
+#define vpiSaveRestartLocation 63 /* name of save/restart data file */
+#define vpiValid               64 /* reentrant task/func frame is valid */
+#define vpiSigned              65 /* TRUE for vpiIODecl and any object in
+                                     the expression class if the object
+                                     has the signed attribute */
+#define vpiLocalParam          70 /* TRUE when a param is declared as a
+                                     localparam */
+#define vpiModPathHasIfNone    71 /* Mod path has an ifnone statement */
+
+/************* vpi_control() constants (added with 1364-2000) *************/
+#define vpiStop                66 /* execute simulator's $stop */
+#define vpiFinish              67 /* execute simulator's $finish */
+#define vpiReset               68 /* execute simulator's $reset */
+#define vpiSetInteractiveScope 69 /* set simulator's interactive scope */
+
+/************************** I/O related defines ***************************/
+#define VPI_MCD_STDOUT 0x00000001
+
+/************************** STRUCTURE DEFINITIONS *************************/
+/***************************** time structure *****************************/
+typedef struct t_vpi_time
+{
+   PLI_INT32 type; /* [vpiScaledRealTime, vpiSimTime, vpiSuppressTime] */
+   PLI_UINT32 high, low; /* for vpiSimTime */
+   double real; /* for vpiScaledRealTime */
+} s_vpi_time, *p_vpi_time;
+
+/* time types */
+#define vpiScaledRealTime 1
+#define vpiSimTime 2
+#define vpiSuppressTime 3
+
+/**************************** delay structures ****************************/
+typedef struct t_vpi_delay
+{
+  struct t_vpi_time *da; /* pointer to user allocated array of delay values */
+  PLI_INT32 no_of_delays; /* number of delays */
+  PLI_INT32 time_type; /* [vpiScaledRealTime, vpiSimTime, vpiSuppressTime] */
+  PLI_INT32 mtm_flag; /* true for mtm values */
+  PLI_INT32 append_flag; /* true for append */
+  PLI_INT32 pulsere_flag; /* true for pulsere values */
+} s_vpi_delay, *p_vpi_delay;
+
+/**************************** value structures ****************************/
+/* vector value */
+typedef struct t_vpi_vecval
+{
+  /* following fields are repeated enough times to contain vector */
+  PLI_INT32 aval, bval; /* bit encoding: ab: 00=0, 10=1, 11=X, 01=Z */
+} s_vpi_vecval, *p_vpi_vecval;
+
+/* strength (scalar) value */
+typedef struct t_vpi_strengthval
+{
+  PLI_INT32 logic; /* vpi[0,1,X,Z] */
+  PLI_INT32 s0, s1; /* refer to strength coding below */
+} s_vpi_strengthval, *p_vpi_strengthval;
+
+/* strength values */
+#define vpiSupplyDrive     0x80
+#define vpiStrongDrive     0x40
+#define vpiPullDrive       0x20
+#define vpiWeakDrive       0x08
+#define vpiLargeCharge     0x10
+#define vpiMediumCharge    0x04
+#define vpiSmallCharge     0x02
+#define vpiHiZ             0x01
+
+/* generic value */
+typedef struct t_vpi_value
+{
+  PLI_INT32 format; /* vpi[[Bin,Oct,Dec,Hex]Str,Scalar,Int,Real,String,
+                              Vector,Strength,Suppress,Time,ObjType]Val */
+  union
+    {
+      PLI_BYTE8 *str; /* string value */
+      PLI_INT32 scalar; /* vpi[0,1,X,Z] */
+      PLI_INT32 integer; /* integer value */
+      double real; /* real value */
+      struct t_vpi_time *time; /* time value */
+      struct t_vpi_vecval *vector; /* vector value */
+      struct t_vpi_strengthval *strength; /* strength value */
+      PLI_BYTE8 *misc; /* ...other */
+    } value;
+} s_vpi_value, *p_vpi_value;
+
+/* value formats */
+#define vpiBinStrVal             1
+#define vpiOctStrVal             2
+#define vpiDecStrVal             3
+#define vpiHexStrVal             4
+#define vpiScalarVal             5
+#define vpiIntVal                6
+#define vpiRealVal               7
+#define vpiStringVal             8
+#define vpiVectorVal             9
+#define vpiStrengthVal          10
+#define vpiTimeVal              11
+#define vpiObjTypeVal           12
+#define vpiSuppressVal          13
+
+/* delay modes */
+#define vpiNoDelay               1
+#define vpiInertialDelay         2
+#define vpiTransportDelay        3
+#define vpiPureTransportDelay    4
+
+/* force and release flags */
+#define vpiForceFlag             5
+#define vpiReleaseFlag           6
+
+/* scheduled event cancel flag */
+#define vpiCancelEvent           7
+
+/* bit mask for the flags argument to vpi_put_value() */
+#define vpiReturnEvent           0x1000
+
+/* scalar values */
+#define vpi0                     0
+#define vpi1                     1
+#define vpiZ                     2
+#define vpiX                     3
+#define vpiH                     4
+#define vpiL                     5
+#define vpiDontCare              6
+
+/*
+#define vpiNoChange 7 Defined under vpiTchkType, but
+can be used here.
+*/
+/********************* system task/function structure *********************/
+typedef struct t_vpi_systf_data
+{
+  PLI_INT32 type;          /* vpiSysTask, vpiSysFunc */
+  PLI_INT32 sysfunctype;   /* vpiSysTask, vpi[Int,Real,Time,Sized,
+                              SizedSigned] Func */
+  PLI_BYTE8 *tfname;       /* first character must be `$' */
+  PLI_INT32 (*calltf)();
+  PLI_INT32 (*compiletf)();
+  PLI_INT32 (*sizetf)(); /* for sized function callbacks only */
+  PLI_BYTE8 *user_data;
+} s_vpi_systf_data, *p_vpi_systf_data;
+
+#define vpiSysTask               1
+#define vpiSysFunc               2
+/* the subtypes are defined under the vpiFuncType property */
+
+/***************** Verilog execution information structure ****************/
+typedef struct t_vpi_vlog_info
+{
+  PLI_INT32 argc;
+  PLI_BYTE8 **argv;
+  PLI_BYTE8 *product;
+  PLI_BYTE8 *version;
+} s_vpi_vlog_info, *p_vpi_vlog_info;
+
+/******************** PLI error information structure *********************/
+typedef struct t_vpi_error_info
+{
+   PLI_INT32 state;              /* vpi[Compile,PLI,Run] */
+   PLI_INT32 level;              /* vpi[Notice,Warning,Error,System,Internal] */
+   PLI_BYTE8 *message;
+   PLI_BYTE8 *product;
+   PLI_BYTE8 *code;
+   PLI_BYTE8 *file;
+   PLI_INT32 line;
+} s_vpi_error_info, *p_vpi_error_info;
+
+
+/* error types */
+#define vpiCompile              1
+#define vpiPLI                  2
+#define vpiRun                  3
+
+#define vpiNotice               1
+#define vpiWarning              2
+#define vpiError                3
+#define vpiSystem               4
+#define vpiInternal             5
+
+/************************** callback structures ***************************/
+/* normal callback structure */
+typedef struct t_cb_data
+{
+  PLI_INT32 reason; /* callback reason */
+  PLI_INT32 (*cb_rtn)(struct t_cb_data *); /* call routine */
+  vpiHandle obj; /* trigger object */
+  p_vpi_time time; /* callback time */
+  p_vpi_value value; /* trigger object value */
+  PLI_INT32 index; /* index of the memory word or var select that changed */
+  PLI_BYTE8 *user_data;
+} s_cb_data, *p_cb_data;
+
+/**************************** CALLBACK REASONS ****************************/
+/*************************** Simulation related ***************************/
+#define cbValueChange          1
+#define cbStmt                 2
+#define cbForce                3
+#define cbRelease              4
+
+/****************************** Time related ******************************/
+#define cbAtStartOfSimTime     5
+#define cbReadWriteSynch       6
+#define cbReadOnlySynch        7
+#define cbNextSimTime          8
+#define cbAfterDelay           9
+
+/***************************** Action related *****************************/
+#define cbEndOfCompile        10
+#define cbStartOfSimulation   11
+#define cbEndOfSimulation     12
+#define cbError               13
+#define cbTchkViolation       14
+#define cbStartOfSave         15
+#define cbEndOfSave           16
+#define cbStartOfRestart      17
+#define cbEndOfRestart        18
+#define cbStartOfReset        19
+#define cbEndOfReset          20
+#define cbEnterInteractive    21
+#define cbExitInteractive     22
+#define cbInteractiveScopeChange 23
+#define cbUnresolvedSystf     24
+
+/************************** Added with 1364-2000 **************************/
+#define cbAssign              25
+#define cbDeassign            26
+#define cbDisable             27
+#define cbPLIError            28
+#define cbSignal              29
+
+/************************* FUNCTION DECLARATIONS **************************/
+/* callback related */
+XXTERN vpiHandle     vpi_register_cb      PROTO_PARAMS((p_cb_data cb_data_p));
+XXTERN PLI_INT32     vpi_remove_cb        PROTO_PARAMS((vpiHandle cb_obj));
+XXTERN void          vpi_get_cb_info      PROTO_PARAMS((vpiHandle object,
+                                            p_cb_data cb_data_p));
+XXTERN vpiHandle     vpi_register_systf   PROTO_PARAMS((p_vpi_systf_data
+                                            systf_data_p));
+XXTERN void vpi_get_systf_info            PROTO_PARAMS((vpiHandle object,
+                                            p_vpi_systf_data systf_data_p));
+/* for obtaining handles */
+XXTERN vpiHandle      vpi_handle_by_name  PROTO_PARAMS((PLI_BYTE8 *name,
+                                            vpiHandle scope));
+XXTERN vpiHandle      vpi_handle_by_index PROTO_PARAMS((vpiHandle object,
+                                            PLI_INT32 indx));
+
+/* for traversing relationships */
+XXTERN vpiHandle      vpi_handle          PROTO_PARAMS((PLI_INT32 type,
+                                            vpiHandle refHandle));
+XXTERN vpiHandle      vpi_handle_multi    PROTO_PARAMS((PLI_INT32 type,
+                                            vpiHandle refHandle1,
+                                            vpiHandle refHandle2, ... ));
+XXTERN vpiHandle      vpi_iterate         PROTO_PARAMS((PLI_INT32 type,
+                                            vpiHandle refHandle));
+XXTERN vpiHandle      vpi_scan            PROTO_PARAMS((vpiHandle iterator));
+
+/* for processing properties */
+XXTERN PLI_INT32 vpi_get                  PROTO_PARAMS((PLI_INT32 property,
+                                            vpiHandle object));
+
+XXTERN PLI_BYTE8 *vpi_get_str             PROTO_PARAMS((PLI_INT32 property,
+                                            vpiHandle object));
+/* delay processing */
+XXTERN void         vpi_get_delays        PROTO_PARAMS((vpiHandle object,
+                                            p_vpi_delay delay_p));
+XXTERN void         vpi_put_delays        PROTO_PARAMS((vpiHandle object,
+                                            p_vpi_delay delay_p));
+
+/* value processing */
+XXTERN void       vpi_get_value           PROTO_PARAMS((vpiHandle expr,                                                    p_vpi_value value_p));
+XXTERN vpiHandle  vpi_put_value           PROTO_PARAMS((vpiHandle object,
+                                            p_vpi_value value_p,
+                                            p_vpi_time time_p,
+                                            PLI_INT32 flags));
+
+/* time processing */
+XXTERN void       vpi_get_time            PROTO_PARAMS((vpiHandle object,
+                                            p_vpi_time time_p));
+
+/* I/O routines */
+XXTERN PLI_UINT32 vpi_mcd_open            PROTO_PARAMS((PLI_BYTE8 *fileName));
+XXTERN PLI_UINT32 vpi_mcd_close           PROTO_PARAMS((PLI_UINT32 mcd));
+XXTERN PLI_BYTE8  *vpi_mcd_name            PROTO_PARAMS((PLI_UINT32 cd));
+XXTERN PLI_INT32  vpi_mcd_printf           PROTO_PARAMS((PLI_UINT32 mcd,
+                                            PLI_BYTE8 *format, ...));
+
+XXTERN PLI_INT32 vpi_printf               PROTO_PARAMS((PLI_BYTE8 *format,
+                                            ...));
+/* utility routines */
+XXTERN PLI_INT32 vpi_compare_objects      PROTO_PARAMS((vpiHandle object1,
+                                            vpiHandle object2));
+XXTERN PLI_INT32 vpi_chk_error            PROTO_PARAMS((p_vpi_error_info
+                                            error_info_p));
+XXTERN PLI_INT32 vpi_free_object          PROTO_PARAMS((vpiHandle object));
+XXTERN PLI_INT32 vpi_get_vlog_info        PROTO_PARAMS((p_vpi_vlog_info
+                                            vlog_info_p));
+
+/* routines added with 1364-2000 */
+XXTERN PLI_INT32 vpi_get_data             PROTO_PARAMS((PLI_INT32 id,
+                                            PLI_BYTE8 *dataLoc,
+                                            PLI_INT32 numOfBytes));
+XXTERN PLI_INT32 vpi_put_data             PROTO_PARAMS((PLI_INT32 id,
+                                            PLI_BYTE8 *dataLoc,
+                                            PLI_INT32 numOfBytes));
+XXTERN void *vpi_get_userdata             PROTO_PARAMS((vpiHandle obj));
+XXTERN PLI_INT32 vpi_put_userdata         PROTO_PARAMS((vpiHandle obj,
+                                            void *userdata));
+XXTERN PLI_INT32 vpi_vprintf              PROTO_PARAMS((PLI_BYTE8 *format,
+                                            va_list ap));
+XXTERN PLI_INT32 vpi_mcd_vprintf          PROTO_PARAMS((PLI_UINT32 mcd,
+                                            PLI_BYTE8 *format, va_list ap));
+XXTERN PLI_INT32 vpi_flush PROTO_PARAMS((void));
+XXTERN PLI_INT32 vpi_mcd_flush            PROTO_PARAMS((PLI_UINT32 mcd));
+XXTERN PLI_INT32 vpi_control PROTO_PARAMS((PLI_INT32 operation,
+...));
+XXTERN vpiHandle vpi_handle_by_multi_index PROTO_PARAMS((vpiHandle obj,
+PLI_INT32 num_index,
+PLI_INT32 *index_array));
+
+/**************************** GLOBAL VARIABLES ****************************/
+PLI_VEXTERN PLI_DLLESPEC void (*vlog_startup_routines[])();
+/* array of function pointers, last pointer should be null */
+#undef PLI_EXTERN
+#undef PLI_VEXTERN
+#ifdef VPI_USER_DEFINED_DLLISPEC
+#undef VPI_USER_DEFINED_DLLISPEC
+#undef PLI_DLLISPEC
+#endif
+#ifdef VPI_USER_DEFINED_DLLESPEC
+#undef VPI_USER_DEFINED_DLLESPEC
+IEEE
+HARDWARE DESCRIPTION LANGUAGE Std 1364-2001
+#undef PLI_DLLESPEC
+#endif
+#ifdef PLI_PROTOTYPES
+#undef PLI_PROTOTYPES
+#undef PROTO_PARAMS
+#undef XXTERN
+#undef EETERN
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VPI_USER_H */
diff --git a/pli_src/README b/pli_src/README
new file mode 100644
index 0000000..16cbc95
--- /dev/null
+++ b/pli_src/README
@@ -0,0 +1,8 @@
+
+Contents:
+
+infodmp.inc   Some routines that you can include in your PLI source
+              using the 1.0 tf_ routines to help with tf_ routine debugging.
+              A good way to use this code is to modify it to your taste
+              and copy it into your source for viewing t_tfexprinfo
+              t_tfnodeinfo structures. 
diff --git a/pli_src/infodmp.inc b/pli_src/infodmp.inc
new file mode 100644
index 0000000..9f58010
--- /dev/null
+++ b/pli_src/infodmp.inc
@@ -0,0 +1,176 @@
+/*
+ * expr and node info dump routines include
+ */
+
+/*
+ * routine to print contents of exprinfo record 
+ */
+#ifdef __STDC__
+int prt_exprinfo(p_tfexprinfo pinfo) {
+#else
+int prt_exprinfo(pinfo)
+ p_tfexprinfo pinfo;
+{
+#endif
+ register int gi;
+ char *exprtyp_tonam();
+ char s1[512]; 
+ 
+ io_printf("**** exprinfo dump ****\n");
+ io_printf(" expr_type: %s\n", exprtyp_tonam(s1, (int) pinfo->expr_type));
+ io_printf(" expr_ngroups: %d\n", pinfo->expr_ngroups);
+ if (pinfo->expr_type == TF_READONLYREAL
+  || pinfo->expr_type == TF_READWRITEREAL)
+   io_printf(" expr_value: %g", pinfo->real_value); 
+ else
+  {
+   for (gi = 0; gi < pinfo->expr_ngroups; gi++) 
+    {
+     io_printf(" group %d: aval=%x, bval=%x\n", gi,
+      pinfo->expr_value_p[gi].avalbits, pinfo->expr_value_p[gi].bvalbits);
+    }
+  }
+ io_printf(" expr_vec_size: %d\n", pinfo->expr_vec_size);
+ io_printf(" expr_sign: %d\n", pinfo->expr_sign);
+ /* think next 2 unused? */
+ io_printf(" expr_lhs_select: %d\n", pinfo->expr_lhs_select);
+ io_printf(" expr_lhs_select: %d\n", pinfo->expr_rhs_select);
+ io_printf("**** end exprinfo ****\n");
+}
+
+/*
+ * convert an expr_type expr info field to a name
+ */
+char *exprtyp_tonam(s, xtyp)
+ char *s;
+ int xtyp;
+{
+ switch (xtyp) {
+  case TF_NULLPARAM: strcpy(s, "tf_nullparam"); break;
+  case TF_STRING: strcpy(s, "tf_string"); break;
+  case TF_READONLY: strcpy(s, "tf_readonly"); break;
+  case TF_READWRITE: strcpy(s, "tf_readwrite"); break;
+  case TF_RWBITSELECT: strcpy(s, "tf_rwbitselect"); break;
+  case TF_RWPARTSELECT: strcpy(s, "tf_rwpartselect"); break;
+  case TF_RWMEMSELECT: strcpy(s, "tf_rwmemselect"); break;
+  case TF_READONLYREAL: strcpy(s, "tf_readonlyreal"); break;
+  case TF_READWRITEREAL: strcpy(s, "tf_readwritereal"); break;
+  default: 
+   tf_message(ERR_INTERNAL, "", "",
+   "unknown exprinfo expr_type value %d", xtyp);
+ }
+ return(s);
+}
+
+/*
+ * routine to print contents of nodeinfo record 
+ */
+#ifdef __STDC__
+int prt_nodeinfo(p_tfnodeinfo pinfo) {
+#else
+int prt_nodeinfo(pinfo)
+ p_tfnodeinfo pinfo;
+{
+#endif
+ register int gi;
+ char *nodetyp_tonam();
+ char s1[512]; 
+ 
+ if (pinfo->node_type == TF_NULL_NODE)
+  {
+   io_printf("**** nodeinfo dump for tf_null_node (no contents) ****\n");
+   return;
+  }
+
+ if (pinfo->node_symbol == NULL) strcpy(s1, "<empty>");
+ else strcpy(s1, pinfo->node_symbol);
+ io_printf("**** nodeinfo dump for symbol %s ****\n", s1);
+ io_printf(" node_type: %s\n", nodetyp_tonam(s1, (int) pinfo->node_type));
+ io_printf(" node_ngroups: %d\n", pinfo->node_ngroups);
+ /* notice for now in Cver t_strengthval never for strength vectors value */
+ /* bits stored in t_vecval (also for scalars) */
+ /* letter to sent to IEEE committee for clarification */
+ if (pinfo->node_type == TF_REAL_NODE)
+   io_printf(" node_value: %g", *pinfo->node_value.real_val_p); 
+ else
+  {
+   for (gi = 0; gi < pinfo->node_ngroups; gi++) 
+    {
+     io_printf(" group %d: aval=%x, bval=%x\n", gi,
+      pinfo->node_value.vecval_p[gi].avalbits,
+      pinfo->node_value.vecval_p[gi].bvalbits);
+    }
+  }
+ io_printf(" node_vec_size: %d\n", pinfo->node_vec_size);
+ io_printf(" node_sign: %d\n", pinfo->node_sign);
+ io_printf(" node_ms_index: %d\n", pinfo->node_ms_index);
+ io_printf(" node_ls_index: %d\n", pinfo->node_ls_index);
+ io_printf(" node_mem_size: %d\n", pinfo->node_mem_size);
+ io_printf(" node_lhs_element: %d\n", pinfo->node_lhs_element);
+ io_printf(" node_rhs_element: %d\n", pinfo->node_rhs_element);
+ io_printf("**** end nodeinfo ****\n");
+}
+
+/*
+ * convert a node_type node info field type to a name
+ */
+char *nodetyp_tonam(s, ntyp)
+ char *s;
+ int ntyp;
+{
+ switch (ntyp) {
+  case TF_NULL_NODE: strcpy(s, "tf_null_node"); break;
+  case TF_REG_NODE: strcpy(s, "tf_reg_node"); break;
+  case TF_INTEGER_NODE: strcpy(s, "tf_integer_node"); break;
+  case TF_REAL_NODE: strcpy(s, "tf_real_node"); break;
+  case TF_TIME_NODE: strcpy(s, "tf_time_node"); break;
+  case TF_NETVECTOR_NODE: strcpy(s, "tf_netvector_node"); break;
+  case TF_NETSCALAR_NODE: strcpy(s, "tf_netscalar_node"); break;
+  case TF_MEMORY_NODE: strcpy(s, "tf_memory_node"); break;
+  default: 
+   tf_message(ERR_INTERNAL, "", "",
+   "unknown nodeinfo node_type value %d", ntyp);
+ }
+ return(s);
+}
+
+char *prt_tfreason(s, reason)
+ char *s;
+ int reason;
+{
+ switch (reason) {
+  case REASON_CHECKTF: strcpy(s, "reason_checktf");
+  case REASON_SIZETF: strcpy(s, "reason_sizetf"); break;
+  case REASON_CALLTF: strcpy(s, "reason_calltf"); break;
+  /* not supported by Cver */
+  case REASON_SAVE: strcpy(s, "reason_save"); break;
+  /* not supported by Cver */
+  case REASON_RESTART: strcpy(s, "reason_restart"); break;
+  /* not supported by Cver */
+  case REASON_DISABLE: strcpy(s, "reason_disable"); break;
+  case REASON_PARAMVC: strcpy(s, "reason_paramvc"); break;
+  case REASON_SYNCH: strcpy(s, "reason_synch"); break;
+  case REASON_FINISH: strcpy(s, "reason_finish"); break;
+  case REASON_REACTIVATE: strcpy(s, "reason_reactivate"); break;
+  case REASON_ROSYNCH: strcpy(s, "reason_rosynch"); break;
+  /* not supported by Cver */
+  case REASON_PARAMDRC: strcpy(s, "reason_paramdrc"); break;
+  case REASON_ENDOFCOMPILE: strcpy(s, "reason_endofcompile"); break;
+  /* not supported by Cver */
+  case REASON_SCOPE: strcpy(s, "reason_scope"); break;
+  case REASON_INTERACTIVE: strcpy(s, "reason_interactive"); break;
+  case REASON_RESET: strcpy(s, "reason_reset"); break;
+  case REASON_ENDOFRESET: strcpy(s, "reason_endofreset"); break;
+  /* not supported by Cver */
+  case REASON_FORCE: strcpy(s, "reason_force"); break;
+  /* not supported by Cver */
+  case REASON_RELEASE: strcpy(s, "reason_release"); break;
+  /* not supported by Cver */
+  case REASON_STARTOFSAVE: strcpy(s, "reason_startofsave"); break;
+  /* not supported by Cver */
+  case REASON_STARTOFRESTART: strcpy(s, "reason_startofrestart"); break;
+  default: 
+   tf_message(ERR_INTERNAL, "", "", "unknown misctf call reason %d", reason);
+ }
+ return(s);
+}
diff --git a/src/INSTALL.README b/src/INSTALL.README
new file mode 100644
index 0000000..1b00a8c
--- /dev/null
+++ b/src/INSTALL.README
@@ -0,0 +1,5 @@
+
+
+                            INSTALLING CVER
+
+See instructions in the README file.  
diff --git a/src/README b/src/README
new file mode 100644
index 0000000..1a44b14
--- /dev/null
+++ b/src/README
@@ -0,0 +1,80 @@
+
+       INSTRUCTIONS FOR MAKING CVER BINARY AND PLI OBJECT
+
+
+  The following instructions assume you are compiling with gcc on either
+a X86 Linux, Sparc Solaris, or Mac OSX, Cygwin (here gcc must be named cc).  
+If not, see instructions below. 
+
+  For X86 Linux, type: 
+
+     make -f makefile.lnx all
+
+  For Solaris running Sparc type:
+
+     make -f makefile.sparc-gcc all
+
+  For Apple OSX type:
+
+     make -f makefile.osx all
+
+  For Cygwin:
+
+     make -f makefile.cygwin all
+
+  These commands will build binary cver in ../bin director.  If you type
+"../bin/cver", Cver will print its start up message and then terminate with
+an error saying no Verilog input files specified.  Next step is to run
+install tests in tests_and examples directory.  See README file in top level
+directory and in tests_and_examples directory for instructions.
+
+   To make just Cver type "make -f makefile.[OS]  cver".  Type
+"make -f makefile.[OS] clean" to remove files so you can remake everything.
+
+A. MAKING CVER ON OTHER SYSTEM
+
+   The makefile.lnx make file should work on any non X86 system running
+Linux.  If you are using a different compiler, just edit the various
+compiler , library and LD make variables and options around line 20 of the
+makefile.lnx file.  If you are not linking with GNU ld, you will need to look
+up your linker's partial link options and edit the cverobj dependency line
+linking action.
+
+   For other systems, you will probably need to deal with differences in
+include files and libraries.  There are only five areas that usually
+require changes:
+
+   1) Cver uses dlopen/dlsym dynamic linking to load user PLI dynamic
+      libraries using either the +load_pli1= or +load_vpi= options. 
+      The programming interface to dynamic linking loading varies
+      between system.  Therefore to port to another system, you will
+      probably need to add ifdefs that include your system's dlopen and
+      dlsym calls.  Your system will probably follow either the unix
+      (sparc/linux) conventions or the Apple OSX (??) conventions.
+      All dynmaic linking code is at the top of v_vpi.c file
+      mostly in the __process_pli_dynamic_libs routine.
+
+   2) Some of the wide math code depends on byte order of your system. See
+      the definitions of ENDIAN in the v.h file.  It appears that different
+      systems define different ENDIAN constants in different include files.
+      Currently, ifdefs are set up for Linux, Apple OSX and Sparc Solaris.
+
+   3) Signals are needed for Cver debugger.  Do a grep for SIGINT and
+      signal calls to find possible problem areas.
+
+   4) The debugger allows escaping to shell script using fork.  Look
+      at the __escape_to_shell routines in v_dbg.c.  One quick fix for
+      this is to just make __escape_to_shell a dummy empty routine since
+      user can always start a shell script in another window.
+
+   5) Cver has been ported to many systems so it should not be too hard
+      to port to other systems although you may need to add a number of
+      ifdefs for your system.
+
+B. MAKING CVER FOR DEBUGGING
+
+   To make a debugging version of either Cver, you need to edit the make
+   file or make copy of the make file and edit that.  Change your makefile
+   around line 35 to comment out the CFLAGS line that compiles without
+   optimization and uncomment the line thatturns on -g.  Then type "gdb cver"
+   and use gdb run command with normal Cver command line options.
diff --git a/src/cver.c b/src/cver.c
new file mode 100644
index 0000000..94a6d8d
--- /dev/null
+++ b/src/cver.c
@@ -0,0 +1,6002 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * main module - command option and license manager code
+ */
+
+/*
+ * main module
+ */
+#include <stdio.h>
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <ctype.h>
+
+#include <signal.h>
+
+#include <setjmp.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+static char copyright[]
+ = "Copyright (c) 1991-2005 Pragmatic C Software Corp.";
+
+/* declares from v.h */
+/* various simulation counting variables */
+char *__vers;          /* actual product info */
+char *__vers2;
+char *__ofdt;
+char *__platform;
+char *__start_sp, *__end_sp;/* pointer for "big" memory allocator */
+char *__pvdate;        /* date in unix form */
+char *__pv_timestamp;  /* timestamp for design */
+time_t __start_time;   /* start wall clock times in secs. */
+time_t __start_mstime; /* start millisecond part */
+time_t __end_comp_time;/* end of compilation time */
+time_t __end_comp_mstime;
+time_t __end_prep_time;/* end of preparation time */
+time_t __end_prep_mstime;
+time_t __end_time;     /* start and end wall clock times */
+time_t __end_mstime;   /* start and end wall clock times */
+
+/* various file variables and global data base flags (i/o vars) */
+char **__in_fils;      /* malloced input file list from args */
+int32 __siz_in_fils;   /* current size of input files */
+int32 __last_inf;      /* last input file in list */
+int32 __last_optf;     /* last option file */
+int32 __last_lbf;      /* last lib/inc file (starts last_inf + 1) */
+int32 __last_srcf;     /* last src containing file for debugger */
+struct incloc_t *__inclst_hdr; /* header of included files list */
+struct incloc_t *__inclst_end; /* end of included files list */
+struct filpos_t *__filpostab; /* in fils size tab of file line pos. */
+FILE *__save_log_s;    /* if $nolog executed, value to use if log */
+int32 __echo_iactcmds_tolog; /* T => echo interactive cmds to log file */
+FILE *__save_key_s;    /* if $nolog executed, value to use if log */
+int32 __nokey_seen;    /* $nokey executed and no key */
+FILE *__in_s;
+FILE *__log_s;
+FILE *__cmd_s;         /* command file source or null for tty */ 
+FILE *__key_s;         /* if key_s nil but key_fnam not, must open */
+struct optlst_t *__opt_hdr;   /* header of expanded option list */
+struct optlst_t *__opt_end;   /* wrk end of expanded option list */
+word32 *__wsupptab;    /* tab (1 bit/msg) for warn and iact suppress */
+char *__blnkline;      /* work blank line */
+char __pv_homedir[RECLEN]; /* home dir - . if HOME env. not set */
+struct mcchan_t __mulchan_tab[32];/* mc desc. tab (32 built in Ver) */ 
+struct fiofd_t **__fio_fdtab; /* array of ptrs to file io stream */
+char *__fiolp;         /* fio file input work string ptr */
+char *__fiofp;         /* fio file input work fmt string ptr */
+long __scanf_pos;      /* byte offset position of scanf in file */
+sighandler *__old_int_sig;  /* value of quit (^c) signal on entry */
+int32 __force_base;    /* for output force base if not BASENONE */
+struct vinstk_t **__vinstk;/* open file/macro list in stack form */
+struct vinstk_t *__visp;/* pointer to top of open input stack */
+int32 __vin_top;       /* index of top of current file stack */
+char *__log_fnam;      /* log file for all terminal output */
+char *__sdf_opt_log_fnam; /* sdf log file if set by cmd arg */
+FILE *__sdf_opt_log_s; /* and open file ptr */
+int32 __sdf_no_warns;  /* T => don't print any SDF warning msgs */
+int32 __sdf_no_errs;   /* T => don't print any SDF error msgs */
+int32 __sdf_from_cmdarg; /* T => SDF annotation call from cmd option */
+char *__cmd_fnam;      /* command interact. input file name */
+char *__cmd_start_fnam;/* -i startup interactive input file name */
+char *__key_fnam;      /* key file name and stream */
+FILE *__tr_s;          /* trace output file - can be stdout */
+char *__tr_fnam;
+int32 __cmd_ifi;       /* constant command in_fils index */
+char *__lic_path;      /* +licpath [path] if option used */
+FILE *__sdf_s;         /* current SDF back annotate file/stream */
+struct sdfnamlst_t *__sdflst; /* list of sdf annotate option files */
+int32 __sdf_sav_enum;  /* saved error num. for annotate inhibit */
+int32 __sdf_sav_maxerrs; /* saved max errors so won't stop */
+int32 __has_sdfann_calls;/* T => no sdf annotate systsk calls in src */ 
+int32 __sdf_active;    /* T => annotating SDF - for PLI erro code  */
+struct mod_t *__sdf_mdp; /* special sdf context mod */
+
+/* cfg variables */
+char *__cmdl_library;  /* library name to file off the command line */
+struct mapfiles_t *__map_files_hd; /* hdr of map files from cmd args */
+struct mapfiles_t *__map_files_tail; /* end of map file list */
+struct cfglib_t *__cfglib_hd; /* head of list of libs for cfg */
+struct cfglib_t *__cfglib_tail; /* and tail */
+struct cfg_t *__cfg_hd;/* head of list of cfgs */
+struct cfg_t *__cur_cfg;/* current cfg */
+struct mod_t *__cfg_mdp;/* SJM - remove me - why global */
+char **__bind_inam_comptab;/* during cfg binding, comp descent comps */ 
+int32 __siz_bind_comps;/* current malloc size of table */
+int32 __last_bind_comp_ndx;/* last currently used comp end index */ 
+int32 __cfg_verbose;   /* T => emit cfg reading verbose messages */ 
+
+/* file variables */
+int32 __cur_infi;      /* index in in_fils of current file */
+struct optlst_t *__new_opt_hdr;/* header of expanded option list */
+struct optlst_t *__new_opt_end;/* wrk end of expanded option list */
+struct optlst_t *__log_olp;   /* log option, nil if none */
+struct optlst_t *__help_olp;  /* help option, nil if none */
+struct optlst_t *__quiet_olp; /* quiet option, nil if none */
+struct optlst_t *__verb_olp;  /* verbose option, nil if none */  
+int32 __vpi_argc;      /* global arg count for vpi */
+char **__vpi_argv;     /* global arg array for vpi */
+char *__vpi_argv0;     /* argv execed program name */
+char *__cur_fnam;      /* being read file name for errors */
+int32 __cur_fnam_ind;  /* index in in_fils of cur_fnam */
+int32 __sfnam_ind;     /* global file index for current stmt. */
+int32 __slin_cnt;      /* global line no. for currently check stmt */
+int32 __vpifnam_ind;   /* vpi_ global current file index */
+int32 __vpilin_cnt;    /* vpi_ global current line no. */
+struct expr_t *__srm_xp; /* current string 'file' for sreadmem */
+char *__srm_strp;      /* char. pos. in sreadmem string */
+char *__srm_strp_beg;  /* work alloced location for sreadmem string */
+int32 __srm_strp_len;  /* alloced length */
+int32 __srm_stargi;    /* current string position number */
+int32 __in_ifdef_level;/* current processing `ifdef level */ 
+int32 __ifdef_skipping;/* T = skipping not included ifdef section */
+char *__langstr;       /* work string for `language */
+int32 __doing_langdir; /* T => processing `language directive */ 
+int32 __rding_top_level; /* T => reading outside top level construct */
+
+/* variables for batch tracing */
+word64 __last_trtime;  /* last trace statement time */
+word64 __last_evtrtime;/* last event trace time */
+struct itree_t *__last_tritp;/* last event traced inst. itree loc. */ 
+
+/* command processing variables and temps */
+int32 __pv_err_cnt, __pv_warn_cnt; /* error counts */
+int32 __inform_cnt;    /* number of informs */
+int32 __outlinpos;     /* current trunc. output line pos. */
+long __mem_use;        /* counts allocated mem for debugging */
+long __mem_allocated;  /* bytes allocated */
+long __mem_freed;      /* bytes freed */
+long __memstr_use;     /* counts allocated string mem for debugging */
+long __arrvmem_use;    /* allocated bytes for Verilog arrays */
+long __mem_udpuse;     /* number of bytes used by udp tables */
+word64 __tim_zero;     /* place for time of constant 0 */
+int32 __num_glbs;      /* total no. of globals in design */
+int32 __num_inmodglbs; /* glbs thar resolve to intra module refs. */
+int32 __num_uprel_glbs;/* number of upward relative globals */
+int32 __nets_removable;/* flat no. of deletable nets */
+int32 __flnets_removable;/* removable static nets */
+int32 __gates_removable; /* removable static gates */
+int32 __flgates_removable; /* flat no. of deletable gates */
+int32 __contas_removable; /* removabale static cont. assigns */
+int32 __flcontas_removable; /* flat no. of deletable cont. assigns */
+
+/* special allocate free variables */
+struct ncablk_t *__hdr_ncablks; /* blocks used for ncomp recs */
+int32 __ncablk_nxti;   /* index of next free pos. */
+struct cpblk_t *__hdr_cpblks; /* blocks used for cell recs*/
+int32 __cpblk_nxti;    /* index of next free pos. */
+struct cppblk_t *__hdr_cppblks; /* blocks used for cell pin recs*/
+int32 __cppblk_nxti;   /* index of next free pos. */
+struct tnblk_t *__hdr_tnblks;  /* blocks of symb table tree nodes */
+int32 __tnblk_nxti;    /* index of next free pos. */ 
+struct cpnblk_t *__hdr_cpnblks;  /* blocks of explicit cell pnames */
+
+/* source processing variables */
+int32 __lin_cnt;       /* line number while reading a file */
+int32 __saverr_cnt;    /* counter to inhibit more than a err in xpr */
+int32 __max_errors;    /* maximum errors before stopping */
+int32 __rding_comment; /* flag so comment non printable chars ok */
+int32 __total_rd_lines;/* total number of lines read */
+int32 __total_lang_dirs; /* total num `language directives read */
+
+/* booleans for program options (flags) */
+int32 __verbose;       /* T => emit various extra messages */
+int32 __quiet_msgs;    /* T => do not emit msgs just errors */
+int32 __no_warns;      /* T => don't print warning msgs */
+int32 __no_errs;       /* T => don't print error msgs */
+int32 __no_informs;    /* T => don't print inform msgs (dflt) */
+int32 __debug_flg;     /* T => turn on debugging output */
+int32 __opt_debug_flg; /* T => turn on vm compiler debugging output */
+int32 __st_tracing;    /* T => trace statement execution */
+int32 __ev_tracing;    /* T => trace event schedules and processes */
+int32 __pth_tracing;   /* T => trace path delays in detail */
+int32 __prt_stats;     /* T => print design statics tables */
+int32 __prt_allstats;  /* T => print design and mod content tabs */
+int32 __show_cancel_e; /* T => chg val to x on pulse cancelled event */
+int32 __showe_onevent; /* T => if showing cancel e, drive x on event */
+int32 __warn_cancel_e; /* T => emit warn cancel_e (indep. of cancel) */
+int32 __rm_gate_pnd0s; /* T => remove #0 from all gates */
+int32 __rm_path_pnd0s; /* T => (default) remove all 0 delay paths */
+int32 __dmpvars_all;   /* T => dumpvars all variables */
+
+/* command option booleans */
+int32 __lib_verbose;   /* T => emit src.file/lib source messages */
+int32 __sdf_verbose;   /* T => emit msgs for SDF annotated delays */
+int32 __switch_verbose;/* T => emit msgs for switch/tran chan build */
+int32 __chg_portdir;   /* T => chg port dir to bid. for XL compat */
+int32 __nb_sep_queue;  /* F => old un-seperated nb in pnd0 queue */
+int32 __decompile;     /* T => decompile and print Verilog source */
+int32 __compile_only;  /* T => check syntax (inc. lib.) no quads */
+int32 __parse_only;    /* T => first pass parse only to chk sep mod */
+int32 __dflt_ntyp;     /* Verilog wire type for normal nets */
+int32 __mintypmax_sel; /* for (e:e:e) expressions value to use */
+int32 __sdf_mintypmax_sel; /* min:nom_max over-ride for $sdf_annotate */
+int32 __gateeater_on;  /* T => attempt to remove (disconnect) gates */ 
+int32 __no_expand;     /* T => make all wire vectors vectored */
+int32 __in_cell_region;/* T => turn on cell bit for every module */
+int32 __unconn_drive;  /* if none TOK_NONE else PULL 0 or PULL 1 */
+int32 __no_specify;    /* T => check but no simulate with specify */
+int32 __no_tchks;      /* T => check but no simulate with tim chks */
+int32 __lib_are_cells; /* T => if in lib, the mark as cell (dflt.) */
+int32 __design_has_cells;/* T => cells somewhere in design */
+int32 __accelerate;    /* T => use short circuits g/prt code if can */
+int32 __pli_keep_src;  /* T => keep more source stmt info for pli */
+int32 __use_impthdels; /* T => use src-dst im path dels */
+
+/* source input variables and temps */
+char __lasttoken[IDLEN];/* current last pushed back symbol name */
+char __token[IDLEN];   /* current symbol (in canonical (lc) form) */
+int32 __toktyp;        /* place for current toktyp value */
+int32 __lasttoktyp;    /* push back token type (= UNDEF if none) */
+int32 __last_attr_prefix;/* push back pending attr prefix state */
+int32 __itoklen;       /* current number token bit length */
+int32 __itoksized;     /* T => token is sized */
+int32 __itokbase;      /* base constant for number token */
+int32 __itoksizdflt;   /* '[base] form with width (uses dflt.) */
+int32 __itok_signed;   /* T => token is signed number */
+double __itok_realval; /* actual scannoer double val */
+char *__strtoken;      /* growable token to hold string */
+int32 __strtok_wid;    /* current size of string token */    
+char *__numtoken;      /* growable token to hold numbers */
+int32 __numtok_wid;    /* current size of number token */    
+int32 __letendnum_state; /* T => letter can end unsized num. */
+int32 __macro_sep_width; /* T => possible beginning of macro 2 tok num */
+int32 __maybe_2tok_sized_num; /* T => seeing number after macro num */
+int32 __macro_sav_nwid;/* value of saved first tok width */
+int32 __first_linetok; /* T => token first on line */
+int32 __file_just_op;  /* T => new file and no token yet returned */
+int32 __first_num_eol; /* T => first tok because number ended line */
+char *__macwrkstr;     /* work string for macros */ 
+int32 __mac_line_len;  /* actual length of macro line in wrk str */   
+int32 __macwrklen;     /* allocated len of mac. work string */
+struct macarg_t *__macarg_hdr; /* hdr of list of format mac. args */
+int32 __macbs_flag;    /* T=> 8'h`DEFINE catch multiple bases errors */
+char *__attrwrkstr;    /* work string for attributes */
+int32 __attr_line_len; /* actual length of attribute string */ 
+int32 __attrwrklen;    /* alloced len of attr work string - grows */
+char *__attrparsestr;  /* string to parse attr out of */
+int32 __attrparsestrlen; /* string to parse attr out of */
+int32 __attr_prefix;   /* T => token has attribute prefix */
+int32 __attr_fnam_ind; /* location of attr inst. */
+int32 __attr_lin_cnt;  /* location of attr inst. */
+struct attr_t __wrk_attr; /* latest read attribute */
+char *__xs, *__xs2;    /* places to put expr to str trunc messages */
+int32 __pv_ctv;        /* tmp for white space skipping macros */
+int32 __syncto_class;  /* token class sync skipping halted at */
+char *__exprline;      /* expr. output line work string */
+int32 __exprlinelen;   /* expr. line length */
+int32 __cur_sofs;      /* ndx of next ofs (position) in expr line */
+word32 *__acwrk;       /* a value work string for scanning number */
+word32 *__bcwrk;       /* b value work string for scanning number */
+word32 __addrtmp[2];   /* up to 32 bit temp with addr. */
+int32 __abwrkwlen;     /* current acwrk a half length in words */
+char __portnam[IDLEN];
+char __pv_varnam[IDLEN]; /* variable name */
+int32 __expr_is_lval;  /* T => parsing proc. assign lhs */
+int32 __allow_scope_var; /* T => process systask arg can be scope */
+
+/* vars needed for pushing back numbers (see var. comment) */
+int32 __lastitokbase;
+int32 __lastitoksized;
+int32 __lastitoksizdflt;
+int32 __lastitok_signed;
+int32 __lastitoklen;
+word32 *__lastacwrk;   /* special malloced push back num value */
+word32 *__lastbcwrk; 
+double __lastitok_realval;
+
+/* the module and module subtask specific work variables */
+struct mod_t *__oinst_mod;/* ptr. to old current module for copying */
+struct mod_t *__end_mdp; /* end of module def. list */
+struct cell_t *__end_cp; /* end of module inst. list */
+int32 __cp_num;          /* counter for unnamed gate/inst pos. */ 
+struct conta_t *__end_ca; /* end of module conta list */
+int32 __conta_num;     /* counter for building symbol for conta */
+struct varinitlst_t *__end_mod_varinitlst; /* end of mod var inits */
+struct symtab_t *__tfcall_wrksytp;/* wrk tf tab for undecl xmr uprel */  
+
+struct dfparam_t *__end_dfp;/* module current end of defparam list */
+struct task_pin_t *__end_tpp; /* end of task port list */
+struct task_t *__end_tbp;/* end of top level task/functions/blocks */
+struct task_t *__cur_tsk;/* ptr. to current task */
+struct net_t *__end_paramnp; /* end of ordered parm decl. list */
+struct net_t *__end_impparamnp; /* end of ordered imprt parm decl lst */
+struct net_t *__end_glbparamnp; /* end of ordered glb parm decl. lst */
+struct net_t *__end_tskparamnp; /* end of task param decl. list */
+struct ialst_t *__end_ialst; /* end of module initial/always list */
+struct gref_t *__grwrktab;  /* work table for building mod glbs */
+int32 __grwrktabsiz;        /* its size */
+int32 __grwrknum;      /* current number of glbs in work table */ 
+int32 __cur_declobj;   /* token type of declared mod or task */
+int32 __pv_stlevel;    /* tmp. for current stmt nesting level */
+int32 __design_no_strens;/* T => no strengths used in design */
+int32 __strenprop_chg; /* during propagate pass at least one chged */
+int32 __splitting;     /* T => in process of splitting module */
+int32 __processing_pnd0s;/* T => in time unit, in end #0 region */
+struct dce_expr_t *__cur_dce_expr; /* glb for edge events eval expr */
+int32 __lofp_port_decls; /* T => exclusive hdr port decls appeared */ 
+struct exprlst_t *__impl_evlst_hd; /* hdr of impl @(*) ev expr list */
+struct exprlst_t *__impl_evlst_tail; /* and its tail */
+int32 __canbe_impl_evctrl; /* glb switch to allow @(*) as ev ctrl */
+
+/* variables for dumpvars */
+int32 __dv_seen;       /* dumpvars seen but not yet setup */
+int32 __dv_state;      /* processing state of dumpvars */
+word64 __dv_calltime;  /* time dump var. first (and only) called */
+int32 __dv_dumplimit_size; /* user set limit of dv file size (0 none) */
+int32 __dv_file_size;  /* current size of dumpvars file */
+int32 __dv_time_emitted; /* flag to stop repeated same #[time] */
+char *__dv_fnam;       /* name of dumpvars output file */
+int32 __dv_func;       /* global set with type of dumpvar dumping */
+struct mdvmast_t *__dv_hdr; /* hdr of mast dumpvar rec. list */
+struct mdvmast_t *__dv_end; /* end of dumpvar rec. list */
+struct dvchgnets_t *__dv_netfreelst; /* free list of time var chges */
+int32 __dv_fd;         /* file number of dmpvars fd */
+char *__dv_buffer;     /* buffer to speed up dumpvars output */
+int32 __dv_nxti;       /* next free location */
+int32 __dv_outlinpos;  /* line postion in dump vars file */ 
+int32 __next_dvnum;    /* highest so far used dumpvars number */
+struct dvchgnets_t *__dv_chgnethdr;  /* curr. time var chg list hdr */
+int32 __dv_isall_form; /* T doing all of design dumpvar setup */
+int32 __dv_allform_insrc;/* T dumpvars all form in source */
+
+/* time scale - precision variables */
+word32 __cur_units;    /* current units (0 (1s) - 15 (1ft) */ 
+word32 __cur_prec;     /* current digits of precision (0-15) */
+word32 __des_timeprec; /* assume -, 0-15 design sim. tick prec. */
+word32 __tfmt_units;   /* %t output units (also interact. units) */
+word32 __tfmt_precunits;/* %t number of prec. digits */
+int32 __des_has_timescales;/* T => design has at least one timescale */
+char *__tfmt_suf;      /* suffix for %t */
+int32 __tfmt_minfwid;  /* minimum field width for %t */
+word64 __itoticks_tab[16];/* table of scales amount from prec. */
+char __timstr_unitsuf[4];/* to_timstr units suffix if needed */
+word64 __timstr_mult;  /* multiplier if needed */
+int32  __nd_timstr_suf;/* T => need to_timstr units */
+
+/* veriusertfs pli user function and task work variables */ 
+/* SJM 07/16/02 - need internal veriuser tfs for new +loadpli1 option */
+struct t_tfcell *__shadow_veriusertfs; /* internal copy of table */
+int32 __last_veriusertf; /* last user veriusertfs tf number */
+struct tfinst_t *__tfinst;/* current tf_ inst loc. */
+struct tfrec_t *__tfrec;/* current tf_ record */ 
+struct dceauxlst_t *__pvc_dcehdr; /* header of current pvc dces */
+struct tfrec_t *__tfrec_hdr; /* header of design wide tfrec list */ 
+struct tfrec_t *__tfrec_end; /* last el of design wide tfrec list */ 
+i_tev_ndx __tehdr_rosynci; /* hdr ndx of slot end ro sync ev lst */ 
+i_tev_ndx __teend_rosynci; /* end of slot end ro sync ev lst */ 
+int32 __now_resetting; /* reset in progress - for cbs and misctf */  
+int32 __rosync_slot;   /* T => processing tf or vpi  ro synch events */
+struct loadpli_t *__pli1_dynlib_hd; /* hd of ld pli1 dynamic lb list */
+struct loadpli_t *__pli1_dynlib_end; /* and its end */
+
+/* vpi_ work variables */
+int32 __last_systf;    /* last vpi_ registered sytfs number */
+int32 __num_vpi_force_cbs; /* number of registered vpi force cbs */
+int32 __vpi_force_cb_always; /* T => always call back on force */
+int32 __num_vpi_rel_cbs; /* number of registered vpi rel cbs */
+int32 __vpi_rel_cb_always; /* T => always call back on release */
+int32 __allforce_cbs_off; /* T => can't reenter any of all force cbs */
+int32 __allrel_cbs_off;/* T => can't reenter any of all release cbs */
+char *__wrks1;         /* work string - can not use xs if func */
+char *__wrks2;
+char __wrk_vpiemsg[IDLEN];/* error msg. work string */
+char __wrk_vpiget_str[IDLEN];/* standard required vpi get str string */
+char __wrk_vpi_product[256];/* product version */
+char __wrk_vpi_errcode[256];/* error codes are Cver err num as str */
+double __wrk_vpi_timedbl;/* time double for vpi error rec */
+char *__wrkvalbufp;    /* buf for vpi get value value_p contents */ 
+int32 __wrkval_buflen; /* and current length */
+int32 __vpi_vlog_start_done;/* T => startup done, no systf registering */
+struct systftab_t *__systftab; /* table of vpi_ systf records */
+int32 __size_systftab; /* current size of systf data rec. table */
+struct xstk_t *__cur_sysf_xsp; /* tmp stk_t for vpi sysf ret val */
+struct expr_t *__cur_sysf_expr;/* tmp calling expr. for vpi sysf*/
+struct st_t *__cur_syst_stp; /* tmp stmt for vpi syst*/
+struct dceauxlst_t *__cbvc_dcehdr; /* header of current vc cb dces */
+struct rfcblst_t *__rel_allcb_hdr;
+struct rfcblst_t *__rel_allcb_end;
+struct rfcblst_t *__force_allcb_hdr;
+struct rfcblst_t *__force_allcb_end;
+i_tev_ndx *__vpicb_tehdri; /* hdr of fixed cb tev list - 1 per class */
+i_tev_ndx *__vpicb_teendi; /* end of fixed cb tev list - 1 per class */
+int32 __have_vpi_actions;/* some use of __vpi actions */
+int32 __have_vpi_gateout_cbs;/* some use of gate out term cbs */
+struct h_t *__vpi_hfree_hdr;  /* handle free list hdr */ 
+struct hrec_t *__vpi_hrecfree_hdr;  /* handle record free list hdr */ 
+struct cbrec_t *__vpi_cbrec_hdr; /* all cbs list header */
+int32 __ithtsiz;       /* size of global work ld/drv handle table */
+struct h_t *__ithtab;  /* and the work ld/drv handle table */
+struct hrec_t *__ithrectab; /* and hrec contents of it */
+int32 __ithtsiz2;      /* size of global work ld/drv handle table */
+struct h_t *__ithtab2; /* 2nd work for in subtree handles */
+struct hrec_t *__ithrectab2; /* and hrec contents of it */
+struct vpisystf_t *__vpi_sysf_hdr; /* hdr sys func call src locs */
+struct vpisystf_t *__vpi_syst_hdr; /* hdr sys task enable src locs */
+int32 __in_vpi_errorcb;/* T => if sim ctrl, suppress error msg error */
+int32 __vpierr_cb_active; /* T => at least one cbError reged */
+int32 __acc_vpi_erroff;/* acc_ flag to stop internal acc_ error cbs */
+int32 __errorcb_suppress_msg; /* T => sim control suppress error msg */
+struct h_t *__cur_vpi_inst;
+struct hrec_t *__cur_vpi_obj;
+struct loadpli_t *__vpi_dynlib_hd; /* hd of ld vpi dynamic lib list */
+struct loadpli_t *__vpi_dynlib_end; /* and its end */
+
+/* specify work variables */
+struct spfy_t *__cur_spfy;/* current specify block */
+struct spcpth_t *__end_spcpths; /* end of specify path st. list */
+int32 __path_num;      /* counter for unnamed paths */
+struct tchk_t *__end_tchks;/* end of specify time check st. list */
+struct net_t *__end_msprms;/* end of specify specparam net list */
+struct tchk_t *__cur_tchk;
+int32 __tchk_num;      /* counter for unnamed paths */
+struct symtab_t *__sav_spsytp;/* save loc. of sym tab in spfy sect. */
+
+/* work compile global variables accessed by routines */
+int32 __v1stren;       /* wire/inst. Ver. 1 strength */
+int32 __v0stren;       /* wire/inst. Ver. 0 strength */
+word32 __pr_iodir;     /* glb. for port ref. expr. I/O direction */
+int32 __pr_wid;        /* global for total port ref. expr. width */
+int32 __mpref_explicit;/* T => mod def header port ref explicit */
+int32 __sym_is_new;    /* set when new symbol added */
+struct sy_t **__wrkstab;/* malloced work symbol table area */
+int32 __last_sy;       /* last symbol in work area */
+int32 __mod_specparams;/* number of declared specparams in mod */
+int32 __name_assigned_to;/* glb set if func. def. name assigned to */
+struct sy_t *__locfnamsyp; /* place for func. def. chk func. symbol */
+int32 __processing_func; /* T => prep or exec of function occuring */
+struct st_t **__nbstk; /* func. nest nblock stack (nxt for exec) */
+int32 __nbsti;      
+struct sy_t *__ca1bit_syp; /* gmsym for 1 bit conta converted gate */
+int32 __chking_conta;  /* T => checking a continuous assignment */
+int32 __rhs_isgetpat;  /* T => flag for checking stylized getpat */
+int32 __lhs_changed;   /* T => assignment changed lhs */
+word32 __badind_a;     /* place for a part of in error index value */
+word32 __badind_b;     /* and for b part */
+int32 __badind_wid;    /* width for bad ind (<32 expr can eval to x) */
+int32 __expr_has_real; /* T => know some real in expr. */
+int32 __isform_bi_xvi; /* glbl for IS net pin bit index in contab */
+int32 __lhsxpr_has_ndel; /* T => component wire of lhs has wire del */
+int32 __checking_only; /* T => no error msg, looking for something */ 
+int32 __task_has_tskcall;/* T => task calls other task (not name blk) */
+int32 __task_has_delay;/* T => task call has del. needs thread */
+int32 __func_has_fcall;/* T => func contains has non sys fcall */
+int32 __iact_must_sched; /* T => iact stmt(s) have $stop or loop */
+int32 __expr_rhs_decl; /* T current expr. is decl. not proc. rhs */ 
+int32 __chg_rng_direct;/* T => change rng dir. for implicitly decl */
+int32 __has_top_mtm;   /* T => for parameter rhs non () m:t:m */
+int32 __nd_0width_catel_remove; /* fx3 file 0 width concat glb */
+
+/* current Verilog module/task/block symbol environment */
+struct symtab_t **__venviron;
+int32 __top_sti;
+struct symtab_t *__modsyms;/* separate symbol table for type names */
+struct symtab_t *__pv_defsyms;/* global table for `defines */
+struct symtab_t *__syssyms;/* global tab for system tasks and funcs */
+struct sy_t **__glbsycmps; /* work global name symbols */
+struct expr_t **__glbxcmps;/* work glbal exprs */
+int32 __last_gsc;
+
+/* n.l. access headers and tables */
+struct mod_t *__modhdr;/* header of top level module list */
+struct udp_t *__udphead; /* header udps */
+struct udp_t *__udp_last;/* end udp list */
+struct inst_t **__top_itab; /* tab of virt inst ptrs of top mods */
+int32 *__top_ipind;    /* binary searchable top insts index */
+int32 __numtopm;       /* number of uninstanciated top modules */
+struct itree_t **__it_roots; /* table of root itree entries */
+int32 __ualtrepipnum;  /* udp rep. change threshold */
+struct thread_t *__initalw_thrd_hdr; /* list hd of per inst in/al thds */
+struct tev_t *__tevtab;/* reallocable tab of events and free evs */
+int32 __numused_tevtab;/* num used at least once in tev tab */
+int32 __size_tevtab;   /* num tev's allocated in tev tab */ 
+word32 *__contab;      /* design wide constant table */
+int32 __contabwsiz;    /* currrent size of const tab in words */
+int32 __contabwi;      /* next free word32 slot in const tab */
+int32 __opempty_contabi; /* special contab ndx for opempty expr leaf */
+struct contab_info_t **__contab_hash; /* contab hash information */
+
+/* n.l. access routines */  
+struct dfparam_t *__dfphdr; /* design wide defparam list header */
+int32 __num_dfps;      /* number of defparams in source */
+int32 __num_glbdfps;   /* number of defparams in design */
+int32 __num_locdfps;   /* number of local defparams */
+int32 __num_inst_pndparams;/* static number of inst. pound params */
+int32 __design_gia_pndparams;/* T => at least one gia range pnd params */
+int32 __design_gi_arrays;  /* T => design has arrays of g/i */ 
+int32 __pndparam_splits; /* T => at least one split from pound params */
+int32 __defparam_splits; /* T => at least one split from def params */
+int32 __dagmaxdist;    /* max. nested mod. inst. level */
+struct mod_t **__mdlevhdr; /* array of ptrs to ith lev linked mods */ 
+struct cell_pin_t *__cphdr;   /* header of temp. cell pin list */
+struct cell_pin_t *__cpp_last;/* current last cell pin*/
+struct tnode_t *__tmp_head;
+
+struct xldlnpp_t *__xldl_hdr; /* other side unproc. xl drv/ld npps */
+struct xldlnpp_t *__last_xldl;/* end of list - place to add after */
+struct xldlvtx_t **__xldlvtxind; /* table of xl drv/ld net/bit vtx */
+int32 __num_xldlvtxs;  /* number of lements in table */
+int32 __siz_xldlvtxtab;/* current size of table */
+
+/* udp table building variables */
+struct wcard_t *__wcardtab; /* level wildcard table */
+int32 __last_wci;      /* last wild card index for line */
+word32 *__cur_utab;    /* current udp table */
+struct utline_t *__cur_utlp; /* current line info struct */
+word32 __cur_uoval;    /* current udp line output value */
+int32 __cur_unochange; /* T => cur line has '-' no change output */
+struct udp_t *__cur_udp; /* current udp struct */
+word32 __cur_upstate;  /* current last input (state) for wide */
+int32 __cur_ueipnum;   /* cur. input pos. num of edge (NO_VAL none) */
+int32 __cur_utabsel;   /* current edge 1st char - 2nd in state line */
+
+/* expression and function processing variables */
+int32 __xndi;          /* next place in collected expression list */
+struct expr_t **__exprtab;/* table to collect expressions into */
+struct expridtab_t **__expr_idtab; /* expr parse id name info */ 
+int32 __exprtabsiz;    /* current operator precedence expr tab siz */
+int32 __last_xtk;
+struct expr_t *__root_ndp;/* root of built and alloced expression */
+struct xstk_t **__xstk;/* expr work vals */
+int32 __xspi;          /* expr. pointer */
+int32 __maxxnest;      /* current size of expr. stack - must grow */ 
+int32 __maxfcnest;     /* size of func. call task stk - must grow */
+struct task_t **__fcstk; /* function call nesting stack */
+int32 __fcspi;           /* fcall tos index */
+
+/* -y and -v library variables */
+struct vylib_t *__vyhdr; /* header of lib. file list */
+struct vylib_t *__end_vy;/* last entry on vy lib. list */
+int32 __num_ylibs;     /* number of ylibs in options */
+int32 __num_vlibs;     /* number of vlibs in options */
+
+struct undef_t *__undefhd;/* head of undefined mod/udp list */   
+struct undef_t *__undeftail; /* tail of undefined mod/udp list */
+int32 __undef_mods;    /* count of undefined modules */
+
+int32 __lib_rescan;    /* T => rescan from start after each */
+int32 __cur_passres;   /* num mods resolved in current pass */
+int32 __rescanning_lib;/* T => for `language exclude after 1st pass */ 
+int32 __num_ys;        /* number of -y options in lib. */
+char **__lbexts;       /* tab of -y library extension suffixes */
+int32 __last_lbx;
+char **__incdirs;      /* tab of +incdir paths (always / end) */
+int32 __last_incdir;
+
+/* simulation preparation variables */
+int32 __cur_npii;      /* current index of inst. in cur. mod */
+struct gate_t *__cur_npgp;/* current net-pin processing gate */
+struct mod_t *__cur_npmdp;/* current net-pin processing module */
+struct conta_t *__cur_npcap; /* current net pin proc. conta */
+struct tfrec_t *__cur_nptfrp; /* current net pin tf arg drvr rec */
+struct net_t *__cur_npnp; /* current net pin net for vpi putv driver */
+int32 __cur_npnum;     /* current port number (from 0) */
+int32 __cur_pbi;       /* current bit number for PB ICONN npp */
+int32 num_optim_cats;  /* number of optimized concats */
+int32 num_optim_catels;/* number of all elements in optim concats */
+int32 __cur_lhscati1;  /* if lhs concat, high rhs psel index */
+int32 __cur_lhscati2;  /* if lhs concat, low rhs psel index */
+struct st_t **__prpstk;/* during prep., continue stp */
+int32 __prpsti;        /* top of nested stmt. stack */
+int32 __nd_parmpnp_free; /* T => after 1st parmnpp need copy not orig */
+int32 __num_rem_gate_pnd0s; /* number of removed source #0 gates */
+int32 __num_flat_rem_gate_pnd0s; /* and flat number */
+int32 __num_rem_mipds; /* number of per bit flat MIPDs 0 delays rmed */
+int32 __last_modxi;    /* global counter used by n.l expr xform code */
+int32 __last_modsti;   /* and counter for statements */
+int32 __optimized_sim; /* generate c code - compile and dl link */
+int32 __dump_flowg;    /* dump flow graph for debugging */
+
+/* timing queue scheduling variables */
+word64 __whetime;      /* current timing wheel end time */
+word64 __simtime;      /* current simulaton time (make 64 bits ?) */
+word32 __num_execstmts;/* total number of executed statements */
+word32 __num_addedexec;/* number of executed added statements */
+word32 __num_proc_tevents;/* total num simulation events processed */
+word32 __nxtstmt_freq_update; /* next ev count for xbig freq upd. */ 
+word32 __num_cancel_tevents; /* total num sim events processed */
+int32 __num_twhevents; /* num of evs currently in timing wheel */
+int32 __num_ovflqevents; /* num of events currently in ovflow q */
+word32 __inertial_cancels; /* num resched form later inertial del */
+word32 __newval_rescheds; /* num rescheduled for same time */
+word32 __num_netchges; /* num of processed net change records */
+word32 __immed_assigns;/* num immed assign (not scheduled) */ 
+word32 __proc_thrd_tevents;/* number of processed thread events */
+struct q_hdr_t *__qlist_hdr; /* for $q_ system task q list header */
+int32 __num_switch_vtxs_processed; /* total num tranif chan vtx done */
+int32 __num_switch_chans; /* total num tranif channels in design */ 
+
+/* storage tables variables */
+byte *__btab;          /* design wide scalar (byte) storage table */
+int32 __btabbsiz;      /* scalar storage byte table size in bytes */
+int32 __btabbi;        /* during var init next index to use */ 
+byte *__nchgbtab;      /* table for per inst nchg bytes */
+int32 __nchgbtabbsiz;  /* size in btab of nchg action bits */
+int32 __nchgbtabbi;    /* during init, next index to use */
+word32 *__wtab;        /* design wide var but not mem storage area */
+int32 __wtabwsiz;      /* precomputed size (need ptrs into) in words */
+int32 __wtabwi;        /* during var init next index to use */ 
+
+/* simulation control and state values */
+int32 __stmt_suspend;  /* set when behavioral code suspends */
+int32 __run_state;     /* state of current simulation run */
+int32 __can_exec;      /* T => for vpi sim ctrl - can now exec */
+int32 __wire_init;     /* T => initializing wires */
+int32 __no_tmove_levels; /* T => infinite 0 delay loop warn path dist */
+struct thread_t *__cur_thd;  /* currently executing thread addr. */
+struct thread_t *__suspended_thd; /* cur thread before suspend */
+struct itree_t *__suspended_itp; /* cur inst ptr before suspend */
+struct itree_t *__inst_ptr; /* current if flattened itree place */ 
+struct mod_t *__inst_mod;   /* module of current itree inst */
+int32 __inum;          /* iti num  of current inst (always set) */
+struct itree_t **__itstk; /* stack of saved itrees */
+int32 __itspi;         /* top of itree stack */
+i_tev_ndx __fsusp_tevpi;/* in func. step, event to undo(cancel) */
+struct itree_t *__tmpitp_freelst; /* free list of wrk itps */
+struct inst_t *__tmpip_freelst; /* free list of wrk ips */
+struct mod_t *__last_libmdp; /* libary module just read */
+int32 __seed;          /* SJM 01/27/04 - glb seed needed if no arg */
+
+/* execution state variables */
+word32 __new_gateval;  /* new gate out val (st. possible) */
+word32 __old_gateval;  /* before gate change (st. possible) */
+word32 __new_inputval; /* new input value for tracing message */
+word32 __old_inputval; /* prev. value of input for wide udp eval */
+word64 __pdlatechgtim; /* for path tracing latest path chg time */
+word64 __pdmindel;     /* for path minimum path delay */
+int32 __nd_neg_del_warn; /* T => must emit warn (or err) for <0 del */ 
+int32 __force_active;  /* T => for trace deassign while force */ 
+int32 __assign_active; /* T => for trace release activates assgn */
+struct dceauxlst_t *__qcaf_dcehdr; /* header of current qcaf dces */
+int32 __nxt_chan_id;   /* cnter and size for assigning chan ids */
+int32 __chanallocsize; /* size of allocated chan tables */
+struct chanrec_t *__chantab;/* tab of channel records (one per id) */
+struct vtxlst_t *__stvtxtab[8]; /* per stren value vertex list */ 
+struct vtxlst_t *__stvtxtabend[8]; /* and ptr to last el on each */
+struct vtxlst_t *__chg_vtxlst_hdr; /* list of chged vertices to store */
+struct vtxlst_t *__chg_vtxlst_end; /* and ptr to end */
+struct vtxlst_t *__off_vtxlst_hdr; /* bid chan vtx list for marks off */
+struct vtxlst_t *__off_vtxlst_end; /* and ptr to end */
+struct vtxlst_t *__vtxlst_freelst; /* free list for vtx lists */
+struct vtx_t *__vtx_freelst;  /* free list for re-using vtxs */   
+struct edge_t *__edge_freelst; /* free list for re-using edges */
+
+word32 __acum_sb;      /* accumulator for stren tran chan combined */
+word32 __acum_a;       /* accumulator for tran chan non stren */
+word32 __acum_b;
+byte *__acum_sbp;      /* ptr to stacked strength byte */
+struct xstk_t *__acum_xsp; /* ptr to stacked strength byte */
+
+/* end of time slot variables, strobe, monitor, time check */
+struct strblst_t *__strobe_hdr; /* list strobe display at slot end */
+struct strblst_t *__strobe_end; /* end of strobe display list */
+struct strblst_t *__strb_freelst; /* head of free strobe elements */
+struct st_t *__monit_stp;/* monit if chg display at slot end stmt */
+struct itree_t *__monit_itp; /* current monitor itree element */
+word32 __slotend_action; /* word32 of 1 bit switches set for action */
+int32 __monit_active;  /* T => monitor can trigger (default) */
+struct dceauxlst_t *__monit_dcehdr; /* header of current dces */
+struct fmonlst_t *__fmon_hdr; /* list of execed (enabled) fmonitors */
+struct fmonlst_t *__fmon_end;
+struct fmonlst_t *__cur_fmon; /* current fmon list entry */
+struct fmselst_t *__fmonse_hdr; /* this slot end fmon eval list */
+struct fmselst_t *__fmonse_end;
+struct fmselst_t *__fmse_freelst; /* fmon slot end free list head */
+
+/* interactive execution variables */
+struct itree_t *__scope_ptr; /* from $scope itree place */
+struct task_t *__scope_tskp; /* from $scope task if present */ 
+struct symtab_t *__last_iasytp; /* last found symbol symbol table */
+struct iahist_t *__iahtab;/* table of history commands */
+int32 __iahsiz;        /* current size of history cmd table */
+int32 __iah_lasti;     /* current (latest) command */
+struct hctrl_t *__hctrl_hd; /* head of active iact stmts */
+struct hctrl_t *__hctrl_end;/* and end */
+int32 __history_on;    /* collecting and saving history is on */
+int32 __hist_cur_listnum;/* number to list for :history command */
+int32 __iasetup;       /* F until interactive entered */
+int32 __ia_entered;    /* F (also for reset) until iact entered */
+int32 __iact_state;    /* T => in interactive processing */
+int32 __iact_can_free; /* T => non monitor/strobe, can free */
+int32 __no_iact;       /* T => no interactive processing for run */
+int32 __intsig_prt_snapshot; /* T => on no iact end, print shapshot */
+int32 __reset_count;   /* count of the number of rests ($reset) */
+int32 __reset_value;   /* 2nd $reset value preserved after reset */ 
+int32 __list_cur_ifi;  /* index in in fils of current source file */
+int32 __list_cur_fd;   /* current opened file no. (-1 if none) */
+int32 __list_cur_lini; /* current line no. in current dbg file */
+int32 __list_cur_listnum;/* number of lines to list at once */
+int32 __list_arg_lini; /* for :b (:ib), user list argument */
+int32 __iact_scope_chg;/* T => always move scope to cur on iact st. */
+struct brkpt_t *__bphdr;/* header of breakpoint list */ 
+int32 __nxt_bpnum;     /* next breakpoint number to use */
+struct dispx_t *__dispxhdr;/* header of display list */ 
+int32 __nxt_dispxnum;  /* next display number to use */
+struct itree_t *__last_stepitp;/* last step inst. itree loc. */ 
+struct task_t *__last_steptskp;/* last step task */
+int32 __last_stepifi;  /* last step in fils index */
+word64 __last_brktime; /* last break or step time */
+int32 __dbg_dflt_base; /* :print debugger default base */ 
+int32 __iact_stmt_err; /* T => syntax error for iact stmt */
+struct mod_t *__iact_mdp; /* current iact dummy module */
+int32 __sav_mtime_units; /* prep of iact statements needs tfmt units */
+
+/* interactive variables */
+char *__iahwrkline;    /* interactive command line work area */
+int32 __iahwrklen;     /* allocated len of iah work string */
+int32 __pending_enter_iact;/* T => enter iact as soon as can */
+int32 __iact_reason;   /* reason for entering interactive state */
+int32 __single_step;   /* T => need to single step */
+int32 __step_rep_cnt;  /* number of times to repeat step */
+int32 __step_from_thread;/* T step from non thread loc. (^c?) */
+struct itree_t *__step_match_itp; /* for istep, exec itp must match */
+int32 __step_lini;     /* line stepping from (must step to next) */  
+int32 __step_ifi;      /* and file */ 
+int32 __verbose_step;  /* T => emit location each step */
+int32 __stop_before_sim; /* T => enter interactive before sim */
+int32 __dbg_stop_before; /* if >100, T (-100) stop before sim */ 
+struct st_t *__blklast_stp; /* stmt loc. saved last stmt in block */
+struct dceauxlst_t *__iact_dcehdr; /* header of current iact dces */
+
+/* event list variables */
+struct telhdr_t **__twheel;
+int32 __twhsize;       /* current size for timing wheel */   
+int32 __cur_twi;
+i_tev_ndx __p0_te_hdri;/* pound 0 event list header */
+i_tev_ndx __p0_te_endi;/* pound 0 event list end */
+i_tev_ndx __cur_te_hdri;
+i_tev_ndx __cur_tevpi; /* ptr to event list for adding to front */
+i_tev_ndx __cur_te_endi;
+i_tev_ndx __tefreelsti;/* free list for events */
+struct tedputp_t *__tedpfreelst; /* tf_ putp rec free list header */
+struct teputv_t *__teputvfreelst; /* vpi_ put value free list hdr */ 
+struct nchglst_t *__nchgfreelst; /* change element free list */
+struct tc_pendlst_t *__tcpendfreelst; /* free slot end changed tchks */
+struct dltevlst_t *__dltevfreelst; /* pend double event free list */
+struct tevlst_t *__ltevfreelst; /* pend event free list */
+i_tev_ndx __nb_te_hdri; /* non-blocking new end queue hd */ 
+i_tev_ndx __nb_te_endi; /* and tail */
+
+/* net change list variables */
+struct nchglst_t *__nchg_futhdr; /* header of future net chg list */
+struct nchglst_t *__nchg_futend; /* end (for add) of future net chgs */
+struct tc_pendlst_t *__tcpendlst_hdr; /* header of pending */ 
+struct tc_pendlst_t *__tcpendlst_end; /* end of pending */
+i_tev_ndx *__wrkevtab; /* for exit, trace of pending events */
+int32 __last_wevti;    /* last filled */
+int32 __size_wrkevtab; /* and current allocated size */ 
+
+/* b tree variables */
+struct bt_t *__btqroot;/* root of timing overflow q */
+/* for fringe node, node previous to place where inserted */
+/* storage for path to fringe - node passed thru if not fringe */
+struct bt_t **__btndstk; /* nodes with node list length */
+struct bt_t **__btndhdrstk;
+int32 __topi;
+int32 __max_level;
+int32 __nd_level;
+
+
+static void open_logfile(void);
+static void init_glbs(void);
+static void set_tfmt_dflts(void);
+static void init_ds(void);
+static void init_cfg(void);
+static void xpnd_args(int32, char **);
+static struct optlst_t *alloc_optlst(void);
+static void copy_xpnd_onelev_args(void);
+static void ins_optlst_marker(int32, int32);
+static void dmp_xpnd_olist(register struct optlst_t *);
+static int32 find_opt(char *);
+static void do_args(void);
+static void bld_inflist(void);
+static void do_sdflocdef(char *, char *, int32);
+static void do_cmdmacdef(char *, struct optlst_t *);
+static int32 bld_incdtab(char *, struct optlst_t *);
+static struct loadpli_t *bld_loadpli_lbs(char *, struct optlst_t *, int32);
+static int32 bld_boot_rout_list(struct loadpli_t *, char *);
+static int32 check_rnam_str(char *);
+static int32 bld_lbxtab(char *, struct optlst_t *);
+static void add_lbfil(char *, char);
+static struct vylib_t *alloc_vylib(char *);
+static int32 add_suppwarn(char *, struct optlst_t *);
+static void wrhelp(void);
+static void init_modsymtab(void);
+static void init_stsymtab(void);
+static void add_systsksym(struct systsk_t *);
+static void add_sysfuncsym(struct sysfunc_t *);
+static void prep_vflist(void);
+static void do_timescale(void);
+static int32 prt_summary(void);
+static void prt_deswide_stats(void);
+static int32 count_tran_nets(void);
+static void mem_use_msg(int32);
+static void prt_alldesmod_tabs(void);
+static void prt2_desmod_tab(void);
+static void bld_modnam(char *, struct mod_t *, int32);
+static void count_mods(int32 *, int32 *);
+static int32 count_cells(struct mod_t *);
+static int32 count_gates(struct mod_t *, int32 *);
+static void prt2_permod_wiretab(void);
+static int32 cnt_modprt_bits(struct mod_t *);
+static void cnt_modwires(struct mod_t *, int32 *, int32 *, int32 *, int32 *, int32 *,
+ int32 *, int32 *);
+static void st_prt2_permod_wiretab(void);
+static void st_cnt_modprt_bits(struct mod_t *, int32 *, int32 *, int32 *);
+static void st_cnt_modwires(struct mod_t *, int32 *, int32 *, int32 *, int32 *);
+static void prt2_permod_tasktabs(void);
+static void cnt_modtasks(struct mod_t *, int32 *, int32 *, int32 *, int32 *, int32 *,
+ int32 *);
+static void prt_modhdr(struct mod_t *);
+static void reset_cntabs(int32 *, int32 *, int32 *, int32 *, int32 *, int32, int32 *,
+ int32 *, int32 *, int32);
+static void accum_usecnts(struct mod_t *, int32 *, int32 *, int32 *, int32 *, int32 *,
+ int32 *, int32 *, int32 *, int32 *);
+
+
+
+/* extern prototypes (maybe defined in this module) */
+extern int32 __dig_main(int32, char **);
+extern void __setup_dbmalloc(void);
+extern void __start_chkchain(void);
+extern void __my_ftime(time_t *, time_t *);
+extern void __prt_end_msg(void);
+extern void __add_infil(char *);
+extern void __grow_infils(int32);
+extern int32 __open_sfil(void);
+extern void __push_vinfil(void);
+extern int32 __pop_vifstk(void);
+extern void __do_decompile(void);
+extern void __process_cdir(void);
+extern char *__get_tmult(char *, word32 *);
+extern void __prt2_mod_typetab(int32);
+extern int32 __enum_is_suppressable(int32);
+
+/* extern prototypes defined in other module */
+extern void __xform_nl_to_modtabs(void);
+extern void __initialize_dsgn_dces(void);
+extern int32 __comp_sigint_handler(void);
+extern char *__my_malloc(int32);
+extern char *__my_realloc(char *, int32 , int32);
+/* pv stralloc is fast small section string alloc but can't be freed */ 
+extern char *__pv_stralloc(char *);
+extern struct symtab_t *__alloc_symtab(int32);
+extern char *__prt_vtok(void);
+extern char *__to_wtnam2(char *, word32);
+extern int32 __fr_wtnam(int32);
+extern int32 __get_arrwide(struct net_t *);
+extern struct tnode_t *__vtfind(char *, struct symtab_t *);
+extern void __do_foreign_lang(void);
+extern void __init_acc(void);
+extern void __my_dv_flush(void);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern void __setup_contab(void);
+extern void __my_exit(int32, int32);
+
+
+extern char *__to_timunitnam(char *, word32);
+extern FILE *__tilde_fopen(char *, char *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern char *__schop(char *, char *);
+extern void __my_fprintf(FILE *, char *, ...);
+extern void __cv_msg(char *s, ...);
+extern void __dbg_msg(char *, ...);
+extern void __crit_msg(char *s, ...);
+extern void __ip_msg(char *s, ...);
+extern void __ip2_msg(char *s, ...);
+extern void __pv_ferr(int32, char *, ...);
+extern void __pv_err(int32, char *, ...);
+extern void __pv_warn(int32, char *, ...);
+extern void __gfwarn(int32, word32, int32, char *, ...);
+extern void __pv_fwarn(int32, char *, ...);
+extern void __gfinform(int32, word32, int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __finform(int32, char *, ...);
+extern void __fterr(int32, char *, ...);
+extern void __pv_terr(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern int32 __fixup_nl(void);
+extern void __prep_sim(void);
+extern void __unget_vtok(void);
+extern void __call_all_checktfs(void);
+extern int32 __get1_vtok(FILE *);
+extern void __skipover_line(void);
+extern int32 __chk_beg_line(int32);
+extern void __collect_line(void);
+extern void __process_sdf_files(void);
+extern void __exec_all_compiletf_routines(void);
+extern void __vpi_endcomp_trycall(void);
+extern void __free_design_pnps(void);
+extern void __rem_0path_dels(void);
+extern void __init_sim(void);
+extern void __call_misctfs_streset(void);
+extern void __vpi_startreset_trycall(void);
+extern void __reset_to_time0(void);
+extern void __pv_sim(void);
+extern void __vpi_endsim_trycall(void);
+extern void __alloc_xsval(struct xstk_t *, int32);
+extern void __my_fclose(FILE *);
+extern void __my_free(char *, int32);
+extern void __maybe_open_trfile(void);
+extern int32 __get_cmdtok(FILE *);
+extern void __do_macdefine(char *, char *);
+extern void __add_sym(char *, struct tnode_t *);
+extern void __setup_veriusertf_systfs(void);
+extern void __call_vlog_startup_procs(void);
+extern void __dmp_mod(FILE *, struct mod_t *);
+extern void __dmp_udp(FILE *, struct udp_t *);
+extern void __get_vtok(void);
+extern void __rd_ver_src(void);
+extern void __rd_ver_mod(void);
+extern int32 __bqline_emptytail(register char *);
+extern void __process_pli_dynamic_libs(struct loadpli_t *);
+extern int32 __rd_cfg(void);
+extern void __expand_lib_wildcards(void); 
+extern void __rd_ver_cfg_src(void);
+extern void __sym_addprims(void);
+
+
+
+/* externs for system error messages */
+extern int32 errno;
+
+/* special external for setjmp environment - reset environment */ 
+extern jmp_buf __reset_jmpbuf;
+extern char __pv_ctab[];
+
+
+
+/*
+ * main
+ */
+extern int32 __dig_main(int32 argc, char **argv)
+{
+ int32 rv, save_quiet;
+ long t1;
+ double timd1;
+ char s1[RECLEN];
+
+ /* only does something if db malloc define set */ 
+ __setup_dbmalloc();
+
+
+ __start_sp = __end_sp = NULL;
+ __log_s = NULL;
+ /* set compilation int32 signal and save entry signal so can restore */
+#if defined(INTSIGS)
+ __old_int_sig = (sighandler *) signal(SIGINT, __comp_sigint_handler);
+#else
+ __old_int_sig = (sighandler *) signal(SIGINT,
+   (void (*)()) __comp_sigint_handler);
+#endif
+
+ init_glbs();
+
+
+ /* vpi argument special format argv only set if needed */
+ __vpi_argc = 0;
+ __vpi_argv = NULL;
+ /* no by convention argv 0 always has program name */
+ __vpi_argv0 = __pv_stralloc(argv[0]);
+
+ /* expand options so have list that looks as if all on command line */
+ xpnd_args(argc, argv);
+
+ /* process special early options - any errors here only to std out */
+ /* notice no verbose message for quiet */
+ if (__quiet_olp != NULL)
+  {
+   __quiet_msgs = TRUE;
+   /* vendor1 runs with -q need to allow verbose switches to be turned on */ 
+   __verbose = FALSE;
+  }
+ open_logfile();
+
+#ifdef __linux__
+#ifdef __ELF__
+ __platform = __pv_stralloc("Linux-elf");
+#else
+ __platform = __pv_stralloc("Linux-aout");
+#endif
+#endif
+
+#ifdef __CYGWIN32__
+ __platform = __pv_stralloc("Cygwin32");
+#endif
+
+#ifdef __FreeBSD__
+ __platform = __pv_stralloc("X86 FreeBSD");
+#endif
+
+#ifdef __APPLE__
+ __platform = __pv_stralloc("Mac OSX");
+#endif
+
+#ifdef __sparc
+ __platform = __pv_stralloc("Sparc-Solaris");
+#endif
+#if defined(__i386__) && defined(__SVR4)
+ __platform = __pv_stralloc("X86-Solaris");
+#endif
+
+#ifdef __hpux
+ __platform = __pv_stralloc("hpux");
+#endif
+
+#ifdef __CYGWIN32__
+ __platform = __pv_stralloc("Cygwin32");
+#endif
+
+ __vers = __pv_stralloc(VERS);
+ __vers2 = __pv_stralloc(VERS2);
+ __ofdt = __pv_stralloc(OFDT);
+ __ip2_msg("%s%s of %s (%s).\n", __vers, __vers2, __ofdt, __platform);
+
+ /* SJM 08/27/03 - change so have separate commercial and open source msgs */ 
+ __ip_msg("Copyright (c) 1991-2005 Pragmatic C Software Corp.\n");
+ __ip_msg(
+  "  All Rights reserved.  Licensed under the GNU General Public License (GPL).\n");
+ __ip_msg(
+  "  See the 'COPYING' file for details.  NO WARRANTY provided.\n");
+
+ __cv_msg("Today is %s.\n", __pvdate);
+
+ if (__help_olp != NULL)
+  {
+   wrhelp();
+   __cv_msg("**Special help mode successfully completed.\n");
+   return(0);
+  }
+
+ if (__verb_olp != NULL)
+  {
+   if (!__quiet_msgs)
+    { __verbose = TRUE; __cv_msg("  Verbose mode is on.\n"); }
+  }
+ if (__log_s != NULL && strcmp(__log_fnam, DFLT_LOGFNAM) != 0)
+  {
+   if (__verbose)
+    __cv_msg("  Output log will be written to \"%s\".\n", __log_fnam);
+  }
+ if (__verbose) __cv_msg("  Invoked by: \"%s\".\n", argv[0]);  
+
+ do_args();
+
+
+ bld_inflist();
+
+ __modhdr = __end_mdp = NULL;
+ __init_acc();
+
+ init_modsymtab();
+ /* must initialize pli table after file processed */
+ init_stsymtab();
+ /* --- DBG remove
+ if (__verbose) 
+  __cv_msg("  Initialization used %ld bytes of allocated memory (%ld free).\n",
+  __memstr_use + __mem_use + TWHINITSIZE*sizeof(struct telhdr_t),
+  __mem_free);
+ --- */
+
+
+ /* SJM 12/05/03 - for now assuming if +config options to specify lib map */ 
+ /* file, then do not read default lib.map in cwd - is that correct? */ 
+ if (__map_files_hd == NULL)
+  {
+   FILE *fp;
+
+   if ((fp = __tilde_fopen("lib.map", "r")) != NULL)
+    {
+     __my_fclose(fp); 
+     __map_files_hd = __map_files_tail = (struct mapfiles_t *) 
+      __my_malloc(sizeof(struct mapfiles_t));
+     __map_files_hd->mapfnam = __pv_stralloc("lib.map");
+     __map_files_hd->mapfnxt = NULL;
+     if (__verbose)
+      {
+       __cv_msg(
+        "  Using map.lib config file because no +config options specified.\n");
+      }
+    }
+   else if (__verbose)
+    {
+     __cv_msg(
+      "  P1364 2001 config map library not specified - using -y/-v libraries.\n"); 
+    }
+  }
+
+ /* read the cfg lib.map file list and build internal d.s. */ 
+ if (__verbose) __cv_msg("  Begin Translation:\n");
+
+ if (__map_files_hd != NULL)
+  {
+   /* SJM - 05/26/04 if config used, ignore any command line .v files */
+   if (__last_inf != __last_optf)
+    {
+     __pv_warn(3138,
+      "config used but verilog files specified on command line - files ignored");
+    }
+   if (__verbose) __cv_msg("  Reading config map.lib files:\n");
+   __rd_cfg();
+   if (__cmdl_library == NULL) __cmdl_library = __pv_stralloc("work");
+   /* after expansion, each library element is a concrete file name */
+   __expand_lib_wildcards(); 
+   __rd_ver_cfg_src();
+  }
+  else
+   {
+    /* use pre-2001 files reading routines */
+    prep_vflist();
+    __rd_ver_src();
+   }
+
+ if (__parse_only)
+  {
+   __cv_msg("  Parsing only run complete.\n");
+   __my_ftime(&__end_time, &__end_mstime);
+   if (__pv_err_cnt != 0) rv = 1; else rv = 0;
+   goto done2;
+  }
+
+ if (__in_ifdef_level != 0)
+  {
+   __pv_err(924, "last `ifdef unterminated in source stream");
+  }
+ if (__end_mdp == NULL)
+  {
+   if (__pv_err_cnt != 0) goto err_done;
+   __crit_msg("**Design contains no modules - nothing to do.\n");
+   goto set_etime;
+  }
+
+ /* calls to fixup routines here */
+ if (__verbose)
+  {
+   __cv_msg("  Begin pass 2:\n");
+  }
+ /* if verbose off will not print anything */
+ mem_use_msg(FALSE); 
+ if (!__fixup_nl()) goto err_done;
+
+ if (__pv_err_cnt != 0) goto err_done; 
+ if (__decompile) __do_decompile();
+ __my_ftime(&__end_comp_time, &__end_comp_mstime);
+ if (__numtopm == 0)
+  {
+   __crit_msg("  Unable to begin simulation - no top level modules.\n");   
+set_etime:
+   __my_ftime(&__end_time, &__end_mstime);
+   rv = 1;
+   goto done2;
+  }
+ 
+ /* notice compilation must include prep. for at least udp checking */
+ __prep_sim();
+
+ if (__pv_err_cnt == 0)
+  {
+   if (__prt_stats || __prt_allstats)
+    {
+     save_quiet = __quiet_msgs;
+     __quiet_msgs = FALSE;
+     prt_alldesmod_tabs();
+     __quiet_msgs = save_quiet;
+    }
+   else if (__verbose)
+    {
+     save_quiet = __quiet_msgs;
+     __quiet_msgs = FALSE;
+     prt_deswide_stats();
+     __quiet_msgs = save_quiet;
+    }
+  }
+ /* RELEASE remove -- */
+ /* LOOKATME - for now need this even when read source only mode */
+ if (__verbose)
+  {
+   __cv_msg(
+    "  Variable storage in bytes: %d for scalars, %d for non scalars.\n", 
+    (__btabbsiz + __nchgbtabbsiz), 4*__wtabwsiz);
+  }
+
+ if (__compile_only)
+  {
+   __cv_msg("  Translation only run complete.\n");
+   __my_ftime(&__end_time, &__end_mstime);
+   goto done;
+  }
+ if (__pv_err_cnt != 0) goto err_done;
+
+ if (__verbose) __cv_msg("  Begin load/optimize:\n");
+ mem_use_msg(FALSE);
+
+ __run_state = SS_LOAD;
+ __can_exec = FALSE;
+
+ /* now that all storage allocated and given some val, call checktf */
+ /* routines, these can call anything not sim queue depended but shouldn't */
+ if (__tfrec_hdr != NULL)
+  {
+   __run_state = SS_RESET;
+   __call_all_checktfs();
+   __run_state = SS_LOAD;
+  }
+
+ /* notice advantage of option is allows use in initialization */
+ /* assumes called from first top level module */ 
+ if (__sdflst != NULL)
+  {
+   __process_sdf_files();
+   if (__pv_err_cnt != 0) goto err_done;
+  }
+ __sfnam_ind = 0;
+ __slin_cnt = 0;
+ /* final step in loading is calling vpi_ systf checktf routines */ 
+ /* can not do until here because d.s. built */ 
+ if (__vpi_sysf_hdr != NULL || __vpi_syst_hdr != NULL)
+  {
+   /* compiletf run in reset state because no time and no events */
+   __run_state = SS_RESET;
+   __exec_all_compiletf_routines();
+   __run_state = SS_LOAD;
+  }
+
+ /* still can use changed params (either type) to elaborate delays */
+ /* from params and set delays even where no delay in source here */
+ /* BEWARE - must not move to after new compile prep xform because exprs */
+ /*          exprs not moved (if move later must add link and chg expr ptr */
+ if (__have_vpi_actions) __vpi_endcomp_trycall();
+
+
+ if (__pv_err_cnt != 0) goto err_done;
+
+ /* SJM 01/14/00 - always can free design pnps since (LABEL does not work */
+ /*                (error emitted) in $sdf_annotate systask calls */
+ /* SJM for sdf do not free - see if works  
+ __free_design_pnps();
+ -- */
+
+ /* after here, delays elaborated - only vpi change of delays now possible */
+ /* but vpi_ change probably not alloed under P1364 */
+ /* SJM 01/14/00 - must allow param changes from label during sim */
+ /*                for sdf annotate calls - undefined change points */ 
+ /*                also can't remove all 0 paths delays may change still */ 
+ if (!__has_sdfann_calls)
+  {
+   /* go through disable all 0 delay only paths - never causes error */
+   if (__rm_path_pnd0s) __rem_0path_dels();
+  }
+
+ /* but can remove gates and any added all 0 mipds (maybe added again if */
+ /* annotate systask used later) so need messages here */ 
+ if (__num_rem_gate_pnd0s != 0 && __verbose)
+  {
+   __cv_msg(
+    "  %d (%d flat) gate or udp zero delays coded in source removed.\n",
+    __num_rem_gate_pnd0s, __num_flat_rem_gate_pnd0s);
+  }
+ if (__num_rem_mipds != 0 && __verbose)
+  {
+   __cv_msg("  %d flattened bits of 0 delay MIPDS removed - no effect.\n",
+    __num_rem_mipds);
+  }
+ /* always do transformations to group elements into per module tables */
+ __xform_nl_to_modtabs();
+
+ /* SJM 05/04/05 - now can only initialize dce previous values */
+ __initialize_dsgn_dces();
+
+ __init_sim();
+ __my_ftime(&__end_prep_time, &__end_prep_mstime);
+
+ if (__verbose) __cv_msg("  Begin simulation:\n");
+ mem_use_msg(TRUE);
+ if (__verbose) __cv_msg("\n");
+
+ /* on setup returns 0, on lng jmp returns 1, but always just exec sim */
+ /* since restart */
+ /* on set returns 0, do not run re-init code */
+ if (setjmp(__reset_jmpbuf) != 0)
+  {
+   if (__tfrec_hdr != NULL) __call_misctfs_streset();
+   if (__have_vpi_actions) __vpi_startreset_trycall();
+   __now_resetting = TRUE;
+   __run_state = SS_RESET;
+   /* change to sim run state in here */
+   __reset_to_time0();
+   /* by here state back to SIM */
+  }
+
+
+ __pv_sim();
+ /* LOOKATME - think also call end sim cb here but LRM says $finish */
+ if (__have_vpi_actions) __vpi_endsim_trycall();
+
+ /* LOOKATME - remove since does not match ovi __cv_msg("\n"); */
+ /* notice must know current end time */
+ __my_ftime(&__end_time, &__end_mstime);
+ __prt_end_msg();
+ goto done;
+
+err_done:
+ __cv_msg("  Unable to begin simulation.\n");
+ __my_ftime(&__end_time, &__end_mstime);
+
+done:
+ if (__dv_fd != -1) __my_dv_flush();
+ if (__verbose)
+  {
+   if (__dv_fd != -1)
+    {
+     if ((t1 = lseek(__dv_fd, 0, SEEK_END)) != -1) 
+      {
+       __cv_msg("  $dumpvars %ld bytes written to file \"%s\".\n", t1,
+        __dv_fnam); 
+      }
+    } 
+   mem_use_msg(FALSE);
+  }
+ rv = prt_summary();
+done2:
+ /* DBG remove --- */
+ if (__xspi != -1 || __itspi != -1 || __fcspi != -1)
+  __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ strcpy(s1, ctime(&__end_time));
+
+ s1[24] = '\0';
+ __pvdate = __pv_stralloc(s1);
+ timd1 = (double) (__end_time - __start_time)
+  + ((double) (__end_mstime - __start_mstime))/1000.0;
+ __cv_msg("End of %s%s at %s (elapsed %.1lf seconds).\n",
+  __vers,__vers2, __pvdate, timd1);
+ __my_exit(rv, FALSE);
+ /* needed to stop warns but exit prevents control from reaching here */
+ return(0);
+}
+
+#ifdef __DBMALLOC__
+/*
+ * start malloc debugging - can call from anywhere
+ */
+extern void __setup_dbmalloc(void)
+{
+ union dbmalloptarg m;
+
+ /* m.i = M_HANDLE_IGNORE; */
+ m.i = M_HANDLE_ABORT;
+ dbmallopt(MALLOC_WARN,&m);
+ m.str = "malloc.log";
+ dbmallopt(MALLOC_ERRFILE,&m);
+
+ /* set to 1 to turn on */
+ /* --- */
+ m.i = 1;
+ dbmallopt(MALLOC_CKCHAIN,&m);
+ /* -- */
+
+ /* 0 means don't check str/mem func args */
+ /* --- */
+ m.i = 1;
+ dbmallopt(MALLOC_CKDATA,&m);
+ /* --- */
+ /* --- */
+ m.i = 0;
+ dbmallopt(MALLOC_REUSE,&m);
+ /* --- */
+ /* -- */
+ m.i = 2;
+ /* m.i = 3; */
+ dbmallopt(MALLOC_FILLAREA, &m);
+ /* -- */
+}
+
+extern void __start_chkchain(void)
+{
+ union dbmalloptarg m;
+
+ m.i = 1;
+ dbmallopt(MALLOC_CKCHAIN,&m);
+ /* -- */
+ m.i = 1;
+ dbmallopt(MALLOC_CKDATA,&m);
+ /* -- */
+}
+#else
+/* nil if db malloc not used */
+extern void __setup_dbmalloc(void)
+{ 
+}
+extern void __start_chkchain(void)
+{
+}
+#endif
+
+/*
+ * routine to compute current time in seconds and milliseconds (if possible)
+ */
+extern void __my_ftime(time_t *secs, time_t *msecs)
+{
+ struct timeval tv;
+ struct timezone tz;
+
+ if (gettimeofday(&tv, &tz) == EINVAL) __arg_terr(__FILE__, __LINE__);
+ 
+ *secs = (long) tv.tv_sec;
+ *msecs = (long) (tv.tv_usec/1000);
+}
+
+/*
+ * print ending verbose message 
+ */
+extern void __prt_end_msg()
+{
+ int32 t1;
+ double timd1, timd2, timd3;
+
+ t1 = (int32) __num_proc_tevents - (int32) __proc_thrd_tevents;
+ if (t1 < 0) t1 = 0;
+ __cv_msg(
+  "%d simulation events and %u declarative immediate assigns processed.\n",
+   t1 , __immed_assigns);
+ /* number of cancelled should equal newval (0 del.) and inertial cancels? */ 
+ if (__num_execstmts - __num_addedexec > 0)
+  {
+     __cv_msg("%u behavioral statements executed (%u procedural suspends).\n",
+      __num_execstmts - __num_addedexec, __proc_thrd_tevents);
+  }
+ else
+  {
+   if (__proc_thrd_tevents > 0 && __optimized_sim)
+    {
+     __cv_msg("Optimized code execution (%u procedural suspends).\n",
+      __proc_thrd_tevents);
+    }
+  }
+ if (__verbose && __debug_flg)
+  {
+   __cv_msg(
+    "  %u(%u) inertial reschedules, %u net changes, %u continuous assigns,\n",
+    __num_cancel_tevents, __inertial_cancels + __newval_rescheds,
+    __num_netchges, __immed_assigns);
+   __cv_msg("  and %d tran/tranif switch vertices processed.\n",
+    __num_switch_vtxs_processed);
+  }
+
+ timd1 = (double) (__end_comp_time - __start_time)
+  + ((double) (__end_comp_mstime - __start_mstime))/1000.0;
+ timd2 = (double) (__end_prep_time - __end_comp_time)
+  + ((double) (__end_prep_mstime - __end_comp_mstime + 50))/1000.0;
+ timd3 = (double) (__end_time - __end_prep_time)
+  + ((double) (__end_mstime - __end_prep_mstime + 50))/1000.0;
+ __cv_msg(
+  "  Times (in sec.):  Translate %.1f, load/optimize %.1f, simulation %.1f.\n",
+  timd1, timd2, timd3);
+}
+
+/*
+ * STARTUP INITIALIZATION ROUTINES
+ */
+
+/*
+ * initialize various globals (including flags)
+ *
+ * sets things that are set and then returned to initial value when done
+ * but routine that uses variable
+ */
+static void init_glbs(void)
+{
+ char *cp;
+ char s1[RECLEN];
+
+ /* initialize things needed before any memory can be allocated */
+ __mem_use = __mem_freed = __mem_allocated = __memstr_use = 0L;
+ __mem_udpuse = __arrvmem_use = 0L;
+
+ /* initialize some vars */
+ __pv_err_cnt = __pv_warn_cnt = __inform_cnt = 0;
+ __max_errors = MAX_ERRORS;
+
+ /* initialize flags */
+ __verbose = FALSE;
+ __quiet_msgs = FALSE;
+ __lib_verbose = FALSE;
+ __cfg_verbose = FALSE;
+ __lib_rescan = FALSE;
+ __rescanning_lib = FALSE;
+ __switch_verbose = FALSE;
+ __chg_portdir = FALSE;
+ __cmd_s = NULL;
+ __cmd_fnam = NULL;
+ __cmd_start_fnam = NULL;
+ __key_s = __save_key_s = NULL;
+ /* default for trace output if stdout */
+ __tr_s = stdout; 
+ __tr_fnam = __pv_stralloc("stdout");
+ __sdflst = NULL;
+ __sdf_s = NULL;
+ __sdf_mdp = NULL;
+ __sdf_verbose = FALSE; 
+ __sdf_opt_log_fnam = NULL;
+ __sdf_opt_log_s = NULL;
+ __has_sdfann_calls = FALSE;
+
+ __map_files_hd = __map_files_tail = NULL;
+ __cmdl_library = NULL;
+ __cfglib_hd = __cfglib_tail = NULL;
+ __cfg_hd = NULL;
+ __cur_cfg = NULL;
+ __cfg_mdp = NULL;
+ __bind_inam_comptab = NULL;
+ __siz_bind_comps = 0;
+ __last_bind_comp_ndx = -1;
+
+ __sdf_active = FALSE;
+ __sdf_no_warns = FALSE;
+ __sdf_no_errs = FALSE;
+ __sdf_from_cmdarg = FALSE;
+ __nokey_seen = FALSE;
+ __key_fnam = NULL;
+ /* notice warns on by default */
+ /* should be more selective about which warnings turned off */
+ __no_warns = FALSE;
+ __no_errs = FALSE;
+ __outlinpos = 0;
+ /* notice informs off by default */
+ __no_informs = TRUE;
+ __compile_only = FALSE;
+ __parse_only = FALSE;
+ __optimized_sim = FALSE;
+ __dump_flowg = FALSE;
+ __opt_debug_flg = FALSE;
+ __iact_state = FALSE;
+ __no_iact = FALSE;
+ __intsig_prt_snapshot = FALSE;
+ __pending_enter_iact = FALSE;
+ __stop_before_sim = FALSE;
+ /* this is for :reset so off (< 100) on start */
+ __dbg_stop_before = 0;
+ __decompile = FALSE;
+ __debug_flg = FALSE;
+ __mintypmax_sel = DEL_TYP;
+ __sdf_mintypmax_sel = __mintypmax_sel;
+ __chking_conta = FALSE;
+ __rhs_isgetpat = FALSE;
+ __expr_rhs_decl = FALSE;
+ __chg_rng_direct = FALSE;
+ __has_top_mtm = FALSE;
+ __nd_0width_catel_remove = FALSE;
+ __next_dvnum = 0;
+ __dv_allform_insrc = FALSE;
+ __st_tracing = FALSE;
+ __ev_tracing = FALSE;
+ __pth_tracing = FALSE;
+ /* SJM 07/13/01 - add option and get code to support src-dst MIPDs working */
+ __use_impthdels = FALSE;
+ __gateeater_on = FALSE;
+ __prt_stats = FALSE;
+ __prt_allstats = FALSE;
+ /* show cancel event pulse handling all off (Verilog default inertial) */ 
+ __show_cancel_e = FALSE;
+ __showe_onevent = TRUE;
+ __warn_cancel_e = FALSE;
+ /* always want to remove all 0 delay path unless turned off */
+ __rm_path_pnd0s = TRUE;
+ __rm_gate_pnd0s = FALSE;
+ __num_rem_gate_pnd0s = 0;
+ __num_flat_rem_gate_pnd0s = 0;
+ __num_rem_mipds = 0;
+ __dmpvars_all = FALSE;
+ __num_execstmts = 0;
+ __num_addedexec = 0;
+ /* this may get turned on for good in timformat fixup code */ 
+ __nd_timstr_suf = FALSE;
+ __num_glbs = 0;
+ __num_uprel_glbs = 0;
+ __num_dfps = __num_glbdfps = __num_locdfps = 0;
+ __num_inst_pndparams = 0;
+ __design_gi_arrays = FALSE;
+ __design_gia_pndparams = FALSE;
+ __mdlevhdr = NULL;
+ __xldl_hdr = __last_xldl = NULL; 
+ __xldlvtxind = NULL;
+ __num_xldlvtxs = 0;
+ __siz_xldlvtxtab = 0;
+
+ __nets_removable = __flnets_removable = 0;
+ __gates_removable = __flgates_removable = 0;
+ __contas_removable = __flcontas_removable = 0;
+ __num_ys = 0;
+ __num_inmodglbs = 0;
+ __accelerate = TRUE;
+ __history_on = TRUE;
+
+ /* set compiler directive values - can be reset to these with `resetall */
+ set_tfmt_dflts();
+ __dflt_ntyp = N_WIRE;
+ __in_cell_region = FALSE;
+ __unconn_drive = TOK_NONE;
+ __no_expand = FALSE;
+ __no_specify = FALSE;
+ __no_tchks = FALSE;
+ __lib_are_cells = TRUE;
+ __design_has_cells = FALSE;
+
+ /* 06/22/00 - SJM - possible cross macro 2 token must start off */
+ __macro_sep_width = FALSE;
+ __maybe_2tok_sized_num = FALSE;
+ __macro_sav_nwid = FALSE;
+
+ __rding_comment = FALSE;
+ __splitting = FALSE;
+ __run_state = SS_COMP;
+ __no_tmove_levels = INFLOOP_MAX;
+ __checking_only = TRUE;
+ __iasetup = FALSE;
+ __ia_entered = FALSE;
+ __force_active = FALSE;
+ __assign_active = FALSE;
+ __qcaf_dcehdr = NULL;
+
+ /* need to leave these so stmt chking does not do special func body chk */
+ __name_assigned_to = TRUE;
+ __locfnamsyp = NULL;
+ /* assume no strengths - if unc. pull, turned off before stren marking*/
+ __design_no_strens = TRUE;
+ __cur_dce_expr = NULL;
+ __impl_evlst_hd = NULL;
+ __impl_evlst_tail = NULL;
+ __canbe_impl_evctrl = FALSE;
+ __nb_sep_queue = TRUE;
+
+ __my_ftime(&__start_time, &__start_mstime);
+ cp = ctime(&__start_time);
+ strcpy(s1, cp);
+ s1[24] = '\0';
+ __pvdate = __pv_stralloc(s1);
+ __pv_timestamp = __pv_stralloc(s1);
+ __end_comp_time = 0L;
+ __end_comp_mstime = 0L;
+ __end_prep_time = 0L;
+ __end_prep_mstime = 0L;
+ /* sim time need for possible pli calls */ 
+ __simtime = 0ULL;
+ init_ds();
+ init_cfg();
+}
+
+/*
+ * set various time format defaults
+ */
+static void set_tfmt_dflts(void)
+{
+ /* default is 1 ns. */
+ __cur_units = 9;
+ __cur_prec = 0;
+ /* this is always set to min. of all modules (and is total) */
+ __des_timeprec = 9;
+ __tfmt_units = 9;
+ /* next three default values required by LRM */
+ __tfmt_precunits = 0;
+ __tfmt_suf = __pv_stralloc("");
+
+ /* this includes space + suffix if suffix is non empty string */
+ __tfmt_minfwid = 20;    
+ __des_has_timescales = FALSE;
+}
+
+/*
+ * initialize data structures if needed
+ */
+static void init_ds(void)
+{
+ register int32 i;
+ int32 len;
+ word64 p, u;
+ char *chp;
+
+ /* HOME env. variable for use by tilde */
+ if ((chp = (char *) getenv ("HOME")) == NULL) strcpy(__pv_homedir, ".");
+ else
+  {
+   strcpy(__pv_homedir, chp);
+   len = strlen(__pv_homedir);
+   if (__pv_homedir[len - 1] == '/') __pv_homedir[len - 1] = '\0';
+  }
+
+ __blnkline = __my_malloc(RECLEN + 1);
+ for (i = 0; i < OUTLINLEN; i++) __blnkline[i] = ' ';
+ __blnkline[OUTLINLEN] = '\0';
+
+ __venviron = (struct symtab_t **)
+  __my_malloc(MAXLEVELS*sizeof(struct symtab_t *));
+ for (i = 0; i < MAXLEVELS; i++) __venviron[i] = NULL;
+
+ __glbsycmps = (struct sy_t **) __my_malloc(MAXGLBCOMPS*sizeof(struct sy_t *));
+ __glbxcmps = (struct expr_t **)
+  __my_malloc(MAXGLBCOMPS*sizeof(struct expr_t *));
+ for (i = 0; i < MAXGLBCOMPS; i++)
+  { __glbsycmps[i] = NULL; __glbxcmps[i] = NULL; }
+
+ /* allocate a work table for building per module global refs */
+ __grwrktab = (struct gref_t *) __my_malloc(100*sizeof(struct gref_t));
+ __grwrktabsiz = 100; 
+ __grwrknum = 0;
+
+ /* initialize expr. parse table and ID name/loc table */
+ __exprtabsiz = 1000;
+ __exprtab = (struct expr_t **)
+  __my_malloc(__exprtabsiz*sizeof(struct expr_t *));
+ /* need first node in case of null expr. */
+ __exprtab[0] = (struct expr_t *) __my_malloc(sizeof(struct expr_t));
+ for (i = 1; i < __exprtabsiz; i++) __exprtab[i] = NULL;
+ __expr_is_lval = FALSE;
+
+ __expr_idtab = (struct expridtab_t **) 
+  __my_malloc(__exprtabsiz*sizeof(struct expridtab_t *));
+ for (i = 0; i < __exprtabsiz; i++) __expr_idtab[i] = NULL;
+
+ /* allocate and initialize eval stack - must grow for recursive functions */
+ __maxxnest = MAXXNEST;
+ __xstk = (struct xstk_t **) __my_malloc(__maxxnest*sizeof(struct xstk_t *));
+ /* assume 1 work dummy size here - just need some value */
+ for (i = 0; i < __maxxnest; i++)
+  {
+   __xstk[i] = (struct xstk_t *) __my_malloc(sizeof(struct xstk_t));
+   /* this fills xstack table fields */ 
+   __alloc_xsval(__xstk[i], 1);
+  }
+ /* notice this is dynamic nesting of recursive func. calls - must grow */ 
+ __maxfcnest = MAXFCNEST;
+ __fcstk = (struct task_t **)
+  __my_malloc(__maxfcnest*sizeof(struct task_t *));
+ for (i = 0; i < __maxfcnest; i++) __fcstk[i] = NULL;
+
+ __nbstk = (struct st_t **) __my_malloc(MAXPRPSTNEST*sizeof(struct st_t *));
+ for (i = 0; i < MAXPRPSTNEST; i++) __nbstk[i] = NULL;
+ __nbsti = -1;
+
+ /* allocate macro definition work string (it grows)*/
+ __macwrklen = IDLEN;
+ __macwrkstr = __my_malloc(__macwrklen);
+ __mac_line_len = 0;
+ __macarg_hdr = NULL;
+ __macbs_flag = FALSE;
+
+ /* allocate attribute collection work string (it grows)*/
+ __attrwrklen = IDLEN;
+ __attrwrkstr = __my_malloc(__attrwrklen);
+ __attr_line_len = 0;
+ __attr_prefix = FALSE; 
+
+ __attrparsestrlen = IDLEN;
+ __attrparsestr = __my_malloc(__attrparsestrlen);
+
+ /* make this so big that even if IDLEN length 2 IDs still will fit */
+ __xs = __my_malloc(2*IDLEN);
+ __xs2 = __my_malloc(2*IDLEN);
+ __wrks1 = __my_malloc(2*IDLEN);
+ __wrks2 = __my_malloc(2*IDLEN);
+ /* SJM 03/20/00 alloc start size for string and number assembly tokens */
+ __strtoken = __my_malloc(IDLEN + 1);
+ __strtok_wid = IDLEN + 1;
+ __numtoken = __my_malloc(IDLEN + 1);
+ __numtok_wid = IDLEN + 1;
+
+ /* need malloc since need to be re-allocated */ 
+ __acwrk = (word32 *) __my_malloc(WRDBYTES*DFLTIOWORDS);
+ __bcwrk = (word32 *) __my_malloc(WRDBYTES*DFLTIOWORDS);
+ __abwrkwlen = DFLTIOWORDS;
+ /* to turn off number, set to TRUE but must be left in F state */
+ __exprline = __my_malloc(IDLEN);
+ __cur_sofs = 0;
+ __exprlinelen = IDLEN;
+ __force_base = BNONE;
+ /* first to use is base */
+ __last_veriusertf = BASE_VERIUSERTFS - 1; 
+ /* SJM 07/16/02 - nee internal shdown table for dynamic pli1 boostrap ret */
+ __shadow_veriusertfs = NULL;
+ /* this is used as counter then added to veriuser tf last */
+ __last_systf = __last_veriusertf;
+
+ /* globals for $q_ system tasks */
+ __qlist_hdr = NULL;
+
+ /* not used until sim, but init here */
+ __tfinst = NULL;
+ __tfrec = NULL;
+ __tfrec_hdr = __tfrec_end = NULL;
+ /* lists of locationss for every registered vpi systf that has compiletf */
+ __vpi_sysf_hdr = __vpi_syst_hdr = NULL;
+ /* SJM 07/08/02 - now pli loads dynamic library with bootstrp func */  
+ __vpi_dynlib_hd = __vpi_dynlib_end = NULL;
+ __pli1_dynlib_hd = __pli1_dynlib_end = NULL;
+
+ __siz_in_fils = MAXFILS;
+ __in_fils = (char **) __my_malloc(__siz_in_fils*sizeof(char *));
+ __last_lbf = 0;
+ __last_srcf = 0;
+ __inclst_hdr = __inclst_end = NULL;
+ __vinstk = (struct vinstk_t **)
+  __my_malloc(MAXFILNEST*sizeof(struct vinstk_t *));
+ __vyhdr = NULL;
+ __end_vy = NULL;
+ __num_ylibs = __num_vlibs = 0;
+
+ /* initialized here since built-in and define + options are added */
+ __pv_defsyms = __alloc_symtab(FALSE);
+ /* LOOKATME - need more than thes 6 defines */
+ __do_macdefine("`__cver__", "");
+ __do_macdefine("`__CVER__", "");
+ __do_macdefine("`__P1364__", "");
+ __do_macdefine("`__p1364__", "");
+
+ __last_lbx = -1;
+ __lbexts = (char **) __my_malloc(MAXLBEXTS*sizeof(char *));
+ __lbexts[0] = NULL;
+
+ __last_incdir = -1;
+ __incdirs = (char **) __my_malloc(MAXINCDIRS*sizeof(char *));
+ __incdirs[0] = NULL;
+
+ __undefhd = __undeftail = NULL;
+ __undef_mods = 0;
+
+ __wsupptab = (word32 *) __my_malloc(MAXWSWRDS*sizeof(word32));
+ for (i = 0; i < MAXWSWRDS; i++) __wsupptab[i] = 0L;
+ __in_ifdef_level = 0;
+ __ifdef_skipping = FALSE;
+ __processing_func = FALSE;
+ __first_num_eol = FALSE;
+ __langstr = NULL;
+ __doing_langdir = FALSE;
+ __rding_top_level = TRUE;
+
+ __itstk = (struct itree_t **)
+  __my_malloc((MAXITDPTH + 1)*sizeof(struct itree_t *));
+ for (i = 0; i <= MAXITDPTH; i++) __itstk[i] = NULL;
+ __itstk[0] = (struct itree_t *) 0xffffffff;
+ __itstk = &(__itstk[1]);
+
+ __xspi = __itspi = __fcspi = -1;
+ __inst_ptr = NULL;
+ __inst_mod = NULL;
+ /* change to test different udp reps. */
+ __ualtrepipnum = UALTREPIPNUM;
+ /* DBG all wide __ualtrepipnum = 1; */ 
+
+ /* filled when used */
+ __wcardtab = (struct wcard_t *)
+  __my_malloc((MAXUPRTS + 1)*sizeof(struct wcard_t));
+
+ __prpstk = (struct st_t **) __my_malloc(MAXPRPSTNEST*sizeof(struct st_t *));
+ for (i = 0; i < MAXPRPSTNEST; i++) __prpstk[i] = NULL;
+
+ __btndstk = (struct bt_t **) __my_malloc(MAXBTDPTH*sizeof(struct bt_t *));
+ __btndhdrstk = (struct bt_t **) __my_malloc(MAXBTDPTH*sizeof(struct bt_t *));
+ for (i = 0; i < MAXBTDPTH; i++) __btndstk[i] = __btndhdrstk[i] = NULL;
+
+ __tmpitp_freelst = NULL;
+ __tmpip_freelst = NULL;
+ 
+ __last_libmdp = NULL;
+
+ /* SJM 01/27/04 - initializing global seed for $random and other dist */
+ /* systfs in case uses omits the seed inout arg */ 
+ /* guessing that 0 will match 2001 LRM rand generator standard */
+ __seed = 0;
+
+ __dv_fnam = __pv_stralloc(DFLTDVFNAM);
+ __dv_fd = -1;
+ __dv_file_size = 0;
+ __dv_buffer = NULL;
+ __dv_nxti = 0;
+
+ /* BEWARE - since this table reallocated for cgen access must index */
+ /* not use address ptr because when reallated to grow ptr will be wrong */
+ __tevtab = (struct tev_t *) __my_malloc(2048*sizeof(struct tev_t));
+ /* do not need to initialize because freed and reused where init needed */
+ __size_tevtab = 2048;
+
+ /* pre-allocate design wide constant table and set some fixed values */
+ __setup_contab();
+
+ /* no var storage value table until prep */
+ __wtab = NULL;
+ __wtabwsiz = -1;
+ __wtabwi = -1;
+
+ __btab = NULL;
+ __btabbsiz = -1;
+ __btabbi = -1;
+
+ __nchgbtab = NULL;
+ __nchgbtabbsiz = -1;
+ __nchgbtabbi = -1;
+
+ /* least first one unused */
+ __numused_tevtab = 0; 
+ /* need to set tev list empty because need to allocate for action cbs */
+ /* this makes sure at start event table empty */
+ __tefreelsti = -1;
+
+ /* set ticks long structs - 16 (built into lang.) by word64 values */
+ __itoticks_tab[0] = 1ULL;
+ u = 10ULL;
+ for (i = 1; i < 16; i++) 
+  {
+   p = u *__itoticks_tab[i - 1];
+   __itoticks_tab[i] = p;
+  }
+ __tim_zero = 0ULL;
+ /* initialize multichannel descriptor table */
+ /* notice on reset will be overwritten */
+ /* SJM 03/26/00 - 32 is unusable for new Verilog 2000 file I/O but */
+ /* init here so wil show as not open */
+ for (i = 2; i < 32; i++)
+  {
+   __mulchan_tab[i].mc_s = NULL;
+   __mulchan_tab[i].mc_fnam = NULL;
+  }
+ /* desc. 0 is hardwired as stdout and 1 to stderr */
+ __mulchan_tab[0].mc_s = stdout;
+ __mulchan_tab[0].mc_fnam = __pv_stralloc("stdout"); 
+ __mulchan_tab[1].mc_s = stderr;
+ __mulchan_tab[1].mc_fnam = __pv_stralloc("stderr"); 
+
+ /* AIV 09/05/03 - initialization code for new P1364 2001 fileio streams */
+ /* SJM 09/05/03 - rewrote to match mulchan I/O program organization */
+
+ /* use first free with closing and freeing algorithm per Unix and mcds */
+ /* SJM 05/17/04 - LOOKATME - stdio.h 16 value is wrong - trying 1024 */ 
+ __fio_fdtab = (struct fiofd_t **)
+  __my_malloc(MY_FOPEN_MAX*sizeof(struct fiofd_t *));
+
+ for (i = 0; i < MY_FOPEN_MAX; i++) __fio_fdtab[i] = NULL; 
+
+ /* numbers probably same as unix but LRM requires predefined 0,1,2 */
+ __fio_fdtab[0] = (struct fiofd_t *) __my_malloc(sizeof(struct fiofd_t));
+ __fio_fdtab[0]->fd_error = FALSE;
+ /* name only needed for user opened in case stdio fopen fails */
+ __fio_fdtab[0]->fd_name = __pv_stralloc("stdin"); 
+ __fio_fdtab[0]->fd_s = stdin;
+
+ __fio_fdtab[1] = (struct fiofd_t *) __my_malloc(sizeof(struct fiofd_t));
+ __fio_fdtab[1]->fd_error = FALSE;
+ __fio_fdtab[1]->fd_name = __pv_stralloc("stdout"); 
+ __fio_fdtab[1]->fd_s = stdout;
+
+ __fio_fdtab[2] = (struct fiofd_t *) __my_malloc(sizeof(struct fiofd_t));
+ __fio_fdtab[2]->fd_error = FALSE;
+ __fio_fdtab[2]->fd_name = __pv_stralloc("stdout"); 
+ __fio_fdtab[2]->fd_s = stdout;
+
+ __fiolp = NULL;
+ __fiofp = NULL;
+ __scanf_pos = -1;
+
+ /* start with no array for ncomp elements */
+ __ncablk_nxti = -1;
+ __hdr_ncablks =  NULL;
+ __cpblk_nxti = -1;
+ __hdr_cpblks = NULL;
+ __cppblk_nxti = -1;
+ __hdr_cppblks = NULL;
+ __tnblk_nxti = -1;
+ __hdr_tnblks = NULL;
+
+ /* initialize the vpi_ variables - reset must leave */
+ __vpi_hfree_hdr = NULL;
+ __vpi_hrecfree_hdr = NULL;
+ __have_vpi_actions = FALSE;
+ __have_vpi_gateout_cbs = FALSE; 
+ /* normal mode is not free iterator handles unless user does explicitly */
+ __wrkval_buflen = 0;
+
+ __num_vpi_force_cbs = 0;
+ __vpi_force_cb_always = FALSE;
+ __vpi_rel_cb_always = FALSE;
+ __num_vpi_rel_cbs = 0;
+ /* SJM 07/24/00 - add flag so no all force/rel vc reentry - off until call */
+ __allforce_cbs_off = FALSE;
+ __allrel_cbs_off = FALSE;
+
+ __vpi_cbrec_hdr = NULL;
+ __errorcb_suppress_msg = FALSE;
+ /* debugging values - set when vpi dump obj routine called */
+ __cur_vpi_inst = NULL;
+ __cur_vpi_obj = NULL;
+ __in_vpi_errorcb = FALSE;
+ __acc_vpi_erroff = FALSE;
+ __ithtsiz = 0;
+ __ithtab = NULL;
+ __ithrectab = NULL;
+ __ithtsiz2 = 0;
+ __ithtab2 = NULL;
+ __ithrectab2 = NULL;
+
+ __vpicb_tehdri = (i_tev_ndx *)
+  __my_malloc((TOPVPIVAL + 1)*sizeof(i_tev_ndx));
+ __vpicb_teendi = (i_tev_ndx *)
+  __my_malloc((TOPVPIVAL + 1)*sizeof(i_tev_ndx));
+ for (i = 0; i <= TOPVPIVAL; i++)
+  __vpicb_tehdri[i] = __vpicb_teendi[i] = -1;
+
+ __rosync_slot = FALSE;
+ __tehdr_rosynci = __teend_rosynci = -1;
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+
+ /* must allocate first block */
+ __hdr_cpnblks = (struct cpnblk_t *) __my_malloc(sizeof(struct cpnblk_t));
+ __hdr_cpnblks->cpnblknxt = NULL;
+ __hdr_cpnblks->cpnblks = __hdr_cpnblks->cpn_start_sp 
+  = __my_malloc(BIG_ALLOC_SIZE);
+ __hdr_cpnblks->cpn_end_sp = __hdr_cpnblks->cpn_start_sp + BIG_ALLOC_SIZE - 16;
+
+}
+
+/*
+ * initialize cfg globals
+ *
+ * CFG FIXME - just add to init glb do not need routine
+ */
+static void init_cfg(void)
+{
+}
+
+/*
+ * OPTION AND COMMAND FILE ARGUMENT PROCESSING ROUTINES
+ */
+
+/* these must be positive word32 up to 16 bit values - gaps ok */
+#define CO_HELP 1
+#define CO_F 2
+#define CO_LOG 3
+#define CO_KEY 4
+#define CO_IAINPUT 5
+#define CO_VERB 6
+#define CO_QUIET 7
+#define CO_MAXERRS 8
+#define CO_C 9
+#define CO_PARSEONLY 10
+#define CO_D 11
+#define CO_A 12
+#define CO_AOFF 13
+#define CO_X 14
+#define CO_STOP 15
+#define CO_E 16
+#define CO_W 17
+#define CO_INFORM 18
+#define CO_UC 19
+#define CO_V 20
+#define CO_Y 21
+#define CO_LBVERB 22
+#define CO_LIBORD 23
+#define CO_LIBRESCAN 24
+#define CO_LIBNOHIDE 25
+#define CO_DEBUG 26
+#define CO_MINDEL 27
+#define CO_TYPDEL 28
+#define CO_MAXDEL 29
+/* options than need to be changed to system tasks */
+/* also $cleartrace here */
+#define CO_SETTRACE 30 
+#define CO_SETEVTRACE 31
+#define CO_SETPTHTRACE 32
+#define CO_TRACEFILE 33
+/* this uses assumed lengths - if change option name must change consts */
+/* also not in normal table */
+#define CO_LBEXT 34
+#define CO_SUPPWARNS 35
+#define CO_DEFINE 36
+#define CO_INCDIR 37
+#define CO_GATE_EATER 38
+#define CO_NO_GATE_EATER 39
+#define CO_PRTSTATS 40
+#define CO_PRTALLSTATS 41
+#define CO_SPIKEANAL 42
+#define CO_SDFANNOTATE 43
+#define CO_SDFVERB 44
+#define CO_NOIACT 45
+#define CO_NOSPFY 46
+#define CO_NOTCHKS 47
+#define CO_LIBNOCELL 48
+
+
+#define CO_SHOWCANCELE 51
+#define CO_NOSHOWCANCELE 52
+#define CO_PULSEX_ONEVENTE 53
+#define CO_PULSEX_ONDETECT 54
+#define CO_WARNCANCELE 55
+#define CO_NOWARNCANCELE 56
+#define CO_RMGATEPND0S 57
+#define CO_NORMPTHPND0S 58
+#define CO_NOKEEPCOMMANDS 59
+#define CO_PLIKEEPSRC 60
+#define CO_OPT_SIM 61
+#define CO_OPT_DEBUG 62
+#define CO_SNAPSHOT 63
+#define CO_FRSPICE 64
+#define CO_SWITCHVERB 65
+#define CO_CHG_PORTDIR 66
+#define CO_NB_NOSEP_QUEUE 67
+#define CO_SDF_LOG 68
+#define CO_SDF_NO_ERRS 69
+#define CO_SDF_NO_WARNS 70 
+#define CO_LOADPLI1 71
+#define CO_LOADVPI 72
+#define CO_LIBLIST 73
+#define CO_LIBMAP 74
+
+/* command line option table */
+/* this does not need to be alphabetical */
+/* single token but parsed options not here */
+static struct namlst_t cmdopts[] = {
+ { CO_HELP, "-h" },
+ { CO_HELP, "-H" },
+ { CO_HELP,  "-?" },
+ { CO_F , "-f" },
+ { CO_LOG, "-l" },
+ { CO_SDF_LOG, "+sdf_log_file" },
+ { CO_KEY, "-k" },
+ { CO_IAINPUT, "-i" },
+ { CO_VERB, "+verbose" },
+ { CO_QUIET, "-q" },
+ { CO_MAXERRS, "+maxerrors" },
+ { CO_C, "-c" },
+ { CO_PARSEONLY, "+parseonly" },
+ { CO_D, "-d" },
+ { CO_A, "-a" }, 
+ { CO_AOFF, "-aoff" },
+ { CO_X, "-x" }, 
+ { CO_STOP,  "-s" },
+ { CO_E , "-e" },
+ { CO_W , "-w" },
+ { CO_INFORM,  "-informs" },
+ { CO_UC, "-u"},
+ { CO_V, "-v" },
+ { CO_Y, "-y" },
+ { CO_LBVERB, "+libverbose" },
+ { CO_LIBORD, "+liborder" },
+ { CO_LIBRESCAN, "+librescan" },
+ { CO_LIBNOHIDE, "+libnohide" },
+ { CO_DEBUG, "+debug" },
+ { CO_MINDEL, "+mindelays" },
+ { CO_TYPDEL , "+typdelays" },
+ { CO_MAXDEL , "+maxdelays" },
+ { CO_SETTRACE, "-t" },
+ { CO_SETEVTRACE, "-et" },
+ { CO_SETPTHTRACE, "-pt" },
+ { CO_TRACEFILE, "+tracefile" },
+ { CO_NO_GATE_EATER, "+nogateeater" },
+ { CO_GATE_EATER, "+gateeater" },
+ { CO_PRTSTATS, "+printstats" },
+ { CO_PRTALLSTATS, "+printallstats" },
+ { CO_SDFANNOTATE, "+sdfannotate" },  
+ { CO_SDFANNOTATE, "+sdf_annotate" },  
+ { CO_SDFVERB, "+sdfverbose" },
+ { CO_SDFVERB, "+sdf_verbose" },
+ { CO_NOIACT, "+nointeractive" },
+ { CO_NOSPFY, "+nospecify" },
+ { CO_NOTCHKS, "+notimingchecks" },
+ { CO_NOTCHKS, "+notimingcheck" },
+ { CO_LIBNOCELL, "+libnocell" },
+ { CO_SPIKEANAL, "+spikes" },
+ { CO_SHOWCANCELE, "+show_canceled_e" },
+ { CO_NOSHOWCANCELE, "+noshow_canceled_e" },
+ { CO_PULSEX_ONEVENTE, "+pulse_e_style_onevent" },
+ { CO_PULSEX_ONDETECT, "+pulse_e_style_ondetect" },
+ { CO_WARNCANCELE, "+warn_canceled_e" },
+ { CO_NOWARNCANCELE, "+nowarn_canceled_e" },
+ { CO_RMGATEPND0S, "+remove_gate_0delays" },
+ { CO_NORMPTHPND0S, "+noremove_path_0delays" },
+ { CO_NOKEEPCOMMANDS, "+nokeepcommands" },
+ { CO_OPT_SIM, "+optimized_sim" },
+ { CO_OPT_SIM, "-O" },
+ { CO_OPT_DEBUG, "+Odebug" },
+ { CO_SNAPSHOT, "+snapshot" },
+ { CO_FRSPICE, "+fromspice" },
+ { CO_SWITCHVERB, "+switchverbose" },
+ { CO_CHG_PORTDIR, "+change_port_type" },
+ { CO_NB_NOSEP_QUEUE, "+no_separate_nb_queue" },
+ { CO_SDF_NO_ERRS, "+sdf_noerrors" },
+ { CO_SDF_NO_WARNS, "+sdf_nowarns" },
+ { CO_LIBLIST, "-L"},
+ { CO_LIBMAP, "+config"}
+};
+#define NCMDOPTS (sizeof(cmdopts) / sizeof(struct namlst_t))
+
+/*
+ * build command option linked list
+ *
+ * only fatal errors here since still no log file
+ */
+static void xpnd_args(int32 argc, char **argv)
+{
+ register int32 i;
+ int32 oi;
+ struct optlst_t *olp;
+ char *chp;
+
+ /* first convert arg list to option list */
+ /* know argv[0] is name of program */
+ /* for command args "file" name is [arg] and lin cnt is arg. no. */
+ /* 0 is [arg] and later none, and 1 is stdin */
+ __opt_hdr = __opt_end = NULL;
+ __last_inf = -1;
+ __add_infil("[args]");
+ __cur_fnam = __in_fils[__last_inf];
+ /* for command number, location indicator - literal index for this */
+ __add_infil("CMD");
+ __cmd_ifi = __last_inf;
+
+ for (olp = NULL, i = 1; i < argc; i++)
+  {
+   if ((int32) strlen(argv[i]) >= IDLEN - 1)
+    {
+     __lin_cnt = i;
+     __pv_ferr(919, "command argument too long (%d) - ignored", IDLEN - 1);
+     continue;
+    }
+   olp = alloc_optlst();
+   if (__opt_end == NULL) __opt_hdr = __opt_end = olp;
+   else { __opt_end->optlnxt = olp; __opt_end = olp; }
+   olp->opt = __pv_stralloc(argv[i]);
+   /* level is 0 for top */
+   olp->optlev = 0;
+   /* this must be index of args */
+   olp->optfnam_ind = 0;
+   olp->optlin_cnt = i;
+  }
+
+ /* repeatedly pass through list and expand good -fs */
+ copy_xpnd_onelev_args();
+ /* DBG --- notice no debug flag at this point ---
+ dmp_xpnd_olist(__opt_hdr);
+ --- */
+
+ /* final step sets some pointers for special options into tab */
+ for (olp = __opt_hdr; olp != NULL; olp = olp->optlnxt)
+  {
+   chp = olp->opt;
+   if (olp->is_bmark || olp->is_emark) continue;
+
+   if (*chp == '+' || *chp == '-')
+    {
+     oi = find_opt(chp);
+     olp->optnum = oi;
+     /* notice - algorithm is to use last if repeated */
+     switch (oi) {
+      case CO_LOG: __log_olp = olp; break;   
+      case CO_HELP: __help_olp = olp; break;
+      case CO_QUIET: __quiet_olp = olp; break;
+      case CO_VERB: __verb_olp = olp; break;
+     }
+    }
+  }
+}
+
+/*
+ * allocate and initialize an option list element
+ */
+static struct optlst_t *alloc_optlst(void)
+{
+ struct optlst_t *olp;
+
+ olp = (struct optlst_t *) __my_malloc(sizeof(struct optlst_t)); 
+ olp->opt = NULL;
+ olp->optnum = 0;
+ olp->optlev = 0;
+ olp->is_bmark = FALSE;
+ olp->is_emark = FALSE;
+ olp->is_argv = FALSE;
+ olp->argv_done = FALSE;
+ olp->optfnam_ind = 0;
+ olp->optlin_cnt = -1;
+ olp->optlnxt = NULL;
+ return(olp);
+}
+
+/*
+ * copy from 1 level from hdr liast to new list
+ */
+static void copy_xpnd_onelev_args(void)
+{
+ register struct optlst_t *olp;
+ int32 savlast_inf, savlin_cnt, some_expanded, lev;
+ struct optlst_t *olp2, *new_olp;
+ FILE *opt_s;
+ char *chp;
+
+ __new_opt_end = __new_opt_hdr = NULL;
+ for (lev = 1;; lev++)
+  {
+   some_expanded = FALSE;
+   for (olp = __opt_hdr; olp != NULL;) 
+    {
+     /* anything but -f just remains in list */
+     /* optnum only CO_F if previous error */
+     if (olp->is_bmark || olp->is_emark
+       || strcmp(olp->opt, "-f") != 0 || olp->optnum == CO_F)
+      {
+       olp2 = olp->optlnxt;
+       if (__new_opt_end == NULL) __new_opt_hdr = __new_opt_end = olp;
+       else { __new_opt_end->optlnxt = olp; __new_opt_end = olp; }
+       olp->optlnxt = NULL;
+       olp = olp2;
+       continue;
+      } 
+     /* logic to possibly (if can be opened) a -f [file] element */
+     olp2 = olp->optlnxt; 
+
+     if (olp2 == NULL) { olp->optnum = CO_F; break; }
+     chp = olp2->opt;
+
+     /* if cannot open, or not followed by file name, leave - error later */
+     /* but leave both -f and [arg] but move 1 past arg */
+     if (chp == NULL || *chp == '+' || *chp == '-'
+      || (opt_s = __tilde_fopen(chp, "r")) == NULL)
+      {
+       olp->optnum = CO_F;
+       if (__new_opt_end == NULL) __new_opt_hdr = __new_opt_end = olp;
+       else { __new_opt_end->optlnxt = olp; __new_opt_end = olp; }
+       __new_opt_end->optlnxt = olp2;
+       __new_opt_end = olp2;
+       olp = olp2->optlnxt;
+       olp2->optlnxt = NULL;
+       continue;
+      }
+
+     /* move olp one past -f and [file name] */
+     olp = olp2->optlnxt;
+     __add_infil(chp);   
+     __cur_fnam = __in_fils[__last_inf];
+     savlin_cnt =  __lin_cnt;
+     savlast_inf = __last_inf;
+     __lin_cnt = 1;
+
+     /* add beginning marker */
+     ins_optlst_marker(TRUE, lev);
+     /* fill a new option list */
+     for (;;)
+      {
+       if ((__toktyp = __get_cmdtok(opt_s)) == TEOF) break;
+
+       new_olp = alloc_optlst();
+       if (__new_opt_end == NULL) __new_opt_hdr = __new_opt_end = new_olp;
+       else { __new_opt_end->optlnxt = new_olp; __new_opt_end = new_olp; }
+       new_olp->opt = __pv_stralloc(__token);
+       new_olp->optlev = lev;
+       new_olp->optfnam_ind = __last_inf;
+       new_olp->optlin_cnt = __lin_cnt;
+       some_expanded = TRUE;
+      }
+     /* add end marker */
+     ins_optlst_marker(FALSE, lev);
+     __my_fclose(opt_s); 
+     __cur_fnam = __in_fils[savlast_inf];
+     __lin_cnt = savlin_cnt;
+    }
+   /* DBG --- no debug flag at this point ---
+   dmp_xpnd_olist(__new_opt_hdr);
+   --- */
+   __opt_hdr = __new_opt_hdr;
+   __opt_end = __new_opt_end;
+   if (!some_expanded) break;
+   __new_opt_hdr = __new_opt_end = NULL;
+  } 
+ /* DBG remove --- no debug flag at this point ---
+ dmp_xpnd_olist(__opt_hdr);
+ --- */
+}
+
+/*
+ * insert a marker
+ */
+static void ins_optlst_marker(int32 is_bmark, int32 lev)
+{
+ struct optlst_t *new_olp;
+ 
+ /* this also initializes */
+ new_olp = alloc_optlst();
+ if (__new_opt_end == NULL) __new_opt_hdr = __new_opt_end = new_olp;
+ else { __new_opt_end->optlnxt = new_olp; __new_opt_end = new_olp; }
+ /* must not be seen as input file */
+ new_olp->optnum = -2;
+ if (is_bmark) new_olp->is_bmark = TRUE;
+ else new_olp->is_emark = TRUE;
+ new_olp->optlev = lev;
+ new_olp->optfnam_ind = __last_inf;
+ new_olp->optlin_cnt = __lin_cnt;
+}
+
+/*
+ * dump expanded option list
+ */
+static void dmp_xpnd_olist(register struct optlst_t *olp)
+{
+ int32 olnum;
+
+ if (olp == NULL)
+  {
+   __dbg_msg("&& argument list empty.\n");
+   return;
+  }
+ __dbg_msg("&&& start of expanded argument list dump.\n"); 
+ for (olnum = 1; olp != NULL; olp = olp->optlnxt, olnum++)
+  {
+   if (olp->is_bmark || olp->is_emark)
+    {
+     if (olp->is_bmark)
+      {
+       __dbg_msg(">> no. %d lev %d: BEGIN MARK at %s\n", olnum, olp->optlev,
+        __bld_lineloc(__xs, olp->optfnam_ind, olp->optlin_cnt));
+      }
+     else
+      {
+       __dbg_msg("<< no. %d lev %d: END MARK at %s\n", olnum, olp->optlev,
+       __bld_lineloc(__xs, olp->optfnam_ind, olp->optlin_cnt));
+      }
+    }
+   else
+    {
+     __dbg_msg("&& no. %d level %d: %s (value %d) at %s\n", olnum,
+      olp->optlev, olp->opt, olp->optnum, __bld_lineloc(__xs,
+      olp->optfnam_ind, olp->optlin_cnt));
+    }
+  }
+ __dbg_msg("&&& expanded argument list end.\n"); 
+}
+
+/*
+ * find an option from table
+ * scheme assume no options with arguments but directions can have arguments
+ * assuming then end with ;
+ */
+static int32 find_opt(char *aval)
+{
+ register int32 i;
+
+ /* first search for normal option (if arg white space separated) */ 
+ for (i = 0; i < NCMDOPTS; i++)
+  {
+   if (strcmp(aval, cmdopts[i].lnam) == 0) return((int32) cmdopts[i].namid);
+  }
+ /* notice these special options are not in cmdopts table */
+ if (strncmp(aval, "+libext+", 8) == 0) return(CO_LBEXT);
+ if (strncmp(aval, "+incdir+", 8) == 0) return(CO_INCDIR);
+ if (strncmp(aval, "+suppress_warns+", 16) == 0) return(CO_SUPPWARNS);
+ if (strncmp(aval, "+define+", 8) == 0) return(CO_DEFINE);
+ /* notice next 2 unusual because use = instead of + since only one pair */
+ if (strncmp(aval, "+loadpli1=", 10) == 0) return(CO_LOADPLI1);
+ if (strncmp(aval, "+loadvpi=", 9) == 0) return(CO_LOADVPI);
+ return(-1);
+}
+
+/*
+ * open log file (need if at all possible)
+ */
+static void open_logfile(void)
+{
+ char *chp;
+ struct optlst_t *arg_olp;
+ char s1[RECLEN];
+ 
+ strcpy(s1, DFLT_LOGFNAM);
+ __save_log_s = NULL;
+ if (__log_olp != NULL)
+  {
+   arg_olp = __log_olp->optlnxt;
+   if (arg_olp != NULL) chp = arg_olp->opt; else chp = NULL;
+   if (chp == NULL || *chp == '+' || *chp == '-')
+    {
+     __gfwarn(505, __log_olp->optfnam_ind, __log_olp->optlin_cnt,
+      "-l option not followed by log file name - %s used", DFLT_LOGFNAM); 
+     goto no_explicit;
+    }
+   /* must mark so not seen as input file */
+   arg_olp->optnum = -2;
+   if ((__log_s = __tilde_fopen(chp, "w")) == NULL)
+    {
+     __gfwarn(505, arg_olp->optfnam_ind, arg_olp->optlin_cnt,
+      "cannot open -l log file %s - trying default", chp);
+     goto no_explicit;
+    }
+   __log_fnam = __pv_stralloc(chp);
+   goto done;
+  }
+
+no_explicit:
+ if ((__log_s = __tilde_fopen(s1, "w")) == NULL)
+  {
+   __pv_fwarn(505, "cannot open default log file %s - no log file", s1);
+   return;
+  }
+ else __log_fnam = __pv_stralloc(s1);
+
+done:;
+ /* SM 03/26/00 - 2 (bit 4) no longer used for log file - lumped in with 1 */
+ /* ---
+ __mulchan_tab[2].mc_s = __log_s;
+ --- */
+ /* know this is closed so no previous name to free */
+ /* ---
+ __mulchan_tab[2].mc_fnam = __pv_stralloc(__log_fnam);
+ --- */
+}
+
+/*
+ * read command line args
+ */
+static void do_args(void )
+{
+ register struct optlst_t *olp; 
+ int32 oi, tmp, len;
+ FILE *f;
+ struct optlst_t *sav_olp;
+ struct loadpli_t *ldp;
+ struct mapfiles_t *mapfp;
+ char *chp, *chp2, *chp3;
+ char s1[2*RECLEN];
+
+ /* notice for options with arguments must mark arg as -2 or will be */
+ /* seen as input file */ 
+ for (olp = __opt_hdr; olp != NULL;)
+  {
+   /* ignore markers added for building vpi argc/argv */
+   if (olp->is_bmark || olp->is_emark)
+    { olp = olp->optlnxt; continue; }
+
+   chp = olp->opt;
+   /* no + or -, ignore for now - next pass add to file list */
+   if (*chp != '-' && *chp != '+') { olp = olp->optlnxt; continue; }
+
+   /* unrecognized +/-, if -, warning, else inform */ 
+   if (olp->optnum == -1)
+    {
+     if (strlen(chp) == 1)
+      {
+       __gfwarn(506, olp->optfnam_ind, olp->optlin_cnt,
+        "%s option prefix without following option name illegal - ignored",
+         chp);
+       olp = olp->optlnxt;
+       continue;
+      } 
+
+     if (*chp == '-')
+      __gfwarn(506, olp->optfnam_ind, olp->optlin_cnt,
+       "unrecogized option %s - ignored ", olp->opt);
+     else __gfinform(410, olp->optfnam_ind, olp->optlin_cnt,
+      "assuming unrecognized option %s for pli or other simulator",
+      olp->opt);
+     
+     olp = olp->optlnxt;
+     continue;
+    }
+   oi = olp->optnum;
+   switch (oi) {
+    /* ignore already processed */
+    case CO_LOG: case CO_HELP: case CO_QUIET: case CO_VERB: break;
+    /* if was not able to open nest file error here */
+    case CO_F: 
+     /* if -f option expanded - will be removed before here */
+     /* left only if error (cannot open file) */
+     if (olp->optlnxt == NULL)
+      {
+       __gferr(920, olp->optfnam_ind, olp->optlin_cnt,
+        "-f include argument not followed by file name");
+       continue;
+      }
+     olp = olp->optlnxt; 
+     /* -f not followed by file name in nested -f file */
+     if (olp->is_emark)
+      {
+       /* here may have long list of emarks that must be skipped */
+       __gferr(920, olp->optfnam_ind, olp->optlin_cnt,
+        "nested -f include argument not followed by file name");
+       break;
+      }
+     __gferr(920, olp->optfnam_ind, olp->optlin_cnt,
+      "cannot open -f include argument file %s", olp->opt);
+     olp->optnum = -2;
+     break;
+
+    /* options followed by 1 white space separated argument */
+    case CO_IAINPUT:
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || chp == NULL || *chp == '+'
+      || *chp == '-')
+      {
+       __gfwarn(505, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "-i option not followed by startup interactive input file name"); 
+       continue;
+      }
+     olp->optnum = -2;
+     /* make sure it can be opened */
+     if ((f = __tilde_fopen(chp, "r")) == NULL)
+      {
+       __gfwarn(505, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "cannot open -i startup interactive input file %s - input from stdin",
+        chp);
+       break;
+      }
+     __my_fclose(f);
+     __cmd_start_fnam = __pv_stralloc(chp);
+     if (__verbose)
+      __cv_msg("  Startup interactive input will be read from file \"%s\".\n",
+       __cmd_start_fnam);
+     break; 
+    case CO_KEY:
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || *chp == '+' || *chp == '-')
+      {
+       __gfwarn(505, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "-k option not followed by file name for transcript of typed keys");
+       continue; 
+      }  
+     olp->optnum = -2;
+     __gfwarn(621, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+      "-k option no effect - key files not supported (use $input scripts)");
+     /* only open if needed (must go in malloc as separate) */
+     break;
+    case CO_TRACEFILE:
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || *chp == '+' || *chp == '-')
+      {
+       __gfwarn(509, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+       "+tracefile option not followed by file name - previous (stdout?) used");
+       continue; 
+      }  
+     olp->optnum = -2;
+     /* only open when tracing enabled */
+     if (strcmp(chp, "STDOUT") == 0) strcpy(chp, "stdout"); 
+     if (__tr_fnam != NULL) __my_free(__tr_fnam, strlen(__tr_fnam) + 1);
+     __tr_fnam = __pv_stralloc(chp);
+     __tr_s = NULL;
+     if (__verbose)
+      __cv_msg(
+       "  Statement and/or event trace output will be written to file \"%s\".\n",
+       __tr_fnam);
+      /* in case -t or -et precedes this option open now */
+     if (__st_tracing || __ev_tracing || __pth_tracing) __maybe_open_trfile();
+     break;
+    case CO_SDF_LOG:
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || *chp == '+' || *chp == '-')
+      {
+       __gfwarn(505, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "+sdf_log_file setting option not followed by file name");
+       continue; 
+      }  
+     olp->optnum = -2;
+     if (__sdf_opt_log_fnam != NULL)
+      __my_free(__sdf_opt_log_fnam, strlen(__sdf_opt_log_fnam) + 1);
+     __sdf_opt_log_fnam = __pv_stralloc(chp);
+
+     if (__verbose)
+      {
+       __cv_msg(
+        "  SDF messages and errors will be written to separate SDF log file %s.\n",
+        __sdf_opt_log_fnam);
+      }
+     break;
+    case CO_SDFANNOTATE:
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || *chp == '+' || *chp == '-')
+      {
+       __gfwarn(593, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "+sdf_annotate option not followed by [file][+<optional scope name>] - ignored");
+       continue;
+      }
+     olp->optnum = -2;
+     do_sdflocdef(chp, __in_fils[sav_olp->optfnam_ind], sav_olp->optlin_cnt);
+     break;
+    case CO_MAXERRS:
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || *chp == '+' || *chp == '-')
+      {
+bad_maxerrs:
+       __gfwarn(502, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "maximum error number must be 0 (no limit) or positive");
+       continue;
+      }
+     olp->optnum = -2;
+     if (sscanf(chp, "%d", &tmp) != 1 || tmp < 0) goto bad_maxerrs;
+     __max_errors = tmp; 
+     if (__max_errors != 0 && __verbose)
+      __cv_msg(
+       "  Translation will stop after %d errors instead of default %d.\n",
+       __max_errors, MAX_ERRORS); 
+     else
+      {
+       if (__verbose)
+        __cv_msg("  Default error termination limit disabled.\n");
+      }
+     break;
+#ifdef __CVLIC__
+    case CO_LICPTH:
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || *chp == '+' || *chp == '-')
+      {
+       __gfwarn(502, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "+licpath option not followed by required [path] - ignored");
+       continue;
+      }
+     olp->optnum = -2;
+     __lic_path = __pv_stralloc(chp);
+     if (__verbose)
+      {
+       __cv_msg(
+        "  License authorization file cver.lic searched for in directory \"%s\".\n",
+        __lic_path);
+      }
+     break;
+#endif
+    case CO_V:
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || *chp == '+' || *chp == '-')
+      {
+       __gfwarn(501, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "-v library file option not followed by file name - ignored");
+       continue;
+      }
+     olp->optnum = -2;
+     if (strcmp(chp, ".") == 0 || strcmp(chp, "..") == 0)
+      {
+       __gfwarn(623, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "-v library file %s illegal", chp);
+      }
+     add_lbfil(chp, 'v');
+     if (__verbose)
+      __cv_msg("  File \"%s\" in library from -v option.\n", chp); 
+     break;
+    case CO_LIBLIST:
+     /* -L library */
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || *chp == '+' || *chp == '-')
+      {
+       __gfwarn(501, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "-L library map file option not followed by file name - ignored");
+       continue;
+      }
+     olp->optnum = -2;
+     /* set the global name of the -L library name */
+     __cmdl_library = __pv_stralloc(chp);
+     if (__verbose)
+      __cv_msg("  File \"%s\" in library from -L option.\n", chp); 
+     break;
+    case CO_LIBMAP:
+     /* +config [filename] */
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || *chp == '+' || *chp == '-')
+      {
+       __gfwarn(501, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "+config [file] library map file option not followed by file name - ignored");
+       continue;
+      }
+     olp->optnum = -2;
+
+     mapfp = (struct mapfiles_t *) __my_malloc(sizeof(struct mapfiles_t));
+     mapfp->mapfnam = __pv_stralloc(chp);
+     mapfp->mapfnxt = NULL;
+
+     if (__map_files_hd == NULL) __map_files_hd = __map_files_tail = mapfp;
+     else
+      {
+       __map_files_tail->mapfnxt = mapfp;
+       __map_files_tail = mapfp;
+      }
+     if (__verbose)
+      __cv_msg(
+       "  Will read \"%s\" map lib file specified by +config [file] option.\n",
+       mapfp->mapfnam); 
+     break;
+    case CO_FRSPICE:
+     break;
+    case CO_Y:
+     sav_olp = olp;
+     olp = olp->optlnxt; 
+     if (olp != NULL) chp = olp->opt;
+     if (olp == NULL || olp->is_emark || *chp == '+' || *chp == '-')
+      {
+       __gfwarn(593, sav_olp->optfnam_ind, sav_olp->optlin_cnt,
+        "-y library directory option not followed by path name - ignored");
+       continue;
+      }
+     olp->optnum = -2;
+     add_lbfil(chp, 'y');
+     if (__verbose)
+      __cv_msg("  Directory \"%s\" searched for libraries from -y option.\n",
+      olp->opt); 
+     break;
+    case CO_DEFINE:
+     chp = olp->opt;
+     do_cmdmacdef(&(chp[8]), olp);
+     break;
+    case CO_INCDIR:
+     chp2 = olp->opt;
+     /* error message on bad format emitted inside here */
+     if (!bld_incdtab(&(chp2[8]), olp)) break;
+     if (__verbose)
+      {
+       __cv_msg(
+        "  %s additional +incdir+ paths searched to find `include files.\n",
+        &(olp->opt[7])); 
+      }
+     break;
+    case CO_LOADPLI1:
+#ifdef __STATIC_PLI__
+    __gfwarn(3123, olp->optfnam_ind, olp->optlin_cnt,
+     "+loadpli1 = option illegal when using old style statically linked cverobj.o - ignored");
+#else
+     chp2 = olp->opt;
+     if ((ldp = bld_loadpli_lbs(&(chp2[10]), olp, TRUE)) == NULL) break;
+     if (__verbose)
+      {
+       /* this can't fail since know well formed */
+       chp3 = strrchr(chp2, ':');
+       /* DBG LINT remove -- */
+       if (chp3 == NULL) __misc_terr(__FILE__, __LINE__);
+       /* -- */
+       if (strcmp(chp3, "") == 0) strcpy(__xs, "[none]");
+       else strcpy(__xs, chp3);
+       __cv_msg(
+        "  +loadpli1 dynamic library %s loaded with bootstrap routine(s) %s\n",
+        ldp->libnam, __xs);
+      }
+#endif
+     break;
+    case CO_LOADVPI:
+#ifdef __STATIC_PLI__
+    __gfwarn(3123, olp->optfnam_ind, olp->optlin_cnt,
+     "+loadvpi= option illegal when using old style statically linked cverobj.o - ignored");
+#else
+     chp2 = olp->opt;
+     if ((ldp = bld_loadpli_lbs(&(chp2[9]), olp, FALSE)) == NULL) break;
+     if (__verbose)
+      {
+       /* this can't fail since know well formed */
+       chp3 = strrchr(chp2, ':');
+       /* DBG LINT remove -- */
+       if (chp3 == NULL) __misc_terr(__FILE__, __LINE__);
+       /* -- */
+       if (strcmp(chp3, "") == 0) strcpy(__xs, "[none]");
+       else strcpy(__xs, chp3);
+       __cv_msg(
+        "  +loadvpi= dynamic library %s loaded with bootstrap routine(s) %s\n",
+        ldp->libnam, __xs);
+      }
+#endif
+     break;
+    case CO_LBEXT:
+     chp2 = olp->opt;
+     if (__last_lbx != -1)
+      {
+       __gfwarn(598, olp->optfnam_ind, olp->optlin_cnt,
+        "+libext+ option for -y library directories cannot be repeated - ignored");
+       /* need to move to next option */
+       break;
+      }
+    
+     if (!bld_lbxtab(&(chp2[8]), olp)) break;
+     if (__verbose)
+      {
+       __cv_msg(
+        "  %s suffix(es) used for -y library extensions from +libext+ options.\n",
+        &(olp->opt[7])); 
+      }
+     break;
+    /* options where arg is suffix of option */
+    case CO_SUPPWARNS:
+     chp2 = olp->opt;
+     len = strlen(chp2);
+     /* if optional ending plus left out - add here */
+     if (chp2[len - 1] != '+')
+      {
+       /* SJM - 12/20/02 - must copy to work string because no room to add */
+       /* plus if not added by user */
+       strcpy(s1, chp2);
+       s1[len] = '+'; s1[len + 1] = '\0';
+       chp2 = s1;
+      }
+
+     /* returns F on error, so tracing for not emitted on T */
+     if (add_suppwarn(chp2, olp)) 
+      {
+       if (__verbose)
+        __cv_msg(
+         "  Following warning or interactive message(s) %s will not be emitted.\n",
+         &(chp2[16]));
+      }
+     break;
+    /* options without arguments */
+    case CO_C:
+     if (__verbose)
+      {
+       __cv_msg(
+        "  Translate only - all files and library directories will be checked.\n");
+      }
+     __compile_only = TRUE;
+     break;
+    case CO_PARSEONLY:
+     if (__verbose)
+      {
+       __cv_msg(
+        "  Parse only - for quick syntax check of separate modules.\n");
+      }
+     __parse_only = TRUE;
+     break;
+    case CO_STOP:
+     if (__verbose)
+      __cv_msg("  Stopping into interactive mode before simulation begins.\n");
+     /* this is not checked until sim begins (if it does) */
+     __stop_before_sim = TRUE;
+     break;
+    case CO_E:
+     __no_errs = TRUE;
+     if (__verbose) __cv_msg("  Error messages will not be printed.\n");
+     break;
+    case CO_D:
+     __decompile = TRUE;
+     if (__verbose)
+      __cv_msg(
+       "  Source after defparam expansion will be decompiled and printed.\n");
+     break;
+    case CO_A:
+     if (__verbose)
+      __cv_msg("-a accelerate option no effect - on by default.\n");
+     break;
+    case CO_AOFF:
+     if (__verbose)
+      __cv_msg("port and gate assignments will not be accelerated.\n");
+     __accelerate = FALSE;
+     break;
+    case CO_X:
+     if (__verbose)
+      __cv_msg("-x option no effect - vector wires expanded by default.\n");
+     break;
+    case CO_DEBUG:
+     __debug_flg = TRUE;
+     if (__verbose)
+      __cv_msg("  Debugging information will be printed.\n");
+     break;
+    case CO_MINDEL:
+     __mintypmax_sel = DEL_MIN;
+     if (__verbose)
+      __cv_msg("  Min:typ:max expressions will use the minimum value.\n");
+     break;
+    case CO_TYPDEL:
+     __mintypmax_sel = DEL_TYP;
+     if (__verbose)
+      __cv_msg(
+       "  Min:typ:max expressions will use the typical value (default).\n");
+     break;
+    case CO_MAXDEL:
+     __mintypmax_sel = DEL_MAX;
+     if (__verbose)
+      __cv_msg("  Min:typ:max expressions will use the maximum value.\n");
+     break;
+    case CO_SETTRACE:
+     __st_tracing = TRUE;
+     __maybe_open_trfile();
+     if (__verbose)
+      __cv_msg("  Execution of behavioral statements will be traced.\n");
+     break;
+    case CO_SETEVTRACE:
+     __ev_tracing = TRUE;
+     __maybe_open_trfile();
+     if (__verbose) __cv_msg("  Event processing will be traced.\n");
+     break;
+    case CO_SETPTHTRACE:
+     __pth_tracing = TRUE;
+     __maybe_open_trfile();
+     if (__verbose)
+      __cv_msg("  Specify delay Path will be traced in detail.\n");
+     break;
+    case CO_GATE_EATER: case CO_NO_GATE_EATER:
+     __gfwarn(507, olp->optfnam_ind, olp->optlin_cnt,
+      "  +gateeater option obsolete - option ignored");
+     break;
+    case CO_W:
+     __no_warns = TRUE;
+     if (__verbose) __cv_msg("  Warning messages will not be printed.\n");
+     break;
+    case CO_INFORM:
+     __no_informs = FALSE;
+     if (__verbose) __cv_msg("  Inform messages will be printed.\n");
+     break;
+    case CO_UC:
+     __gfwarn(507, olp->optfnam_ind, olp->optlin_cnt,
+      "  -u option unsupported - input is case sensitive");
+     break;
+    case CO_SDFVERB:
+     __sdf_verbose = TRUE;
+     
+     if (__verbose)
+      __cv_msg("  SDF annotation tracing verbose mode is on.\n");
+     break;
+    case CO_SDF_NO_ERRS:
+     __sdf_no_errs = TRUE;
+     if (__verbose) __cv_msg("  SDF error messages will not be printed.\n");
+     break;
+    case CO_SDF_NO_WARNS:
+     __sdf_no_warns = TRUE;
+     if (__verbose) __cv_msg("  SDF warning messages will not be printed.\n");
+     break;
+    case CO_LBVERB:
+     __lib_verbose = TRUE;
+     __cfg_verbose = TRUE;
+     if (__verbose) __cv_msg("  Library tracing verbose mode is on.\n");
+     break;
+    case CO_SWITCHVERB:
+     __switch_verbose = TRUE;
+     /* SJM 11/29/00 - message only output if verbose not switch verbose */
+     if (__verbose)
+      __cv_msg("  Switch channel construction verbose mode is on.\n");
+     break;
+    case CO_CHG_PORTDIR:
+     /* SJM 11/29/00 - new option that changes port direction if connected */  
+     /* as inout, most designs do not need this option but some do */
+     __chg_portdir = TRUE;
+     if (__verbose)
+      __cv_msg(
+       "  Changing port type (direction) to inout for ports connected as inout.\n");
+     break;
+    case CO_NB_NOSEP_QUEUE:
+     /* AIV 06/28/05 - new option that changes causes old non blocking */
+     /* algorithm that did not have separate after pnd0 (each section) */
+     /* event queue to be used */
+     __nb_sep_queue = FALSE;
+     if (__verbose)
+      {
+       __cv_msg(
+        "  Using old Cver non-blocking scheduling - no separate non blocking queuel\n");
+      }
+     break;
+    case CO_LIBRESCAN:
+     __lib_rescan = TRUE;
+     if (__verbose)
+      __cv_msg(
+       "  Library rescanned from beginning after every name resolved.\n");
+     break;
+    case CO_LIBORD:
+     __gfwarn(503, olp->optfnam_ind, olp->optlin_cnt,
+      "+liborder option unsupported");
+lib_mth:
+     if (__verbose)
+      __cv_msg("  Using default or +librescan library scanning method.\n");
+     break;
+    case CO_LIBNOHIDE:
+     __gfwarn(594, olp->optfnam_ind, olp->optlin_cnt,
+      "+libnohide option unsupported");
+     goto lib_mth;
+    case CO_PRTSTATS:
+     __prt_stats = TRUE;
+     if (__verbose) __cv_msg("  Design content tables will be written.\n");
+     break;
+    case CO_PRTALLSTATS:
+     __prt_allstats = TRUE;
+     if (__verbose)
+      __cv_msg(
+       "  Voluminous design and module content tables will be written.\n");
+     break;
+    case CO_SPIKEANAL:
+     __gfwarn(591, olp->optfnam_ind, olp->optlin_cnt,
+      "+spikes option name changed - use standardized +show_canceled_e instead");
+     break;
+    case CO_SHOWCANCELE:
+     __show_cancel_e = TRUE;
+     if (__verbose)
+      __cv_msg("  Pulse canceled events X shown (glitches cause X output).\n");
+     break;
+    case CO_NOSHOWCANCELE:
+     __show_cancel_e = FALSE;
+     if (__verbose)
+      __cv_msg(
+       "  Pulse canceled events not shown (glitches removed - default).\n");
+     break;
+    case CO_PULSEX_ONEVENTE:
+     __showe_onevent = TRUE;
+     if (__verbose)
+      __cv_msg("  Pulse shown Xs scheduled at pulse leading edge (default).\n");
+     break;
+    case CO_PULSEX_ONDETECT:
+     __showe_onevent = FALSE;
+     if (__verbose)
+      __cv_msg("  Pulse shown Xs set when pulse (glitch) detected.\n");
+     break;
+    case CO_WARNCANCELE:
+     __warn_cancel_e = TRUE;
+     if (__verbose)
+      __cv_msg("  Warning message emitted when pulse (glitch) detected.\n");
+     break;
+    case CO_NOWARNCANCELE: 
+     __warn_cancel_e = FALSE;
+     if (__verbose)
+      {
+       __cv_msg(
+        "  No warning message emitted when pulse (glitch) detected (detected).\n");
+      }
+     break;
+    case CO_RMGATEPND0S:
+     __rm_gate_pnd0s = TRUE;  
+     if (__verbose)
+      {
+       __cv_msg(
+        "  All gate #0 delays converted to no delay to speed up simulation.\n");
+      }
+     break;
+    case CO_NORMPTHPND0S:
+     /* remove path pound 0 delays by default */
+     __rm_path_pnd0s = FALSE;  
+     if (__verbose)
+      {
+       __cv_msg("  Disabling removal of all 0 (no effect) path delays.\n");
+      }
+     break;
+    case CO_NOKEEPCOMMANDS:
+     __history_on = FALSE;
+     if (__verbose)
+      {
+       __cv_msg(
+       "  Entered (or $input or piped in) commands not kept on history list.\n");
+      }
+     break;
+    case CO_PLIKEEPSRC:
+     if (__verbose)
+      { 
+       __cv_msg(
+        "  +pli_keep_source option removed - all PLI source access kept");
+      }
+     break;
+    case CO_NOIACT:
+     /* if no signal - then no interactive automatic but flag must be */
+     /* off since still need callbacks for invoking signal handler */
+     __no_iact = TRUE;
+     if (__verbose)
+      __cv_msg("  No interactive commands for this run - ^c causes finish.\n");
+     break;
+    case CO_SNAPSHOT:
+     __intsig_prt_snapshot = TRUE;
+     if (__verbose)
+      __cv_msg(
+       "  Activity snap shot printed upon interrupt signal (^c) termination");
+     break;
+    case CO_NOSPFY:
+     __no_specify = TRUE;
+     if (__verbose)
+      __cv_msg("  Specify section(s) will be discarded before simulation.\n");
+     break;
+    case CO_NOTCHKS:
+     __no_tchks = TRUE;
+     if (__verbose)
+      __cv_msg("  Timing checks will be discarded before simulation.\n");
+     break;
+    case CO_LIBNOCELL:
+     __lib_are_cells = FALSE;
+     if (__verbose)
+      __cv_msg(
+       "  Library modules will not be cells unless in `celldefine region.\n");
+     break;
+    /* just ignore if optimization not compiled in */
+    case CO_OPT_DEBUG:
+    case CO_OPT_SIM:
+     __gfwarn(3121, olp->optfnam_ind, olp->optlin_cnt,
+      " -O native assembly code simulation not enabled in this version.\n");
+     break;
+  
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   olp = olp->optlnxt; 
+  }
+ /* some option consistency checks */
+ if (__intsig_prt_snapshot && !__no_iact)
+  {
+   __pv_warn(508,
+     "+snapshot option no effect because +nointeractive (or +compiled_sim) not selected");
+  }
+}
+
+/*
+ * build input file list after freeing list for argumnts
+ * know now done with arguments
+ */
+static void bld_inflist(void)
+{
+ register struct optlst_t *olp; 
+ struct optlst_t *olp2; 
+
+ /* must not free option files - need for mc scan args pli task ? */
+ /* notice can copy because [args] and *none* same length */
+ strcpy(__in_fils[0], "*none*");
+ __last_optf = __last_inf;
+
+ for (olp = __opt_hdr; olp != NULL; olp = olp->optlnxt) 
+  {
+   /* -1 are unrecognized +/- options, -2 is file used as arg, > 0 is opt */
+   /* so 0 is verilog input file */ 
+   if (olp->optnum == CO_F)
+    {
+     olp2 = olp->optlnxt;
+     if (olp2 != NULL) olp = olp2;
+     continue;
+    }
+   /* added markers automaticaly ignored */
+   if (olp->optnum == 0) __add_infil(olp->opt);
+  }
+}
+
+/*
+ * add an in file
+ * used first for -f command file and then reused for source and include
+ * files
+ * last inf is location of new file
+ * fatal error if more than 64k in files
+ */
+extern void __add_infil(char *fnam)
+{
+ if (++__last_inf >= __siz_in_fils) __grow_infils(__last_inf);
+ __in_fils[__last_inf] = __pv_stralloc(fnam);
+}
+
+/*
+ * re allocate in fils pointer table 
+ */
+extern void __grow_infils(int32 new_last)
+{
+ int32 osize, nsize;
+
+ /* file index must fit in word32 16 bits still */
+ if (new_last >= 0xfffe)
+  {
+   __fterr(305,
+    "too many comand -f , input, `include and library files (%d)",
+    0xfffe);
+  }
+ /* re-alloc area */
+ osize = __siz_in_fils*sizeof(char *); 
+ __siz_in_fils *= 2;
+ /* if hits fffd this will do a realloc that does nothing */
+ if (__siz_in_fils >= 0xfffd) __siz_in_fils = 0xffff;
+ nsize = __siz_in_fils*sizeof(char *); 
+ /* notice realloc may move but works because ptrs to the strings */
+ __in_fils = (char **) __my_realloc((char *) __in_fils, osize, nsize);
+}
+     
+/*
+ * extract SDF annotation file name and optional scope and save in list
+ */
+static void do_sdflocdef(char *sdfloc, char *optfnam, int32 oplin_cnt)
+{
+ register char *chp;
+ struct sdfnamlst_t *sdfp, *sdfp2, *last_sdfp;
+ char *chp2; 
+ char fnam[IDLEN], pthnam[IDLEN]; 
+
+ /* form is [file name]+[optional scope] */
+ strcpy(pthnam, "");
+ if ((chp = strchr(sdfloc, '+')) == NULL) strcpy(fnam, sdfloc);
+ else  
+  {
+   if (chp == sdfloc || chp[-1] == '\\')
+    {
+     chp2 = chp + 1;
+     for (;;)
+      {
+       if ((chp = strchr(chp2, '+')) == NULL)
+        { strcpy(fnam, sdfloc); goto sep_done; }
+
+       if (chp[-1] != '\\') goto bld_both;
+       chp2 = chp + 1;
+      }
+    }
+bld_both:
+   strncpy(fnam, sdfloc, chp - sdfloc);
+   fnam[chp - sdfloc] = '\0';  
+   strcpy(pthnam, ++chp);
+  }
+  
+sep_done:
+ sdfp = (struct sdfnamlst_t *) __my_malloc(sizeof(struct sdfnamlst_t));
+ sdfp->fnam = __pv_stralloc(fnam); 
+ sdfp->scopnam = __pv_stralloc(pthnam);  
+ sdfp->optfnam = __pv_stralloc(optfnam);
+ sdfp->opt_slcnt = oplin_cnt;
+ sdfp->sdfnamnxt = NULL;
+ last_sdfp = NULL;
+
+ /* put on end since must do in order */
+ for (sdfp2 = __sdflst; sdfp2 != NULL; sdfp2 = sdfp2->sdfnamnxt)
+  last_sdfp = sdfp2;
+ if (last_sdfp == NULL) __sdflst = sdfp; else last_sdfp->sdfnamnxt = sdfp;
+ if (strcmp(sdfp->scopnam, "") == 0) 
+  {
+   if (__verbose)
+    {
+     __cv_msg(
+      "  Delay annotation values read from SDF 3.0 file \"%s\" design context.\n",
+      sdfp->fnam); 
+    }
+  }
+ else
+  {
+   if (__verbose)
+    {  
+     __cv_msg(
+      "  Delay annotation values read from SDF 3.0 file \"%s\" scope context %s.\n",
+     sdfp->fnam, sdfp->scopnam); 
+    }
+  }
+}
+
+/*
+ * process a +define argument and do the define and emit verbose msg 
+ *
+ * know defarg starts just after +define+
+ */
+static void do_cmdmacdef(char *defarg, struct optlst_t *olp) 
+{
+ int32 slen; 
+ char *chp, *chp2, *chp3;
+ char optnam[IDLEN], optval[IDLEN], s1[3*IDLEN];
+
+ for (chp = defarg;;)
+  {
+   /* know chp pointer to char after current + */ 
+   /* separate off string to next '+' */
+   if ((chp2 = strchr(chp, '+')) == NULL) { strcpy(s1, chp); goto got_def; } 
+
+got_plus:
+   chp2--;
+   /* if escaped +, keep looking until find end non escaped */
+   if (*chp2 == '\\')
+    {
+     chp2++; chp2++;
+     chp3 = chp2;
+     if ((chp2 = strchr(chp3, '+')) == NULL)
+      { strcpy(s1, chp); goto got_def; }
+     goto got_plus;
+    }
+   /* nove back to point to + */
+   chp2++;
+   strncpy(s1, chp, chp2 - chp);
+   s1[chp2 - chp] = '\0'; 
+
+got_def:
+   /* now have define in s1 with chp2 either name nil */
+   optnam[0] = '`'; 
+   if ((chp = strchr(s1, '=')) == NULL)
+    {
+     if (strcmp(s1, "") == 0)
+      {
+bad_nam:
+       __gferr(962, olp->optfnam_ind, olp->optlin_cnt,
+        "+define+[name]+ ... or +define+[name]=[value] option empty [name] illegal");
+       return;
+      }
+     strcpy(&(optnam[1]), s1);
+     if (__verbose)
+      __cv_msg("  `define of %s (no value form) added from command option.\n",
+       s1); 
+     __do_macdefine(optnam, "");
+    }
+   else
+    {
+     strncpy(&(optnam[1]), s1, chp - s1); 
+     /* notice plus 1 because 1st char of optnam already filled */
+     optnam[chp - s1 + 1] = '\0';  
+     if (strcmp(optnam, "`") == 0) goto bad_nam;
+     chp++;
+     if (*chp == '\\' && *chp == '"') chp++;
+     strcpy(optval, chp);
+     slen = strlen(optval);
+     /* if escaped " remove escape */
+     if (slen > 1)
+      {
+       if (optval[slen - 2] == '\\' && optval[slen - 1] == '"')
+        { optval[slen - 2] = optval[slen - 1]; optval[slen - 1] = '\0'; }
+      }
+     if (__verbose)
+      __cv_msg("  `define of %s value %s added from command option.\n",
+       &(optnam[1]), optval); 
+     __do_macdefine(optnam, optval);
+    }
+   /* chp2 either points to NULL or ending '+' */
+   /* end can be NULL or final '+' */
+   if (chp2 == NULL) break;
+   chp2++;
+   if (*chp2 == '\0') break;
+   chp = chp2;
+  }
+}
+
+/*
+ * build (add to) +incdir path table
+ *
+ * concatenate on end (in option order) for +incdir+ list
+ * if path does not end in / one is added - `include cated on end
+ * and attempt is made to open that path
+ */
+static int32 bld_incdtab(char *incdirptr, struct optlst_t *olp) 
+{
+ int32 len;
+ char *cp, *cpbg, *chp2;
+ char s1[IDLEN], s2[IDLEN];
+
+ len = strlen(incdirptr);
+ if (len == 0)
+  {
+   __gfwarn(505, olp->optfnam_ind, olp->optlin_cnt,
+    "+incdir+ option missing include file path name list - option ignored");
+   return(FALSE);
+  }
+
+ /* if optional ending plus left out - add here */
+ if (incdirptr[len - 1] != '+')
+  {
+   chp2 = s2;
+   strcpy(chp2, incdirptr);
+   chp2[len] = '+';
+   chp2[len + 1] = '\0';
+  }
+ else chp2 = incdirptr;
+
+ for (cpbg = chp2, len = 0;;)
+  {
+   /* notice - if no + will just be one - this is internal fmt screw up */
+   if ((cp = strchr(cpbg, '+')) == NULL || (len = cp - cpbg) >= IDLEN - 1)
+    __misc_terr(__FILE__, __LINE__);
+
+   if (++__last_incdir >= MAXINCDIRS)
+    __pv_terr(306, "+incdir+ option - too many include file paths (%d)",
+     MAXINCDIRS);
+   if (len > 0)
+    {
+     strncpy(s1, cpbg, len);
+     if (s1[len - 1] != '/') { s1[len] = '/'; len++; }
+     s1[len] = '\0';
+     __incdirs[__last_incdir] = __pv_stralloc(s1);
+    }
+   else
+    {
+     __gfwarn(514, olp->optfnam_ind, olp->optlin_cnt,
+      "+incdir+ path list contains empty (++) path - just skipping"); 
+     __last_incdir--;
+    }
+   cpbg = ++cp;
+   if (*cpbg == '\0') break;
+  }
+ return(TRUE);
+}
+
+/*
+ * process +loadpli1 or +loadvpi PLI dynamic library and bootstrap load arg
+ *
+ * formats exactly:
+ *   +loadpli1=[.so lib]:[boostrap routines (, sep - none legal)]
+ *   +loadvpi=[.so lib]:[boostrap routines (, sep - none legal)]
+ *
+ * LOOKATME - option must be contiguous - some shells may require
+ * quoting on command line (not in -f files) but quotes stripped by shell 
+ */
+static struct loadpli_t *bld_loadpli_lbs(char *loadpliptr,
+ struct optlst_t *olp, int32 is_pli1)
+{
+ int32 len;
+ char *cp;
+ char lbnam[IDLEN], rnams[IDLEN], onam[RECLEN];
+ struct loadpli_t *ldp;
+
+ if (is_pli1) strcpy(onam, "+loadpli1="); else strcpy(onam, "+loadvpi=");
+ len = strlen(loadpliptr);
+ if (len == 0)
+  {
+   __gfwarn(505, olp->optfnam_ind, olp->optlin_cnt,
+    "%s option missing [dynamic lib]:[bootstrap routine list] pair - option ignored",
+    onam);
+   return(NULL);
+  }
+ /* if dynamic library missing - use dlsym look up in all other libs */
+ if (loadpliptr[0] == ':')
+  { 
+   /* library missing - ok if boot routine defined in some other dyn lib */
+   __gfwarn(505, olp->optfnam_ind, olp->optlin_cnt,
+    "%s [dynamic lib] omitted - required because mixed static/dynamic not supported - option ignored",
+    onam);
+   return(NULL);
+  }
+ for (cp = &(loadpliptr[len - 1]);;)
+  {
+   if (*cp == ':') break;
+   if (--cp == loadpliptr)
+    {
+     __gfwarn(505, olp->optfnam_ind, olp->optlin_cnt,
+    "%s [dynamic lib] and [bootstrap routine] ':' separator missing - option ignored",
+     onam);
+     return(NULL);
+    }
+  }
+ strncpy(lbnam, loadpliptr, cp - loadpliptr);
+ lbnam[cp - loadpliptr] = '\0'; 
+ cp++;
+ strcpy(rnams, cp);
+ /* FIXME ??? - think should allow omitted lib and static and dynamic  */
+ if (strcmp(rnams, "") == 0)
+  {
+   /* missing bootstrap ok since other load pli option can supply boostrap */ 
+   __gfwarn(505, olp->optfnam_ind, olp->optlin_cnt,
+    "%s [bootstrap routine] missing - ok since not required", onam);
+   return(NULL);
+  }
+
+ /* LOOKATME - maybe should remove extra ' or " */
+ /* fill the load pli record */
+ ldp = (struct loadpli_t *) __my_malloc(sizeof(struct loadpli_t));
+ if (is_pli1) ldp->pli1_option = TRUE; else ldp->pli1_option = FALSE;
+ ldp->libnam = __pv_stralloc(lbnam);
+ ldp->load_plinxt = NULL;
+ if (!bld_boot_rout_list(ldp, rnams))
+  {
+   __my_free((char *) ldp, sizeof(struct loadpli_t));
+   return(NULL);   
+  }
+
+ if (is_pli1)
+  {
+   /* need separate lists since pli1 can add user systf tfcell elements */
+   if (__pli1_dynlib_hd == NULL)
+    { __pli1_dynlib_hd = __pli1_dynlib_end = ldp; }
+   else
+    {
+     /* add to end - libs must be processed in option order */  
+     __pli1_dynlib_end->load_plinxt = ldp;
+     __pli1_dynlib_end = ldp;
+    }
+   return(ldp);
+  }
+
+ /* build the vpi list */
+ if (__vpi_dynlib_hd == NULL) { __vpi_dynlib_hd = __vpi_dynlib_end = ldp; }
+ else
+  {
+   /* add to end - libs must be processed in option order */  
+   __vpi_dynlib_end->load_plinxt = ldp;
+   __vpi_dynlib_end = ldp;
+  }
+ return(ldp);
+}
+
+/*
+ * routine to check 
+ */
+static int32 bld_boot_rout_list(struct loadpli_t *ldp, char *rnams)
+{
+ int32 len;
+ struct dynboot_t *dnbp, *last_dnbp;
+ char *chp2, *chp;
+ char s1[RECLEN];
+
+ /* first check for one routine name or , separated list - no spaces */  
+ if (!check_rnam_str(rnams)) return(FALSE);
+
+ last_dnbp = NULL;
+ chp2 = rnams;
+ for (chp = rnams;; chp++)
+  {
+   if (*chp == ',' || *chp == '\0')
+    {
+     len = chp - chp2;
+     strncpy(s1, chp2, len);
+     s1[len] = '\0';
+     dnbp = (struct dynboot_t *) __my_malloc(sizeof(struct dynboot_t));
+     dnbp->bootrout_nam = __pv_stralloc(s1);
+     dnbp->dynu.vpi_rout = NULL;
+     dnbp->ret_veriusertf = NULL;
+     dnbp->dynbootnxt = NULL;
+
+     if (last_dnbp == NULL) ldp->dynblst = dnbp;
+     else last_dnbp->dynbootnxt = dnbp;
+     last_dnbp = dnbp;
+
+     if (*chp == '\0') break;
+     chp2 = chp;
+     chp2++;
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * check to make sure boot routine has legal no space , sep list
+ */
+static int32 check_rnam_str(char *rnams)
+{
+ int32 len;
+ char *chp, *chp2;
+
+ if (strlen(rnams) == 1 && rnams[0] == ',') return(FALSE);
+ chp2 = rnams;
+ for (chp = rnams; *chp != '\0'; chp++)
+  {
+   if (isspace(*chp)) return(FALSE);
+   if (*chp == '.') return(FALSE);
+   if (*chp == ',')
+    {
+     len = chp - chp2;
+     if (len == 0) return(FALSE);
+     chp2 = chp + 1;
+    }
+  }
+ chp--;
+ if (*chp == ',') return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * build (add to) lib. ext. table
+ * concatenate on end (in option order) for +libext+ list
+ *
+ * LOOKATME - following XL only one +libext+ option allowed - maybe should
+ * allow more (this routine never called if __last lbx > -1)
+ */
+static int32 bld_lbxtab(char *lbxptr, struct optlst_t *olp)
+{
+ int32 len;
+ char *cp, *cpbg, *chp2;
+ char s1[IDLEN], s2[IDLEN];
+
+ len = strlen(lbxptr);
+ if (len == 0)
+  {
+   __gfwarn(505, olp->optfnam_ind, olp->optlin_cnt,
+    "+libext+ option missing libary extension list - ignored");
+   return(FALSE);
+  }
+ 
+ /* if optional ending plus left out - add here */
+ if (lbxptr[len - 1] != '+')
+  { chp2 = s2; strcpy(chp2, lbxptr); chp2[len] = '+'; chp2[len + 1] = '\0'; }
+ else chp2 = lbxptr;
+
+ for (cpbg = chp2, len = 0;;)
+  {
+   /* notice - if no + will just be one - this is internal fmt screw up */
+   if ((cp = strchr(cpbg, '+')) == NULL || (len = cp - cpbg) >= IDLEN - 1)
+    __misc_terr(__FILE__, __LINE__);
+
+   if (++__last_lbx >= MAXLBEXTS)
+    {
+     __pv_terr(306, "+libext+ option - too many library suffixes (%d)",
+      MAXLBEXTS);
+    }
+   /* notice empty is legal extension - name as is */
+   if (len > 0) strncpy(s1, cpbg, len);
+   s1[len] = '\0';
+   __lbexts[__last_lbx] = __pv_stralloc(s1);
+   cpbg = ++cp;
+   if (*cpbg == '\0') break;
+  }
+ return(TRUE);
+}
+
+/*
+ * add one library file to list
+ */
+static void add_lbfil(char *fnam, char tlet)
+{
+ struct vylib_t *vyp;
+
+ vyp = alloc_vylib(fnam);
+ if (tlet == 'y') __num_ylibs++;
+ else if (tlet == 'v') __num_vlibs++;
+ else __case_terr(__FILE__, __LINE__);
+ vyp->vytyp = tlet;
+ if (__vyhdr == NULL) __vyhdr = vyp; else __end_vy->vynxt = vyp;
+ __end_vy = vyp;
+}
+
+/*
+ * allocate a vylib entry
+ */
+static struct vylib_t *alloc_vylib(char *nam)
+{
+ struct vylib_t *vyp;
+
+ vyp = (struct vylib_t *) __my_malloc(sizeof(struct vylib_t));
+ vyp->vyu.vyfnam = __pv_stralloc(nam);
+ vyp->vyfnam_ind = 0;
+ vyp->vytyp = ' ';
+ vyp->yfiles = NULL;
+ vyp->vynxt = NULL;
+ return(vyp);
+}
+
+struct warnsup_t {
+  int32 rngbeg;
+  int32 rngend;
+};
+
+struct warnsup_t warnsuptab[] = {
+ /* 1 to 399 - fatal errors */
+ /* 400 to 679 suppressable normal informs and warnings */
+ { 400, 679 },
+ /* 680 to 1399 normal errors */ 
+ /* iact errors 1400 to 1499 can be suppressed */
+ { 1400, 1499 },
+ /* 1500 to 1599 are SDF errors - not suppressable */
+ /* 1600-1699 are iact warnings - can be suppressed */
+ { 1600, 1699 },
+ /* 1700 to 1999 are PLI errors */
+ /* 2000 to 2199 are PLI warns and informs */
+ { 2000, 2199 },
+ /* 2200 to 2499 are vendor specific warns and informs */
+ { 2200, 2499 },
+ /* 2500 to 2599 are code gen warns and informs */
+ { 2500, 2599 },
+
+ /* 2600 - 2899 vendor specific errors or unused - not suppressable */
+ /* 2900 - 2999 optimizer errors or unused - not suppressable */
+ /* 3000 to 3099 are new Verilog 2000 informs - suppressable */
+ /* 3100 to 3499 are new Verilog 2000 warns - suppressable */
+ { 3000, 3399 },
+ /* 3400 to 4000 Verilog 2000 errors - not suppressable */ 
+ { -1, -1 }
+};
+
+/*
+ * return T if error message is suppressable (i.e. inform or warn)
+ */
+extern int32 __enum_is_suppressable(int32 errnum)
+{
+ register int32 i;
+
+ for (i = 0;; i++)
+  {
+   if (warnsuptab[i].rngbeg == -1) break;
+
+   if (errnum >= warnsuptab[i].rngbeg && errnum <= warnsuptab[i].rngend)
+    return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * add each +num+ num to table of suppressed warnings (or in 1) 
+ * this returns F on error 
+ * know if + at end left off, will have been added
+ */
+static int32 add_suppwarn(char *pluslst, struct optlst_t *olp) 
+{
+ int32 ernum, len, noerr;
+ char *cp, *cpbg;
+ char s1[IDLEN];
+
+ cpbg = &(pluslst[16]);
+ for (noerr = TRUE, len = 0;;)
+  {
+   if ((cp = strchr(cpbg, '+')) == NULL || (len = cp - cpbg) >= IDLEN)
+    {
+     __misc_terr(__FILE__, __LINE__);
+     return(FALSE);
+    }
+   strncpy(s1, cpbg, len);
+   s1[len] = '\0';
+   if (sscanf(s1, "%d", &ernum) != 1)
+    {
+bad_num:
+     __gfwarn(513, olp->optfnam_ind, olp->optlin_cnt,
+      "+suppress_warnings number %s not warn, not inform, or out of range - ignored",
+      s1); 
+     noerr = FALSE;
+     goto nxt_msg;
+    }
+   if (!__enum_is_suppressable(ernum)) goto bad_num;
+
+   __wsupptab[ernum/WBITS] |= (1 << (ernum % WBITS)); 
+
+nxt_msg:
+   cpbg = ++cp;
+   if (*cpbg == '\0') break;
+  }
+ return(noerr);
+}
+
+/*
+ * help screen
+ */ 
+static char *txhelp[] =  
+{
+ "             ** CVER VERILOG SIMULATOR HELP MESSAGE **",
+ " ",
+ "  Cver is a Verilog HDL simulator following the 1995 IEEE P1364 standard",
+ "  with some 2001 P1364 LRM features added and some modifications to match",
+ "  actual behavior of de facto standard XL simulator.  Modeling in C/C++ and",
+ "  Verilog using PLI 1 and PLI 2 interfaces is supported.  PLI implementation",
+ "  follows 2001 P1364 LRM.  Cver now supports faster compiled to byte code",
+ "  virtual machine (VM) execution simulation selected using -O (optimize on)",
+ "  option (** NOTE -O not available in GPL Cver).  See release notes in doc",
+ "  directory for list of P1364 2001 supported features and list of known",
+ "  problems.",
+ " ",
+ "  Usage:  cver [intermixed options and Verilog source files].",
+ " ",
+ "  Command line and -f command file options must be in lower case and must",
+ "  begin with a - or +.  Each option requires a separate - or +.  Type", 
+ "  'cver -?' or 'cver -h' to generate this help message.  To enter the", 
+ "  Verilog statement interactive debugger (press interrupt (^c) or execute",
+ "  $stop), then type :help' for interactive debugger help.",
+ " ",
+ "  It is assumed that you already know Verilog and have access to a P1364 LRM",
+ "  or other Verilog documentation.  Cver supports both PLI (Programming",
+ "  Language Interface) 1 tf_ and acc_ and PLI 2 vpi_ utility, design object",
+ "  and callback routines using +loadpli1= and +loadvpi= dynamic PLI load",
+ "  options defined below.  Both old PLI 1 and new PLI 2 libraries can be",
+ "  dynamically loaded during one run.  See examples in examples.vpi,",
+ "  examples.tf and examples.acc release directories for examples showing how",
+ "  to link and run PLI models.  If you need to statically link PLI models, you",
+ "  must obtain different Cver binary and cverobj.o library.  Cver contains a",
+ "  number of new system tasks and functions.  See systasks.1 man page in the",
+ "  doc directory for definition of every system task and system function",
+ "  supported by Cver.",
+ " ",
+ "  Cver generally produces results matching other simulators even when other",
+ "  simulators differ from P1364 standard up to differences in event order.",
+ "  However, Cver does not change port direction because of net connection",
+ "  direction (i.e. treat nets with wrong side of port drivers as inouts)",
+ "  unless the +change_port_type option is selected.  It is suggested that",
+ "  you change your designs so port type changing is not needed, but for full",
+ "  compatibility with other simulators always run with +change_port_type",
+ "  option.  Cver implements pulse (glitch) detection for gates as well as",
+ "  paths.  This may cause some simulation result differences.  This more",
+ "  stringent pulse analysis is consistent with Cver's intended use as",
+ "  accurate gate level simulator.",
+ " ",
+ "  Since all options are collected before processing, if any options are",
+ "  duplicated, the rightmost (last) will be used.  All Cver options are",
+ "  listed in this help message.  Any other option will be ignored by Cver",
+ "  although it may be scanned and used by a user PLI routine.  All options",
+ "  not listed in this help message will have warning 506 emitted for minus",
+ "  options and inform 410 for plus options.",
+ " ",
+ "  Options defined in the IEEE P1364 reference manual are supported and have",
+ "  the following effect:",
+ " ",
+ "   -f [file]  Read options and source file names from [file] until it is", 
+ "         exhausted at which point continue reading from command line.  May",
+ "         be nested.", 
+ "   -l [file]  By default all output is written to stdout and to log file",
+ "         verilog.log.  -l changes to log file [file].  System task",
+ "         $log([file]) changes to log file [file] during simulation, $nolog",
+ "         turns off log file output.  Added system task $flushlog calls OS",
+ "         fflush on log file.  $reset does not reset log file.",
+ "   -s    Stop just before starting simulation and enter interactive debugger.", 
+ "   -i [file]  Read interactive debugger commands from file [file] the first",
+ "         time interactive mode is entered (usually with -s but possibly by",
+ "         $stop or interrupt signal (^c)).  Nested -i [file] options are",
+ "         chained not nested.",
+ "   -c    Translate source and all referenced library models only.  Ends just",
+ "         before loading the translated model into memory.", 
+ "   -w    Suppress all warning messages.  See +suppress_warns added option for",
+ "         suppression of warnings and informs by message number.",   
+ "   -d    Dump source that is constructed from internal representation.  All",
+ "         parameters are replaced by their constant value in the",
+ "         reconstructed source output.  Debugger source listing lists lines",  
+ "         from source files instead of reconstructing source.",
+ "   -q    Quiet mode.  Do not print normal progress messages.  Opposite",
+ "         of -q is +verbose that prints even more progress messages than normal.", 
+ "   +mindelays, +typdelays, +maxdelays  Choose either minimum, typical or",
+ "         maximum value from any constant (min:typ:max) forms in source.",
+ "         Selection is made during input scanning so min:typ:max forms",
+ "         become constant numbers at translation time.",
+ "   -t    Trace procedural statement execution.  Use -et to trace event",
+ "         processing.  In other simulators, -t means both -t and -et.",
+ "         $settrace,  $setevtrace, $cleartrace, $clearevtrace to control",
+ "         tracing during simulation.",  
+ "   +libnocell  Ignore `celldefine directives in source and libraries.  This",
+ "         should not be used if delay back annotation is used since it will",
+ "         probably cause annotation to fail.",
+ "   +notimingchecks  After checking for correct syntax, ignore timing checks.",
+ "   -u    Ignored.  For all upper case, use an OS filter command to convert",
+ "         source to all upper case.",
+ " ",
+ "  Only default and +librescan library scanning order supported.  By default",
+ "  all library files from -v [file] and all directories of library elements",
+ "  from -y [directory] are scanned from first to last according to input option",
+ "  order.  If unresolved names remain after completion of a pass, the list is",
+ "  rescanned from the beginning.  If +librescan option is selected, unresolved",
+ "  names are resolved one at a time in order they are first seen.  After a",
+ "  name has been resolved, the next name in order is resolved by rescanning",
+ "  from the beginning of library list.  Options to control order dependent",
+ "  resolution and +libnamehide are not implemented.  Library options are:",  
+ " ",
+ "   -v [file]   Treat [file] as a library containing module and UDP",
+ "         definitions.  File is sequentially searched for definitions that",
+ "         resolve unresolved names.  Within a -v file, if a name if defined",
+ "         before use, it is resolved before moving to next library element.",  
+ "   -y [directory]  Treat every file in [directory] as a -v library although",
+ "         usually each file will only contain one definition.  File name in",  
+ "         directory along with +libext+ option used to find unresolved name.",
+ "   +libext+  In -y directory files, name resolution uses file names.  If",
+ "         no +libext+ option is present only files whose name exactly",
+ "         matches an unresolved module or primitive will be read.  There can",
+ "         be no extension.  Normally, each -y file will contain the",
+ "         definition for exactly one element but if more elements are present",
+ "         they will be used to resolve other unresolved elements.  Use",
+ "         +libext+[extension with dot]+[extension with dot]+...  to cause",
+ "         file name extensions to be removed before matching file names to",
+ "         unresolved element names.  Only one +libext+ option may appear and",
+ "         matching is in order when library extensions do not follow the",
+ "         simple .[suffix name] convention.  If all files in -y directories",
+ "         end with either .v or .V (a common case), use +libext+.v+.V+",
+ "   +librescan  Rescan to beginning of library file and directory list after",
+ "         every unresolved name is resolved.  At most one name resolved per",
+ "         library pass.",
+ "   +libverbose  Emit detailed trace messages giving resolution order and",
+ "         reason a particular element was resolved at the particular place.",
+ "   +show_canceled_e  Path and gate (1 bit continuous assignments implemented",
+ "         as gates) outputs set to X when pulses occur that cause scheduled",
+ "         but not matured events to be canceled because second input edge",
+ "         occurs before output has changed (switched).  The output",
+ "         remains at X until another input edge causes an output change",
+ "         because it is unknown if a pulse (glitch) will cause output",
+ "         switching.  Some other simulators use a less pessimistic algorithm",
+ "         that assumes pulses never cause switching and schedule a change",
+ "         from X back to original output value on trailing edge of pulse.  If",
+ "         your model will not run, use the +warn_canceled_e instead of this",
+ "         option and examine warnings.  Cver does not allow only some",
+ "         paths and gates to use pulse X showing using specify section",
+ "         directives because X showing does not slow down simulation.",
+ "         Normally X from a pulse is shown on leading edge of glitch.  Use",
+ "         +pulse_e_style_ondetect to cause X to be shown(driven) when pulse",
+ "         detected from input change.  Option is standardized replacement for",
+ "         previous +spikes option.", 
+ "   +noshow_canceled_e  Path and gate outputs not driven (shown) as X when",
+ "         pulses occur (second input change earlier than selected delay).",
+ "         This is the default (normally it is not needed).  It selects normal",
+ "         Verilog inertial delay algorithm where the latest input change",
+ "         causes the previously scheduled but unmatured event to be canceled.",
+ "   +pulse_e_style_ondetect  If +show_canceled_e option selected, this option",
+ "         causes output to be set to X (shown) when the pulse (glitch) is",
+ "         detected.  If this option is not selected, output is set to X",
+ "         (shown) when the pulse propagates to an output.  This option",
+ "         selects a more pessimistic (starting earlier) X region.",
+ "   +pulse_e_style_onevent  If +show_canceled_e option selected, this option",
+ "         selects the default output setting to X (showing) option that sets",
+ "         output to X when glitch propagates to output (leading edge is time",
+ "         at which the event scheduled latest matures).  There is no reason",
+ "         to use this option since it is default.  Control of X showing for",
+ "         individual gates and paths is not supported.",
+ "   +warn_canceled_e  Emit warning for every gate (including UDP) or path event",
+ "         cancel (inertial cancel and reschedule).  This option may cause",
+ "         voluminous output so the $suppress_warns and $allow_warns system",
+ "         tasks can be used to select particular time periods when warnings",
+ "         are emitted.  This option and +show_canceled_e are unrelated so both",
+ "         error messages and x showing (injection) may be enabled.",
+ "   +nowarn_canceled_e  Because this option is the default it is never needed",
+ "         Last of all +warn_canceled_e and +nowarn_canceled_e is used.",
+ " ",
+ "  The following two options for dynamically loading user PLI libraries are",
+ "  not explicitly defined in IEEE P1364 reference manual but are supported",
+ "  by all modern simulators.  If you need to statically link your PLI models",
+ "  you must request a different Cver binary and cverobj.o static PLI library,",
+ "  but we strongly encourage use of dynamic PLI loading:",
+ " ",
+ "   +loadpli1=[.so library]:[boostrap routines]  Load [.so library] dynamic",
+ "         library containing user PLI 1 model and execute each bootstrap",
+ "         routine.  [bootstrap routines] is a comma separated list of C",
+ "         routines.  List may be empty but : is still required.  No spaces",
+ "         are allowed around the equal sign, the colon or commas separating",
+ "         bootstrap C routine names.  All dynamic libraries defined by",
+ "         +loadpli1= options are first loaded using OS dlopen mechanism and",
+ "         then all bootstrap routines are executed before elaboration begins.",
+ "         The OS specific dynamic library suffix (.so on Linux) may be",
+ "         omitted.  If omitted and the [.so library] is not found in any",
+ "         LD_LIBRARY_PATH directory, the dynamic library suffix is added and",
+ "         the LD_LIBRARY_PATH directories are searched again.",
+ " ",
+ "         Each [bootstrap routines] list routine must return a pointer to a",
+ "         s_tfcell veriusertfs table that ends with zero value type field.",
+ "         Multiple +loadpli1= options are allowed and just before elaboration",
+ "         all [bootstrap routines] for every +loadpli1= option are executed.",
+ "         Each s_tfcell returned table is added to one design wide master",
+ "         s_tfcell table in option and routine in list order.  The master",
+ "         table defines all PLI 1 system functions and tasks used during a",
+ "         simulation run.  The [bootstrap routines] must not call any PLI",
+ "         routines.  Any C file containing [bootstrap routines] list must",
+ "         include both veriuser.h and cv_veriuser.h files.  Some OS shells",
+ "         may require quoting and escaping option separators and file names",
+ "         within the +loadpli1= option string.  Problem can be avoided by",
+ "         coding +loadpli1= option in a -f command argument file. See release",
+ "         examples.tf directory in tests_and_examples directory for example",
+ "         PLI 1 programs and make files specific to your operating system.",
+ "   +loadvpi=[.so library]:[boostrap routines]  Load [.so library] dynamic",
+ "         library containing user PLI 2 vpi model and execute each bootstrap",
+ "         routine.  [bootstrap routines] is a comma separated list of C/C++",
+ "         routines.  List may be empty but : is still required.  No spaces",
+ "         are allowed around the equal sign, the colon or commas separating",
+ "         bootstrap C routine names.  All dynamic libraries defined by",
+ "         +loadvpi= options are first loaded using OS dlopen mechanism and",
+ "         then all bootstrap routines are executed before elaboration begins.",
+ "         The OS specific dynamic library suffix (.so on Linux) may be",
+ "         omitted.  If omitted and the [.so library] is not found in any",
+ "         LD_LIBRARY_PATH directory, the dynamic library suffix is added and",
+ "         the LD_LIBRARY_PATH directories are searched again.",
+ " ",
+ "         Each [bootstrap routines] is saved on an ordered list and executed",
+ "         in order before elaboration begins.  Normally [bootstrap routines]",
+ "         will execute routines in vlog_startup_routines table, but any PLI 2",
+ "         vpi routines callable before elaboration may be called including",
+ "         vpi_register_systf and vpi_register_cb PLI 2 routines.  Some OS",
+ "         shells may require quoting and escaping option separators and file",
+ "         names within the +loadvpi= option string.  Problem can be avoided by",
+ "         coding +loadvpi= option in a -f command argument file. See release",
+ "         examples.vpi directory for example PLI 1 programs and make files",
+ "         specific to your operating system.",
+ " ",
+ "  The following other options not defined in the IEEE P1364 reference manual",
+ "  are supported:",
+ "   +verbose  Print various simulation progress messages and design component",
+ "         counts.  Memory sizes do not count memory used by udp tables.", 
+ "   +maxerrors [number]  Normally translation terminates after 32",
+ "         errors.  Use this option to change the number. 0 means no limit.",
+ "         Option applies to translation only, simulation is never stopped.",
+ "   -e    Turn off printing of non fatal error messages.", 
+ "   -informs  Turn on printing of informatory messages.  Off by default.",
+ "         Informs may be emitted during translation and during simulation.",
+ "         Enable this option to determine if a plus option is misspelled and",
+ "         to cause OS error message description strings to be printed.",
+ "         Option will probably produce voluminous output unless",
+ "         +suppress_warns+[+ separated list] option(s) also used.",
+ "   -O    Turn on simulation byte code optimizer (**NOTE not available in",
+ "         GPL Cver).  If this option is selected statement breakpoints",
+ "         can not be set but all other interpreter features are supported.",
+ "   -et   Turn on event tracing.  Option is similar to the -t (or $settrace)",
+ "         option but -t only traces procedural execution.  To dynamically",
+ "         control event tracing use $setevtrace and $clearevtrace system",
+ "         tasks.  Option produces voluminous output. Use -t and -et to", 
+ "         duplicate other simulator -t tracing.",
+ "   +tracefile [name]  Set the output file for any trace output (either",
+ "         statement or event).  Use $settracefile system task to change",
+ "         trace file during execution.  Name can be stdout and if no option",
+ "         or $tracefile, defaults to stdout and log file.  $flushlog system", 
+ "         task flushes this file during simulation.",
+ "   +printstats  Print tables of design contents.  Primitives, instances,",
+ "         and wires that will use silicon area are tabulated.  More",
+ "         detailed alternative to $showallinstances.",
+ "   +printallstats  Option equivalent to +printstats but additionally prints",
+ "         the declarative content of every module.",      
+ "   +suppress_warns+  Individual warning and informatory messages can be",
+ "         suppressed (not errors) by including a + separated list. i.e.",
+ "         +suppress_warns+403+502+507+564+.  All such options are combined.",
+ "         The $suppress_warns([comma separated list]) and $allow_warns",
+ "         system tasks can be used during simulation for the same effect.",
+ "   +remove_gate_0delays  Change all gates with #0 or #(0, 0, 0) delay to no",
+ "         delay (1 bit continuous assigns implemented as gates).  Option can",
+ "         significantly speed up simulation but in very rare situation cause",
+ "         simulation to fail (#0 delays used to mask races).  If you see a",
+ "         large simulation speed up from option, you can probably speed up",
+ "         simulation even more by recoding most common cells as udps.  Option",
+ "         needed because some simulators only allow delay annotation if gate",
+ "         has a delay coded in source.", 
+ "   +nokeepcommands  Do not save interactive commands to history list.  By",
+ "         default,  Interactive commands are saved to history list.  The",
+ "         $keepcommands; and $nokeepcommands; system tasks enable and disable",
+ "         saving of of history during simulation.  Option should be used when",
+ "         interactive input comes from $input or from shell pipe to stdin.",
+ "   +define+[symbol] or +define+[symbol]=[string]   Define back quote macro",
+ "         symbol [symbol] with an empty text string (first form) for use with",
+ "         `ifdef and `ifndef macro facility.  [symbol] does not include back",
+ "         quote.  Second form defines symbol with value [string].  [String]",
+ "         must not contain white space but can contain anything else including",
+ "         surrounding quotes.  Escaped surrounding quotes are converted to",
+ "         normal quotes while non escaped will probably be removed",
+ "         by your shell.  The $scan$plusargs system task is an alternative",
+ "         for setting preprocessor values into variables.",
+ "   +incdir+[path]+[path]+...+  Define paths that are searched for `include",
+ "         files when `include file not found in current directory.  Only",
+ "         `include files that are non absolute paths (not staring with '/'",
+ "         or '.' or '..' or '~') are searched for using +incdir paths.",
+ "         Paths that do not end with '/' have a '/' path separator appended",
+ "         to end.  For file included in different directory, files included",
+ "         from it are still searched for in original (not include file)",
+ "         directory.  Multiple +incdir+ options may be specified.  Paths",
+ "         directories are searched in order of +incdir+ options.",
+ "   +sdf_log_file [file]  File is used for SDF annotation instead of default",
+ "         writing of SDF messages and errors to Verilog log file.",
+ "   +sdf_annotate [file] or +sdf_annotate [file]+[scope reference]  File must",
+ "         be in IEEE P1497 standard delay file format.  File is read and used",
+ "         to set delay and specify values.  +mindelays, +typdelays or",
+ "         +maxdelays setting used to select rtriple value.  Multiple",
+ "         +sdf_annotate options (and files) allowed.  If +[scope reference]",
+ "         provided, SDF path references relative to scope.  Otherwise, SDF",
+ "         paths rooted (context is entire design).  Annotation files processed",
+ "         in option order.  Alternatively, $sdf_annotate system task can be",
+ "         used to annotate delays.  See systsks.1 man page for documentation.",
+ "         Large designs that require large SDF files load somewhat faster if",
+ "         command line option instead of system task is used.",
+ "   +sdfverbose  Emit trace messages giving new delay value for every delay",
+ "         changed during +sdf_annotate delay annotation.  Option can generate",
+ "         voluminous output.",
+ "   +sdf_noerrors  Do not emit SDF annotation error messages.  SDF errors do",
+ "         not stop simulation but cause SDF object delay setting to be skipped",
+ "         so +maxerrors error limit does not apply.  Use this option to turn",
+ "         off printing of SDF error messages.",
+ "   +sdf_nowarns  Do not emit warning messages during SDF annotation.  SDF",
+ "         warnings and informs can also be suppressed by message number",
+ "         using +suppress_warns+ option.",
+ "   +switchverbose  Emit trace and size messages for inout and tran gate",
+ "         switch channels elaboration. Use this option to print progress",
+ "         messages when simulating models with very large switch channels.",
+ "   +change_port_type  Some designs require ports that are not declared as",
+ "         inout but are connected as inouts and require bidirectional signal",
+ "         flow for correct simulation have their port type changes to inout.",
+ "         Use this option to cause port direction to be changed to inout for",
+ "         input ports with loconn drivers and for output ports with highconn",
+ "         drivers.  WARNING: Use of this option may be required to match",
+ "         results of other simulators that use port collapsing algorithm.",
+ "   +no_separate_nb_queue  Cver non blocking event scheduling algorithm has",
+ "         changed to match XL (all non blocking events scheduled only",
+ "         after all #0 events processed).  Use this option for backward",
+ "         compatibility with old cver algorithm that mixed non blocking",
+ "         eventing in the #0 queue.  If using this option changes your",
+ "         results, your circuit probably has a race.",
+ "   +nospecify  Simulation run with specify section ignored.  This option",
+ "         causes specify section to be read and parsed but it is discarded",
+ "         before simulation.  +nospecify of course implies +notimingchecks.",
+ "   +nointeractive  Option turns off interactive environment, interrupt signal",
+ "         (^c) causes immediate termination.  $stop causes a warning to be",
+ "         printed without stopping.  Suppress warning 560 to silently ignore",
+ "         stops.  If machine code simulation option +compiled_sim is selected,",
+ "          this option is automatically turned on.",
+ "   +snapshot  If +nointeractive option is selected, if interrupt signal",
+ "         (^c) is generated, this option causes a port mortem activity",
+ "         snapshot to be printed before program termination.  Debugger",
+ "         :where and $snapshot system task produces same output without",
+ "         ending simulation.",
+ ""
+};
+
+/*
+ * write the help message to standard output and log file
+ */
+static void wrhelp(void)
+{
+ int32 i;
+
+ for (i = 0; *txhelp[i] != '\0'; i++) __crit_msg("%s\n", txhelp[i]);
+}
+
+/*
+ * BUILT IN INITIALIZATTON ROUTINES
+ */
+
+/* built-in Verilog gates */
+/* gateid is, if has corresponding operator gate id, else G_ symbol */
+static struct primtab_t prims[] = {
+ /* special gate for continuous assign */
+ /* notice since starts with number can never be found accidently */
+ { G_ASSIGN, GC_LOGIC, NULL, "1-bit-assign" },
+ { G_BITREDAND, GC_LOGIC , NULL, "and" },
+ { G_BUF, GC_LOGIC, NULL, "buf" },
+ { G_BUFIF0, GC_BUFIF, NULL, "bufif0" },
+ { G_BUFIF1, GC_BUFIF, NULL, "bufif1" },
+ { G_CMOS, GC_CMOS, NULL, "cmos" },
+ { G_NAND, GC_LOGIC, NULL, "nand" },
+ { G_NMOS, GC_MOS, NULL, "nmos" },
+ { G_NOR, GC_LOGIC, NULL, "nor" },
+ { G_NOT, GC_LOGIC, NULL, "not" },
+ { G_NOTIF0, GC_BUFIF, NULL, "notif0" },
+ { G_NOTIF1, GC_BUFIF, NULL, "notif1" },
+ { G_BITREDOR, GC_LOGIC, NULL, "or" },
+ { G_PMOS, GC_MOS, NULL, "pmos" },
+ /* next 2 initialized so can drive fi>1 wires but do not exist */
+ { G_PULLDOWN, GC_PULL, NULL, "pulldown" },
+ { G_PULLUP, GC_PULL, NULL, "pullup" },
+ { G_RCMOS, GC_CMOS, NULL, "rcmos" },
+ { G_RNMOS, GC_MOS, NULL, "rnmos" },
+ { G_RPMOS, GC_MOS, NULL, "rpmos" },
+ { G_RTRAN, GC_TRAN, NULL, "rtran" },
+ { G_RTRANIF0, GC_TRANIF, NULL, "rtranif0" },
+ { G_RTRANIF1, GC_TRANIF, NULL, "rtranif1" },
+ { G_TRAN, GC_TRAN, NULL, "tran" },
+ { G_TRANIF0, GC_TRANIF, NULL, "tranif0" },
+ { G_TRANIF1, GC_TRANIF, NULL, "tranif1" },
+ { G_BITREDXOR, GC_LOGIC, NULL, "xor" },
+ { G_REDXNOR, GC_LOGIC, NULL, "xnor" },
+};
+#define NPRIMS (sizeof(prims) / sizeof(struct primtab_t))
+
+static void init_modsymtab(void)
+{
+ __cur_fnam_ind = 0;
+
+ __cur_fnam = __in_fils[__cur_fnam_ind];
+ __lin_cnt = 0;
+ /* disguised trigger for expired copy expiration */
+ __slotend_action = 0;
+ /* this symbol table is not a symbol table of any symbol */
+ __modsyms = __alloc_symtab(FALSE);
+ __sym_addprims();
+}
+
+/*
+ * add primitives to module type name symbol table - separate name space
+ */
+extern void __sym_addprims(void)
+{
+ register int32 i;
+ struct sy_t *syp;
+ struct tnode_t *tnp;
+ struct primtab_t *primp;
+
+ for (i = 0, primp = prims; i < NPRIMS; i++, primp++)
+  {
+   /* spcial 1 bit continuous assign primitive - not searched in table */
+   tnp = __vtfind(primp->gatnam, __modsyms);
+   /* err if inconsistent primitive table */
+   if (!__sym_is_new) __misc_terr(__FILE__, __LINE__);
+   __add_sym(primp->gatnam, tnp);
+   (__modsyms->numsyms)++;
+   syp = tnp->ndp;
+   syp->sytyp = SYM_PRIM;
+   syp->sydecl = TRUE;
+   syp->el.eprimp = primp;
+
+   /* need global when 1 bit continuous assigns converted */
+   if (primp->gateid == G_ASSIGN) __ca1bit_syp = syp;
+  }
+}
+
+/*
+ * predefined built-in system tasks
+ *
+ * system task arguments are defined by fixup checking code and follow
+ * no pattern 
+ */
+static struct systsk_t vsystasks[] = {
+ { STN_CLEARDEBUG, "$cleardebug" },
+ { STN_CLEAREVTRACE, "$clearevtrace" },
+ { STN_CLEARTRACE, "$cleartrace" },
+ { STN_DEFINEGROUPWAVES, "$define_group_waves" },
+ { STN_DISPLAY, "$display" },
+ { STN_DISPLAYB, "$displayb" },
+ { STN_DISPLAYH, "$displayh" },
+ { STN_DISPLAYO, "$displayo" },
+ { STN_DUMPALL, "$dumpall" },
+ { STN_DUMPFILE, "$dumpfile" },
+ { STN_DUMPFLUSH, "$dumpflush" },
+ { STN_DUMPLIMIT, "$dumplimit" },
+ { STN_DUMPOFF, "$dumpoff" },
+ { STN_DUMPON, "$dumpon" },
+ { STN_DUMPVARS, "$dumpvars" },
+ { STN_FCLOSE, "$fclose" },
+ { STN_FDISPLAY, "$fdisplay" },
+ { STN_FDISPLAYB, "$fdisplayb" },
+ { STN_FDISPLAYH, "$fdisplayh" },
+ { STN_FDISPLAYO, "$fdisplayo" },
+ { STN_FINISH, "$finish" },
+ { STN_FLUSHLOG, "$flushlog" }, 
+ { STN_FMONITOR , "$fmonitor" },
+ { STN_FMONITORB, "$fmonitorb" },
+ { STN_FMONITORH, "$fmonitorh" },
+ { STN_FMONITORO, "$fmonitoro" },
+ { STN_FREEZEWAVES, "$freeze_waves" },
+ { STN_FSTROBE, "$fstrobe" },
+ { STN_FSTROBEB, "$fstrobeb" },
+ { STN_FSTROBEH, "$fstrobeh" },
+ { STN_FSTROBEO, "$fstrobeo" },
+ { STN_FWRITE, "$fwrite" },
+ { STN_FWRITEB, "$fwriteb" },
+ { STN_FWRITEH, "$fwriteh" },
+ { STN_FWRITEO, "$fwriteo" },
+ { STN_GRREMOTE, "$gr_remote" },
+ { STN_GRREGS, "$gr_regs" },
+ { STN_GRSYNCHON, "$gr_synchon" },
+ { STN_GRWAVES, "$gr_waves" },
+ { STN_HISTORY, "$history" },
+ { STN_INCSAVE, "$incsave" },
+ { STN_INPUT, "$input" },
+ { STN_KEEPCMDS, "$keepcommands" },
+ { STN_KEY, "$key" },
+ { STN_LIST, "$list" },
+ { STN_LOG, "$log" },
+ { STN_MEMUSE, "$memuse" },
+ { STN_MONITOR, "$monitor" },
+ { STN_MONITORB, "$monitorb" },
+ { STN_MONITORH, "$monitorh" },
+ { STN_MONITORO, "$monitoro" },
+ { STN_MONITOROFF, "$monitoroff" },
+ { STN_MONITORON, "$monitoron" },
+ { STN_NOKEEPCMDS, "$nokeepcommands" },
+ { STN_NOKEY, "$nokey" },
+ { STN_NOLOG, "$nolog" },
+ { STN_PRINTTIMESCALE, "$printtimescale" },
+ { STN_PSWAVES, "$ps_waves" },
+ { STN_Q_ADD, "$q_add" },
+ { STN_Q_EXAM, "$q_exam" },
+ { STN_Q_INITIALIZE, "$q_initialize" },
+ { STN_Q_REMOVE, "$q_remove" },
+ { STN_READMEMB, "$readmemb" },
+ { STN_READMEMH, "$readmemh" },
+ { STN_RESET, "$reset" },
+ { STN_RESTART, "$restart" },
+ { STN_SAVE, "$save" },
+ { STN_SCOPE, "$scope" },
+ { STN_SDF_ANNOTATE, "$sdf_annotate" },
+ { STN_SETDEBUG, "$setdebug" },
+ { STN_SETEVTRACE, "$setevtrace" },
+ { STN_SETTRACE, "$settrace" },
+ { STN_SHOWALLINSTANCES, "$showallinstances" },
+ { STN_SHOWEXPANDEDNETS, "$showexpandednets" },
+ { STN_SHOWSCOPES, "$showscopes" },
+ { STN_SHOWVARIABLES, "$showvariables" },
+ { STN_SHOWVARS, "$showvars" },
+ { STN_SNAPSHOT, "$snapshot" },
+ { STN_SREADMEMB, "$sreadmemb" },
+ { STN_SREADMEMH, "$sreadmemh" },
+ { STN_STOP, "$stop" },
+ { STN_STROBE, "$strobe" },
+ { STN_STROBEB, "$strobeb" },
+ { STN_STROBEH, "$strobeh" },
+ { STN_STROBEO, "$strobeo" },
+ { STN_SUPWARNS, "$suppress_warns" },
+ { STN_ALLOWWARNS, "$allow_warns" },
+ { STN_SYSTEM, "$system" },
+ { STN_TIMEFORMAT, "$timeformat" },
+ { STN_TRACEFILE, "$tracefile" },
+ { STN_WRITE, "$write" },
+ { STN_WRITEB, "$writeb" },
+ { STN_WRITEH, "$writeh" },
+ { STN_WRITEO, "$writeo" },
+ /* AIV 09/05/03 - added for fileio - only one that is sys task */
+ { STN_FFLUSH, "$fflush"},
+ /* SJM 09/05/03 - also add the new fileio string forms - see 2001 LRM */
+ /* SJM 05/21/04 - these are sys tasks not functs (but LRM inconsistent) */
+ { STN_SWRITE, "$swrite" },
+ { STN_SWRITEB, "$swriteb" },
+ { STN_SWRITEH, "$swriteh" },
+ { STN_SWRITEO, "$swriteo" },
+ /* same as $swrite except 2nd arg (can be var) must be only format string */
+ { STN_SFORMAT, "$sformat" },
+ /* patches for getting models to compile pli tasks -- */
+ /* STN_LAI_INPUTS, "$lai_inputs", */
+ /* STN_LAI_OUTPUTS, "$lai_outputs", */
+ /* STN_ERRORNTL, "$errorNTL", */
+ /* STN_SUSPENDCHECK, "$suspendCheck", */
+ { 0, "" }
+};
+
+/* predefined built-in system functions */
+/* mostly alphabetical but for now really does not need to be */
+/* and new transcendentals at end */ 
+struct sysfunc_t __vsysfuncs[] = {
+ /* { internal num., ret. type, signed (1), type, returned width, name } */
+ { STN_BITSTOREAL, N_REAL, 1, SYSF_BUILTIN, REALBITS, "$bitstoreal"},
+ { STN_COUNT_DRIVERS, N_REG, 0, SYSF_BUILTIN, WBITS, "$countdrivers"},
+ { STN_DIST_CHI_SQUARE, N_REG, 1, SYSF_BUILTIN, WBITS, "$dist_chi_square"},
+ { STN_DIST_ERLANG, N_REG, 1, SYSF_BUILTIN, WBITS, "$dist_erlang"},
+ { STN_DIST_EXPONENTIAL, N_REG, 1, SYSF_BUILTIN, WBITS, "$dist_exponential"},
+ { STN_DIST_NORMAL, N_REG, 1, SYSF_BUILTIN, WBITS, "$dist_normal"},
+ { STN_DIST_POISSON, N_REG, 1, SYSF_BUILTIN, WBITS, "$dist_poisson"},
+ { STN_DIST_T, N_REG, 1, SYSF_BUILTIN, WBITS, "$dist_t"},
+ { STN_DIST_UNIFORM, N_REG, 1, SYSF_BUILTIN, WBITS, "$dist_uniform"},
+ { STN_FOPEN, N_REG, 1, SYSF_BUILTIN, WBITS, "$fopen"},
+ /* width is really width of argument memory */
+ /* only allow on rhs of cont. assign */
+ { STN_GETPATTERN, N_REG, 0, SYSF_BUILTIN, WBITS, "$getpattern"},
+ { STN_ITOR, N_REAL, 1, SYSF_BUILTIN, REALBITS, "$itor"},
+ { STN_Q_FULL, N_REG, 0, SYSF_BUILTIN, WBITS, "$q_full"},
+ { STN_RANDOM, N_REG, 1, SYSF_BUILTIN, WBITS, "$random"},
+ { STN_REALTIME, N_REAL, 1, SYSF_BUILTIN, REALBITS , "$realtime"},
+ /* this codes the real as 64 bit and b part */
+ { STN_REALTOBITS, N_REG, 0, SYSF_BUILTIN, 64, "$realtobits"},
+ { STN_RESET_COUNT, N_REG, 0, SYSF_BUILTIN, WBITS, "$reset_count" },
+ { STN_RESET_VALUE, N_REG, 1, SYSF_BUILTIN, WBITS, "$reset_value"},
+ { STN_RTOI, N_REG, 1, SYSF_BUILTIN, WBITS, "$rtoi"},
+ /* scale takes as argument the module whose scale to return */
+ { STN_SCALE, N_REAL, 0, SYSF_BUILTIN, REALBITS, "$scale"},
+ /* SJM 10/01/03 - special conversion to signed - arg size is ret size */
+ { STN_SIGNED, N_REG, 1, SYSF_BUILTIN, 0, "$signed" }, 
+ { STN_STIME, N_REG, 0, SYSF_BUILTIN, WBITS, "$stime"},
+ { STN_TESTPLUSARGS, N_REG, 0, SYSF_BUILTIN, WBITS, "$test$plusargs" },
+ { STN_SCANPLUSARGS, N_REG, 0, SYSF_BUILTIN, WBITS, "$scan$plusargs" },
+ { STN_TIME, N_TIME, 0, SYSF_BUILTIN, TIMEBITS, "$time"},
+ /* cver system function extensions */
+ { STN_STICKSTIME, N_REG, 0, SYSF_BUILTIN, WBITS, "$stickstime"},
+ { STN_TICKSTIME, N_TIME, 0, SYSF_BUILTIN, TIMEBITS, "$tickstime"},
+ /* SJM 10/01/03 - special conversion to signed - arg size is ret size */
+ { STN_UNSIGNED, N_REG, 0, SYSF_BUILTIN, 0, "$unsigned" }, 
+ /* new transcendental functions */
+ { STN_COS, N_REAL, 1, SYSF_BUILTIN, WBITS, "$cos"},
+ { STN_SIN, N_REAL, 1, SYSF_BUILTIN, WBITS, "$sin"},
+ { STN_TAN, N_REAL, 1, SYSF_BUILTIN, WBITS, "$tan"},
+ { STN_ACOS, N_REAL, 1, SYSF_BUILTIN, WBITS, "$acos"},
+ { STN_ASIN, N_REAL, 1, SYSF_BUILTIN, WBITS, "$asin"},
+ { STN_ATAN, N_REAL, 1, SYSF_BUILTIN, WBITS, "$atan"},
+ { STN_ATAN2, N_REAL, 1, SYSF_BUILTIN, WBITS, "$atan2"},
+ { STN_COSH, N_REAL, 1, SYSF_BUILTIN, WBITS, "$cosh"},
+ { STN_SINH, N_REAL, 1, SYSF_BUILTIN, WBITS, "$sinh"},
+ { STN_TANH, N_REAL, 1, SYSF_BUILTIN, WBITS, "$tanh"},
+ { STN_ACOSH, N_REAL, 1, SYSF_BUILTIN, WBITS, "$acosh"},
+ { STN_ASINH, N_REAL, 1, SYSF_BUILTIN, WBITS, "$asinh"},
+ { STN_ATANH, N_REAL, 1, SYSF_BUILTIN, WBITS, "$atanh"},
+ /* LOOKATME - think this should be removed - other ways to get sign */
+ /* next 2 new transcendental except returns int32 */
+ { STN_SGN, N_REG, 1, SYSF_BUILTIN, WBITS, "$sgn"},
+ { STN_INT, N_REG, 1, SYSF_BUILTIN, WBITS, "$int"},
+ { STN_LN, N_REAL, 1, SYSF_BUILTIN, WBITS, "$ln"},
+ { STN_LOG10, N_REAL, 1, SYSF_BUILTIN, WBITS, "$log10"},
+ { STN_ABS, N_REAL, 1, SYSF_BUILTIN, WBITS, "$abs"},
+ { STN_POW, N_REAL, 1, SYSF_BUILTIN, WBITS, "$pow"},
+ { STN_SQRT, N_REAL, 1, SYSF_BUILTIN, WBITS, "$sqrt"},
+ { STN_EXP, N_REAL, 1, SYSF_BUILTIN, WBITS, "$exp"},
+ { STN_MIN, N_REAL, 1, SYSF_BUILTIN, WBITS, "$min"},
+ { STN_MAX, N_REAL, 1, SYSF_BUILTIN, WBITS, "$max"},
+ { STN_HSQRT, N_REAL, 1, SYSF_BUILTIN, WBITS, "$hsqrt" },
+ { STN_HPOW, N_REAL, 1, SYSF_BUILTIN, WBITS, "$hpow" },
+ { STN_HPWR, N_REAL, 1, SYSF_BUILTIN, WBITS, "$hpwr" },
+ { STN_HLOG, N_REAL, 1, SYSF_BUILTIN, WBITS, "$hlog" },
+ { STN_HLOG10, N_REAL, 1, SYSF_BUILTIN, WBITS, "$hlog10" },
+ { STN_HDB, N_REAL, 1, SYSF_BUILTIN, WBITS, "$hdb" },
+ { STN_HSIGN, N_REAL, 1, SYSF_BUILTIN, WBITS, "$hsign" },
+ { STN_HYPOT, N_REAL, 1, SYSF_BUILTIN, WBITS, "$hypot" },
+ /* AIV 09/05/03 - add the fileio sy funcs */
+ { STN_FGETC, N_REG, 1, SYSF_BUILTIN, WBITS, "$fgetc" },
+ { STN_UNGETC, N_REG, 1, SYSF_BUILTIN, WBITS, "$ungetc" },
+ { STN_FGETS, N_REG, 1, SYSF_BUILTIN, WBITS, "$fgets" },
+ { STN_FTELL, N_REG, 1, SYSF_BUILTIN, WBITS, "$ftell" },
+ { STN_REWIND, N_REG, 1, SYSF_BUILTIN, WBITS, "$rewind" },
+ { STN_FSEEK, N_REG, 1, SYSF_BUILTIN, WBITS, "$fseek" },
+ { STN_FERROR, N_REG, 1, SYSF_BUILTIN, WBITS, "$ferror" },
+ { STN_FREAD, N_REG, 1, SYSF_BUILTIN, WBITS, "$fread" },
+ { STN_FSCANF, N_REG, 1, SYSF_BUILTIN, WBITS, "$fscanf" },
+ { STN_SSCANF, N_REG, 1, SYSF_BUILTIN, WBITS, "$sscanf" },
+ { 0, 0, 0, 0, 0, "" }
+};
+
+/*
+ * initialize the system task symbol table
+ * this is special symbol table used to find module and primitives
+ * not in normal symbol table stack 
+ */
+static void init_stsymtab(void)
+{
+ register int32 i;
+ struct systsk_t *stbp;
+ struct sysfunc_t *sfbp;
+
+ /* system symbols handled specially - only tasks and funcs */
+ /* this sets symbol table to emtpy also */
+ /* not a symbol table of any symbol */
+ __syssyms = __alloc_symtab(FALSE);
+ __cur_fnam_ind = 0;
+ __cur_fnam = __in_fils[__cur_fnam_ind];
+ __lin_cnt = 0;
+
+ /* add system tasks */
+ /* then normal system tasks - var. (or unknown) args */
+ for (i = 0;; i++)
+  {
+   stbp = &(vsystasks[i]);
+   if (strcmp(stbp->stsknam, "") == 0) break;
+   add_systsksym(stbp);
+  }
+ /* add system functions */
+ for (i = 0;; i++)
+  {
+   sfbp = &(__vsysfuncs[i]);
+   if (strcmp(sfbp->syfnam, "") == 0) break;
+   add_sysfuncsym(sfbp);
+  }
+
+ /* SJM 07/08/02 - setup both old veriusertfs systf and new +loadpli1 */
+ __setup_veriusertf_systfs();
+
+
+ /* SJM 07/08/02 - handle all +loadvpi option dynamic lib loading */
+ __process_pli_dynamic_libs(__vpi_dynlib_hd);
+
+ /* because variable number of vpi_ systf (dynamic registering), must add */
+ /* tf_ first, vpi_ registered systfs one after last tf_ */
+ __call_vlog_startup_procs();
+}
+
+/*
+ * add system tasks symbol to syssyms table
+ */
+static void add_systsksym(struct systsk_t *stbp)
+{
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+
+ tnp = __vtfind(stbp->stsknam, __syssyms);
+ /* built in system task table mis-coded */ 
+ if (!__sym_is_new) __misc_terr(__FILE__, __LINE__);
+ __add_sym(stbp->stsknam, tnp);
+ (__syssyms->numsyms)++;
+ syp = tnp->ndp;
+ syp->sytyp = SYM_STSK;
+ syp->sydecl = TRUE;
+ syp->sylin_cnt = 0;
+ syp->syfnam_ind = 0;
+ syp->el.esytbp = stbp;
+}
+
+/*
+ * add system function to system symbol symbol table
+ */
+static void add_sysfuncsym(struct sysfunc_t *sfbp)
+{
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+
+ tnp = __vtfind(sfbp->syfnam, __syssyms);
+ /* built in system function table mis-coded */ 
+ if (!__sym_is_new) __misc_terr(__FILE__, __LINE__);
+ __add_sym(sfbp->syfnam, tnp);
+ (__syssyms->numsyms)++;
+ syp = tnp->ndp;
+ syp->sytyp = SYM_SF;
+ syp->sydecl = TRUE;
+ syp->sylin_cnt = 0;
+ syp->syfnam_ind = 0;
+ syp->el.esyftbp = sfbp;
+}
+
+/*
+ * INPUT FILE PREPARATION ROUTINES
+ */
+
+/*
+ * prepare the input file stack (know input files infiles[0:__last_inf])
+ * macro expansions and `include put on top of stack
+ * this puts one open file struct on tos and open 1st file with guts
+ */
+static void prep_vflist(void)
+{
+ register int32 fi;
+
+ /* no files since 0  and 1 are special */
+ if (__last_inf == __last_optf)
+  __pv_terr(301, "no Verilog input files specified");
+ __last_lbf = __last_inf;
+
+ /* set open file/macro exp./include stack to empty */
+ for (fi = 0; fi < MAXFILNEST; fi++) __vinstk[fi] = NULL;
+ __vin_top = -1;
+ __lasttoktyp = UNDEF;
+ __last_attr_prefix = FALSE;
+ /* this builds the empty top of stack entry */
+ __push_vinfil();
+ /* fill with 1st file and open it */
+ /* __in_fils[0] is no file "none" */
+ /* set to one after last option file */
+ __cur_infi = __last_optf + 1;
+ if (!__open_sfil())
+  __pv_terr(301, "no Verilog input - all files empty or cannot be opened");
+}
+
+
+/*
+ * try to open the next input source file and fill top of stack with its info
+ * file must be openable and have contents
+ * return F on no sucess in opening any of succeeding files
+ */
+extern int32 __open_sfil(void)
+{
+again:
+ /* if not first time, close previous file */
+ if (__visp->vi_s != NULL)
+  { __my_fclose(__visp->vi_s); __visp->vi_s = NULL; }
+ __cur_fnam = __in_fils[__cur_infi];
+ if ((__in_s = __tilde_fopen(__cur_fnam, "r")) == NULL)
+  {
+   __pv_err(700, "cannot open Verilog input file %s - skipped", __cur_fnam);
+try_next:
+   if (__cur_infi + 1 > __last_inf) return(FALSE);
+   __cur_infi++;
+   goto again;
+  }
+ if (feof(__in_s))
+  {
+   __pv_warn(508, "Verilog input file %s empty", __cur_fnam);
+   goto try_next;
+  }
+ /* whenever open new file must discard pushed back */
+ __lasttoktyp = UNDEF;
+ __visp->vi_s = __in_s;
+ /* in fils of 0 is no file "none" */
+ /* vilin_cnt always 0 when opened */
+ __visp->vifnam_ind = __cur_infi;
+ __cur_fnam_ind = __cur_infi;
+ __cur_fnam = __in_fils[__cur_fnam_ind];
+ __lin_cnt = 1;
+ /* emit source filed compiled unless -q */
+ __cv_msg("Compiling source file \"%s\"\n", __cur_fnam);
+ __file_just_op = TRUE;
+ __first_num_eol = FALSE; 
+ /* 06/22/00 - SJM - possible cross macro 2 token number off on new file */
+ __macro_sep_width = FALSE;
+ __maybe_2tok_sized_num = FALSE;
+ __macro_sav_nwid = FALSE;
+ return(TRUE);
+}
+
+/*
+ * allocate a new Verilog input file stack element on top
+ * this does not open or fill anything just builds the tos entry
+ * this sets global __visp
+ */
+extern void __push_vinfil(void)
+{
+ if (++__vin_top >= MAXFILNEST)
+  __pv_terr(308, "`define macro and `include nesting level too large (%d)",
+   MAXFILNEST);
+ if (__vinstk[__vin_top] == NULL)
+  {
+   __vinstk[__vin_top] = (struct vinstk_t *)
+     __my_malloc(sizeof(struct vinstk_t));
+  }
+ __visp = __vinstk[__vin_top];
+ __visp->vilin_cnt = 0;
+ /* in fils of 0 is no file "none" */
+ __visp->vifnam_ind = 0;
+ __visp->vi_s = NULL;
+ __visp->vichp = NULL;
+ __visp->vichplen = -1;
+ __visp->vichp_beg = NULL;
+}
+
+/*
+ * previous file(s) eof encounted pop stack (know thing under open)
+ */
+extern int32 __pop_vifstk(void)
+{
+ /* first pop previous */
+ if (__vin_top == 0)
+  {
+   /* PUT ME BACK */
+   return(FALSE);
+  }
+ /* notice never pop below bottom open current source file */
+ /* if reached end of current source file, pop */
+ /* define stack should never be popped below bottom */
+ if (__vin_top < 0) __misc_terr(__FILE__, __LINE__);
+
+ /* close current top file if open or null out macro */
+ __visp = __vinstk[__vin_top];
+ if (__visp->vi_s != NULL)
+  { __my_fclose(__visp->vi_s); __visp->vi_s = NULL; }
+ if (__visp->vichp != NULL)
+  {
+   /* if -1, pointing to non arg macro in symbol table must not free */
+   /* for use of fixed visp for parsing from history list will just be -1 */
+   /* else len built for arg macro and must be freed */
+   /* need original start which is - length since at ending 0 */
+   if (__visp->vichplen != -1)
+    __my_free(__visp->vichp_beg, __visp->vichplen + 1);
+   __visp->vichp = NULL;
+   __visp->vichp_beg = NULL;
+   __visp->vichplen = -1;
+  }
+
+ /* once popped gone for ever except in_fils entry stays */
+ __visp = __vinstk[--__vin_top];
+
+ /* then access under - notice number of simultaneously open files may */
+ /* be limited by os */
+
+ /* handle nested macro expansion */
+ /* notice here can never be first token for reprocessing `directive */
+ /* since "`define xx `include "yy"" then line with `xx only is illegal */ 
+ /* FIXME - this can never be exec because already set to nil ??? */
+ if (__visp->vichp != NULL)
+  {
+   /* must not change file name and line number */
+   __in_s = NULL;
+   return(TRUE);
+  }
+ /* pop down to previously opened file - macro exp. end or `include */
+ __cur_fnam_ind = __visp->vifnam_ind;
+ __cur_fnam = __in_fils[__cur_fnam_ind];
+ __lin_cnt = __visp->vilin_cnt;
+ __in_s = __visp->vi_s;
+ __file_just_op = TRUE;
+ __first_num_eol = FALSE; 
+ return(TRUE);
+}
+
+/*
+ * return to print internally stored source
+ * know only called if no errors
+ *
+ * must save cur iti num since this is debug routine that can be called
+ * from anywhere
+ */
+extern void __do_decompile(void)
+{
+ register struct mod_t *mdp;
+ register struct udp_t *udpp;
+ int32 first_time;
+
+ __cv_msg("  Reconstructing post compilation source:\n");
+
+ /* for debugging dump every inst. need flag for has IS forms */
+ for (first_time = TRUE, mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (!mdp->msym->sydecl) continue;
+   if (first_time)
+    { __cur_units = 9; __cur_prec = 0; first_time = FALSE; }
+   __push_wrkitstk(mdp, 0);
+   __dmp_mod(stdout, mdp);
+   __pop_wrkitstk();
+  }
+ for (udpp = __udphead; udpp != NULL; udpp = udpp->udpnxt)
+  __dmp_udp(stdout, udpp);
+
+}
+
+/*
+ * TOP LEVEL SOURCE PROCESSING ROUTINES - ALSO DIRECTIVE HANDLING
+ */
+
+/*
+ * read the Verilog source input
+ * know 1st file and 1st token read
+ */
+extern void __rd_ver_src(void)
+{
+ __total_rd_lines = 0;
+ __total_lang_dirs = 0;
+ /* go through loop once for each module */
+ /* everything in Verilog in modules */
+ /* enter loop with first token in toktyp */
+ for (;;)
+  {
+   /* EOF is eof of all in files - get tok. will open next input if need */
+   __get_vtok();
+   if (__toktyp == TEOF) break;
+   /* system tasks not allowed at top level - interacte mode handled */
+   /* elsewhere - but may be a compiler directive */
+   if (__toktyp >= CDIR_TOKEN_START && __toktyp <= CDIR_TOKEN_END)
+    __process_cdir();
+   /* if ever will have synced to one before file level thing */
+   else
+    {
+     /* SJM 03/20/00 - build top level attribute if present */
+     if (__attr_prefix)
+      {
+       __wrk_attr.attr_tok = MODULE;
+       __wrk_attr.attr_seen = TRUE;
+       __wrk_attr.attrnam = __pv_stralloc(__attrwrkstr);
+       __wrk_attr.attr_fnind = __attr_fnam_ind;
+       __wrk_attr.attrlin_cnt = __attr_lin_cnt;
+      }
+     else __wrk_attr.attr_seen = FALSE;
+
+     __rding_top_level = FALSE;
+     __rd_ver_mod();
+     __rding_top_level = TRUE;
+    }
+   if (__toktyp == TEOF) break;
+  }
+}
+
+/*
+ * process built in compiler directives
+ * know directive read and for now just reads what is needed
+ * if `define form will be handled by get tok
+ * directive here only if allowed (and probably required) outside of module
+ */
+extern void __process_cdir(void)
+{
+ int32 wtyp, savlin_cnt;
+ char s1[RECLEN];
+
+ if (!__chk_beg_line(__toktyp))
+  {
+   __pv_fwarn(605, "directive %s not first token on line - ignored",
+    __prt_vtok());
+   /* still skip rest of line */
+   if (!__iact_state) __skipover_line();
+   return;
+  } 
+ switch ((byte) __toktyp) {
+  case CDIR_TIMESCALE:
+   do_timescale();
+   return;
+  case CDIR_DFLNTYP:
+   savlin_cnt = __lin_cnt;
+   __toktyp = __get1_vtok(__in_s);
+   if (savlin_cnt != __lin_cnt)
+    {
+     __pv_ferr(927,
+      "`defaultnettype directive wire type must be on same line");
+     __unget_vtok();
+     return;
+    }
+   if ((wtyp = __fr_wtnam(__toktyp)) == -1)
+    __pv_ferr(704,
+     "`defaultnettype compiler directive not followed by wire type - %s read",
+     __prt_vtok());
+   else if (wtyp >= NONWIRE_ST || wtyp == N_SUPPLY0 || wtyp == N_SUPPLY1)
+    {
+     __pv_ferr(705, "`defaultnettype compiler directive wire type %s illegal",
+      __to_wtnam2(s1, (word32) wtyp)); 
+    }
+   else __dflt_ntyp = wtyp;
+   break;
+  case CDIR_AEXPVECNETS:
+  case CDIR_XPNDVNETS:
+   /* this is default */
+   __no_expand = FALSE;
+   break;
+  case CDIR_NOXPNDVNETS:
+   __no_expand = TRUE;
+   break;
+  case CDIR_CELLDEF:
+   __in_cell_region = TRUE;
+   break;
+  case CDIR_ECELLDEF:
+   __in_cell_region = FALSE;
+   break;
+  /* this takes pull0 or pull1 and connects pull up to unc. input port ? */
+  case CDIR_UNCONNDRIVE:
+   savlin_cnt = __lin_cnt;
+   __toktyp = __get1_vtok(__in_s);
+   if (savlin_cnt != __lin_cnt)
+    {
+     __pv_ferr(1037,
+      "`unconnected_drive directive strength must be on same line");
+     __unget_vtok();
+     return;
+    }
+   if (__toktyp != PULL0 && __toktyp != PULL1)
+    {
+     __pv_ferr(1041,
+      "`unconnected_drive directive requires pull0 or pull1 argument - %s read",
+      __prt_vtok());
+     __unget_vtok();
+     return;
+    }
+   __unconn_drive = __toktyp;
+   break;
+  case CDIR_NOUNCONNDRIVE:
+   __unconn_drive = TOK_NONE;
+   break;
+  case CDIR_RESETALL:
+   /* this does not effect `ifdef, `define, i.e. symbol tables left as is */
+   set_tfmt_dflts();
+   __dflt_ntyp = N_WIRE;
+   __in_cell_region = FALSE;
+   __unconn_drive = TOK_NONE;
+   __no_expand = FALSE;
+   __cur_units = 9;
+   __cur_prec = 0;
+   break;
+  case CDIR_LANG:
+   __do_foreign_lang();
+   /* must return since already skipped to end of line */
+   return;
+
+  /* these need to be supported */
+  case CDIR_ENDPROTECT:
+  case CDIR_ENDPROTECTED:
+  case CDIR_PROTECT:
+  case CDIR_PROTECTED:
+   __pv_fwarn(619, "directive %s unimplemented", __prt_vtok());
+   break;
+
+  /* these do not do anything */
+  case CDIR_ACCEL:
+  case CDIR_NOACCEL:
+  case CDIR_REMGATESNAMES:
+  case CDIR_REMNETNAMES:
+  case CDIR_NOREMGATENAMES:
+  case CDIR_NOREMNETNAMES:
+  case CDIR_DFLTDECAYTIME:
+  case CDIR_DFLTTRIREGSTREN:
+  case CDIR_DELMODEDIST:
+  case CDIR_DELMODEPATH:
+  case CDIR_DELMODEUNIT:
+  case CDIR_DELMODEZERO:
+
+   /* these are all one name and ignored for now */
+   __finform(430, "directive %s has no effect", __prt_vtok());
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ /* this skip over anything else (such as comments) on line */
+ __skipover_line();
+}
+
+/*
+ * process the time scale directive
+ * must be on line by itself and cannot tokenize
+ * anything on line after `timescale not read - / * cannot start there
+ * fomrmat is `timescale <time_unit>/<time_prec>
+ * this sets globals cur_units and cur_prec 
+ *
+ * storage is time exponent - 1s is 1, 100 ms = 3, 1 ns = 9, 10 ns = 10, etc
+ */
+static void do_timescale(void)
+{
+ register char *cp, *cp2;
+ word32 tuexp, tpexp, tunit, tprec;
+ char *s1;
+
+ __collect_line();
+ s1 = (char *) __my_malloc(__macwrklen);
+ /* copy line removing all white space */
+ for (cp2 = __macwrkstr, cp = s1; *cp2 != '\0'; cp2++)
+  { if (!vis_nonnl_white_(*cp2)) *cp++ =  *cp2; }
+ *cp = '\0';
+
+ /* first expect 1, 10, or 100 */
+ cp = s1;
+ tunit = 0;
+ tuexp = 0;
+ if (*cp++ != '1') goto tscale_bad;
+ if (*cp++ == '0') tuexp = 1; else { cp--; goto get_tunit; }
+ if (*cp++ == '0') tuexp = 2; else cp--;
+
+get_tunit:
+ if ((cp = __get_tmult(cp, &tunit)) == NULL) goto tscale_bad;
+ if (*cp != '/') goto tscale_bad;
+ /* if second must be 1 */
+ if (tunit == 0 && tuexp > 0) goto tscale_bad;
+ cp++;
+ tunit -= tuexp; 
+
+ tpexp = 0;
+ if (*cp++ != '1') goto tscale_bad;
+ if (*cp++ == '0') tpexp = 1; else { cp--; goto get_tprec; }
+ if (*cp++ == '0') tpexp = 2; else  cp--; 
+get_tprec:
+ if ((cp = __get_tmult(cp, &tprec)) == NULL) goto tscale_bad;
+ /* if 10s and 100s illegal */
+ if (tprec == 0 && tpexp > 0) goto tscale_bad;
+ tprec -= tpexp;
+
+ /* precision must be smaller or = tick or higher or = exponent */
+ if (tprec < tunit)
+  {
+   __pv_ferr(936,
+    "time unit %s cannot be smaller than precision %s - `timescale ignored",
+     __to_timunitnam(__xs, tunit),  __to_timunitnam(__xs2, tprec));
+   goto done;
+  }
+ /* cur units stored as inverse of exponenent so 1 ns 9 not -9 as returned */ 
+ __cur_units = tunit;
+ /* cur precision is amount to add to cur units */
+ __cur_prec = tprec - __cur_units;
+ /* warning if extra stuff on end of line - should not be there */
+ if (!__bqline_emptytail(cp))
+  __pv_fwarn(567, "`timescale non white space at end of line ignored");
+ __des_has_timescales = TRUE;
+ goto done;
+
+tscale_bad:
+ __pv_ferr(934, "`timescale directive format incorrect - time scale unchanged");
+
+done:
+ __my_free(s1, __macwrklen);
+}
+
+/*
+ * get a time unit - returns NULL on error else ending cp
+ */
+extern char *__get_tmult(char *cp, word32 *num_zeros)
+{
+ switch (*cp) {
+  case 'f': *num_zeros = 15; break;
+  case 'p': *num_zeros = 12; break;
+  case 'n': *num_zeros = 9; break;
+  case 'u': *num_zeros = 6; break;
+  case 'm': *num_zeros = 3; break;
+  case 's': *num_zeros = 0; return(++cp);
+  default: return(NULL);
+ }
+ if (*(++cp) != 's') return(NULL);
+ return(++cp);
+}
+
+
+
+
+
+
+/*
+ * SUMMARY AND DESIGN CONTENTS ROUTINES
+ */
+
+/*
+ * routine to print the summary for entire run
+ */
+static int32 prt_summary(void)
+{
+ if (__pv_err_cnt != 0 || __pv_warn_cnt != 0 || __inform_cnt != 0)
+  __cv_msg("  There were %d error(s), %d warning(s), and %d inform(s).\n",
+   __pv_err_cnt, __pv_warn_cnt, __inform_cnt);
+
+ if (__pv_err_cnt != 0 || __undef_mods > 0) return(1);
+ if (__verbose)
+  {
+   if (__pv_warn_cnt == 0 && __inform_cnt == 0)
+    __cv_msg("  No errors and no warnings.\n");
+  }
+ return(0);
+}
+
+/*
+ * print the design wide stats
+ */
+static void prt_deswide_stats(void)
+{
+ register struct udp_t *udpp;
+ register struct mod_t *mdp;
+ int32 numudps, nummods, numsplitmods, num_tran_nets;
+
+ for (numudps = 0, udpp = __udphead; udpp != NULL; udpp = udpp->udpnxt)
+  numudps++;
+ for (nummods = numsplitmods = 0, mdp = __modhdr; mdp != NULL;
+  mdp = mdp->mnxt)
+  {
+   numsplitmods++;
+   if (!mdp->msplit && !mdp->mpndsplit) nummods++;
+  }
+
+ if (__verbose) 
+  {
+   __cv_msg("  Verbose mode statistics:\n");
+   __cv_msg("  %d source lines read (includes -v/-y library files).\n",
+    __total_rd_lines);
+   if (__total_lang_dirs != 0)
+    __cv_msg("  %d non Verilog source inclusion `language directive(s) read.\n",
+     __total_lang_dirs);
+   if (numsplitmods == nummods)
+    __cv_msg("  Design contains %d module types.\n", nummods);
+   else
+    __cv_msg(
+     "  Design contains %d module types (%d after parameter substitution).\n",
+      nummods, numsplitmods);
+
+   /* notice memory here goes to next higher 160k from end - i.e. 900k is 2m */
+   if (numudps != 0)
+    __cv_msg(
+     "  %d instantiated udp tables of total size less than %d million bytes.\n",
+     numudps, (__mem_udpuse + 1160000)/1000000);
+   if (__num_glbs != 0 || __num_inmodglbs != 0)
+    __cv_msg(
+     "  There are %d cross module and %d intra module hierarchical references.\n",
+     __num_glbs - __num_inmodglbs, __num_inmodglbs);
+   if ((num_tran_nets = count_tran_nets()) != 0) 
+    {
+     __cv_msg(
+      "  %d nets in inout or tran gate connecting transistor channels.\n",
+      num_tran_nets);
+    }
+   if (__gates_removable != 0 || __contas_removable != 0)
+    {
+     __cv_msg(
+      "  %d gates (%d flat) and %d assigns (%d flat) disconnected by gate eater.\n",
+      __gates_removable, __flgates_removable, __contas_removable,
+      __flcontas_removable);
+    }
+   if (__nets_removable != 0)
+    {
+     __cv_msg("  %d nets (%d flat) disconnected by gate eater.\n",
+      __nets_removable, __flnets_removable);
+    }
+   __cv_msg("\n");
+  }
+}
+
+/*
+ * count design total nets in transistor or inout channels
+ */
+static int32 count_tran_nets(void)
+{
+ register int32 ni;
+ register struct net_t *np;
+ register struct mod_t *mdp;
+ int32 ntrnets;
+
+ for (ntrnets = 0, mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mnnum == 0 || (!mdp->mod_hasbidtran && !mdp->mod_hastran))
+    continue;
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+    { if (np->ntraux != NULL) ntrnets++; }
+  }
+ return(ntrnets);
+}
+
+/*
+ * print a message giving memory use
+ */
+static void mem_use_msg(int32 also_mems)
+{ 
+ double d1;
+
+ if (__verbose)
+  {
+   __cv_msg("  Approximately %ld bytes storage allocated (excluding udps).\n",
+    __mem_use);
+   d1 = 100.0*((double) __arrvmem_use/(double) (__memstr_use + __mem_use)); 
+   if (also_mems && __arrvmem_use != 0)
+    {
+     __cv_msg(
+      "  Verilog arrays (memories) require %ld bytes (%.2lf%% of total).\n",
+      __arrvmem_use, d1);
+    }
+   /* RELEASE remove --
+   __prt_memstats();
+   -- */
+  }
+}
+
+/*
+ * print all the design 1 line per module type tables
+ */
+static void prt_alldesmod_tabs(void)
+{
+ __cv_msg("+++ Printing Design Statistics +++\n");
+ /* even if verbose print design wide statistics here */
+ prt_deswide_stats();
+ /* first general module. declarative counts - 1 line per mod */
+ prt2_desmod_tab();
+ /* then 1 line per mod of wire stats */
+ prt2_permod_wiretab();
+ /* 1 line per mod of strength wires stats if design has strength wires */
+ st_prt2_permod_wiretab();
+ /* print task both wire and numbers stats - 1 line per mod with tasks */
+ prt2_permod_tasktabs();
+
+ /* print the per module type usage tables */
+ __prt2_mod_typetab(__prt_allstats);
+ __cv_msg("+++ End of Design Statistics +++\n");
+}
+
+/*
+ * print table of summary modules statistics for every module
+ */
+static void prt2_desmod_tab(void)
+{
+ register struct mod_t *mdp;
+ int32 num_mods, num_tops, num_cells, num_insts, num_gates, num_contas;
+ int32 num_nets, tot_num_cells, tot_num_insts, tot_num_gates;
+ int32 tot_num_contas, tot_num_nets;
+ int32 fltot_num_cells, fltot_num_insts, fltot_num_gates, fltot_num_contas;
+ int32 fltot_num_nets, num1bcas, fltot_insts_in;
+ char s1[RECLEN];
+ 
+ tot_num_cells = tot_num_insts = tot_num_gates = 0;
+ tot_num_contas = tot_num_nets = 0;
+ fltot_num_cells = fltot_num_insts = fltot_num_gates = fltot_num_contas = 0;
+ fltot_num_nets = fltot_insts_in = 0;
+
+ count_mods(&num_mods, &num_tops);
+ __cv_msg("  Design Module Table: %d modules (%d top level):\n", num_mods,
+  num_tops);
+ __cv_msg(
+  "Module            Level Cells-in Insts-in Primitives  Assigns    Nets");
+ __cv_msg("  Insts-of\n");
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   num_cells = count_cells(mdp);
+   tot_num_cells += num_cells;
+   fltot_num_cells += num_cells*(int32) mdp->flatinum;
+   num_insts = (int32) mdp->minum - num_cells;
+   tot_num_insts += num_insts;
+   fltot_num_insts += num_insts*(int32) mdp->flatinum;
+   num_gates = count_gates(mdp, &num1bcas);
+   tot_num_gates += num_gates;
+   fltot_num_gates += num_gates*(int32) mdp->flatinum;
+   num_contas = num1bcas;
+   num_contas += mdp->mcanum;
+   tot_num_contas += num_contas;
+   fltot_num_contas += num_contas*(int32) mdp->flatinum;
+   num_nets = mdp->mnnum;
+   tot_num_nets += num_nets;
+   fltot_num_nets += num_nets*(int32) mdp->flatinum;
+   fltot_insts_in += mdp->flatinum; 
+   bld_modnam(s1, mdp, 20);
+   __cv_msg("%-20s%3d   %6d   %6d     %6d   %6d  %6d    %6d\n", s1,
+    mdp->mlpcnt, num_cells, num_insts, num_gates, num_contas,
+    num_nets, mdp->flatinum);
+  }
+ __cv_msg(
+  "                          ------   ------     ------   ------  ------");
+ __cv_msg("    ------\n");
+ __cv_msg("Static Total:            %7d  %7d    %7d  %7d %7d\n",
+  tot_num_cells, tot_num_insts, tot_num_gates, tot_num_contas, tot_num_nets);
+ __cv_msg("Flat Total:              %7d  %7d    %7d  %7d %7d   %7d\n",
+  fltot_num_cells, fltot_num_insts, fltot_num_gates, fltot_num_contas,
+  fltot_num_nets, fltot_insts_in);
+}
+
+/*
+ * build mod name with trunc. and add (C) for cells
+ * s must be big enough
+ */
+static void bld_modnam(char *s, struct mod_t *mdp, int32 fldsiz)
+{
+ int32 mlen;
+  
+ if (mdp->m_iscell)
+  {
+   mlen = strlen(mdp->msym->synam);
+   if (mlen + 3 > fldsiz)
+    {
+     strncpy(s, mdp->msym->synam, fldsiz - 4);
+     s[fldsiz - 4] = '-';
+     s[fldsiz - 3] = '\0';
+     strcat(s, "(C)");
+    }
+   else { strcpy(s, mdp->msym->synam); strcat(s, "(C)"); }
+   return;
+  }
+ if ((mlen = strlen(mdp->msym->synam)) > fldsiz)
+  {
+   strncpy(s, mdp->msym->synam, fldsiz - 1);
+   s[fldsiz - 1] = '-';
+   s[fldsiz] = '\0';
+  }
+ else strcpy(s, mdp->msym->synam);
+}
+
+/*
+ * count number of modules and top modules in circuit
+ */
+static void count_mods(int32 *nummods, int32 *numtops)
+{
+ register struct mod_t *mdp;
+
+ *nummods = 0;
+ *numtops = 0;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   (*nummods)++;
+   if (mdp->minstnum == 0) (*numtops)++;
+  }
+}
+
+/*
+ * count number of instances in module that are cells
+ */
+static int32 count_cells(struct mod_t *mdp)
+{
+ register int32 ii;
+ int32 cnum;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+
+ for (cnum = 0, ii = 0; ii < mdp->minum; ii++)
+  {
+   ip = &(mdp->minsts[ii]);
+   imdp = ip->imsym->el.emdp;
+   if (imdp->m_iscell) cnum++;
+  }   
+ return(cnum);
+}
+
+/*
+ * count the number of gates in module (includes udps)
+ * 
+ * cannot just use number because 1 bit contas in gate array
+ */
+static int32 count_gates(struct mod_t *mdp, int32 *num1bitcas)
+{
+ register int32 gi;
+ register struct gate_t *gp;
+ int32 gcnt, n1bcas;
+
+ for (gcnt = 0, n1bcas = 0, gi = 0; gi < mdp->mgnum; gi++)
+  {
+   gp = &(mdp->mgates[gi]);
+   if (gp->gmsym->el.eprimp->gateid == G_ASSIGN) n1bcas++; 
+   else gcnt++;
+  }
+ *num1bitcas = n1bcas;
+ return(gcnt);
+}
+
+/*
+ * print the per module wiring table
+ */
+static void prt2_permod_wiretab(void)
+{
+ register struct mod_t *mdp;
+ int32 prts, prtbits, wires, wirebits, regs, regbits, arrs, arrcells, arrbits;
+ int32 tot_prts, tot_prtbits, tot_wires, tot_wirebits, tot_regs;
+ int32 tot_regbits, tot_arrs, tot_arrcells, tot_arrbits;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[RECLEN], s5[RECLEN];
+
+ tot_prts = tot_prtbits = 0;
+ tot_wires = tot_wirebits = tot_regs = tot_regbits = tot_arrs = 0;
+ tot_arrcells = tot_arrbits = 0;
+ __cv_msg("\n  Per Module Wiring Table (Task Variables Excluded):\n");
+ __cv_msg("Module           Ports(Bits)   Wires(Bits) Registers(Bits)");
+ __cv_msg(" Memory(Cells, Bits)\n");
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   prts = (int32) mdp->mpnum;
+   prtbits = cnt_modprt_bits(mdp);
+   cnt_modwires(mdp, &wires, &wirebits, &regs, &regbits, &arrs, &arrcells,
+    &arrbits);
+   
+   tot_prts += prts*(int32) mdp->flatinum;
+   tot_prtbits += prtbits*(int32) mdp->flatinum;    
+   tot_wires += wires*(int32) mdp->flatinum;
+   tot_wirebits += wirebits*(int32) mdp->flatinum;
+   tot_regs += regs*(int32) mdp->flatinum;
+   tot_regbits += regbits*(int32) mdp->flatinum;
+   tot_arrs += arrs*(int32) mdp->flatinum;
+   tot_arrcells += arrcells*(int32) mdp->flatinum;
+   tot_arrbits += arrbits*(int32) mdp->flatinum;
+   if (prts == 0) strcpy(s1, ""); else sprintf(s1, "%d(%d)", prts, prtbits);
+   if (wires == 0) strcpy(s2, "");
+   else sprintf(s2, "%d(%d)", wires, wirebits);
+   if (regs == 0) strcpy(s3, ""); else sprintf(s3, "%d(%d)", regs, regbits);
+   if (arrs == 0) strcpy(s4, ""); 
+   else sprintf(s4, "%d(%d, %d)", arrs, arrcells, arrbits);
+   bld_modnam(s5, mdp, 18);
+   __cv_msg("%-18s%10s%14s%16s%20s\n", s5, s1, s2, s3, s4);   
+  }
+ __cv_msg("                ------------ ------------- ---------------");
+ __cv_msg(" -------------------\n");
+ if (tot_prts == 0) strcpy(s1, "");
+ else sprintf(s1, "%d(%d)", tot_prts, tot_prtbits);
+ if (tot_wires == 0) strcpy(s2, "");
+ else sprintf(s2, "%d(%d)", tot_wires, tot_wirebits);
+ if (tot_regs == 0) strcpy(s3, "");
+ else sprintf(s3, "%d(%d)", tot_regs, tot_regbits);
+ if (tot_arrs == 0) strcpy(s4, ""); 
+ else sprintf(s4, "%d(%d, %d)", tot_arrs, tot_arrcells, tot_arrbits);
+ __cv_msg("Flat total:    %13s%14s%16s%20s\n", s1, s2, s3, s4);
+}
+
+/*
+ * count the number of module port bits
+ */
+static int32 cnt_modprt_bits(struct mod_t *mdp)
+{ 
+ register int32 pi;
+ int32 modpbits;
+ struct mod_pin_t *mpp;
+
+ for (modpbits = 0, pi = 0; pi < mdp->mpnum; pi++)  
+  {
+   mpp = &(mdp->mpins[pi]);
+   modpbits += (int32) mpp->mpwide;
+  }
+ return(modpbits);
+}
+
+/*
+ * count the number of top level (non in task/func) wires and bits
+ */
+static void cnt_modwires(struct mod_t *mdp, int32 *wires, int32 *wirebits,
+ int32 *regs, int32 *regbits, int32 *arrs, int32 *arrcells, int32 *arrbits)
+{
+ register int32 ni;
+ register struct net_t *np;
+ int32 acells;
+
+ *wires = 0;
+ *wirebits = 0;
+ *regs = 0;
+ *regbits = 0;
+ *arrs = 0;
+ *arrcells = 0;
+ *arrbits = 0;
+
+ /* mnets of 0 will not exist unless has at least one net */ 
+ if (mdp->mnnum == 0) return;
+ for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+  {
+   /* module ports not counted here */
+   if (np->iotyp != NON_IO) continue;
+   if (np->ntyp < NONWIRE_ST)
+    {
+     (*wires)++;
+     *wirebits += np->nwid;
+     continue;
+    }
+   if (np->n_isarr)
+    {
+     (*arrs)++;
+     acells = (int32) __get_arrwide(np);
+     *arrcells += acells;
+     *arrbits += acells*np->nwid;
+     continue;
+    }
+   (*regs)++;
+   *regbits += np->nwid;
+  } 
+} 
+
+/*
+ * print the per module strength wiring table
+ */
+static void st_prt2_permod_wiretab(void)
+{
+ register struct mod_t *mdp;
+ int32 first_time;
+ int32 prts, prtbits, wires, wirebits;
+ int32 st_prts, st_prtbits, st_wires, st_wirebits;
+ int32 tot_prts, tot_prtbits, tot_wires, tot_wirebits;
+ int32 st_tot_prts, st_tot_prtbits, st_tot_wires, st_tot_wirebits;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[RECLEN], s5[RECLEN];
+
+ if (__design_no_strens) return;
+
+ tot_prts = tot_prtbits = st_tot_prts = st_tot_prtbits = 0;
+ tot_wires = tot_wirebits = st_tot_wires = st_tot_wirebits = 0;
+ first_time = TRUE;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* always need to count wires and ports even if no strengths */
+   prts = (int32) mdp->mpnum;
+   st_cnt_modprt_bits(mdp, &prtbits, &st_prts, &st_prtbits);
+   st_cnt_modwires(mdp, &wires, &wirebits, &st_wires, &st_wirebits);
+   tot_prts += prts*(int32) mdp->flatinum;
+   tot_prtbits += prtbits*(int32) mdp->flatinum;    
+   tot_wires += wires*(int32) mdp->flatinum;
+   tot_wirebits += wirebits*(int32) mdp->flatinum;
+
+   /* even if module no strengths, goes in total wires */
+   if (!mdp->mhassts) continue;
+   if (first_time)
+    {
+     __cv_msg("\n  Per Module Strength Wiring Table:\n");
+     __cv_msg(
+      "Module                Ports(Bits)       Percent      Wires(Bits)");
+     __cv_msg("       Percent\n");
+     first_time = FALSE;
+    }
+   st_tot_prts += st_prts*(int32) mdp->flatinum;
+   st_tot_prtbits += st_prtbits*(int32) mdp->flatinum;    
+   st_tot_wires += st_wires*(int32) mdp->flatinum;
+   st_tot_wirebits += st_wirebits*(int32) mdp->flatinum;
+
+   if (st_prts == 0) { strcpy(s1, ""); strcpy(s2, ""); }
+   else
+    {
+     sprintf(s1, "%d(%d)", st_prts, st_prtbits);
+     sprintf(s2, "%.1f(%.1f)", 100.0*((double) st_prts/prts),
+      100.0*((double) st_prtbits/prtbits));
+    }
+   if (st_wires == 0) { strcpy(s3, ""); strcpy(s4, ""); }
+   else
+    {
+     sprintf(s3, "%d(%d)", st_wires, st_wirebits);
+     sprintf(s4, "%.1f(%.1f)", 100.0*((double) st_wires/wires),
+      100.0*((double) st_wirebits/wirebits));
+    }
+   bld_modnam(s5, mdp, 20);
+   __cv_msg("%-20s%13s  %12s  %15s  %12s\n", s5, s1, s2, s3, s4);   
+  }
+ __cv_msg(
+  "                      -----------    ----------      -----------  ");
+ __cv_msg("------------\n");
+ if (st_tot_prts == 0) { strcpy(s1, ""); strcpy(s2, ""); }
+ else
+  {
+   sprintf(s1, "%d(%d)", st_tot_prts, st_tot_prtbits);
+   sprintf(s2, "%.1f(%.1f)", 100.0*((double) st_tot_prts/tot_prts),
+    100.0*((double) st_tot_prtbits/tot_prtbits));
+  }
+ if (tot_wires == 0) { strcpy(s3, ""); strcpy(s4, ""); }
+ else
+  {
+   sprintf(s3, "%d(%d)", st_tot_wires, st_tot_wirebits);
+   sprintf(s4, "%.1f(%.1f)", 100.0*((double) st_tot_wires/tot_wires),
+    100.0*((double) st_tot_wirebits/tot_wirebits));
+  }
+ __cv_msg("Strength total:   %15s   %11s%17s  %12s\n", s1, s2, s3, s4);
+}
+
+/*
+ * count the number of strength module ports and bits
+ */
+static void st_cnt_modprt_bits(struct mod_t *mdp, int32 *prtbits, int32 *st_prts,
+ int32 *st_prtbits)
+{ 
+ register int32 pi;
+ register struct expr_t *catxp; 
+ int32 st_modpbits, modpbits, st_modprts;
+ struct mod_pin_t *mpp;
+ struct expr_t *mxp;
+
+ st_modprts = 0;
+ for (modpbits = st_modpbits = 0, pi = 0; pi < mdp->mpnum; pi++)  
+  {
+   mpp = &(mdp->mpins[pi]);
+   modpbits += (int32) mpp->mpwide;
+   mxp = mpp->mpref;
+   if (!mxp->x_stren) continue;
+   st_modprts++;
+   if (mxp->optyp != LCB) { st_modpbits += (int32) mpp->mpwide; continue; }
+
+   /* notice for concats some ports may be strength others not ? */
+   for (catxp = mxp->ru.x; catxp != NULL; catxp = catxp->ru.x) 
+    { if (catxp->lu.x->x_stren) st_modpbits += (int32) catxp->lu.x->szu.xclen; }
+  }
+ *prtbits = modpbits;
+ *st_prts = st_modprts;
+ *st_prtbits = st_modpbits;
+}
+
+/*
+ * count the number of top level (non in task/func) wires and bits
+ */
+static void st_cnt_modwires(struct mod_t *mdp, int32 *wires, int32 *wirebits,
+ int32 *st_wires, int32 *st_wirebits)
+{
+ register int32 ni;
+ register struct net_t *np;
+ int32 mwires, mwirebits, st_mwires, st_mwirebits;
+
+ mwires = 0;
+ mwirebits = 0;
+ st_mwires = 0;
+ st_mwirebits = 0;
+ if (mdp->mnnum != 0)
+  {
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+    {
+     /* module ports not counted here */
+     if (np->iotyp != NON_IO) continue;
+     if (np->ntyp >= NONWIRE_ST) continue;
+
+     mwires++;
+     mwirebits += np->nwid;
+     if (!np->n_stren) continue;
+     st_mwires++;
+     st_mwirebits += np->nwid;
+    } 
+  }
+ *wires = mwires;
+ *wirebits = mwirebits;
+ *st_wires = st_mwires;
+ *st_wirebits = st_mwirebits;
+} 
+
+/*
+ * print the per module task numbers
+ * notice number of instances of module does not multiply here 
+ */
+static void prt2_permod_tasktabs(void)
+{
+ register struct mod_t *mdp;
+ int32 inits, always, tasks, funcs, begblks, frks;
+ int32 tot_inits, tot_always, tot_tasks, tot_funcs, tot_begblks, tot_frks;
+ int32 first_time;
+ char s1[RECLEN];
+
+ tot_inits = tot_always = tot_tasks = tot_funcs = tot_begblks = tot_frks = 0;
+ for (first_time = TRUE, mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mtasks == NULL) continue;
+   if (first_time)
+    {
+     __cv_msg("\n  Per Module Task Definition Table:\n");
+     __cv_msg(
+     "Module            Initial  Always    Task  Function   Lab. Begin");
+     __cv_msg("  Lab. Fork\n");
+     first_time = FALSE;
+    }
+
+   cnt_modtasks(mdp, &inits, &always, &tasks, &funcs, &begblks, &frks);
+   tot_inits += inits;
+   tot_always += always;
+   tot_tasks += frks;
+   tot_funcs += funcs;
+   tot_begblks += begblks;
+   tot_frks += frks;
+   bld_modnam(s1, mdp, 20);
+   __cv_msg("%-20s%5d   %5d   %5d     %5d        %5d      %5d\n", s1, inits,
+    always, tasks, funcs, begblks, frks);
+  }
+ if (!first_time)
+  {
+   __cv_msg("                    -----   -----   -----     -----        ");
+   __cv_msg("-----      -----\n");
+   __cv_msg("Static Total       %6d  %6d  %6d    %6d       %6d     %6d\n",
+    tot_inits, tot_always, tot_tasks, tot_funcs, tot_begblks, tot_frks);
+  }
+}
+
+/*
+ * count the number of tasks, named blocks and funcs
+ */
+static void cnt_modtasks(struct mod_t *mdp, int32 *inits, int32 *always,
+ int32 *tsks, int32 *funcs, int32 *begblks, int32 *frks)
+{
+ register struct ialst_t *ialp;
+ register struct task_t *tskp;
+ int32 iat;
+
+ *inits = *always = *tsks = *funcs = *begblks = *frks = 0;
+ for (ialp = mdp->ialst; ialp != NULL; ialp = ialp->ialnxt)
+  {
+   iat = ialp->iatyp;
+   if (iat == INITial) (*inits)++;
+   else if (iat == ALWAYS) (*always)++;
+   else __case_terr(__FILE__, __LINE__);
+  }
+ for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+   if (tskp->tsktyp == FUNCTION) (*funcs)++;
+   else if (tskp->tsktyp == TASK) (*tsks)++;
+   else if (tskp->tsktyp == Begin) (*begblks)++;
+   else if (tskp->tsktyp == FORK) (*frks)++;
+   else __case_terr(__FILE__, __LINE__);
+  }
+}
+
+/*
+ * dump every module's table of instantiated types and gate statistics
+ */
+extern void __prt2_mod_typetab(int32 prt_all)
+{
+ register struct mod_t *mdp;
+ register struct udp_t *udpp;
+ register int32 i;
+ int32 gid;
+ int32 *gftab, *gstab, *cgftab, *mftab, *mstab, *uftab, *ustab, *cuftab;
+ int32 num_mods, num_udps, mhasudps, first_time;
+ int32 num_contas, tot_insts, tot_gates, tot_udps, tot_fcontas, tot_scontas;
+ int32 tot_cells, tot_cellgates, tot_celludps, tot_cellassigns;
+ struct mod_t *imdp;
+ struct primtab_t *primp;
+ struct sy_t *syp;
+ char s1[RECLEN], s2[RECLEN], filref[RECLEN];
+
+ /* allocate the needed tables */ 
+ gftab = (int32 *) __my_malloc((LAST_GSYM + 1)*sizeof(int32));
+ gstab = (int32 *) __my_malloc((LAST_GSYM + 1)*sizeof(int32));
+ cgftab = (int32 *) __my_malloc((LAST_GSYM + 1)*sizeof(int32));
+
+ for (num_mods = 0, mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* need to assign sequence no. to each module */
+   /* NOTICE - lastinum used for mod splitting but no more needed by here */ 
+   mdp->lastinum = num_mods;
+   num_mods++;
+  }
+ /* know there will always be at least one inst or not get here */
+ mftab = (int32 *) __my_malloc(num_mods*sizeof(int32));
+ mstab = (int32 *) __my_malloc(num_mods*sizeof(int32));
+
+ num_udps = 0;
+ uftab = ustab = cuftab = NULL;
+ if (__udphead != NULL)
+  {
+   for (udpp = __udphead; udpp != NULL; udpp = udpp->udpnxt)
+    {
+     /* need to assign sequence no. to each udp type */
+     udpp->uidnum = num_udps;
+     num_udps++;
+    }
+   uftab = (int32 *) __my_malloc(num_udps*sizeof(int32));
+   ustab = (int32 *) __my_malloc(num_udps*sizeof(int32));
+   cuftab = (int32 *) __my_malloc(num_udps*sizeof(int32));
+  }
+ reset_cntabs(gftab, gstab, cgftab, mftab, mstab, num_mods, uftab, ustab,
+  cuftab, num_udps);
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* to get design totals do not zero fields each time through */
+   accum_usecnts(mdp, gftab, gstab, cgftab, mftab, mstab, uftab, ustab,
+    cuftab, &mhasudps);
+  }
+ /* print design wide totals */
+ __cv_msg("\n  Design Usage Table:\n");
+ __cv_msg("Type                      Class  Static   Flat   Location\n"); 
+ __cv_msg("                                 Number  Number\n"); 
+ /* first 1 line per mod inst - need sorted so must go through mods */
+ tot_insts = tot_gates = tot_udps = tot_fcontas = tot_scontas = 0;
+ tot_cells = tot_cellgates = tot_cellassigns = tot_celludps = 0;
+ for (imdp = __modhdr; imdp != NULL; imdp = imdp->mnxt)
+  {
+   syp = imdp->msym;
+   if (strlen(syp->synam) > 24)
+    { strncpy(s1, syp->synam, 23); s1[23] = '-'; s1[24] = '\0'; }
+   else strcpy(s1, syp->synam);
+
+   if (imdp->minstnum == 0) strcpy(s2, "top");
+   else if (imdp->m_iscell) strcpy(s2, "cell");
+   else strcpy(s2, "module");
+   __cv_msg("%-24s  %-6s%7d %7d  %s:%d\n", s1, s2, mstab[imdp->lastinum],
+    mftab[imdp->lastinum], __schop(filref, __in_fils[syp->syfnam_ind]),
+    syp->sylin_cnt); 
+   tot_insts += (int32) mftab[imdp->lastinum];
+   num_contas = imdp->mcanum;
+   if (imdp->m_iscell)
+    { 
+     tot_cellassigns += (int32) imdp->flatinum*num_contas;
+     tot_cells += (int32) mftab[imdp->lastinum];
+    }
+   tot_fcontas += (int32) imdp->flatinum*num_contas;
+   tot_scontas += num_contas;
+  }
+ for (udpp = __udphead; udpp != NULL; udpp = udpp->udpnxt)
+  {
+   /* if udp defined list even if not used */
+   syp = udpp->usym;
+   if (strlen(syp->synam) > 24)
+    { strncpy(s1, syp->synam, 23); s1[23] = '-'; s1[24] = '\0'; }
+    else strcpy(s1, syp->synam);
+   __cv_msg("%-24s  %-6s%7d %7d  %s:%d\n", s1, "udp", ustab[udpp->uidnum],
+    uftab[udpp->uidnum], __schop(filref, __in_fils[syp->syfnam_ind]),
+    syp->sylin_cnt); 
+
+   tot_udps += (int32) uftab[udpp->uidnum];
+   tot_celludps += (int32) cuftab[udpp->uidnum];
+  }
+ for (i = 0, primp = prims; i < NPRIMS; i++, primp++)
+  {
+   gid = primp->gateid;
+   if (gstab[gid] == 0) continue;
+   __cv_msg("%-24s  %-6s%7d %7d\n", primp->gatnam, "gate", gstab[gid],
+    gftab[gid]);
+   tot_gates += gftab[gid]; 
+   tot_cellgates += cgftab[gid];
+  }
+ if (tot_fcontas != 0 || tot_scontas != 0)
+  __cv_msg("%-24s  %-6s%7d %7d\n", "wide-assign", "assign", tot_scontas,
+   tot_fcontas);
+
+ if (tot_cells == 0)
+  {
+   __cv_msg(
+    "\n  Flattened Design: %d instances, %d udps, %d gates and %d assigns.\n",
+    tot_insts, tot_udps, tot_gates - gftab[G_ASSIGN],
+    tot_fcontas + gftab[G_ASSIGN]);
+  }
+ else
+  { 
+   __cv_msg(
+   "\n  Flattened Design: %d instances (%d of cells), %d udps (%d in cells),\n",
+    tot_insts, tot_cells, tot_udps, tot_celludps);
+   __cv_msg("   %d gates (%d in cells) and %d assigns (%d in cells).\n",
+    tot_gates - gftab[G_ASSIGN], tot_cellgates - cgftab[G_ASSIGN],
+    tot_fcontas + gftab[G_ASSIGN], tot_cellassigns + cgftab[G_ASSIGN]);
+  }
+
+ if (!prt_all) goto free_tabs;
+ __cv_msg(
+  "\n  Individual Modules Content Tables (Procedural Only Excluded)");
+ first_time = TRUE;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   first_time = TRUE;
+   reset_cntabs(gftab, gstab, cgftab, mftab, mstab, num_mods, uftab, ustab,
+    cuftab, num_udps);
+   accum_usecnts(mdp, gftab, gstab, cgftab, mftab, mstab, uftab, ustab,
+    cuftab, &mhasudps);
+
+   /* first 1 line per mod inst - need sorted so must go through mods */
+   for (imdp = __modhdr; imdp != NULL; imdp = imdp->mnxt)
+    {
+     if (mstab[imdp->lastinum] == 0) continue;
+     if (first_time) { prt_modhdr(mdp); first_time = FALSE; }
+     if (strlen(imdp->msym->synam) > 24)
+      { strncpy(s1, imdp->msym->synam, 23); s1[23] = '-'; s1[24] = '\0'; }
+     else strcpy(s1, imdp->msym->synam);
+     if (imdp->m_iscell) strcpy(s2, "cell"); else strcpy(s2, "module");
+     __cv_msg("%-24s  %-6s        %10d      %10d\n", s1, s2,
+      mstab[imdp->lastinum], mftab[imdp->lastinum]);
+    }
+   if (mhasudps)
+    {
+     for (udpp = __udphead; udpp != NULL; udpp = udpp->udpnxt)
+      {
+       if (ustab[udpp->uidnum] == 0) continue;
+
+       if (first_time) { prt_modhdr(mdp); first_time = FALSE; }
+       if (strlen(udpp->usym->synam) > 24)
+        { strncpy(s1, udpp->usym->synam, 23); s1[23] = '-'; s1[24] = '\0'; }
+       else strcpy(s1, udpp->usym->synam);
+       __cv_msg("%-24s  %-6s        %10d      %10d\n", s1, "udp",
+        ustab[udpp->uidnum], uftab[udpp->uidnum]);
+      }
+    }
+   if (mdp->mgates != NULL)
+    {
+     for (i = 0, primp = prims; i < NPRIMS; i++, primp++)
+      {
+       gid = primp->gateid;
+       if (gstab[gid] == 0) continue;
+       if (first_time) { prt_modhdr(mdp); first_time = FALSE; }
+       __cv_msg("%-24s  gate          %10d      %10d\n", primp->gatnam,
+        gstab[gid], gftab[gid]);
+      }
+    }
+   num_contas = mdp->mcanum;
+   if (num_contas != 0)
+    {
+     if (first_time) { prt_modhdr(mdp); first_time = FALSE; }
+     __cv_msg("%-24s  %-12s  %10d      %10d\n", "wide-assign",
+      "assign", num_contas, num_contas*(int32)mdp->flatinum);
+    }
+  }
+ /* may somehow have no modules? */
+ if (first_time) __cv_msg("\n");
+free_tabs:;
+ /* if no alloca would need frees here */
+
+ __my_free((char *) gftab, (LAST_GSYM + 1)*sizeof(int32));
+ __my_free((char *) gstab, (LAST_GSYM + 1)*sizeof(int32));
+ __my_free((char *) cgftab, (LAST_GSYM + 1)*sizeof(int32));
+ __my_free((char *) mftab, num_mods*sizeof(int32));
+ __my_free((char *) mstab, num_mods*sizeof(int32));
+ if (uftab != NULL) __my_free((char *) uftab, num_udps*sizeof(int32)); 
+ if (ustab != NULL) __my_free((char *) ustab, num_udps*sizeof(int32)); 
+ if (cuftab != NULL) __my_free((char *) cuftab, num_udps*sizeof(int32)); 
+}
+
+/*
+ * print the module table header - if contains declared elements    
+ */
+static void prt_modhdr(struct mod_t *mdp)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ if (!mdp->m_iscell) strcpy(s1, "Module"); else strcpy(s1, "Cell");
+ if (mdp->minstnum == 0) strcpy(s2, "(top)");
+ else sprintf(s2, "(Instantiated %d Times)", mdp->flatinum);
+ __cv_msg("\n  %s %s %s Type Usage Table:\n", s1, mdp->msym->synam, s2);
+ __cv_msg(
+  "Type                      Class      Static Number     Flat Number\n");
+} 
+
+/*
+ * reset all count tables
+ */
+static void reset_cntabs(int32 *gftab, int32 *gstab, int32 *cgftab, int32 *mftab,
+ int32 *mstab, int32 nmods, int32 *uftab, int32 *ustab, int32 *cuftab, int32 nudps)
+{
+ if (gftab != NULL) memset(gftab, 0, (LAST_GSYM + 1)*sizeof(int32));
+ if (gstab != NULL) memset(gstab, 0, (LAST_GSYM + 1)*sizeof(int32));
+ if (cgftab != NULL) memset(cgftab, 0, (LAST_GSYM + 1)*sizeof(int32));
+
+ if (mftab != NULL) memset(mftab, 0, nmods*sizeof(int32));
+ if (mstab != NULL) memset(mstab, 0, nmods*sizeof(int32));
+ if (uftab != NULL) memset(uftab, 0, nudps*sizeof(int32));
+ if (ustab != NULL) memset(ustab, 0, nudps*sizeof(int32));
+ if (cuftab != NULL) memset(cuftab, 0, nudps*sizeof(int32));
+}
+
+/*
+ * accumulate usage statistics gates in one module 
+ * must be reset to 0 before here - values accumulated 
+ * if this module has udps sets has udp flag
+ */
+static void accum_usecnts(struct mod_t *mdp, int32 *gftab, int32 *gstab,
+ int32 *cgftab, int32 *mftab, int32 *mstab, int32 *uftab, int32 *ustab, int32 *cuftab,
+ int32 *mhasudps)
+{
+ register int32 ii, gi;
+ int32 gid;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+ struct gate_t *gp;
+ struct udp_t *udpp;
+
+ /* notice previous call always reset each mod use count */
+ /* first time starts at 0 */
+ /* update both in this module count and design wide use count */
+ for (ii = 0; ii < mdp->minum; ii++)
+  {
+   ip = &(mdp->minsts[ii]);
+   imdp = ip->imsym->el.emdp;
+   /* notice lastinum is just sequence no. assigned here - fld reused here */
+   mstab[imdp->lastinum] += 1; 
+   mftab[imdp->lastinum] += (int32) mdp->flatinum;
+  }   
+ /* finally do the counting */
+ *mhasudps = FALSE;
+ for (gi = 0; gi < mdp->mgnum; gi++)
+  {
+   gp = &(mdp->mgates[gi]);
+   if (gp->g_class == GC_UDP)
+    {
+     *mhasudps = TRUE;
+     udpp = gp->gmsym->el.eudpp;
+     /* DBG remove --- */
+     if (ustab == NULL) __misc_terr(__FILE__, __LINE__);
+     if (uftab == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     ustab[udpp->uidnum] += 1;
+     uftab[udpp->uidnum] += (int32) mdp->flatinum;
+     continue;
+    }
+   gid = gp->gmsym->el.eprimp->gateid;
+   gstab[gid] += 1;
+   gftab[gid] += (int32) mdp->flatinum;
+  }
+ if (!mdp->m_iscell) return;
+ 
+ for (gi = 0; gi < mdp->mgnum; gi++)
+  {
+   gp = &(mdp->mgates[gi]);
+   if (gp->g_class == GC_UDP)
+    {
+     udpp = gp->gmsym->el.eudpp;
+     /* DBG remove --- */
+     if (cuftab == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     cuftab[udpp->uidnum] += (int32) mdp->flatinum;
+     continue;
+    }
+   gid = gp->gmsym->el.eprimp->gateid;
+   cgftab[gid] += (int32) mdp->flatinum;
+  }
+}
diff --git a/src/cvmacros.h b/src/cvmacros.h
new file mode 100644
index 0000000..38ad0ee
--- /dev/null
+++ b/src/cvmacros.h
@@ -0,0 +1,328 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * various code macro definitions
+ * mostly for speed in long value processing
+ * notice these macros sometimes use globals and call procedures
+ * that are assumed to be defined
+ */
+
+/* DBG remove - */
+extern void __push_itstk(struct itree_t *);
+extern void __pop_itstk(void);
+/* --- */
+
+/* these make only 1 or 2 percent different in worse case now */
+/* RELEASE NOLONGERUSED MAYBE ADD --
+#define __push_itstk(itp) \
+ do { \
+  __itstk[++__itspi] = __inst_ptr = (itp); \
+  __inst_mod = __inst_ptr->itip->imsym->el.emdp; \
+  __inum = __inst_ptr->itinum; \
+ } while (0)
+--- */
+
+/* remove assign of nil to inst mod to improve speed if needed */
+/* RELEASE NOLONGERUSED MAYBE ADD --
+#define __pop_itstk() \
+ do { \
+  __inst_ptr = __itstk[--__itspi]; \
+  if (__itspi != -1) \
+   { \
+    __inst_mod = __inst_ptr->itip->imsym->el.emdp; \
+    __inum = __inst_ptr->itinum; \
+   } \
+  -* else { __inst_mod = NULL; __inum = 0xffffffff; } *- \
+  else __inst_mod = NULL; \
+ } while (0)
+-- */
+
+/* DBG ??? add --
+extern void __pop_xstk(void);
+-- */
+
+/* --- release add */
+#define __pop_xstk() __xspi--
+/* -- */
+
+/* DBG ??? add -- 
+extern struct xstk_t *__push_xstk(int32);
+#define push_xstk_(xsp, blen) (xsp) = __push_xstk((blen))
+--- */
+
+/* BEWARE - a and b parts must be contiguous because often refed as only a */ 
+/*--- release add --- */
+#define push_xstk_(xsp, blen) \
+ do { \
+  if (++__xspi >= __maxxnest) __grow_xstk(); \
+  (xsp) = __xstk[__xspi]; \
+  if (wlen_(blen) > (xsp)->xsawlen) __chg_xstk_width((xsp), wlen_(blen)); \
+  (xsp)->bp = &((xsp)->ap[wlen_(blen)]); \
+  (xsp)->xslen = (blen); \
+ } while (0)
+/* --- */
+
+/* DBG ??? add --
+extern struct xstk_t *__eval_xpr(struct expr_t *);
+--- */
+/* --- release add */
+#define __eval_xpr __eval2_xpr
+/* --- */
+
+/* DBG ??? add --- */
+extern i_tev_ndx __alloc_tev(int32, struct itree_t *, word64);
+#define alloc_tev_(tevpi, etyp, itp, absetime) \
+ (tevpi) = __alloc_tev((etyp), (itp), (absetime))
+/*--- */
+
+/* -- ??? release add
+#define alloc_tev_(tevpi, etyp, itp, absetime) \
+ do { \
+  register struct tev_t *tevp__; \
+  if (__tefreelsti != -1) \
+   { tevpi = __tefreelsti; __tefreelsti = __tevtab[__tefreelsti].tenxti; } \
+  else \
+   { \
+    if (++__numused_tevtab >= __size_tevtab) __grow_tevtab(); \
+    tevpi = __numused_tevtab; \
+   } \
+  tevp__ = &(__tevtab[tevpi]); \
+  memset(tevp__, 0, sizeof(struct tev_t)); \
+  tevp__->tetyp = etyp; \
+  tevp__->teitp = itp; \
+  tevp__->etime = absetime; \
+  tevp__->tenxti = -1; \
+ } while (0)
+-- */
+
+#define ld_scalval_(ap, bp, bytp) \
+ do { \
+  (ap)[0] = (word32) ((bytp)[__inum]); \
+  (bp)[0] = ((ap)[0] >> 1) & 1L; \
+  (ap)[0] &= 1L; \
+ } while(0)
+
+/* LOOKATME _ notice this assumes av and bv values only occupy low bit */ 
+#define st_scalval_(bp, av, bv) \
+ (bp)[__inum] = (byte) ((av) | ((bv) << 1))
+
+#define st2_scalval_(bp, val) (bp)[__inum] = (byte) (val)
+
+#define chg_st_scalval_(bp, av, bv) \
+ do { \
+  register word32 nval__; \
+  nval__ = (av) | ((bv) << 1); \
+  if (((word32) (bp)[__inum]) != (nval__)) \
+   { (bp)[__inum] = (byte) (nval__); __lhs_changed = TRUE; } \
+ } while(0)
+
+#define get_stwire_addr_(sbp, np) \
+ (sbp) = &((np)->nva.bp[np->nwid*__inum])
+
+/* DBG ??? add --
+extern void __record_nchg(struct net_t *);
+#define record_nchg_(np) __record_nchg(np)
+--- */
+
+/* SJM 08/08/03 - can't assume caller turns off chged flag any more */
+/* but one record called, it must be off for dctrl processing - not needed */ 
+
+/* recording var change macros */
+/* DBG ??? release add --- */
+#define record_nchg_(np) \
+ do { \
+  __lhs_changed = FALSE; \
+  if (np->nchg_has_dces) \
+   __wakeup_delay_ctrls(np, -1, -1); \
+  if (((np)->nchgaction[__inum] & NCHG_ALL_CHGED) == 0) __add_nchglst_el(np); \
+  if (((np)->nchgaction[__inum] & (NCHG_DMPVARNOW | NCHG_DMPVNOTCHGED)) \
+   == (NCHG_DMPVARNOW | NCHG_DMPVNOTCHGED)) \
+   { \
+    (np)->nchgaction[__inum] &= ~(NCHG_DMPVNOTCHGED); \
+    __add_dmpv_chglst_el(np); \
+   } \
+ } while (0) 
+
+/* --- */
+
+/* DBG ??? add --- 
+extern void __record_sel_nchg(struct net_t *, int32, int32);
+#define record_sel_nchg_(np, i1, i2) __record_sel_nchg(np, i1, i2)
+ --- */
+
+/* SJM 08/08/03 - can't assume caller turns off chged flag any more */
+/* but one record called, it must be off for dctrl processing - not needed */ 
+/* DBG ??? release add --- */
+#define record_sel_nchg_(np, i1, i2) \
+ do { \
+  __lhs_changed = FALSE; \
+  if ((np)->dcelst != NULL) __wakeup_delay_ctrls(np, (i1), (i2)); \
+  if (((np)->nchgaction[__inum] & NCHG_ALL_CHGED) == 0) \
+   __add_select_nchglst_el((np), (i1), (i2)); \
+  if (((np)->nchgaction[__inum] & (NCHG_DMPVARNOW | NCHG_DMPVNOTCHGED)) \
+   == (NCHG_DMPVARNOW | NCHG_DMPVNOTCHGED)) \
+   { \
+    (np)->nchgaction[__inum] &= ~(NCHG_DMPVNOTCHGED); \
+    __add_dmpv_chglst_el(np); \
+   } \
+ } while (0) 
+/* --- */
+
+/* conversion macros */
+#define valtoch_(c) (((c) < 10) ? '0' + (c) : 'a' + (c) - 10)
+/* conversion from real to int32 in Verilog is rounding away from 0 */
+#define ver_rint_(x) ((int32) (((x) >= 0.0) \
+  ? ((x) + 0.500000000) : ((x) - 0.500000000))) 
+#define ver_rword(x) ((word32) ((x) + 0.500000000))
+
+/* convert a 64 bit delay to no. of sim ticks */ 
+#define cnv_num64to_ticks_(tickstim, inttim, mdp) \
+ (tickstim) = __itoticks_tab[__des_timeprec - (mdp)->mtime_units]*(inttim)
+
+/* value extraction macros */
+#define get_packintowrd_(nva, inum, vecw) \
+ (((vecw) <= 4) ? ((word32) (nva).bp[(inum)]) \
+ : (((vecw) > 8) ? (nva).wp[(inum)] : (word32) (nva).hwp[(inum)]))
+
+#define st_packintowrd_(nva, ind, uwrd, vecw) \
+ (((vecw) <= 4) ? ((nva).bp[(ind)] = (byte) (uwrd)) \
+ : (((vecw) > 8) ? ((nva).wp[(ind)] = (uwrd)) : ((nva).hwp[(ind)] = (hword) (uwrd))))
+
+#define ubits_(blen) ((blen) & 0x1f)
+#define wlen_(blen) (((blen) + 31) >> 5)
+#define get_wofs_(bi) ((bi) >> 5)
+#define get_bofs_(bi) ((bi) & 0x1f)
+
+/* version of ubits that returns 32 for all used not 0 */
+#define ubits2_(blen) (((blen & 0x1f) == 0) ? WBITS : (blen & 0x1f))
+
+/* get conducting tranif state for cur. instance (for non input 3rd gate) */
+/* possibilities are 1 on, 0 off, or 3 unknown */
+#define get_tranif_onoff_(gp) \
+  (((gp)->gstate.wp[get_wofs_(2*__inum)] >> get_bofs_(2*__inum)) & 3L)
+
+/* -- unused */
+/* #define cmpxlen(w1, b1, w2, b2) \ */
+/*  (((w1)==(w2)) ? ((b1) - (b2)) : ((w1) - (w2))) */
+
+/* comparison macros */
+#define cvt_wrdbool_(av, bv)  \
+ ((((av) & ~(bv)) != 0L) ? 1 : (((bv) != 0L) ? 3 : 0))
+
+#define vval_is0_(wp, blen) \
+ (((blen) <= WBITS) ? (*(wp) == 0L) : __wide_vval_is0((wp), (blen)))
+
+/* comparing entire 2 wlen section - unused in both must be 0 */
+#define cmp_vval_(wp1, wp2, blen) \
+ memcmp((wp2), (wp1), (WRDBYTES*(wlen_(blen))))
+#define cmp_wvval_(wp1, wp2, wlen) memcmp((wp2), (wp1), (WRDBYTES*wlen))
+
+/* bit load and store macros */
+#define rhsbsel_(wp, bi) ((wp)[get_wofs_(bi)] >> get_bofs_(bi)) & 1L
+
+/* value change macros - can't assume no overlap here */
+#define cp_walign_(dwp, swp, blen) \
+ memmove((dwp), (swp), (int32) (WRDBYTES*(wlen_(blen)))); \
+ (dwp)[wlen_(blen) - 1] &= __masktab[ubits_(blen)]
+
+#define zero_allbits_(wp, blen) memset(((wp)), 0, \
+ (int32) (WRDBYTES*(wlen_(blen))))
+
+#define one_allbits_(wp, blen) \
+ do { register int32 __i; \
+  for (__i = 0; __i < wlen_(blen); __i++) (wp)[__i] = ALL1W; \
+  (wp)[(wlen_(blen)) - 1] &= __masktab[ubits_(blen)]; \
+ } while (0)
+
+/* macro must be passed a byte pointer */
+#define set_byteval_(sbp, len, stval) \
+ do { register int32 __i; \
+  for (__i = 0; __i < (len); __i++) (sbp)[__i] = ((byte) (stval)); \
+ } while (0)
+
+/* this macro may need to be surrounded by { } in some places */
+#define set_regtox_(ap, bp, len) \
+ one_allbits_((ap), len); one_allbits_((bp), len);
+
+/* map index from source [i1:i2] to internal h:0 */
+#define normalize_ndx_(ndxval, mi1, mi2) \
+ (((mi1) >= (mi2)) ? (ndxval - mi2) : (mi2 - ndxval))
+
+/* misc macros */
+#define reg_fr_inhibit_(np) \
+ (np->nu2.qcval[2*__inum].qc_active \
+ || np->nu2.qcval[2*__inum + 1].qc_active)
+
+/* i/o macros */
+
+#define vis_white_(c) \
+ ((((__pv_ctv = __pv_ctab[(c) & 0x7f]) == 1) || __pv_ctv == 3) ? TRUE : FALSE)
+
+#define vis_nonnl_white_(c) ((__pv_ctab[(c) & 0x7f] == 1) ? TRUE : FALSE)
+
+/* notice this does not leave line null terminated */
+#define addch_(ch) \
+ do { \
+  if (__cur_sofs >= __exprlinelen - 1) __chg_xprline_size(1); \
+  __exprline[__cur_sofs++] = (ch); \
+ } while (0)
+
+#define my_puts_(s, f) \
+ do { \
+   fputs((s), (f)); \
+   if ((f) == stdout && __log_s != NULL) fputs((s), __log_s); \
+  } while (0)
+
+#define my_putc_(c, f) \
+ do { \
+   fputc((c), (f)); \
+   if ((f) == stdout && __log_s != NULL) fputc((c), __log_s); \
+  } while (0)
+
+#define my_ungetc_(c, f) \
+ if (f == NULL) \
+ { if (c == EOF) *__visp->vichp = '\0'; else *(--__visp->vichp) = c; } \
+ else ungetc(c, f)
+
+/* must follow convention only immediately read char can be pushed back */
+/* --- DBG remove --- 
+#define my_ungetc_(c, f) \
+  if (f == NULL) \
+   { \
+    if (c == EOF) \
+     { \
+      if (*__visp->vichp != '\0') __arg_terr(__FILE__, __LINE__); \
+      *__visp->vichp = '\0'; \
+     } \
+    else \
+     { \
+      (__visp->vichp)--; \
+      if (*__visp->vichp != c) __arg_terr(__FILE__, __LINE__); \
+      *(__visp->vichp) = c; \
+     } \
+   } \
+  else ungetc(c, f) \
+---- */ 
diff --git a/src/dig_main.c b/src/dig_main.c
new file mode 100644
index 0000000..7ae0df7
--- /dev/null
+++ b/src/dig_main.c
@@ -0,0 +1,16 @@
+/* Copyright (c) 1998-2005 Pragmatic C Software Corp. */
+
+/* === INSERT LICENSE === */
+
+extern int __dig_main(int, char **);
+
+/*
+ * dummy top main module - for PLI user can supply own
+ */
+int main(int argc, char **argv)
+{
+ int rv1;
+
+ rv1 = __dig_main(argc, argv);
+ return(rv1);
+}
diff --git a/src/makefile.amd64 b/src/makefile.amd64
new file mode 100644
index 0000000..c26e3df
--- /dev/null
+++ b/src/makefile.amd64
@@ -0,0 +1,153 @@
+#
+# makefile for Linux
+#
+# by default things get put into directories one level up from src directory
+# and all rules are literal and per file so primitive makes will work
+#
+# this is good starting point for porting to other systems
+#
+
+# define location flags
+INCS=-I../pli_incs
+OBJS=../objs
+BIN=../bin
+
+# you can replace dummy main with your more complicated main
+MAINOBJ=$(OBJS)/dig_main.o
+
+# define list of object files explictly - if add must update list
+CVER_OBJS=$(OBJS)/cver.o $(OBJS)/v_src.o $(OBJS)/v_src2.o $(OBJS)/v_src3.o \
+$(OBJS)/v_fx.o $(OBJS)/v_fx2.o $(OBJS)/v_fx3.o $(OBJS)/v_cnv.o \
+$(OBJS)/v_ex.o $(OBJS)/v_ex2.o $(OBJS)/v_ex3.o $(OBJS)/v_ex4.o \
+$(OBJS)/v_trch.o $(OBJS)/v_del.o $(OBJS)/v_sdf.o $(OBJS)/v_prp.o \
+$(OBJS)/v_prp2.o $(OBJS)/v_sim.o $(OBJS)/v_dbg.o $(OBJS)/v_dbg2.o \
+$(OBJS)/v_ms.o $(OBJS)/v_tf.o $(OBJS)/v_acc.o $(OBJS)/v_vpi.o \
+$(OBJS)/v_vpi2.o $(OBJS)/v_vpi3.o 
+
+# define compilation flags
+WARNS=-Wall
+# omit frame pointer option needed for 25% speed improvment
+OPTFLGS=-fno-strength-reduce -fomit-frame-pointer
+# option good in general, change if you know your X86 architecture
+ARCHFLGS= -march=pentiumpro
+
+# select one of the sets of C flags - comment out others
+
+# cflags when making optimized cver
+CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) $(OPTFLGS) -O2 -m32
+
+# cflags when making -g debugging version 
+# CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) -g -m32
+
+# cflags when making malloc and -g debugging version 
+# assumes dbmalloc-14L2.tgz .a lib and malloc.h installed one level up
+# CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) -D__DBMALLOC__ -g -m32
+
+# change gcc version if needed 
+CC=gcc
+
+# select loader
+LD=ld
+# needed for dynamic PLI loading
+LFLAGS=-export-dynamic
+
+# system libs
+LIBS= -lm -ldl
+# select to use dbmalloc if installed
+# LIBS= -lm ../libdbmalloc.a
+
+# rule for making the cver binary
+cver:	$(MAINOBJ) $(CVER_OBJS)
+	$(CC) $(CFLAGS) $(LFLAGS) $(MAINOBJ) $(CVER_OBJS) \
+	$(LIBS) -o $(BIN)/cver
+
+$(OBJS):	v.h systsks.h cvmacros.h 
+
+$(OBJS)/dig_main.o:	dig_main.c
+	$(CC) $(CFLAGS) -o $(OBJS)/dig_main.o -c dig_main.c
+
+# when adding source files need lines here - insures right c files used
+$(OBJS)/cver.o:	cver.c
+	$(CC) $(CFLAGS) -o $(OBJS)/cver.o -c cver.c
+
+$(OBJS)/v_src.o:	v_src.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src.o -c v_src.c
+
+$(OBJS)/v_src2.o:	v_src2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src2.o -c v_src2.c
+
+$(OBJS)/v_src3.o:	v_src3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src3.o -c v_src3.c
+
+$(OBJS)/v_fx.o:	v_fx.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx.o -c v_fx.c
+
+$(OBJS)/v_fx2.o:	v_fx2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx2.o -c v_fx2.c
+
+$(OBJS)/v_fx3.o:	v_fx3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx3.o -c v_fx3.c
+
+$(OBJS)/v_cnv.o:	v_cnv.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_cnv.o -c v_cnv.c
+
+$(OBJS)/v_ex.o:	v_ex.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex.o -c v_ex.c
+
+$(OBJS)/v_ex2.o:	v_ex2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex2.o -c v_ex2.c
+
+$(OBJS)/v_ex3.o:	v_ex3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex3.o -c v_ex3.c
+
+$(OBJS)/v_ex4.o:	v_ex4.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex4.o -c v_ex4.c
+
+$(OBJS)/v_trch.o:	v_trch.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_trch.o -c v_trch.c
+
+$(OBJS)/v_del.o:	v_del.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_del.o -c v_del.c
+
+$(OBJS)/v_sdf.o:	v_sdf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sdf.o -c v_sdf.c
+
+$(OBJS)/v_prp.o:	v_prp.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp.o -c v_prp.c
+
+$(OBJS)/v_prp2.o:	v_prp2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp2.o -c v_prp2.c
+
+$(OBJS)/v_sim.o:	v_sim.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sim.o -c v_sim.c
+
+$(OBJS)/v_dbg.o:	v_dbg.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg.o -c v_dbg.c
+
+$(OBJS)/v_dbg2.o:	v_dbg2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg2.o -c v_dbg2.c
+
+$(OBJS)/v_ms.o:	v_ms.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ms.o -c v_ms.c
+
+$(OBJS)/v_tf.o:	v_tf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_tf.o -c v_tf.c
+
+$(OBJS)/v_vpi.o:	v_vpi.c 
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi.o -c v_vpi.c
+
+$(OBJS)/v_vpi2.o:	v_vpi2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi2.o -c v_vpi2.c 
+
+$(OBJS)/v_vpi3.o:	v_vpi3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi3.o -c v_vpi3.c 
+
+$(OBJS)/v_acc.o:	v_acc.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_acc.o -c v_acc.c 
+
+all:	cver
+	echo "done"
+
+# no make clean - just erase all .o files and binary
+clean:
+	rm -f $(OBJS)/*.o $(BIN)/cver
diff --git a/src/makefile.cygwin b/src/makefile.cygwin
new file mode 100644
index 0000000..564b1f7
--- /dev/null
+++ b/src/makefile.cygwin
@@ -0,0 +1,153 @@
+#
+# makefile for Cygwin
+#
+# by default things get put into directories one level up from src directory
+# and all rules are literal and per file so primitive makes will work
+#
+# this is good starting point for porting to other systems
+#
+
+# define location flags
+INCS=-I../pli_incs
+OBJS=../objs
+BIN=../bin
+
+# you can replace dummy main with your more complicated main
+MAINOBJ=$(OBJS)/dig_main.o
+
+# define list of object files explictly - if add must update list
+CVER_OBJS=$(OBJS)/cver.o $(OBJS)/v_src.o $(OBJS)/v_src2.o $(OBJS)/v_src3.o \
+$(OBJS)/v_fx.o $(OBJS)/v_fx2.o $(OBJS)/v_fx3.o $(OBJS)/v_cnv.o \
+$(OBJS)/v_ex.o $(OBJS)/v_ex2.o $(OBJS)/v_ex3.o $(OBJS)/v_ex4.o \
+$(OBJS)/v_trch.o $(OBJS)/v_del.o $(OBJS)/v_sdf.o $(OBJS)/v_prp.o \
+$(OBJS)/v_prp2.o $(OBJS)/v_sim.o $(OBJS)/v_dbg.o $(OBJS)/v_dbg2.o \
+$(OBJS)/v_ms.o $(OBJS)/v_tf.o $(OBJS)/v_acc.o $(OBJS)/v_vpi.o \
+$(OBJS)/v_vpi2.o $(OBJS)/v_vpi3.o 
+
+# define compilation flags
+WARNS=-Wall
+# omit frame pointer option needed for 25% speed improvment
+OPTFLGS=-fno-strength-reduce -fomit-frame-pointer
+# option good in general, change if you know your X86 architecture
+ARCHFLGS= -march=pentium
+
+# select one of the sets of C flags - comment out others
+
+# cflags when making optimized cver
+CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) $(OPTFLGS) -O2
+
+# cflags when making -g debugging version 
+# CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) -g
+
+# cflags when making malloc and -g debugging version 
+# assumes dbmalloc-14L2.tgz .a lib and malloc.h installed one level up
+# CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) -D__DBMALLOC__ -g
+
+# change gcc version if needed 
+CC=gcc
+
+# select loader
+LD=ld
+# needed for dynamic PLI loading
+LFLAGS=-export-dynamic
+
+# system libs
+LIBS= -lm 
+# select to use dbmalloc if installed
+# LIBS= -lm ../libdbmalloc.a
+
+# rule for making the cver binary
+cver:	$(MAINOBJ) $(CVER_OBJS)
+	$(CC) $(CFLAGS) $(LFLAGS) $(MAINOBJ) $(CVER_OBJS) \
+	$(LIBS) -o $(BIN)/cver
+
+$(OBJS):	v.h systsks.h cvmacros.h 
+
+$(OBJS)/dig_main.o:	dig_main.c
+	$(CC) $(CFLAGS) -o $(OBJS)/dig_main.o -c dig_main.c
+
+# when adding source files need lines here - insures right c files used
+$(OBJS)/cver.o:	cver.c
+	$(CC) $(CFLAGS) -o $(OBJS)/cver.o -c cver.c
+
+$(OBJS)/v_src.o:	v_src.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src.o -c v_src.c
+
+$(OBJS)/v_src2.o:	v_src2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src2.o -c v_src2.c
+
+$(OBJS)/v_src3.o:	v_src3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src3.o -c v_src3.c
+
+$(OBJS)/v_fx.o:	v_fx.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx.o -c v_fx.c
+
+$(OBJS)/v_fx2.o:	v_fx2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx2.o -c v_fx2.c
+
+$(OBJS)/v_fx3.o:	v_fx3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx3.o -c v_fx3.c
+
+$(OBJS)/v_cnv.o:	v_cnv.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_cnv.o -c v_cnv.c
+
+$(OBJS)/v_ex.o:	v_ex.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex.o -c v_ex.c
+
+$(OBJS)/v_ex2.o:	v_ex2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex2.o -c v_ex2.c
+
+$(OBJS)/v_ex3.o:	v_ex3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex3.o -c v_ex3.c
+
+$(OBJS)/v_ex4.o:	v_ex4.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex4.o -c v_ex4.c
+
+$(OBJS)/v_trch.o:	v_trch.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_trch.o -c v_trch.c
+
+$(OBJS)/v_del.o:	v_del.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_del.o -c v_del.c
+
+$(OBJS)/v_sdf.o:	v_sdf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sdf.o -c v_sdf.c
+
+$(OBJS)/v_prp.o:	v_prp.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp.o -c v_prp.c
+
+$(OBJS)/v_prp2.o:	v_prp2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp2.o -c v_prp2.c
+
+$(OBJS)/v_sim.o:	v_sim.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sim.o -c v_sim.c
+
+$(OBJS)/v_dbg.o:	v_dbg.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg.o -c v_dbg.c
+
+$(OBJS)/v_dbg2.o:	v_dbg2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg2.o -c v_dbg2.c
+
+$(OBJS)/v_ms.o:	v_ms.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ms.o -c v_ms.c
+
+$(OBJS)/v_tf.o:	v_tf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_tf.o -c v_tf.c
+
+$(OBJS)/v_vpi.o:	v_vpi.c 
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi.o -c v_vpi.c
+
+$(OBJS)/v_vpi2.o:	v_vpi2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi2.o -c v_vpi2.c 
+
+$(OBJS)/v_vpi3.o:	v_vpi3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi3.o -c v_vpi3.c 
+
+$(OBJS)/v_acc.o:	v_acc.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_acc.o -c v_acc.c 
+
+all:	cver
+	echo "done"
+
+# no make clean - just erase all .o files and binary
+clean:
+	rm -f $(OBJS)/*.o $(BIN)/cver
diff --git a/src/makefile.freebsd b/src/makefile.freebsd
new file mode 100644
index 0000000..3ef0778
--- /dev/null
+++ b/src/makefile.freebsd
@@ -0,0 +1,147 @@
+#
+# makefile for Free BSD 
+#
+# by default things get put into directories one level up from src directory
+# and all rules are literal and per file so primitive makes will work
+#
+# this is good starting point for porting to other systems
+#
+
+# define location flags
+INCS=-I../pli_incs
+OBJS=../objs
+BIN=../bin
+
+# you can replace dummy main with your more complicated main
+MAINOBJ=$(OBJS)/dig_main.o
+
+# define list of object files explictly - if add must update list
+CVER_OBJS=$(OBJS)/cver.o $(OBJS)/v_src.o $(OBJS)/v_src2.o $(OBJS)/v_src3.o \
+$(OBJS)/v_fx.o $(OBJS)/v_fx2.o $(OBJS)/v_fx3.o $(OBJS)/v_cnv.o \
+$(OBJS)/v_ex.o $(OBJS)/v_ex2.o $(OBJS)/v_ex3.o $(OBJS)/v_ex4.o \
+$(OBJS)/v_trch.o $(OBJS)/v_del.o $(OBJS)/v_sdf.o $(OBJS)/v_prp.o \
+$(OBJS)/v_prp2.o $(OBJS)/v_sim.o $(OBJS)/v_dbg.o $(OBJS)/v_dbg2.o \
+$(OBJS)/v_ms.o $(OBJS)/v_tf.o $(OBJS)/v_acc.o $(OBJS)/v_vpi.o \
+$(OBJS)/v_vpi2.o $(OBJS)/v_vpi3.o 
+
+# define compilation flags
+WARNS=-Wall
+# omit frame pointer option needed for 25% speed improvment
+OPTFLGS=-fno-strength-reduce -fomit-frame-pointer
+# use this option for current Apple systems
+# ARCHFLGS= -mcpu=powerpc
+
+# select one of the sets of C flags - comment out others
+
+# cflags when making optimized cver
+CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) $(OPTFLGS) -O2 
+
+# cflags when making -g debugging version 
+# CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) -g
+
+# change gcc version if needed 
+CC=cc
+
+# select loader
+LD=ld
+# needed for dynamic PLI loading
+LFLAGS=-export-dynamic
+
+# system libs
+LIBS= -lm
+
+# rule for making the cver binary
+cver:	$(MAINOBJ) $(CVER_OBJS)
+	$(CC) $(CFLAGS) $(LFLAGS) $(MAINOBJ) $(CVER_OBJS) \
+	$(LIBS) -o $(BIN)/cver
+
+$(OBJS):	v.h systsks.h cvmacros.h 
+
+$(OBJS)/dig_main.o:	dig_main.c
+	$(CC) $(CFLAGS) -o $(OBJS)/dig_main.o -c dig_main.c
+
+# when adding source files need lines here - insures right c files used
+$(OBJS)/cver.o:	cver.c
+	$(CC) $(CFLAGS) -o $(OBJS)/cver.o -c cver.c
+
+$(OBJS)/v_src.o:	v_src.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src.o -c v_src.c
+
+$(OBJS)/v_src2.o:	v_src2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src2.o -c v_src2.c
+
+$(OBJS)/v_src3.o:	v_src3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src3.o -c v_src3.c
+
+$(OBJS)/v_fx.o:	v_fx.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx.o -c v_fx.c
+
+$(OBJS)/v_fx2.o:	v_fx2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx2.o -c v_fx2.c
+
+$(OBJS)/v_fx3.o:	v_fx3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx3.o -c v_fx3.c
+
+$(OBJS)/v_cnv.o:	v_cnv.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_cnv.o -c v_cnv.c
+
+$(OBJS)/v_ex.o:	v_ex.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex.o -c v_ex.c
+
+$(OBJS)/v_ex2.o:	v_ex2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex2.o -c v_ex2.c
+
+$(OBJS)/v_ex3.o:	v_ex3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex3.o -c v_ex3.c
+
+$(OBJS)/v_ex4.o:	v_ex4.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex4.o -c v_ex4.c
+
+$(OBJS)/v_trch.o:	v_trch.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_trch.o -c v_trch.c
+
+$(OBJS)/v_del.o:	v_del.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_del.o -c v_del.c
+
+$(OBJS)/v_sdf.o:	v_sdf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sdf.o -c v_sdf.c
+
+$(OBJS)/v_prp.o:	v_prp.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp.o -c v_prp.c
+
+$(OBJS)/v_prp2.o:	v_prp2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp2.o -c v_prp2.c
+
+$(OBJS)/v_sim.o:	v_sim.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sim.o -c v_sim.c
+
+$(OBJS)/v_dbg.o:	v_dbg.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg.o -c v_dbg.c
+
+$(OBJS)/v_dbg2.o:	v_dbg2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg2.o -c v_dbg2.c
+
+$(OBJS)/v_ms.o:	v_ms.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ms.o -c v_ms.c
+
+$(OBJS)/v_tf.o:	v_tf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_tf.o -c v_tf.c
+
+$(OBJS)/v_vpi.o:	v_vpi.c 
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi.o -c v_vpi.c
+
+$(OBJS)/v_vpi2.o:	v_vpi2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi2.o -c v_vpi2.c 
+
+$(OBJS)/v_vpi3.o:	v_vpi3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi3.o -c v_vpi3.c 
+
+$(OBJS)/v_acc.o:	v_acc.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_acc.o -c v_acc.c 
+
+all:	cver
+	echo "done"
+
+# no make clean - just erase all .o files and binary
+clean:
+	rm -f $(OBJS)/*.o $(BIN)/cver
diff --git a/src/makefile.lnx b/src/makefile.lnx
new file mode 100644
index 0000000..e6d48b2
--- /dev/null
+++ b/src/makefile.lnx
@@ -0,0 +1,153 @@
+#
+# makefile for Linux
+#
+# by default things get put into directories one level up from src directory
+# and all rules are literal and per file so primitive makes will work
+#
+# this is good starting point for porting to other systems
+#
+
+# define location flags
+INCS=-I../pli_incs
+OBJS=../objs
+BIN=../bin
+
+# you can replace dummy main with your more complicated main
+MAINOBJ=$(OBJS)/dig_main.o
+
+# define list of object files explictly - if add must update list
+CVER_OBJS=$(OBJS)/cver.o $(OBJS)/v_src.o $(OBJS)/v_src2.o $(OBJS)/v_src3.o \
+$(OBJS)/v_fx.o $(OBJS)/v_fx2.o $(OBJS)/v_fx3.o $(OBJS)/v_cnv.o \
+$(OBJS)/v_ex.o $(OBJS)/v_ex2.o $(OBJS)/v_ex3.o $(OBJS)/v_ex4.o \
+$(OBJS)/v_trch.o $(OBJS)/v_del.o $(OBJS)/v_sdf.o $(OBJS)/v_prp.o \
+$(OBJS)/v_prp2.o $(OBJS)/v_sim.o $(OBJS)/v_dbg.o $(OBJS)/v_dbg2.o \
+$(OBJS)/v_ms.o $(OBJS)/v_tf.o $(OBJS)/v_acc.o $(OBJS)/v_vpi.o \
+$(OBJS)/v_vpi2.o $(OBJS)/v_vpi3.o 
+
+# define compilation flags
+WARNS=-Wall
+# omit frame pointer option needed for 25% speed improvment
+OPTFLGS=-fno-strength-reduce -fomit-frame-pointer
+# option good in general, change if you know your X86 architecture
+ARCHFLGS= -march=pentiumpro
+
+# select one of the sets of C flags - comment out others
+
+# cflags when making optimized cver
+CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) $(OPTFLGS) -O2 
+
+# cflags when making -g debugging version 
+# CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) -g
+
+# cflags when making malloc and -g debugging version 
+# assumes dbmalloc-14L2.tgz .a lib and malloc.h installed one level up
+# CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) -D__DBMALLOC__ -g
+
+# change gcc version if needed 
+CC=gcc
+
+# select loader
+LD=ld
+# needed for dynamic PLI loading
+LFLAGS=-export-dynamic
+
+# system libs
+LIBS= -lm -ldl
+# select to use dbmalloc if installed
+# LIBS= -lm ../libdbmalloc.a
+
+# rule for making the cver binary
+cver:	$(MAINOBJ) $(CVER_OBJS)
+	$(CC) $(CFLAGS) $(LFLAGS) $(MAINOBJ) $(CVER_OBJS) \
+	$(LIBS) -o $(BIN)/cver
+
+$(OBJS):	v.h systsks.h cvmacros.h 
+
+$(OBJS)/dig_main.o:	dig_main.c
+	$(CC) $(CFLAGS) -o $(OBJS)/dig_main.o -c dig_main.c
+
+# when adding source files need lines here - insures right c files used
+$(OBJS)/cver.o:	cver.c
+	$(CC) $(CFLAGS) -o $(OBJS)/cver.o -c cver.c
+
+$(OBJS)/v_src.o:	v_src.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src.o -c v_src.c
+
+$(OBJS)/v_src2.o:	v_src2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src2.o -c v_src2.c
+
+$(OBJS)/v_src3.o:	v_src3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src3.o -c v_src3.c
+
+$(OBJS)/v_fx.o:	v_fx.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx.o -c v_fx.c
+
+$(OBJS)/v_fx2.o:	v_fx2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx2.o -c v_fx2.c
+
+$(OBJS)/v_fx3.o:	v_fx3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx3.o -c v_fx3.c
+
+$(OBJS)/v_cnv.o:	v_cnv.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_cnv.o -c v_cnv.c
+
+$(OBJS)/v_ex.o:	v_ex.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex.o -c v_ex.c
+
+$(OBJS)/v_ex2.o:	v_ex2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex2.o -c v_ex2.c
+
+$(OBJS)/v_ex3.o:	v_ex3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex3.o -c v_ex3.c
+
+$(OBJS)/v_ex4.o:	v_ex4.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex4.o -c v_ex4.c
+
+$(OBJS)/v_trch.o:	v_trch.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_trch.o -c v_trch.c
+
+$(OBJS)/v_del.o:	v_del.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_del.o -c v_del.c
+
+$(OBJS)/v_sdf.o:	v_sdf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sdf.o -c v_sdf.c
+
+$(OBJS)/v_prp.o:	v_prp.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp.o -c v_prp.c
+
+$(OBJS)/v_prp2.o:	v_prp2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp2.o -c v_prp2.c
+
+$(OBJS)/v_sim.o:	v_sim.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sim.o -c v_sim.c
+
+$(OBJS)/v_dbg.o:	v_dbg.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg.o -c v_dbg.c
+
+$(OBJS)/v_dbg2.o:	v_dbg2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg2.o -c v_dbg2.c
+
+$(OBJS)/v_ms.o:	v_ms.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ms.o -c v_ms.c
+
+$(OBJS)/v_tf.o:	v_tf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_tf.o -c v_tf.c
+
+$(OBJS)/v_vpi.o:	v_vpi.c 
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi.o -c v_vpi.c
+
+$(OBJS)/v_vpi2.o:	v_vpi2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi2.o -c v_vpi2.c 
+
+$(OBJS)/v_vpi3.o:	v_vpi3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi3.o -c v_vpi3.c 
+
+$(OBJS)/v_acc.o:	v_acc.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_acc.o -c v_acc.c 
+
+all:	cver
+	echo "done"
+
+# no make clean - just erase all .o files and binary
+clean:
+	rm -f $(OBJS)/*.o $(BIN)/cver
diff --git a/src/makefile.osx b/src/makefile.osx
new file mode 100644
index 0000000..e9f7732
--- /dev/null
+++ b/src/makefile.osx
@@ -0,0 +1,147 @@
+#
+# makefile for Linux
+#
+# by default things get put into directories one level up from src directory
+# and all rules are literal and per file so primitive makes will work
+#
+# this is good starting point for porting to other systems
+#
+
+# define location flags
+INCS=-I../pli_incs
+OBJS=../objs
+BIN=../bin
+
+# you can replace dummy main with your more complicated main
+MAINOBJ=$(OBJS)/dig_main.o
+
+# define list of object files explictly - if add must update list
+CVER_OBJS=$(OBJS)/cver.o $(OBJS)/v_src.o $(OBJS)/v_src2.o $(OBJS)/v_src3.o \
+$(OBJS)/v_fx.o $(OBJS)/v_fx2.o $(OBJS)/v_fx3.o $(OBJS)/v_cnv.o \
+$(OBJS)/v_ex.o $(OBJS)/v_ex2.o $(OBJS)/v_ex3.o $(OBJS)/v_ex4.o \
+$(OBJS)/v_trch.o $(OBJS)/v_del.o $(OBJS)/v_sdf.o $(OBJS)/v_prp.o \
+$(OBJS)/v_prp2.o $(OBJS)/v_sim.o $(OBJS)/v_dbg.o $(OBJS)/v_dbg2.o \
+$(OBJS)/v_ms.o $(OBJS)/v_tf.o $(OBJS)/v_acc.o $(OBJS)/v_vpi.o \
+$(OBJS)/v_vpi2.o $(OBJS)/v_vpi3.o 
+
+# define compilation flags
+WARNS=-Wall
+# omit frame pointer option needed for 25% speed improvment
+OPTFLGS=-fno-strength-reduce -fomit-frame-pointer
+# use this option for current Apple systems
+ARCHFLGS= -mcpu=powerpc
+
+# select one of the sets of C flags - comment out others
+
+# cflags when making optimized cver
+CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) $(OPTFLGS) -O2 
+
+# cflags when making -g debugging version 
+# CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) -g
+
+# change gcc version if needed 
+CC=cc
+
+# select loader
+LD=ld
+# needed for dynamic PLI loading
+LFLAGS=--export-dynamic
+
+# system libs
+LIBS= -lm -ldl
+
+# rule for making the cver binary
+cver:	$(MAINOBJ) $(CVER_OBJS)
+	$(CC) $(CFLAGS) $(LFLAGS) $(MAINOBJ) $(CVER_OBJS) \
+	$(LIBS) -o $(BIN)/cver
+
+$(OBJS):	v.h systsks.h cvmacros.h 
+
+$(OBJS)/dig_main.o:	dig_main.c
+	$(CC) $(CFLAGS) -o $(OBJS)/dig_main.o -c dig_main.c
+
+# when adding source files need lines here - insures right c files used
+$(OBJS)/cver.o:	cver.c
+	$(CC) $(CFLAGS) -o $(OBJS)/cver.o -c cver.c
+
+$(OBJS)/v_src.o:	v_src.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src.o -c v_src.c
+
+$(OBJS)/v_src2.o:	v_src2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src2.o -c v_src2.c
+
+$(OBJS)/v_src3.o:	v_src3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src3.o -c v_src3.c
+
+$(OBJS)/v_fx.o:	v_fx.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx.o -c v_fx.c
+
+$(OBJS)/v_fx2.o:	v_fx2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx2.o -c v_fx2.c
+
+$(OBJS)/v_fx3.o:	v_fx3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx3.o -c v_fx3.c
+
+$(OBJS)/v_cnv.o:	v_cnv.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_cnv.o -c v_cnv.c
+
+$(OBJS)/v_ex.o:	v_ex.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex.o -c v_ex.c
+
+$(OBJS)/v_ex2.o:	v_ex2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex2.o -c v_ex2.c
+
+$(OBJS)/v_ex3.o:	v_ex3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex3.o -c v_ex3.c
+
+$(OBJS)/v_ex4.o:	v_ex4.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex4.o -c v_ex4.c
+
+$(OBJS)/v_trch.o:	v_trch.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_trch.o -c v_trch.c
+
+$(OBJS)/v_del.o:	v_del.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_del.o -c v_del.c
+
+$(OBJS)/v_sdf.o:	v_sdf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sdf.o -c v_sdf.c
+
+$(OBJS)/v_prp.o:	v_prp.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp.o -c v_prp.c
+
+$(OBJS)/v_prp2.o:	v_prp2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp2.o -c v_prp2.c
+
+$(OBJS)/v_sim.o:	v_sim.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sim.o -c v_sim.c
+
+$(OBJS)/v_dbg.o:	v_dbg.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg.o -c v_dbg.c
+
+$(OBJS)/v_dbg2.o:	v_dbg2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg2.o -c v_dbg2.c
+
+$(OBJS)/v_ms.o:	v_ms.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ms.o -c v_ms.c
+
+$(OBJS)/v_tf.o:	v_tf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_tf.o -c v_tf.c
+
+$(OBJS)/v_vpi.o:	v_vpi.c 
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi.o -c v_vpi.c
+
+$(OBJS)/v_vpi2.o:	v_vpi2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi2.o -c v_vpi2.c 
+
+$(OBJS)/v_vpi3.o:	v_vpi3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi3.o -c v_vpi3.c 
+
+$(OBJS)/v_acc.o:	v_acc.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_acc.o -c v_acc.c 
+
+all:	cver
+	echo "done"
+
+# no make clean - just erase all .o files and binary
+clean:
+	rm -f $(OBJS)/*.o $(BIN)/cver
diff --git a/src/makefile.sparc-gcc b/src/makefile.sparc-gcc
new file mode 100644
index 0000000..4395109
--- /dev/null
+++ b/src/makefile.sparc-gcc
@@ -0,0 +1,145 @@
+#
+# makefile for Sparc Solaris using gcc
+#
+# by default things get put into directories one level up from src directory
+# and all rules are literal and per file so primitive makes will work
+#
+
+# define location flags
+INCS=-I../pli_incs
+OBJS=../objs
+BIN=../bin
+
+# you can replace dummy main with your more complicated main
+MAINOBJ=$(OBJS)/dig_main.o
+
+# define list of object files explictly - if add must update list
+CVER_OBJS=$(OBJS)/cver.o $(OBJS)/v_src.o $(OBJS)/v_src2.o $(OBJS)/v_src3.o \
+$(OBJS)/v_fx.o $(OBJS)/v_fx2.o $(OBJS)/v_fx3.o $(OBJS)/v_cnv.o \
+$(OBJS)/v_ex.o $(OBJS)/v_ex2.o $(OBJS)/v_ex3.o $(OBJS)/v_ex4.o \
+$(OBJS)/v_trch.o $(OBJS)/v_del.o $(OBJS)/v_sdf.o $(OBJS)/v_prp.o \
+$(OBJS)/v_prp2.o $(OBJS)/v_sim.o $(OBJS)/v_dbg.o $(OBJS)/v_dbg2.o \
+$(OBJS)/v_ms.o $(OBJS)/v_tf.o $(OBJS)/v_acc.o $(OBJS)/v_vpi.o \
+$(OBJS)/v_vpi2.o $(OBJS)/v_vpi3.o 
+
+# define compilation flags
+WARNS=-Wall
+# omit frame pointer option needed for 25% speed improvment
+OPTFLGS=-fno-strength-reduce -fomit-frame-pointer
+# option good in general, change if you know your sparc gcc architecture
+ARCHFLGS= -mcpu=v8
+
+# select one of the sets of C flags - comment out others
+
+# cflags when making optimized cver
+CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) $(OPTFLGS) -O2 
+
+# cflags when making -g debugging version 
+# CFLAGS= $(ARCHFLGS) -pipe $(WARNS) $(INCS) -g
+
+# change gcc version if needed 
+CC=gcc
+
+# select loader
+LD=ld
+# needed for dynamic PLI loading
+LFLAGS=--export-dynamic
+
+# system libs
+LIBS= -lm -ldl
+
+# rule for making the cver binary
+cver:	$(MAINOBJ) $(CVER_OBJS)
+	$(CC) $(CFLAGS) $(LFLAGS) $(MAINOBJ) $(CVER_OBJS) \
+	$(LIBS) -o $(BIN)/cver
+
+$(OBJS):	v.h systsks.h cvmacros.h 
+
+$(OBJS)/dig_main.o:	dig_main.c
+	$(CC) $(CFLAGS) -o $(OBJS)/dig_main.o -c dig_main.c
+
+# when adding source files need lines here - insures right c files used
+$(OBJS)/cver.o:	cver.c
+	$(CC) $(CFLAGS) -o $(OBJS)/cver.o -c cver.c
+
+$(OBJS)/v_src.o:	v_src.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src.o -c v_src.c
+
+$(OBJS)/v_src2.o:	v_src2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src2.o -c v_src2.c
+
+$(OBJS)/v_src3.o:	v_src3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_src3.o -c v_src3.c
+
+$(OBJS)/v_fx.o:	v_fx.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx.o -c v_fx.c
+
+$(OBJS)/v_fx2.o:	v_fx2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx2.o -c v_fx2.c
+
+$(OBJS)/v_fx3.o:	v_fx3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_fx3.o -c v_fx3.c
+
+$(OBJS)/v_cnv.o:	v_cnv.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_cnv.o -c v_cnv.c
+
+$(OBJS)/v_ex.o:	v_ex.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex.o -c v_ex.c
+
+$(OBJS)/v_ex2.o:	v_ex2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex2.o -c v_ex2.c
+
+$(OBJS)/v_ex3.o:	v_ex3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex3.o -c v_ex3.c
+
+$(OBJS)/v_ex4.o:	v_ex4.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ex4.o -c v_ex4.c
+
+$(OBJS)/v_trch.o:	v_trch.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_trch.o -c v_trch.c
+
+$(OBJS)/v_del.o:	v_del.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_del.o -c v_del.c
+
+$(OBJS)/v_sdf.o:	v_sdf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sdf.o -c v_sdf.c
+
+$(OBJS)/v_prp.o:	v_prp.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp.o -c v_prp.c
+
+$(OBJS)/v_prp2.o:	v_prp2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_prp2.o -c v_prp2.c
+
+$(OBJS)/v_sim.o:	v_sim.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_sim.o -c v_sim.c
+
+$(OBJS)/v_dbg.o:	v_dbg.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg.o -c v_dbg.c
+
+$(OBJS)/v_dbg2.o:	v_dbg2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_dbg2.o -c v_dbg2.c
+
+$(OBJS)/v_ms.o:	v_ms.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_ms.o -c v_ms.c
+
+$(OBJS)/v_tf.o:	v_tf.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_tf.o -c v_tf.c
+
+$(OBJS)/v_vpi.o:	v_vpi.c 
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi.o -c v_vpi.c
+
+$(OBJS)/v_vpi2.o:	v_vpi2.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi2.o -c v_vpi2.c 
+
+$(OBJS)/v_vpi3.o:	v_vpi3.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_vpi3.o -c v_vpi3.c 
+
+$(OBJS)/v_acc.o:	v_acc.c
+	$(CC) $(CFLAGS) -o $(OBJS)/v_acc.o -c v_acc.c 
+
+all:	cver
+	echo "done"
+
+# no make clean - just erase all .o files and binary
+clean:
+	rm -f $(OBJS)/*.o $(BIN)/cver
diff --git a/src/systsks.h b/src/systsks.h
new file mode 100644
index 0000000..0c0e060
--- /dev/null
+++ b/src/systsks.h
@@ -0,0 +1,246 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * system function id numbers
+ * notice no patters other than pli tf_ start above these (at 1000 for now)
+ */
+
+/* functions for converting reals */
+#define STN_BITSTOREAL 1
+#define STN_ITOR 2
+#define STN_REALTOBITS 3
+#define STN_RTOI 4
+
+/* time related system functions */
+#define STN_REALTIME 5
+#define STN_STIME 6
+#define STN_TIME 7
+#define STN_SCALE 8
+
+/* random number generators */
+#define STN_RANDOM 9
+#define STN_DIST_UNIFORM 10
+#define STN_DIST_NORMAL 11
+#define STN_DIST_EXPONENTIAL 12
+#define STN_DIST_POISSON 13
+#define STN_DIST_CHI_SQUARE 14
+#define STN_DIST_T 15
+#define STN_DIST_ERLANG 16
+
+/* misc. system functions */
+#define STN_TESTPLUSARGS 17
+#define STN_FOPEN 18
+#define STN_COUNT_DRIVERS 19
+#define STN_RESET_COUNT 21
+#define STN_RESET_VALUE 22
+#define STN_GETPATTERN 20
+#define STN_Q_FULL 23
+
+/* AIV 09/08/03 - new P1364 2001 fileio sys funcs */
+#define STN_FGETC 24
+#define STN_UNGETC 25
+#define STN_FGETS 26
+#define STN_FTELL 27
+#define STN_REWIND 28
+#define STN_FSEEK 29
+#define STN_FERROR 30 
+#define STN_FREAD 31
+#define STN_FSCANF 32 
+#define STN_SSCANF 33
+
+/* system task id numbers */
+
+/* display type tasks */
+#define STN_FCLOSE 100
+/* formated procedural display - implied cr */
+#define STN_DISPLAY 101
+#define STN_DISPLAYB 102
+#define STN_DISPLAYH 103
+#define STN_DISPLAYO 104
+#define STN_FDISPLAY 105
+#define STN_FDISPLAYH 106
+#define STN_FDISPLAYB 107
+#define STN_FDISPLAYO 108
+
+/* formated procedural display - no implied cr */
+#define STN_WRITE 109
+#define STN_WRITEH 110
+#define STN_WRITEB 111
+#define STN_WRITEO 112
+#define STN_FWRITE 113
+#define STN_FWRITEH 114
+#define STN_FWRITEB 115
+#define STN_FWRITEO 116
+
+/* like display except write at end of current time */
+#define STN_STROBE 117
+#define STN_STROBEH 118
+#define STN_STROBEB 119
+#define STN_STROBEO 120
+#define STN_FSTROBE 121
+#define STN_FSTROBEH 122
+#define STN_FSTROBEB 123
+#define STN_FSTROBEO 124
+
+#define STN_MONITOR 125
+#define STN_MONITOROFF 126
+#define STN_MONITORON 127
+#define STN_FMONITOR 128
+#define STN_MONITORH 129
+#define STN_MONITORB 130
+#define STN_MONITORO 131
+#define STN_FMONITORH 132
+#define STN_FMONITORB 133
+#define STN_FMONITORO 134
+
+/* time releated system tasks */
+#define STN_PRINTTIMESCALE 135
+#define STN_TIMEFORMAT 136
+
+/* notice specify section timing checks not here - no exec - built in tevs */
+#define STN_READMEMB 137
+#define STN_READMEMH 138
+#define STN_SREADMEMB 139
+#define STN_SREADMEMH 140
+
+/* dump variables tasks */
+#define STN_DUMPVARS 141
+#define STN_DUMPALL 142
+#define STN_DUMPFILE 143
+#define STN_DUMPFLUSH 144
+#define STN_DUMPLIMIT 145
+#define STN_DUMPOFF 146
+#define STN_DUMPON 147
+
+/* mainly interactive system tasks */
+#define STN_KEY 148
+#define STN_NOKEY 149
+#define STN_LIST 150
+#define STN_LOG 151
+#define STN_NOLOG 152
+#define STN_HISTORY 153
+#define STN_SAVE 154
+#define STN_INCSAVE 155
+#define STN_INPUT 156
+#define STN_RESTART 157
+#define STN_SETTRACE 158
+#define STN_CLEARTRACE 159
+#define STN_RESET 160
+#define STN_FINISH 161
+#define STN_STOP 162
+#define STN_KEEPCMDS 163
+#define STN_NOKEEPCMDS 164
+
+/* internal simulation state printng tasks */
+#define STN_SCOPE 165
+#define STN_SHOWALLINSTANCES 166
+#define STN_SHOWEXPANDEDNETS 167
+#define STN_SHOWSCOPES 168
+#define STN_SHOWVARIABLES 169
+#define STN_SHOWVARS 170
+
+/* q manipulation tasks - also q_full function */
+#define STN_Q_INITIALIZE 171
+#define STN_Q_ADD 172
+#define STN_Q_REMOVE 173
+#define STN_Q_EXAM 174
+
+/* sdf annotate system task */
+#define STN_SDF_ANNOTATE 175
+
+/* new P1364 2001 special signed/word32 conversion system functions */
+#define STN_SIGNED 176
+#define STN_UNSIGNED 177
+
+/* graphical output tasks */
+#define STN_GRREMOTE 180
+#define STN_PSWAVES 181
+#define STN_GRSYNCHON 182
+#define STN_GRREGS 183
+#define STN_GRWAVES 184
+#define STN_FREEZEWAVES 185
+#define STN_DEFINEGROUPWAVES 186
+
+/* Cver extension (system tasks or functions) */
+#define STN_SETDEBUG 190 
+#define STN_CLEARDEBUG 191
+#define STN_SETEVTRACE 192
+#define STN_CLEAREVTRACE 193
+#define STN_TRACEFILE 194
+#define STN_STICKSTIME 195
+#define STN_TICKSTIME 196
+#define STN_SNAPSHOT 197
+#define STN_SYSTEM 198
+#define STN_SUPWARNS 199
+#define STN_ALLOWWARNS 200
+#define STN_MEMUSE 201
+#define STN_FLUSHLOG 202
+#define STN_SCANPLUSARGS 203
+
+/* new ams transcendental function extension but works in digital */
+/* SJM 10/01/03 - leaving in for now */
+#define STN_COS 217
+#define STN_SIN 218
+#define STN_TAN 219
+#define STN_ACOS 220
+#define STN_ASIN 221
+#define STN_ATAN 222
+#define STN_ATAN2 223
+#define STN_COSH 224
+#define STN_SINH 225
+#define STN_TANH 226
+#define STN_ACOSH 227
+#define STN_ASINH 228
+#define STN_ATANH 229
+
+#define STN_INT 230
+#define STN_SGN 231
+#define STN_LN 232
+#define STN_LOG10 233
+#define STN_ABS 234
+#define STN_POW 235
+#define STN_SQRT 236
+#define STN_EXP 237
+#define STN_MIN 238
+#define STN_MAX 239
+
+#define STN_HSQRT 240
+#define STN_HPOW 241
+#define STN_HPWR 242
+#define STN_HLOG 243
+#define STN_HLOG10 244
+#define STN_HDB 245
+#define STN_HSIGN 246
+#define STN_HYPOT 247
+
+/* AIV 09/08/03 - new P1364 2001 fileio sys tasks */
+#define STN_FFLUSH 248
+#define STN_SWRITE 249
+#define STN_SWRITEB 250
+#define STN_SWRITEH 251
+#define STN_SWRITEO 252
+#define STN_SFORMAT 253
+
diff --git a/src/v.h b/src/v.h
new file mode 100644
index 0000000..7e549ad
--- /dev/null
+++ b/src/v.h
@@ -0,0 +1,3671 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+#define VERS "GPLCVER_2"
+
+#define VERS2 ".11a"
+
+#define OFDT "07/05/05"
+#define OUTLINLEN 71          /* length of output file line */
+#define DFLTIOWORDS 8         /* preallocated size for I/O and work values */
+#define MUSTFREEWORDS 64      /* for stk values wider free when done */
+/* ? for debugging */
+/* #define DFLTIOWORDS 1 */   /* preallocated size for I/O and work values */
+/* #define MUSTFREEWORDS 1 */ /* for stk values wider free when done */
+
+#define MAXNUMBITS 1000000    /* allowing 1 million for now */
+#define MAXNUMPORTS 1000000   /* index must fit in 20 bits so 1 million max */
+#define MAXXNEST 256          /* initial exp. eval. stack depth - grows */
+#define MAXFCNEST 256         /* initial fcall eval stack depth - grows */
+#define XNESTFIXINC 0x4096    /* increase xpr stack by this */
+#define IDCHARS 4090          /* max. ID length (need 7 for unique) */   
+#define IDLEN 4097            /* size of string to hold ID */
+#define RECLEN 4097           /* length for normal temp string (plus \0) */
+#define MSGTRUNCLEN 1265      /* for msg len. to trunc to (... end) - id fit */
+#define TRTRUNCLEN 66         /* for tracing truncate length (short) */
+#define MAXFILS 500           /* start number of in and lib. files (grows) */
+#define MAXFILNEST 1024       /* max. num. of `include macro nestings */
+#define MAXLEVELS 800         /* max. num. nested param/task/block decls */
+#define MAXGLBCOMPS 800       /* max. components in global name */
+#define MAXLBEXTS 512         /* max. no. of -y library extensions */
+#define MAXINCDIRS 2048       /* max. no. of +incidr search paths files */
+#define MAXNOOPTMODS 2048     /* max. no of +optimize_off module names */
+#define MAXUPRTS 11           /* max. no. of udp ports */
+#define UALTREPIPNUM 7        /* lowest port number to use slower udp rep */
+#define TWHINITSIZE 4000      /* size of fixed timing wheel */
+#define MAXVERIUSERTFS 4095   /* maximum number of pli veriusertfs tfs */
+#define SYSTFDATSIZE 256      /* starting size of vpi_ systf table (grows) */
+#define BASE_VERIUSERTFS 1000 /* base for pli (veriuser) system tf_s */
+#define MAXITDPTH 800         /* dpth of itstk */
+#define MAXCIRDPTH 4096       /* maximum depth of a circuit */ 
+#define IAHISTSIZ 256         /* start history list line and command size */
+#define INFLOOP_MAX 1000      /* stages with time move for loop checking */
+#define DFLT_SNAP_EVS 5       /* default number futuren events to print */
+#define GDVAL 0x400           /* good value */
+#define BDVAL 1000            /* bad value */
+#define TOPVPIVAL 1023        /* biggest vpi define const value (MUST EXTND) */
+#define PVH_MAGIC 0x625       /* 11 bit vpi handle magic number */
+
+#define MAXPRPSTNEST 800      /* maximum statement nesting */
+#define MAXBTDPTH 40          /* maximum depth of timing q (3**40)/2 or so */
+#define BTREEMAXWID 8         /* max. b tree node width (usually .5 full) */
+
+#define BIG_ALLOC_SIZE 0x3ff8 /* size of block to allocate at once */
+#define VPI_OBJALLOCNUM 2048  /* number of vpi object to allocate at once */
+#define RDBUFSIZ 0x4000       /* source list buffer size */
+#define DVBUFSIZ 0x10000      /* 256k buffer for dumpvars output */
+#define MAX_ERRORS 32         /* error limit in one run */
+#define MAXEMSGNUM 4000       /* highest possible any type error num */
+
+#define MY_FOPEN_MAX 1024     /* guess at OS process max open stdio.h wrong */
+
+typedef unsigned long word32;
+typedef long sword32;
+typedef int int32;
+typedef unsigned long long word64;
+typedef long long sword64;
+typedef unsigned char byte;
+typedef unsigned short hword;
+typedef short hsword;
+typedef int32 i_tev_ndx;
+/* needed to allow signals to use normal decls */
+typedef int32 sighandler();
+
+#ifndef __sparc
+/* BEWARE - assuming all non sparc systems define BYTE_ORDER and endian.h */
+/* to PORT change for your system */ 
+# ifdef __APPLE__
+#  include <sys/types.h>
+# else
+#  ifdef __CYGWIN32__
+#   include <sys/param.h>
+#  else
+#   ifdef __FreeBSD__
+#    include <sys/endian.h>
+#   else
+#    include <endian.h>
+#   endif
+#  endif
+# endif
+
+typedef union {
+ word64 w64v; 
+#if (BYTE_ORDER == BIG_ENDIAN)
+ struct { word32 high; word32 low; } w_u;
+#else
+ struct { word32 low; word32 high; } w_u;
+#endif
+} w64_u;
+#else
+#include <sys/isa_defs.h>
+
+typedef union {
+ word64 w64v; 
+#if defined(_BIG_ENDIAN)
+ struct { word32 high; word32 low; } w_u;
+#else
+ struct { word32 low; word32 high; } w_u;
+#endif
+} w64_u;
+#endif
+
+#define TRUE 1
+#define FALSE 0
+#define WBITS 32
+#define LWBITS 64
+#define WRDBYTES 4
+#define MAXWSWRDS ((MAXEMSGNUM + WBITS)/WBITS)
+#define TIMEBITS 64
+#define WORDMASK_ULL 0xffffffffULL
+#define ALL1W 0xffffffff
+#define ALL1HW 0xffff
+#define SHORTBASE (1 << (WBITS/2))
+
+/* these values are IEEE */
+#define REALBITS 32           /* 64 bit double - but no no b part */
+#define LG2_DIV_LG10 0.3010299956639812
+#define EPSILON 2.2204460492503131E-16  /* float.h dbl == diff. amount */
+#define _DEXPLEN 11           /* double exp. len (not incl. sign) */
+
+/* number base constants */
+#define BHEX 0
+#define BBIN 1
+#define BOCT 2
+#define BDEC 3
+#define BDBLE 4               /* special base for printing */
+#define BNONE 5               /* indicator for no base override */
+/* debugger only bases */
+#define BCHAR 6               /* force treatment as char */
+#define BSTR 7                /* froce treatment as string */
+
+/* net representation forms */
+#define NX_CT 0
+#define NX_ARR 1
+#define NX_DWIR 2
+#define NX_WIR 3
+#define NX_SCALWIR 4          /* for scalar empty range field */
+
+/* net storage representation forms */
+#define SR_VEC 0
+#define SR_SVEC 1
+#define SR_SCAL 2
+#define SR_SSCAL 3
+#define SR_ARRAY 4
+#define SR_PVEC 5             /* now only used for gates */
+#define SR_PXPR 6             /* for parameter src. normal rhs expr */ 
+#define SR_PISXPR 7           /* for # and defparams, per inst. array of x */
+#define SR_PNUM 8             /* after fix up simple parameter const. */
+#define SR_PISNUM 9           /* after fix up IS parameter const. */
+
+
+/* strength types */
+#define LOW_STREN 1
+#define HIGH_STREN 2
+#define CAP_STREN 3
+
+/* strength values - must fit in 3 bits */
+/* notice semantics requires this exact strength assignment for 0 to 7 */
+#define ST_HIGHZ 0
+#define ST_SMALL 1
+#define ST_MEDIUM 2
+#define ST_WEAK 3
+#define ST_LARGE 4
+#define ST_PULL 5
+#define ST_STRONG 6
+#define ST_SUPPLY 7
+
+/* capacitor sizes */
+#define CAP_NONE 0
+#define CAP_SMALL 1 
+#define CAP_MED 2
+#define CAP_LARGE 3
+
+/* 6 bit stren only constants */
+#define NO_STREN 8            /* never a strength - indicator only */
+#define ST_STRVAL 0x36        /* (strong0,strong1) 110110 */
+
+/* strength and value constants */
+#define ST_STRONGX ((ST_STRVAL << 2) | 3)
+#define ST_HIZ 0x02           /* <hiZ:hiZ>=z - 00000010 */
+#define ST_PULL0 0xb4         /* <Pu:Pu>=0 - 10110100 */
+#define ST_PULL1 0xb5         /* <Pu:Pu>=1 - 10110101 */
+#define ST_SUPPLY0 0xfc       /* <Su:Su>=0 - 11111100 */ 
+#define ST_SUPPLY1 0xfd       /* <Su:Su>=1 - 11111101 */ 
+
+/* udp types */
+#define U_COMB 0
+#define U_LEVEL 1
+#define U_EDGE 2
+#define NO_VAL 0x7f           /* misc. empty for byte no edge, no val etc. */
+
+/* udp edge values (? and b legal in edges) */
+#define UV_0 0
+#define UV_1 1
+#define UV_X 3
+#define UV_Q 4
+#define UV_B 5
+
+/* net pin connection types */
+#define NP_GATE 0
+#define NP_CONTA 1            /* connects to lhs or rhs of cont. assign */
+#define NP_PB_ICONN 2         /* per bit form of iconn type - now ld/drv */
+#define NP_ICONN 3            /* for load down assign, driver to up iconn */
+#define NP_PB_MDPRT 4         /* per bit mdprt form both drv/ld now */
+#define NP_MDPRT 5            /* for drvr down port assgn, load up to iconn */
+/* notice last of in src npps must be mdprt */
+#define NP_MIPD_NCHG 6        /* for MIPD/interconnect, conn net(s) nchg */
+#define NP_TCHG 7             /* specify time chg record subtyp determines */
+#define NP_TRANIF 8           /* third tranif port enable is normal rhs */
+#define NP_PULL 9             /* constant strength pullup or pulldown drv. */
+/* PLI only not seen by vpi_ routines */
+#define NP_TFRWARG 10         /* driver is tf_ task/func is_rw driver */
+#define NP_VPIPUTV 11         /* driver is vpi_ put value wire driver */
+/* removed from net drvs after tran channels built - drivers only */
+#define NP_TRAN 12            /* driver/load for special tran/tranif gate */ 
+#define NP_BIDICONN 13 
+#define NP_BIDMDPRT 14 
+
+/* port direction change net driver states - pre added np list states */
+#define DRVR_NONE 0           /* net not driven */
+#define DRVR_NON_PORT 1       /* inout port or gate/conta */
+#define DRVR_ICONN 2          /* one up iconn inst conn output driver */ 
+#define DRVR_MDPRT 3          /* one down mod port input driver */ 
+
+/* parmnplst net pin types - disjoint32 from sim time npps */
+#define PNP_GATEDEL 0
+#define PNP_CONTADEL 1
+#define PNP_NETDEL 2
+#define PNP_PROCDCTRL 3
+#define PNP_PATHDEL 4
+#define PNP_TCHKP1 5
+#define PNP_TCHKP2 6
+
+/* change record subtypes */
+#define NPCHG_NONE 0
+#define NPCHG_TCSTART 1
+#define NPCHG_TCCHK 2
+#define NPCHG_PTHSRC 3
+
+/* kinds of net pin global processing - npgru interpretation */
+#define XNP_LOC 0
+#define XNP_DOWNXMR 1
+#define XNP_RTXMR 2
+#define XNP_UPXMR 3
+
+/* kinds of net pin processing */
+#define NP_PROC_INMOD 0
+#define NP_PROC_GREF 1
+#define NP_PROC_FILT 2
+
+/* left hand expression types */
+#define LHS_DECL 1
+#define LHS_PROC 2
+
+/* tokens types - must < 255 */
+#define TOK_NONE 0
+#define ID 1
+#define BADOBJ 2
+#define NUMBER 3
+#define ISNUMBER 4            /* array of constants - cur_itp selects */
+#define REALNUM 5
+#define ISREALNUM 6
+#define LITSTR 7              /* token returned for literal str by scanner */
+#define OPEMPTY 8             /* unc. expr place holder in expr. list */ 
+#define UNCONNPULL 9          /* unc. inst. input port `unconndrive val. */
+#define RMADDR 10             /* special readmem address token */
+
+/* punctuation */
+#define SEMI 12
+#define COMMA 13
+#define COLON 14
+#define SHARP 15
+#define LPAR 16
+#define RPAR 17
+#define LSB 18                /* [ (also bit select operator) */
+#define RSB 19
+#define LCB 20                /* { */
+#define RCB 21
+#define DOT 22
+#define AT 23
+
+/* special unary */
+#define CAUSE 24              /* -> not an expression operator */
+#define EQ 25                 /* = (assignment but not an expr. lang.) */
+
+/* unary only operators - real 0.0 is F for logical */
+#define BITNOT 26             /* ~ */
+#define NOT 27                /* ! (logical) */
+/* real unary only (0.0 if F else T) */
+#define REALNOT 28 
+
+/* both unary and binary */
+#define REDXNOR 29            /* must ^~ - ~^ is 2 unaries */
+#define PLUS 30               /* + */
+#define MINUS 31              /* - */
+#define BITREDAND 32          /* bin & (bit) - un red. and */
+#define BITREDOR 33           /* bin | (bit) - un red. or */
+#define BITREDXOR 34          /* bin ^ (bit) - un red. xor */
+/* both real - notice type must be in operator */
+/* notice this should have at 5? number */
+#define REALMINUS 35
+
+/* binary operators */
+#define TIMES 36              /* * */
+#define DIV 37                /* / */
+#define MOD 38                /* % */
+#define RELGE 39              /* >= */
+#define RELGT 40              /* > */
+#define RELLE 41              /* <= (also non block cont. assign token) */
+#define RELLT 42              /* < */
+#define RELCEQ 43             /* === */
+#define RELEQ 44              /* == */
+#define RELCNEQ 45            /* !== */
+#define RELNEQ 46             /* != */
+#define BOOLAND 47            /* && */
+#define BOOLOR 48             /* || */
+#define SHIFTL 49             /* << */
+#define ASHIFTL 50            /* <<< - differenet operator but same as << */
+#define SHIFTR 51             /* >> */
+#define ASHIFTR 52            /* >>> */
+#define FPTHCON 53            /* *> (full path conn spfy. op.) */
+#define PPTHCON 54            /* => (parallel path conn spfy. op.) */
+#define TCHKEVAND 55          /* &&& (timing check conditional event op.) */
+/* real binary */
+#define REALPLUS 56
+#define REALTIMES 57
+#define REALDIV 58
+#define REALRELGT 59
+#define REALRELGE 60
+#define REALRELLT 61
+#define REALRELLE 62
+#define REALRELEQ 63
+#define REALRELNEQ 64
+#define REALBOOLAND 65
+#define REALBOOLOR 66
+/* notice logical non bit-wise and non-reduction 0.0 is F */
+
+/* special ops */
+/* special expression operators that do not correspond to read tokens */
+#define QUEST 67              /* binary ? part of ?: */
+#define QCOL 68               /* : part of ?: */
+#define PARTSEL 69            /* part select [ */
+#define CATCOM 70             /* concatenate comma (really list indicator) */
+#define CATREP 71             /* concatenate repeat form */
+#define FCALL 72              /* function call */
+#define FCCOM 73              /* func/task call , (really list indicator) */
+#define OPEVOR 74             /* event control or */
+#define OPEVCOMMAOR 75        /* alternative to event ctrl or - sims same */
+#define OPPOSEDGE 76          /* posedge in delay ctrl expr. */
+#define OPNEGEDGE 77          /* negedge in delay ctrl expr. */
+/* real specials */
+#define REALREALQUEST 78      /* binary ?  part of ?: - all reals */ 
+#define REALREGQUEST 79       /* bin ? part of ?: - real cond : part reg */ 
+#define REGREALQCOL 80        /* binary : part of ?: - normal cond : real */
+
+/* global expression componnents */ 
+#define GLBREF 81             /* this is sort of ID and sort of expr. */    
+#define GLBPTH 82             /* this is global path as XMRID expr (list) */
+#define XMRID 83              /* ID node that is part of xmr (no sy) */
+#define XMRCOM 84
+
+/* special indicators */
+#define UNDEF 85              /* toktyp for no pushed back token */
+#define TEOF 86
+
+/* notice unused token no. gap here for addition operators ? */
+
+/* these can all appear outside modules - some can appear inside */
+/* back quote is ascii 96 (0x60) just before lower case (after upper case) */
+#define CDIR_ACCEL 100
+#define CDIR_AEXPVECNETS 101
+#define CDIR_CELLDEF 102
+#define CDIR_DEFINE 103
+#define CDIR_DFLNTYP 104
+#define CDIR_ECELLDEF 105
+#define CDIR_ELSE 106
+#define CDIR_ENDIF 107
+#define CDIR_ENDPROTECT 108
+#define CDIR_ENDPROTECTED 109
+#define CDIR_XPNDVNETS 110
+#define CDIR_IFDEF 111
+#define CDIR_IFNDEF 112
+#define CDIR_INCLUDE 113
+#define CDIR_NOACCEL 114
+#define CDIR_NOXPNDVNETS 115
+#define CDIR_NOREMGATENAMES 116
+#define CDIR_NOREMNETNAMES 117
+#define CDIR_NOUNCONNDRIVE 118
+#define CDIR_PROTECT 119
+#define CDIR_PROTECTED 120
+#define CDIR_REMGATESNAMES 121
+#define CDIR_REMNETNAMES 122
+#define CDIR_RESETALL 123
+#define CDIR_TIMESCALE 124
+#define CDIR_UNCONNDRIVE 125
+#define CDIR_UNDEF 126
+#define CDIR_DFLTDECAYTIME 127
+#define CDIR_DFLTTRIREGSTREN 128
+#define CDIR_DELMODEDIST 129
+#define CDIR_DELMODEPATH 130
+#define CDIR_DELMODEUNIT 131
+#define CDIR_LANG 132 
+#define CDIR_DELMODEZERO 134
+
+#define CDIR_TOKEN_START CDIR_ACCEL
+#define CDIR_TOKEN_END CDIR_DELMODEZERO
+
+/* notice 19 unused token no. gap here ? */
+#define ALWAYS 140
+#define ASSIGN 141
+#define Begin 142
+#define CASE 143
+#define CASEX 144
+#define CASEZ 145
+#define DEASSIGN 146
+#define DEFAULT 147
+#define DEFPARAM 148
+#define DISABLE 149
+#define EDGE 150
+#define ELSE 151
+#define END 152
+#define ENDCASE 153
+#define ENDFUNCTION 154
+#define ENDGENERATE 155
+#define ENDMODULE 156
+#define ENDPRIMITIVE 157
+#define ENDSPECIFY 158
+#define ENDTABLE 159
+#define ENDTASK 160
+#define EVENT 161
+#define FOR 162
+#define FORCE 163
+#define FOREVER 164
+#define FORK 165
+#define FUNCTION 166
+#define GENERATE 167
+#define HIGHZ0 168
+#define HIGHZ1 169
+#define IF 170
+#define IFNONE 171
+#define INITial 172
+#define INOUT 173
+#define INPUT 174
+#define INTEGER 175
+#define JOIN 176
+#define LARGE 177
+#define MACROMODULE 178
+#define MEDIUM 179
+#define MODULE 180
+#define NEGEDGE 181
+#define OUTPUT 182
+#define PARAMETER 183
+#define POSEDGE 184
+#define PRIMITIVE 185
+#define PULL0 186
+#define PULL1 187
+#define REAL 188
+#define REALTIME 189
+#define REG 190
+#define RELEASE 191
+#define REPEAT 192
+#define SCALARED 193
+#define SIGNED 194
+#define SPECIFY 195
+#define SPECPARAM 196
+#define SMALL 197
+#define Strength 198
+#define STRONG0 199
+#define STRONG1 200
+#define SUPPLY0 201
+#define SUPPLY1 202
+#define TABLE 203
+#define TASK 204
+#define TIME 205
+#define TRI 206
+#define TRI0 207
+#define TRI1 208
+#define TRIAND 209
+#define TRIOR 210
+#define TRIREG 211
+#define VECTORED 212
+#define WAIT 213
+#define WAND 214
+#define WEAK0 215
+#define WEAK1 216
+#define WHILE 217
+#define WIRE 218
+#define WOR 219
+
+/* gate nums (not tokens) for sim - now separate gatid range */
+/* now for debugging do not use low numbers */
+#define G_ASSIGN 10 
+#define G_BITREDAND 11
+#define G_BUF 12
+#define G_BUFIF0 13
+#define G_BUFIF1 14
+#define G_CMOS 15
+#define G_NAND 16
+#define G_NMOS 17
+#define G_NOR 18
+#define G_NOT 19
+#define G_NOTIF0 20
+#define G_NOTIF1 21
+#define G_BITREDOR 22
+#define G_PMOS 23
+#define G_PULLDOWN 24
+#define G_PULLUP 25
+#define G_RCMOS 26
+#define G_RNMOS 27
+#define G_RPMOS 28
+#define G_RTRAN 29
+#define G_RTRANIF0 30
+#define G_RTRANIF1 31
+#define G_TRAN 32
+#define G_TRANIF0 33
+#define G_TRANIF1 34
+#define G_BITREDXOR 35
+#define G_REDXNOR 36
+
+#define LAST_GSYM G_REDXNOR
+
+/* gate classes */ 
+#define GC_LOGIC 0
+#define GC_BUFIF 1
+#define GC_MOS 2
+#define GC_CMOS 3
+#define GC_TRAN 4
+#define GC_TRANIF 5
+#define GC_UDP 6
+#define GC_PULL 7
+
+/* region separation constants */
+#define FIRSTKEY CDIR_ACCEL
+#define BKEYS FIRSTKEY
+/* this is last real op. part select's etc. come after */
+#define LASTOP TEOF
+
+/* unconnected pull directive OPEMPTY values */
+#define NO_UNCPULL 0
+#define UNCPULL0 1
+#define UNCPULL1 2
+
+/* net types (ntyp field) - meaningful when iotyp is NON_IO */
+#define N_WIRE 0
+#define N_TRI 1
+#define N_TRI0 2
+#define N_TRI1 3
+#define N_TRIAND 4
+#define N_TRIOR 5
+#define N_TRIREG 6
+#define N_WA 7
+#define N_WO 8
+#define N_SUPPLY0 9
+#define N_SUPPLY1 10
+#define N_REG 11
+#define N_INT 12
+#define N_TIME 13
+#define N_REAL 14
+#define N_EVENT 15            /* needs to be event so -d decls in order */
+
+/* beware - number ranges used so all reg types must come after all wires */ 
+#define NONWIRE_ST N_REG
+
+/* the i/o net and port types - separate from net type */
+#define IO_IN 0
+#define IO_OUT 1
+#define IO_BID 2
+#define IO_UNKN 3
+#define NON_IO 4
+
+/* sync to location classes */
+#define SYNC_FLEVEL 0
+#define SYNC_MODLEVEL 1
+#define SYNC_STMT 2
+#define SYNC_SPECITEM 3
+#define SYNC_UDPLEVEL 4
+#define SYNC_TARG 5
+
+/* scalared/vectored splitting states */
+#define SPLT_DFLT 0
+#define SPLT_SCAL 1
+#define SPLT_VECT 2
+
+/* min/typ/max delay selection values */
+#define DEL_MIN 1
+#define DEL_TYP 2
+#define DEL_MAX 3
+
+/* symbol types - determines net list element */
+/* front end only symbols */
+#define SYM_UNKN 0
+#define SYM_M 1               /* module type name (not in pli) */
+#define SYM_STSK 2            /* built in system task name */
+#define SYM_SF 3              /* built in system function name */
+#define SYM_DEF 4             /* preprocessor `define sym, separate table */
+
+/* in module (real pli) objects */
+#define SYM_I 5               /* inst. name in module */
+#define SYM_TSK 6             /* task name */
+#define SYM_F 7               /* function name */
+#define SYM_LB 8              /* labeled block */
+#define SYM_PRIM 9            /* built in primitive */
+#define SYM_UDP 10            /* udp definition name */
+#define SYM_N 11              /* wire, regs, events and I/O ports (nets) */
+#define SYM_CA 12             /* symbol for conta */
+#define SYM_TCHK 13           /* symbol for time check */
+#define SYM_PTH 14            /* symbol for delay path */
+
+/* pli only object (handle) types - no front end symbol */
+#define SYM_IMPATH 19         /* inter module (inst.) path not in ovi ? */
+#define SYM_MPATH 20          /* any intra module path */
+#define SYM_PRIMPATH 21       /* path between primitives - not in ovi ? */
+#define SYM_WIREPATH 22       /* another kind of non ovi path ? */
+#define SYM_TERM 23           /* primitive terminal dummy */
+#define SYM_MPTERM 24         /* terminal of mod path - only acc handle */
+#define SYM_PORT 25           /* module port dummy */
+#define SYM_BIT 26            /* bit of expanded net dummy */
+#define SYM_PBIT 27           /* bit of expanded port dummy */
+
+/* tree balance constants */
+#define BLEFT 0
+#define BEVEN 1
+#define BRIGHT 2
+
+/* btree (timing queue) constants */
+#define BTNORM 0
+#define BTFRNGE 1
+
+/* statement types */
+#define S_NULL 0              /* ; by itself */
+#define S_PROCA 1
+#define S_NBPROCA 2
+#define S_RHSDEPROCA 3
+#define S_IF 4
+#define S_CASE 5
+#define S_FOR 6
+#define S_FOREVER 7
+#define S_REPEAT 8
+#define S_WHILE 9             /* execept forever only sim time loop */
+#define S_WAIT 10
+#define S_DELCTRL 11
+#define S_NAMBLK 12
+#define S_UNBLK 13
+#define S_UNFJ 14             /* this is for unnamed block fork-join only */
+#define S_TSKCALL 15
+#define S_QCONTA 16
+#define S_QCONTDEA 17
+#define S_CAUSE 18            /* CAUSE (->) <event> */
+#define S_DSABLE 19           /* disable <task or block> */
+#define S_STNONE 20           /* thing inside empty block */
+/* special invisible simulation control statements */
+#define S_REPSETUP 21         /* set up repeat count - st_u empty */
+#define S_REPDCSETUP 22       /* event repeat form dctrl setup */ 
+#define S_GOTO 23             /* goto statement for loops */
+#define S_FORASSGN 24         /* special added (before) for assign */
+#define S_BRKPT 25            /* for setting break point at statement */
+
+
+/* system function types */
+#define SYSF_UNKNOWN 0
+#define SYSF_BUILTIN 1
+#define SYSF_TF 2
+#define SYSF_VPI 3
+
+/* break point types */
+#define BP_UNKN 0
+#define BP_INST 1 
+#define BP_TYPE 2
+
+/* interactive entry reasons */
+#define IAER_UNKN 0
+#define IAER_BRKPT 1
+#define IAER_STEP 2
+#define IAER_STOP 3
+#define IAER_CTRLC 4
+
+/* event control types */
+#define DC_NONE 0
+#define DC_EVENT 1
+#define DC_DELAY 2
+#define DC_RHSEVENT 3
+#define DC_RHSDELAY 4
+#define DC_WAITEVENT 5
+
+/* statement dump new line control constants */
+#define NONL 1
+#define NL 2
+
+/* Verilog operator types */
+#define NOTANOP 0
+#define UNOP 1
+#define BINOP 2
+#define BOTHOP 3
+#define SPECOP 4
+#define RUNOP 5
+#define RBINOP 6
+#define RBOTHOP 7
+
+/* indicator if operand legal for reals */
+#define REALOP TRUE
+#define NOTREALOP FALSE
+#define PTHOP TRUE
+#define NOTPTHOP FALSE
+
+/* operater width result pattern */
+#define WIDNONE 0             /* no width result */
+#define WIDONE 1              /* result width 1 (for logicals) */
+#define WIDENONE 2            /* result one, but widen opands to wides */
+#define WIDLEFT 3             /* left operand width of binary */
+#define WIDMAX 4              /* max. of 2 operands */
+#define WIDSUM 5              /* sum of operand width for concats */
+#define WIDSELF 6             /* width self determining (like [] or un ~/-) */
+
+/* specify section constants */
+#define PTH_PAR 0             /* => */
+#define PTH_FULL 1            /* *> */
+#define PTH_NONE 2
+
+#define POLAR_NONE 0
+#define POLAR_PLUS 1
+#define POLAR_MINUS 2
+
+#define TCHK_SETUP 0
+#define TCHK_HOLD 1
+#define TCHK_WIDTH 2
+#define TCHK_PERIOD 3
+#define TCHK_SKEW 4
+#define TCHK_RECOVERY 5
+#define TCHK_NOCHANGE 6
+#define TCHK_SETUPHOLD 7
+#define TCHK_FULLSKEW 8
+#define TCHK_RECREM 9
+#define TCHK_REMOVAL 10
+#define TCHK_TIMESKEW 11
+
+/* for [edge ...] form allows list so multiple bits possible */
+/* values must match acc_ pli values */
+#define NOEDGE 0
+#define EDGE01 0x1
+#define EDGE10 0x2
+#define EDGE0X 0x4
+#define EDGEX1 0x8
+#define EDGE1X 0x10
+#define EDGEX0 0x20
+/* these are or of relevants */
+#define E_POSEDGE 0xd
+#define E_NEGEDGE 0x32
+
+/* delay union form for all delays after simulation preparation */
+/* notice for non IS form no byte and halfword packed forms */
+#define DT_NONE 0
+#define DT_1V 1
+#define DT_IS1V  2            /* all is forms have 1,2 and 8 byte forms */
+#define DT_IS1V1 3
+#define DT_IS1V2 4
+#define DT_4V 5               /* 4v forms only for primtives not paths */ 
+#define DT_IS4V 6
+#define DT_IS4V1 7
+#define DT_IS4V2 8
+#define DT_16V 9              /* except for 1v all spec. delays need 15v */
+#define DT_IS16V 10
+#define DT_IS16V1 11
+#define DT_IS16V2 12
+#define DT_1X 13
+#define DT_4X 14
+#define DT_PTHDST 15
+#define DT_CMPLST 16
+
+/* for checking 0 and path delays, kinds of bad delays */
+#define DGOOD 1
+#define DBAD_NONE 2
+#define DBAD_EXPR 3
+#define DBAD_0 4
+#define DBAD_MAYBE0 5
+
+/* timing event types - what tested by not starting at 0 ? */
+#define TE_THRD 2
+#define TE_G 3
+#define TE_CA 4
+#define TE_WIRE 5
+#define TE_BIDPATH 6
+#define TE_MIPD_NCHG 7
+#define TE_NBPA 8
+#define TE_TFSETDEL 9
+#define TE_SYNC 10
+#define TE_TFPUTPDEL 11
+#define TE_VPIPUTVDEL 12
+#define TE_VPIDRVDEL 13
+#define TE_VPICBDEL 14
+#define TE_UNKN 15
+
+#define DFLT_LOGFNAM "verilog.log"
+#define DFLTDVFNAM "verilog.dump"
+#define DFLTKEYFNAM "verilog.key"
+
+/* dumpvars action state */
+#define DVST_NOTSETUP 0
+#define DVST_DUMPING 1
+#define DVST_NOTDUMPING 2
+#define DVST_OVERLIMIT 3
+
+/* baseline dump types for dumpvars */
+#define DMPV_CHGONLY 0
+#define DMPV_DMPALL 1
+#define DMPV_DUMPX 2
+
+/* delay control event filter processing types */
+#define DCE_RNG_INST 0
+#define DCE_INST 1
+#define DCE_RNG_MONIT 2
+#define DCE_MONIT 3
+#define DCE_NONE 4
+#define DCE_QCAF 5
+#define DCE_RNG_QCAF 6
+#define DCE_CBF 7
+#define DCE_RNG_CBF 8
+#define DCE_CBR 9
+#define DCE_RNG_CBR 10
+/* BEWARE these always require prevval - must be higher number than above */
+#define DCE_PVC 11
+#define DCE_RNG_PVC 12
+#define DCE_CBVC 13
+#define DCE_RNG_CBVC 14
+
+#define ST_ND_PREVVAL DCE_PVC
+
+/* slotend action masks - multiple can be on at time */
+#define SE_TCHK_VIOLATION 1
+#define SE_MONIT_CHG 0x2      /* definite chg including first time */
+#define SE_MONIT_TRIGGER 0x4  /* monit chg where val saved (chk at end) */
+/* FIXME - why is this never referenced */ 
+#define SE_FMONIT_TRIGGER 0x8
+#define SE_STROBE 0x10
+#define SE_DUMPVARS 0x20      /* ON => some dumpvars action required */ 
+#define SE_DUMPALL 0x40       /* need slot end dump all */
+#define SE_DUMPON  0x800      /* need to turn dumping on at slot end */
+#define SE_DUMPOFF 0x100      /* need to turn dumping off at slot end */
+#define SE_TFROSYNC 0x200     /* have list of rosync events to process */
+#define SE_VPIROSYNC 0x400    /* have list of vpi rw sync to process */
+
+/* selectors for type of tran channel routine to use (low 3 bits) */ 
+#define TRPROC_UNKN 0
+#define TRPROC_BID 1
+#define TRPROC_STBID 2
+#define TRPROC_STWTYPBID 3
+#define TRPROC_TRAN 4
+
+/* type of gate acceleration - for selecting routine */
+#define ACC_NONE 0
+#define ACC_STD 1
+#define ACC_BUFNOT 2
+#define ACC_STIBUFNOT 3
+#define ACC_4IGATE 4
+#define ACC_ST4IGATE 5
+
+/* internal vpi_ call back type classes */
+#define CB_NONE 0
+#define CB_VALCHG 1 
+#define CB_DELAY 2
+#define CB_ACTION 3
+
+/* simulation (run) progress states */
+#define SS_COMP 1
+#define SS_LOAD 2
+#define SS_RESET 3
+#define SS_SIM 4
+
+/* Cver supported error severity levels */
+#define INFORM 0
+#define WARN 1
+#define ERROR 2
+#define FATAL 3
+
+/* per inst. masks for net nchg action byte array */
+#define NCHG_DMPVARNOW 0x1    /* dumpvaring of this var inst on/off */
+#define NCHG_DMPVNOTCHGED 0x2 /* var inst. not chged during current time */
+#define NCHG_DMPVARED 0x4     /* var inst. dumpvared (setup) */
+#define NCHG_ALL_CHGED 0x08   /* all var inst. bits chged (also if no lds) */
+
+/* AIV 09/05/03 consts for new fileio OS file descriptor streams support */
+#define FIO_MSB 0x80000000
+#define FIO_FD 0x7fffffff
+#define FIO_STREAM_ST 3       /* first usable ver fio fd open file number */
+#define SE_VPIROSYNC 0x400    /* have list of vpi rw sync to process */
+
+/* AIV 12/02/03 constants for cfg get token */
+/* FIXME ??? - needed here because cfg get tok in v ms but used in cver? */
+#define CFG_UNKNOWN 0
+#define CFG_ID 1
+#define CFG_COMMA 2
+#define CFG_SEMI 3
+#define CFG_EOF 4
+#define CFG_LIBRARY 5
+#define CFG_CFG 6
+#define CFG_INCLUDE 7
+#define CFG_DESIGN 8
+#define CFG_LIBLIST 9
+#define CFG_INSTANCE 10
+#define CFG_CELL 11
+#define CFG_USE 12
+#define CFG_ENDCFG 13
+#define CFG_DEFAULT 14
+
+/* SJM 07/31/01 - need system type def. include files for 64 bit types */
+#include <time.h>
+
+/* various forward references */
+struct sy_t;
+struct st_t;
+struct mod_pin_t;
+struct thread_t;
+struct tchk_t;
+struct tchg_t;
+struct fmonlst_t;
+
+/* data structure for keywords and command line/file options */
+struct namlst_t {
+ int32 namid;
+ char *lnam;
+};
+
+/* SJM 06/03/01 - to prepare for 64 bits union to avoid int32 to ptr cast */
+/* SJM 10/12/04 - can't use p because need index into contab not addr */
+union intptr_u {
+ int32 i;
+ int32 xvi;
+};
+
+/* SJM 08/22/01 - must be at top for new expr node union */
+union pck_u {
+ word32 *wp;
+ hword *hwp;
+ byte *bp;
+ double *dp;
+};
+
+/* data struct for help message line tables - hnum is namlst_t namid */
+struct hlplst_t {
+ /* LOOKATME - why is this unused */
+ int32 hnamid;
+ char **hmsgtab;
+};
+
+struct sdfnamlst_t { 
+ char *fnam;
+ char *scopnam;
+ char *optfnam;
+ int32 opt_slcnt;
+ struct sdfnamlst_t *sdfnamnxt;
+};
+
+struct optlst_t {
+ unsigned optfnam_ind : 16;
+ unsigned is_bmark : 1;       /* special -f markers for vpi_ */         
+ unsigned is_emark : 1;
+ unsigned is_argv : 1;
+ unsigned argv_done : 1;
+ int32 optlin_cnt;
+ int32 optnum;
+ int32 optlev;
+ char *opt;
+ char **dargv;
+ struct optlst_t *optlnxt;
+};
+
+/* data structure for input file/`define/`include stack */
+/* could be union but not too many ? */
+struct vinstk_t {
+ int32 vilin_cnt;
+ word32 vifnam_ind;
+ FILE *vi_s;
+ char *vichp_beg;             /* beginning of macro string */  
+ int32 vichplen;              /* if not -1, len + 1 must be freed */
+ char *vichp;                 /* macro string current char */
+};
+
+/* P1364 2001 cfg include structs */
+/* list of map files - uses map.lib in CWD if none from options */
+struct mapfiles_t {
+ char *mapfnam;
+ struct mapfiles_t *mapfnxt;
+};
+
+/* order list of config element names */
+struct cfgnamlst_t {
+ char *nam;
+ struct cfgnamlst_t *cnlnxt;
+};
+
+/* describes component of path during wild card expansion */
+struct xpndfile_t {
+ char *fpat;                  /* the original pattern per dir, split by '/' */
+ int32 nmatch;                /* the number of matched files */
+ int32 level;                 /* current directory level */
+ unsigned wildcard: 2;        /* T=> if it contains a wild char, *, ? or ... */
+ unsigned incall : 1;         /* include the entire dir, ends in '/' */
+ struct xpndfile_t *xpfnxt;   /* next part of original pattern */
+};
+
+/* record for library element (after expand, all wild cards removed) */
+struct libel_t {
+ unsigned lbelsrc_rd : 1;     /* T => expanded lib file name src all read */
+ unsigned expanded : 1;       /* T => file has been expanded  */ 
+ char *lbefnam; 
+ struct libcellndx_t **lbcelndx; /* byte offset of cell names for seeking */
+ struct symtab_t *lbel_sytab; /* symbol table of cells in file */
+ struct libel_t *lbenxt;
+};
+
+/* cfg library record - sort of corresponds to -v/y data record */ 
+struct cfglib_t {
+ unsigned lbsrc_rd : 1;       /* T => lib src files already read */
+ unsigned sym_added : 1;      /* T => sym table has been read */
+ char *lbname;                /* library name */ 
+ struct libel_t *lbels;       /* list of library file path spec elements */
+ struct cfglib_t *lbnxt;      /* pointer to the next library */
+ char *cfglb_fnam;            /* location of library in src needed */
+ int32 cfglb_lno;
+ struct cfg_t *cfgnxt;
+};
+
+/* config body rule record */
+struct cfgrule_t {
+ unsigned rultyp : 8;         /* type - cfg symbol number */
+ unsigned use_rule_cfg : 1;   /* T => use clause config form */ 
+ unsigned matched : 1;        /* T => rule was bound at least once */ 
+ unsigned is_use : 1;         /* T => 'use' else 'liblist' */ 
+ char *objnam;                /* inst clause: [XMR inst path] */ 
+ char *libnam;                /* cell clause: <lib name>.[cell name] */
+ char *rul_use_libnam;        /* use <lib name.>[cell name][:config] */
+ char *rul_use_celnam;
+ char **inam_comptab;         /* table of inst clause XMR components */
+ int32 inam_comp_lasti;       /* number of components in XMR inst path */
+
+ struct cfgnamlst_t *rul_libs;/* liblist clause - just list of libraries */
+ int32 rul_lno;
+ struct cfgrule_t *rulnxt;
+};
+
+/* record for list of config design cell identifiers */
+struct cfgdes_t {
+ char *deslbnam;          /* name of config design library */
+ struct cfglib_t *deslbp; /* ptr to config design library */
+ char *topmodnam;         /* name of top level cell (type) */
+ struct cfgdes_t *desnxt;  
+};
+
+/* record for each cfg block */
+struct cfg_t {
+ char *cfgnam;                /* name of the cfg */
+ struct cfgdes_t *cfgdeslist; /* list of config design [lib].[cell]s */
+
+ /* SJM 12/11/03 - notice preserving exact order of rules critical */
+ struct cfgrule_t *cfgrules;  /* ordered list of config rules */
+ struct cfgrule_t *cfgdflt;   /* default lib list if rules find no matches */
+ char *cfg_fnam;
+ int32 cfg_lno;
+ struct cfg_t *cfgnxt;
+};
+
+/* for debugger include file and last included place */
+struct incloc_t {
+ int32 inc_fnind;             /* in_fils index of included file */
+ int32 incfrom_fnind;         /* in_fils index file included from */
+ int32 incfrom_lcnt;          /* lin cnt where included */ 
+ struct incloc_t *inclocnxt;
+};
+
+/* doubly linked list for undefined modules */
+struct undef_t {
+ struct sy_t *msyp;
+ int32 dfi;
+ char *modnam;
+ struct undef_t *undefprev;
+ struct undef_t *undefnxt;
+};
+
+/* struct for files in ylib - to avoid opening if not needed */
+struct mydir_t {
+ unsigned ydirfnam_ind : 16;
+ unsigned ylbxi : 16;         /* ndx in lbexts (-1 if none), -2 no match */
+ char *dirfnam;
+};
+
+/* -y and -v file list */
+struct vylib_t {
+ unsigned vyfnam_ind : 16;    /* for rescanning file ind or num dir files */
+ unsigned vytyp : 8;          /* 'v' for -v andd 'y' for -y */
+ union {
+  char *vyfnam;               /* file name */ 
+  char *vydirpth;             /* for -y directory, directory path */
+ } vyu;
+ struct mydir_t *yfiles;      /* for -y header of file list */
+ struct vylib_t *vynxt;
+};
+
+/* struct for multi-channel descriptors - need to save file name */ 
+struct mcchan_t { 
+ FILE *mc_s; 
+ char *mc_fnam;
+};
+
+/* ver fd number record for new 2001 P1364 file io package */
+struct fiofd_t {
+ unsigned fd_error : 1;      /* error indicator */
+ char *fd_name;              /* name of stdio file */
+ FILE *fd_s;                 /* corresponding OS FILE * descriptor */ 
+};
+
+/* debugger source file cache line start location rec */
+struct filpos_t {
+ int32 nlines;
+ int32 *lpostab;
+};
+
+/* formal macro argument list */
+struct macarg_t {
+ char *macargnam;
+ struct macarg_t *macargnxt;
+};
+
+/* macro expansion templace list */
+struct macexp_t {
+ char *leading_str;
+ int32 leadlen;
+ int32 ins_argno;
+ struct macexp_t *macexpnxt;
+};
+
+/* arg macro record */ 
+struct amac_t { 
+ int32 num_formal_args;
+ struct macexp_t *amxp;
+};
+
+/* operator info struct for predefined table (index by op. symbol number) */
+/* Verilog ops always associate left */
+struct opinfo_t {
+ unsigned opclass : 8;
+ unsigned realop : 8;
+ unsigned pthexpop: 8;        /* T => op legal in SDPD condional expr. */
+ unsigned reswid : 8;
+ char *opnam;
+};
+
+/* value in q for $q_ system tasks */
+struct q_val_t {
+ int32 job_id;
+ int32 inform_id;
+ word64 enter_tim;
+};
+
+/* q header record - linked list of all queues */
+struct q_hdr_t {
+ unsigned q_fifo : 1;       /* T => fifo, F => lifo */
+ int32 q_id;                /* user passed ID */
+ int32 q_hdr;               /* index of current head */
+ int32 q_tail;              /* index of current tail */
+ int32 q_maxlen;            /* maximum length of queue */
+ int32 q_size;              /* need to store size for q_exam */
+ struct q_val_t *qarr;      /* table contain queue */
+ word64 q_minwait;          /* shortest wait (min) of all els. ever in Q */
+ int32 q_maxsize;           /* for entire run, max size of q */
+ struct q_hdr_t *qhdrnxt; 
+};
+
+/* history suspended statement control record */
+struct hctrl_t {
+ struct st_t *hc_stp;     /* initial style statement list */
+ struct itree_t *hc_itp;  /* itree loc. runs in if reenabled */
+ struct thread_t *hc_thp; /* associated thread */ 
+ int32 hc_lini;           /* line loc. in history of statement */ 
+ int32 hc_ifi; 
+ struct hctrl_t *hc_nxt;  /* list next for non history traversing */
+ struct hctrl_t *hc_prev; /* and previous */
+ struct iahist_t *hc_iahp;/* ptr to history element if history on */
+ struct dceauxlst_t *hc_dcelst; /* aux. list of per inst iact dces to free */ 
+ struct gref_t *hc_grtab; /* table of any grefs used in this statement */ 
+ int32 hc_numglbs;        /* size of table */
+};
+
+/* interactive history command record */
+struct iahist_t { 
+ char *iah_lp;            /* history line (may have embedded new lines) */
+ struct hctrl_t *iah_hcp; /* parsed suspended stmt control record */
+ struct itree_t *iah_itp; /* for non immed. save original itree loc. */
+};
+
+/* parallel to expr table during expr collect id name info struct */  
+struct expridtab_t {
+ char *idnam;
+ int32 idfldwid;
+ int32 idfnam_ind;
+ int32 idlin_cnt;
+};
+
+/* structs for expressions */
+union l_u {
+ struct expr_t *x;
+ int32 xi; /* for compile/save changed to indices */
+ struct sy_t *sy;
+ int32 si; /* for compile/save changed to indices */
+};
+
+union r_u {
+ struct expr_t *x;
+ int32 xvi;                   /* wrd index into constant tab */
+ union pck_u iop_ptr;         /* for special malloc iopt node ptr to area */
+ struct gref_t *grp;          /* during compile/exec - ptr to gref */
+ int32 gri;                   /* for compile/save index */
+ char *qnchp;                 /* for local qual. name, pointer to name */ 
+};
+
+/* expression size or tf rec union */
+union sz_u {
+ int32 xclen;
+ struct tfrec_t *xfrec;
+ void *vpi_sysf_datap;        /* for vpi_ sysf get/put data routine */
+};
+
+/* expression tree storage - eventually will fit in 12 bytes */
+struct expr_t {
+ /* operator token type - leaf node if var or number */
+ unsigned optyp : 8;          /* token type of node */
+ unsigned has_sign : 1;       /* T => result must be signed */
+ unsigned rel_ndssign : 1;    /* T => 1 bit result relational needs sign */
+ unsigned is_string : 1;      /* T => constant in src as string (quoted) */
+ unsigned unsiznum : 1;       /* T => constant is unsized */
+ unsigned ibase : 3;          /* for sized no., base char. */
+ unsigned sizdflt : 1;        /* T => '[base] form but no width */
+ unsigned is_real : 1;        /* T => expr. value is real number */
+ unsigned cnvt_to_real : 1;   /* T => non real operand of real expr */
+ unsigned unsgn_widen : 1;    /* T => for cases unsigned widen if needed */
+ unsigned consubxpr : 1;      /* T => node will evaluate to number */
+ unsigned consub_is : 1;      /* T => node will eval to IS number */
+ unsigned folded : 1;         /* T => const. folded (also empty cat rep rem) */
+ unsigned getpatlhs : 1;      /* T => expressions is lhs of get pattern */
+ unsigned ind_noth0 : 1;      /* T => constant index has been normalized */
+ unsigned x_multfi : 1;       /* T => expr has multi fan-in or stren wire */
+ unsigned tf_isrw : 1;        /* T => for user tf arg. - assignable (rw) */
+ unsigned x_islhs : 1;        /* T => expr. is lhs */
+ unsigned locqualnam : 1;     /* T => if printing name is local qualified */
+ unsigned lhsx_ndel : 1;      /* T => wire in lhs expr. has net delay */
+ unsigned x_stren : 1;        /* T => expr. is strength wire/bs/ps */
+ unsigned unc_pull : 2;       /* unc. pull directive value for OPEMPTY */
+ union sz_u szu;              /* size of func tf rec. union */ 
+ union l_u lu;                /* left sub expr. or symbol union */
+ union r_u ru;                /* right sub expr. or ptr. to value union */
+};
+
+struct xstk_t {
+ int32 xslen;                 /* number of bits required to store */
+ int32 xsawlen;               /* word32 length of a/b half of alloced size */
+ word32 *ap;                  /* a part of value but must be contigous */
+ word32 *bp;                  /* b part of value */
+};
+
+struct exprlst_t {
+ struct expr_t *xp;
+ struct exprlst_t *xpnxt;
+};
+
+/* for new ver 2001 var (not wire) decl initialize assign list */
+struct varinitlst_t {
+ struct sy_t *init_syp;
+ struct expr_t *init_xp;
+ struct varinitlst_t *varinitnxt;
+};
+
+/* struct for storing # delays but not instance pound params */
+struct paramlst_t {
+ struct expr_t *plxndp;
+ struct paramlst_t *pmlnxt;
+};
+
+/* struct for storing defparams - list is design wide */
+struct dfparam_t {
+ unsigned dfp_local : 1;      /* T => defparam is local or in top mod */
+ unsigned dfp_rooted : 1;     /* T => rooted lhs gref */
+ unsigned dfp_mustsplit : 1;  /* T = mst split rng cat lhs dest. param */
+ unsigned dfp_done : 1;       /* during splitting, done with this one */
+ unsigned dfp_has_idents : 1; /* T => identical to other rooted defparam */
+ unsigned dfp_checked : 1;    /* T => after fix-up check done */
+ unsigned dfpfnam_ind : 16;
+ int32 dfplin_cnt;
+ int32 last_dfpi;             /* last element of path */
+
+ struct expr_t *dfpxlhs;
+ struct expr_t *dfpxrhs;
+ struct mod_t *in_mdp;        /* module appeared in for non rooted */
+ struct dfparam_t *dfpnxt;
+ int32 *dfpiis;               /* array of in its indices for path of defp */
+ char *gdfpnam;               /* lhs name from gref */
+ struct sy_t *targsyp;        /* target symbol from gref */
+ struct dfparam_t *idntmastdfp;/* ptr to master if >1 with identical path */
+ struct dfparam_t *idntnxt;   /* list from master of identicals path */
+ struct dfparam_t *rooted_dfps;/* work for converting downward to rooted */
+ struct itree_t *indfp_itp;   /* for rooted, itree place rhs evaled in */ 
+ struct task_t *dfptskp;      /* if non NULL, task target declared in */
+};
+
+/* per type delay storage - 1 array acess during scheduling */
+union del_u {
+ word64 *d1v;                 /* 1 constant (non 0) delay value */
+ word64 *dis1v;               /* 1 constant (IS form maybe some 0) delay */
+ byte *dis1v1;                /* 1 constant IS fits in one byte */
+ hword *dis1v2;               /* 1 constant IS fits in two byte */
+ word64 *d4v;                 /* 4 value constant delay table */
+ word64 *dis4v;               /* 4 constant (IS form maybe some 0) delay */
+ byte *dis4v1;                /* 4 constant IS fits in one byte */
+ hword *dis4v2;               /* 4 constant IS fits in two byte */
+ word64 *d16v;                /* 16 constant IS form */
+ word64 *dis16v;              /* 16 constant (IS form) delay */
+ byte *dis16v1;               /* 16 constant IS fits in one byte */
+ hword *dis16v2;              /* 16 constant IS fits in two bytes */
+ struct expr_t *d1x;          /* 1 delay expr. */
+ struct expr_t **d4x;         /* array of 4 expression ptrs */
+ struct pthdst_t **pb_pthdst; /* per bit path dest. ptr to same dst. src */
+ struct paramlst_t *pdels;    /* original compile time # delay form */
+};
+
+/* input instance structure before known whether gate or cell */
+struct cell_pin_t {
+ struct expr_t *cpxnd;        /* connecting expression root node */
+ word32 cpfnam_ind;           /* file symbol defined in */
+ int32 cplin_cnt;             /* def. line no. */
+ char *pnam;                  /* probably no symbol table when read */
+ struct cell_pin_t *cpnxt;
+};
+
+struct namparam_t {
+ struct expr_t *pxndp;        /* parameter value as expr. */
+ word32 prmfnam_ind;          /* file pound parameter appears in */
+ int32 prmlin_cnt;            /* line pound parameter defined on */
+ char *pnam;                  /* name as string - no sym table when read */
+ struct namparam_t *nprmnxt;
+};
+
+/* record to store attributes - table of each from attribute inst */
+struct attr_t {
+ unsigned attr_tok : 8;       /* token attribute on */
+ unsigned attr_seen : 1;      /* turn on when see attr of attr tok type */
+                              /* off when added to object */
+ unsigned attr_fnind : 16;    /* file attribute instance defined at */
+ char *attrnam;               /* name but before parsed entire attr inst str */ 
+ struct expr_t *attr_xp;      /* expr - nil if no value expr */
+ int32 attrlin_cnt;           /* and line no. */
+ struct attr_t *attrnxt;
+};
+
+/* source location struct for saving cell port line numbers */
+struct srcloc_t {
+ word32 sl_fnam_ind;
+ int32 sl_lin_cnt;
+};
+
+/* compile time cell or gate contents */
+struct cell_t {
+ unsigned c_hasst : 1;        /* T => strength appears in source */
+ unsigned c_stval : 6;        /* (3 bit 0 st. and 3 bit 1 st. */
+ unsigned cp_explicit : 1;    /* T => all explicit connection list */
+ unsigned c_named : 1;        /* T => instance is named */
+ unsigned c_iscell : 1;       /* T => this is a timing lib. cell */  
+ struct sy_t *csym;
+ struct sy_t *cmsym;          /* module type symbol */
+ struct cell_t *cnxt;
+ struct expr_t *cx1, *cx2;    /* for arrays of gates/insts, the range */
+ struct namparam_t *c_nparms;
+ struct attr_t *cattrs;       /* attrs for cell - moved later */
+ struct cell_pin_t *cpins;
+};
+
+/* list for blocks of allocated cells for fast block freeing */
+struct cpblk_t {
+ struct cell_t *cpblks;
+ struct cpblk_t *cpblknxt; 
+};
+
+/* list for blocks of allocated cell pins for fast block freeing */
+struct cppblk_t {
+ struct cell_pin_t *cppblks;
+ struct cppblk_t *cppblknxt;
+};
+
+/* list of tree node blocks */
+struct tnblk_t {
+ struct tnode_t *tnblks;
+ struct tnblk_t *tnblknxt;
+};
+
+struct cpnblk_t {
+ char *cpnblks;
+ char *cpn_start_sp, *cpn_end_sp;
+ struct cpnblk_t *cpnblknxt;
+}; 
+
+union gia_u {
+ struct inst_t *gia_ip;
+ struct gate_t *gia_gp;
+};
+
+/* index record for mod gate or inst arrays - pted to by insts/gates */ 
+/* only need one of these per array of gate/insts */
+struct giarr_t {
+ unsigned gia_xpnd : 1;       /* T => inst/gate arr xpnd to per bit */
+ unsigned gia_rng_has_pnd : 1;/* T => range has passed pound param */
+ struct expr_t *giax1, *giax2;/* src constant rng exprs from cell */
+ int32 gia1, gia2;            /* evaluated range - expr may chg */
+ int32 gia_bi;                /* base mgates or minsts index */
+ struct expr_t **giapins;     /* tab of original g/i pin expressions */
+ struct sy_t *gia_base_syp;   /* original source base symbol name */
+};
+
+/* run time module instance contents */
+struct inst_t {
+ unsigned ip_explicit : 1;
+ unsigned pprm_explicit : 1;  /* has explicit form pound params */
+ unsigned i_iscell : 1;       /* instance is a cell */
+ unsigned i_pndsplit : 1;     /* T => must pound param split */
+ struct sy_t *isym;
+ struct sy_t *imsym;          /* module type symbol */
+ struct expr_t **ipxprtab;    /* inst. pound param expr. table, nil for none */
+ struct attr_t *iattrs;       /* attribute table for inst. */
+ struct expr_t **ipins;       /* ptr to array of port expr ptrs */
+ struct expr_t ***pb_ipins_tab; /* if non nil, ptr to pb sep pin expr tab */ 
+};
+
+/* as if flattened instance structure - should use inum arrays instead ? */
+/* think this can be smaller but per mod. inst. array better ? */
+struct itree_t {
+ int32 itinum;
+ struct itree_t *up_it;       /* containing itree inst. */
+ struct itree_t *in_its;      /* array of low itree elements */
+ struct inst_t *itip;         /* corresponding inst_t info */
+};
+
+/* gate contents after fixup separation */
+struct gate_t {
+ unsigned gpnum : 14;         /* number of gate ports (limit 16k) */
+ unsigned g_class : 3;        /* gate class for processing case */
+ unsigned g_hasst : 1;        /* T => stren in src or tran(if) cycle break */
+ unsigned g_stval : 6;        /* (3 bit each 0 and 1 st.) <ST:ST> if none */
+ unsigned g_delrep : 5;
+ unsigned g_unam : 1;         /* primitive has no instance name */
+ unsigned g_gone : 1;         /* gate removed, no state */ 
+ unsigned g_pdst : 1;         /* T => gate drives del/pth */
+ union del_u g_du;            /* per type delay union */
+ struct sy_t *gsym;
+ struct sy_t *gmsym;          /* gate type symbol */
+ union pck_u gstate;          /* per inst. storage of state vector */
+ i_tev_ndx *schd_tevs;        /* per inst. array of scheduled events ndxes */
+ struct attr_t *gattrs;       /* optional gate attribute */
+ struct expr_t **gpins;       /* ptr to table of input port expr ptrs */
+
+ /* routine to eval gate on input change */
+ void (*gchg_func)(register struct gate_t *, register word32);
+};
+
+union pbca_u {
+ struct conta_t *pbcaps;      /* for rhs cat per bit conta tab for sim */
+ struct conta_t *mast_cap;    /* for per bit element, ptr to master */
+ struct conta_t *canxt;       /* once mod's 1 bit conta rem, use table */
+};
+
+/* notice 1 bit ca's are simulated as gates */
+struct conta_t {
+ struct sy_t *casym;
+ unsigned ca_hasst : 1;
+ unsigned ca_stval : 6;       /* (3 bit 0 st. and 3 bit 1 st. */
+ unsigned ca_delrep : 5;
+ unsigned ca_4vdel : 1;       /* T => delay 4v so need to eval new_gateval */
+ unsigned ca_gone : 1;        /* continuous assign could be removed */
+ unsigned ca_pb_sim : 1;      /* T => in src rhs concat simulates as PB */
+ unsigned ca_pb_el : 1;       /* T => this is a per bit el pb fld is master */
+ union del_u ca_du;           /* per type delay table (only in master) */
+ struct expr_t *lhsx;
+ struct expr_t *rhsx;
+ i_tev_ndx *caschd_tevs;      /* per inst. scheduled event ndx array */
+ union pck_u ca_drv_wp;       /* ptr to rhs drive a/b values if needed */
+ union pck_u schd_drv_wp;     /* pck per inst. scheduled value */
+ union pbca_u pbcau;          /* up or down tab rhs cat decomposed PB val */ 
+ struct conta_t *canxt;       /* for non rhs cat decomposed PB, nxt field */  
+};
+
+/* net storage */
+/* compilation specific net auxiliary fields */
+struct ncomp_t {
+ /* compile time only flags */
+ unsigned n_iotypknown : 1;
+ unsigned n_wirtypknown : 1;
+ unsigned n_rngknown : 1;     /* needed to separte range in i/o/wire decls */
+ unsigned n_impldecl : 1;     /* declared implicitly */
+ unsigned n_in_giarr_rng : 1; /* in array of g/i range expression */
+ unsigned n_spltstate : 2;    /* scalared/vectored splitting of wire */
+ unsigned n_onrhs : 1;        /* appears on some rhs (also declarative) */ 
+ unsigned n_onlhs : 1;        /* appears on some lhs */
+ unsigned n_2ndonlhs : 1;     /* T => more than 1 on lhs (for in to inout) */
+ unsigned num_prtconns : 2;   /* count to 2 of no. of ports wire conns to */
+ unsigned n_widthdet : 1;     /* T => parm is width determing - no IS form */
+ unsigned n_indir_widthdet : 1; /* T => parm passed down to width det */
+ unsigned p_setby_defpnd : 1; /* T => can't recalc since set by def/pnd */
+ unsigned p_specparam : 1;    /* T => specify parameter */
+ unsigned p_rhs_has_param : 1;/* T => param def rhs contains param */
+ unsigned p_locparam : 1;     /* T => local parameter (never # or def) */
+ unsigned prngdecl : 1;       /* T => range declared in source */
+ unsigned ptypdecl : 1;       /* T => type declared in source */
+ unsigned psigndecl : 1;      /* T => signed keyword declared in source */
+ unsigned parm_srep : 4;      /* for parameter n_dels_u original expr rep */ 
+ unsigned pbase : 3;          /* base of original rhs */
+ unsigned pstring : 1;        /* T => if string appeared on original rhs */
+ unsigned frc_assgn_in_src : 1; /* T => force or assign appears in src */
+ unsigned monit_in_src : 1;   /* T => has mon/fmon in source for var */
+ unsigned dmpv_in_src : 1;    /* if not all dummpvar => has mon/fmon in src */
+ unsigned n_iscompleted : 1;  /* type def completed in earlier source */ 
+ 
+ struct expr_t *nx1, *nx2;
+ struct expr_t *ax1, *ax2;
+ union del_u n_dels_u;
+ byte *n_pb_drvtyp;           /* per bit drvr state tab for port dir chg */ 
+ byte n_drvtyp;               /* for scalar simple stat tab for dir chg */
+};
+
+/* list for blocks of allocated ncomp for fast block freeing */
+struct ncablk_t {
+ struct ncomp_t *ancmps;
+ struct ncablk_t *ncablknxt; 
+};
+
+/* array - LOOKATME - one dimensional only so far */
+struct rngarr_t {
+ int32 ni1, ni2;
+ int32 ai1, ai2;
+};
+
+/* normal wire with delay or path destination wire */
+struct rngdwir_t {
+ int32 ni1, ni2;
+ unsigned n_delrep : 5;
+ union del_u n_du;            /* every bit has same delay for nets */ 
+ i_tev_ndx *wschd_pbtevs;     /* any schd. event ndxes - indexed nwid*inst */
+};
+
+struct rngwir_t {
+ int32 ni1, ni2;
+};
+
+/* various extra storage information for various stages for nets */
+union nx_u {
+ struct ncomp_t *ct;          /* compile time value */
+ struct rngarr_t *rngarr;
+ struct rngdwir_t *rngdwir;
+ struct rngwir_t *rngwir;
+};
+
+union np_u {
+ struct gref_t *npgrp;        /* xmr glb that needs normal downward proc. */
+ struct itree_t *filtitp;     /* for root or uprel xmr filt to 1 inst */
+ struct h_t *vpihp;           /* for vpi_ added, the assoc. handle */
+};
+
+/* auxiliary list struct of lists of per inst dce lsts for qcaf lhs concats */
+struct dceauxlstlst_t {
+ /* SJM 06/23/02 - for wire dce list for 1 lhs bit but ndx is per inst/bit */
+ struct dceauxlst_t **dcelsttab; /* peri(/bit) tab of ptrs to dce lsts */
+ struct dceauxlstlst_t *dcelstlstnxt;
+};
+
+/* auxiliary list struct for removing dce's of various types */ 
+struct dceauxlst_t {
+ struct dcevnt_t *ldcep;
+ struct dceauxlst_t *dclnxt;
+};
+
+struct dvchgnets_t {
+ struct net_t *dvchg_np; 
+ struct itree_t *dvchg_itp;
+ struct dvchgnets_t *dvchgnxt;
+};
+
+union dce_u {
+ struct gref_t *dcegrp;       /* xmr glb that needs normal downward proc. */
+ int32 pnum;                  /* for pvc dce tf routine port number */     
+ struct task_t *tskp;         /* for dmpv dce, task variable in */
+ struct cbrec_t *dce_cbp;     /* cbrec for vpi_ val chg callback */
+};
+
+/* SJM 06/12/02 - need 2nd union to separate different types of data */
+union dce2_u {
+ struct fmonlst_t *dce_fmon;  /* nil if monit else fmon record for monitors */
+ struct expr_t *dce_pvc_fcallx; /* pvc misctf fcall expr */
+ struct st_t *dce_pvc_stp;    /* pvc misctf statment */
+ struct qcval_t *dce_qcvalp;  /* for qcaf dce, stmts qcval record */ 
+};
+
+/* for edge where value expr., need general information for filtering */
+/* all decomposed dce's from expr, pt. to one of these */
+struct dce_expr_t {
+ struct expr_t *edgxp;
+ byte *bp;
+ struct dcevnt_t *mast_dcep;  /* one master (first) for alloc and init */ 
+};
+
+/* fixed (except $monitor chges) list off wire of things to trigger */
+struct dcevnt_t {
+ unsigned dce_typ : 8;        /* itree location and action match type */ 
+ unsigned dce_xmrtyp : 2;     /* indicates if xmr and type */ 
+ unsigned dce_1inst : 1;      /* one instance form must match match itp */
+ unsigned dce_edge : 1;       /* T => need edge filtering  */
+ unsigned dce_edgval : 8;     /* edge signature for filter (only pos/neg) */
+ unsigned dce_nomonstren : 1; /* T => ignore stren for monit of stren */
+ unsigned dce_tfunc : 1;      /* T => for pvc dce func. not task */
+ unsigned dce_off : 1;        /* for byte code PLI/monitor need dce on/off */ 
+ unsigned is_fmon : 1;        /* monitor is fmon */
+ union pck_u prevval;         /* storage for wire or range for non dmpv */
+ int32 dci1;                  /* for range dci2 union for IS param */ 
+ union intptr_u dci2;         /* for IS param union rng ptr (dci1 = -2) */
+ struct net_t *dce_np;        /* net this dce is triggerd by */
+ struct delctrl_t *st_dctrl;  /* statement's delay control record */
+ union dce_u dceu;            /* for xmr - propagation gref info */
+ union dce2_u dceu2;          /* nil if monit else fmon record */
+ struct itree_t *dce_matchitp;/* for 1 inst. must match this itree target */
+ struct itree_t *dce_refitp;  /* for 1 inst. this is reference itree loc */
+ struct itree_t *iact_itp;    /* for per inst. iact need inst. to match */
+ struct dce_expr_t *dce_expr; /* for edge where need expr old val and expr */
+ struct dcevnt_t *dcenxt;     /* next on wire dcelst */
+};
+
+/* built in table for every built in primitive (gate) */
+struct primtab_t {
+ unsigned gateid : 8;
+ unsigned gclass : 8;         /* class of gate */
+ struct sy_t *gnsym;
+ char *gatnam;
+};
+
+/* table for system task info */
+struct systsk_t {
+ word32 stsknum;              /* systask ind or 1000+index veriusertfs[] */
+ char *stsknam;               /* name of system task or pli task */
+};
+
+/* list for +loadvpi or +loadpli1 dynamic lib and bootstrap function pairs */
+union dynlb_u {
+ void (*vpi_rout)(void);
+ void *(*tf_rout)(void);
+};
+
+/* need list of boot strap routines because option allows more than one */
+struct dynboot_t {
+ char *bootrout_nam;
+ union dynlb_u dynu;
+ struct t_tfcell *ret_veriusertf;
+ struct dynboot_t *dynbootnxt;
+}; 
+
+struct loadpli_t {
+ unsigned pli1_option : 1;    /* T => +loadpli1= option */
+ char *libnam;
+ struct dynboot_t *dynblst;   /* list of boot routines (can be empty) */ 
+ /* for pli1, if non nil ptr to veriusertf tab */
+ struct loadpli_t *load_plinxt;
+};
+
+struct tfinst_t { 
+ struct expr_t *callx;
+ struct st_t *tfstp;
+ struct itree_t *tfitp;
+ struct task_t *tftskp;
+};
+
+/* table for system function info */
+struct sysfunc_t {
+ word32 syfnum;               /* sysfunc ind. or 1000+ind veriusertfs[] */
+ unsigned retntyp : 8;
+ unsigned retsigned : 1;      /* need for signed wire */
+ unsigned tftyp : 8;          /* type */
+ int32 retwid;                /* for veriuser and vpi systf sizetf call sets */
+ char *syfnam;                /* name of system function */
+};
+
+union vsystf_u {
+ struct expr_t *sysfcallx;    /* if systf fcall, vpi_ systf call expr. */
+ struct st_t *syststp;        /* stmt vpi_ systf call or task enable in */
+};
+
+/* list element for each location vpi_ systf appears in source */
+/* cross linked through sz_u from calling expr node */
+struct vpisystf_t {
+ unsigned is_sysfunc : 1;     /* t +> vpi_ systf func */
+ unsigned vstffnam_ind : 16;
+ int32 vstflin_cnt;
+ struct mod_t *curmdp;        /* ptr. to current mod source line of call in */
+ struct task_t *curtskp;      /* ptr. to current task source line of call in */
+ union vsystf_u vsystfu;      /* ptr to callx or sys task stmt */ 
+ struct vpisystf_t *vpistfnxt; 
+};
+
+union mpp_afunc_u {
+ /* routine for input cross port assign */
+ void (*mpp_downassgnfunc)(register struct expr_t *,
+  register struct expr_t *, struct itree_t *);
+ /* routine for output cross port assign */
+ void (*mpp_upassgnfunc)(register struct expr_t *,
+  register struct expr_t *, struct itree_t *);
+};
+
+/* work record for decomposed into per bit declarative assign */
+struct pbexpr_t {
+ unsigned ndx_outofrng : 1;
+ unsigned rhs_const : 1;
+ unsigned no_rhs_expr : 1;     /* lhs widers bits need 0/z assign */
+ struct expr_t *xp;
+ int32 bi;                     /* for bsel/psel offset in var object */
+ word32 aval;                  /* aways 1 bit constant value (for rhs only) */
+ word32 bval;
+};
+
+/* module port element */
+struct mod_pin_t {
+ unsigned mptyp : 3;          /* I/O type - maybe changed with warning */
+ unsigned mp_explicit : 1;    /* T => source explicit port reference */
+ unsigned mp_jmpered : 1;     /* T => port has net also in other port */
+ unsigned inout_unc : 1;      /* T => this inout unc. somewhere */
+ unsigned assgnfunc_set : 1;  /* T => know the port assign func */
+ unsigned has_mipd : 1;       /* T => input port has mipd delay */
+ unsigned has_scalar_mpps : 1;/* T => simulated per bit */
+ unsigned mpfnam_ind : 16;    /* file symbol defined in */
+ int32 mplin_cnt;             /* def. line no. */
+ int32 mpwide;                /* width of port */
+ 
+ char *mpsnam;                /* name not symbol of port (can be NULL) */
+ struct expr_t *mpref;        /* expression form port list (const.) */
+ struct attr_t *mpattrs;      /* all I/O decls attrs for conn nets */
+
+ /* union of proc ptrs  for input/output cross port assign */
+ union mpp_afunc_u mpaf;
+ struct mod_pin_t *pbmpps;    /* for rhs hconn input port, per bit mpp */
+ struct mod_pin_t *mpnxt;     /* elaborate time next link */
+};
+
+/* table build per line for wild card processing */
+struct wcard_t {
+ int32 wcinum;                /* in port (also state) numb for wild card */
+ char wcchar;                 /* wild card ? or b */
+};
+
+/* udp table storage */
+struct utline_t {
+ /* these must be char pairs even for combinatorial */
+ unsigned ulhas_wcard : 1;
+ unsigned ullen : 8;          /* length of original tline in bytes */
+ unsigned utabsel : 8;        /* first edge char table select (maybe wc) */
+ unsigned uledinum : 8;       /* input position number of one allowed edge */
+ unsigned utlfnam_ind : 16;   /* file no. of udp line */
+ int32 utlin_cnt;             /* line no. of udp tble line */
+ char *tline;                 /* table line - for edge 2nd char in line */
+ struct utline_t *utlnxt;
+};
+
+/* special struct for udp tables */
+struct udptab_t {
+ word32 *ludptab;
+ /* alloced according to required size (max 27 pointers to tabs of words */
+ word32 **eudptabs;
+};
+
+struct udp_t {
+ unsigned utyp : 4;
+ unsigned numins : 8;         /* number of inputs */
+ unsigned numstates : 8;      /* for combinatorial same else one more */
+ unsigned ival : 8;           /* initial value (0,1,3 - none) */
+ unsigned u_used : 1;         /* T => need table, instanciated in some mod */
+ unsigned u_wide : 1;         /* T => uses alt. wide representation */
+ int32 uidnum;                /* tmp. id number for counting */
+ struct sy_t *usym;
+ struct symtab_t *usymtab;    /* symbol table just for terminals */
+ struct mod_pin_t *upins;     /* defined ports for order */
+ struct utline_t *utlines;
+ struct udp_t *udpnxt;
+ struct udptab_t *utab;
+};
+
+/* task port (like procedural variable - all info in reg(wire)) */
+struct task_pin_t {
+ unsigned trtyp : 8;          /* i/o type (same as sym np iotyp) */
+ struct sy_t *tpsy;           /* port name sym. points to wire/reg */
+ struct task_pin_t *tpnxt;
+};
+
+/* procedureal assignment statement */
+struct proca_t {
+ struct expr_t *lhsx;         /* need to make sure this is an lvalue */
+ struct expr_t *rhsx;
+};
+
+/* quasi continous assigns */
+struct qconta_t {
+ unsigned qcatyp : 8;
+ unsigned regform : 8;
+ struct expr_t *qclhsx;
+ struct expr_t *qcrhsx;
+ struct dceauxlstlst_t *rhs_qcdlstlst;
+};
+
+/* quasi cont. deassigns - no continuous deassign */
+struct qcontdea_t {
+ unsigned qcdatyp : 8;
+ unsigned regform : 8;
+ struct expr_t *qcdalhs;
+};
+
+struct if_t {
+ struct expr_t *condx;
+ struct st_t *thenst;
+ struct st_t *elsest;
+};
+
+struct csitem_t {
+ struct exprlst_t *csixlst;
+ struct st_t *csist;          /* for unnamed block can be list */
+ struct csitem_t *csinxt;
+};
+
+struct case_t {
+ unsigned castyp : 8;
+ unsigned maxselwid : 24;
+ struct expr_t *csx;
+ struct csitem_t *csitems;    /* first item always default: place holder */  
+};
+
+struct wait_t { 
+ struct expr_t *lpx;
+ struct st_t *lpst;
+ struct delctrl_t *wait_dctp;
+};
+
+/* for forever and while */
+struct while_t {
+ struct expr_t *lpx;
+ struct st_t *lpst;
+};
+
+struct repeat_t {
+ struct expr_t *repx;
+ word32 *reptemp;             /* per inst. word32 current value tmp */
+ struct st_t *repst;
+};
+
+struct for_t {
+ struct st_t *forassgn;
+ struct expr_t *fortermx;
+ struct st_t *forinc;
+ struct st_t *forbody;
+};
+
+/* for Ver 2001 - implicit delay control var list in action stmt */
+struct evctlst_t {
+ struct net_t *evnp; 
+ int32 evi1, evi2;
+};
+
+/* normal separate delay control - but in case of rhs control contains st. */
+/* event expression allow events edges of events and oring of ev. exprs */
+struct delctrl_t {
+ unsigned dctyp : 8;          /* event or delay */
+ unsigned dc_iact : 1;        /* iact delay control */ 
+ /* SJM 06/10/02 - distinguish non blocking from blocking event ctrls */  
+ unsigned dc_nblking : 1;     /* T => delay control is non blocking form */
+ unsigned implicit_evxlst : 1;/* special all rhs's @(*) ev var-ndx list */ 
+ unsigned dc_delrep : 5;      /* normal gca delay type */
+ union del_u dc_du;           /* normal delay union (also used for ev ctrl) */
+ struct expr_t *repcntx;      /* for rhs ev ctrl repeat form, rep cnt expr */
+ i_tev_ndx *dceschd_tevs;     /* per inst. scheduled event ndxes */ 
+ /* SJM 04/02/01 - need word32 down repeat counter with end when becomes 0 */ 
+ word32 *dce_repcnts;         /* per inst. current ev rep down count val */
+ struct st_t *actionst;
+};
+
+/* header list for each initial always block */
+struct ialst_t {
+ unsigned iatyp : 8;
+ struct st_t *iastp; 
+ 
+ int32 ia_first_lini;         /* line no. of initial/always */
+ int32 ia_first_ifi;          /* and file index */
+ int32 ia_last_lini;          /* line no. of end (mabye in next file) */
+ int32 ia_last_ifi;           /* end file in case spans multiple files */
+ struct ialst_t *ialnxt;   
+};
+
+union tf_u {
+ struct expr_t *callx;        /* for tf_ func ptr back to call expr else nil */
+ struct st_t *tfstp;          /* for tf_ task ptr back to call stmt else nil */
+};
+
+union tfx_u {
+ struct expr_t *axp;          /* for arg the expr. */
+ word32 *awp;                 /* for 0th return value just the value */
+};
+
+/* per parameter tfrec record */
+struct tfarg_t {
+ union tfx_u arg;
+ struct net_t *anp;           /* for is rw, the wire */
+ byte *old_pvc_flgs;          /* old and sav pvc flags */
+ byte *sav_pvc_flgs;
+ struct dltevlst_t **dputp_tedlst;/* per inst ptr to list of delputps */
+ char **sav_xinfos;           /* per inst evalp saved expr info rec */
+ union pck_u tfdrv_wp;        /* for rw, pointer to param driver value */ 
+};
+
+/* extra task call side data for pli tasks/funcs (each call loc. differs) */
+struct tfrec_t {
+ unsigned tf_func : 1;        /* is record for tf_ func */
+ unsigned fretreal : 1;       /* func. returns real */
+ unsigned tffnam_ind : 16;
+ int32 tflin_cnt;
+ int32 tfanump1;              /* no. of args plus 1 (included 0th func ret) */
+ int32 fretsiz;               /* for function return size (sizetf ret. val) */  
+ union tf_u tfu;              /* ptr back to tf_ task or function */
+ struct mod_t *tf_inmdp;      /* module in (for inst. number) */
+ struct task_t *tf_intskp;    /* task call in (nil in in init/always */
+ struct tfarg_t *tfargs;      /* per parameter param record table */
+ char **savwrkarea;           /* per inst saved work areas */
+ i_tev_ndx *sync_tevp;        /* per inst ndx to sync event */
+ i_tev_ndx *rosync_tevp;      /* per inst ndx to ro sync event in list */ 
+ byte *asynchon;              /* per inst. async on flag */
+ struct tevlst_t **setd_telst; /* per inst ptr to list of set dels */  
+ struct dceauxlst_t **pvcdcep;/* per inst dce list but all parameters */
+ struct tfrec_t *tfrnxt;      /* linked list */
+};
+
+/* vpi handle union of internal d.s. elements */
+union h_u {
+ struct gate_t *hgp;
+ struct net_t *hnp;
+ struct task_t *htskp;        /* also named block and function */
+ struct mod_t *hmdp;          /* for mods in modsyms table */
+ struct ialst_t *hialstp;     /* process - init or always */
+ struct mod_pin_t *hmpp;      /* udp port or net-pin list mod. I/O port */
+ struct conta_t *hcap;        /* pointer to conta */
+ struct spcpth_t *hpthp;      /* point back to path for special id symbol */    
+ struct dfparam_t *hdfp;      /* for defparam source reconstruction handles */
+ struct tchk_t *htcp;         /* and back to time check */      
+ struct expr_t *hxp;          /* representation as ptr to expr. */
+ struct st_t *hstp;           /* statement handle */
+ struct csitem_t *hcsip;      /* case item */
+ int32 hpi;                   /* for port bit handle the port index */
+ /* this is only contents field that is freed */
+ struct pviter_t *hiterp;     /* iterator indirect element with alloc list */
+ struct cbrec_t *hcbp;        /* callback handle guts record */
+ i_tev_ndx htevpi;            /* event ndx for sched. vpi put value only */
+ struct net_pin_t *hnpp;      /* for driver the drvr net pin record */
+ struct udp_t *hudpp;         /* udp handle object record */ 
+ struct utline_t *hutlp;      /* udp line for table entry handle */
+ struct schdev_t *hevrec;     /* pending vpi_ driver all net sched. evs tab */
+ void *hanyp;                 /* any ptr so do not need to cast to it */
+ struct hrec_t *hfreenxt;     /* ptr to next hrec on free list */
+};
+
+/* non-blocking event list */
+struct nb_event_t { 
+ i_tev_ndx nb_tevpi; 
+ struct nb_event_t *nbnxt;
+};
+
+/* handle object event table record for scheduled vector events */ 
+struct schdev_t {
+ struct net_t *evnp;
+ i_tev_ndx *evndxtab; 
+};
+
+/* actual handle */
+struct h_t {
+ struct hrec_t *hrec;         /* hadnle content record */
+ struct itree_t *hin_itp;     /* itree inst object in (if relevant) */
+};
+
+/* handle contents */
+struct hrec_t {
+ unsigned htyp : 16;          /* vpi object type of handle */
+ unsigned htyp2 : 16;         /* extra type */
+ unsigned h_magic : 11;       /* magic number for internal checking */
+ unsigned in_iter : 1;        /* part of iterr, free when iterator freed */
+ unsigned free_xpr : 1;       /* free expr. when free handle */
+ unsigned evnt_done : 1;      /* for vpi schd event, event happened */
+ unsigned bith_ndx : 1;       /* bit handle index form (also any tab form) */ 
+ union h_u hu;                /* ptr to object (could be void *) */ 
+ int32 hi;                    /* for bit of object handle the index */
+ struct task_t *hin_tskp;     /* task (scope) handle in (or ialst) */
+};
+
+struct pviter_t {
+ struct h_t *scanhtab;        /* table of handles built by vpi iterator */
+ struct hrec_t *ihrectab;     /* table of handle content records */ 
+ int32 nxthi;                 /* next handle to return */
+ int32 numhs;                 /* total number of handles for iterator */
+};
+
+struct onamvpi_t {
+ char *vpiobjnam;
+ word32 vpiotyp;              /* redundant value same as obj constant ind */
+};
+
+struct pnamvpi_t { 
+ char *vpipropnam;
+ int32 vpiproptyp;            /* redundant value same as prop constant ind */
+};
+
+struct opnamvpi_t { 
+ char *vpiopnam;
+ int32 vpioptyp;              /* redundant value same as op constant ind */
+ char *vpiopchar;             /* operator character (such as +) */
+};
+
+union systf_u { 
+ struct systsk_t *stbp;
+ struct sysfunc_t *sfbp;
+};
+
+struct systftab_t {
+ unsigned systf_chk : 1;      /* T => already seen in source and checked */ 
+ void *vpi_sytfdat;
+ union systf_u sfu;
+};
+
+/* guts of callback handle - separate handle for each instance */
+/* info from passed user cb_data record copied into here */
+struct cbrec_t {
+ unsigned cb_reason : 12;     /* reason field from passed cb_data rec. */
+ unsigned cb_rettimtyp : 6;   /* time record field type to return */
+ unsigned cb_retvalfmt : 7;   /* value record field format to return */
+ unsigned cb_class : 3;       /* internal scheduling class */  
+ unsigned cb_ndxobj : 1;      /* T => value chg handle is indexed */  
+ unsigned cb_user_off : 1;    /* T => user turned off with sim control */
+ unsigned cb_gateout : 1;     /* T => gate outut val chg type cb */ 
+ struct h_t *cb_hp;           /* object */ 
+ int32 (*cb_rtn)();           /* cb_data call back routine */
+ char *cb_user_data;          /* user data field from passed cb_data rec. */
+ struct dceauxlst_t *cbdcep;  /* list of dces for cb removal */ 
+ i_tev_ndx cbtevpi;           /* ndx (ptr) back to event */
+ struct h_t *cb_cbhp;         /* associated handle of call back */
+ struct cbrec_t *cbnxt;       /* next in chain of all callbacks */
+ struct cbrec_t *cbprev;      /* previous in chain of all callbacks */
+};
+
+/* list for release and force cb all forms - many cbs possible */
+struct rfcblst_t {
+ struct cbrec_t *rfcbp; 
+ struct rfcblst_t *rfcbnxt;
+};
+
+/* SJM 06/20/02 - for monit now bld dces where can during prep, need dce ptr */
+struct monaux_t {
+ unsigned dces_blt : 1;       /* T => dces already built for this monit */
+ byte *argisvtab;             /* tab of v format flags for monitor */
+ struct dceauxlst_t **mon_dcehdr; /* lst of per inst dces bld during prep */ 
+};
+
+/* SJM 06/20/02 - change sys task aux field to union instead of casts */
+/* sys task call union for PLI systf calls and monitor/fmonitor aux info */
+union tkcaux_u {
+ struct tfrec_t *trec;        /* ptr to aux pli tf_ data */
+ struct monaux_t *mauxp;      /* ptr to mon aux v format flag and dce ptr */
+ void *vpi_syst_datap;
+};
+
+struct tskcall_t {
+ struct expr_t *tsksyx;       /* task symbol or global table entry */
+ struct expr_t *targs;        /* FCCOM expr of args */
+ union tkcaux_u tkcaux;       /* ptr to aux pli tf_ data or monit rec */
+};
+
+struct dsable_t {
+ struct expr_t *dsablx;       /* expr. (ID/GLB) of disable task/func/blk */
+ struct st_t *func_nxtstp;    /* for functions disable is goto */
+};
+
+struct fj_t {
+ struct st_t **fjstps;        /* ptr to tab (nil ended) fork-join stmts */
+ int32 *fjlabs;               /* ptr to tab of fj start lab nums */
+};
+
+/* slot end stmt list for strobes with itree where execed strobe appeared */
+struct strblst_t {
+ struct st_t *strbstp;
+ struct itree_t *strb_itp;
+ struct strblst_t *strbnxt;
+};
+
+/* slot end triggered fmonitor list */
+struct fmselst_t {
+ struct fmonlst_t *fmon;
+ struct fmselst_t *fmsenxt;
+};
+
+/* acctivated fmonitor list with itree location */
+struct fmonlst_t {
+ word32 fmon_forcewrite;
+ struct st_t *fmon_stp;
+ struct itree_t *fmon_itp;
+ struct fmselst_t *fmse_trig; /* set when monitor triggered 1st time */
+ struct dceauxlst_t *fmon_dcehdr;
+ struct fmonlst_t *fmonnxt;
+}; 
+
+/* union either 4 byte ptr or 12 byte union in statment */
+/* save space since previously needed 4 byte ptr plus record */
+union st_u {
+ struct proca_t spra;
+ struct if_t sif;
+ struct case_t scs;
+ struct while_t swh;
+ struct wait_t swait;
+ struct repeat_t srpt;
+ struct for_t *sfor;
+ struct delctrl_t *sdc;
+ struct task_t *snbtsk;       /* named (like task) block */
+ struct st_t *sbsts;          /* unnamed block statement list */
+ struct fj_t fj;              /* fj 2 tabs (1 stps and 1 fj c code labs */
+ struct tskcall_t stkc;
+ struct qconta_t *sqca;       /* assign and force */
+ struct qcontdea_t sqcdea;    /* deassign and release */
+ struct expr_t *scausx;       /* cause expr. node symbor or global id. */
+ struct dsable_t sdsable;     /* disable struct (also place for goto dest) */
+ struct st_t *sgoto;          /* destination of added goto */
+};
+
+/* statement structure */
+struct st_t {
+ unsigned stmttyp : 5;
+ unsigned rl_stmttyp : 5;     /* for break set at statment, real type */
+ unsigned st_unbhead : 1;     /* if unnamed block removed, indicated here */  
+ unsigned strb_seen_now : 1;  /* T => for checking strobe on list for now */
+ unsigned lpend_goto : 1;     /* T => this is loopend goto */
+ unsigned dctrl_goto : 1;     /* T => this is next after dctrl chain goto */ 
+ unsigned lstend_goto : 1;    /* T => list end continue goto */
+ unsigned st_schd_ent : 1;    /* T => can be first stmt entered from schd */
+ unsigned lpend_goto_dest : 1; /* dest. of loop end back goto for compiler */
+ unsigned stfnam_ind : 16;
+ int32 stlin_cnt;
+ union st_u st;
+ struct st_t *stnxt;
+};
+
+/* contents of break point table */
+struct brkpt_t {
+ unsigned bp_type : 4;        /* type of breakpoint */ 
+ unsigned bp_can_halt : 1;    /* T => really break, F start and reset */
+ unsigned bp_enable : 1;      /* T => break not disabled */
+ unsigned bp_prttyp : 2;      /* type of printing when hit */
+ unsigned bp_dup : 1;         /* T => multiple break points at statement */
+ unsigned bp_rm_when_hit : 1; /* T => remove when hit */
+ int32 bp_num;                /* identifying number */
+ int32 bp_ignore_cnt;
+ int32 bp_hit_cnt;            /* number of times hit */
+ struct st_t *bp_stp;         /* statement this break point breaks at */
+ struct itree_t *bp_itp;      /* itree loc. - any (first?) for all of type */ 
+ struct task_t *bp_tskp;      /* task break point in else NULL if not */
+ struct expr_t *bp_condx;     /* :cond cmd filter expr. */ 
+ /* expressions and watch point values go here */
+ struct brkpt_t *bpnxt;
+};
+
+struct dispx_t {
+ unsigned dsp_enable : 1;
+ unsigned dsp_frc_unsign : 1;
+ int32 dsp_num;
+ int32 dsp_prtfmt;
+ int32 dsp_prtwidth;
+ struct expr_t *dsp_xp;
+ struct itree_t *dsp_itp;
+ struct task_t *dsp_tskp;
+ struct dispx_t *dsp_nxt;
+};
+
+/* horizontal doubly linked list of task threads */
+struct tskthrd_t {
+ struct tskthrd_t *tthd_l, *tthd_r;
+ struct thread_t *tthrd;
+};
+
+/* task definition - type of task name symbol determines task type */
+struct task_t {
+ unsigned tsktyp : 8;         /* symbol number giving task type */
+ unsigned t_used : 1;         /* T => task/func. invoked some where */
+ unsigned thas_outs : 1;      /* T => task has outs that must be stored */ 
+ unsigned thas_tskcall : 1;   /* T => task contains other task call */
+ unsigned fhas_fcall : 1;     /* T => func contains non sys fcall */
+ unsigned tf_lofp_decl : 1;   /* T => t/f hdr list of port decl form */ 
+ struct sy_t *tsksyp;         /* name symbol in module level table */
+ int32 tsk_last_lini;         /* line no. of end (mabye in next file) */
+ int32 tsk_last_ifi;          /* end file in case spans multiple files */
+ struct symtab_t *tsksymtab;  /* symbol table for objects in task */
+ struct st_t *st_namblkin;    /* stmt named block in in */
+ struct task_pin_t *tskpins;  /* task ports - procedural not wires */
+ struct net_t *tsk_prms;      /* parameters defined in task */
+ int32 tprmnum;               /* number of task parameters */
+ struct net_t *tsk_regs;      /* list then array of nets in task */
+ int32 trnum;                 /* number of task regs */   
+ struct st_t *tskst;          /* one task statement (usually a block) */
+ struct task_t *tsknxt;       /* next defined task in current module */
+ struct tskthrd_t **tthrds;   /* per inst. list of active threads for task */
+};
+
+/* symbol table tree nodes */
+struct tnode_t {
+ unsigned bal : 8;
+ unsigned via_dir : 8;
+ struct sy_t *ndp;
+ struct tnode_t *lp, *rp;
+};
+
+/* symbol table element (type) pointer union */
+union el_u {
+ struct cell_t *ecp;
+ struct inst_t *eip;
+ struct gate_t *egp;
+ struct net_t *enp;
+ struct st_t *estp;
+ struct delctrl_t *edctp;     /* delay ctrl for re prep pnps */
+ struct task_t *etskp;        /* also named block and function */
+ struct systsk_t *esytbp;     /* pointer to system task table entry */
+ struct sysfunc_t *esyftbp;   /* pointer to system func. table entry */
+ struct mod_t *emdp;          /* for mods in modsyms table */
+ struct primtab_t *eprimp;    /* for prims (gates) in modsyms table */
+ struct udp_t *eudpp;         /* for udps in modsysm table */
+ struct mod_pin_t *empp;      /* udp port or net-pin list mod. I/O port */
+ char *edfchp;                /* value of `define macros in defsyms table */
+ struct amac_t *eamacp;       /* value for macro with arguments */
+ struct conta_t *ecap;        /* pointer to conta */
+ struct spcpth_t *epthp;      /* point back to path for special id symbol */    
+ struct tchk_t *etcp;         /* and back to time check */      
+ int32 eii;                   /* index of inst. in mod inst list or ni */
+ struct tchg_t *etchgp;       /* time change record */ 
+ struct chktchg_t *echktchgp; /* check time change record */
+ struct undef_t *eundefp;     /* for undefined temp. link to list el. */
+ struct tfrec_t *etfrp;       /* ptr to tf_ func/task record */
+ void *eanyp;                 /* castable void * for special cases */
+ struct mipd_t *emipdbits;    /* ptr to per bit mipd record for MIPD npp */
+};
+
+
+/* net pin aux struct for special cases */
+struct npaux_t {
+ int32 nbi1;                  /* range of connection (-1 for all) */
+ /* convention if nbi1 is -2, nbi2 is word32 * union ptr to 2 ISNUM tables */
+ union intptr_u nbi2;         /* for IS param union rng ptr (dci1 = -2) */
+ int32 lcbi1, lcbi2;          /* if fi is lhs concat, the rhs val subrange */
+ union np_u npu;
+ /* for src down itree loc tab for root, must match targ. itree */
+ /* SJM 05/14/03 - since only for rooted XMR npp, this is addr not peri tab */
+ struct itree_t *npdownitp;
+};
+
+struct net_pin_t {
+ unsigned npntyp : 4;         /* type of net pin connection */
+ unsigned npproctyp : 2;      /* type of npp processing needed */ 
+ unsigned chgsubtyp : 3;      /* for change the change subtype */
+ unsigned np_xmrtyp : 2;      /* xmr type */
+ unsigned pullval : 1;        /* for pull driver 0 or 1 */
+ unsigned obnum : 20;         /* port index number */
+ int32 pbi;                   /* for per bit bit index */
+
+ union el_u elnpp;            /* net pin connecting objects */
+ struct npaux_t *npaux;       /* aux. for net pins needing special fields */
+ struct net_pin_t *npnxt;
+};
+
+/* parm nplist for delay update on param change delay anotation */
+struct parmnet_pin_t {
+ unsigned pnptyp : 8;         /* delay expr (or list) type param ref. in */
+ unsigned pnp_free : 1;       /* T => master ptr to delay need to free */
+ union el_u elpnp;            /* in mod element with delay */
+ struct paramlst_t *pnplp;    /* param list (all dels) - copy or orig */
+ struct parmnet_pin_t *pnpnxt;
+};
+
+/* PLI list of mod port or iconn npp's not yet processed for XL style iters */
+struct xldlnpp_t {
+ struct net_pin_t *xlnpp;
+ struct itree_t *xlitp;
+ struct xldlnpp_t *xlnxt;
+};
+
+/* record accessed through sorted index of net/bits with xl style drv/lds */
+struct xldlvtx_t {
+ struct net_t *dlnp;
+ int32 dlbi;
+ struct itree_t *dlitp;
+};
+
+/* edge list - since both vertices point to this */
+struct edge_t { 
+ struct vtx_t *ev2;           /* other side edge, this side is cur vtx */
+ struct itree_t *edgoside_itp; /* edge other side itree loc (nil if same) */
+ /* npnxt has value for traux list for vpi - tran chan must not touch */ 
+ struct net_pin_t *enpp;      /* npp of connecting edge (npp) */
+ struct edge_t *enxt;
+};
+
+/* vertex of tran graph - only traversed thru edges - need npp itp chg */ 
+struct vtx_t {
+ unsigned new_vtxval : 8;     /* for tran chan, new value */
+ unsigned old_vtxval : 8;     /* value at start of tran relax */
+ unsigned vtx_chged : 1;      /* T => vertex changes - when done store */
+ unsigned vtx_in_vicinity : 1;/* T => vertex already in vincinity */
+ unsigned vtx_forced : 1;     /* T => vertex is forced */
+ unsigned vtx_supply : 1;     /* T => vertex hard drivers/decl supply */ 
+ unsigned vtx_mark : 1;       /* mark bit used for cutting cycles */
+ unsigned vtx_mark2 : 1;      /* mark bit used for turning off marks */
+ struct net_t *vnp;           /* net in channel */
+ int32 vi1;                   /* bit index for vector wire */
+ struct edge_t *vedges;       /* ptr to adjacency list for this node */
+};
+
+/* per bit vtx and chan. id table for this static inst. loc. */
+struct vbinfo_t {
+ int32 chan_id;               /* ID for channel */
+ struct vtx_t *vivxp;         /* vertex */
+};
+
+/* net tran aux record on - exists if net on some bid or tran channel */
+struct traux_t {
+ union pck_u trnva;           /* per inst hard driver values for all of net */
+ struct vbinfo_t **vbitchans; /* (chan_id, vtx) per bit or bit-inst */
+ /* notice this uses npp npnxt field because unused by edges */
+ struct net_pin_t *tran_npps; /* ptr to linked tran chan npps */
+};
+
+/* list element for tran channel relaxation */
+struct vtxlst_t { 
+ struct vtx_t *vtxp;
+ struct itree_t *vtx_itp;
+ struct vtxlst_t *vtxnxt;
+};
+
+/* list of net/bits in switch channel for init and change processing */
+struct bidvtxlst_t {
+ struct net_t *vnp;           /* net in channel */
+ int32 vi1;                   /* bit index for vector wire */
+ struct itree_t *bidvtx_itp;
+ struct bidvtxlst_t *bidvtxnxt;
+};
+
+/* per channel info - some needed for future rtran(if) cutting */
+struct chanrec_t {
+ unsigned chtyp : 3;          /* channel processing type */
+ unsigned chan_diffwtyps : 1; /* T => different wire types in channel */
+ unsigned chan_no_vtxs : 1;   /* T => for pure bid after cnvt to list */
+ struct vtx_t *chvxp;         /* for now one random vertex */ 
+ struct itree_t *chvitp;      /* and its itree loc. */
+ struct bidvtxlst_t *bid_vtxlp;  /* for bid only, list with itree loc */
+ word32 numvtxs;              /* number of vertices (net-bits) in channel */
+};
+
+/* master dumpvar header record for module argument */
+struct mdvmast_t { 
+ struct itree_t *mdv_itprt;   /* itree root of subtree or var itree loc */
+ struct task_t *mdv_tskp;     /* task variable or scope in */
+ struct net_t *mdv_np;        /* for var. form, pointer to wire */
+ struct mdvmast_t *mdvnxt; 
+ int32 mdv_levels;            /* level down from $dumpvars call */
+};
+
+struct qcval_t {
+ unsigned qc_active : 1;      /* T => this net(/bit) force or assign active */
+ unsigned qc_overridden : 1;  /* T => reg assgn active but force overrides */
+ struct st_t *qcstp;
+ int32 qcrhsbi;               /* if concat, rhs low bit index else -1 */
+ int32 qclhsbi;               /* for wire, select lhs low bit index */
+ struct itree_t *lhsitp;
+ struct dceauxlst_t *qcdcep;  /* rhs dce tab of lists */
+};
+
+/* qcval union during prep and exec but other uses earlier and for params */
+union nqc_u {
+ word32 *wp;                  /* for params work saved param val ptr */ 
+ int32 npi;                   /* for params fixup sorting/matching val */
+ struct net_t *nnxt;          /* during src rd and fixup, nets not yet tab */ 
+ struct qcval_t *qcval;       /* per inst. (maybe per bit) qc aux records */
+};
+
+/* table of driver and scheduled values for each added vpi_ net driver */
+/* know if any at least two, last has both fields nil */
+struct vpi_drv_t {
+ union pck_u vpi_hasdrv;      /* per inst. net wide driver added table */
+ union pck_u vpi_drvwp;       /* per inst. net wide driver values */
+ struct dltevlst_t **putv_drv_tedlst;/* per inst per bit pending ev. lists */
+ struct dltevlst_t **softforce_putv_tedlst; /* per inst/bit pend ev lists */
+};
+
+struct net_t {
+ unsigned ntyp : 4;
+ unsigned iotyp : 3;          /* I/O direction */
+ unsigned n_isaparam : 1;     /* T => net is a parameter */
+ unsigned srep : 4;           /* storage representation of value - nva fld */
+ unsigned nrngrep : 3;        /* representation for net ranges - nx_u fld */
+ unsigned n_isavec : 1;       /* this is a vector */
+ unsigned vec_scalared : 1;   /* wire is scalared (bit by bit, T if scalar) */
+ unsigned n_isarr : 1;
+ unsigned n_signed : 1;
+ unsigned n_stren : 1;        /* T => needs strength model */
+ unsigned n_capsiz : 2;       /* special capacitor size constant */
+ unsigned n_mark : 1;         /* misc. marking flag for var. uses */ 
+ unsigned n_multfi : 1;       /* at least one bit fi > 1 */
+ unsigned n_isapthsrc : 1;    /* T => port net a pth src (or tc ref ev.) */
+ unsigned n_isapthdst : 1;    /* T => port net is a path dest */
+ unsigned n_hasdvars : 1;     /* T => at least one inst. dumpvared */
+ unsigned n_onprocrhs : 1;    /* appears on some procedural rhs */
+ unsigned n_gone : 1;         /* T => net deleted by gate eater */
+ /* 03/21/01 - these are fields from removed separate optim table */ 
+ unsigned nchg_nd_chgstore : 1;/* need chg store for var */
+ unsigned nchg_has_dces : 1;  /* T => var currently has delay ctrls */
+ unsigned nchg_has_lds : 1;   /* var has lds (structural from src */
+ unsigned frc_assgn_allocated : 1; /* T => force/assign in src or PLI added */
+ unsigned dmpv_in_src : 1;    /* T => dumpvars for net in src */
+ unsigned monit_in_src : 1;   /* monit for var somewhere in src */
+ unsigned n_onrhs : 1;        /* appears on some rhs (also declarative) */ 
+ unsigned n_onlhs : 1;        /* appears on some lhs */
+ unsigned n_drvtyp : 3;       /* for scalar, pre elab p type chg drvr state */
+ int32 nwid;                  /* net width */
+ union pck_u nva;             /* storage for net */
+ struct sy_t *nsym;
+ union nx_u nu;               /* ptr to auxiliary range and delay values */
+ struct dcevnt_t *dcelst;     /* fixed list of dce/monit events */
+ struct net_pin_t *ndrvs;     /* list of net drivers */
+ struct net_pin_t *nlds;      /* list of loads driven by net */
+ struct traux_t *ntraux;      /* aux tran channel record */  
+ byte *nchgaction;            /* per inst. (or 0 only) assign action bits */
+ /* SJM 07/24/00 - need both add driver and soft force for wires */
+ struct dltevlst_t **regwir_putv_tedlst; /*  per inst (all bits) ev list */
+ struct vpi_drv_t **vpi_ndrvs;/* ptr to table of ptrs to drivers */
+ union nqc_u nu2;             /* union - comp. nnxt, and qcval */  
+ struct attr_t *nattrs;       /* table of net's attributes */
+};
+
+/* symbol table contents and avl tree link info */
+struct sy_t {
+ unsigned sytyp : 8;
+ unsigned sydecl : 1;         /* symbol has been declared */
+ unsigned syundefmod : 1;     /* undefined mod or udp */ 
+ unsigned cfg_needed : 1;     /* T => symbol is used in config */
+ unsigned sy_impldecl : 1;    /* for wire, declared implicitly */
+ unsigned sy_argsmac : 1;     /* macro symbol with arguments */
+ unsigned sy_giabase : 1;     /* T => symbol is g/i array base */
+ unsigned syfnam_ind : 16;    /* file symbol defined in */
+ int32 sylin_cnt;             /* def. line no. */
+ char *synam;
+ union el_u el;
+ struct sy_t *spltsy;
+};
+
+/* separate work array storage of global component names */
+struct glbncmp_t {
+ int32 gncsiz;                /* size of largest alloc component (reused) */
+ char *gncmp;
+};
+
+union targ_u {
+ struct itree_t *targitp;     /* only for rooted - one target itree place */
+ struct itree_t **uprel_itps; /* parallel to mod itps dest itree table */
+}; 
+
+/* global ref. info - master global rec. also used during simulation */
+struct gref_t {
+ unsigned upwards_rel : 1;    /* T => upwards relative form path */
+ unsigned is_upreltsk : 1;    /* T => upward rel and special just task name */
+ unsigned is_rooted : 1;      /* T => path starts at top module root */
+ unsigned path_has_isel : 1;  /* T => down or root path has inst arr select */
+ unsigned pathisel_done : 1;  /* T => for upward rel., grcmps fixed */
+ unsigned gr_inst_ok : 1;     /* T => xmr can be inst. maybe just 1 comp. */
+ unsigned gr_defparam : 1;    /* T => allow parameter as net tail */
+ unsigned gr_gone : 1;        /* T => for defparam processing - now gone */
+ unsigned gr_err : 1;         /* T => global is incorrect */
+ unsigned grfnam_ind : 16;    /* file location of ref. */
+ int32 grflin_cnt;            /* line location of ref. */
+ int32 last_gri;              /* last - 1 (1 before target) symbol in path */
+
+ char *gnam;                  /* name */
+ struct expr_t *gxndp;        /* back link to expr. node containing xmr */
+ struct expr_t *glbref;       /* original gref expr for inst. array eval. */
+ struct symtab_t *grsytp;     /* symtab where ref. appears */
+ struct mod_t *targmdp;       /* module target declared in */
+ struct task_t *targtskp;     /* if non NULL, task target declared in */
+ struct mod_t *gin_mdp;       /* place where gref used, for netchg prop. */
+ struct sy_t **grcmps;        /* table of path symbols (prep fixes ia sels) */
+ struct expr_t **grxcmps;     /* table of arr of inst path symbol sel exprs */
+ union targ_u targu;          /* up rel. itp list or rooted 1 target itp */
+ struct sy_t *targsyp;        /* actual end path symbol in target module */
+ struct gref_t *spltgrp;      /* ptr from split off grp back to original */
+ /* SJM 08/18/99 - now using gref tables no next */
+};
+
+/* symbol table - separate for each module */
+/* needs union here ? */
+struct symtab_t {
+ unsigned freezes : 1;
+ unsigned numsyms : 31;
+ struct tnode_t *n_head;
+ struct sy_t **stsyms;        /* non null means frozed form */
+ struct symtab_t *sytpar;     /* parent is enclosing scope */
+ struct symtab_t *sytsib;     /* sibling is disjoint32 same level scope */
+ struct symtab_t *sytofs;     /* offspring is list hdr of enclosed scopes */
+ struct sy_t *sypofsyt;       /* symbol this table is symbol table of */
+};
+
+/* list for saving timing check chk event changes for end of time slot */
+struct tc_pendlst_t {
+ struct chktchg_t *tc_chkchgp;
+ struct itree_t *tc_itp;
+ struct tc_pendlst_t *tc_plnxt;
+};
+
+union tchg_u {
+ struct tchk_t *chgtcp;
+ struct spcpth_t *chgpthp;
+};
+
+/* time of last chg net pin record - np from context, bit from npp rec. */
+struct tchg_t {
+ union tchg_u chgu;           /* union pointer to associated master */
+ byte *oldval;                /* per inst. old value of source bit */
+ word64 *lastchg;             /* per inst. last chg time for this 1 bit */
+};
+
+/* time check change record - access tchk record thru start change */
+struct chktchg_t {
+ struct tchg_t *startchgp;    /* corresponding start wire time change */
+ byte *chkoldval;
+ word64 *chklastchg;          /* per inst. last chg time for check event */
+};
+
+/* simulation per bit path delay element */
+struct pthdst_t {
+ struct tchg_t *pstchgp;      /* path src time change and indir. to path */ 
+ struct pthdst_t *pdnxt;      /* destination bit can have >1 sources */
+};
+
+/* one path elment */
+struct pathel_t {
+ int32 pthi1, pthi2;          /* specparam then index number value */
+ struct net_t *penp;          /* path input/out wire - NULL if removed */
+}; 
+
+/* work data struct for checking multiple same sdpds */
+struct xpnd_pthel_t {
+ unsigned in_equiv_set : 1;
+ struct spcpth_t *pthp;
+ int32 peii, peoi; 
+ struct xpnd_pthel_t *xpthnxt;
+};
+
+struct spcpth_t {
+ unsigned pthtyp : 2;         /* type of path (full or *>) */ 
+ unsigned pth_gone : 1;       /* must ignore because of serious error */
+ unsigned pth_as_xprs : 1;    /* T => fixup not done path els still exprs */
+ unsigned pth_delrep : 5;     /* delay representation for path */
+ unsigned pthpolar : 2;       /* simple path polarity (no sim meaning) */
+ unsigned pthedge : 8;        /* if edge, edge sensitive path */
+ unsigned dsrc_polar : 2;     /* if edge sensitive polarity */
+ unsigned pth_ifnone : 1;     /* T => condition is ifnone and other sdpds */
+ unsigned pth_0del_rem : 1;   /* T => removed from 0 delay */ 
+ struct sy_t *pthsym;         /* built symbol for identifying path */
+ int32 last_pein;
+ int32 last_peout;
+ struct pathel_t *peins;      /* array of path input elements */
+ struct pathel_t *peouts;     /* array of path output elements */
+ union del_u pth_du;          /* delay value */
+ struct expr_t *datasrcx;     /* non sim polarity expr, can be FCCOM list */
+ struct expr_t *pthcondx;     /* for if (cond) sdpd, the cond expr. */
+ struct spcpth_t *spcpthnxt;
+};
+
+/* timing check system task master record */
+struct tchk_t {
+ unsigned tchktyp : 8;        /* timing check type */
+ unsigned tc_delrep : 5;      /* limit delay type (will be same for both) */
+ unsigned tc_delrep2 : 5;     /* type of 2nd limit if present */ 
+ unsigned tc_gone : 1;        /* must ignore because of error */
+ unsigned tc_supofsuphld : 1; /* setup (added) part of setup hold */
+ unsigned tc_recofrecrem : 1; /* recovery (added) part of recrem */
+ unsigned tc_haslim2 : 1;     /* lim2 value present */
+ unsigned startedge : 8;      /* edge byte (pli 1 bit per rf coding) */
+ unsigned chkedge : 8;        /* edge byte (pli 1 bit per rf coding) */
+ struct sy_t *tcsym;          /* symbol with constructed name for del set */
+ struct expr_t *startxp;      /* event (reference) expr */
+ struct expr_t *startcondx;   /* &&& ref. event or edge path delay sel. */
+ struct expr_t *chkxp;        /* event (data - check) expr */
+ struct expr_t *chkcondx;     /* &&& data event or edge path delay sel. */
+ union del_u tclim_du;        /* 1st limit as delay */
+ union del_u tclim2_du;       /* 2nd optional limit as delay */
+ struct net_t *ntfy_np;       /* notify wire (known during fix up) */
+ struct tchk_t *tchknxt;      /* next in current specify block */
+};
+
+/* concatenation of all module specify items */
+struct spfy_t {
+ struct symtab_t *spfsyms;    /* specify symbol table for specparams */
+ struct spcpth_t *spcpths;    /* delay paths */
+ struct tchk_t *tchks;        /* timing checks */
+ struct net_t *msprms;        /* module's specify parameters */
+ int32 sprmnum;               /* number of specify parameters in table */
+};
+
+/* SJM 07/10/01 - d.s. for new delay net load propagation algorithm */
+/* for inter module paths, each src-dest pair has one of these */
+struct impth_t {
+ unsigned impth_delrep : 8;   /* delrep */
+ union del_u impth_du;        /* for inter mod non IS del for src/dst pair */
+ struct net_t *snp;           /* source net */
+ int32 sbi;                   /* and bit */
+ struct itree_t *sitp;        /* and itree loc */
+ word64 lastchg;              /* last chg time for this 1 pth bit of inst */
+ struct impth_t *impthnxt;    /* for || paths dst has >1 src with diff del */
+};
+
+/* mipd npp elnpp field points to per bit array mipd records */
+struct mipd_t {
+ unsigned no_mipd : 1;        /* T => no mipd delay for this bit */
+ unsigned pth_mipd : 1;       /* T => do not treat as src-dest inter mod pth */
+ unsigned pb_mipd_delrep : 5; /* bit's delay type */ 
+ union del_u pb_mipd_du;      /* bit's delay - max if src-dst impth */
+ byte *oldvals;               /* per inst array of old values */
+ i_tev_ndx *mipdschd_tevs;    /* per inst sched. event ndxes (-1 if none) */
+ struct impth_t **impthtab;   /* per inst inter mod src-dst pth ptr list */
+};
+
+struct srtmp_t {
+ int32 mppos;
+ struct mod_pin_t *smp;
+};
+
+/* top level n.l. entry points - this is a real user defined module */
+struct mod_t {
+ unsigned minstnum : 2;       /* static inst no. 0, 1, 2 (more than once) */
+ unsigned mhassts : 1;        /* T => module has strength wire(s) */
+ unsigned msplit : 1;         /* T => module created from defparam splitting */
+ unsigned mpndsplit : 1;      /* T => split off from # params */
+ unsigned mhassplit : 1;      /* T => modules split off from this one */
+ unsigned mgone : 1;          /* T => split from defparam but same params */
+ unsigned msplitpth : 1;      /* T => module comp. of split off chain */
+ unsigned mwiddetdone : 1;    /* T => mod width determing param marking done */
+ unsigned mhas_widthdet : 1;  /* T => module has width determin param */
+ unsigned mhas_indir_widdet : 1; /* T => module has indr width det param */
+ unsigned mgiarngdone : 1;    /* T => mod in array of g/i rng marking done */
+ unsigned mpndprm_ingirng : 1;/* T => module has pound param in gi range */ 
+ unsigned mpnd_girng_done : 1;/* T => gi rng pound param eval finished */
+ unsigned mhasisform : 1;     /* T => at least oe IS form constant in mod */
+ unsigned mtime_units : 4;    /* no. of significant units of time rounded */
+ unsigned mtime_prec : 4;     /* prec. - exp. 0 (1 sec.) - 15 (1 fs) */
+ unsigned mno_unitcnv : 1;    /* F => need for delay unit conv. */
+ unsigned m_iscell : 1;       /* T => module is asic style cell */
+ unsigned m_hascells : 1;     /* T => module contains asic style cells */
+ unsigned mod_hasdvars : 1;   /* T => for at least 1 inst. all vars dumped */
+ unsigned mod_dvars_in_src : 1;/* T => all vars dumpved in src */
+ unsigned mod_dumiact : 1;    /* T => dummy iact. info mod. */
+ unsigned mod_rhs_param : 1;  /* T => mod has param def with rhs param */ 
+ unsigned mod_hasbidtran : 1; /* T => has inout mod. port - tran chan */
+ unsigned mod_hastran : 1;    /* T => has tran gate - tran chan */
+ unsigned mod_gatetran : 1;   /* T => module has tran gate in it */
+ unsigned mod_has_mipds : 1;  /* T => mod has SDF or vpi_ only set mipds */  
+ unsigned mod_parms_gd : 1;   /* T => all dependent and pound params right */
+ unsigned mod_1bcas : 1;      /* T => contains 1 bit ca - special for vpi */
+ unsigned mod_lofp_decl : 1;  /* T => port decl uses list of ports form */ 
+ unsigned mod_dfltntyp : 4;   /* T => for vpi, from directive net dflt type */
+ unsigned mod_uncdrv : 8;     /* for vpi, mod val of unc drive directive */ 
+ unsigned m_inconfig : 1;     /* T => module is from a config file */
+ unsigned cfg_scanned : 1;    /* T => module has been scanned by config */
+ unsigned mhas_frcassgn : 1;  /* T => mod contains force/assign(s) */
+
+ int32 flatinum;              /* num. of flattened instances of module */
+ int32 mpnum;                 /* number of module ports */
+ int32 minum;                 /* number of instances in module */
+ int32 mgnum;                 /* number of gates in module */
+ int32 mcanum;                /* number of non 1 bit cas in module */ 
+ int32 mnnum;                 /* number of nets in module */  
+ int32 mtotvarnum;            /* total number of variables mod+task */
+ int32 mprmnum;               /* number of pound params defined */ 
+ int32 mlpcnt;                /* mod. inst. loop count (static level) */
+ struct sy_t *msym;           /* symbol from separate module name space */
+ int32 mod_last_lini;         /* line no. of end (mabye in next file) */
+ int32 mod_last_ifi;          /* and file in case spans multiple */
+ struct symtab_t *msymtab;    /* symbol table for objects in module */
+ struct cfglib_t *mod_cfglbp; /* config lib this mod's cells bound using */
+ struct mod_pin_t *mpins;     /* defined ports first list then arr. */
+ struct gate_t *mgates;       /* array of gates, udps and assigns */
+ struct giarr_t **mgarr;      /* parallel ptr array to mgates for gate arr. */
+ struct conta_t *mcas;        /* module cont. assigns */
+ struct inst_t *minsts;       /* array of module instance records */
+ struct giarr_t **miarr;      /* parallel ptr array to minst for inst arr. */
+ struct net_t *mprms;         /* local param definitions - list then tab */
+ struct net_t *mnets;         /* list then array of nets in module */
+ /* SJM 12/19/04 - only fixed ones from conn npin - vpi added malloced */
+ struct net_pin_t *mnpins;    /* table of all npins in module */
+ struct itree_t **moditps;    /* itnum to itree struct mapping table */
+ struct mod_t *mnxt;          /* next defined module */
+
+ /* new Verilog 2000 fields */
+ struct attr_t *mattrs;       /* mod attrs - used only if inst has no attr */
+ struct varinitlst_t *mvarinits; /* list of var (not net) init decls */
+ i_tev_ndx **mgateout_cbs;    /* per gate ptr to per inst list of vc cbs */
+
+ /* LOOKATME - these are compile only and can maybe be freed after fixup */
+ int32 mversno;               /* version number for split modules */
+ int32 lastinum;              /* while assigning inums - last used */
+ struct mod_t *mlevnxt;       /* link to next same level module */
+ struct mod_t *mspltmst;      /* pointer to defparam master if split off */
+ struct mod_t *mpndspltmst;   /* pointer to pound master if split off */
+ struct cell_t *mcells;       /* unordered list of module objects */
+ struct srtmp_t *smpins;      /* sorted table of module pins */
+ struct srcloc_t **iploctab;  /* || to insts ptr tab to tab of port locs */
+
+ struct dfparam_t *mdfps;     /* modules defparams */
+ struct task_t *mtasks;       /* tasks declared in module */
+ struct ialst_t *ialst;       /* initial/always list */
+ struct spfy_t *mspfy;        /* module's specify elements */
+ char *mndvcodtab;            /* table of dmpvar codes for all nets */
+
+ /* per module record tables - for optimized code and save/restart */
+ struct expr_t *mexprtab;     /* per mod table of expr. records */    
+ int32 mexprnum;              /* size of mod's expr tab */
+
+ struct st_t *msttab;         /* per mod table of mod stmts */
+ int32 mstnum;                /* size of mod's stmt tab */
+
+ struct gref_t *mgrtab;       /* list of xmr's appearing in this mod. */
+ int32 mgrnum;                /* number of grefs in module */
+};
+
+/*
+ * run time only structures
+ */
+/* doubly linked list of events for cancelling some */ 
+struct dltevlst_t {
+ i_tev_ndx tevpi;
+ struct dltevlst_t *telp, *terp;
+};
+
+/* singly linked list of events for cancel (short search from front) */ 
+struct tevlst_t {
+ i_tev_ndx tevpi;
+ struct tevlst_t *telnxt;
+};
+
+/* threads - because associated with an event, inst. specific */
+struct thread_t {
+ unsigned tsk_stouts : 1;     /* T => when task returns has outs to store */
+ unsigned th_dsable : 1;      /* thread done because disabled */
+ unsigned th_rhsform : 1;     /* T => rhs form so value in thread record */
+ unsigned th_fj : 1;          /* T => thread is fj - assoc. task is upward */
+ unsigned th_postamble : 1;   /* T => pending task needs end store/trace */
+ unsigned th_ialw : 1;        /* T => thread in initial/always list */
+ unsigned thofscnt : 24;      /* num of still active fork-join offspring */
+ word32 thenbl_sfnam_ind;     /* file index of place thread enabled from */
+ int32 thenbl_slin_cnt;       /* and line number */
+
+ struct st_t *thnxtstp;       /* next st. in thread to execute (resume pc) */
+ /* tree of 2 way linked sibling subthread lists */
+ struct thread_t *thpar;      /* thread that invoked this one */
+ struct thread_t *thright;    /* double linked same level right ptr */
+ struct thread_t *thleft;     /* double linked same level right ptr */
+ struct thread_t *thofs;      /* list of threads, enabled by this one */
+ struct tskthrd_t *tthlst;    /* ptr to this task assoc. thrd list el. */
+ i_tev_ndx thdtevi;           /* if thread has scheduled event, ndx of it */
+ struct task_t *assoc_tsk;    /* if created from task, connection to it */
+
+ struct delctrl_t *th_dctp;   /* if armed but not trig. ev ctrl, ptr to it */
+ word32 *th_rhswp;            /* for rhs delay/event controls, rhs value */  
+ int32 th_rhswlen;            /* word32 length of rhs value for disable */
+ struct itree_t *th_itp;      /* itree loc. thread runs in */
+ struct hctrl_t *th_hctrl;    /* for iact, pointer to control rec. */
+};
+
+union ten_u {
+ struct net_t *np;
+ struct mod_pin_t *mpp;
+};
+
+/* net bit or MIPD event storage - must be alloced and freed as used */
+struct tenp_t {
+ int32 nbi;
+ union ten_u tenu;
+};
+
+/* storage for scheduled but not matured non blocking assign event */ 
+struct tenbpa_t {
+ word32 *nbawp;
+ struct st_t *nbastp;
+ struct expr_t *nblhsxp;      /* if var ndx expr (maybe cat) const ndx copy */
+ struct delctrl_t *nbdctp;
+};
+
+/* tf strdelputp event storage - one schedule change (tev has instance) */
+struct tedputp_t {
+ struct tfrec_t *tedtfrp;
+ int32 tedpnum;
+ word32 *tedwp;               /* point to both half - know exact lhs word32 len */
+};
+
+/* vpi put value event storage (for both reg net driver assign */
+struct teputv_t { 
+ int32 nbi;
+ int32 di;                    /* for mult. drivers the ndx no. in table */
+ struct net_t *np;
+ word32 *putv_wp;
+ struct h_t *evnt_hp;         /* ptr back to event for cancelling */
+};
+
+union te_u {
+ struct thread_t *tethrd;
+ struct gate_t *tegp;
+ struct conta_t *tecap;
+ struct tenp_t *tenp;
+ struct tenbpa_t *tenbpa;
+ struct tfrec_t *tetfrec;
+ struct tedputp_t *tedputp;
+ struct teputv_t *teputvp; 
+ struct h_t *tehp;
+};
+
+struct tev_t {
+ unsigned tetyp : 5;
+ unsigned te_cancel : 1;      /* this event canceled */
+ unsigned nb_evctrl : 1;      /* for non blocking event is event control */
+ unsigned te_trdecay : 1;     /* event is trireg decay */
+ unsigned gev_acc : 1;        /* accelerated gate value assign */
+ unsigned vpi_reschd : 1;     /* T => vpi_ time cb moves to other slot part */
+ unsigned vpi_onfront : 1;    /* T => cb sim time start, add on fut. front */
+ unsigned vpi_regwir_putv : 1;/* T => putv to reg/wire soft force */
+ unsigned outv : 8;           /* for gate output value */
+ word64 etime;                /* absolute time not delay */
+ struct itree_t *teitp;       /* instance tree inst event executes in */
+ union te_u tu;
+ i_tev_ndx tenxti;
+};
+
+struct telhdr_t {
+ i_tev_ndx te_hdri, te_endi;
+ int32 num_events;
+};
+
+/* list element for pending net changes to process after event done */
+struct nchglst_t {
+ int32 delayed_mipd;          /* T - 2nd after schedule from ev process */
+ int32 bi1, bi2;
+ struct net_t *chgnp;
+ struct itree_t *nchg_itp;
+ struct nchglst_t *nchglnxt;
+};
+
+/* b tree (timing queue) structs */
+union bofs_u {
+ struct bt_t *btofs;
+ struct telhdr_t *telp;
+};
+
+struct bt_t {
+ unsigned bttyp : 8;
+ unsigned btnfill : 8;        /* no. of filled nodes in btree node */
+ word64 btltim;               /* time of highest left subtree */
+ union bofs_u ofsu;
+ struct bt_t *btnxt;
+};
+
+struct fbel_t {
+ struct fbel_t *fbnxt;
+};
+
+/* table of separate c funcs - usually only one unless too large */
+/* SJM ### ??? why is this not referenced? */
+struct cproc_t {
+ int32 cpnum;                 /* number c proc name suffix */
+ void (*funcptr)();           /* ptr to dlsym found c routine */ 
+ void *restabptr;             /* ptr to extrn in c resume label table */
+ int32 last_u32var;           /* highest num u32 var to decl in c proc */
+ struct cproctab_t *cptabnxt; 
+};
+
+struct contab_info_t {
+ int32 cwid;
+ int32 xvi;
+ struct contab_info_t *cnxt;
+};
+
+/* various simulation counting variables */
+extern char *__vers;          /* actual product info */
+extern char *__vers2;
+extern char *__ofdt;
+extern char *__platform;
+extern char *__start_sp, *__end_sp;/* pointer for "big" memory allocator */
+extern char *__pvdate;        /* date in unix form */
+extern char *__pv_timestamp;  /* timestamp for design */
+extern time_t __start_time;   /* start wall clock times in secs. */
+extern time_t __start_mstime; /* start millisecond part */
+extern time_t __end_comp_time;/* end of compilation time */
+extern time_t __end_comp_mstime;
+extern time_t __end_prep_time;/* end of preparation time */
+extern time_t __end_prep_mstime;
+extern time_t __end_time;     /* start and end wall clock times */
+extern time_t __end_mstime;   /* start and end wall clock times */
+
+/* various file variables and global data base flags (i/o vars) */
+extern char **__in_fils;      /* malloced input file list from args */
+extern int32 __siz_in_fils;   /* current size of input files */
+extern int32 __last_inf;      /* last input file in list */
+extern int32 __last_optf;     /* last option file */
+extern int32 __last_lbf;      /* last lib/inc file (starts last_inf + 1) */
+extern int32 __last_srcf;     /* last src containing file for debugger */
+extern struct incloc_t *__inclst_hdr; /* header of included files list */
+extern struct incloc_t *__inclst_end; /* end of included files list */
+extern struct filpos_t *__filpostab; /* in fils size tab of file line pos. */
+extern FILE *__save_log_s;    /* if $nolog executed, value to use if log */
+extern int32 __echo_iactcmds_tolog; /* T => echo interactive cmds to log file */
+extern FILE *__save_key_s;    /* if $nolog executed, value to use if log */
+extern int32 __nokey_seen;    /* $nokey executed and no key */
+extern FILE *__in_s;
+extern FILE *__log_s;
+extern FILE *__cmd_s;         /* command file source or null for tty */ 
+extern FILE *__key_s;         /* if key_s nil but key_fnam not, must open */
+extern struct optlst_t *__opt_hdr;   /* header of expanded option list */
+extern struct optlst_t *__opt_end;   /* wrk end of expanded option list */
+extern word32 *__wsupptab;    /* tab (1 bit/msg) for warn and iact suppress */
+extern char *__blnkline;      /* work blank line */
+extern char __pv_homedir[RECLEN]; /* home dir - . if HOME env. not set */
+extern struct mcchan_t __mulchan_tab[32];/* mc desc. tab (32 built in Ver) */ 
+extern struct fiofd_t **__fio_fdtab; /* array of ptrs to file io stream */
+extern char *__fiolp;         /* fio file input work string ptr */
+extern char *__fiofp;         /* fio file input work fmt string ptr */
+extern long __scanf_pos;      /* byte offset position of scanf in file */
+extern sighandler *__old_int_sig;  /* value of quit (^c) signal on entry */
+extern int32 __force_base;    /* for output force base if not BASENONE */
+extern struct vinstk_t **__vinstk;/* open file/macro list in stack form */
+extern struct vinstk_t *__visp;/* pointer to top of open input stack */
+extern int32 __vin_top;       /* index of top of current file stack */
+extern char *__log_fnam;      /* log file for all terminal output */
+extern char *__sdf_opt_log_fnam; /* sdf log file if set by cmd arg */
+extern FILE *__sdf_opt_log_s; /* and open file ptr */
+extern int32 __sdf_no_warns;  /* T => don't print any SDF warning msgs */
+extern int32 __sdf_no_errs;   /* T => don't print any SDF error msgs */
+extern int32 __sdf_from_cmdarg; /* T => SDF annotation call from cmd option */
+extern char *__cmd_fnam;      /* command interact. input file name */
+extern char *__cmd_start_fnam;/* -i startup interactive input file name */
+extern char *__key_fnam;      /* key file name and stream */
+extern FILE *__tr_s;          /* trace output file - can be stdout */
+extern char *__tr_fnam;
+extern int32 __cmd_ifi;       /* constant command in_fils index */
+extern char *__lic_path;      /* +licpath [path] if option used */
+extern FILE *__sdf_s;         /* current SDF back annotate file/stream */
+extern struct sdfnamlst_t *__sdflst; /* list of sdf annotate option files */
+extern int32 __sdf_sav_enum;  /* saved error num. for annotate inhibit */
+extern int32 __sdf_sav_maxerrs; /* saved max errors so won't stop */
+extern int32 __has_sdfann_calls;/* T => no sdf annotate systsk calls in src */ 
+extern int32 __sdf_active;    /* T => annotating SDF - for PLI erro code  */
+extern struct mod_t *__sdf_mdp; /* special sdf context mod */
+
+/* cfg variables */
+extern char *__cmdl_library;  /* library name to file off the command line */
+extern struct mapfiles_t *__map_files_hd; /* hdr of map files from cmd args */
+extern struct mapfiles_t *__map_files_tail; /* end of map file list */
+extern struct cfglib_t *__cfglib_hd; /* head of list of libs for cfg */
+extern struct cfglib_t *__cfglib_tail; /* and tail */
+extern struct cfg_t *__cfg_hd;/* head of list of cfgs */
+extern struct cfg_t *__cur_cfg;/* current cfg */
+extern struct mod_t *__cfg_mdp;/* SJM - remove me - why global */
+extern char **__bind_inam_comptab;/* during cfg binding, comp descent comps */ 
+extern int32 __siz_bind_comps;/* current malloc size of table */
+extern int32 __last_bind_comp_ndx;/* last currently used comp end index */ 
+extern int32 __cfg_verbose;   /* T => emit cfg reading verbose messages */ 
+
+/* file variables */
+extern int32 __cur_infi;      /* index in in_fils of current file */
+extern struct optlst_t *__new_opt_hdr;/* header of expanded option list */
+extern struct optlst_t *__new_opt_end;/* wrk end of expanded option list */
+extern struct optlst_t *__log_olp;   /* log option, nil if none */
+extern struct optlst_t *__help_olp;  /* help option, nil if none */
+extern struct optlst_t *__quiet_olp; /* quiet option, nil if none */
+extern struct optlst_t *__verb_olp;  /* verbose option, nil if none */  
+extern int32 __vpi_argc;      /* global arg count for vpi */
+extern char **__vpi_argv;     /* global arg array for vpi */
+extern char *__vpi_argv0;     /* argv execed program name */
+extern char *__cur_fnam;      /* being read file name for errors */
+extern int32 __cur_fnam_ind;  /* index in in_fils of cur_fnam */
+extern int32 __sfnam_ind;     /* global file index for current stmt. */
+extern int32 __slin_cnt;      /* global line no. for currently check stmt */
+extern int32 __vpifnam_ind;   /* vpi_ global current file index */
+extern int32 __vpilin_cnt;    /* vpi_ global current line no. */
+extern struct expr_t *__srm_xp; /* current string 'file' for sreadmem */
+extern char *__srm_strp;      /* char. pos. in sreadmem string */
+extern char *__srm_strp_beg;  /* work alloced location for sreadmem string */
+extern int32 __srm_strp_len;  /* alloced length */
+extern int32 __srm_stargi;    /* current string position number */
+extern int32 __in_ifdef_level;/* current processing `ifdef level */ 
+extern int32 __ifdef_skipping;/* T = skipping not included ifdef section */
+extern char *__langstr;       /* work string for `language */
+extern int32 __doing_langdir; /* T => processing `language directive */ 
+extern int32 __rding_top_level; /* T => reading outside top level construct */
+
+/* variables for batch tracing */
+extern word64 __last_trtime;  /* last trace statement time */
+extern word64 __last_evtrtime;/* last event trace time */
+extern struct itree_t *__last_tritp;/* last event traced inst. itree loc. */ 
+
+/* command processing variables and temps */
+extern int32 __pv_err_cnt, __pv_warn_cnt; /* error counts */
+extern int32 __inform_cnt;    /* number of informs */
+extern int32 __outlinpos;     /* current trunc. output line pos. */
+extern long __mem_use;        /* counts allocated mem for debugging */
+extern long __mem_allocated;  /* bytes allocated */
+extern long __mem_freed;      /* bytes freed */
+extern long __memstr_use;     /* counts allocated string mem for debugging */
+extern long __arrvmem_use;    /* allocated bytes for Verilog arrays */
+extern long __mem_udpuse;     /* number of bytes used by udp tables */
+extern word64 __tim_zero;     /* place for time of constant 0 */
+extern int32 __num_glbs;      /* total no. of globals in design */
+extern int32 __num_inmodglbs; /* glbs thar resolve to intra module refs. */
+extern int32 __num_uprel_glbs;/* number of upward relative globals */
+extern int32 __nets_removable;/* flat no. of deletable nets */
+extern int32 __flnets_removable;/* removable static nets */
+extern int32 __gates_removable; /* removable static gates */
+extern int32 __flgates_removable; /* flat no. of deletable gates */
+extern int32 __contas_removable; /* removabale static cont. assigns */
+extern int32 __flcontas_removable; /* flat no. of deletable cont. assigns */
+
+/* special allocate free variables */
+extern struct ncablk_t *__hdr_ncablks; /* blocks used for ncomp recs */
+extern int32 __ncablk_nxti;   /* index of next free pos. */
+extern struct cpblk_t *__hdr_cpblks; /* blocks used for cell recs*/
+extern int32 __cpblk_nxti;    /* index of next free pos. */
+extern struct cppblk_t *__hdr_cppblks; /* blocks used for cell pin recs*/
+extern int32 __cppblk_nxti;   /* index of next free pos. */
+extern struct tnblk_t *__hdr_tnblks;  /* blocks of symb table tree nodes */
+extern int32 __tnblk_nxti;    /* index of next free pos. */ 
+extern struct cpnblk_t *__hdr_cpnblks;  /* blocks of explicit cell pnames */
+
+/* source processing variables */
+extern int32 __lin_cnt;       /* line number while reading a file */
+extern int32 __saverr_cnt;    /* counter to inhibit more than a err in xpr */
+extern int32 __max_errors;    /* maximum errors before stopping */
+extern int32 __rding_comment; /* flag so comment non printable chars ok */
+extern int32 __total_rd_lines;/* total number of lines read */
+extern int32 __total_lang_dirs; /* total num `language directives read */
+
+/* booleans for program options (flags) */
+extern int32 __verbose;       /* T => emit various extra messages */
+extern int32 __quiet_msgs;    /* T => do not emit msgs just errors */
+extern int32 __no_warns;      /* T => don't print warning msgs */
+extern int32 __no_errs;       /* T => don't print error msgs */
+extern int32 __no_informs;    /* T => don't print inform msgs (dflt) */
+extern int32 __debug_flg;     /* T => turn on debugging output */
+extern int32 __opt_debug_flg; /* T => turn on vm compiler debugging output */
+extern int32 __st_tracing;    /* T => trace statement execution */
+extern int32 __ev_tracing;    /* T => trace event schedules and processes */
+extern int32 __pth_tracing;   /* T => trace path delays in detail */
+extern int32 __prt_stats;     /* T => print design statics tables */
+extern int32 __prt_allstats;  /* T => print design and mod content tabs */
+extern int32 __show_cancel_e; /* T => chg val to x on pulse cancelled event */
+extern int32 __showe_onevent; /* T => if showing cancel e, drive x on event */
+extern int32 __warn_cancel_e; /* T => emit warn cancel_e (indep. of cancel) */
+extern int32 __rm_gate_pnd0s; /* T => remove #0 from all gates */
+extern int32 __rm_path_pnd0s; /* T => (default) remove all 0 delay paths */
+extern int32 __dmpvars_all;   /* T => dumpvars all variables */
+
+/* command option booleans */
+extern int32 __lib_verbose;   /* T => emit src.file/lib source messages */
+extern int32 __sdf_verbose;   /* T => emit msgs for SDF annotated delays */
+extern int32 __switch_verbose;/* T => emit msgs for switch/tran chan build */
+extern int32 __chg_portdir;   /* T => chg port dir to bid. for XL compat */
+extern int32 __nb_sep_queue;  /* F => old un-seperated nb in pnd0 queue */
+extern int32 __decompile;     /* T => decompile and print Verilog source */
+extern int32 __compile_only;  /* T => check syntax (inc. lib.) no quads */
+extern int32 __parse_only;    /* T => first pass parse only to chk sep mod */
+extern int32 __dflt_ntyp;     /* Verilog wire type for normal nets */
+extern int32 __mintypmax_sel; /* for (e:e:e) expressions value to use */
+extern int32 __sdf_mintypmax_sel; /* min:nom_max over-ride for $sdf_annotate */
+extern int32 __gateeater_on;  /* T => attempt to remove (disconnect) gates */ 
+extern int32 __no_expand;     /* T => make all wire vectors vectored */
+extern int32 __in_cell_region;/* T => turn on cell bit for every module */
+extern int32 __unconn_drive;  /* if none TOK_NONE else PULL 0 or PULL 1 */
+extern int32 __no_specify;    /* T => check but no simulate with specify */
+extern int32 __no_tchks;      /* T => check but no simulate with tim chks */
+extern int32 __lib_are_cells; /* T => if in lib, the mark as cell (dflt.) */
+extern int32 __design_has_cells;/* T => cells somewhere in design */
+extern int32 __accelerate;    /* T => use short circuits g/prt code if can */
+extern int32 __pli_keep_src;  /* T => keep more source stmt info for pli */
+extern int32 __use_impthdels; /* T => use src-dst im path dels */
+
+/* source input variables and temps */
+extern char __lasttoken[IDLEN];/* current last pushed back symbol name */
+extern char __token[IDLEN];   /* current symbol (in canonical (lc) form) */
+extern int32 __toktyp;        /* place for current toktyp value */
+extern int32 __lasttoktyp;    /* push back token type (= UNDEF if none) */
+extern int32 __last_attr_prefix;/* push back pending attr prefix state */
+extern int32 __itoklen;       /* current number token bit length */
+extern int32 __itoksized;     /* T => token is sized */
+extern int32 __itokbase;      /* base constant for number token */
+extern int32 __itoksizdflt;   /* '[base] form with width (uses dflt.) */
+extern int32 __itok_signed;   /* T => token is signed number */
+extern double __itok_realval; /* actual scannoer double val */
+extern char *__strtoken;      /* growable token to hold string */
+extern int32 __strtok_wid;    /* current size of string token */    
+extern char *__numtoken;      /* growable token to hold numbers */
+extern int32 __numtok_wid;    /* current size of number token */    
+extern int32 __letendnum_state; /* T => letter can end unsized num. */
+extern int32 __macro_sep_width; /* T => possible beginning of macro 2 tok num */
+extern int32 __maybe_2tok_sized_num; /* T => seeing number after macro num */
+extern int32 __macro_sav_nwid;/* value of saved first tok width */
+extern int32 __first_linetok; /* T => token first on line */
+extern int32 __file_just_op;  /* T => new file and no token yet returned */
+extern int32 __first_num_eol; /* T => first tok because number ended line */
+extern char *__macwrkstr;     /* work string for macros */ 
+extern int32 __mac_line_len;  /* actual length of macro line in wrk str */   
+extern int32 __macwrklen;     /* allocated len of mac. work string */
+extern struct macarg_t *__macarg_hdr; /* hdr of list of format mac. args */
+extern int32 __macbs_flag;    /* T=> 8'h`DEFINE catch multiple bases errors */
+extern char *__attrwrkstr;    /* work string for attributes */
+extern int32 __attr_line_len; /* actual length of attribute string */ 
+extern int32 __attrwrklen;    /* alloced len of attr work string - grows */
+extern char *__attrparsestr;  /* string to parse attr out of */
+extern int32 __attrparsestrlen; /* string to parse attr out of */
+extern int32 __attr_prefix;   /* T => token has attribute prefix */
+extern int32 __attr_fnam_ind; /* location of attr inst. */
+extern int32 __attr_lin_cnt;  /* location of attr inst. */
+extern struct attr_t __wrk_attr; /* latest read attribute */
+extern char *__xs, *__xs2;    /* places to put expr to str trunc messages */
+extern int32 __pv_ctv;        /* tmp for white space skipping macros */
+extern int32 __syncto_class;  /* token class sync skipping halted at */
+extern char *__exprline;      /* expr. output line work string */
+extern int32 __exprlinelen;   /* expr. line length */
+extern int32 __cur_sofs;      /* ndx of next ofs (position) in expr line */
+extern word32 *__acwrk;       /* a value work string for scanning number */
+extern word32 *__bcwrk;       /* b value work string for scanning number */
+extern word32 __addrtmp[2];   /* up to 32 bit temp with addr. */
+extern int32 __abwrkwlen;     /* current acwrk a half length in words */
+extern char __portnam[IDLEN];
+extern char __pv_varnam[IDLEN]; /* variable name */
+extern int32 __expr_is_lval;  /* T => parsing proc. assign lhs */
+extern int32 __allow_scope_var; /* T => process systask arg can be scope */
+
+/* vars needed for pushing back numbers (see var. comment) */
+extern int32 __lastitokbase;
+extern int32 __lastitoksized;
+extern int32 __lastitoksizdflt;
+extern int32 __lastitok_signed;
+extern int32 __lastitoklen;
+extern word32 *__lastacwrk;   /* special malloced push back num value */
+extern word32 *__lastbcwrk; 
+extern double __lastitok_realval;
+
+/* the module and module subtask specific work variables */
+extern struct mod_t *__oinst_mod;/* ptr. to old current module for copying */
+extern struct mod_t *__end_mdp; /* end of module def. list */
+extern struct cell_t *__end_cp; /* end of module inst. list */
+extern int32 __cp_num;          /* counter for unnamed gate/inst pos. */ 
+extern struct conta_t *__end_ca; /* end of module conta list */
+extern int32 __conta_num;     /* counter for building symbol for conta */
+extern struct varinitlst_t *__end_mod_varinitlst; /* end of mod var inits */
+extern struct dfparam_t *__end_dfp;/* module current end of defparam list */
+extern struct task_pin_t *__end_tpp; /* end of task port list */
+extern struct task_t *__end_tbp;/* end of top level task/functions/blocks */
+extern struct task_t *__cur_tsk;/* ptr. to current task */
+extern struct net_t *__end_paramnp; /* end of ordered parm decl. list */
+extern struct net_t *__end_impparamnp; /* end of ordered imprt parm decl lst */
+extern struct net_t *__end_glbparamnp; /* end of ordered glb parm decl. lst */
+extern struct net_t *__end_tskparamnp; /* end of task param decl. list */
+extern struct ialst_t *__end_ialst; /* end of module initial/always list */
+extern struct gref_t *__grwrktab;  /* work table for building mod glbs */
+extern int32 __grwrktabsiz;        /* its size */
+extern int32 __grwrknum;      /* current number of glbs in work table */ 
+extern int32 __cur_declobj;   /* token type of declared mod or task */
+extern int32 __pv_stlevel;    /* tmp. for current stmt nesting level */
+extern int32 __design_no_strens;/* T => no strengths used in design */
+extern int32 __strenprop_chg; /* during propagate pass at least one chged */
+extern int32 __splitting;     /* T => in process of splitting module */
+extern int32 __processing_pnd0s;/* T => in time unit, in end #0 region */
+extern struct dce_expr_t *__cur_dce_expr; /* glb for edge events eval expr */
+extern int32 __lofp_port_decls; /* T => exclusive hdr port decls appeared */ 
+extern struct exprlst_t *__impl_evlst_hd; /* hdr of impl @(*) ev expr list */
+extern struct exprlst_t *__impl_evlst_tail; /* and its tail */
+extern int32 __canbe_impl_evctrl; /* glb switch to allow @(*) as ev ctrl */
+
+/* variables for dumpvars */
+extern int32 __dv_seen;       /* dumpvars seen but not yet setup */
+extern int32 __dv_state;      /* processing state of dumpvars */
+extern word64 __dv_calltime;  /* time dump var. first (and only) called */
+extern int32 __dv_dumplimit_size; /* user set limit of dv file size (0 none) */
+extern int32 __dv_file_size;  /* current size of dumpvars file */
+extern int32 __dv_time_emitted; /* flag to stop repeated same #[time] */
+extern char *__dv_fnam;       /* name of dumpvars output file */
+extern int32 __dv_func;       /* global set with type of dumpvar dumping */
+extern struct mdvmast_t *__dv_hdr; /* hdr of mast dumpvar rec. list */
+extern struct mdvmast_t *__dv_end; /* end of dumpvar rec. list */
+extern struct dvchgnets_t *__dv_netfreelst; /* free list of time var chges */
+extern int32 __dv_fd;         /* file number of dmpvars fd */
+extern char *__dv_buffer;     /* buffer to speed up dumpvars output */
+extern int32 __dv_nxti;       /* next free location */
+extern int32 __dv_outlinpos;  /* line postion in dump vars file */ 
+extern int32 __next_dvnum;    /* highest so far used dumpvars number */
+extern struct dvchgnets_t *__dv_chgnethdr;  /* curr. time var chg list hdr */
+extern int32 __dv_isall_form; /* T doing all of design dumpvar setup */
+extern int32 __dv_allform_insrc;/* T dumpvars all form in source */
+
+/* time scale - precision variables */
+extern word32 __cur_units;    /* current units (0 (1s) - 15 (1ft) */ 
+extern word32 __cur_prec;     /* current digits of precision (0-15) */
+extern word32 __des_timeprec; /* assume -, 0-15 design sim. tick prec. */
+extern word32 __tfmt_units;   /* %t output units (also interact. units) */
+extern word32 __tfmt_precunits;/* %t number of prec. digits */
+extern int32 __des_has_timescales;/* T => design has at least one timescale */
+extern char *__tfmt_suf;      /* suffix for %t */
+extern int32 __tfmt_minfwid;  /* minimum field width for %t */
+extern word64 __itoticks_tab[16];/* table of scales amount from prec. */
+extern char __timstr_unitsuf[4];/* to_timstr units suffix if needed */
+extern word64 __timstr_mult;  /* multiplier if needed */
+extern int32  __nd_timstr_suf;/* T => need to_timstr units */
+
+/* veriusertfs pli user function and task work variables */ 
+/* SJM 07/16/02 - need internal veriuser tfs for new +loadpli1 option */
+extern struct t_tfcell *__shadow_veriusertfs; /* internal copy of table */
+extern int32 __last_veriusertf; /* last user veriusertfs tf number */
+extern struct tfinst_t *__tfinst;/* current tf_ inst loc. */
+extern struct tfrec_t *__tfrec;/* current tf_ record */ 
+extern struct dceauxlst_t *__pvc_dcehdr; /* header of current pvc dces */
+extern struct tfrec_t *__tfrec_hdr; /* header of design wide tfrec list */ 
+extern struct tfrec_t *__tfrec_end; /* last el of design wide tfrec list */ 
+extern i_tev_ndx __tehdr_rosynci; /* hdr ndx of slot end ro sync ev lst */ 
+extern i_tev_ndx __teend_rosynci; /* end of slot end ro sync ev lst */ 
+extern int32 __now_resetting; /* reset in progress - for cbs and misctf */  
+extern int32 __rosync_slot;   /* T => processing tf or vpi  ro synch events */
+extern struct loadpli_t *__pli1_dynlib_hd; /* hd of ld pli1 dynamic lb list */
+extern struct loadpli_t *__pli1_dynlib_end; /* and its end */
+
+/* vpi_ work variables */
+extern int32 __last_systf;    /* last vpi_ registered sytfs number */
+extern int32 __num_vpi_force_cbs; /* number of registered vpi force cbs */
+extern int32 __vpi_force_cb_always; /* T => always call back on force */
+extern int32 __num_vpi_rel_cbs; /* number of registered vpi rel cbs */
+extern int32 __vpi_rel_cb_always; /* T => always call back on release */
+extern int32 __allforce_cbs_off; /* T => can't reenter any of all force cbs */
+extern int32 __allrel_cbs_off;/* T => can't reenter any of all release cbs */
+extern char *__wrks1;         /* work string - can not use xs if func */
+extern char *__wrks2;
+extern char __wrk_vpiemsg[IDLEN];/* error msg. work string */
+extern char __wrk_vpiget_str[IDLEN];/* standard required vpi get str string */
+extern char __wrk_vpi_product[256];/* product version */
+extern char __wrk_vpi_errcode[256];/* error codes are Cver err num as str */
+extern double __wrk_vpi_timedbl;/* time double for vpi error rec */
+extern char *__wrkvalbufp;    /* buf for vpi get value value_p contents */ 
+extern int32 __wrkval_buflen; /* and current length */
+extern int32 __vpi_vlog_start_done;/* T => startup done, no systf registering */
+extern struct systftab_t *__systftab; /* table of vpi_ systf records */
+extern int32 __size_systftab; /* current size of systf data rec. table */
+extern struct xstk_t *__cur_sysf_xsp; /* tmp stk_t for vpi sysf ret val */
+extern struct expr_t *__cur_sysf_expr;/* tmp calling expr. for vpi sysf*/
+extern struct st_t *__cur_syst_stp; /* tmp stmt for vpi syst*/
+extern struct dceauxlst_t *__cbvc_dcehdr; /* header of current vc cb dces */
+extern struct rfcblst_t *__rel_allcb_hdr;
+extern struct rfcblst_t *__rel_allcb_end;
+extern struct rfcblst_t *__force_allcb_hdr;
+extern struct rfcblst_t *__force_allcb_end;
+extern i_tev_ndx *__vpicb_tehdri; /* hdr of fixed cb tev list - 1 per class */
+extern i_tev_ndx *__vpicb_teendi; /* end of fixed cb tev list - 1 per class */
+extern int32 __have_vpi_actions;/* some use of __vpi actions */
+extern int32 __have_vpi_gateout_cbs;/* some use of gate out term cbs */
+extern struct h_t *__vpi_hfree_hdr;  /* handle free list hdr */ 
+extern struct hrec_t *__vpi_hrecfree_hdr;  /* handle record free list hdr */ 
+extern struct cbrec_t *__vpi_cbrec_hdr; /* all cbs list header */
+extern int32 __ithtsiz;       /* size of global work ld/drv handle table */
+extern struct h_t *__ithtab;  /* and the work ld/drv handle table */
+extern struct hrec_t *__ithrectab; /* and hrec contents of it */
+extern int32 __ithtsiz2;      /* size of global work ld/drv handle table */
+extern struct h_t *__ithtab2; /* 2nd work for in subtree handles */
+extern struct hrec_t *__ithrectab2; /* and hrec contents of it */
+extern struct vpisystf_t *__vpi_sysf_hdr; /* hdr sys func call src locs */
+extern struct vpisystf_t *__vpi_syst_hdr; /* hdr sys task enable src locs */
+extern int32 __in_vpi_errorcb;/* T => if sim ctrl, suppress error msg error */
+extern int32 __vpierr_cb_active; /* T => at least one cbError reged */
+extern int32 __acc_vpi_erroff;/* acc_ flag to stop internal acc_ error cbs */
+extern int32 __errorcb_suppress_msg; /* T => sim control suppress error msg */
+extern struct h_t *__cur_vpi_inst;
+extern struct hrec_t *__cur_vpi_obj;
+extern struct loadpli_t *__vpi_dynlib_hd; /* hd of ld vpi dynamic lib list */
+extern struct loadpli_t *__vpi_dynlib_end; /* and its end */
+
+/* specify work variables */
+extern struct spfy_t *__cur_spfy;/* current specify block */
+extern struct spcpth_t *__end_spcpths; /* end of specify path st. list */
+extern int32 __path_num;      /* counter for unnamed paths */
+extern struct tchk_t *__end_tchks;/* end of specify time check st. list */
+extern struct net_t *__end_msprms;/* end of specify specparam net list */
+extern struct tchk_t *__cur_tchk;
+extern int32 __tchk_num;      /* counter for unnamed paths */
+extern struct symtab_t *__sav_spsytp;/* save loc. of sym tab in spfy sect. */
+
+/* work compile global variables accessed by routines */
+extern int32 __v1stren;       /* wire/inst. Ver. 1 strength */
+extern int32 __v0stren;       /* wire/inst. Ver. 0 strength */
+extern word32 __pr_iodir;     /* glb. for port ref. expr. I/O direction */
+extern int32 __pr_wid;        /* global for total port ref. expr. width */
+extern int32 __mpref_explicit;/* T => mod def header port ref explicit */
+extern int32 __sym_is_new;    /* set when new symbol added */
+extern struct sy_t **__wrkstab;/* malloced work symbol table area */
+extern int32 __last_sy;       /* last symbol in work area */
+extern int32 __mod_specparams;/* number of declared specparams in mod */
+extern int32 __name_assigned_to;/* glb set if func. def. name assigned to */
+extern struct sy_t *__locfnamsyp; /* place for func. def. chk func. symbol */
+extern int32 __processing_func; /* T => prep or exec of function occuring */
+extern struct st_t **__nbstk; /* func. nest nblock stack (nxt for exec) */
+extern int32 __nbsti;      
+extern struct sy_t *__ca1bit_syp; /* gmsym for 1 bit conta converted gate */
+extern int32 __chking_conta;  /* T => checking a continuous assignment */
+extern int32 __rhs_isgetpat;  /* T => flag for checking stylized getpat */
+extern int32 __lhs_changed;   /* T => assignment changed lhs */
+extern word32 __badind_a;     /* place for a part of in error index value */
+extern word32 __badind_b;     /* and for b part */
+extern int32 __badind_wid;    /* width for bad ind (<32 expr can eval to x) */
+extern int32 __expr_has_real; /* T => know some real in expr. */
+extern int32 __isform_bi_xvi; /* glbl for IS net pin bit index in contab */
+extern int32 __lhsxpr_has_ndel; /* T => component wire of lhs has wire del */
+extern int32 __checking_only; /* T => no error msg, looking for something */ 
+extern int32 __task_has_tskcall;/* T => task calls other task (not name blk) */
+extern int32 __task_has_delay;/* T => task call has del. needs thread */
+extern int32 __func_has_fcall;/* T => func contains has non sys fcall */
+extern int32 __iact_must_sched; /* T => iact stmt(s) have $stop or loop */
+extern int32 __expr_rhs_decl; /* T current expr. is decl. not proc. rhs */ 
+extern int32 __chg_rng_direct;/* T => change rng dir. for implicitly decl */
+extern int32 __has_top_mtm;   /* T => for parameter rhs non () m:t:m */
+extern int32 __nd_0width_catel_remove; /* fx3 file 0 width concat glb */
+
+/* current Verilog module/task/block symbol environment */
+extern struct symtab_t **__venviron;
+extern int32 __top_sti;
+extern struct symtab_t *__modsyms;/* separate symbol table for type names */
+extern struct symtab_t *__pv_defsyms;/* global table for `defines */
+extern struct symtab_t *__syssyms;/* global tab for system tasks and funcs */
+extern struct sy_t **__glbsycmps; /* work global name symbols */
+extern struct expr_t **__glbxcmps;/* work glbal exprs */
+extern int32 __last_gsc;
+
+/* n.l. access headers and tables */
+extern struct mod_t *__modhdr;/* header of top level module list */
+extern struct udp_t *__udphead; /* header udps */
+extern struct udp_t *__udp_last;/* end udp list */
+extern struct inst_t **__top_itab; /* tab of virt inst ptrs of top mods */
+extern int32 *__top_ipind;    /* binary searchable top insts index */
+extern int32 __numtopm;       /* number of uninstanciated top modules */
+extern struct itree_t **__it_roots; /* table of root itree entries */
+extern int32 __ualtrepipnum;  /* udp rep. change threshold */
+extern struct thread_t *__initalw_thrd_hdr; /* list hd of per inst in/al thds */
+extern struct tev_t *__tevtab;/* reallocable tab of events and free evs */
+extern int32 __numused_tevtab;/* num used at least once in tev tab */
+extern int32 __size_tevtab;   /* num tev's allocated in tev tab */ 
+extern word32 *__contab;      /* design wide constant table */
+extern int32 __contabwsiz;    /* currrent size of const tab in words */
+extern int32 __contabwi;      /* next free word32 slot in const tab */
+extern int32 __opempty_contabi; /* special contab ndx for opempty expr leaf */
+extern struct contab_info_t **__contab_hash; /* contab hash information */
+
+/* n.l. access routines */  
+extern struct dfparam_t *__dfphdr; /* design wide defparam list header */
+extern int32 __num_dfps;      /* number of defparams in source */
+extern int32 __num_glbdfps;   /* number of defparams in design */
+extern int32 __num_locdfps;   /* number of local defparams */
+extern int32 __num_inst_pndparams;/* static number of inst. pound params */
+extern int32 __design_gia_pndparams;/* T => at least one gia range pnd params */
+extern int32 __design_gi_arrays;  /* T => design has arrays of g/i */ 
+extern int32 __pndparam_splits; /* T => at least one split from pound params */
+extern int32 __defparam_splits; /* T => at least one split from def params */
+extern int32 __dagmaxdist;    /* max. nested mod. inst. level */
+extern struct mod_t **__mdlevhdr; /* array of ptrs to ith lev linked mods */ 
+extern struct cell_pin_t *__cphdr;   /* header of temp. cell pin list */
+extern struct cell_pin_t *__cpp_last;/* current last cell pin*/
+extern struct tnode_t *__tmp_head;
+
+extern struct xldlnpp_t *__xldl_hdr; /* other side unproc. xl drv/ld npps */
+extern struct xldlnpp_t *__last_xldl;/* end of list - place to add after */
+extern struct xldlvtx_t **__xldlvtxind; /* table of xl drv/ld net/bit vtx */
+extern int32 __num_xldlvtxs;  /* number of lements in table */
+extern int32 __siz_xldlvtxtab;/* current size of table */
+
+/* udp table building variables */
+extern struct wcard_t *__wcardtab; /* level wildcard table */
+extern int32 __last_wci;      /* last wild card index for line */
+extern word32 *__cur_utab;    /* current udp table */
+extern struct utline_t *__cur_utlp; /* current line info struct */
+extern word32 __cur_uoval;    /* current udp line output value */
+extern int32 __cur_unochange; /* T => cur line has '-' no change output */
+extern struct udp_t *__cur_udp; /* current udp struct */
+extern word32 __cur_upstate;  /* current last input (state) for wide */
+extern int32 __cur_ueipnum;   /* cur. input pos. num of edge (NO_VAL none) */
+extern int32 __cur_utabsel;   /* current edge 1st char - 2nd in state line */
+
+/* expression and function processing variables */
+extern int32 __xndi;          /* next place in collected expression list */
+extern struct expr_t **__exprtab;/* table to collect expressions into */
+extern struct expridtab_t **__expr_idtab; /* expr parse id name info */ 
+extern int32 __exprtabsiz;    /* current operator precedence expr tab siz */
+extern int32 __last_xtk;
+extern struct expr_t *__root_ndp;/* root of built and alloced expression */
+extern struct xstk_t **__xstk;/* expr work vals */
+extern int32 __xspi;          /* expr. pointer */
+extern int32 __maxxnest;      /* current size of expr. stack - must grow */ 
+extern int32 __maxfcnest;     /* size of func. call task stk - must grow */
+extern struct task_t **__fcstk; /* function call nesting stack */
+extern int32 __fcspi;           /* fcall tos index */
+
+/* -y and -v library variables */
+extern struct vylib_t *__vyhdr; /* header of lib. file list */
+extern struct vylib_t *__end_vy;/* last entry on vy lib. list */
+extern int32 __num_ylibs;     /* number of ylibs in options */
+extern int32 __num_vlibs;     /* number of vlibs in options */
+
+extern struct undef_t *__undefhd;/* head of undefined mod/udp list */   
+extern struct undef_t *__undeftail; /* tail of undefined mod/udp list */
+extern int32 __undef_mods;    /* count of undefined modules */
+
+extern int32 __lib_rescan;    /* T => rescan from start after each */
+extern int32 __cur_passres;   /* num mods resolved in current pass */
+extern int32 __rescanning_lib;/* T => for `language exclude after 1st pass */ 
+extern int32 __num_ys;        /* number of -y options in lib. */
+extern char **__lbexts;       /* tab of -y library extension suffixes */
+extern int32 __last_lbx;
+extern char **__incdirs;      /* tab of +incdir paths (always / end) */
+extern int32 __last_incdir;
+
+/* simulation preparation variables */
+extern int32 __cur_npii;      /* current index of inst. in cur. mod */
+extern struct gate_t *__cur_npgp;/* current net-pin processing gate */
+extern struct mod_t *__cur_npmdp;/* current net-pin processing module */
+extern struct conta_t *__cur_npcap; /* current net pin proc. conta */
+extern struct tfrec_t *__cur_nptfrp; /* current net pin tf arg drvr rec */
+extern struct net_t *__cur_npnp; /* current net pin net for vpi putv driver */
+extern int32 __cur_npnum;     /* current port number (from 0) */
+extern int32 __cur_pbi;       /* current bit number for PB ICONN npp */
+extern int32 num_optim_cats;  /* number of optimized concats */
+extern int32 num_optim_catels;/* number of all elements in optim concats */
+extern int32 __cur_lhscati1;  /* if lhs concat, high rhs psel index */
+extern int32 __cur_lhscati2;  /* if lhs concat, low rhs psel index */
+extern struct st_t **__prpstk;/* during prep., continue stp */
+extern int32 __prpsti;        /* top of nested stmt. stack */
+extern int32 __nd_parmpnp_free; /* T => after 1st parmnpp need copy not orig */
+extern int32 __num_rem_gate_pnd0s; /* number of removed source #0 gates */
+extern int32 __num_flat_rem_gate_pnd0s; /* and flat number */
+extern int32 __num_rem_mipds; /* number of per bit flat MIPDs 0 delays rmed */
+extern int32 __last_modxi;    /* global counter used by n.l expr xform code */
+extern int32 __last_modsti;   /* and counter for statements */
+extern int32 __optimized_sim; /* generate c code - compile and dl link */
+extern int32 __dump_flowg;    /* dump flow graph for debugging */
+
+/* timing queue scheduling variables */
+extern word64 __whetime;      /* current timing wheel end time */
+extern word64 __simtime;      /* current simulaton time (make 64 bits ?) */
+extern word32 __num_execstmts;/* total number of executed statements */
+extern word32 __num_addedexec;/* number of executed added statements */
+extern word32 __num_proc_tevents;/* total num simulation events processed */
+extern word32 __nxtstmt_freq_update; /* next ev count for xbig freq upd. */ 
+extern word32 __num_cancel_tevents; /* total num sim events processed */
+extern int32 __num_twhevents; /* num of evs currently in timing wheel */
+extern int32 __num_ovflqevents; /* num of events currently in ovflow q */
+extern word32 __inertial_cancels; /* num resched form later inertial del */
+extern word32 __newval_rescheds; /* num rescheduled for same time */
+extern word32 __num_netchges; /* num of processed net change records */
+extern word32 __immed_assigns;/* num immed assign (not scheduled) */ 
+extern word32 __proc_thrd_tevents;/* number of processed thread events */
+extern struct q_hdr_t *__qlist_hdr; /* for $q_ system task q list header */
+extern int32 __num_switch_vtxs_processed; /* total num tranif chan vtx done */
+extern int32 __num_switch_chans; /* total num tranif channels in design */ 
+
+/* storage tables variables */
+extern byte *__btab;          /* design wide scalar (byte) storage table */
+extern int32 __btabbsiz;      /* scalar storage byte table size in bytes */
+extern int32 __btabbi;        /* during var init next index to use */ 
+extern byte *__nchgbtab;      /* table for per inst nchg bytes */
+extern int32 __nchgbtabbsiz;  /* size in btab of nchg action bits */
+extern int32 __nchgbtabbi;    /* during init, next index to use */
+extern word32 *__wtab;        /* design wide var but not mem storage area */
+extern int32 __wtabwsiz;      /* precomputed size (need ptrs into) in words */
+extern int32 __wtabwi;        /* during var init next index to use */ 
+
+/* simulation control and state values */
+extern int32 __stmt_suspend;  /* set when behavioral code suspends */
+extern int32 __run_state;     /* state of current simulation run */
+extern int32 __can_exec;      /* T => for vpi sim ctrl - can now exec */
+extern int32 __wire_init;     /* T => initializing wires */
+extern int32 __no_tmove_levels; /* T => infinite 0 delay loop warn path dist */
+extern struct thread_t *__cur_thd;  /* currently executing thread addr. */
+extern struct thread_t *__suspended_thd; /* cur thread before suspend */
+extern struct itree_t *__suspended_itp; /* cur inst ptr before suspend */
+extern struct itree_t *__inst_ptr; /* current if flattened itree place */ 
+extern struct mod_t *__inst_mod;   /* module of current itree inst */
+extern int32 __inum;          /* iti num  of current inst (always set) */
+extern struct itree_t **__itstk; /* stack of saved itrees */
+extern int32 __itspi;         /* top of itree stack */
+extern i_tev_ndx __fsusp_tevpi;/* in func. step, event to undo(cancel) */
+extern struct itree_t *__tmpitp_freelst; /* free list of wrk itps */
+extern struct inst_t *__tmpip_freelst; /* free list of wrk ips */
+extern struct mod_t *__last_libmdp; /* libary module just read */
+extern int32 __seed;          /* SJM 01/27/04 - glb seed needed if no arg */
+
+/* execution state variables */
+extern word32 __new_gateval;  /* new gate out val (st. possible) */
+extern word32 __old_gateval;  /* before gate change (st. possible) */
+extern word32 __new_inputval; /* new input value for tracing message */
+extern word32 __old_inputval; /* prev. value of input for wide udp eval */
+extern word64 __pdlatechgtim; /* for path tracing latest path chg time */
+extern word64 __pdmindel;     /* for path minimum path delay */
+extern int32 __nd_neg_del_warn; /* T => must emit warn (or err) for <0 del */ 
+extern int32 __force_active;  /* T => for trace deassign while force */ 
+extern int32 __assign_active; /* T => for trace release activates assgn */
+extern struct dceauxlst_t *__qcaf_dcehdr; /* header of current qcaf dces */
+extern int32 __nxt_chan_id;   /* cnter and size for assigning chan ids */
+extern int32 __chanallocsize; /* size of allocated chan tables */
+extern struct chanrec_t *__chantab;/* tab of channel records (one per id) */
+extern struct vtxlst_t *__stvtxtab[8]; /* per stren value vertex list */ 
+extern struct vtxlst_t *__stvtxtabend[8]; /* and ptr to last el on each */
+extern struct vtxlst_t *__chg_vtxlst_hdr; /* list of chged vertices to store */
+extern struct vtxlst_t *__chg_vtxlst_end; /* and ptr to end */
+extern struct vtxlst_t *__off_vtxlst_hdr; /* bid chan vtx list for marks off */
+extern struct vtxlst_t *__off_vtxlst_end; /* and ptr to end */
+extern struct vtxlst_t *__vtxlst_freelst; /* free list for vtx lists */
+extern struct vtx_t *__vtx_freelst;  /* free list for re-using vtxs */   
+extern struct edge_t *__edge_freelst; /* free list for re-using edges */
+
+extern word32 __acum_sb;      /* accumulator for stren tran chan combined */
+extern word32 __acum_a;       /* accumulator for tran chan non stren */
+extern word32 __acum_b;
+extern byte *__acum_sbp;      /* ptr to stacked strength byte */
+extern struct xstk_t *__acum_xsp; /* ptr to stacked strength byte */
+
+/* end of time slot variables, strobe, monitor, time check */
+extern struct strblst_t *__strobe_hdr; /* list strobe display at slot end */
+extern struct strblst_t *__strobe_end; /* end of strobe display list */
+extern struct strblst_t *__strb_freelst; /* head of free strobe elements */
+extern struct st_t *__monit_stp;/* monit if chg display at slot end stmt */
+extern struct itree_t *__monit_itp; /* current monitor itree element */
+extern word32 __slotend_action; /* word32 of 1 bit switches set for action */
+extern int32 __monit_active;  /* T => monitor can trigger (default) */
+extern struct dceauxlst_t *__monit_dcehdr; /* header of current dces */
+extern struct fmonlst_t *__fmon_hdr; /* list of execed (enabled) fmonitors */
+extern struct fmonlst_t *__fmon_end;
+extern struct fmonlst_t *__cur_fmon; /* current fmon list entry */
+extern struct fmselst_t *__fmonse_hdr; /* this slot end fmon eval list */
+extern struct fmselst_t *__fmonse_end;
+extern struct fmselst_t *__fmse_freelst; /* fmon slot end free list head */
+
+/* interactive execution variables */
+extern struct itree_t *__scope_ptr; /* from $scope itree place */
+extern struct task_t *__scope_tskp; /* from $scope task if present */ 
+extern struct symtab_t *__last_iasytp; /* last found symbol symbol table */
+extern struct iahist_t *__iahtab;/* table of history commands */
+extern int32 __iahsiz;        /* current size of history cmd table */
+extern int32 __iah_lasti;     /* current (latest) command */
+extern struct hctrl_t *__hctrl_hd; /* head of active iact stmts */
+extern struct hctrl_t *__hctrl_end;/* and end */
+extern int32 __history_on;    /* collecting and saving history is on */
+extern int32 __hist_cur_listnum;/* number to list for :history command */
+extern int32 __iasetup;       /* F until interactive entered */
+extern int32 __ia_entered;    /* F (also for reset) until iact entered */
+extern int32 __iact_state;    /* T => in interactive processing */
+extern int32 __iact_can_free; /* T => non monitor/strobe, can free */
+extern int32 __no_iact;       /* T => no interactive processing for run */
+extern int32 __intsig_prt_snapshot; /* T => on no iact end, print shapshot */
+extern int32 __reset_count;   /* count of the number of rests ($reset) */
+extern int32 __reset_value;   /* 2nd $reset value preserved after reset */ 
+extern int32 __list_cur_ifi;  /* index in in fils of current source file */
+extern int32 __list_cur_fd;   /* current opened file no. (-1 if none) */
+extern int32 __list_cur_lini; /* current line no. in current dbg file */
+extern int32 __list_cur_listnum;/* number of lines to list at once */
+extern int32 __list_arg_lini; /* for :b (:ib), user list argument */
+extern int32 __iact_scope_chg;/* T => always move scope to cur on iact st. */
+extern struct brkpt_t *__bphdr;/* header of breakpoint list */ 
+extern int32 __nxt_bpnum;     /* next breakpoint number to use */
+extern struct dispx_t *__dispxhdr;/* header of display list */ 
+extern int32 __nxt_dispxnum;  /* next display number to use */
+extern struct itree_t *__last_stepitp;/* last step inst. itree loc. */ 
+extern struct task_t *__last_steptskp;/* last step task */
+extern int32 __last_stepifi;  /* last step in fils index */
+extern word64 __last_brktime; /* last break or step time */
+extern int32 __dbg_dflt_base; /* :print debugger default base */ 
+extern int32 __iact_stmt_err; /* T => syntax error for iact stmt */
+extern struct mod_t *__iact_mdp; /* current iact dummy module */
+extern int32 __sav_mtime_units; /* prep of iact statements needs tfmt units */
+
+/* interactive variables */
+extern char *__iahwrkline;    /* interactive command line work area */
+extern int32 __iahwrklen;     /* allocated len of iah work string */
+extern int32 __pending_enter_iact;/* T => enter iact as soon as can */
+extern int32 __iact_reason;   /* reason for entering interactive state */
+extern int32 __single_step;   /* T => need to single step */
+extern int32 __step_rep_cnt;  /* number of times to repeat step */
+extern int32 __step_from_thread;/* T step from non thread loc. (^c?) */
+extern struct itree_t *__step_match_itp; /* for istep, exec itp must match */
+extern int32 __step_lini;     /* line stepping from (must step to next) */  
+extern int32 __step_ifi;      /* and file */ 
+extern int32 __verbose_step;  /* T => emit location each step */
+extern int32 __stop_before_sim; /* T => enter interactive before sim */
+extern int32 __dbg_stop_before; /* if >100, T (-100) stop before sim */ 
+extern struct st_t *__blklast_stp; /* stmt loc. saved last stmt in block */
+extern struct dceauxlst_t *__iact_dcehdr; /* header of current iact dces */
+
+/* event list variables */
+extern struct telhdr_t **__twheel;
+extern int32 __twhsize;       /* current size for timing wheel */   
+extern int32 __cur_twi;
+extern i_tev_ndx __p0_te_hdri;/* pound 0 event list header */
+extern i_tev_ndx __p0_te_endi;/* pound 0 event list end */
+extern i_tev_ndx __cur_te_hdri;
+extern i_tev_ndx __cur_tevpi; /* ptr to event list for adding to front */
+extern i_tev_ndx __cur_te_endi;
+extern i_tev_ndx __tefreelsti;/* free list for events */
+extern struct tedputp_t *__tedpfreelst; /* tf_ putp rec free list header */
+extern struct teputv_t *__teputvfreelst; /* vpi_ put value free list hdr */ 
+extern struct nchglst_t *__nchgfreelst; /* change element free list */
+extern struct tc_pendlst_t *__tcpendfreelst; /* free slot end changed tchks */
+extern struct dltevlst_t *__dltevfreelst; /* pend double event free list */
+extern struct tevlst_t *__ltevfreelst; /* pend event free list */
+extern i_tev_ndx __nb_te_hdri; /* non-blocking new end queue hd */ 
+extern i_tev_ndx __nb_te_endi; /* and tail */
+
+/* net change list variables */
+extern struct nchglst_t *__nchg_futhdr; /* header of future net chg list */
+extern struct nchglst_t *__nchg_futend; /* end (for add) of future net chgs */
+extern struct tc_pendlst_t *__tcpendlst_hdr; /* header of pending */ 
+extern struct tc_pendlst_t *__tcpendlst_end; /* end of pending */
+extern i_tev_ndx *__wrkevtab; /* for exit, trace of pending events */
+extern int32 __last_wevti;    /* last filled */
+extern int32 __size_wrkevtab; /* and current allocated size */ 
+
+/* b tree variables */
+extern struct bt_t *__btqroot;/* root of timing overflow q */
+/* for fringe node, node previous to place where inserted */
+/* storage for path to fringe - node passed thru if not fringe */
+extern struct bt_t **__btndstk; /* nodes with node list length */
+extern struct bt_t **__btndhdrstk;
+extern int32 __topi;
+extern int32 __max_level;
+extern int32 __nd_level;
+
+
+#include "systsks.h"
diff --git a/src/v_acc.c b/src/v_acc.c
new file mode 100644
index 0000000..b8f0d19
--- /dev/null
+++ b/src/v_acc.c
@@ -0,0 +1,8709 @@
+/* Copyright (c) 1998-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * module to implement pli acc routines
+ */
+
+/*
+ * CONVENTION: assumption here is that vpi_ objects and acc_ objects
+ * are all pointers to struct h_t and can be cast between each other 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <stdarg.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+#include "veriuser.h"
+#include "cv_veriuser.h"
+#include "acc_user.h"
+#include "cv_acc_user.h"
+
+/* LOOKATME - maybe move to include file */
+#define ACCSTRBUFSIZ 65536    /* size of reused str buf (must be 4k) */   
+
+#define ACCMAPTOMIP_MAX 0
+#define ACCMAPTOMIP_MIN 1
+#define ACCMAPTOMIP_LAST 2
+
+#define ACCTOHIZ_AVG 0
+#define ACCTOHIZ_MAX 1
+#define ACCTOHIZ_MIN 2
+#define ACCTOHIZ_FROMUSER 3
+
+struct vpi_to_acc_t {
+ int32 vpiotyp;
+ int32 acc_otyp;
+};
+
+struct accnam_t {
+ char *accnam;
+ int32 accval;
+};
+
+/* two way list (so can release) of active acc iterators */
+struct acciter_t {
+ struct h_t *aiter;
+ struct acciter_t *aiternxt;
+ struct acciter_t *aiterprev;
+};
+
+/* user data field for vpi_ val change call backs with acc_ vcl record */
+struct vclrec_t {
+ unsigned vclflg : 8;         /* user passed vcl flag */
+ unsigned vcl_oldstval : 8;   /* old stren val not vpi for chg of val only */
+ unsigned vcl_reason : 8;     /* object determined change reason */
+ handle vclobj;               /* acc_ handle of object vcl on */
+ int32 (*vcl_cb_rtn)();         /* acc_ vcl call back routine */
+ char *vcl_udata;             /* user's user data (not vpi_ cb) */
+ struct cbrec_t *vclcbp;      /* internal cver cbrec */
+};
+
+/* internal acc varaible declarations */ 
+char *__acc_strbuf;           /* ptr to reused acc_ str buf */ 
+int32 __acc_strbuf_nxti;        /* next free ndx - gets rewound */
+int32 __acc_open;               /* T => acc initialize routine called */
+int32 __acc_scope_set;          /* T => acc scope changed from call tf inst */
+vpiHandle __acc_scope_vpiobj; /* currently set acc_ scope as vpi objec */
+
+/* need separate work tables for acc_ since sometimes call vpi iterators */
+/* that may reuse normal ith word32 tables */ 
+int32 __aithtsiz;               /* size of acc work handle table */
+struct h_t *__aithtab;        /* and the work handle table */
+struct hrec_t *__aithrectab;  /* and hrec contents of it */
+int32 __aithtsiz2;             /* size of acc 2nd work handle table */
+struct h_t *__aithtab2;      /* 2nd work for in subtree handles */
+struct hrec_t *__aithrectab2;/* and hrec contents of it */
+
+/* indexed by vpi type table of active acc iters (next and collect) */
+struct acciter_t **__aiter_tab; /* table by vpi type of acc next iters */
+struct acciter_t *__last_aiter; /* for count/collect need last */
+struct acciter_t *__aiter_freelst;
+struct acciter_t *__aiter_accnxt_list; /* list for all acc next (no type) */
+
+/* configure parameter variables - see P1364 acc LRM chapter */
+int32 __acc_pathdelaycount;
+char *__acc_pathdelimstr;
+int32 __acc_displayerrors;
+int32 __acc_defaultattr0;
+int32 __acc_tohizdelay;
+int32 __acc_enableargs_pth;
+int32 __acc_enableargs_tchk;
+int32 __acc_enableargs_setscope;
+int32 __acc_displaywarnings;
+char *__acc_developmentversion;
+int32 __acc_maptomipd;
+int32 __acc_mintypmaxdelays;
+
+/* declaration (definition) of acc_user variables */
+bool acc_error_flag;
+
+/* acc extern prototypes */
+extern bool acc_append_delays(handle object, ...);
+extern bool acc_append_pulsere(handle object, double val1, double val1x, ...);
+extern void acc_close(void);
+extern handle *acc_collect(handle (*p_next_routine)(), handle scope_object,
+ int32 *aof_count);
+extern bool acc_compare_handles(handle h1, handle h2);
+extern int32 acc_count(handle (*next_function)(), handle object_handle);
+extern bool acc_configure(int32 item, char *value);
+extern int32 acc_fetch_argc(void);
+extern void **acc_fetch_argv(void);
+extern double acc_fetch_attribute(handle object, ...);
+extern int32 acc_fetch_attribute_int(handle object, ...);
+extern char *acc_fetch_attribute_str(handle object, ...);
+extern char *acc_fetch_defname(handle object_handle);
+extern int32 acc_fetch_delay_mode(handle object_p);
+extern bool acc_fetch_delays(handle object, ...);
+extern int32 acc_fetch_direction(handle object_handle);
+extern int32 acc_fetch_edge(handle acc_object);
+extern char *acc_fetch_fullname(handle object_handle);
+extern int32 acc_fetch_fulltype(handle object_h);
+extern int32 acc_fetch_index(handle object_handle);
+extern double acc_fetch_itfarg(int32 n, handle tfinst);
+extern int32 acc_fetch_itfarg_int(int32 n, handle tfinst);
+extern char *acc_fetch_itfarg_str(int32 n, handle tfinst);
+extern int32 acc_fetch_location(p_location location_p, handle object);
+extern char *acc_fetch_name(handle object_handle);
+extern int32 acc_fetch_paramtype(handle param_p);
+extern double acc_fetch_paramval(handle param);
+extern int32 acc_fetch_polarity(handle path);
+extern int32 acc_fetch_precision(void);
+extern bool acc_fetch_pulsere(handle path_p, double *val1r,
+ double *val1e, ...);
+extern int32 acc_fetch_range(handle node, int32 *msb, int32 *lsb);
+extern int32 acc_fetch_size(handle obj_h);
+extern double acc_fetch_tfarg(int32 n);
+extern int32 acc_fetch_tfarg_int(int32 n);
+extern char *acc_fetch_tfarg_str(int32 n);
+extern void acc_fetch_timescale_info(handle obj,
+ p_timescale_info aof_timescale_info);
+extern int32 acc_fetch_type(handle object_handle);
+extern char *acc_fetch_type_str(int32 type);
+extern char *acc_fetch_value(handle object_handle, char *format_str,
+ p_acc_value acc_value_p);
+extern void acc_free(handle *array_ptr);
+extern handle acc_handle_by_name(char *inst_name, handle scope_p);
+extern handle acc_handle_condition(handle obj);
+extern handle acc_handle_conn(handle term_p);
+extern handle acc_handle_datapath(handle path);
+extern handle acc_handle_hiconn(handle port_ref);
+extern handle acc_handle_interactive_scope(void);
+extern handle acc_handle_itfarg(int32 n, handle tfinst);
+extern handle acc_handle_loconn(handle port_ref);
+extern handle acc_handle_modpath(handle mod_p, char *pathin_name,
+ char *pathout_name, ...);
+extern handle acc_handle_notifier(handle tchk);
+extern handle acc_handle_object(char *object_name);
+extern handle acc_handle_parent(handle object_p);
+extern handle acc_handle_path(handle source, handle destination);
+extern handle acc_handle_pathin(handle path_p);
+extern handle acc_handle_pathout(handle path_p);
+extern handle acc_handle_port(handle mod_handle, int32 port_num);
+extern handle acc_handle_scope(handle object);
+extern handle acc_handle_simulated_net(handle net_h);
+extern handle acc_handle_tchk(handle mod_p, int32 tchk_type,
+ char *arg1_conn_name, int32 arg1_edgetype, ...);
+extern handle acc_handle_tchkarg1(handle tchk);
+extern handle acc_handle_tchkarg2(handle tchk);
+extern handle acc_handle_terminal(handle gate_handle, int32 terminal_index);
+extern handle acc_handle_tfarg(int32 n);
+extern handle acc_handle_tfinst(void);
+extern bool acc_initialize(void);
+extern handle acc_next(int32 *type_list, handle h_scope, handle h_object);
+extern handle acc_next_bit(handle vector, handle bit);
+extern handle acc_next_cell(handle scope, handle cell);
+extern handle acc_next_cell_load(handle net_handle, handle load);
+extern handle acc_next_child(handle mod_handle, handle child);
+extern handle acc_next_driver(handle net, handle driver);
+extern handle acc_next_hiconn(handle port, handle hiconn);
+extern handle acc_next_input(handle path, handle pathin);
+extern handle acc_next_load(handle net, handle load);
+extern handle acc_next_loconn(handle port, handle loconn);
+extern handle acc_next_modpath(handle mod_p, handle path);
+extern handle acc_next_net(handle mod_handle, handle net);
+extern handle acc_next_output(handle path, handle pathout);
+extern handle acc_next_parameter(handle module_p, handle param);
+extern handle acc_next_port(handle ref_obj_p, handle port);
+extern handle acc_next_portout(handle mod_p, handle port);
+extern handle acc_next_primitive(handle mod_handle, handle prim);
+extern handle acc_next_scope(handle ref_scope_p, handle scope);
+extern handle acc_next_specparam(handle module_p, handle sparam);
+extern handle acc_next_tchk(handle mod_p, handle tchk);
+extern handle acc_next_terminal(handle gate_handle, handle term);
+extern handle acc_next_topmod(handle topmod);
+extern bool acc_object_of_type(handle object, int32 type);
+extern bool acc_object_in_typelist(handle object, int32 *type_list);
+extern int32 acc_product_type(void);
+extern char *acc_product_version(void);
+extern int32 acc_release_object(handle obj);
+extern bool acc_replace_delays(handle object, ...);
+extern bool acc_replace_pulsere(handle object, double val1r,
+ double val1x, ...);
+extern void acc_reset_buffer(void);
+extern bool acc_set_interactive_scope(handle scope, int32 callback_flag);
+extern bool acc_set_pulsere(handle path_p, double val1r, double val1e);
+extern char *acc_set_scope(handle object, ...);
+extern int32 acc_set_value(handle obj, p_setval_value setval_p,
+ p_setval_delay delay_p);
+extern void acc_vcl_add(handle object_p, int32 (*consumer)(), char *user_data,
+ int32 vcl_flags);
+extern void acc_vcl_delete(handle object_p, int32 (*consumer)(),
+ char *user_data, int32 vcl_flags);
+extern char *acc_version(void);
+extern int32 __primtermprop_vpiget(struct h_t *, int32);
+extern char *__to_sytyp(char *, word32);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern char * __get_eval_cstr(struct expr_t *, int32 *);
+
+/* local prototypes */
+static int32 str_truefalse(char *);
+static int32 legal_delimstr(char *);
+static struct h_t *find_acc_attr_param(struct h_t *, char *, char *);
+static struct net_t *tryfnd_param(char *, struct symtab_t *, char *, char *); 
+static void init_acc_config(void);
+static int32 bld_accnext_iter(int32 *, handle);
+static int32 nd_modscope(struct h_t *);
+static int32 nd_anyscope(struct h_t *);
+static int32 cellinst_addto_iter(vpiHandle, int32, int32);
+static void acc_internal_itfree(struct h_t *);
+static int32 var_addto_iter(vpiHandle, int32, int32);
+static int32 param_addto_iter(vpiHandle, int32, int32);
+static int32 prim_addto_iter(vpiHandle, int32, int32, int32);
+static handle portbit_accnext(handle, handle);
+static void linkout_aiter(struct acciter_t *, int32, int32);
+static void linkout_accnext_aiter(struct acciter_t *);
+static handle netbit_accnext(handle, handle);
+static struct acciter_t *find_aiter_rec(register struct acciter_t *,
+ struct h_t *); 
+static vpiHandle bld_acc_cells_iter(struct h_t *);
+static int32 collect_loc_insts(struct h_t *);
+static int32 addto_acc_cells_iter(struct h_t *, int32, int32);
+static handle do_acc_next_ld_drv(char *, handle, handle);
+static int32 map_acc_delaymode_to_vpi(int32);
+static char *get_acc_delmode_nam(char *, int32);
+static int32 fill_vpival_fromacc(struct t_vpi_value *, struct t_setval_value *);
+static int32 chk_add_del_vclobj(char *, struct h_t **, int32 (*)(), char *);
+static int32 set_vcl_reason(struct net_t *, int32);
+static struct vclrec_t *findmatch_net_vcl_dce(struct h_t *, int32 (*)(), char *);
+static struct vclrec_t *findmatch_term_vcl_dce(struct h_t *, int32 (*)(),
+ char *);
+static int32 exec_acc_vclcb(struct t_cb_data *);
+static int32 exec_acc_gateout_vclcb(struct t_cb_data *);
+static int32 map_to_accvclval(word32);
+static int32 map_vpi_to_accvclval(word32);
+static int32 map_vpi_to_accval(word32);
+static int32 map_acc_to_vpival(word32);
+static int32 map_vpi_to_accstren(word32);
+static vpiHandle bld_cell_load_iter(struct h_t *);
+static vpiHandle bld_driver_iter(struct h_t *);
+static handle do_acc_next_hilo_conn(char *, handle, handle, int32);
+static vpiHandle bld_load_iter(struct h_t *);
+
+
+static vpiHandle rem_ins_from_iter(struct mod_t *, vpiHandle); 
+
+static char *add_accstrbuf(char *);
+static char *get_cfgconst_nam(char *, int32);
+static struct vpi_to_acc_t *get_acc_typerec(struct h_t *);
+static vpiHandle get_acc_current_systf(char *);
+static int32 get_systf_acc_expr_val(int32, struct expr_t *, s_vpi_value *,
+ struct h_t *, char *);
+static int32 fr_accfmt_to_vpifmt(int32);
+static char *to_accfmtnam(char *, int32);
+static int32 copy_vpival_to_accval(s_setval_value *, s_vpi_value *, int32);
+static handle get_systf_accargobj(struct h_t *, int32, struct expr_t *, char *);
+static int32 get_acc_fulltype(vpiHandle, struct vpi_to_acc_t *);
+static char *get_accnam(int32);
+static void acc_not_sim_err(char *);
+static int32 validate_acc_handle(char *, struct h_t *); 
+extern int32 __validate_otyp(word32);
+static char *to_acc_onam(char *, word32);
+static void wrong_nxtobj_error(char *, int32, int32);
+static struct acciter_t *alloc_aiter(void);
+static void init_aiter(struct acciter_t *);
+static handle do_acc_child_topmod(char *, handle);
+static int32 exec_acc_set_delays(struct h_t *, int32, va_list);
+
+/* extern prototypes (maybe defined in this module) */
+extern char *__my_malloc(int32);
+extern char *__my_realloc(char *, int32, int32);
+extern void __my_free(char *, int32);
+extern char *__to_vpionam(char *, word32);
+extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern vpiHandle __mk_exprclass_handle(struct expr_t *, struct itree_t *,
+ struct task_t *);
+extern char *__to_vvstnam(char *, word32);
+extern int32 __map_frvpi_stren(int32);
+extern int32 __name_vpi_hasdot(char *);
+extern vpiHandle __mk_handle(word32, void *, struct itree_t *,
+ struct task_t *);
+extern void __free_iterator(vpiHandle);
+extern word32 __to_vpi_tasktyp(word32);
+extern word32 __gate_to_vpiprimtyp(struct gate_t *);
+extern void __bld_vpi_argv(void);
+extern void __init_hrec(struct hrec_t *);
+extern void __grow_acc_htab(int32);
+extern void __grow_acc_htab2(int32);
+extern char *__to_timstr(char *, word64 *);
+extern struct pviter_t *__alloc_iter(int32, vpiHandle *);
+extern void __cberror_fill_einfo(int32, int32, char *, char *, int32);
+extern void __vpi_error_trycall(void);
+extern word32 __map_tovpi_stren(word32);
+extern int32 __v64_to_real(double *, word64 *);
+extern void __free_hp(struct h_t *); 
+extern void __call_misctfs_scope(void);
+extern int32 __my_vpi_chk_error(void);
+extern int32 __chk_showobj(struct h_t *, int32 *, int32 *);
+
+/* misc extern prototypes */
+extern void __pv_terr(int32, char *, ...);
+extern void __my_fprintf(FILE *, char *, ...);
+extern void __my_vfprintf(FILE *, char *, va_list, va_list);
+
+extern void __acc_err(int32, char *fmt, ...);
+extern void __acc_sferr(int32, char *fmt, ...);
+extern void __acc_warn(int32, char *fmt, ...);
+extern void __acc_sfwarn(int32, char *, ...);
+extern void __acc_terr(char *, int32);
+extern void __acc_vpi_terr(char *, int32);
+
+static struct vpi_to_acc_t vpi_to_acc[];
+
+/* extern word32 __masktab[]; */
+
+/*
+ * EXTRA ACC INTIALIZATION ROUTINES
+ */
+
+/*
+ * initialize acc when Cver starts (not after acc close)
+ *
+ * cver acc_ setup during simulation startup - acc_initialize and 
+ * acc_close not needed - acc_close does free all handles
+ *
+ * LOOKATME - is an error call back needed
+ */
+extern void __init_acc(void)
+{
+ register int32 aii;
+
+ __acc_open = FALSE;
+ acc_error_flag = FALSE;
+ __acc_scope_set = FALSE;
+ __acc_scope_vpiobj = NULL;
+ __aiter_freelst = NULL;
+
+ /* set up string buffer */
+ if (__acc_strbuf == NULL) __acc_strbuf = __my_malloc(ACCSTRBUFSIZ);
+ __acc_strbuf_nxti = 0; 
+
+ /* always setup acc_next tables */ 
+ __aiter_tab = (struct acciter_t **)
+  __my_malloc((TOPVPIVAL + 1)*(sizeof(struct acciter_t *)));
+ for (aii = 0; aii <= TOPVPIVAL; aii++) __aiter_tab[aii] = NULL;
+ __last_aiter = NULL;
+ __aiter_accnxt_list = NULL;
+
+ __aithtsiz = 0;
+ __aithtab = NULL;
+ __aithrectab = NULL;
+ __aithtsiz2 = 0;
+ __aithtab2 = NULL;
+ __aithrectab2 = NULL;
+
+ /* must call init acc config in case user doesn't */ 
+ init_acc_config();
+}
+
+/*
+ * ACC_ ROUTINES IN ALPHABETICAL ORDER
+ */
+
+/*
+ * append (add to) delays - acc style just wrapper for vpi put delays
+ * with append flag set
+ */
+/*VARARGS*/
+extern bool acc_append_delays(handle object, ...)
+{
+ int32 rv;
+ va_list va;
+
+ va_start(va, object);
+ rv = exec_acc_set_delays((struct h_t *) object, TRUE, va);
+ va_end(va);
+ return(rv);
+}
+
+/*
+ * appende pulse handling limits
+ * notice these never array form 
+ *
+ * FIXME - simulator needs to support these
+ */
+/*VARARGS*/
+extern bool acc_append_pulsere(handle object, double val1, double val1x, ...)
+{
+ struct h_t *hp;
+ struct hrec_t *hrp;
+ 
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object; 
+ if (!validate_acc_handle("acc_append_pulsere", hp)) return(0); 
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiModPath && hrp->htyp != vpiPort
+  && hrp->htyp != vpiPortBit)  
+  {
+   __acc_err(1764, "acc_append_pulsere: object %s illegal - path required",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(0);
+  }
+ __acc_warn(2052,
+  "acc_append_pulsere no effect - pulse limits not stored by tool");
+ return(1);
+}
+
+/*
+ * close acc - end acc routines to not interfere with other acc apps 
+ */
+extern void acc_close(void)
+{
+ if (!__acc_open)
+  {
+   __acc_warn(2047, "acc_close: acc_initialize was not called");
+  }
+
+ /* reset string buffer */
+ /* LOOKATME - probably not needed */
+ __acc_strbuf_nxti = 0;
+ 
+ /* reset acc configuration parameters to defaults */
+ init_acc_config();
+ __acc_open = FALSE;
+ acc_error_flag = FALSE;
+ /* LOOKATME - must leave all next state to match XL */
+ /* LOOKATME - more to do??? */
+}
+
+/*
+ * collect iterator into an array of handle (outside of iterator)
+ *
+ * uses normal next object with nil to build iterator 
+ * finds iterator from last var, then copies into array
+ * finally frees iterator
+ *
+ * need fence NULL at end so know how many to free
+ * array of handles has no place to store size
+ */
+extern handle *acc_collect(handle (*p_next_routine)(), handle scope_object,
+ int32 *aof_count)
+{
+ register int32 hi;
+ int32 isize;
+ struct h_t *hp, *hp2, *hp3, *hp4;
+ struct acciter_t *aip;
+ struct pviter_t *iterp; 
+ vpiHandle *htabref;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) scope_object;
+ if (hp != NULL)
+  { if (!validate_acc_handle("acc_collect", hp)) return(NULL); }
+
+ if (p_next_routine == acc_next_topmod)
+  {
+   __acc_err(1995,
+    "acc_collect: acc_next_topmod illegal p_next_routine - use acc_next_child with NULL mod_handle"); 
+   return(NULL);
+  }
+
+ /* get first which builds iterator */
+ hp2 = (struct h_t *) (*(p_next_routine))(scope_object, NULL);
+ /* will always return nil on error and emit error message */ 
+ if (hp2 == NULL) return(NULL);
+
+ /* know iterator just constructed always pointed to by this */
+ aip = __last_aiter;
+ hp3 = aip->aiter;
+ iterp = hp3->hrec->hu.hiterp;
+ isize = iterp->numhs;
+ htabref = (vpiHandle *) __my_malloc((isize + 1)*sizeof(vpiHandle));
+ /* need to copy handles because may need to copy non bith exprs */
+
+ for (hi = 0; hi < isize; hi++)
+  {
+   __acc_vpi_erroff = TRUE;
+   hp4 = (struct h_t *) vpi_copy_object((vpiHandle) &(iterp->scanhtab[hi]));
+   htabref[hi] = (vpiHandle) hp4;
+   /* this access error vpi_ error info and turns off vpi error cbs */  
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1953, "acc_collect error building collected handle array");
+     __my_free((char *) htabref, isize*sizeof(vpiHandle));
+     htabref = NULL;
+     *aof_count = 0;
+     goto do_free;
+    }
+  }
+ htabref[isize] = NULL;
+
+do_free:
+ /* LOOKATME - here think always must free - guts copied no longer needed */
+ linkout_aiter(aip, hp2->hrec->htyp, FALSE);
+ *aof_count = isize;
+ return((handle *) htabref);
+}
+
+/*
+ * compare acc handle that are really just vpi_ objects
+ */
+extern bool acc_compare_handles(handle h1, handle h2)
+{
+ int32 rv;
+ struct h_t *hp1, *hp2; 
+
+ acc_error_flag = FALSE;
+
+ hp1 = (struct h_t *) h1; 
+ hp2 = (struct h_t *) h2; 
+ if (!validate_acc_handle("acc_compare_handles(first)", hp1))
+  return(FALSE); 
+ if (!validate_acc_handle("acc_compare_handles(second)", hp2))
+  return(FALSE); 
+
+ __acc_vpi_erroff = TRUE;
+ rv = vpi_compare_objects((vpiHandle) h1, (vpiHandle) h2);
+
+ /* this access error vpi_ error info and turns off vpi error cbs */  
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1954,
+    "acc_compare_handles error during compare (handles %s or %s corrupted?)",
+    to_acc_onam(__wrks1, hp1->hrec->htyp),
+    to_acc_onam(__wrks2, hp2->hrec->htyp));
+   return(FALSE);
+  }
+ return(rv);
+}
+
+/*
+ * configure acc configureation parameter to value value 
+ */
+extern bool acc_configure(int32 item, char *value)
+{
+ int32 boolval, dnum;
+
+ acc_error_flag = FALSE;
+ switch (item) {
+  case accDefaultAttr0:
+   if ((boolval = str_truefalse(value)) == -1)
+    {
+bad_true_false:
+     __acc_err(1950,
+      "acc_configure configuration item %s %s illegal value - must be \"true\" or \"false\"",
+      get_cfgconst_nam(__xs, item), value);
+     return(FALSE);
+    }
+   __acc_defaultattr0 = boolval;
+   break;
+  case accDevelopmentVersion:
+   if (__acc_developmentversion != NULL)
+    __my_free(__acc_developmentversion, strlen(__acc_developmentversion) + 1);
+   __acc_developmentversion = __my_malloc(strlen(value) + 1);
+   strcpy(__acc_developmentversion, value);
+   break;
+  case accDisplayErrors:
+   if ((boolval = str_truefalse(value)) == -1) goto bad_true_false;
+   __acc_displayerrors = boolval;
+   break;
+  case accDisplayWarnings:
+   if ((boolval = str_truefalse(value)) == -1) goto bad_true_false;
+   __acc_displaywarnings = boolval;
+   break;
+  case accEnableArgs:
+   if (strcmp(value, "acc_handle_modpath") == 0) __acc_enableargs_pth = TRUE;
+   else if (strcmp(value, "no_acc_handle_modpath") == 0)
+     __acc_enableargs_pth = FALSE;
+   else if (strcmp(value, "acc_handle_tchk") == 0)
+    __acc_enableargs_tchk = TRUE;
+   else if (strcmp(value, "no_acc_handle_tchk") == 0)
+    __acc_enableargs_tchk = FALSE;
+   else if (strcmp(value, "acc_set_scope") == 0)
+    __acc_enableargs_setscope = TRUE;
+   else if (strcmp(value, "no_acc_set_scope") == 0)
+    __acc_enableargs_setscope = FALSE;
+   else
+    {
+     __acc_err(1943,
+      "acc_configure accEnableArgs configuration value %s illegal",
+      value);
+     return(FALSE);
+    }
+   break;
+  case accMapToMipd:
+   if (strcmp(value, "max") == 0) __acc_maptomipd = ACCMAPTOMIP_MAX;
+   else if (strcmp(value, "min") == 0) __acc_maptomipd = ACCMAPTOMIP_MIN;
+   else if (strcmp(value, "latest") == 0) __acc_maptomipd = ACCMAPTOMIP_LAST;
+   else
+    {
+     __acc_err(1943,
+      "acc_configure accMapToMipd configuration value %s illegal", value);
+     return(FALSE);
+    }
+   break;
+  case accMinTypMaxDelays:
+   if ((boolval = str_truefalse(value)) == -1) goto bad_true_false;
+   if (boolval)
+    {
+     __acc_warn(2051,
+      "acc_configure accMinTypMaxDelays same delay for all three - option selects the one value");
+    }
+   __acc_mintypmaxdelays = boolval;
+   break;
+  case accPathDelayCount:
+   if (sscanf(value, "%d", &dnum) != 1)
+    {
+bad_delcnt:
+     __acc_err(1943,
+      "acc_configure accPathDelayCount configuration value %s illegal - one of \"1\", \"2\", \"3\", \"6\", \"12\" required",
+      value);
+     return(FALSE);
+    }
+   if (dnum != 1 && dnum != 2 && dnum != 3 && dnum != 6 && dnum != 12)
+    goto bad_delcnt;
+   __acc_pathdelaycount = dnum;
+   break;
+  case accPathDelimStr:
+   if (!legal_delimstr(value))
+    {
+     __acc_err(1945,
+      "acc_configure accPathDelimStr configuration value %s illegal Verilog identifier",
+      value);
+     return(FALSE);
+    }
+   if (__acc_pathdelimstr != NULL)
+    __my_free(__acc_pathdelimstr, strlen(__acc_pathdelimstr) + 1);
+   __acc_pathdelimstr = __my_malloc(strlen(value) + 1);
+   strcpy(__acc_pathdelimstr, value);
+   break;
+  case accToHiZDelay:
+   if (strcmp(value, "average") == 0) __acc_tohizdelay = ACCTOHIZ_AVG;
+   else if (strcmp(value, "max") == 0) __acc_tohizdelay = ACCTOHIZ_MAX;
+   else if (strcmp(value, "min") == 0) __acc_tohizdelay = ACCTOHIZ_MIN;
+   else if (strcmp(value, "from_user") == 0)
+    __acc_tohizdelay = ACCTOHIZ_FROMUSER;
+   else
+    {
+     __acc_err(1943,
+      "acc_configure accToHiZDelay configuration value %s illegal", value);
+     return(FALSE);
+    }
+   break;
+  default:
+   __acc_err(1944, "acc_configure parameter item value %d illegal", item);
+   return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * check a string true/false value (returns -1 on error)
+ */
+static int32 str_truefalse(char *s)
+{
+ if (strcmp(s, "true") == 0 || strcmp(s, "TRUE") == 0) return(TRUE);
+ else if (strcmp(s, "false") == 0 || strcmp(s, "FALSE") == 0) return(FALSE);
+ return(-1);
+} 
+
+/*
+ * return T if path delimiter string legal - else F
+ */
+static int32 legal_delimstr(char *s)
+{
+ register char *chp;
+
+ for (chp = s; chp != '\0'; chp++)
+  {
+   if (*chp == '$' || *chp == '_' || isalnum(*chp)) continue;
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * count number of objects acc_collect would return
+ *
+ * same as acc_collect but no allocating and copying of handle array 
+ */
+extern int32 acc_count(handle (*next_function)(), handle object_handle)
+{
+ int32 isize;
+ struct acciter_t *aip;
+ struct pviter_t *iterp;
+ struct h_t *hp, *hp2, *hp3;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object_handle;
+ if (hp != NULL)
+  { if (!validate_acc_handle("acc_collect", hp)) return(0); }
+
+ if (next_function == acc_next_topmod)
+  {
+   __acc_err(1995,
+    "acc_count: acc_next_topmod illegal next_function routine - use acc_next_child with NULL mod_handle"); 
+   return(0);
+  }
+
+ /* get first which builds iterator */
+ hp2 = (struct h_t *) (*(next_function))(object_handle, NULL);
+ /* will always return nil on error and emit error message */ 
+ if (hp2 == NULL) return(0);
+
+ /* know iterator just constructed always pointed to by this */
+ aip = __last_aiter;
+ hp3 = aip->aiter;
+ iterp = hp3->hrec->hu.hiterp;
+ isize = iterp->numhs;
+
+ /* done with iterator free */ 
+ /* LOOKATME - here think always must free - iterator needed only or size */
+ linkout_aiter(aip, hp2->hrec->htyp, FALSE);
+ return(isize);
+}
+
+/*
+ * ACC FETCH ROUTINES IN ALPHABETICAL ORDER EXCEPT TFARG TOGETHER
+ */
+
+/*
+ * get processed (-f are ** argv) argument count
+ */
+extern int32 acc_fetch_argc(void)
+{
+ acc_error_flag = FALSE;
+ /* know error can't happen here */
+ if (__vpi_argv == NULL) __bld_vpi_argv();
+ return(__vpi_argc); 
+}
+
+/*
+ * get processed (-f are ** argv) argument list ptr
+ *
+ * LOOKATME - is this really void?
+ */
+extern void **acc_fetch_argv(void)
+{
+ acc_error_flag = FALSE;
+ /* know error can't happen here */
+ if (__vpi_argv == NULL) __bld_vpi_argv();
+ return((void **) __vpi_argv); 
+}
+
+/*
+ * get acc_ style attribute value as real
+ * attr is param or specparam value where name matches
+ */
+/*VARARGS*/
+extern double acc_fetch_attribute(handle object, ...)
+{
+ struct h_t *hp, *rhp;
+ double d1;
+ va_list va;
+ s_vpi_value tmpval;
+ char *attrstr;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object; 
+ if (!validate_acc_handle("acc_fetch_attribute", hp)) return(0.0); 
+
+ va_start(va, object);
+ attrstr = va_arg(va, char *);
+
+ if ((rhp = find_acc_attr_param(hp, attrstr, "acc_fetch_attribute")) == NULL)
+  {
+ret_def:
+   /* T return 0.0 - ignore any possible pass default value */
+   if (__acc_defaultattr0) return(0.0);
+   /* F return user passed default attribute value */
+   d1 = va_arg(va, double);
+   va_end(va);
+   return(d1);
+  }
+ /* access object value as real */
+ __acc_vpi_erroff = TRUE;
+ tmpval.format = vpiRealVal; 
+ vpi_get_value((vpiHandle) rhp, &tmpval);
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1956,
+    "acc_fetch_attribute: error accessing real value for attribute %s",
+    rhp->hrec->hu.hnp->nsym->synam);
+   goto ret_def;
+  }
+ va_end(va);
+ return(tmpval.value.real);
+}
+
+/*
+ * find attribute matching parameter - NULL if not found
+ * passed attribute and ref. object, returns param as h_t if found else nil 
+ */
+static struct h_t *find_acc_attr_param(struct h_t *hp, char *anam, char *rtnam)
+{
+ int32 sav_acc_disperrs;
+ struct mod_t *mdp;
+ struct net_t *np;
+ struct h_t *rhp;
+ char *chp, sname[2*IDLEN];
+
+ /* make handle for object's module (inst) */
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+
+ /* if module no params, then can't possible match */ 
+ if (mdp->mprmnum == 0 && (mdp->mspfy == NULL || mdp->mspfy->sprmnum == 0))
+  return(NULL);
+
+ /* turn off acc error displaying and then get acc name */
+ sav_acc_disperrs = __acc_displayerrors;
+ __acc_displayerrors = FALSE;
+ chp = acc_fetch_name((handle) hp);
+ __acc_displayerrors = sav_acc_disperrs;
+
+ /* LOOKATME - assumining if object no name only look for 2nd no name attr */
+ if (chp == NULL || acc_error_flag) 
+  {
+   __acc_err(1993,
+    "%s: object %s unnamed - searching without associated name",
+    rtnam, to_acc_onam(__wrks1, hp->hrec->htyp));
+   chp = NULL;
+  }
+ acc_error_flag = FALSE;
+ 
+ /* search with object name */
+ if (chp != NULL)
+  {
+   sprintf(sname, "%s%s", anam, chp);
+   if ((np = tryfnd_param(sname, mdp->msymtab, rtnam, "parameter")) != NULL)
+    {
+     rhp = (struct h_t *) __mk_handle(vpiParameter, (void *) np, hp->hin_itp,
+      NULL); 
+     return(rhp);
+    }
+   if (mdp->mspfy == NULL || mdp->mspfy->spfsyms == NULL) goto try_no_name;
+   np = tryfnd_param(sname, mdp->mspfy->spfsyms, rtnam, "specparam");
+   if (np != NULL)
+    {
+     rhp = (struct h_t *) __mk_handle(vpiSpecParam, (void *) np, hp->hin_itp,
+      NULL); 
+     return(rhp);
+    }
+  }
+try_no_name:
+ /* look up attribute name with no object name */
+ if ((np = tryfnd_param(anam, mdp->msymtab, rtnam, "parameter")) != NULL)
+  {
+   rhp = (struct h_t *) __mk_handle(vpiParameter, (void *) np, hp->hin_itp,
+    NULL); 
+   return(rhp);
+  }
+ if (mdp->mspfy == NULL || mdp->mspfy->spfsyms == NULL) return(NULL);
+ np = tryfnd_param(anam, mdp->mspfy->spfsyms, rtnam, "specparam");
+ if (np != NULL)
+  {
+   rhp = (struct h_t *) __mk_handle(vpiSpecParam, (void *) np, hp->hin_itp,
+    NULL); 
+   return(rhp);
+  }
+ return(NULL);
+}
+
+/*
+ * search for an attr  param/sparam in passed symbol table for attribte
+ */
+static struct net_t *tryfnd_param(char *anam, struct symtab_t *sytp,
+ char *rtnam, char *ptnam) 
+{
+ struct sy_t *syp;
+
+ if ((syp = __get_sym(anam, sytp)) == NULL) return(NULL);
+ if (syp->sytyp != SYM_N)
+  {
+   __acc_warn(2054,
+    "%s: attribute %s not found - looking for %s object is a %s", rtnam, 
+    anam, ptnam, __to_sytyp(__xs, syp->sytyp));
+   return(NULL);
+  }
+ if (!syp->el.enp->n_isaparam)
+  {
+   __acc_warn(2054,
+    "%s: attribute %s not found - object is not a %s", rtnam, anam, ptnam); 
+   return(NULL);
+  }
+ /* FIXME - when specparams in modules need to make sure right parm type */
+ return(syp->el.enp);
+}
+
+/*
+ * acc fetch attribute - return as int32 variant
+ */
+/*VARARGS*/
+extern int32 acc_fetch_attribute_int(handle object, ...)
+{
+ struct h_t *hp, *rhp;
+ int32 i1;
+ va_list va;
+ s_vpi_value tmpval;
+ char *attrstr;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object; 
+ if (!validate_acc_handle("acc_fetch_attribute_int", hp)) return(0); 
+
+ va_start(va, object);
+ attrstr = va_arg(va, char *);
+
+ if ((rhp = find_acc_attr_param(hp, attrstr, "acc_fetch_attribute_int"))
+  == NULL)
+  {
+ret_def:
+   /* T return 0 - ignore any possible pass default value */
+   if (__acc_defaultattr0) return(0);
+   /* F return user passed default attribute value */
+   i1 = va_arg(va, int32);
+   va_end(va);
+   return(i1);
+  }
+ /* access object value as real */
+ __acc_vpi_erroff = TRUE;
+ tmpval.format = vpiIntVal; 
+ vpi_get_value((vpiHandle) rhp, &tmpval);
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1956,
+    "acc_fetch_attribute_int: error accessing int32 value for attribute %s",
+    rhp->hrec->hu.hnp->nsym->synam);
+   goto ret_def;
+  }
+ va_end(va);
+ return(tmpval.value.integer);
+}
+
+/*
+ * acc fetch attribute - return as str variant
+ */
+/*VARARGS*/
+extern char *acc_fetch_attribute_str(handle object, ...)
+{
+ struct h_t *hp, *rhp;
+ va_list va;
+ s_vpi_value tmpval;
+ char *attrstr, *valchp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object; 
+ if (!validate_acc_handle("acc_fetch_attribute_str", hp)) return(NULL); 
+
+ va_start(va, object);
+ attrstr = va_arg(va, char *);
+
+ if ((rhp = find_acc_attr_param(hp, attrstr, "acc_fetch_attribute_str")) == NULL)
+  {
+ret_def:
+   /* LOOKATME - should this be empty string */
+   /* T return NULL - ignore any possible pass default value */
+   if (__acc_defaultattr0) return(NULL);
+   /* F return user passed default attribute value */
+   valchp = va_arg(va, char *);
+   va_end(va);
+   return(valchp);
+  }
+ /* access object value as real */
+ __acc_vpi_erroff = TRUE;
+ tmpval.format = vpiStringVal; 
+ vpi_get_value((vpiHandle) rhp, &tmpval);
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1956,
+    "acc_fetch_attribute_int: error accessing int32 value for attribute %s",
+    rhp->hrec->hu.hnp->nsym->synam);
+   goto ret_def;
+  }
+ va_end(va);
+ return(tmpval.value.str);
+}
+
+/*
+ * get a definition name
+ */
+extern char *acc_fetch_defname(handle object_handle)
+{
+ struct h_t *hp;
+ char *chp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object_handle; 
+ if (!validate_acc_handle("acc_fetch_defname", hp)) return(NULL); 
+
+ /* works because acc handles are same as vpi handles */
+ __acc_vpi_erroff = TRUE;
+ chp = vpi_get_str(vpiDefName, (vpiHandle) object_handle);
+
+ /* this access error vpi_ error info */  
+ /* only error is object not having vpi_ property */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1716,
+    "acc_fetch_defname: object %s does not have defname - must be instances or primitive",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ /* finally add to acc_ string buffer */ 
+ return(add_accstrbuf(chp));
+}
+
+/*
+ * add string to acc string buffer
+ */
+static char *add_accstrbuf(char *s)
+{
+ int32 slen;
+ char *chp;
+
+ slen = strlen(s);
+ /* if won't fit, reset string buffer */
+ if (__acc_strbuf_nxti + (slen + 1) >= ACCSTRBUFSIZ) 
+  {
+   __acc_warn(2042,
+    "acc string buffer reset - not enough room to add new string (%d needed)",
+    slen + 1); 
+   __acc_strbuf_nxti = 0;
+   /* DBG remove --- */
+   if (slen + 1 >= ACCSTRBUFSIZ) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+  }
+ chp = &(__acc_strbuf[__acc_strbuf_nxti]);
+ strcpy(chp, s);
+ __acc_strbuf_nxti += slen + 1;
+ return(chp);
+}
+
+/*
+ * get delay mode - delay modes not supported in Cver
+ *
+ * only supported delay mode is accDelayModePath
+ * Cver tool does not store 3 values for MTM delays because it is a
+ * simulator
+ */
+extern int32 acc_fetch_delay_mode(handle object_p)
+{
+ struct h_t *hp; 
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object_p; 
+ if (!validate_acc_handle("acc_fetch_delay_mode", hp)) return(0); 
+ if (hp->hrec->htyp != vpiModule)
+  {
+   __acc_err(1725, "acc_next: scope object %s illegal must be accModule",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(0);
+  }
+ return(accDelayModePath);
+}
+
+/*
+ * fetch delays first into vpi_ delay struct then set rigth values
+ *
+ * number or arguments for primitives determined by gate class not
+ * configure setting
+ *
+ * LOOKATME - LRM says tranif turn-on/off 2 but think needs to be 3
+ */
+/*VARARGS*/
+extern bool acc_fetch_delays(handle object, ...)
+{
+ register int32 i, j;
+ double *d1p, *d2p, *d3p, *da;
+ va_list va;
+ struct h_t *hp; 
+ struct hrec_t *hrp;
+ struct gate_t *gp;
+ struct mod_pin_t *mpp;
+ s_vpi_delay vpideltmp;
+ /* need to be able to store 3*12 (same min:typ:max) for each */
+ s_vpi_time delarr[36]; 
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object; 
+ if (!validate_acc_handle("acc_fetch_delays", hp)) return(0); 
+ hrp = hp->hrec;
+
+ for (i = 0; i < 36; i++) delarr[0].type = vpiScaledRealTime;
+ vpideltmp.da = &(delarr[0]);
+ vpideltmp.time_type = vpiScaledRealTime;
+ vpideltmp.mtm_flag = FALSE;
+ vpideltmp.append_flag = FALSE;
+ vpideltmp.pulsere_flag = FALSE;
+ 
+ switch (hrp->htyp) {
+  case vpiGate: case vpiUdp: case vpiSwitch:
+   /* 3 values */
+   __acc_vpi_erroff = TRUE;
+   /* always get 3 delays - although ignore 3rd for logic/udp with only 2 */
+   gp = hrp->hu.hgp;
+   vpideltmp.no_of_delays = 3;
+   vpi_get_delays((vpiHandle) hp, &vpideltmp);
+
+   /* this access error vpi_ error info */  
+   /* only error is object not having property */
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1718,
+      "acc_fetch_delays: unable to access delays for object %s",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(0);
+    }
+   va_start(va, object);
+   /* notice gates always return 3 */ 
+   vpideltmp.no_of_delays = 2;
+   if (__acc_mintypmaxdelays)
+    {
+     da = va_arg(va, double *);
+     da[0] = da[1] = da[2] = vpideltmp.da[0].real; 
+     da[3] = da[4] = da[5] = vpideltmp.da[1].real; 
+     if (gp->g_class != GC_UDP && gp->g_class != GC_LOGIC)
+      {
+       da[6] = da[7] = da[8] = vpideltmp.da[2].real; 
+      }
+    }
+   else
+    {
+     d1p = va_arg(va, double *);
+     *d1p = vpideltmp.da[0].real; 
+     d2p = va_arg(va, double *);
+     *d2p = vpideltmp.da[1].real; 
+     if (gp->g_class != GC_UDP && gp->g_class != GC_LOGIC)
+      {
+       d3p = va_arg(va, double *);
+       *d3p = vpideltmp.da[2].real; 
+      }
+    }
+   va_end(va);
+   break;
+  case vpiPort: case vpiPortBit: 
+   /* up to 12 - see draft 3 or later new LRM */
+   mpp = &(hp->hin_itp->itip->imsym->el.emdp->mpins[hrp->hu.hpi]);
+   if (mpp->mptyp != IO_IN && mpp->mptyp != IO_BID)
+    {
+     __acc_err(1761,
+      "acc_fetch_delays: unable to access delays for %s - output port illegal",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(0); 
+    }
+   if (hrp->htyp == vpiPort && mpp->mpwide != 1)
+    {
+     __acc_err(1761,
+      "acc_fetch_delays: unable to access delays for accPort - must be scalar");
+     return(0);
+    }
+   if (!mpp->has_mipd)
+    {
+     __acc_warn(2045,
+      "acc_fetch_delays: %s does not have MIPD - delays all 0",
+     to_acc_onam(__wrks1, hp->hrec->htyp));
+      
+     va_start(va, object);
+     if (__acc_mintypmaxdelays)
+      {
+       da = va_arg(va, double *);
+       for (i = 0; i < 3*__acc_pathdelaycount; i += 3)
+        { da[i] = da[i + 1] = da[i + 2] = 0.0; }
+      }
+     else
+      {
+       for (i = 0; i < __acc_pathdelaycount; i++)
+        { d1p = va_arg(va, double *); *d1p = 0.0; }
+      }
+     va_end(va);
+     return(1);
+    }
+   /* FALLTHRU */
+  case vpiModPath:
+   __acc_vpi_erroff = TRUE;
+   /* port MIPD since inter module paths not supported) and paths from cfg */
+   vpideltmp.no_of_delays = __acc_pathdelaycount;
+   vpi_get_delays((vpiHandle) hp, &vpideltmp);
+
+   /* this access error vpi_ error info */  
+   /* only error is object not having property */
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1718,
+      "acc_fetch_delays: unable to access path or MIPD delays for object %s",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(0);
+    }
+   va_start(va, object);
+   if (__acc_mintypmaxdelays)
+    {
+     da = va_arg(va, double *);
+     for (i = 0, j = 0; i < 3*__acc_pathdelaycount; i +=3, j++)
+      {
+       da[i + 0] = da[i + 1] = da[i + 2] = vpideltmp.da[j].real; 
+      } 
+    }
+   else
+    {
+     for (i = 0; i < __acc_pathdelaycount; i++)
+      {
+       d1p = va_arg(va, double *);
+       *d1p = vpideltmp.da[i].real; 
+      } 
+    }
+   va_end(va);
+   break;
+  case vpiTchk:
+   /* 1 value - for 2 limit cases only first accessible in acc_ */
+   __acc_vpi_erroff = TRUE;
+   /* always get 1 delay (first limit) */
+   vpideltmp.no_of_delays = 1;
+   vpi_get_delays((vpiHandle) hp, &vpideltmp);
+
+   /* this access error vpi_ error info */  
+   /* only error is object not having property */
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1718,
+      "acc_fetch_delays: unable to access delays for object %s",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(0);
+    }
+   va_start(va, object);
+   if (__acc_mintypmaxdelays)
+    {
+     da = va_arg(va, double *);
+     da[0] = da[1] = da[2] = vpideltmp.da[0].real; 
+    }
+   else
+    {
+     d1p = va_arg(va, double *);
+     *d1p = vpideltmp.da[0].real; 
+    }
+   va_end(va);
+   break;
+  default:
+   __acc_err(1759,
+    "acc_fetch_delays: object %s illegal - does not have acc_ accessible delays",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(0);
+  }
+ return(1);
+}
+
+/*
+ * get direction of acc port or terminal (also tchk terminals)
+ *
+ * LOOKATME - does acc support timing check terminal directions?
+ * this returns 0 on error
+ */
+extern int32 acc_fetch_direction(handle object_handle)
+{
+ int32 rv;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object_handle; 
+ if (!validate_acc_handle("acc_fetch_directon", hp)) return(0); 
+
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiPort && hrp->htyp != vpiPortBit
+  && hrp->htyp != vpiPrimTerm)
+  {
+   __acc_err(1757,
+    "acc_fetch_direction: object %s does not have direction - must be port or primitive terminal",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(0);
+  }
+
+ __acc_vpi_erroff = TRUE;
+ rv = vpi_get(vpiDirection, (vpiHandle) object_handle);
+
+ /* this access error vpi_ error info */  
+ /* only error is object not having property */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1718,
+   "acc_fetch_direction: unable to access direction for object %s",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(0);
+  }
+ switch (rv) {
+  case vpiInput: rv = accInput; break;
+  case vpiOutput: rv = accOutput; break;
+  case vpiInout: rv = accInout; break;
+  case vpiMixedIO: rv = accMixedIo; break;
+  case vpiNoDirection:
+   __acc_err(1719,
+    "acc_fetch_direction failed - object %s direction unknown",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   rv = 0;
+ } 
+ return(rv);
+}
+
+/*
+ * get an acc edge (same values as vpi edge)
+ *
+ * FIXME - although acc and vpi edge values same need routine to convert
+ * LOOKATME - is returning 0 on error correct? 
+ */
+extern int32 acc_fetch_edge(handle acc_object)
+{
+ int32 rv;
+ struct h_t *hp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) acc_object; 
+ if (!validate_acc_handle("acc_fetch_edge", hp)) return(0); 
+
+ __acc_vpi_erroff = TRUE;
+ rv = vpi_get(vpiEdge, (vpiHandle) acc_object);
+
+ /* this access error vpi_ error info */  
+ /* only error is object not having property */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1721,
+   "acc_fetch_edge: object %s does not have edge - must be path or timing check",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(0);
+  }
+ /* same edge encoding between acc and vpi_ */
+ return(rv);
+}
+
+/*
+ * fetch full (xmr if needed) name
+ */
+extern char *acc_fetch_fullname(handle object_handle)
+{
+ struct h_t *hp;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+ char *chp, s1[3*RECLEN], s2[6*RECLEN], s3[6*RECLEN];
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object_handle; 
+ if (!validate_acc_handle("acc_fetch_fullname", hp)) return(NULL); 
+
+ /* only acc not vpi_ returns full heirarchical path name for ports */ 
+ if (hp->hrec->htyp == vpiPort || hp->hrec->htyp == vpiPortBit)
+  {
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
+   if (mpp->mpsnam == NULL)
+    {
+     __acc_err(1762, "acc_fetch_fullname: accPort object unnamed");
+     return(NULL);
+    }
+   if (hp->hin_itp->up_it != NULL)
+    sprintf(s1, "%s.%s", __msg2_blditree(s2, hp->hin_itp), mpp->mpsnam);
+   else strcpy(s2, mpp->mpsnam);
+   chp = s1;
+   goto add_str;
+  }
+
+ /* acc constructs path names from terminals */
+ if (hp->hrec->htyp == vpiModPath || hp->hrec->htyp == vpiInterModPath)
+  {
+   sprintf(s1, "%s%s%s", hp->hrec->hu.hpthp->peins[0].penp->nsym->synam, 
+    __acc_pathdelimstr, hp->hrec->hu.hpthp->peouts[0].penp->nsym->synam);
+   if (hp->hin_itp->up_it != NULL)
+    sprintf(s2, "%s.%s", __msg2_blditree(s3, hp->hin_itp), s1);
+   else strcpy(s2, s1);
+   chp = s2;
+   goto add_str;
+  }
+
+ __acc_vpi_erroff = TRUE;
+ chp = vpi_get_str(vpiFullName, (vpiHandle) object_handle);
+
+ /* this access error vpi_ error info */  
+ /* only error is object not having vpi_ property */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1722, "acc_fetch_fullname: object %s does not have fullname",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+add_str:
+ /* finally add to acc_ string buffer */ 
+ return(add_accstrbuf(chp));
+}
+
+/*
+ * get acc full type (usually same as type)
+ */
+extern int32 acc_fetch_fulltype(handle object_h)
+{
+ struct h_t *hp;
+ struct vpi_to_acc_t *accvpip;
+
+ acc_error_flag = FALSE;
+ hp = (struct h_t *) object_h; 
+
+ if (!validate_acc_handle("acc_fetch_fulltype", hp)) return(0); 
+ /* once handle validated this can never fail */
+ accvpip = get_acc_typerec(hp);
+ return(get_acc_fulltype((vpiHandle) object_h, accvpip));
+}
+
+/*
+ * get index (pos. starting at 0) of a port or terminal
+ *
+ * LOOKATME - does acc port index also start at 0
+ */
+extern int32 acc_fetch_index(handle object_handle)
+{
+ int32 rv;
+ struct h_t *hp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object_handle; 
+ if (!validate_acc_handle("acc_fetch_index", hp)) return(0); 
+
+ __acc_vpi_erroff = TRUE;
+ if (hp->hrec->htyp == vpiPrimTerm)
+  rv = vpi_get(vpiTermIndex, (vpiHandle) object_handle);
+ else if (hp->hrec->htyp == vpiPort)
+  rv = vpi_get(vpiPortIndex, (vpiHandle) object_handle);
+ else goto bad_arg;
+
+ /* this access error vpi_ error info */  
+ /* only error is object not having property */
+ if (__my_vpi_chk_error())
+  {
+bad_arg:
+   __acc_err(1723,
+   "acc_fetch_index: object %s does not have list index - must be port or terminal",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   rv = 0;
+  }
+ return(rv);
+}
+
+/*
+ * fetch line number and file name location of acc object
+ */
+extern int32 acc_fetch_location(p_location location_p, handle object)
+{
+ int32 lineno;
+ struct h_t *hp;
+ char *chp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object; 
+ if (!validate_acc_handle("acc_fetch_location", hp)) return(FALSE); 
+
+ __acc_vpi_erroff = TRUE;
+ lineno = vpi_get(vpiLineNo, (vpiHandle) object);
+
+ /* this access error vpi_ error info */  
+ /* only error is object not having vpi_ property */
+ if (__my_vpi_chk_error())
+  {
+bad_arg:
+   __acc_err(1958, "acc_fetch_location: object %s does not have location",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(FALSE);
+  }
+ __acc_vpi_erroff = TRUE;
+ chp = vpi_get_str(vpiFile, (vpiHandle) object);
+ if (__my_vpi_chk_error()) goto bad_arg;
+
+ location_p->line_no = lineno;
+ location_p->filename = add_accstrbuf(chp);
+ return(FALSE);
+}
+
+/*
+ * access objects name (in module local name)
+ *
+ * notice because of path needing 3 elements - work string 3x ID size 
+ */
+extern char *acc_fetch_name(handle object_handle)
+{
+ struct h_t *hp;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+ char *chp, s1[3*RECLEN];
+ struct hrec_t *hrp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object_handle; 
+ if (!validate_acc_handle("acc_fetch_name", hp)) return(NULL); 
+ hrp = hp->hrec;
+
+ /* only acc not vpi_ returns full heirarchical path name for ports */ 
+ if (hrp->htyp == vpiPort || hrp->htyp == vpiPortBit)
+  {
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   mpp = &(mdp->mpins[hrp->hu.hpi]);
+   if (mpp->mpsnam == NULL)
+    {
+     __acc_err(1763, "acc_fetch_name: accPort object unnamed");
+     return(NULL);
+    }
+   chp = mpp->mpsnam;
+   goto add_str;
+  }
+
+ /* acc constructs port names from terminals */
+ if (hrp->htyp == vpiModPath || hrp->htyp == vpiInterModPath)
+  {
+   sprintf(s1, "%s%s%s", hrp->hu.hpthp->peins[0].penp->nsym->synam, 
+    __acc_pathdelimstr, hrp->hu.hpthp->peouts[0].penp->nsym->synam);
+   chp = s1;
+   goto add_str;
+  }
+
+ __acc_vpi_erroff = TRUE;
+ chp = vpi_get_str(vpiName, (vpiHandle) object_handle);
+
+ /* this access error vpi_ error info */  
+ /* only error is object not having vpi_ property */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1724, "acc_fetch_name: object %s does not have name",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+
+add_str:
+ /* finally add to acc_ string buffer */ 
+ return(add_accstrbuf(chp));
+}
+
+/*
+ * get declaration type of parameter
+ *
+ * LOOKATME is non string and non real always int32 algorithm right? 
+ */
+extern int32 acc_fetch_paramtype(handle param_p)
+{
+ struct h_t *hp;
+ struct net_t *np;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) param_p; 
+ if (!validate_acc_handle("acc_fetch_paramtype", hp)) return(0); 
+ 
+ np = hp->hrec->hu.hnp;
+ /* DBG remove --- */
+ if (!np->n_isaparam) __acc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ if (np->ntyp == N_REAL) return(accRealParam);
+ if (np->nu.ct->pstring) return(accStringParam);
+ return(accIntegerParam);
+}
+
+/*
+ * fetch value of a parameter (def or spec) in a double
+ *
+ * caller can convert int32 back to int32 by cast
+ * for string parameter double is really ptr to char * that user
+ * must cast double back to char * by first casting to int32 then to char *
+ */
+extern double acc_fetch_paramval(handle param)
+{
+ word32 w;
+ double d1;
+ struct h_t *hp;
+ struct net_t *np;
+ s_vpi_value tmpval;
+ char *chp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) param; 
+ if (!validate_acc_handle("acc_fetch_paramval", hp)) return(0.0); 
+ 
+ np = hp->hrec->hu.hnp;
+ /* DBG remove --- */
+ if (!np->n_isaparam) __acc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ if (np->ntyp == N_REAL)
+  {
+   __acc_vpi_erroff = TRUE;
+   tmpval.format = vpiRealVal; 
+   vpi_get_value((vpiHandle) param, &tmpval);
+   if (__my_vpi_chk_error())
+    {
+bad_getval:
+     __acc_err(1956, "acc_fetch_paramval: error accessing parameter value");
+     return(0.0);
+    }
+   d1 = tmpval.value.real;
+  }
+ else if (np->nu.ct->pstring)
+  {
+   __acc_vpi_erroff = TRUE;
+   tmpval.format = vpiStringVal; 
+   vpi_get_value((vpiHandle) param, &tmpval);
+   if (__my_vpi_chk_error()) goto bad_getval;
+   /* PORTABILITY - acc standard here requires strange cast */ 
+   chp = add_accstrbuf(tmpval.value.str);
+   w = (word32) chp;
+   d1 = (double) w;
+  }
+ else
+  {
+   __acc_vpi_erroff = TRUE;
+   /* LOOKATME - notice getting vpi_ to do conversion to double */
+   tmpval.format = vpiRealVal; 
+   vpi_get_value((vpiHandle) param, &tmpval);
+   if (__my_vpi_chk_error()) goto bad_getval;
+   d1 = tmpval.value.real;
+  }
+ return(d1);
+}
+
+/*
+ * get polarity - type of vpi object
+ *
+ * LOOKATME - what about data path polarity
+ */
+extern int32 acc_fetch_polarity(handle path)
+{
+ int32 rv;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) path; 
+ if (!validate_acc_handle("acc_fetch_polarity", hp)) return(0); 
+ hrp = hp->hrec;
+
+ if (hrp->htyp != vpiModPath)
+  {
+   __acc_err(1946,
+    "acc_fetch_polarity: object %s does not have polarity - accModPath required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(0);
+  }
+
+ __acc_vpi_erroff = TRUE;
+ rv = vpi_get(vpiPolarity, (vpiHandle) path);
+
+ /* this access error vpi_ error info */  
+ /* only error is object not having property */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1959,
+    "acc_fetch_polarity: unable to access polarity for object %s",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(0);
+  }
+ /* same edge encoding between acc and vpi_ */
+ return(rv);
+}
+
+/*
+ * get design wide precicison (minimum time scale)
+ */
+extern int32 acc_fetch_precision(void)
+{
+ acc_error_flag = FALSE;
+
+ if (!__des_has_timescales)
+  {
+   __acc_warn(2046,
+    "acc_fetch_precision meaningless - design contains no `timescale directives");
+   return(0);
+  }
+ return(-((int32) __des_timeprec));
+}
+
+/*
+ * fetch pulsere (inertial glitch error ranges)
+ *
+ * almost same as acc_fetch_delays except mintypmax flag off
+ * this never uses min:typ:max flags and never array form
+ *
+ * Cver does not yet store and simulate so use 0 and delay
+ * works by getting one delay not "faked" vpi_ pulsere
+ * although LRM says only mod path either type of path legal arg
+ * return 0 for reject limit and delay for e_limit
+ */
+/*VARARGS*/
+extern bool acc_fetch_pulsere(handle path_p, double *val1r, double *val1e, ...)
+{
+ register int32 i;
+ int32 sav_acc_mintypmaxdelays, rv;
+ double *rp, *ep;
+ va_list va;
+ struct h_t *hp; 
+ struct hrec_t *hrp;
+ struct mod_pin_t *mpp;
+ s_vpi_delay vpideltmp;
+ /* need to be able to store 3*12 (same min:typ:max) for each */
+ s_vpi_time delarr[36]; 
+
+ __acc_warn(1954,
+  "acc_fetch_pulsere reject value always 0 - e_limit same as delay - tools does not support");
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) path_p; 
+ if (!validate_acc_handle("acc_fetch_pulsere", hp)) return(FALSE); 
+ hrp = hp->hrec;
+
+ vpideltmp.da = &(delarr[0]);
+ vpideltmp.time_type = vpiScaledRealTime;
+ vpideltmp.mtm_flag = FALSE;
+ vpideltmp.append_flag = FALSE;
+ vpideltmp.pulsere_flag = FALSE;
+ 
+ sav_acc_mintypmaxdelays = __acc_mintypmaxdelays;
+ __acc_mintypmaxdelays = FALSE;
+ switch (hrp->htyp) {
+  case vpiPort: case vpiPortBit: 
+   /* up to 12 - see draft 3 or later new LRM */
+   mpp = &(hp->hin_itp->itip->imsym->el.emdp->mpins[hrp->hu.hpi]);
+   if (mpp->mptyp != IO_IN && mpp->mptyp != IO_BID)
+    {
+     __acc_err(1761,
+      "acc_fetch_pulsere: unable to access pulsere for %s - output port illegal",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     rv = FALSE;
+     goto done;
+    }
+   if (hrp->htyp == vpiPort && mpp->mpwide != 1)
+    {
+     __acc_err(1761,
+      "acc_fetch_pulsere: unable to access pulsere for accPort - must be scalar");
+     rv = FALSE;
+     goto done;
+    }
+   if (!mpp->has_mipd)
+    {
+     __acc_warn(2045,
+      "acc_fetch_pulsere: %s does not have MIPD - pulsere all 0",
+     to_acc_onam(__wrks1, hp->hrec->htyp));
+      
+     *val1r = 0.0;
+     *val1e = 0.0;
+     va_start(va, val1e);
+     for (i = 1; i < __acc_pathdelaycount; i++)
+      {
+       rp = va_arg(va, double *);
+       *rp = 0.0;
+       ep = va_arg(va, double *);
+       *ep = 0.0;
+      }
+     va_end(va);
+     break;
+    }
+   /* FALLTHRU */
+  case vpiModPath:
+   __acc_vpi_erroff = TRUE;
+   /* port MIPD since inter module paths not supported) and paths from cfg */
+   vpideltmp.no_of_delays = __acc_pathdelaycount;
+   vpi_get_delays((vpiHandle) hp, &vpideltmp);
+
+   /* this access error vpi_ error info */  
+   /* only error is object not having property */
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1718,
+      "acc_fetch_pulsere: unable to access path or MIPD pulsere for object %s",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     rv = FALSE;
+     goto done;
+    }
+   *val1r = 0.0;
+   *val1e = vpideltmp.da[0].real; 
+   va_start(va, val1e);
+   for (i = 1; i < __acc_pathdelaycount; i++)
+    {
+     rp = va_arg(va, double *);
+     *rp = 0.0;
+     ep = va_arg(va, double *);
+     *ep = vpideltmp.da[i].real; 
+    }
+   va_end(va);
+   break;
+  default:
+   __acc_err(1759,
+    "acc_fetch_pulsere: object %s illegal - only path has pulsere's",
+    to_acc_onam(__wrks1, hrp->htyp));
+   rv = FALSE;
+   goto done;
+  }
+ rv = TRUE;
+done:
+ __acc_mintypmaxdelays = sav_acc_mintypmaxdelays;
+ return(rv);
+}
+
+/*
+ * fetch a range of only a vector 
+ *
+ * notice msb is first range although may be less than lsb
+ * LOOKATME - what are objects for this (allowing vpiMemoryWord)
+ */
+extern int32 acc_fetch_range(handle node, int32 *msb, int32 *lsb)
+{
+ register struct hrec_t *hrp;
+ int32 r1, r2;
+ struct h_t *hp;
+ vpiHandle rrng, lrng;
+ s_vpi_value tmpval;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) node; 
+ if (!validate_acc_handle("acc_fetch_range", hp)) return(FALSE); 
+ hrp = hp->hrec;
+
+ if (hrp->htyp != vpiNet && hrp->htyp != vpiReg && hrp->htyp != vpiMemoryWord)
+  {
+bad_obj:
+   __acc_err(1961,
+    "acc_fetch_range: object %s illegal - not a vector net or reg",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(FALSE);
+  }
+ if (!hrp->hu.hnp->n_isavec) goto bad_obj;
+
+ __acc_vpi_erroff = TRUE;
+ lrng = vpi_handle(vpiLeftRange, (vpiHandle) node);
+ if (__my_vpi_chk_error())
+  {
+bad_rng:
+   __acc_err(1962, "acc_fetch_range: unable to access range value");
+   return(FALSE);
+  }
+ __acc_vpi_erroff = TRUE;
+ rrng = vpi_handle(vpiRightRange, (vpiHandle) node);
+ if (__my_vpi_chk_error()) goto bad_rng;
+
+ __acc_vpi_erroff = TRUE;
+ tmpval.format = vpiIntVal; 
+ vpi_get_value(lrng, &tmpval);
+ if (__my_vpi_chk_error()) goto bad_rng;
+ r1 = tmpval.value.integer;
+
+ __acc_vpi_erroff = TRUE;
+ tmpval.format = vpiIntVal; 
+ vpi_get_value(rrng, &tmpval);
+ if (__my_vpi_chk_error()) goto bad_rng;
+ r2 = tmpval.value.integer;
+ *msb = r1;
+ *lsb = r2;
+
+ return(TRUE);
+}
+
+/*
+ * get size of a net type object
+ *
+ * LOOKATME - what are objects allowed for this
+ */
+extern int32 acc_fetch_size(handle obj_h)
+{
+ register struct hrec_t *hrp;
+ struct h_t *hp;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp; 
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) obj_h; 
+ if (!validate_acc_handle("acc_fetch_size", hp)) return(0); 
+ hrp = hp->hrec;
+
+ switch (hrp->htyp) {
+  case vpiNetBit: case vpiRegBit: case vpiPortBit: case vpiVarSelect:
+   return(1);
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   return(hrp->hu.hnp->nwid);
+  case vpiPort:
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   mpp = &(mdp->mpins[hrp->hu.hpi]);
+   return(mpp->mpwide);
+  case vpiMemoryWord:
+   return(hrp->hu.hnp->nwid);
+  default: break;
+ }
+ __acc_err(1963,
+  "acc_fetch_size: object %s illegal - not a net/reg/port or bit thereof",
+  to_acc_onam(__wrks1, hrp->htyp));
+ return(0);
+}
+
+/*
+ * SIX ALMOST IDENTICAL ROUTINES TO ACCESS CALLED TF ARG AS VALUE
+ */
+
+/*
+ * fetch nth tf arg for current tf object as real 
+ *
+ * special handling of string values (constants) required where value
+ * returned is pointer cast to double
+ */
+extern double acc_fetch_tfarg(int32 n)
+{
+ register struct hrec_t *shrp;
+ word32 w;
+ vpiHandle systfp;
+ struct h_t *shp;
+ struct tskcall_t *tkcp;
+ struct expr_t *argxp;
+ s_vpi_value tmpval;
+ char *chp;
+
+ acc_error_flag = FALSE;
+
+ /* returns 0.0 if not called from user defined systf */
+ if ((systfp = get_acc_current_systf("acc_fetch_tfarg")) == NULL) return(0.0);
+
+ shp = (struct h_t *) systfp;
+ shrp = shp->hrec;
+
+ if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
+ else if (shrp->htyp == vpiSysTaskCall) 
+  {
+   tkcp = &(shrp->hu.hstp->st.stkc);
+   argxp = tkcp->targs;
+  }
+ else { __acc_terr(__FILE__, __LINE__); return(0.0); }
+
+ tmpval.format = vpiRealVal;
+
+ if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_tfarg"))
+  return(0.0);
+ if (tmpval.format == vpiStringVal)
+  {
+   /* string value returned as pointer to string converted to double */
+   chp = add_accstrbuf(tmpval.value.str);
+   w = (word32) chp;
+   return((double) w);
+  }
+ return(tmpval.value.real);
+}
+
+/*
+ * for current context fetch tfarg, get systf handle
+ */
+static vpiHandle get_acc_current_systf(char *rnam)
+{
+ vpiHandle systfp;
+
+ if (__tfinst == NULL)
+  { 
+   __acc_err(1955,
+    "%s: unable to access calling tfinst because no PLI tf called", rnam);  
+   return(NULL);
+  }
+
+ /* know this is run with current instance on itree stack */
+ if (__tfinst->callx != NULL)
+  systfp = __mk_handle(vpiSysFuncCall, (void *) __tfinst->callx, __inst_ptr,
+   __tfrec->tf_intskp);
+ else systfp = __mk_handle(vpiSysTaskCall, (void *) __tfinst->tfstp,
+  __inst_ptr, __tfrec->tf_intskp);
+ return(systfp);
+}
+
+/*
+ * access systf argument value from expression
+ * fills value and returns T - if error returns F
+ * caller must set expected type in valp
+ * notice for literal strings passed get value type changed to string
+ *
+ * FIXME - what happen when argument is instance form (no value?)
+ */
+static int32 get_systf_acc_expr_val(int32 n, struct expr_t *argxp,
+ s_vpi_value *valp, struct h_t *shp, char *rnam)
+{
+ register int32 argi;
+ register struct expr_t *xp2;
+ vpiHandle arghp;
+
+ /* get expression corresponding to nth argument */
+ if (n < 1)
+  {
+outofrng:
+   __acc_warn(2047, "%s: argument position %d out of range", rnam, n);
+   /* error flag not set here */
+   return(FALSE);
+  }
+
+ for (argi = 0, xp2 = argxp; xp2 != NULL; xp2 = xp2->ru.x, argi++)
+  {
+   if (argi == n - 1) goto found_it;
+  }
+ goto outofrng; 
+
+found_it:
+ /* FIXME - tf arg instance argument core dumps */
+ /* this can not currently fail */
+ arghp = __mk_exprclass_handle(xp2->lu.x, shp->hin_itp, shp->hrec->hin_tskp);
+
+ /* literal strings always accessed as strings */
+ if (xp2->lu.x->is_string) valp->format = vpiStringVal;
+
+ __acc_vpi_erroff = TRUE;
+ vpi_get_value(arghp, valp);
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1756, "%s: error accessing %s argument %d value", rnam,
+    vpi_get_str(vpiName, (vpiHandle) shp), n);  
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * fetch nth tf arg for task function object tfinst as real 
+ *
+ * LOOKATME - LRM does say whether expressions (not net/reg and selects
+ * of)
+ *
+ * FIXME - need special case for ports where expression is low conn
+ */
+extern double acc_fetch_itfarg(int32 n, handle tfinst)
+{
+ register struct hrec_t *shrp;
+ word32 w;
+ struct h_t *shp;
+ struct tskcall_t *tkcp;
+ struct expr_t *argxp;
+ s_vpi_value tmpval;
+ char *chp;
+
+ acc_error_flag = FALSE;
+
+ if (tfinst == NULL)
+  {
+   __acc_err(1755,
+    "acc_fetch_itfarg: no argument accessed because tfinst argument NULL");
+   return(0.0);
+  }
+ 
+ shp = (struct h_t *) tfinst;
+ if (!validate_acc_handle("acc_fetch_itfarg", shp)) return(0.0); 
+ shrp = shp->hrec;
+
+ if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
+ else if (shrp->htyp == vpiSysTaskCall) 
+  {
+   tkcp = &(shrp->hu.hstp->st.stkc);
+   argxp = tkcp->targs;
+  }
+ else
+  {
+   __acc_err(1957,
+    "acc_fetch_itfarg: tfinst %s argument illegal - must be acc system tf call",
+    to_acc_onam(__wrks1, shrp->htyp));
+   return(0.0);
+  }
+
+ tmpval.format = vpiRealVal;
+ if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_itfarg"))
+  return(0.0);
+
+ if (tmpval.format == vpiStringVal)
+  {
+   /* string value returned as pointer to string converted to double */
+   chp = add_accstrbuf(tmpval.value.str);
+
+   /* LOOKATME - this cast looks wrong and unportable ?? */
+   w = (word32) chp;
+   return((double) w);
+  }
+ else return(tmpval.value.real);
+}
+
+/*
+ * fetch nth tf arg for current tf object as int32 
+ */
+extern int32 acc_fetch_tfarg_int(int32 n)
+{
+ register struct hrec_t *shrp;
+ vpiHandle systfp;
+ word32 w;
+ struct h_t *shp;
+ struct tskcall_t *tkcp;
+ struct expr_t *argxp;
+ s_vpi_value tmpval;
+ char *chp;
+
+ acc_error_flag = FALSE;
+
+ if ((systfp = get_acc_current_systf("acc_fetch_tfarg_int")) == NULL)
+  return(0);
+
+ shp = (struct h_t *) systfp;
+ shrp = shp->hrec;
+
+ if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
+ else if (shrp->htyp == vpiSysTaskCall) 
+  {
+   tkcp = &(shrp->hu.hstp->st.stkc);
+   argxp = tkcp->targs;
+  }
+ else { __acc_terr(__FILE__, __LINE__); return(0); }
+
+ tmpval.format = vpiIntVal;
+ 
+ if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_tfarg_int"))
+  return(0);
+
+ if (tmpval.format == vpiStringVal)
+  {
+   /* string value returned as pointer to string converted to double */
+   chp = add_accstrbuf(tmpval.value.str);
+   /* FIXME ??? - NOT 64 bit portable */
+   w = (word32) chp;
+   return((int32) w);
+  }
+
+ return(tmpval.value.integer);
+}
+
+/*
+ * fetch nth tf arg for task function object tfinst as int
+ */
+extern int32 acc_fetch_itfarg_int(int32 n, handle tfinst)
+{
+ register struct hrec_t *shrp;
+ word32 w;
+ struct h_t *shp;
+ struct tskcall_t *tkcp;
+ struct expr_t *argxp;
+ s_vpi_value tmpval;
+ char *chp;
+
+ acc_error_flag = FALSE;
+
+ if (tfinst == NULL)
+  {
+   __acc_err(1756,
+    "acc_fetch_itfarg_int: no argument accessed because tfinst argument NULL");
+   return(0);
+  }
+ 
+ shp = (struct h_t *) tfinst;
+ if (!validate_acc_handle("acc_fetch_itfarg_int", shp)) return(0); 
+ shrp = shp->hrec;
+
+ if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
+ else if (shrp->htyp == vpiSysTaskCall) 
+  {
+   tkcp = &(shrp->hu.hstp->st.stkc);
+   argxp = tkcp->targs;
+  }
+ else
+  {
+   __acc_err(1957,
+    "acc_fetch_itfarg_int: tfinst %s argument illegal - must be acc system tf call",
+    to_acc_onam(__wrks1, shrp->htyp));
+   return(0);
+  }
+ tmpval.format = vpiIntVal;
+ if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_itfarg_int"))
+  return(0);
+
+ if (tmpval.format == vpiStringVal)
+  {
+   /* string value returned as pointer to string converted to double */
+   chp = add_accstrbuf(tmpval.value.str);
+   /* FIXME ??? - NOT 64 bit portable */
+   w = (word32) chp;
+   return((int32) w);
+  }
+ return(tmpval.value.integer);
+}
+
+/*
+ * fetch nth tf arg for current tf object as str 
+ * must copy string value to acc string table
+ *
+ * following LRM interpret value as string no matter what it is
+ */
+extern char *acc_fetch_tfarg_str(int32 n)
+{
+ register struct hrec_t *shrp;
+ vpiHandle systfp;
+ struct h_t *shp;
+ struct tskcall_t *tkcp;
+ struct expr_t *argxp;
+ s_vpi_value tmpval;
+
+ acc_error_flag = FALSE;
+
+ if ((systfp = get_acc_current_systf("acc_fetch_tfarg_str")) == NULL)
+  return(NULL);
+
+ shp = (struct h_t *) systfp;
+ shrp = shp->hrec;
+
+ if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
+ else if (shrp->htyp == vpiSysTaskCall) 
+  {
+   tkcp = &(shrp->hu.hstp->st.stkc);
+   argxp = tkcp->targs;
+  }
+ else { __acc_terr(__FILE__, __LINE__); return(NULL); }
+
+ tmpval.format = vpiStringVal;
+ 
+ /* string val goes into vpi get value specific internal big enough buf */ 
+ if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_tfarg_str"))
+  return(NULL);
+
+ return(add_accstrbuf(tmpval.value.str));
+}
+
+/*
+ * fetch nth tf arg for task function object tfinst as string
+ * must copy string value to acc string table
+ *
+ * following LRM interpret value as string no matter what it is
+ */
+extern char *acc_fetch_itfarg_str(int32 n, handle tfinst)
+{
+ register struct hrec_t *shrp;
+ struct h_t *shp;
+ struct tskcall_t *tkcp;
+ struct expr_t *argxp;
+ s_vpi_value tmpval;
+
+ acc_error_flag = FALSE;
+
+ if (tfinst == NULL)
+  {
+   __acc_err(1755,
+    "acc_fetch_itfarg_str: no argument accessed because tfinst argument NULL");
+   return(NULL);
+  }
+ 
+ shp = (struct h_t *) tfinst;
+ if (!validate_acc_handle("acc_fetch_itfarg_str", shp)) return(NULL); 
+ shrp = shp->hrec;
+
+ if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
+ else if (shrp->htyp == vpiSysTaskCall) 
+  {
+   tkcp = &(shrp->hu.hstp->st.stkc);
+   argxp = tkcp->targs;
+  }
+ else
+  {
+   __acc_err(1957,
+    "acc_fetch_itfarg_str: tfinst %s argument illegal - must be acc system tf call",
+    to_acc_onam(__wrks1, shrp->htyp));
+   return(NULL);
+  }
+
+ tmpval.format = vpiStringVal;
+ 
+ if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_tfarg_str"))
+  return(NULL);
+ return(add_accstrbuf(tmpval.value.str));
+}
+
+/*
+ * get timescale info or active $timeformat value
+ */
+extern void acc_fetch_timescale_info(handle obj,
+ p_timescale_info aof_timescale_info)
+{
+ struct h_t *hp;
+ struct mod_t *mdp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) obj;
+ /* case 1: get active timeformat info */
+ if (hp == NULL)
+  {
+   aof_timescale_info->unit = -((int32) __tfmt_units);
+   aof_timescale_info->precision = __tfmt_precunits; 
+   return;
+  }
+
+ /* get module's timescale */
+ if (!validate_acc_handle("acc_fetch_timescale_info", hp)) return; 
+ 
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ if (mdp->mno_unitcnv)
+  {
+   aof_timescale_info->unit = -((short int) __des_timeprec);
+   aof_timescale_info->precision = -((short int) __des_timeprec);
+  }
+ else
+  {
+   aof_timescale_info->unit = -((short int) mdp->mtime_units);
+   aof_timescale_info->precision =
+    -((short int) (mdp->mtime_units + mdp->mtime_prec));
+  }
+ /* SJM 09/01/00 - this is wrong since over-writes --- 
+ REMOVED - aof_timescale_info->unit = -((int32) mdp->mtime_units);
+ REMOVED - aof_timescale_info->precision = -((int32) mdp->mtime_prec); 
+ --- */
+}
+
+/*
+ * get type of object
+ */
+extern int32 acc_fetch_type(handle object_handle)
+{
+ struct h_t *hp;
+ struct vpi_to_acc_t *accvpip;
+ s_vpi_systf_data systfdat;
+
+ acc_error_flag = FALSE;
+ hp = (struct h_t *) object_handle; 
+
+ if (!validate_acc_handle("acc_fetch_type", hp)) return(0); 
+
+ accvpip = get_acc_typerec(hp);
+
+ /* DBG remove --- */
+ if (accvpip->acc_otyp == -1) __acc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ if (accvpip->acc_otyp != accUserFunction
+  && accvpip->acc_otyp != accSystemFunction)
+  {
+   return(accvpip->acc_otyp);
+  }
+
+ /* handle 2 systf acc objects that require checking to distinguish */
+ /* distinguish real from non real case */
+ __acc_vpi_erroff = TRUE;
+ vpi_get_systf_info((vpiHandle) object_handle, &systfdat);
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1952,
+    "acc_fetch_type unable to access systf_info for %s object",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(0);
+  }
+ if (systfdat.sysfunctype == vpiRealFunc)
+  {
+   if (hp->hrec->htyp == vpiUserSystf) return(accUserRealFunction);
+   if (hp->hrec->htyp == vpiSysFuncCall) return(accSystemRealFunction);
+   __acc_terr(__FILE__, __LINE__);
+  }
+ if (hp->hrec->htyp == vpiUserSystf) return(accUserFunction);
+ if (hp->hrec->htyp == vpiSysFuncCall) return(accSystemFunction);
+ __acc_terr(__FILE__, __LINE__);
+ return(0);
+}
+
+/*
+ * access type as string name (not constant value)
+ */
+extern char *acc_fetch_type_str(int32 type)
+{
+ char *chp;
+
+ acc_error_flag = FALSE;
+
+ if ((chp = get_accnam(type)) == NULL)
+  {
+   __acc_err(1964,
+    "acc_fetch_type_str type value %d illegal - no type or fulltype matches", 
+    type);
+   return(NULL);
+  }
+ return(add_accstrbuf(chp));
+}
+
+/*
+ * fetch acc value using either %% or acc value structure 
+ *
+ * FIXME - need checking for legal objects
+ * LOOKATME - what returned for %% case
+ */
+extern char *acc_fetch_value(handle object_handle, char *format_str,
+ p_acc_value acc_value_p)
+{
+ int32 fvfmt, owid;
+ word32 wval, s0val, s1val;
+ struct h_t *hp;
+ s_vpi_value tmpval;
+ char s1[RECLEN];
+
+ acc_error_flag = FALSE;
+ hp = (struct h_t *) object_handle; 
+
+ if (!validate_acc_handle("acc_fetch_value", hp)) return(NULL); 
+
+ if (strcmp(format_str, "%b") == 0) fvfmt = vpiBinStrVal; 
+ else if (strcmp(format_str, "%d") == 0) fvfmt = vpiDecStrVal; 
+ else if (strcmp(format_str, "%h") == 0) fvfmt = vpiHexStrVal; 
+ else if (strcmp(format_str, "%o") == 0) fvfmt = vpiOctStrVal; 
+ /* notice this is strength string not vpi style strength record */
+ else if (strcmp(format_str, "%v") == 0) fvfmt = vpiStrengthVal; 
+ else if (strcmp(format_str, "%%") == 0)
+  {
+   if (acc_value_p == NULL)
+    {
+     __acc_err(1967,
+      "acc_fetch_value %% format illegal - value structure argument NULL");
+     return(NULL);
+    }
+   if ((fvfmt = fr_accfmt_to_vpifmt(acc_value_p->format)) == -1)
+    {
+     __acc_err(1968,
+     "acc_fetch_value %% format s_setval_value argument record format value %d illegal",
+     acc_value_p->format);
+     return(NULL);
+    }
+   __acc_vpi_erroff = TRUE;
+   tmpval.format = fvfmt;
+   /* notice for vector a/b value arrays, vpi_ allocates work storage */
+   vpi_get_value((vpiHandle) object_handle, &tmpval);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1969, "acc_fetch_value unable to access %% format type %s",
+      to_accfmtnam(__wrks1, fvfmt));
+     return(NULL);
+    }
+   /* final step - convert vpi value format to acc */
+   owid = 1;
+   if (acc_value_p->format == accVectorVal)
+    {
+     __acc_vpi_erroff = TRUE;
+     owid = vpi_get(vpiSize, (vpiHandle) object_handle);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1970,
+        "acc_fetch_value %% format accVectorVal type - unable to access object size");
+       return(NULL);
+      }
+    }
+   if (!copy_vpival_to_accval(acc_value_p, &tmpval, owid))
+    {
+     __acc_err(1971,
+      "acc_fetch_value %% format unable to fill acc_value_p record");
+    }
+   return(NULL);
+  }
+ else 
+  {
+   __acc_err(1965, "acc_fetch_value format string %s illegal", format_str);
+   return(NULL);
+  }
+ /* simple string case */
+ __acc_vpi_erroff = TRUE;
+ tmpval.format = fvfmt;
+ vpi_get_value((vpiHandle) object_handle, &tmpval);
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1966,
+    "acc_fetch_value unable to access %s format_str value of %s object",
+    format_str, to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ if (fvfmt == vpiStrengthVal)
+  {
+   /* LOOKATME - what happens if value is non strength? */
+   /* build 1 byte internal Cver strength value in word32 form vpi_ */
+   wval = (word32) tmpval.value.strength->logic;
+   if (wval != 2) 
+    {
+     s0val = __map_frvpi_stren(tmpval.value.strength->s0);
+     s1val = __map_frvpi_stren(tmpval.value.strength->s1);
+     /* form into byte and return in acc string buf */
+     wval |= (((((byte) s0val) & 7L) << 5) | ((((byte) s1val) & 7L) << 2));
+    }
+   return(add_accstrbuf(__to_vvstnam(s1, wval)));
+  }
+ return(add_accstrbuf(tmpval.value.str));
+}
+
+/*
+ * map from a acc format constant to a vpi_ format constant 
+ */
+static int32 fr_accfmt_to_vpifmt(int32 accfmt)
+{
+ switch (accfmt) {
+  case accBinStrVal: return(vpiBinStrVal);
+  case accOctStrVal: return(vpiOctStrVal);
+  case accDecStrVal: return(vpiDecStrVal);
+  case accHexStrVal: return(vpiHexStrVal);
+  case accScalarVal: return(vpiScalarVal);
+  case accIntVal: return(vpiIntVal);
+  case accRealVal: return(vpiRealVal);
+  case accStringVal: return(vpiStringVal);
+  case accVectorVal: return(vpiVectorVal);
+  default: break;
+ }
+ return(-1);
+}
+
+/*
+ * map from acc format constant to its name
+ */
+static char *to_accfmtnam(char *s, int32 accfmt)
+{
+ switch (accfmt) {
+  case accBinStrVal: strcpy(s, "accBinStrVal"); break;
+  case accOctStrVal: strcpy(s, "accOctStrVal"); break;
+  case accDecStrVal: strcpy(s, "accDecStrVal"); break;
+  case accHexStrVal: strcpy(s, "accHexStrVal"); break;
+  case accScalarVal: strcpy(s, "accScalarVal"); break;
+  case accIntVal: strcpy(s, "accIntVal"); break;
+  case accRealVal: strcpy(s, "accRealVal"); break;
+  case accStringVal: strcpy(s, "accStringVal"); break;
+  case accVectorVal: strcpy(s, "accVectorVal"); break;
+  default: __acc_terr(__FILE__, __LINE__); strcpy(s, "");
+ }
+ return(s);
+}
+
+
+/*
+ * copy a t_vpi_value record to a acc t_setval_value record
+ * this can fail if vpi value not compatible - returns F if fails
+ *
+ * caller must have allocated any needed fields in acc value record
+ */
+static int32 copy_vpival_to_accval(s_setval_value *avp, s_vpi_value *vvp,
+ int32 owid)
+{
+ int32 wlen;
+ char *chp;
+
+ /* SJM 12/17/02 - selection was from wrong vpi but almost worked */
+ /* because constants the same except for vec val gap */ 
+ switch (avp->format) {
+  case accBinStrVal: case accOctStrVal: case accDecStrVal:
+  case accHexStrVal: case accStringVal:
+   /* easy case - just copy string */
+   chp = add_accstrbuf(vvp->value.str);
+   avp->value.str = chp;
+   break;
+  case accScalarVal:
+   avp->value.scalar = vvp->value.scalar;
+   break;
+  case accIntVal:
+   avp->value.integer = vvp->value.integer;
+   break;
+  case accRealVal:
+   /* SJM 11/19/02 - this must copy real not int32 - need 8 byte copy */
+   avp->value.real = vvp->value.real;
+   break;
+  case accVectorVal:
+   wlen = wlen_(owid);
+   /* caller must have allocated right size p_acc_vecval area */
+   memmove(avp->value.vector, vvp->value.vector, 2*WRDBYTES*wlen);
+   break;
+  default: return(FALSE);
+ }
+ return(TRUE); 
+}
+
+/*
+ * free an array of objects collected by acc collect
+ *
+ * know object array has NULL ending fence
+ */
+extern void acc_free(handle *array_ptr)
+{
+ register int32 htabsiz;
+ struct h_t *hp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) array_ptr[0];
+ if (!validate_acc_handle("acc_free (first handle)", hp)) return; 
+
+ /* count and free handles inside array */
+ for (htabsiz = 0;; htabsiz++)
+  {
+   if (array_ptr[htabsiz] == NULL) break; 
+   hp = (struct h_t *) array_ptr[htabsiz];
+   __acc_vpi_erroff = TRUE;
+   /* FIXME this free is wrong because links out of vpi not acc list */
+   /* SJM 03/15/00 - must not free since following XL acc_ free does */
+   /* nothing */
+   /* ---
+   if (!vpi_free_object((vpiHandle) hp))
+    {
+     __acc_err(1996,
+      "acc_free free of object %s (pos. %d) in array failed (possible internal error)",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+    }
+   --- */
+  }
+ /* finally, free array itself */
+ __my_free((char *) array_ptr, (htabsiz + 1)*sizeof(vpiHandle));
+}
+
+/*
+ * ACC HANDLE ACCESS ROUTINES
+ */
+
+/*
+ * access an object from a local nmae
+ *
+ * LOOKATME inst_name and scope_p name meaningless
+ */
+extern handle acc_handle_by_name(char *inst_name, handle scope_p)
+{
+ struct h_t *hp;
+ vpiHandle objp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) scope_p;
+ if (hp != NULL)
+  {
+   if (!validate_acc_handle("acc_handle_by_name scope", hp)) return(NULL); 
+  } 
+
+ /* SJM 05/21/01 - following other simulators - allow in qualified name */
+ __acc_vpi_erroff = TRUE;
+ objp = vpi_handle_by_name(inst_name, (vpiHandle) scope_p); 
+ /* if just can not find name - no error just returns nil */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1714,
+    "acc_handle_by_name for object %s failed (possible internal error)",
+    inst_name);
+   return(NULL);
+  }
+ return((handle) objp);
+}
+
+/*
+ * get a timincg check terminal or module path condition expression 
+ * as handle
+ */
+extern handle acc_handle_condition(handle obj)
+{
+ vpiHandle termp;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+
+ acc_error_flag = FALSE;
+ hp = (struct h_t *) obj;
+ if (!validate_acc_handle("acc_handle_condition", hp)) return(NULL); 
+ hrp = hp->hrec;
+
+ if (hrp->htyp != vpiTchkTerm && hrp->htyp != vpiModPath)
+  {
+   __acc_err(1701,
+    "acc_handle_condition object type %s illegal - must be accModPath or accTchkTerminal",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ __acc_vpi_erroff = TRUE;
+ termp = vpi_handle(vpiCondition, (vpiHandle) obj); 
+ /* if just can not find name - no error just returns nil */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1975,
+    "acc_handle_condition for object %s failed (possible internal error)",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ return((handle) termp);
+}
+
+/*
+ * access expression object connected to 
+ *
+ * LOOKATME - think vpi_ vpiExpr 1-to-1 method works because 1 bit exprs
+ */
+extern handle acc_handle_conn(handle term_p)
+{
+ register struct hrec_t *hrp;
+ vpiHandle expr;
+ struct h_t *hp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) term_p;
+ if (!validate_acc_handle("acc_handle_conn", hp)) return(NULL); 
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiTchkTerm && hrp->htyp != vpiModPath
+  && hrp->htyp != vpiPrimTerm)
+  {
+   __acc_err(1702,
+    "acc_handle_conn object type %s illegal - must be accPathTerminal or accTchkTerminal or accTerminal",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ __acc_vpi_erroff = TRUE;
+ expr = vpi_handle(vpiExpr, (vpiHandle) term_p); 
+ /* if just can not find name - no error just returns nil */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1975,
+    "acc_handle_conn for object %s failed (possible internal error)",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ return((handle) expr);
+}
+
+/*
+ * get acc handle for data path associated with mod path if exists
+ *
+ * FIXME - this is wrong acc data path access different - how work?
+ * FIXME - need to distinguish paths with datasrcx in acc
+ * same as module path but has datapthin and datapthout
+ */
+extern handle acc_handle_datapath(handle path)
+{
+ struct h_t *hp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) path;
+ if (!validate_acc_handle("acc_handle_datapath", hp)) return(NULL); 
+ if (hp->hrec->htyp != vpiModPath)
+  {
+   __acc_err(1703,
+    "acc_handle_datapath object type %s illegal - must be edge sensitive accModPath",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ if (hp->hrec->hu.hpthp->datasrcx != NULL) return(NULL);
+ /* maybe need acc copy of this? */
+ return(path);
+}
+
+/*
+ * get highconn expression for a accPort or accPortBit 
+ *
+ * returns nil if vectored port (not passed port bit or scalar port)
+ */
+extern handle acc_handle_hiconn(handle port_ref)
+{
+ int32 bithtyp;
+ vpiHandle expr;
+ struct h_t *hp, *hp2, *hp3;
+ struct hrec_t *hrp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) port_ref;
+ if (!validate_acc_handle("acc_handle_hiconn", hp)) return(NULL); 
+ hrp = hp->hrec;
+
+ if (hrp->htyp != vpiPort && hrp->htyp != vpiPortBit)
+  {
+   __acc_err(1704,
+    "acc_handle_hiconn object type %s illegal - must be accPort or accPortBit",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ if (hrp->htyp == vpiPort && !vpi_get(vpiScalar, (vpiHandle) port_ref))
+  { 
+   __acc_err(1976,
+    "acc_handle_hiconn failed port_ref is not accPortBit or scalar accPort");
+   return(NULL);
+  }
+ __acc_vpi_erroff = TRUE;
+ expr = vpi_handle(vpiHighConn, (vpiHandle) port_ref); 
+ /* if just can not find name - no error just returns nil */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1975,
+    "acc_handle_hiconn for object %s failed (possible internal error)",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ /* must be one bit or concatenate in acc */
+ hp2 = (struct h_t *) expr;
+ switch (hp2->hrec->htyp) {
+  case vpiNet:
+   bithtyp = vpiNetBit;
+   goto bld_hiconn; 
+  case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   bithtyp = vpiRegBit;
+bld_hiconn:
+   /*for int32 or time, know this will always be T */
+   if (hp2->hrec->hu.hnp->nwid != 1)
+    {
+     /* here need to construct accBit handle of low bit */
+     hp3 = (struct h_t *) __mk_handle(bithtyp, (void *) hp->hrec->hu.hnp,
+      hp2->hin_itp, NULL); 
+     hp3->hrec->hi = 0;
+     hp3->hrec->bith_ndx = TRUE;
+     /* free object here right since copied guts and returning other handle */
+     if (!vpi_free_object(expr))
+      { __acc_terr(__FILE__, __LINE__); }
+     return((handle) hp3);
+    }
+   return((handle) expr);
+  case vpiRegBit: case vpiNetBit:
+   return((handle) expr);
+  default:
+   __acc_err(1976,
+    "acc_handle_hiconn failed - highconn object %s is not net/reg or net/reg bit select",
+    to_acc_onam(__wrks1, hp2->hrec->htyp));
+   break;
+ }
+ return(NULL);
+}
+
+/*
+ * return current interactive scope (know there always is one) 
+ * this can't fail
+ */
+extern handle acc_handle_interactive_scope(void)
+{
+ int32 typ;
+ struct mod_t *mdp;
+
+ acc_error_flag = FALSE;
+
+ if (__scope_tskp != NULL) 
+  {
+   typ = __to_vpi_tasktyp(__scope_tskp->tsktyp);
+   return((handle) __mk_handle(typ, (void *) __scope_tskp, __scope_ptr,
+    (struct task_t *) NULL)); 
+  }
+ mdp = __scope_ptr->itip->imsym->el.emdp;
+ return((handle) __mk_handle(vpiModule, (void *) mdp, __scope_ptr,
+  (struct task_t *) NULL)); 
+}
+
+/*
+ * get loconn expression for a accPort or accPortBit 
+ *
+ * returns nil if vectored port (not passed port bit)
+ */
+extern handle acc_handle_loconn(handle port_ref)
+{
+ vpiHandle expr;
+ struct h_t *hp, *hp2;
+ struct hrec_t *hrp2;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) port_ref;
+ if (!validate_acc_handle("acc_handle_loconn", hp)) return(NULL); 
+ if (hp->hrec->htyp != vpiPort && hp->hrec->htyp != vpiPortBit)
+  {
+   __acc_err(1905,
+    "acc_handle_loconn object type %s illegal - must be accPort or accPortBit",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ __acc_vpi_erroff = TRUE;
+ expr = vpi_handle(vpiLowConn, (vpiHandle) port_ref); 
+ /* if just can not find name - no error just returns nil */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1975,
+    "acc_handle_loconn for object %s failed (possible internal error)",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ /* must be one bit or concatenate in acc */
+ hp2 = (struct h_t *) expr;
+ hrp2 = hp2->hrec;
+ switch (hrp2->htyp) {
+  case vpiReg: case vpiNet: 
+   if (hrp2->hu.hnp->nwid != 1) goto bad_loconn;
+   break;
+  case vpiRegBit: case vpiNetBit:
+   break;
+  default:
+bad_loconn:
+   __acc_err(1976,
+    "acc_handle_loconn failed - loconn object %s is not scalar or bit select",
+    to_acc_onam(__wrks1, hrp2->htyp));
+   return(NULL);
+ }
+ return((handle) expr);
+}
+
+/*
+ * get handle to module path - tricky because must construct name
+ * WRITEME
+ */
+/*VARARGS*/
+extern handle acc_handle_modpath(handle mod_p, char *pathin_name,
+ char *pathout_name, ...)
+{
+ /* va_list va; */
+ __acc_err(1941, "acc_handle_modpath not yet implemented");
+ /* va_end(va); */
+ return(NULL);
+}
+
+/*
+ * access a timing check's notifier if it exists
+ */
+extern handle acc_handle_notifier(handle tchk)
+{
+ vpiHandle notifp;
+ struct h_t *hp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) tchk;
+ if (!validate_acc_handle("acc_handle_notifier", hp)) return(NULL); 
+ if (hp->hrec->htyp != vpiTchk)
+  {
+   __acc_err(1706,
+    "acc_handle_notifier object type %s illegal - must be accTchk",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ __acc_vpi_erroff = TRUE;
+ notifp = vpi_handle(vpiTchkNotifier, (vpiHandle) tchk); 
+ /* if just can not find name - no error just returns nil */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1975,
+    "acc_handle_notifier for object %s failed (possible internal error)",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ return((handle) notifp);
+}
+
+/*
+ * get acc handle from object name
+ *
+ * LOOKATME - new LRM drafts say paths using acc_ $ convention illegal
+ *            see if true?
+ */
+extern handle acc_handle_object(char *object_name)
+{
+ vpiHandle objp, scoph;
+ char s1[RECLEN];
+
+ acc_error_flag = FALSE;
+
+ if (__acc_scope_set) scoph = __acc_scope_vpiobj;
+ else
+  {
+   scoph = get_acc_current_systf("acc_handle_object");
+   if (acc_error_flag) return(NULL);
+  }
+
+ /* nil or empty string return current scope defaults to cur systf scope */
+ /* LOOKATME - should this also be used for empty string */ 
+ if (object_name == NULL)
+  {
+   objp = vpi_copy_object(scoph);
+   return((handle) objp);
+  }
+
+ __acc_vpi_erroff = TRUE;
+ /* first search for rooted - use scope next if not found */
+ objp = vpi_handle_by_name(object_name, NULL);
+ if (__my_vpi_chk_error()) goto bad_vpi;
+ if (objp != NULL) return((handle) objp);
+
+ /* then search in scope for relative */
+ objp = vpi_handle_by_name(object_name, (vpiHandle) scoph);
+ /* if just can not find name - no error just returns nil */
+ if (__my_vpi_chk_error())
+  {
+bad_vpi:
+   if (scoph == NULL) strcpy(s1, "**NONE**");
+   else sprintf(s1, "%s", vpi_get_str(vpiName, scoph));
+   __acc_err(1975,
+    "acc_handle_object search for %s in scope %s failed (possible internal error)",
+    object_name, s1);
+   return(NULL);
+  }
+ return((handle) objp);
+}
+
+/*
+ * get parent
+ *
+ * notice acc algorithm differs from vpi_ in that parent of bit of
+ * something is module not variable - cannot use vpiParent
+ *
+ * for other than port bit and prim terminal, this is like vpiModule
+ * 1-to-1 access method not parent
+ *
+ * if passed good handle, this can not fail
+ */
+extern handle acc_handle_parent(handle object_p)
+{
+ register struct hrec_t *hrp;
+ int32 typ;
+ struct h_t *hp;
+ struct itree_t *itp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object_p;
+ if (!validate_acc_handle("acc_handle_parent", hp)) return(NULL); 
+ hrp = hp->hrec;
+
+ if (hrp->htyp == vpiPrimTerm)
+  {
+   /* this is internal vpi primitive type (i.e. vpi Switch) */
+   typ = __gate_to_vpiprimtyp(hrp->hu.hgp);
+   return((handle) __mk_handle(typ, (void *) hrp->hu.hgp, hp->hin_itp, NULL)); 
+  }
+ if (hrp->htyp == vpiPortBit)
+  {
+   /* task here always nil - port indicated by hpi bit by hi */
+   return((handle) __mk_handle(vpiPort, (void *) hrp->hu.hpi, hp->hin_itp,
+    hrp->hin_tskp));
+  }
+ if (hrp->htyp == vpiModule)
+  {
+   if ((itp = hp->hin_itp->up_it) == NULL) return(NULL);  
+   return((handle) __mk_handle(vpiModule, (void *) itp->itip->imsym->el.emdp,
+    itp, NULL));
+  }
+ /* finally - anything else gets containing module */
+ return((handle)__mk_handle(vpiModule,
+  (void *) hp->hin_itp->itip->imsym->el.emdp, hp->hin_itp, NULL));
+}
+
+/*
+ * WRITEME 
+ */
+extern handle acc_handle_path(handle source, handle destination)
+{
+ __acc_err(1941, "acc_handle_path not yet implemented (only MIPDs supported)");
+ return(NULL);
+}
+
+/*
+ * get first net used in path source (path input)
+ *
+ * this directly get first pathin net - general acc_next_input method
+ * return accPathTerminal for which acc_handle_conn is used to get
+ * connected object including possible bit selects
+ *
+ * LOOKATME - for bit select LRM says still returns accNet object - check?
+ * LOOKATME - using short cut to directly access net instead of using
+ *            normal vpi 2 step to get object so is dependent on storage
+ *            of paths but eliminates dealing with bit objects
+ */
+extern handle acc_handle_pathin(handle path_p)
+{
+ struct h_t *hp, *hp2;
+ struct spcpth_t *pthp;
+ struct net_t *np;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) path_p;
+ if (!validate_acc_handle("acc_handle_pathin", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModPath)
+  { 
+   __acc_err(1734, "acc_handle_pathin: %s object illegal - accModPath required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ pthp = hp->hrec->hu.hpthp;
+ np = pthp->peins[0].penp;
+ /* can't be a task context here */
+ hp2 = (struct h_t *) __mk_handle(vpiNet, (void *) np, hp->hin_itp, NULL); 
+ return((handle) hp2);
+}
+
+/*
+ * get first net used in path dest (path output)
+ *
+ * this directly get first pathout net - general acc_next_output method
+ * return accPathTerminal for which acc_handle_conn is used to get
+ * connected object including possible bit selects
+ *
+ * LOOKATME - for bit select LRM says still returns accNet object - check?
+ * LOOKATME - using short cut to directly access net instead of using
+ *            normal vpi 2 step to get object so is dependent on storage
+ *            of paths but eliminates dealing with bit objects
+ */
+extern handle acc_handle_pathout(handle path_p)
+{
+ struct h_t *hp, *hp2;
+ struct spcpth_t *pthp;
+ struct net_t *np;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) path_p;
+ if (!validate_acc_handle("acc_handle_pathout", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModPath)
+  { 
+   __acc_err(1734, "acc_handle_pathout: %s object illegal - accModPath required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ pthp = hp->hrec->hu.hpthp;
+ np = pthp->peouts[0].penp;
+ /* can't be a task context here */
+ hp2 = (struct h_t *) __mk_handle(vpiNet, (void *) np, hp->hin_itp, NULL); 
+ return((handle) hp2);
+}
+
+/*
+ * access a module port handle using port index (order pos.) 
+ */
+/*VARARGS*/
+extern handle acc_handle_port(handle port, int32 port_num)
+{
+ struct h_t *hp, *hp2;
+ struct mod_t *mdp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) port;
+ if (!validate_acc_handle("acc_handle_port", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModule)
+  {
+   __acc_err(1708,
+    "acc_handle_port object type %s illegal - must be type accModule",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ mdp = hp->hrec->hu.hmdp;
+ if (port_num < 0 || port_num >= mdp->mpnum) 
+  {
+   __acc_err(1977,
+    "acc_handle_port accmodule port index value %d out of range", port_num);
+   return(NULL);
+  }
+ /* notice unusual vpi_ object - index is only type indicator */
+ hp2 = (struct h_t *) __mk_handle(vpiPort, NULL, hp->hin_itp, NULL); 
+ hp2->hrec->hi = port_num;
+ return((handle) hp2);
+}
+
+/*
+ * get scope that contains object
+ *
+ * LOOKATME - are acc and vpi_ scopes same?
+ */
+extern handle acc_handle_scope(handle object)
+{
+ vpiHandle scopeptr;
+ struct h_t *hp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object;
+ 
+ if (!validate_acc_handle("acc_handle_scope", hp)) return(NULL); 
+ __acc_scope_set = FALSE;
+ __acc_scope_vpiobj = NULL;
+
+ __acc_vpi_erroff = TRUE;
+ scopeptr = vpi_handle(vpiScope, (vpiHandle) object);
+ /* if just can not find name - no error just returns nil */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1709, "acc_handle_scope %s object scope access failed",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ return((handle) scopeptr);
+}
+
+/*
+ * get simulated net - always same so can not fail
+ *
+ * LOOKATME - allowing any net/var type thing
+ */
+extern handle acc_handle_simulated_net(handle net_h)
+{
+ struct h_t *hp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) net_h; 
+ if (!validate_acc_handle("acc_handle_simulated_net", hp)) return(NULL); 
+ /* only nets can be collapsed and not collapsed in Cver */
+ switch (hp->hrec->htyp) {
+  case vpiNet: case vpiNetBit:
+  case vpiReg: case vpiRegBit:
+  case vpiIntegerVar: case vpiTimeVar:
+   break;
+  default:
+   __acc_err(1710,
+    "acc_handle_simulated_net object type %s illegal - must be HDL net or net bit object",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+ }
+ return(net_h);
+}
+
+/*
+ * WRITEME
+ */
+/*VARARGS*/
+extern handle acc_handle_tchk(handle mod_p, int32 tchk_type,
+ char *arg1_conn_name, int32 arg1_edgetype, ...)
+{
+ /* va_list va; */
+ __acc_err(1941, "acc_handle_tchk not yet implemented");
+ /*va_end(va); */
+ return(NULL);
+}
+
+/*
+ * WRITEME
+ */
+extern handle acc_handle_tchkarg1(handle tchk)
+{
+ __acc_err(1941, "acc_handle_tchkarg1 not yet implemented");
+ return(NULL);
+}
+
+/*
+ * WRITEME
+ */
+extern handle acc_handle_tchkarg2(handle tchk)
+{
+ __acc_err(1941, "acc_handle_tchkarg2 not yet implemented");
+ return(NULL);
+}
+
+/*
+ * access acc primitive (gate/switch/udp) terminal by index (out is 0)
+ */
+extern handle acc_handle_terminal(handle gate_handle, int32 terminal_index)
+{
+ register struct hrec_t *hrp;
+ struct h_t *hp, *hp2;
+ struct gate_t *gp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) gate_handle;
+ if (!validate_acc_handle("acc_handle_terminal", hp)) return(NULL); 
+ hrp = hp->hrec;
+
+ if (hrp->htyp != vpiGate && hrp->htyp != vpiSwitch && hrp->htyp != vpiUdp)
+  {
+   __acc_err(1711,
+    "acc_handle_terminal object type %s illegal - must be accPrimitive",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ gp = hrp->hu.hgp;
+ if (terminal_index < 0 || terminal_index >= gp->gpnum) 
+  {
+   __acc_err(1977,
+    "acc_handle_terminal accPrimitive (%s) terminal index %d out of range",
+    to_acc_onam(__wrks1, hrp->htyp), terminal_index);
+   return(NULL);
+  }
+ hp2 = (struct h_t *) __mk_handle(vpiPrimTerm, (void *) gp, hp->hin_itp, NULL); 
+ hp2->hrec->hi = terminal_index;
+ return((handle) hp2);
+}
+
+/*
+ * access handle to currently called PLI sys tf nth argument
+ *
+ * FIXME - must also allow instances and gates are args to PLI
+ * sys tasks and funcs
+ *
+ * FIXME - special non vpi_ argument processing -
+ * must be either variable (lhs) or quoted string where look up
+ * using acc_handle_object rules
+ */
+extern handle acc_handle_tfarg(int32 n)
+{
+ register struct hrec_t *shrp;
+ vpiHandle systfp;
+ struct h_t *shp;
+ struct tskcall_t *tkcp;
+ struct expr_t *argxp;
+
+ acc_error_flag = FALSE;
+
+ if ((systfp = get_acc_current_systf("acc_handle_tfarg")) == NULL)
+  return(NULL);
+
+ /* no need to validate */
+ shp = (struct h_t *) systfp;
+ shrp = shp->hrec;
+
+ if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
+ else if (shrp->htyp == vpiSysTaskCall) 
+  {
+   tkcp = &(shrp->hu.hstp->st.stkc);
+   argxp = tkcp->targs;
+  }
+ else { __acc_terr(__FILE__, __LINE__); return(NULL); }
+
+ return(get_systf_accargobj(shp, n, argxp, "acc_handle_tfarg"));
+}
+
+/*
+ * access handle to PLI sys tf object tfinst nth argument
+ *
+ * FIXME - must also allow instances and gates are args to PLI
+ * sys tasks and funcs
+ *
+ * special non vpi_ argument processing -
+ * must be either variable (lhs) or quoted string where look up
+ * using acc_handle_object rules
+ */
+extern handle acc_handle_itfarg(int32 n, handle tfinst)
+{
+ register struct hrec_t *shrp;
+ struct h_t *shp;
+ struct expr_t *argxp;
+ struct tskcall_t *tkcp;
+
+ acc_error_flag = FALSE;
+
+ if (tfinst == NULL)
+  {
+   __acc_err(1755,
+    "acc_handle_itfarg: no argument accessed because tfinst argument NULL");
+   return(NULL);
+  }
+ 
+ shp = (struct h_t *) tfinst;
+ if (!validate_acc_handle("acc_handle_itfarg", shp)) return(NULL); 
+ shrp = shp->hrec;
+
+ if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
+ else if (shrp->htyp == vpiSysTaskCall)
+  {
+   tkcp = &(shrp->hu.hstp->st.stkc);
+   argxp = tkcp->targs;
+  }
+ else
+  {
+   __acc_err(1957,
+    "acc_handle_itfarg: tfinst %s argument illegal - must be acc system tf call",
+    to_acc_onam(__wrks1, shrp->htyp));
+   return(NULL);
+  }
+ return(get_systf_accargobj(shp, n, argxp, "acc_handle_itfarg"));
+}
+
+/*
+ * access systf nth argument handle (arguments in acc_ start at 1)
+ *
+ * FIXME - what happen when argument is instance form (no value?)
+ * FIXME - must treat literal string as argument to look up handle of
+ */
+static handle get_systf_accargobj(struct h_t *shp, int32 n,
+ struct expr_t *argxp, char *rnam)
+{
+ register int32 argi;
+ register struct expr_t *xp2;
+ int32 arglen, free_shp3;
+ vpiHandle arghp, objp;
+ struct h_t *shp2, *shp3;
+ struct mod_t *mdp;
+ char *argchp, s1[RECLEN];
+
+ /* get expression corresponding to nth argument */
+ if (n < 1)
+  {
+outofrng:
+   __acc_warn(2047, "%s: argument position %d out of range", rnam, n);
+   return(NULL);
+  }
+
+ for (argi = 0, xp2 = argxp; xp2 != NULL; xp2 = xp2->ru.x, argi++)
+  {
+   if (argi == n - 1) goto found_it;
+  }
+ goto outofrng; 
+
+found_it:
+ /* literal string is special case - must look up */
+ if (xp2->lu.x->is_string)
+  {
+   argchp = __get_eval_cstr(xp2->lu.x, &arglen);
+
+   objp = NULL;
+   shp3 = NULL;
+   free_shp3 = FALSE;
+   /* if scope set, search there first */
+   if (__acc_scope_set)
+    {
+     shp2 = (struct h_t *) __acc_scope_vpiobj;
+     __acc_vpi_erroff = TRUE;
+     /* first search for rooted - use scope next if not found */
+     objp = vpi_handle_by_name(argchp, (vpiHandle) shp2);
+     if (__my_vpi_chk_error())
+      {
+bad_vpi:
+       sprintf(s1, "%s", vpi_get_str(vpiName, (vpiHandle) shp2));
+       __acc_err(1975,
+        "%s: search for %s in scope %s failed (possible internal error)",
+        rnam, argchp, s1);
+       if (free_shp3)
+        {
+         if (!vpi_free_object((vpiHandle) shp3))
+          { __acc_terr(__FILE__, __LINE__); }
+        }
+       return(NULL);
+      }
+     if (objp != NULL)
+      {
+       __my_free(argchp, arglen + 1);
+       return((handle) objp);
+      }
+    }
+   else shp2 = NULL;
+
+   /* if not found try scope of current systf */
+   if (shp2 == NULL)
+    {
+     mdp = shp->hin_itp->itip->imsym->el.emdp;
+     /* convert from systf call vpi object to its scope object */
+     shp3 = (struct h_t *) __mk_handle(vpiModule, (void *) mdp,
+      shp->hin_itp, shp->hrec->hin_tskp);
+     free_shp3 = TRUE;
+
+     /* if current scope and systf scope name, no reason to search again */
+     objp = NULL;
+     if (shp2 != NULL
+      && vpi_compare_objects((vpiHandle) shp3, (vpiHandle) shp2) == 0)
+      goto done_ret;
+
+     __acc_vpi_erroff = TRUE;
+     /* first search for rooted - use scope next if not found */
+     objp = vpi_handle_by_name(argchp, (vpiHandle) shp3);
+     if (__my_vpi_chk_error()) goto bad_vpi;
+     if (objp != NULL) goto done_ret;
+
+     /* finally see if rooted XMR */
+     __acc_vpi_erroff = TRUE;
+     /* first search for rooted - use scope next if not found */
+     objp = vpi_handle_by_name(argchp, NULL);
+     if (__my_vpi_chk_error()) goto bad_vpi;
+
+done_ret:
+     if (!vpi_free_object((vpiHandle) shp3))
+      { __acc_terr(__FILE__, __LINE__); }
+    }
+   __my_free(argchp, arglen + 1);
+   return((handle) objp);
+  }
+ /* think anything legal here except LCB */
+ if (xp2->lu.x->optyp == LCB)
+  {
+   __acc_err(1960,
+    "%s: argument %d illegal argument - must be lvalue or literal string",
+    rnam, n);
+   return(NULL);
+  }
+
+ /* FIXME - tf arg instance argument core dumps */
+ /* this can not currently fail */
+ arghp = __mk_exprclass_handle(xp2->lu.x, shp->hin_itp, shp->hrec->hin_tskp);
+
+ return((handle) arghp);
+}
+
+/*
+ * get acc handle of calling accSysFunc[type] or accSysTask
+ */
+extern handle acc_handle_tfinst(void)
+{
+ vpiHandle systfp;
+ 
+ acc_error_flag = FALSE;
+
+ systfp = get_acc_current_systf("acc_handle_tfinst");
+ return((handle) systfp);
+}
+
+/*
+ * initialize acc interface
+ *
+ * usually each acc application calls this to start and acc cloxe to end 
+ * following XL, initialial values are used if this is not called
+ *
+ * LOOKATME - think normal way to use acc_ is to start with this
+ * and end processing with close - way of freeing storage
+ */
+extern bool acc_initialize(void)
+{
+ if (__acc_open)
+  {
+   __acc_warn(2044,
+    "acc_initialize called more than once - re-initializing anyway");
+  }
+
+ /* LOOKATME - must not change internal state */
+
+ /* LRM requires reset of configuration parameters at initialize anc close */
+ init_acc_config();
+ __acc_open = TRUE;
+ return(TRUE);
+}
+
+/*
+ * initialize routine acc config 
+ */
+static void init_acc_config(void)
+{
+ char s1[RECLEN];
+
+ __acc_defaultattr0 = FALSE;
+
+ sprintf(s1, "%s%s of %s\n", __vers, __vers2, __ofdt);
+ if (__acc_developmentversion != NULL)
+  __my_free(__acc_developmentversion, strlen(__acc_developmentversion) + 1);
+ __acc_developmentversion = __my_malloc(strlen(s1) + 1);
+ strcpy(__acc_developmentversion, s1);
+
+ __acc_displayerrors = TRUE;
+ __acc_displaywarnings = FALSE;
+ __acc_enableargs_pth = FALSE;
+ __acc_enableargs_tchk = FALSE;
+ __acc_enableargs_setscope = FALSE;
+ __acc_maptomipd = ACCMAPTOMIP_MAX;
+ __acc_mintypmaxdelays = FALSE;
+ __acc_pathdelaycount = 6;
+
+ strcpy(s1, "$");
+ if (__acc_pathdelimstr != NULL)
+   __my_free(__acc_pathdelimstr, strlen(__acc_pathdelimstr) + 1);
+ __acc_pathdelimstr = __my_malloc(strlen(s1) + 1);
+ strcpy(__acc_pathdelimstr, s1);
+
+ __acc_tohizdelay = ACCTOHIZ_FROMUSER;
+}
+
+/*
+ * ROUTINES TO IMPLEMENT TYPE LIST GENERAL ACC NEXT 
+ */
+
+/*
+ * repeatedly call acc_next for each element of array
+ *
+ * first time call this construct iterator containing all objects
+ * iterator will contain various types of handles
+ *
+ * FIXME - why is accSpecParam not in this list?
+ * LOOKATME - assuming for cells only cells in given cell or module scope
+ * LOOKATME - for parameters assuming reg is acc int32 param type
+ */
+extern handle acc_next(int32 *type_list, handle h_scope, handle h_object)
+{
+ register int32 iti; 
+ int32 itsiz;
+ struct h_t *hp, *hp2;
+ vpiHandle ihref, nxth;
+ struct pviter_t *iterp;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ if (h_scope != NULL)
+  {
+   hp = (struct h_t *) h_scope;
+   if (!validate_acc_handle("acc_next", hp)) return(NULL); 
+  } 
+
+ /* first time build "giant" all inclusive iterator */
+ if (h_object == NULL)
+  {
+   itsiz = bld_accnext_iter(type_list, h_scope);
+   /* now have construct iterator in ith table */
+   if (itsiz == 0) return(NULL);
+
+   /* build the iterator since ith tab only tmp work tab */
+   iterp = __alloc_iter(itsiz, &ihref);
+   /* copy from work accumulator ith tab into new iterator */
+   /* copy is from 1st arg to 2nd */
+   memcpy(iterp->scanhtab, __aithtab, itsiz*sizeof(struct h_t));
+   memcpy(iterp->ihrectab, __aithrectab, itsiz*sizeof(struct hrec_t));
+
+   for (iti = 0; iti < itsiz; iti++)
+    {
+     iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
+    }
+
+   /* add iterator to special acc_next list and retur*/
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+   __aiter_accnxt_list = NULL; 
+   aip->aiternxt = __aiter_accnxt_list;
+   __aiter_accnxt_list = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) h_object;
+ if (!validate_acc_handle("acc_next", hp2)) return(NULL); 
+ if ((aip = find_aiter_rec(__aiter_accnxt_list, hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next last object not returned by previous acc_next call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL)
+  { linkout_accnext_aiter(aip); return(NULL); }
+
+ return((handle) nxth);
+}
+
+/*
+ * routine to build iterator for each legal acc next() acc_ object type
+ *
+ * checks, emit errors and returns iterator if one is built
+ * return NULL if nothing in iterator or error
+ *
+ * this allocates iterator first time then adds to one passed
+ */
+static int32 bld_accnext_iter(int32 *atyp_list, handle scope_h)
+{
+ register int32 iti2, hi;
+ int32 oi, accnum, has_err, rm_cells, itsiz, vntyp, vpiotyp, gclass, gtyp;
+ vpiHandle ihref;
+ struct h_t *scope_hp, *ihp; 
+ struct pviter_t *iterp;
+ char *onamchp;
+
+ has_err = FALSE;
+ scope_hp = (struct h_t *) scope_h;
+ ihref = NULL;
+ for (oi = 0, iti2 = 0;; oi++)
+  {
+   if ((accnum = atyp_list[oi]) == 0) break;
+   
+   if ((onamchp = get_accnam(accnum)) == NULL)
+    {
+     __acc_err(1971,
+      "acc_next type_list array (pos. %d) illegal acc_ object number %d",
+      oi + 1, accnum);
+     has_err = TRUE;
+     continue;
+    }
+   /* know legal acc object but nil only legal for module (insts) */
+   if (scope_hp == NULL)
+    {
+     /* acc Top module is full type of acc Module so either legal */
+     if (accnum != accTopModule && accnum != accModule)
+      {
+       __acc_warn(2048,
+        "acc_next array (pos. %d) %s object not accTopModule but h_scope handle NULL - no objects found",
+        oi + 1, onamchp);
+       continue;
+      }
+    }
+   else
+    {
+     if (accnum == accTopModule)
+      {
+       __acc_warn(2053,
+       "acc_next array (pos. %d) accTopModule object but h_scope handle non NULL - no objects found",
+        oi + 1);
+       continue;
+      }
+    }
+
+   switch (accnum) {
+    /* type is module - any module (including top) */
+    case accModule: case accTopModule:
+    case accModuleInstance: case accCellInstance:
+     if (scope_hp != NULL)
+      {
+       if (!nd_modscope(scope_hp)) { has_err = TRUE; continue; }
+      }
+   
+     /* know scope consistent with module type or full type */ 
+     __acc_vpi_erroff = TRUE;
+     /* scope handle can be nil */
+     ihref = vpi_iterate(vpiModule, (vpiHandle) scope_h);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1983,
+        "acc_next with type_list element %s - error finding first",
+        onamchp);
+       has_err = TRUE;
+       continue;
+      }
+     /* nothing in iterator - nothing to add */
+     if (ihref == NULL) continue;
+
+     /* no filtering needed - copy all elements to iterator */
+     if (accnum == accModule || accnum == accTopModule) break; 
+     ihp = (struct h_t *) ihref;
+     rm_cells = (accnum == accModuleInstance) ? TRUE : FALSE;
+     iti2 = cellinst_addto_iter(ihref, iti2, rm_cells);
+     continue;
+
+    /* variables that are types themselves but grouped together in vpi_ */ 
+    case accIntegerVar: vntyp = N_INT; goto do_varnxt;
+    case accRealVar: vntyp = N_REAL; goto do_varnxt;
+    case accTimeVar: vntyp = N_TIME;
+
+do_varnxt:
+     /* know scope hp not nil, if nil will not get here */
+     if (!nd_anyscope(scope_hp)) { has_err = TRUE; continue; }
+
+     __acc_vpi_erroff = TRUE;
+     ihref = vpi_iterate(vpiVariables, (vpiHandle) scope_h);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1983,
+        "acc_next with type_list element %s - error finding first", onamchp);
+       has_err = TRUE;
+       continue;
+      }
+     /* nothing in iterator - nothing to add */
+     if (ihref == NULL) continue;
+     /* filter only right variable type */
+     iti2 = var_addto_iter(ihref, iti2, vntyp);
+     continue;
+
+    case accNamedEvent:
+     vpiotyp = vpiNamedEvent;  
+     goto do_regnxt;
+    case accRegister:
+     vpiotyp = vpiReg;
+     /* these have exact vpi iterators defined */
+do_regnxt:
+     /* know scope hp not nil, if nil will not get here */
+     if (!nd_anyscope(scope_hp)) { has_err = TRUE; continue; }
+
+     __acc_vpi_erroff = TRUE;
+     ihref = vpi_iterate(vpiotyp, (vpiHandle) scope_h);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1983,
+        "acc_next with type_list element %s - error finding first", onamchp);
+       has_err = TRUE;
+       continue;
+      }
+     /* nothing in iterator - nothing to add */
+     if (ihref == NULL) continue;
+     /* entire iterator added */
+     break;
+
+     /* net is type - no subtype include entire iterator */
+     case accNet:
+      /* net type unused but set to catch error */
+      vntyp = 0;
+      goto do_netnxt;
+      
+     /* these are full types of net */
+     /* notice wand, triand, etc. same function but separated here */
+     case accWire: vntyp = N_WIRE; goto do_netnxt;
+     case accTri: vntyp = N_TRI; goto do_netnxt; 
+     case accWand: vntyp = N_WA; goto do_netnxt;
+     case accTriand: vntyp = N_TRIAND; goto do_netnxt;
+     case accWor: vntyp = N_WO; goto do_netnxt;
+     case accTrior: vntyp = N_TRIOR; goto do_netnxt;
+     case accTri0: vntyp = N_TRI0; goto do_netnxt;
+     case accTri1: vntyp = N_TRI1; goto do_netnxt;
+     case accSupply0: vntyp = N_SUPPLY0; goto do_netnxt;
+     case accSupply1: vntyp = N_SUPPLY1; goto do_netnxt;
+     case accTrireg:
+      vntyp = N_TRIREG;
+
+do_netnxt:
+     /* know scope hp not nil, if nil will not get here */
+     if (!nd_anyscope(scope_hp)) { has_err = TRUE; continue; }
+
+     __acc_vpi_erroff = TRUE;
+     ihref = vpi_iterate(vpiNet, (vpiHandle) scope_h);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1983,
+        "acc_next with type_list element %s - error finding first", onamchp);
+       has_err = TRUE;
+       continue;
+      }
+     /* nothing in iterator - nothing to add */
+     if (ihref == NULL) continue;
+     /* entire iterator added if net */
+     if (accnum == accNet) break;
+
+     /* filter net fulltypes */
+     iti2 = var_addto_iter(ihref, iti2, vntyp);
+     break; 
+
+    /* any parameter */
+    case accParameter:
+    /* these are full types of parameter */
+    case accIntegerParam: case accRealParam: case accStringParam:
+     /* know scope hp not nil, if nil will not get here */
+     /* parameters can be in any scope */
+     if (!nd_anyscope(scope_hp)) { has_err = TRUE; continue; }
+
+     __acc_vpi_erroff = TRUE;
+     ihref = vpi_iterate(vpiParameter, (vpiHandle) scope_h);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1983,
+        "acc_next with type_list element %s - error finding first", onamchp);
+       has_err = TRUE;
+       continue;
+      }
+     /* nothing in iterator - nothing to add */
+     if (ihref == NULL) continue;
+     /* entire iterator added if net */
+     if (accnum == accParameter) break;
+
+     /* filter net fulltypes */
+     iti2 = param_addto_iter(ihref, iti2, accnum);
+     continue;
+
+    /* primitives - first is all others need full type filtering */
+    case accPrimitive: gclass = 0; gtyp = 0; goto do_primnxt;
+
+    /* these are full types of primitive */
+    case accAndGate: gclass = vpiGate; gtyp = G_BITREDAND; goto do_primnxt;
+    case accNandGate: gclass = vpiGate; gtyp = G_NAND; goto do_primnxt;
+    case accNorGate: gclass = vpiGate; gtyp = G_NOR; goto do_primnxt;
+    case accOrGate: gclass = vpiGate; gtyp = G_BITREDOR; goto do_primnxt;
+    case accXnorGate: gclass = vpiGate; gtyp = G_REDXNOR; goto do_primnxt;
+    case accXorGate: gclass = vpiGate; gtyp = G_BITREDXOR; goto do_primnxt;
+    case accBufGate: gclass = vpiGate; gtyp = G_BUF; goto do_primnxt;
+    case accNotGate: gclass = vpiGate; gtyp = G_NOT; goto do_primnxt;
+    case accBufif0Gate: gclass = vpiGate; gtyp = G_BUFIF0; goto do_primnxt;
+    case accBufif1Gate: gclass = vpiGate; gtyp = G_BUFIF1; goto do_primnxt;
+    case accNotif0Gate: gclass = vpiGate; gtyp = G_NOTIF0; goto do_primnxt;
+    case accNotif1Gate: gclass = vpiGate; gtyp = G_NOTIF1; goto do_primnxt;
+    case accNmosGate: gclass = vpiGate; gtyp = G_NMOS; goto do_primnxt;
+    case accPmosGate: gclass = vpiGate; gtyp = G_PMOS; goto do_primnxt;
+    case accRnmosGate: gclass = vpiGate; gtyp = G_RNMOS; goto do_primnxt;
+    case accRpmosGate: gclass = vpiGate; gtyp = G_RPMOS; goto do_primnxt;
+    case accCmosGate: gclass = vpiGate; gtyp = G_CMOS; goto do_primnxt;
+    case accRcmosGate: gclass = vpiGate; gtyp = G_RCMOS; goto do_primnxt;
+    case accRtranGate: gclass = vpiSwitch; gtyp = G_RTRAN; goto do_primnxt;
+    case accRtranif0Gate:
+     gclass = vpiSwitch; gtyp = G_RTRANIF0; goto do_primnxt;
+    case accRtranif1Gate:
+     gclass = vpiSwitch; gtyp = G_RTRANIF1; goto do_primnxt;
+    case accTranGate: gclass = vpiSwitch; gtyp = G_TRAN; goto do_primnxt;
+    case accTranif0Gate: gclass = vpiSwitch; gtyp = G_TRANIF0; goto do_primnxt;
+    case accTranif1Gate: gclass = vpiSwitch; gtyp = G_TRANIF1; goto do_primnxt;
+    case accPulldownGate: gclass = vpiGate; gtyp = G_PULLDOWN; goto do_primnxt;
+    case accPullupGate: gclass = vpiGate; gtyp = G_PULLUP; goto do_primnxt;
+    case accSeqPrim: gclass = vpiUdp; gtyp = vpiSeqPrim; goto do_primnxt;
+    case accCombPrim: gclass = vpiUdp; gtyp = vpiCombPrim; 
+
+do_primnxt:
+     /* know scope hp not nil, if nil will not get here */
+     if (!nd_anyscope(scope_hp)) { has_err = TRUE; continue; }
+
+     __acc_vpi_erroff = TRUE;
+     ihref = vpi_iterate(vpiNet, (vpiHandle) scope_h);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1983,
+        "acc_next with type_list element %s - error finding first", onamchp);
+       has_err = TRUE;
+       continue;
+      }
+     /* nothing in iterator - nothing to add */
+     if (ihref == NULL) continue;
+     /* entire iterator added if net */
+     if (accnum == accNet) break;
+
+     /* filter net fulltypes */
+     iti2 = prim_addto_iter(ihref, iti2, gclass, gtyp);
+     continue;
+
+    default:
+     __acc_err(1971,
+      "acc_next array (pos. %d) %s object illegal in object_type_array",
+      oi + 1, onamchp);
+     has_err = TRUE;
+     continue;
+   }
+
+   /* non filtering case, copy entire iterator into accumulator */
+   ihp = (struct h_t *) ihref;
+   iterp = ihp->hrec->hu.hiterp;
+   if (iterp->numhs + iti2 >= __aithtsiz)
+    __grow_acc_htab((iterp->numhs + iti2) - __aithtsiz);
+
+   itsiz = iterp->numhs;
+
+   /* copy IS from 1st arg to 2nd */
+   memcpy(&(__aithtab[iti2]), iterp->scanhtab, itsiz*sizeof(struct h_t));
+   memcpy(&(__aithrectab[iti2]), iterp->ihrectab,
+    itsiz*sizeof(struct hrec_t));
+
+   iti2 += itsiz;
+   /* SJM 10/23/00 - must reconnect all cross links in case relloced */
+   /* LOOKATME - really only need to reconnect from old size up */
+   for (hi = 0; hi < iti2; hi++)
+    {
+     __aithtab[hi].hrec = &(__aithrectab[hi]);
+    }
+   acc_internal_itfree(ihp);
+  }
+ return(iti2);
+}
+
+/*
+ * check for scope that must be module
+ */
+static int32 nd_modscope(struct h_t *hp)
+{
+ if (hp->hrec->htyp != vpiModule)
+  {
+   __acc_err(1725, "acc_next: scope object %s illegal must be accModule",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * check for scope that must be module
+ */
+static int32 nd_anyscope(struct h_t *hp)
+{
+ switch (hp->hrec->htyp) {
+  case vpiModule: case vpiTask: case vpiFunction:
+  case vpiNamedBegin: case vpiNamedFork:
+   break;
+  default:
+   __acc_err(1726, "acc_next: scope_h %s illegal - not required scope object",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * add to accumlator iterator with cell/inst filtering
+ * returns new size of accumulator iterator table
+ *
+ * know iterator contains at least one element but may not add any
+ * area inserted is from passed iti2 to iti2 + num hs in new iterator
+ */
+static int32 cellinst_addto_iter(vpiHandle ihref, int32 iti2, int32 rm_cells)
+{
+ register int32 iti;
+ register struct h_t *hp2;
+ register struct pviter_t *iterp;
+ struct mod_t *mdp;
+ struct h_t *ihp;
+
+ ihp = (struct h_t *) ihref;
+ iterp = ihp->hrec->hu.hiterp;
+ for (iti = 0; iti < iterp->numhs; iti++)
+  {
+   hp2 = &(iterp->scanhtab[iti]);
+   mdp = hp2->hin_itp->itip->imsym->el.emdp;
+   /* remove if wrong full type */
+   if (rm_cells) { if (mdp->m_iscell) continue; }
+   else { if (!mdp->m_iscell) continue; }
+
+   /* SJM 11/02/04 - previous fix was wrong - this must be htat size not 2 */
+   if (iti2 >= __aithtsiz) __grow_acc_htab(1);
+
+   /* know no malloced expr to deal with - but must copy 2 parts */
+   __aithrectab[iti2] = *(hp2->hrec);   
+   __aithtab[iti2] = *hp2;
+   /* only need to set cross link in newly added one */
+   __aithtab[iti2].hrec = &(__aithrectab[iti2]);
+   iti2++;
+  }
+ acc_internal_itfree(ihp);
+ return(iti2);
+}
+
+/*
+ * free internal work acc_ iterator (version one - know know alloc exprs)
+ *
+ * free iterator struct and tables but know no allocated expr
+ */
+static void acc_internal_itfree(struct h_t *ihp)
+{
+ register struct pviter_t *iterp;
+
+ iterp = ihp->hrec->hu.hiterp;
+
+ /* free both 8 byte handle object and hrec */
+ /* need real free or high water mark for these internals too high */
+ __my_free((char *) iterp->scanhtab, iterp->numhs*sizeof(struct h_t));
+ __my_free((char *) iterp->ihrectab, iterp->numhs*sizeof(struct hrec_t));
+ __my_free((char *) iterp, sizeof(struct pviter_t));
+ /* zero and free and put on vpi handle free list */
+ __free_hp(ihp);
+}
+
+/*
+ * add to accumlator iterator with filtered net type for variables
+ * returns new size of accumulator iterator table
+ *
+ * 2 uses: separates variable (real, time, int32) and separate nets
+ * into subtype
+ *
+ * know iterator contains at least one element but may not add any
+ */
+static int32 var_addto_iter(vpiHandle ihref, int32 iti2, int32 vntyp)
+{
+ register int32 iti;
+ register struct h_t *hp2;
+ register struct pviter_t *iterp;
+ struct net_t *np;
+ struct h_t *ihp;
+
+ ihp = (struct h_t *) ihref;
+ iterp = ihp->hrec->hu.hiterp;
+
+ for (iti = 0; iti < iterp->numhs; iti++)
+  {
+   hp2 = &(iterp->scanhtab[iti]);
+   np = hp2->hrec->hu.hnp;
+   /* know this is one of real, integer, or time */
+   if (np->ntyp != vntyp) continue;
+
+   if (iti2 >= __aithtsiz) __grow_acc_htab(1);
+   /* know no malloced expr to deal with - but must copy 2 parts */
+   __aithrectab[iti2] = *(hp2->hrec);   
+   __aithtab[iti2] = *hp2;
+   /* just need to set cross link in newly added one */
+   __aithtab[iti2].hrec = &(__aithrectab[iti2]);
+   iti2++;
+  }
+ acc_internal_itfree(ihp);
+ return(iti2);
+}
+
+/*
+ * add to accumlator iterator with filtered param type 
+ * returns new size of accumulator iterator table
+ *
+ * LOOKATME - making all non string and non real 
+ *
+ * know iterator contains at least one element but may not add any
+ */
+static int32 param_addto_iter(vpiHandle ihref, int32 iti2, int32 aotyp)
+{
+ register int32 iti;
+ register struct h_t *hp2;
+ register struct pviter_t *iterp;
+ struct h_t *ihp;
+ struct net_t *np;
+
+ ihp = (struct h_t *) ihref;
+ iterp = ihp->hrec->hu.hiterp;
+
+ for (iti = 0; iti < iterp->numhs; iti++)
+  {
+   hp2 = &(iterp->scanhtab[iti]);
+   np = hp2->hrec->hu.hnp;
+
+   if (aotyp == accIntegerParam)
+    {
+     if (np->ntyp == N_REAL || np->nu.ct->pstring) continue;
+    }
+   else if (aotyp == accRealParam)
+    {
+     if (np->ntyp != N_REAL) continue;
+    }
+   else if (aotyp == accStringParam)
+    {
+     if (np->ntyp == N_REAL) continue;
+     if (!np->nu.ct->pstring) continue;
+    }
+   else __acc_terr(__FILE__, __LINE__);
+
+   if (iti2 >= __aithtsiz) __grow_acc_htab(1);
+   /* know no malloced expr to deal with - but must copy 2 parts */
+   __aithrectab[iti2] = *(hp2->hrec);   
+   __aithtab[iti2] = *hp2;
+   /* only need to set cross link in newly added one */
+   __aithtab[iti2].hrec = &(__aithrectab[iti2]);
+   iti2++;
+  }
+ acc_internal_itfree(ihp);
+ return(iti2);
+}
+
+/*
+ * add to accumlator iterator with filtered primitive full type
+ * returns new size of accumulator iterator table
+ *
+ * called with primitive full type and filters out all but passed gate
+ * full type
+ *
+ * know iterator contains at least one element but may not add any
+ */
+static int32 prim_addto_iter(vpiHandle ihref, int32 iti2, int32 gclass, int32 gtyp)
+{
+ register int32 iti;
+ register struct h_t *hp2;
+ register struct pviter_t *iterp;
+ int32 pclasstyp;
+ struct primtab_t *ptp;
+ struct h_t *ihp;
+ struct gate_t *gp;
+
+ ihp = (struct h_t *) ihref;
+ iterp = ihp->hrec->hu.hiterp;
+
+ for (iti = 0; iti < iterp->numhs; iti++)
+  {
+   hp2 = &(iterp->scanhtab[iti]);
+
+   gp = hp2->hrec->hu.hgp;
+
+   /* filter out non full type matching by continuing */
+   if (gp->g_class == GC_UDP)
+    {
+     if (gclass != vpiUdp) continue;
+
+     if (gp->gmsym->el.eudpp->utyp == U_COMB)
+      { if (gtyp != vpiCombPrim) continue; }
+     else { if (gtyp != vpiSeqPrim) continue; }
+    }
+   else
+    {
+     /* if gate class do not match, do not check more */
+     pclasstyp = __gate_to_vpiprimtyp(gp);
+     if (pclasstyp != gclass) continue;
+     ptp = gp->gmsym->el.eprimp; 
+     if (ptp->gateid != gtyp) continue;
+    } 
+
+   /* grow by 3/2 fibronacci + 1 for new element */
+   if (iti2 >= __aithtsiz) __grow_acc_htab(1);
+   /* know no malloced expr to deal with - but must copy 2 parts */
+   __aithrectab[iti2] = *(hp2->hrec);   
+   __aithtab[iti2] = *hp2;
+   /* only need to set cross link in newly added one */
+   __aithtab[iti2].hrec = &(__aithrectab[iti2]);
+   iti2++;
+  }
+ acc_internal_itfree(ihp);
+ return(iti2);
+}
+
+/*
+ * grow acc work handle table (must add at least addnum)
+ *
+ * whenever size expanded must reset cross links - only acc world ptrs
+ */
+extern void __grow_acc_htab(int32 addnum)
+{
+ register int32 iti;
+ int32 old_aithtsiz, nnum, osize, nsize, ohrsize, nhrsize;
+
+ /* only allocate if accessing driver/load style handles at all */ 
+ if (__aithtsiz == 0)
+  {
+   nnum = 1000 + addnum;
+   __aithtab = (struct h_t *) __my_malloc(nnum*sizeof(struct h_t));
+   __aithrectab = (struct hrec_t *) __my_malloc(nnum*sizeof(struct hrec_t));
+   __aithtsiz = nnum; 
+   /* since was empty, no need to set cross links */
+   return;
+  }
+
+ old_aithtsiz = __aithtsiz;
+ osize = old_aithtsiz*sizeof(struct h_t);
+ ohrsize = old_aithtsiz*sizeof(struct hrec_t);
+ __aithtsiz = addnum + (3*__aithtsiz)/2; 
+ nsize = __aithtsiz*sizeof(struct h_t);
+ nhrsize = __aithtsiz*sizeof(struct hrec_t);
+ __aithtab = (struct h_t *) __my_realloc((char *) __aithtab, osize, nsize);
+ __aithrectab = (struct hrec_t *) __my_realloc((char *) __aithrectab,
+  ohrsize, nhrsize);
+
+ /* SJM 10/23/00 - must reconnect all cross links in case relloced */
+ /* just need to reset all in previous copied part */
+ for (iti = 0; iti < old_aithtsiz; iti++)
+  { __aithtab[iti].hrec = &(__aithrectab[iti]); }
+}
+
+/*
+ * grow 2nd for subtree processing  global work handle table
+ */
+extern void __grow_acc_htab2(int32 addnum)
+{
+ register int32 iti;
+ int32 old_aithtsiz2, nnum, osize, nsize, ohrsize, nhrsize;
+
+ /* only allocate if accessing driver/load style handles at all */ 
+ if (__aithtsiz2 == 0)
+  {
+   nnum = 1000 + addnum;
+   __aithtab2 = (struct h_t *) __my_malloc(nnum*sizeof(struct h_t));
+   __aithrectab2 = (struct hrec_t *) __my_malloc(nnum*sizeof(struct hrec_t));
+   __aithtsiz2 = nnum; 
+   return;
+  }
+ old_aithtsiz2 = __aithtsiz2;
+ osize = old_aithtsiz2*sizeof(struct h_t);
+ ohrsize = old_aithtsiz2*sizeof(struct hrec_t);
+ __aithtsiz2 = addnum + (3*__aithtsiz2)/2; 
+ nsize = __aithtsiz2*sizeof(struct h_t);
+ nhrsize = __aithtsiz2*sizeof(struct hrec_t);
+ __aithtab2 = (struct h_t *) __my_realloc((char *) __aithtab2, osize, nsize);
+ __aithrectab2 = (struct hrec_t *) __my_realloc((char *) __aithrectab2,
+  ohrsize, nhrsize);
+
+ /* SJM 10/23/00 - must reconnect all cross links in case relloced */
+ /* just need to reset all in previous copied part */
+ for (iti = 0; iti < old_aithtsiz2; iti++)
+  { __aithtab2[iti].hrec = &(__aithrectab2[iti]); }
+}
+
+/*
+ * ROUTINES TO IMPLEMENT OBJECT SPECIFIC ACC NEXT
+ */
+
+/*
+ * get next bit from port, vector, or path terminal
+ *
+ * scalars (one bit) treated as one bit vector here (returns object itself)
+ */
+extern handle acc_next_bit(handle vector, handle bit)
+{  
+  register struct hrec_t *hrp;
+ struct h_t *hp;
+  
+  acc_error_flag = FALSE;
+  
+  hp = (struct h_t *) vector;
+  if (!validate_acc_handle("acc_next_bit", hp)) return(NULL); 
+  hrp = hp->hrec;
+  
+  if (hrp->htyp == vpiPort) return(portbit_accnext(vector, bit));
+  
+  /* LOOKATME - are bits of int32 and time var accessible - think yes */
+  if (hrp->htyp == vpiNet || hrp->htyp == vpiReg || hrp->htyp == vpiIntegerVar
+   || hrp->htyp == vpiTimeVar) 
+   {
+    return(netbit_accnext(vector, bit));
+   }
+  if (hrp->htyp == vpiPathTerm)
+   {
+    /* WRITEME */
+    __acc_err(1941, "acc_next_bit for accPathTerminal not yet implemented");
+    return(NULL);
+   }
+  __acc_err(1728, "acc_next_bit: object %s does not have next bit",
+   to_acc_onam(__wrks1, hrp->htyp));
+  return(NULL);
+}
+
+/*
+ * do acc next bit for port bits
+ */
+static handle portbit_accnext(handle port, handle bit)
+{
+ struct h_t *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ /* build the iterator since this is first time */
+ if (bit == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiBit, (vpiHandle) port);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_bit error finding first accPortBit");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   /* SJM 02/11/00 - table indexed by object returned not by iterator */
+   aip->aiternxt = __aiter_tab[vpiPortBit]; 
+   __aiter_tab[vpiPortBit] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) bit;
+ if (!validate_acc_handle("acc_next_bit", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiPortBit)
+  {
+   wrong_nxtobj_error("acc_next_bit", hp2->hrec->htyp, accPortBit); 
+   return(NULL);
+  }
+ if ((aip = find_aiter_rec(__aiter_tab[vpiPortBit], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_bit last accPortBit object not returned by previous acc_next_bit call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL)
+  { linkout_aiter(aip, vpiPortBit, FALSE); return(NULL); }
+
+ return((handle) nxth);
+}
+
+/*
+ * do acc next bit for net/reg bits
+ */
+static handle netbit_accnext(handle vector, handle bit)
+{
+ int32 vpibtyp;
+ struct h_t *hp, *hp2; 
+ struct net_t *np;
+ vpiHandle ihref, nxth;
+ struct pviter_t *iterp;
+ struct acciter_t *aip;
+ struct hrec_t *hrp;
+
+ hp = (struct h_t *) vector;
+ hrp = hp->hrec;
+ np = hrp->hu.hnp;
+ if (hrp->htyp == vpiReg) vpibtyp = vpiRegBit;
+ else if (hrp->htyp == vpiIntegerVar || hrp->htyp == vpiTimeVar)
+  vpibtyp = vpiVarSelect;
+ else if (hrp->htyp == vpiNet) vpibtyp = vpiNetBit;
+ else 
+  { 
+   __acc_err(1983, "acc_next_bit for object %s llegal",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (bit == NULL)
+  {
+   /* scalars are legal and just return the one bit */
+   if (!np->n_isavec)
+    {
+     /* can not use vpi iterate for scalars */
+     /* LOOKATME - is this really a bit handle for a scalar - LRM say so */
+     /* build special 1 element acc iterator - then treat as normal case */
+     iterp = __alloc_iter(1, &ihref);
+     hp2 = &(iterp->scanhtab[0]);
+     if (np->ntyp >= NONWIRE_ST) hp2->hrec->htyp = vpiRegBit;
+     else hp2->hrec->htyp = vpiNetBit;
+     hp2->hrec->hu.hnp = np; 
+     hp2->hrec->bith_ndx = TRUE;
+     hrp->hi = 0;
+     hp2->hin_itp = hp->hin_itp;
+    }
+   else
+    {
+     __acc_vpi_erroff = TRUE;
+     ihref = vpi_iterate(vpiBit, (vpiHandle) vector);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1983, "acc_next_bit error finding first %s",
+        to_acc_onam(__wrks1, vpibtyp));
+       return(NULL);
+      }
+     /* can only happen if empty or error for bit of iterators */
+     if (ihref == NULL) return(NULL);
+    }
+
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+   /* using type of vector handle (master object) */ 
+   /* SJM 02/11/00 - table indexed by object returned not by iterator */
+   aip->aiternxt = __aiter_tab[vpibtyp]; 
+   __aiter_tab[vpibtyp] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) bit;
+ if (!validate_acc_handle("acc_next_bit", hp2)) return(NULL); 
+
+ if (hp2->hrec->htyp != vpibtyp)
+  {
+   struct vpi_to_acc_t *accvpip;
+
+   /* SJM 05/14/01 - error needs acc type not vpi */
+   accvpip = &(vpi_to_acc[hp->hrec->htyp]);
+   wrong_nxtobj_error("acc_next_bit", hp2->hrec->htyp,
+    accvpip->acc_otyp);
+   return(NULL);
+  }
+
+ if ((aip = find_aiter_rec(__aiter_tab[vpibtyp], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_bit last %s object not returned by previous acc_next_bit call",
+    to_acc_onam(__wrks1, hp2->hrec->htyp));
+   return(NULL);
+  }
+ ihref = (vpiHandle) aip->aiter;
+ nxth = vpi_scan(ihref);
+ if (nxth == NULL) { linkout_aiter(aip, vpibtyp, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * find right iterator given type (vpi) and previous 
+ *
+ * linear search needed but will normally be only one
+ */
+static struct acciter_t *find_aiter_rec(register struct acciter_t *aip,
+ struct h_t *lasthp)
+{
+ struct pviter_t *iterp; 
+ struct h_t *ihp, *hp2;
+
+ for (; aip != NULL; aip = aip->aiternxt)
+  {
+   ihp = aip->aiter;
+   /* DBG remove -- */
+   if (ihp->hrec == NULL) __acc_terr(__FILE__, __LINE__);
+   /* -- */
+   iterp = ihp->hrec->hu.hiterp;
+   
+   /* DBG remove -- */
+   if (iterp->nxthi == 0) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   hp2 = &(iterp->scanhtab[iterp->nxthi - 1]);
+   /* last object must be point to exactly same address */ 
+   /* ??? FIXME - this must match last returned or error - where emitted */
+   if (lasthp == hp2) return(aip); 
+  }
+ return(NULL);
+}
+
+/*
+ * get next cell for all module instances under scope
+ *
+ * stop at cells but descend into module instances
+ * no vpi_ iterator for all cells under - must build special acc iterator
+ */
+extern handle acc_next_cell(handle scope, handle cell)
+{
+ struct h_t *hp, *hp2, *ihp; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) scope;
+ if (!validate_acc_handle("acc_next_cell", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModule)
+  {
+   __acc_err(1729, "acc_next_cell: scope object %s illegal must be accModule",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ hp = (struct h_t *) scope;
+ /* build the iterator since this is first time */
+ if (cell == NULL)
+  {
+   /* SJM 10/23/00 - no vpi iterator since need special acc cells build */
+   /* although this is not vpi_ iterator build as special inst (mod) type */
+   /* if empty iterator so nothing ih tab this returns nil */
+   ihp = (struct h_t *) bld_acc_cells_iter(hp);
+   if (ihp == NULL) return(NULL);
+   ihref = (vpiHandle) ihp;
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiModule]; 
+   __aiter_tab[vpiModule] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) cell;
+ if (!validate_acc_handle("acc_next_cell", hp2)) return(NULL); 
+
+ if (hp2->hrec->htyp != vpiModule 
+  || !hp2->hin_itp->itip->imsym->el.emdp->m_iscell)
+  {
+   wrong_nxtobj_error("acc_next_cell", hp2->hrec->htyp, accModule); 
+   return(NULL);
+  }
+
+ /* LOOKATME could emit error if not under scope - but caught here */ 
+ if ((aip = find_aiter_rec(__aiter_tab[vpiModule], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_cell last accModule (accCellInstance) object not returned by previous acc_next_cell call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiModule, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * build cells under instance scope iterator - only for acc
+ */
+static vpiHandle bld_acc_cells_iter(struct h_t *hp)
+{
+ register int32 iti;
+ int32 num, cnum;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+
+ /* collect all cells and instances into first ith tab iterator */
+ /* number used is num */
+ if ((num = collect_loc_insts(hp)) == 0) return(NULL);
+
+ /* copy from aithtab to aithtab2 descending into instances to find cells */ 
+ cnum = addto_acc_cells_iter(hp, num, 0);
+ if (cnum == 0) return(NULL);
+
+ /* build the new iterator from 2nd work ithtab */
+ iterp = __alloc_iter(cnum, &ihref);
+ memcpy(iterp->scanhtab, __aithtab2, cnum*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __aithrectab2, cnum*sizeof(struct hrec_t));
+
+ for (iti = 0; iti < cnum; iti++)
+  {
+   iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
+  }
+ return(ihref);
+}
+
+/*
+ * collect local cells and instances into iterator
+ * hp is scope under which all instances are collected
+ *
+ * places cells into work ith tab that is over-written
+ */
+static int32 collect_loc_insts(struct h_t *hp)
+{
+ register int32 ii;
+ register struct hrec_t *hrp2;
+ struct itree_t *itp, *itp2;
+ struct h_t *hp2;
+ struct mod_t *mdp;
+
+ itp = hp->hin_itp;
+ mdp = itp->itip->imsym->el.emdp;
+ for (ii = 0; ii < mdp->minum; ii++)
+  {
+   if (ii >= __aithtsiz) __grow_acc_htab(1);
+   hp2 = &(__aithtab[ii]);
+   hrp2 = &(__aithrectab[ii]);
+   __init_hrec(hrp2);
+
+   /* not using alloc iter so need to set in iter bit explicitly */
+   hrp2->in_iter = TRUE;
+   hrp2->htyp = vpiModule;
+   itp2 = &(itp->in_its[ii]);
+   hrp2->hu.hmdp = itp2->itip->imsym->el.emdp;
+   hp2->hin_itp = itp2;
+   /* only need to set cross link in newly added one */
+   __aithtab[ii].hrec = &(__aithrectab[ii]);
+  }
+ return(mdp->minum);
+}
+
+/*
+ * add to local loads inside itree loc as net/bit handle hp
+ *
+ * know first work ith tab filled with local loads 
+ * fill (add to) second work ith tab2 starting at cnum
+ *
+ * FIXME why is hp not used
+ */
+static int32 addto_acc_cells_iter(struct h_t *hp, int32 locnum, int32 cnum)
+{
+ register int32 ii;
+ int32 newcnum;
+ struct h_t *hp2;
+ struct mod_t *mdp;
+
+ for (ii = 0; ii < locnum; ii++)
+  {
+   hp2 = &(__aithtab[ii]); 
+   mdp = hp2->hin_itp->itip->imsym->el.emdp;
+   /* if cell add (move copying guts) and do not descend */
+   if (mdp->m_iscell)
+    {
+     if (cnum >= __aithtsiz2)
+      { 
+       __grow_acc_htab2(cnum - __aithtsiz2 + 1);
+      }
+     /* can copy guts because original not used after this loop */
+     __aithtab2[cnum] = *hp2;
+     __aithrectab2[cnum] = *(hp2->hrec);
+     /* cross connect only the current one */
+     __aithtab2[cnum].hrec = &(__aithrectab2[cnum]);
+     cnum++;
+     continue;
+    }
+
+   /* if instance descend and copy cells in */
+   /* this fills (and over-writes) first ith tab that is then copied */
+   /* into final table starting at point just after last one added */
+   newcnum = collect_loc_insts(hp2);
+   if (newcnum == 0) continue;
+   cnum = addto_acc_cells_iter(hp2, newcnum, cnum);
+  }
+ return(cnum);
+}
+
+/*
+ * get primitive terminal in cell (only one) loads (inputs) of a net 
+ *
+ * this is same as vpiLoad except 1) only primitive terminals,
+ * 2) only terminals in cells, 3) only one terminal per cell
+ */
+extern handle acc_next_cell_load(handle net_handle, handle load)
+{
+ return(do_acc_next_ld_drv("acc_next_cell_load", net_handle, load));
+}
+
+/*
+ * execute any acc_next load or drivers iterators
+ *
+ * all the same except for building the vpi iterator
+ */
+static handle do_acc_next_ld_drv(char *rtnnam, handle net_handle, 
+ handle ld_drv)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) net_handle;
+ if (!validate_acc_handle(rtnnam, hp)) return(NULL); 
+
+ /* net handle must be scalar reg/net or reg/net bit */
+ if (hp->hrec->htyp == vpiNet || hp->hrec->htyp == vpiReg)
+  {
+   if (hp->hrec->hu.hnp->nwid != 1)
+    {
+     __acc_err(1982,
+      "%s %s vector illegal - only net/reg bit or scalar allowed",
+      rtnnam, to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(NULL);
+    }
+  }
+ else if (hp->hrec->htyp != vpiNetBit && hp->hrec->htyp != vpiRegBit)
+  { 
+   __acc_err(1731, "%s: %s object illegal net_handle", rtnnam,
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (ld_drv == NULL)
+  {
+   if (strcmp(rtnnam, "acc_next_cell_load") == 0)
+    ihref = bld_cell_load_iter(hp);
+   else if (strcmp(rtnnam, "acc_next_load") == 0)
+    ihref = bld_load_iter(hp);
+   else if (strcmp(rtnnam, "acc_next_driver") == 0)
+    ihref = bld_driver_iter(hp);
+   else { __acc_terr(__FILE__, __LINE__); return(NULL); }
+
+   /* can only happen if error for bit of iterators */
+   if (ihref == NULL) return(NULL);
+
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   /* using vpiPrimitive since that is "acc" only(?) possible driver/load */
+   aip->aiternxt = __aiter_tab[vpiPrimTerm]; 
+   __aiter_tab[vpiPrimTerm] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) ld_drv;
+ if (!validate_acc_handle(rtnnam, hp2)) return(NULL); 
+
+ if (hp2->hrec->htyp != vpiPrimTerm)
+  {
+   wrong_nxtobj_error(rtnnam, hp2->hrec->htyp, accTerminal); 
+   return(NULL);
+  }
+
+ /* LOOKATME could emit error if not in subtree - but caught here */ 
+ if ((aip = find_aiter_rec(__aiter_tab[vpiPrimTerm], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "%s last accTerminal object not returned by previous %s call",
+    rtnnam, rtnnam);
+   return(NULL);
+  }
+ ihref = (vpiHandle) aip->aiter;
+ nxth = vpi_scan(ihref);
+ /* SJM 02/11/99 - this must be prim terminal - was wrong net */
+ if (nxth == NULL) { linkout_aiter(aip, vpiPrimTerm, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * build the cell load prim term only iterator
+ *
+ * build vpi load iterator then filter out any not primitive terminals,
+ * and not in cells and >1 terminal per cell
+ *
+ * this builds free then builds final iterator
+ */
+static vpiHandle bld_cell_load_iter(struct h_t *hp)
+{
+ register int32 iti;
+ int32 iti2, iti3, *ndcptab;
+ struct h_t *hp2, *hp3, *ihp;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct mod_t *mdp;
+
+ __acc_vpi_erroff = TRUE;
+ ihref = vpi_iterate(vpiLoad, (vpiHandle) hp);
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1983, "acc_next_cell_load error finding first %s",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ /* if no loads, must pass nil up */
+ if (ihref == NULL) return(NULL);
+
+ ihp = (struct h_t *) ihref;
+ iterp = ihp->hrec->hu.hiterp;
+ /* go through iterator copying only terminals in cells into aith tab */
+ /* also elminate non primitive vpi but not acc_ terminals here */
+ for (iti = iti2 = 0; iti < iterp->numhs; iti++)
+  {
+   hp2 = &(iterp->scanhtab[iti]);
+   mdp = hp2->hin_itp->itip->imsym->el.emdp;
+   if (!mdp->m_iscell) continue;
+   /* SJM 11/02/04 - ### ??? does this need to be removed not match PLI book */
+   if (hp2->hrec->htyp != vpiPrimTerm) continue;
+
+   if (iti2 >= __aithtsiz) __grow_acc_htab(1);
+   /* can copy guts because know these are prim terms with no ptrs */
+   __aithtab[iti2] = *hp2;
+   __aithrectab[iti2] = *(hp2->hrec);
+   /* only need to set cross link in newly added one */
+   __aithtab[iti2].hrec = &(__aithrectab[iti2]); 
+   iti2++;
+  }
+ if (iti2 == 0) return(NULL);
+
+ /* filter out more than one terminal in cell copying by marking */
+ /* FIXME - this is slow (n**2) - should build array and sort for next */
+ /* marking needed because must always return first in cell */
+
+ ndcptab = (int32 *) __my_malloc(iti2*sizeof(int32));
+ /* assume all are copied */
+ for (iti = 0; iti < iti2; iti++) ndcptab[iti] = TRUE; 
+
+ for (iti = 0; iti < iti2; iti++)
+  {
+   /* since copying only first, if this is repeated after first ignore */
+   if (!ndcptab[iti]) continue;
+   hp2 = &(__aithtab[iti]);
+   for (iti3 = iti + 1; iti3 < iti2; iti3++)
+    {
+     /* already marked not to copy */
+     if (!ndcptab[iti3]) continue;
+
+     hp3 = &(__aithtab[iti3]);
+     if (hp2->hin_itp == hp3->hin_itp) 
+      {
+       /* mark after first to not copy - must keep looking */
+       ndcptab[iti3] = FALSE;
+      }
+    }
+  }
+ /* now copy into second ith tab */
+ for (iti = 0, iti3 = 0; iti < iti2; iti++)
+  {
+   if (ndcptab[iti])
+    {
+     /* SJM 11/30/04 - since growning htab2 must test against htab2 size */
+     if (iti3 >= __aithtsiz2) __grow_acc_htab2(1);
+     /* can copy guts because know these are prim terms with no ptrs */
+     __aithtab2[iti3] = __aithtab[iti];
+     __aithrectab2[iti3] = *(__aithtab[iti].hrec);
+     /* only need to set cross link in newly added one */
+     __aithtab2[iti3].hrec = &(__aithrectab2[iti3]); 
+     iti3++;
+    }
+  }
+ __my_free((char *) ndcptab, iti2*sizeof(int32));
+ /* final step is to free old iterator and build new one */
+ acc_internal_itfree(ihp);
+ iterp = __alloc_iter(iti3, &ihref);
+
+ /* copying only bodies works because not expressions */
+ memcpy(iterp->scanhtab, __aithtab2, iti3*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __aithrectab2, iti3*sizeof(struct hrec_t));
+
+ for (iti = 0; iti < iti3; iti++)
+  {
+   iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
+  }
+ return(ihref);
+}
+
+/*
+ * get accModule (instances) inside mod_handle 
+ *
+ * if mod_handle is nil, get top modules
+ */
+extern handle acc_next_child(handle mod_handle, handle child)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ /* nil scope case - same as acc next topmod */
+ if (mod_handle == NULL)
+  {
+   return(do_acc_child_topmod("acc_next_child (NULL scope)", child));
+  }
+
+ hp = (struct h_t *) mod_handle;
+ if (!validate_acc_handle("acc_next_child", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModule)
+  {
+   __acc_err(1732, "acc_next_child: scope object %s illegal must be accModule",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (child == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiModule, (vpiHandle) mod_handle);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_child error finding first child accModule");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiModule]; 
+   __aiter_tab[vpiModule] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) child;
+ if (!validate_acc_handle("acc_next_child", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiModule)
+  {
+   wrong_nxtobj_error("acc_next_child", hp2->hrec->htyp, accModule); 
+   return(NULL);
+  }
+ /* last object must be inside mod_handle instance */
+ if (hp2->hin_itp->up_it != hp->hin_itp)
+  {
+   __acc_err(1979,
+    "acc_next_child previous child handle wrong - not contained in %s",
+    __msg2_blditree(__wrks1, hp->hin_itp));  
+   return(NULL);
+  } 
+ if ((aip = find_aiter_rec(__aiter_tab[vpiModule], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_child last accModule object not returned by previous acc_next_child call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiModule, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * get primitive terminal in cell (only one) drivers (outputs) of a net 
+ *
+ * this is same as vpiDriver except 1) only primitive terminals,
+ */
+extern handle acc_next_driver(handle net, handle driver)
+{
+ return(do_acc_next_ld_drv("acc_next_driver", net, driver));
+}
+
+/*
+ * build the acc driver prim term only iterator
+ *
+ * build vpi driver iterator then filter out any non primitive terminals
+ * this maniplates (reallocs) guts of iterator
+ */
+static vpiHandle bld_driver_iter(struct h_t *hp)
+{
+ register int32 iti;
+ int32 iti2;
+ struct h_t *hp2, *ihp;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+
+ __acc_vpi_erroff = TRUE;
+ ihref = vpi_iterate(vpiDriver, (vpiHandle) hp);
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1983, "acc_next_driver error finding first %s",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ /* if no drivers, must pass nil up */
+ if (ihref == NULL) return(NULL);
+
+ ihp = (struct h_t *) ihref;
+ iterp = ihp->hrec->hu.hiterp;
+ /* go through iterator copying only terminals in cells into aith tab */
+ /* also elminate non primitive vpi but not acc_ terminals here */
+ for (iti = iti2 = 0; iti < iterp->numhs; iti++)
+  {
+   hp2 = &(iterp->scanhtab[iti]);
+   if (hp2->hrec->htyp != vpiPrimTerm) continue;
+
+   if (iti2 >= __aithtsiz) __grow_acc_htab(1);
+   /* can copy guts because know these are prim terms with no ptrs */
+   __aithtab[iti2] = *hp2;
+   __aithrectab[iti2] = *(hp2->hrec);
+   /* only need to set cross link in newly added one */
+   __aithtab[iti2].hrec = &(__aithrectab[iti2]);
+   iti2++;
+  }
+ if (iti2 == 0) return(NULL);
+
+ /* final step is to free old iterator and build new one */
+ acc_internal_itfree(ihp);
+
+ iterp = __alloc_iter(iti2, &ihref);
+
+ /* copying only bodies works because not expressions */
+ memcpy(iterp->scanhtab, __aithtab, iti2*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __aithrectab, iti2*sizeof(struct hrec_t));
+
+ for (iti = 0; iti < iti2; iti++)
+  {
+   iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
+  }
+ return(ihref);
+}
+
+/*
+ * get next hiconn bit of a port
+ *
+ * this is for vector ports (or scalar where just one bit is returned)
+ * works for bit selects, part selects, and vectored ports (not concat?)
+ */
+extern handle acc_next_hiconn(handle port, handle hiconn)
+{
+ return(do_acc_next_hilo_conn("acc_next_hiconn", port, hiconn, TRUE));
+}
+
+/*
+ * get next hiconn or loconn bit of a port (routine does both)
+ *
+ * this is for vector ports (or scalar where just one bit is returned)
+ * works for bit selects, part selects, and vectored ports (not concat?)
+ *
+ * best way in acc_ to do this is first get port bit then use
+ * acc handle hicon to get the high conn bit
+ * 
+ * if scalar port just returns the highconn (at most one) else gets
+ * each bit of vector in turn
+ *
+ * LOOKATME - what happens for hiconn that is not reg/net scalar or bit
+ *
+ * LOOKATME - there is discussion in P1364 task force notes on problems
+ * with this
+ */
+static handle do_acc_next_hilo_conn(char *rtnnam, handle port, handle conn,
+ int32 is_hiconn)
+{
+ register int32 iti;
+ int32 nbits;
+ struct h_t *hp, *hp2, *hp3, *ihp;
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+ struct pviter_t *iterp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) port;
+ if (!validate_acc_handle(rtnnam, hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiPort)
+  {
+   __acc_err(1733, "%s: object %s illegal must be accPort", rtnnam,
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (conn == NULL)
+  {
+   /* case 1: scalar port - special case with only one to return */
+   if (vpi_get(vpiScalar, (vpiHandle) port))
+    {
+     if (is_hiconn) return(acc_handle_hiconn((handle) port));
+     else return(acc_handle_loconn((handle) port));
+    }
+
+   /* case 2: vector - first build vpiPortBit iterator */
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiPortBit, (vpiHandle) port);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1985, "%s error separating port into accPortBit(s)", rtnnam);
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+
+   ihp = (struct h_t *) ihref;
+   iterp = ihp->hrec->hu.hiterp;
+   /* must build each of the acc highconn */  
+   nbits = iterp->numhs;
+   /* DBG remove -- */
+   if (nbits <= 0) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   for (iti = 0; iti < nbits; iti++)
+    {
+     hp2 = &(iterp->scanhtab[iti]);
+     /* unc. (NULL) possible here */
+     if (is_hiconn) hp3 = (struct h_t *) acc_handle_hiconn((handle) hp2);
+     else hp3 = (struct h_t *) acc_handle_loconn((handle) hp2);
+     if (hp3 == NULL)
+      {
+       __acc_err(1986,
+        "%s error - iterator imposible - some bits unconnected", rtnnam);
+       /* no hiconn to free since returned nil */
+       acc_internal_itfree(hp2);
+       return(NULL);
+      }
+     if (iti >= __aithtsiz) __grow_acc_htab(1);
+     /* can copy guts because know these are scalars or non expr bits */
+     __aithtab[iti] = *hp3;
+     __aithrectab[iti] = *(hp3->hrec);
+     /* only need to set cross link in newly added one */
+     __aithtab[iti].hrec = &(__aithrectab[iti]);
+
+     /* free vpi_object since contents copied */
+     if (!vpi_free_object((vpiHandle) hp3))
+      { __acc_terr(__FILE__, __LINE__); }
+    }
+   /* free old iterator and build new one */
+   acc_internal_itfree(ihp);
+   iterp = __alloc_iter(nbits, &ihref);
+   /* copying only bodies works because not expressions */
+   memcpy(iterp->scanhtab, __aithtab, nbits*sizeof(struct h_t));
+   memcpy(iterp->ihrectab, __aithrectab, nbits*sizeof(struct hrec_t));
+
+   for (iti = 0; iti < nbits; iti++)
+    {
+     iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
+    }
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiPortBit]; 
+   __aiter_tab[vpiPortBit] = aip;
+   aip->aiterprev = NULL;
+
+   /* LOOKATME - much faster to just get object from scanhtab but for */
+   /* now leaving extra checking */
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+
+ /* get next from previously built iterator */
+ hp2 = (struct h_t *) conn;
+ /* case 1: scalar port - know at most one connection */
+ if (vpi_get(vpiScalar, (vpiHandle) port))
+  { 
+   /* free vpi_object since contents copied */
+   /* SJM 03/15/00 - must not free since not part of copied iterator */  
+   /* ---
+   if (!vpi_free_object((vpiHandle) hp2))
+    { __acc_terr(__FILE__, __LINE__); }
+   -- */
+   return(NULL);
+  }
+ /* case 2: vector port */
+ if (!validate_acc_handle(rtnnam, hp2)) return(NULL); 
+ /* lots of different types of handles possible here */
+ if ((aip = find_aiter_rec(__aiter_tab[vpiPortBit], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "%s last net or reg scalar or bit object not returned by previous %s call",
+    rtnnam, rtnnam);
+   return(NULL);
+  }
+
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiPortBit, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * WRITEME
+ */
+extern handle acc_next_input(handle path, handle pathin)
+{
+ __acc_err(1941, "acc_next_input (for path inputs) not yet implemented");
+ return(NULL);
+}
+
+/*
+ * get primitive terminal loads (inputs) of a net 
+ *
+ * this is same as vpiLoad except 1) only primitive terminals,
+ */
+extern handle acc_next_load(handle net, handle load)
+{
+ return(do_acc_next_ld_drv("acc_next_load", net, load));
+}
+
+/*
+ * build the acc load prim term only iterator
+ *
+ * build vpi driver iterator then filter out any non primitive terminals
+ * this maniplates (reallocs) guts of iterator
+ *
+ * differs from cell load iterator because includes all prim term
+ * drivers on net and also include instances that are not cells
+ */
+static vpiHandle bld_load_iter(struct h_t *hp)
+{
+ register int32 iti;
+ int32 iti2;
+ struct h_t *ihp, *hp2;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+
+ __acc_vpi_erroff = TRUE;
+ ihref = vpi_iterate(vpiLoad, (vpiHandle) hp);
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1983, "acc_next_load error finding first %s",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ if (ihref == NULL) return(NULL);
+ ihp = (struct h_t *) ihref;
+ iterp = ihp->hrec->hu.hiterp;
+ /* go through iterator copying only terminals in cells into aith tab */
+ /* also elminate non primitive vpi but not acc_ terminals here */
+ for (iti = iti2 = 0; iti < iterp->numhs; iti++)
+  {
+   hp2 = &(iterp->scanhtab[iti]);
+   if (hp2->hrec->htyp != vpiPrimTerm) continue;
+
+   if (iti2 >= __aithtsiz) __grow_acc_htab(1);
+   /* can copy guts because know these are prim terms with no ptrs */
+   __aithtab[iti2] = *hp2;
+   __aithrectab[iti2] = *(hp2->hrec);
+   /* only need to set cross link in newly added one */
+   __aithtab[iti2].hrec = &(__aithrectab[iti2]); 
+   iti2++;
+  }
+
+ /* to free old iterator and probably build new one unless empty */
+ acc_internal_itfree(ihp);
+ if (iti2 == 0) return(NULL);
+
+ iterp = __alloc_iter(iti2, &ihref);
+ /* copying only bodies works because not expressions */
+ memcpy(iterp->scanhtab, __aithtab, iti2*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __aithrectab, iti2*sizeof(struct hrec_t));
+
+ for (iti = 0; iti < iti2; iti++)
+  {
+   iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
+  }
+ return(ihref);
+}
+
+/*
+ * get next loconn bit of a port
+ *
+ * this is for vector ports (or scalar where just one bit is returned)
+ * works for bit selects, part selects, and vectored ports (not concat?)
+ *
+ * loconn at least must be lhs and never width mismatch (vpi handles)
+ */
+extern handle acc_next_loconn(handle port, handle loconn)
+{
+ return(do_acc_next_hilo_conn("acc_next_loconn", port, loconn, FALSE));
+}
+
+/*
+ * return next module path in module mod_p
+ * normal contents of module iterator
+ */
+extern handle acc_next_modpath(handle mod_p, handle path)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) mod_p;
+ if (!validate_acc_handle("acc_next_modpath", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModule)
+  { 
+   __acc_err(1734, "acc_next_modpath: %s object illegal - accModule required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (path == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiModPath, (vpiHandle) mod_p);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_modpath error finding first accModPath");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiModPath]; 
+   __aiter_tab[vpiModPath] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) path;
+ if (!validate_acc_handle("acc_next_modpath", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiModPath)
+  {
+   wrong_nxtobj_error("acc_next_modpath", hp2->hrec->htyp, accModPath); 
+   return(NULL);
+  }
+ if ((aip = find_aiter_rec(__aiter_tab[vpiModPath], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_modpath last accModPath object not returned by previous acc_next_modpath call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiModPath, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * get next net
+ *
+ * notice this is only for nets - use acc_next with array to get other
+ * variable tupes
+ */
+extern handle acc_next_net(handle mod_handle, handle net)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) mod_handle;
+ if (!validate_acc_handle("acc_next_net", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModule)
+  { 
+   __acc_err(1735, "acc_next_net: %s object illegal - accModule required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (net == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiNet, (vpiHandle) mod_handle);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_net error finding first accNet");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+
+
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiNet]; 
+   __aiter_tab[vpiNet] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) net;
+ if (!validate_acc_handle("acc_next_net", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiNet)
+  {
+   wrong_nxtobj_error("acc_next_net", hp2->hrec->htyp, accNet); 
+   return(NULL);
+  }
+ if ((aip = find_aiter_rec(__aiter_tab[vpiNet], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_net last accNet object not returned by previous acc_next_net call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiNet, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * link out iterator that is finished from list
+ *
+ * SJM 10/11/99 - scan frees iterator when nil reached so do not do here
+ * unless free iter flag true
+ */
+static void linkout_aiter(struct acciter_t *aip, int32 otyp, int32 iter_free)
+{
+ if (iter_free) __free_iterator((vpiHandle) aip->aiter); 
+
+ /* always link out from acc_ iterator list */
+ if (aip->aiterprev != NULL) aip->aiterprev->aiternxt = aip->aiternxt;
+ else __aiter_tab[otyp] = aip->aiternxt;
+ if (aip->aiternxt != NULL) aip->aiternxt->aiterprev = aip->aiterprev;
+}
+
+/*
+ * link out iterator that is finished from accnext list
+ */
+static void linkout_accnext_aiter(struct acciter_t *aip)
+{
+ /* always link out from acc_ iterator list */
+ if (aip->aiterprev != NULL) aip->aiterprev->aiternxt = aip->aiternxt;
+ else __aiter_accnxt_list = aip->aiternxt;
+ if (aip->aiternxt != NULL) aip->aiternxt->aiterprev = aip->aiterprev;
+}
+
+
+/*
+ * WRITEME
+ */
+extern handle acc_next_output(handle path, handle pathout)
+{
+ __acc_err(1941, "acc_next_output (for path outputs) not yet implemented");
+ return(NULL);
+}
+
+/*
+ * get next parameter 
+ *
+ * parameter arrays never seen here
+ */
+extern handle acc_next_parameter(handle module_p, handle param)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) module_p;
+ if (!validate_acc_handle("acc_next_parameter", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModule)
+  { 
+   __acc_err(1736,
+    "acc_next_parameter: %s object illegal - accModule required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (param == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiParameter, (vpiHandle) module_p);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_parameter error finding first accParameter");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiParameter]; 
+   __aiter_tab[vpiParameter] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) param;
+ if (!validate_acc_handle("acc_next_parameter", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiParameter)
+  {
+   wrong_nxtobj_error("acc_next_parameter", hp2->hrec->htyp, accParameter); 
+   return(NULL);
+  }
+ if ((aip = find_aiter_rec(__aiter_tab[vpiParameter], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_parameter last accParameter object not returned by previous acc_next_parameter call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiParameter, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * get next port (all port types including inputs)
+ *
+ * if ref obj is a net or reg - all ports connected to net or reg
+ */
+extern handle acc_next_port(handle ref_obj_p, handle port)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) ref_obj_p;
+ if (!validate_acc_handle("acc_next_port", hp)) return(NULL); 
+
+ switch (hp->hrec->htyp) {
+  case vpiModule: case vpiNet: case vpiNetBit: case vpiReg: case vpiRegBit:
+  case vpiIntegerVar: case vpiTimeVar: case vpiVarSelect:
+   break;
+  default: 
+   __acc_err(1737, "acc_next_port: object %s illegal ref_obj_p - must be accModule or net/reg object",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (port == NULL)
+  {
+   /* if ref obj is net or reg, vpi iterator works right and gets ports */ 
+   /* connected to net - this can not be bit form */
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiPort, (vpiHandle) ref_obj_p);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_port error finding first accPort");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiPort]; 
+   __aiter_tab[vpiPort] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) port;
+ if (!validate_acc_handle("acc_next_port", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiPort)
+  {
+   wrong_nxtobj_error("acc_next_port", hp2->hrec->htyp, accPort); 
+   return(NULL);
+  }
+ if ((aip = find_aiter_rec(__aiter_tab[vpiPort], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_port last accPort object not returned by previous acc_next_port call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiPort, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * get next port (only outputs and inouts)
+ *
+ * here mod_p can not
+ */
+extern handle acc_next_portout(handle mod_p, handle port)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+ struct mod_t *mdp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) mod_p;
+ if (!validate_acc_handle("acc_next_portout", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModule)
+  {
+   __acc_err(1738, "acc_next_portout: object %s illegal - accModule required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (port == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiPort, (vpiHandle) mod_p);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_portout error finding first output accPort");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+
+   /* remove input ports from iterator */
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   if ((ihref = rem_ins_from_iter(mdp, ihref)) == NULL) return(NULL); 
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiPort]; 
+   __aiter_tab[vpiPort] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) port;
+ if (!validate_acc_handle("acc_next_portout", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiPort)
+  {
+   wrong_nxtobj_error("acc_next_portout", hp2->hrec->htyp, accPort); 
+   return(NULL);
+  }
+ if ((aip = find_aiter_rec(__aiter_tab[vpiPort], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_portout last accPort object not returned by previous acc_next_portout call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiPort, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * go through port iterator removing all input ports
+ * 
+ * know iterator only contains ports
+ * must pass containing module because iterator objects no itree loc.
+ */
+static vpiHandle rem_ins_from_iter(struct mod_t *mdp, vpiHandle ihref) 
+{
+ register int32 iti, iti2;
+ struct h_t *hp2, *ihp; 
+ struct pviter_t *iterp;
+ struct mod_pin_t *mpp;
+
+ ihp = (struct h_t *) ihref;
+ iterp = ihp->hrec->hu.hiterp;
+ /* go through iterator copying only terminals in cells into aith tab */
+ /* also elminate non primitive vpi but not acc_ terminals here */
+ for (iti = iti2 = 0; iti < iterp->numhs; iti++)
+  {
+   hp2 = &(iterp->scanhtab[iti]);
+   mpp = &(mdp->mpins[hp2->hrec->hu.hpi]);
+   if (mpp->mptyp == IO_IN) continue;
+
+   if (iti2 >= __aithtsiz) __grow_acc_htab(1);
+   /* can copy guts because know these are prim terms with no ptrs */
+   __aithtab[iti2] = *hp2;
+   __aithrectab[iti2] = *(hp2->hrec);
+   /* only need to set cross link in newly added one */
+   __aithtab[iti2].hrec = &(__aithrectab[iti2]);
+   iti2++; 
+  }
+ if (iti2 == 0) return(NULL);
+
+ /* final step is to free old iterator and build new one */
+ acc_internal_itfree(ihp);
+ iterp = __alloc_iter(iti2, &ihref);
+ /* copying only bodies works because not expressions */
+ memcpy(iterp->scanhtab, __aithtab, iti2*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __aithrectab, iti2*sizeof(struct hrec_t));
+
+ for (iti = 0; iti < iti2; iti++)
+  {
+   iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
+  }
+ return(ihref);
+}
+
+/*
+ * return handle to next primitive - gate, udp, switch
+ *
+ * can not use vpi_ iterators because acc_ no internal storage
+ * always just uses last (or nil) to get next 
+ */
+extern handle acc_next_primitive(handle mod_handle, handle prim)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) mod_handle;
+ if (!validate_acc_handle("acc_next_primitive", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModule)
+  {
+   __acc_err(1739, "acc_next_primitive: object %s illegal - accModule required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (prim == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiPrimitive, (vpiHandle) mod_handle);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_primitive error finding first accPrimitive");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   /* LOOKATME - this is slightly wrong since returned object are one of */
+   /* 3 gate types - using iterator access object works since consistent */
+   aip->aiternxt = __aiter_tab[vpiPrimitive]; 
+   __aiter_tab[vpiPrimitive] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) prim;
+ if (!validate_acc_handle("acc_next_primitive", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiGate && hp2->hrec->htyp != vpiUdp
+  && hp2->hrec->htyp != vpiSwitch)
+  {
+   wrong_nxtobj_error("acc_next_primitive", hp2->hrec->htyp, accPrimitive); 
+   return(NULL);
+  }
+ if ((aip = find_aiter_rec(__aiter_tab[vpiPrimitive], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_primitive last accPrimitive object not returned by previous acc_next_primitive call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiPrimitive, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * emit current handle wrong type error
+ */
+static void wrong_nxtobj_error(char *nxtrtnam, int32 htyp, int32 ndacctyp)
+{
+ char *chp, s1[RECLEN];
+
+ /* should never happen since vpi handles validated */
+ /* DBG remove -- */
+ if (ndacctyp == -1)__acc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ chp = get_accnam(ndacctyp);
+ /* DBG remove -- */
+ if (chp == NULL) __acc_terr(__FILE__, __LINE__);
+ /* --- */
+ __acc_err(1981, "%s current handle wrong type (%s) - %s required",
+  nxtrtnam, to_acc_onam(s1, htyp), chp);
+}
+
+/*
+ * allociate new acc iterator record
+ */
+static struct acciter_t *alloc_aiter(void)
+{
+ struct acciter_t *aip;
+
+ if (__aiter_freelst != NULL)
+  { 
+   aip = __aiter_freelst;
+   aip = __aiter_freelst->aiternxt;
+  }
+ else aip = (struct acciter_t *) __my_malloc(sizeof(struct acciter_t));
+ init_aiter(aip);
+ return(aip); 
+}
+
+/*
+ * initialize acc iterator record
+ */
+static void init_aiter(struct acciter_t *aiterp)
+{
+ aiterp->aiter = NULL;
+ aiterp->aiternxt = NULL;
+ aiterp->aiterprev = NULL;
+}
+
+/*
+ * return
+ */
+extern handle acc_next_scope(handle ref_scope_p, handle scope)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) ref_scope_p;
+ if (!validate_acc_handle("acc_next_scope", hp)) return(NULL); 
+
+ switch (hp->hrec->htyp) {
+  case vpiModule: case vpiTask: case vpiFunction:
+  case vpiNamedBegin: case vpiNamedFork:
+   break;
+  default:
+   __acc_err(1741, "acc_next_scope: object %s illegal - scope object required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+ } 
+
+ /* build the iterator since this is first time */
+ if (scope == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiInternalScope, (vpiHandle) ref_scope_p);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_scope error finding first scope object");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   /* LOOKATME - this is access method but since table big enough */
+   /* just using as header - next returns varied contained scope objects */ 
+   aip->aiternxt = __aiter_tab[vpiScope]; 
+   __aiter_tab[vpiScope] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan((vpiHandle) aip->aiter);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) scope;
+ if (!validate_acc_handle("acc_next_scope", hp2)) return(NULL); 
+ /* many scope object types can't check */
+ if ((aip = find_aiter_rec(__aiter_tab[vpiScope], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_scope last accPrimitive object not returned by previous acc_next_scope call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiScope, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * get next specparam
+ */
+extern handle acc_next_specparam(handle module_p, handle sparam)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) module_p;
+ if (!validate_acc_handle("acc_next_specparam", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModule)
+  { 
+   __acc_err(1742,
+    "acc_next_specparam: %s object illegal - accModule required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (sparam == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiSpecParam, (vpiHandle) module_p);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_specparam error finding first accSpecparam");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiSpecParam]; 
+   __aiter_tab[vpiSpecParam] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) sparam;
+ if (!validate_acc_handle("acc_next_specparam", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiSpecParam)
+  {
+   wrong_nxtobj_error("acc_next_specparam", hp2->hrec->htyp, accSpecparam); 
+   return(NULL);
+  }
+ if ((aip = find_aiter_rec(__aiter_tab[vpiSpecParam], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_specparam last accSpecparam object not returned by previous acc_next_specparam call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiSpecParam, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * get next timing checking
+ */
+extern handle acc_next_tchk(handle mod_p, handle tchk)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) mod_p;
+ if (!validate_acc_handle("acc_next_tchk", hp)) return(NULL); 
+
+ if (hp->hrec->htyp != vpiModule)
+  { 
+   __acc_err(1743, "acc_next_tchk: %s object illegal - accModule required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (tchk == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiTchk, (vpiHandle) mod_p);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_tchk error finding first accTchk");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiTchk]; 
+   __aiter_tab[vpiTchk] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) tchk;
+ if (!validate_acc_handle("acc_next_tchk", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiTchk)
+  {
+   wrong_nxtobj_error("acc_next_tchk", hp2->hrec->htyp, accTchk); 
+   return(NULL);
+  }
+ if ((aip = find_aiter_rec(__aiter_tab[vpiTchk], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_tchk last accTchk object not returned by previous acc_next_tchk call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiTchk, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * get next gate (primive terminal) 
+ */
+extern handle acc_next_terminal(handle gate_handle, handle term)
+{
+ struct h_t *hp, *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) gate_handle;
+ if (!validate_acc_handle("acc_next_terminal", hp)) return(NULL); 
+
+ /* SJM 02/11/00 - vpiPrimtive is iterator that include all 3 different */
+ /* vpi_ primitive types not type itself must allow all 3 */
+ if (hp->hrec->htyp != vpiGate && hp->hrec->htyp != vpiUdp
+  && hp->hrec->htyp != vpiSwitch)
+  { 
+   __acc_err(1744,
+    "acc_next_terminal: %s object illegal - accPrimitive required",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+
+ /* build the iterator since this is first time */
+ if (term == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiPrimTerm, (vpiHandle) gate_handle);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "acc_next_terminal error finding first accTerminal");
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiPrimTerm]; 
+   __aiter_tab[vpiPrimTerm] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan(ihref);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) term;
+ if (!validate_acc_handle("acc_next_terminal", hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiPrimTerm)
+  {
+   wrong_nxtobj_error("acc_next_terminal", hp2->hrec->htyp, accTerminal); 
+   return(NULL);
+  }
+ if ((aip = find_aiter_rec(__aiter_tab[vpiPrimTerm], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "acc_next_terminal last accTerminal object not returned by previous acc_next_terminal call");
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiPrimTerm, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * get next returns all top level instances (modules because 1-1)
+ *
+ * no reference object handle here
+ * routine does not work with acc_collect type routines - need next child
+ */
+extern handle acc_next_topmod(handle topmod)
+{
+ acc_error_flag = FALSE;
+
+ return(do_acc_child_topmod("acc_next_topmod", topmod));
+}
+
+/*
+ * implement get next top module
+ * acc next child no scope case or acc next topmod
+ */
+static handle do_acc_child_topmod(char *rtnnam, handle child)
+{
+ struct h_t *hp2; 
+ vpiHandle ihref, nxth;
+ struct acciter_t *aip;
+
+ if (child == NULL)
+  {
+   __acc_vpi_erroff = TRUE;
+   ihref = vpi_iterate(vpiModule, NULL);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1983, "%s error finding first top level instance", rtnnam);
+     return(NULL);
+    }
+   if (ihref == NULL) return(NULL);
+ 
+   aip = alloc_aiter();
+   /* insert on front since expect last new to be used until done */
+   aip->aiter = (struct h_t *) ihref;
+   __last_aiter = aip;
+
+   aip->aiternxt = __aiter_tab[vpiModule]; 
+   __aiter_tab[vpiModule] = aip;
+   aip->aiterprev = NULL;
+   nxth = vpi_scan((vpiHandle) aip->aiter);
+   /* DBG reomve --- */
+   if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   return((handle) nxth);
+  }
+ /* get next - find previously built iterator */
+ hp2 = (struct h_t *) child;
+ if (!validate_acc_handle(rtnnam, hp2)) return(NULL); 
+ if (hp2->hrec->htyp != vpiModule)
+  {
+   wrong_nxtobj_error(rtnnam, hp2->hrec->htyp, accModule); 
+   return(NULL);
+  }
+ /* last object must be top level module */
+ if ((aip = find_aiter_rec(__aiter_tab[vpiModule], hp2)) == NULL)
+  {
+   __acc_err(1984,
+    "%s last accModule object not returned by previous %s call",
+    rtnnam, rtnnam);
+   return(NULL);
+  }
+ nxth = vpi_scan((vpiHandle) aip->aiter);
+ if (nxth == NULL) { linkout_aiter(aip, vpiModule, FALSE); return(NULL); }
+ return((handle) nxth);
+}
+
+/*
+ * return T if object is of given type
+ *
+ * type can be any type, full type, or special property 
+ * (see case for special object properties)
+ */
+extern bool acc_object_of_type(handle object, int32 type)
+{
+ int32 objtyp, objfulltyp;
+ struct h_t *hp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object;
+ if (!validate_acc_handle("acc_object_of_type", hp)) return(FALSE); 
+
+ /* handle special properties in case */
+ switch (type) {
+  case accScalar:
+   if (hp->hrec->htyp == vpiNet || hp->hrec->htyp == vpiReg)
+    { if (hp->hrec->hu.hnp->n_isavec) return(FALSE); else return(TRUE); }
+   return(FALSE);
+  case accVector:
+   if (hp->hrec->htyp == vpiNet || hp->hrec->htyp == vpiReg)
+    { if (hp->hrec->hu.hnp->n_isavec) return(TRUE); else return(FALSE); }
+   if (hp->hrec->htyp == vpiIntegerVar || hp->hrec->htyp == vpiTimeVar)
+    return(TRUE);
+   return(FALSE);
+  case accCollapsedNet:
+   /* Cver nets never collapses nets aways so always F */
+   return(FALSE);
+  case accExpandedVector:
+   /* no unexpanded nets in Cver */
+   /* LOOKATME - are time and ints really unexpanded? */
+   if (hp->hrec->htyp == vpiNet || hp->hrec->htyp == vpiReg
+    || hp->hrec->htyp == vpiIntegerVar || hp->hrec->htyp == vpiTimeVar)
+    return(TRUE);
+   return(FALSE);
+  case accUnExpandedVector:
+   return(FALSE);
+  case accScope:
+   switch (hp->hrec->htyp) {
+    case vpiFunction: case vpiModule: case vpiNamedBegin:
+    case vpiNamedFork: case vpiTask: case vpiFuncCall:
+     return(TRUE);
+    default: break;
+   }
+   return(FALSE);
+  case accModPathHasIfnone:
+   if (hp->hrec->htyp == vpiModPath)
+    { if (hp->hrec->hu.hpthp->pth_ifnone) return(TRUE); else return(FALSE); }
+   return(FALSE);
+  default:
+   /* only way to exit loop is here */
+   break;
+ }
+ /* know either type or full type */
+ objtyp = acc_fetch_type((handle) hp);
+ if (objtyp == type) return(TRUE);
+ objfulltyp = acc_fetch_fulltype((handle) hp);
+ if (objfulltyp == type) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * version of object of type that works with list (T if on 1st match)
+ */
+extern bool acc_object_in_typelist(handle object, int32 *type_list)
+{
+ register int32 li;
+ struct h_t *hp;
+
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object;
+ if (!validate_acc_handle("acc_object_in_typelist", hp)) return(FALSE); 
+
+ for (li = 0;; li++)
+  {
+   if (type_list[li] == 0) break;
+   if (acc_object_of_type(object, type_list[li])) return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * return predefined acc constant for tool type
+ */
+extern int32 acc_product_type(void)
+{
+ return(accSimulator);
+}
+
+/*
+ * get a string indicating product version
+ */
+extern char *acc_product_version(void)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ sprintf(s1, "%s%s of %s (%s).\n", __vers, __vers2, __ofdt, __platform);
+ sprintf(s2, "Cver Verilog simulator Version %s", s1); 
+ return(add_accstrbuf(s2));
+}
+
+/*
+ * release acc_next_input or acc_next_output (for path src/dst) aux. storage
+ *
+ * does nothing in Cver since no extra storage
+ * LOOKATME - is there something that can be freed
+ */
+extern int32 acc_release_object(handle obj)
+{
+ return(1);
+}
+
+/*
+ * replace (set) delays - acc style just wrapper for vpi put delays
+ */
+/*VARARGS*/
+extern bool acc_replace_delays(handle object, ...)
+{
+ int32 rv;
+ va_list va;
+
+ va_start(va, object);
+ rv = exec_acc_set_delays((struct h_t *) object, FALSE, va);
+ va_end(va);
+ return(rv);
+}
+
+/*
+ * do acc_ replace or append routines (same except for append flag)
+ *
+ * caller calls va_start and va_end
+ * LOOKATME - is this use of varargs Posix compatible?
+ */
+static int32 exec_acc_set_delays(struct h_t *hp, int32 is_append, va_list va)
+{
+ register int32 i;
+ double *d1p, *d2p, *d3p, *da;
+ double mintoz, typtoz, maxtoz; 
+ struct hrec_t *hrp;
+ struct mod_pin_t *mpp;
+ s_vpi_delay vpideltmp;
+ s_vpi_time delarr[36]; 
+ char s1[RECLEN];
+
+ if (is_append) strcpy(s1, "acc_append_delays");
+ else strcpy(s1, "acc_replace_delays");
+ acc_error_flag = FALSE;
+
+ if (!validate_acc_handle(s1, hp)) return(0); 
+ hrp = hp->hrec;
+
+ for (i = 0; i < 36; i++) delarr[i].type = vpiScaledRealTime;
+ vpideltmp.da = &(delarr[0]);
+ vpideltmp.time_type = vpiScaledRealTime;
+ vpideltmp.mtm_flag = FALSE;
+ /* append must be off since replacing */
+ if (is_append) vpideltmp.append_flag = TRUE;
+ else vpideltmp.append_flag = FALSE;
+ vpideltmp.pulsere_flag = FALSE;
+ 
+ switch (hrp->htyp) {
+  case vpiGate: case vpiUdp: case vpiSwitch:
+   /* 3 values */
+   __acc_vpi_erroff = TRUE;
+   /* always get 3 delays - LOOKATME - what about 2 delay prims? */
+   vpideltmp.no_of_delays = 3;
+
+   if (__acc_mintypmaxdelays)
+    {
+     da = va_arg(va, double *);
+     /* need to compute hiz delay according to acc config setting */
+     if (__acc_tohizdelay == ACCTOHIZ_AVG)
+      {
+       mintoz = (da[0] + da[3])/2.0;
+       typtoz = (da[1] + da[4])/2.0;
+       maxtoz = (da[2] + da[5])/2.0;
+      }
+     else if (__acc_tohizdelay == ACCTOHIZ_MAX)
+      {
+       if (da[0] > da[3]) mintoz = da[0]; else mintoz = da[3];
+       if (da[1] > da[4]) typtoz = da[1]; else typtoz = da[4];
+       if (da[2] > da[5]) maxtoz = da[2]; else maxtoz = da[5];
+      }
+     else if (__acc_tohizdelay == ACCTOHIZ_MIN)
+      {
+       if (da[0] < da[3]) mintoz = da[0]; else mintoz = da[3];
+       if (da[1] < da[4]) typtoz = da[1]; else typtoz = da[4];
+       if (da[2] < da[5]) maxtoz = da[2]; else maxtoz = da[5];
+      }
+     /* ACCTOHIZ_FROMUSER */
+     else { mintoz = da[6]; typtoz = da[7]; maxtoz = da[8]; }
+     if (__mintypmax_sel == DEL_MIN) 
+      {
+       vpideltmp.da[0].real = da[0]; 
+       vpideltmp.da[1].real = da[3];
+       vpideltmp.da[2].real = mintoz;
+      }
+     else if (__mintypmax_sel == DEL_TYP) 
+      {
+       vpideltmp.da[0].real = da[1]; 
+       vpideltmp.da[1].real = da[4];
+       vpideltmp.da[2].real = typtoz;
+      }
+     else if (__mintypmax_sel == DEL_MAX) 
+      {
+       vpideltmp.da[0].real = da[2]; 
+       vpideltmp.da[1].real = da[5];
+       vpideltmp.da[2].real = maxtoz;
+      }
+     else __acc_terr(__FILE__, __LINE__);
+    }
+   else
+    {
+     d1p = va_arg(va, double *);
+     vpideltmp.da[0].real = *d1p; 
+     d2p = va_arg(va, double *);
+     vpideltmp.da[1].real = *d2p;
+
+     if (__acc_tohizdelay == ACCTOHIZ_AVG)
+      vpideltmp.da[2].real = (*d1p + *d2p)/2.0;
+     else if (__acc_tohizdelay == ACCTOHIZ_MAX)
+      {
+       if (*d1p > *d2p) vpideltmp.da[2].real = *d1p;
+       else vpideltmp.da[2].real = *d2p;
+      }
+     else if (__acc_tohizdelay == ACCTOHIZ_MIN)
+      {
+       if (*d1p < *d2p) vpideltmp.da[2].real = *d1p;
+       else vpideltmp.da[2].real = *d2p;
+      }
+     else
+      {
+       /* ACCTOHIZ_FROMUSER */
+       d3p = va_arg(va, double *);
+       vpideltmp.da[3].real = *d3p;
+      }
+    }
+
+   vpi_put_delays((vpiHandle) hp, &vpideltmp);
+
+   /* this access error vpi_ error info */  
+   /* only error is hp not having property */
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1718, "%s: unable to change delays for object %s", s1,
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(0);
+    }
+   break;
+  case vpiPort: case vpiPortBit: 
+   /* up to 12 - see draft 3 or later new LRM */
+   mpp = &(hp->hin_itp->itip->imsym->el.emdp->mpins[hrp->hu.hpi]);
+   if (mpp->mptyp != IO_IN && mpp->mptyp != IO_BID)
+    {
+     __acc_err(1761,
+      "%s: unable to change delays for %s - output port illegal", s1,
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(0); 
+    }
+   if (hrp->htyp == vpiPort && mpp->mpwide != 1)
+    {
+     __acc_err(1761,
+      "%s: unable to change delays for accPort object - must be scalar", s1);
+     return(0);
+    }
+   /* FALLTHRU */
+  case vpiModPath:
+   __acc_vpi_erroff = TRUE;
+   /* port MIPD since inter module paths not supported) and paths from cfg */
+   vpideltmp.no_of_delays = __acc_pathdelaycount;
+
+   if (__acc_mintypmaxdelays)
+    {
+     da = va_arg(va, double *);
+     for (i = 0; i < __acc_pathdelaycount; i++)
+      {
+       if (__mintypmax_sel == DEL_MIN) vpideltmp.da[i].real = da[3*i + 0]; 
+       else if (__mintypmax_sel == DEL_TYP) vpideltmp.da[i].real = da[3*i + 1]; 
+       else if (__mintypmax_sel == DEL_MAX) vpideltmp.da[i].real = da[3*i + 2]; 
+       else __acc_terr(__FILE__, __LINE__);
+      }
+    }
+   else
+    {
+     for (i = 0; i < __acc_pathdelaycount; i++)
+      {
+       d1p = va_arg(va, double *);
+       vpideltmp.da[i].real = *d1p; 
+      } 
+    }
+   vpi_put_delays((vpiHandle) hp, &vpideltmp);
+
+   /* this access error vpi_ error info */  
+   /* only error is hp not having property */
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1718,
+      "%s: unable to change path or MIPD delays for object %s", s1,
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(0);
+    }
+   break;
+  case vpiTchk:
+   /* 1 value - for 2 limit cases only first accessible in acc_ */
+   __acc_vpi_erroff = TRUE;
+   /* always set 1 delay (first limit) */
+   if (__acc_mintypmaxdelays)
+    {
+     da = va_arg(va, double *);
+     if (__mintypmax_sel == DEL_MIN) vpideltmp.da[0].real = da[0]; 
+     else if (__mintypmax_sel == DEL_TYP) vpideltmp.da[0].real = da[1]; 
+     else if (__mintypmax_sel == DEL_MAX) vpideltmp.da[0].real = da[2]; 
+     else __acc_terr(__FILE__, __LINE__);
+    }
+   else
+    {
+     d1p = va_arg(va, double *);
+     vpideltmp.da[0].real = *d1p; 
+    }
+
+   vpideltmp.no_of_delays = 1;
+   vpi_put_delays((vpiHandle) hp, &vpideltmp);
+
+   /* this access error vpi_ error info */  
+   /* only error is hp not having property */
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1718, "%s: unable to access delays for object %s",
+      s1, to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(0);
+    }
+   break;
+  default:
+   __acc_err(1759,
+    "%s: object %s illegal - does not have acc_ changeable delays",
+    s1, to_acc_onam(__wrks1, hrp->htyp));
+   return(0);
+  }
+ return(1);
+}
+
+/*
+ * replace pulse handling limits
+ * notice these never array form
+ *
+ * FIXME - simulator needs to support these for now does nothing
+ */
+/*VARARGS*/
+extern bool acc_replace_pulsere(handle object, double val1r, double val1x, ...)
+{
+ struct h_t *hp;
+ struct hrec_t *hrp;
+ 
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) object; 
+ if (!validate_acc_handle("acc_replace_pulsere", hp)) return(0); 
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiModPath && hrp->htyp != vpiPort
+  && hrp->htyp != vpiPortBit)  
+  {
+   __acc_err(1765, "acc_replace_pulsere: object %s illegal - path required",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(FALSE);
+  }
+ __acc_warn(2052,
+  "acc_replace_pulsere no effect - pulse limits not stored by tool");
+ return(TRUE);
+}
+
+/*
+ * reset string buffer
+ *
+ * doesn't do much because user can not assume strings stay in string
+ * buf since any addition can cause reset with warning
+ */
+extern void acc_reset_buffer(void)
+{
+ __acc_strbuf_nxti = 0;
+}
+
+/*
+ * set interactive scope
+ * call all misctfs with reason reason_scope if flag T
+ */
+extern bool acc_set_interactive_scope(handle scope, int32 callback_flag)
+{
+ struct h_t *hp;
+ 
+ hp = (struct h_t *) scope;
+ if (!validate_acc_handle("acc_set_interactive_scope", hp)) return(FALSE); 
+
+ switch (hp->hrec->htyp) {
+  case vpiModule:
+   __scope_ptr = hp->hin_itp;
+   __scope_tskp = NULL;
+   break;
+  case vpiTask: case vpiFunction: case vpiNamedBegin: case vpiNamedFork:
+   __scope_ptr = hp->hin_itp;
+   __scope_tskp = hp->hrec->hin_tskp;
+   break;
+  default:
+   __acc_err(1745, "acc_set_interactive_scope: object %s is not a scope object",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(FALSE); 
+  }
+
+ /* LOOKATME - think vpi_ call backs should not be called here */
+ if (callback_flag && __tfrec_hdr != NULL) __call_misctfs_scope();
+ return(TRUE);
+}
+
+/*
+ * set pulse handling limits from percentages
+ *
+ * FIXME - simulator needs to support these for now does nothing
+ */
+extern bool acc_set_pulsere(handle path_p, double val1r, double val1e)
+{
+ struct h_t *hp;
+ struct hrec_t *hrp;
+ 
+ acc_error_flag = FALSE;
+
+ hp = (struct h_t *) path_p; 
+ if (!validate_acc_handle("acc_set_pulsere", hp)) return(0); 
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiModPath && hrp->htyp != vpiPort
+  && hrp->htyp != vpiPortBit)  
+  {
+   __acc_err(1766, "acc_set_pulsere: object %s illegal - path required",
+    to_acc_onam(__wrks1, hrp->htyp));
+   return(FALSE);
+  }
+
+ __acc_warn(2052,
+  "acc_set_pulsere no effect - pulse limits not stored by tool");
+ return(TRUE);
+}
+
+/*
+ * set acc working scope 
+ *
+ * interpretation of arguments effected by configuration 
+ */
+/*VARARGS*/
+extern char *acc_set_scope(handle object, ...)
+{
+ vpiHandle scopobj;
+ struct h_t *hp;
+ struct itree_t *itp;
+ struct mod_t *mdp;
+ va_list va;
+ char *chp, *module_name;
+
+ /* case 1, object is not nil */
+ if (object != NULL)
+  {
+   hp = (struct h_t *) object;
+   if (!validate_acc_handle("acc_set_scope", hp)) return(FALSE); 
+   if (hp->hrec->htyp != vpiModule)
+    {
+     __acc_err(1712,
+      "acc_set_scope object has illegal type %s - must be type accModule",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(NULL);
+    }
+   __acc_scope_set = TRUE;
+   __acc_scope_vpiobj = vpi_copy_object((vpiHandle) object);
+   goto bld_path;
+  }
+
+ /* case 2a: object nil and name nil or acc_no_set_scope configure set */
+ if (!__acc_enableargs_setscope)
+  {
+do_first_root:
+   itp = __it_roots[0];
+   mdp = itp->itip->imsym->el.emdp;
+   __acc_scope_set = TRUE;
+   __acc_scope_vpiobj = __mk_handle(vpiModule, (void *) mdp, itp, NULL); 
+   goto bld_path;
+  }
+ va_start(va, object);
+ module_name = va_arg(va, char *);
+ if (module_name == NULL)
+  {
+   va_end(va);
+   goto do_first_root;  
+  }
+
+ /* case 3: look up name - must be rooted */
+ __acc_vpi_erroff = TRUE;
+ /* name must be rooted */
+ scopobj = vpi_handle_by_name(module_name, NULL);
+ /* if just can not find name - no error just returns nil */
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1715,
+    "acc_set_scope with acc_set_scope configuration - unable to find module scope for %s",
+    module_name);
+   va_end(va);
+   return(NULL);
+  }
+ 
+ hp = (struct h_t *) scopobj;
+ if (hp->hrec->htyp != vpiModule)
+  {
+   __acc_err(1713,
+    "acc_set_scope module_name %s wrong object type %s - accModule required",
+    module_name, to_acc_onam(__wrks1, hp->hrec->htyp));
+   va_end(va);
+   return(NULL);
+  }
+ va_end(va);
+ __acc_scope_set = TRUE;
+ __acc_scope_vpiobj = vpi_copy_object(scopobj);
+ 
+bld_path:
+ hp = (struct h_t *) __acc_scope_vpiobj;
+ chp = __msg2_blditree(__xs, hp->hin_itp);
+ return(add_accstrbuf(chp));
+}
+
+/*
+ * implement acc_set_value - almost the same as vpi set value  
+ *
+ * LOOKATME - are bit objects allowed (LRM says no)
+ *
+ * FIXME - somehow on acc_close and reset need to remove events?
+ *
+ * SJM 12/17/02 - this is exception to rest of acc_ - return 0 on success
+ * and 1 on error
+ */
+extern int32 acc_set_value(handle obj, p_setval_value setval_p,
+ p_setval_delay delay_p)
+{
+ int32 vpi_delflag;
+ struct t_vpi_time tmptim; 
+ struct t_vpi_value tmpval;
+ struct h_t *hp;
+ word64 timv;
+ double d1;
+
+ acc_error_flag = FALSE;
+ if (__run_state != SS_SIM)
+  { acc_not_sim_err("acc_set_value"); return(1); } 
+
+ hp = (struct h_t *) obj;
+ if (!validate_acc_handle("acc_set_value", hp)) return(1); 
+
+ /* check for legal object to set value to */
+ switch (hp->hrec->htyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+  /* SJM 05/14/01 - misread LRM - all vpi put values legal */
+  case vpiNetBit: case vpiRegBit: case vpiRealVar:
+  /* SJM 05/14/01 - LOOKATME- indistinguishable from reg bit in acc? */
+  case vpiVarSelect:
+   break;
+  case vpiUdp: 
+   /* WRITEME */ 
+   __acc_err(1941,
+    "acc_set_value: accUdp initial value setting not yet implemented");
+   return(1);
+  case vpiUserSystf:
+   /* WRITEME */ 
+   __acc_err(1941,
+    "acc_set_value: accUserFunction (PLI) value setting not yet implemented");
+   return(1);
+  default:
+   __acc_err(1746, "acc_set_value: value cannot be set for %s object",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return(1);
+ }
+
+ /* build the vpi set value d.s. */ 
+ /* idea here is to alloc vpi records in local (stack) memory */
+ /* because vpi put value copies into its internal storage */
+
+ /* copy acc time record into vpi time record */   
+ if (delay_p->time.type == accTime)
+  {
+   /* this is 64 bit scaled (containing module of object) time */
+   /* no matching vpi_ time type */
+   /* use vpi real - think 52 bits of time is enough for scaled */
+   timv = ((word64) ((word32) delay_p->time.low))
+    | (((word64) ((word32) delay_p->time.high)) << 32);
+   if (!__v64_to_real(&d1, &timv))
+    {
+     __acc_warn(2049,
+      "conversion from scaled accTime to time as real lost precision");
+    }
+   tmptim.type = vpiScaledRealTime;
+   tmptim.real = d1;
+  }
+ else if (delay_p->time.type == accSimTime)
+  {
+   /* this is internal ticks */
+   tmptim.type = vpiSimTime;
+   tmptim.low = delay_p->time.low;
+   tmptim.high = delay_p->time.high;
+  }
+ else if (delay_p->time.type == accRealTime)
+  {
+   /* this is real scaled (containing module of object) time */
+   tmptim.type = vpiScaledRealTime;
+   tmptim.real = delay_p->time.real;
+  }
+ else 
+  {
+   /* SJM 04/15/01 - remove internal error for bad delay time type field */
+   if (delay_p->model == accNoDelay)
+    {
+     /* acc delay model is no delay, delay_p can be nil but emit warn */
+     tmptim.type = vpiSimTime;
+     tmptim.low = 0;
+     tmptim.high = 0;
+
+     __acc_warn(2043,
+      "acc_set_value: delay_p time type field value (%d) illegal - used anyway since accNoDelay model",
+     delay_p->time.type);
+    }
+   else
+    {
+     __acc_err(1994,
+      "acc_set_value: delay_p time type field value (%d) illegal",
+      delay_p->time.type);
+     return(1);
+    }
+  }
+
+ /* SJM 04/15/01 - if delay_p model is no delay - time need not be set */
+ /* convert acc delay model to vpi */
+ if ((vpi_delflag = map_acc_delaymode_to_vpi(delay_p->model)) == -1)
+  return(1);
+
+ /* build the vpi_ value record */
+ if (!fill_vpival_fromacc(&tmpval, setval_p)) return(1);
+
+ /* actually do the vpi put value */ 
+ /* this may be immediate or schedule event but storage copied so */
+ /* can be freed after here */
+ /* since not saving scheduled event handle, no need to check return */ 
+ vpi_put_value((vpiHandle) hp, &tmpval, &tmptim, vpi_delflag);
+ /* ??? FIXME - need to vpi check here in case this fails */
+ return(0);
+}
+
+/*
+ * map from acc delay models to vpi_ delay
+ *
+ * one-to-one except need to add assign/deassign for Verilog 99 vpi_
+ * return -1 on error
+ */
+static int32 map_acc_delaymode_to_vpi(int32 accdmode)
+{
+ int32 vpidmode;
+
+ /* extract delay type from acc_ setval_delay value */ 
+ switch (accdmode) {
+  case accNoDelay: vpidmode = vpiNoDelay; break;
+  case accInertialDelay: vpidmode = vpiInertialDelay; break;
+  case accTransportDelay: vpidmode = vpiTransportDelay; break;
+  case accPureTransportDelay: vpidmode = vpiPureTransportDelay; break;
+  case accForceFlag: vpidmode = vpiForceFlag; break; 
+  case accReleaseFlag: vpidmode = vpiReleaseFlag; break; 
+  case accAssignFlag: case accDeassignFlag:
+   /* WRITEME */ 
+   __acc_err(1988,
+    "acc_set_value: %s s_setval_delay model value not yet implemented - use force/release for now",
+    get_acc_delmode_nam(__wrks1, accdmode));
+   return(-1);
+  default:
+   __acc_err(1992, "acc_set_value: s_setval_delay model value %d illegal",
+    accdmode);
+   return(-1);
+ }
+ return(vpidmode);
+}
+
+/*
+ * convert acc delay mode value to string
+ */
+static char *get_acc_delmode_nam(char *s, int32 accdmode)
+{
+ switch (accdmode) {
+  case accNoDelay: strcpy(s, "accNoDelay"); break;
+  case accInertialDelay: strcpy(s, "accInertialDelay");  break;
+  case accTransportDelay: strcpy(s, "accTransportDelay"); break;
+  case accPureTransportDelay: strcpy(s, "accPureTransportDelay"); break;
+  case accForceFlag: strcpy(s, "accForceFlag"); break;
+  case accReleaseFlag: strcpy(s, "accReleaseFlag"); break;
+  case accAssignFlag: strcpy(s, "accAssignFlag"); break;
+  case accDeassignFlag: strcpy(s, "accDeassignFlag"); break;
+  default: sprintf(s, "[?? Unknown: %d]", accdmode); break;
+ }
+ return(s);
+}
+
+/*
+ * fill vpi t_vpi_value record from acc t_setval_value
+ * returns F on error else T
+ *
+ * call must allocate vpi value record
+ * because vpi copies value contents - this mostly just copies ptrs
+ *
+ * this works because both use same vector aval/bval format
+ * and acc value types are subset of vpi_ 
+ */
+static int32 fill_vpival_fromacc(struct t_vpi_value *vpivalp,
+ struct t_setval_value *accvalp)
+{
+ switch (accvalp->format) {
+  /* string forms same except for constant */
+  case accBinStrVal:
+   vpivalp->format = vpiBinStrVal; 
+   vpivalp->value.str = accvalp->value.str;
+   break;
+  case accOctStrVal:
+   vpivalp->format = vpiOctStrVal; 
+   vpivalp->value.str = accvalp->value.str;
+   break;
+  case accDecStrVal:
+   vpivalp->format = vpiDecStrVal; 
+   vpivalp->value.str = accvalp->value.str;
+   break;
+  case accHexStrVal:
+   vpivalp->format = vpiHexStrVal; 
+   vpivalp->value.str = accvalp->value.str;
+   break;
+  case accScalarVal:
+   vpivalp->format = vpiScalarVal; 
+   /* notice vpi and acc 4 values different */
+   vpivalp->value.scalar = map_acc_to_vpival(accvalp->value.scalar);
+   break;
+  case accIntVal:
+   vpivalp->format = vpiIntVal; 
+   vpivalp->value.integer = accvalp->value.integer;
+   break;
+  case accRealVal:
+   vpivalp->format = vpiRealVal; 
+   vpivalp->value.real = accvalp->value.real;
+   break;
+  case accStringVal:
+   vpivalp->format = vpiStringVal; 
+   /* can just use same ptr here */
+   vpivalp->value.str = accvalp->value.str;
+   break;
+  case accVectorVal:
+   /* BEWARE - this assumes internal vec val a/b values same */
+   vpivalp->format = vpiVectorVal; 
+   vpivalp->value.vector = (struct t_vpi_vecval *) accvalp->value.vector;
+   break;
+  default:
+   __acc_err(1992, "acc_set_value: s_setval_value foramt value %d illegal",
+    accvalp->format);
+   return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * add a value change call back to a net 
+ *
+ * can add to reg/net/var and bit select of vector reg/net
+ * also loconns expr of port and exprs connected to of terminals
+ *
+ * loconn must not be concatenate or part select - must catch
+ *
+ * Cver allows any vector reg/net (not just unexpanded)
+ * FIXME - allow vpi_ cbs and therefore also acc_ vcls on declared events
+ */
+extern void acc_vcl_add(handle object_p, int32 (*consumer)(), char *user_data,
+ int32 vcl_flags)
+{
+ struct h_t *hp, *hp2, *hp3;
+ struct net_t *np;
+ struct gate_t *gp;
+ struct expr_t *xp;
+ struct t_cb_data cbrec; 
+ struct t_vpi_time tmptim;
+ struct t_vpi_value tmpval;
+ struct vclrec_t *vclp;
+
+ acc_error_flag = FALSE;
+ if (__run_state != SS_SIM)
+  { acc_not_sim_err("acc_vcl_add"); return; } 
+
+ /* check arguments */
+ if (consumer == NULL)
+  {
+   __acc_err(1987,
+    "acc_vcl_add call illegal - consumer routine must not be NULL");
+   return;
+  }
+
+ hp = (struct h_t *) object_p;
+ if (!validate_acc_handle("acc_vcl_add", hp)) return; 
+
+ /* SJM 11/28/00 - if tran terminal, must replace with connected expr */
+ if (hp->hrec->htyp == vpiPrimTerm)
+  {
+   gp = hp->hrec->hu.hgp;
+   if (gp->g_class == GC_PULL || gp->g_class == GC_TRAN
+    || gp->g_class == GC_TRANIF)
+    {
+     if (gp->g_class == GC_TRANIF && hp->hrec->hi == 2)
+      {
+       __acc_err(1980,
+        "acc_vcl_add for accTerminal (pos. %d) of tranif %s.%s illegal input - only inout allowed",
+        hp->hrec->hi + 1, __msg2_blditree(__xs, hp->hin_itp), gp->gsym->synam);
+       return;
+      }
+     xp = hp->hrec->hu.hgp->gpins[hp->hrec->hi];
+     /* SJM 11/28/00 - also must change handle to terminal index handle */
+     hp3 = (struct h_t *) __mk_exprclass_handle(xp, hp->hin_itp,
+      hp->hrec->hin_tskp);
+     hp = hp3;
+    }
+  }
+
+ /* if already added or error, done */ 
+ if (!chk_add_del_vclobj("acc_vcl_add", &hp, consumer, user_data)) return;
+
+ /* add it */
+ /* if monitoring for strength, must be 1 bit object */ 
+ if (hp->hrec->htyp == vpiNetBit && hp->hrec->htyp == vpiRegBit)
+  {
+   if (vcl_flags == vcl_verilog_strength) 
+    {
+     np = hp->hrec->hu.hnp;
+     if (np->nwid != 1)
+      {
+       __acc_err(1949,
+        "acc_vcl_add - vcl_flags value VCL_VERILOG_STRENGTH illegal for vector object %s",
+        to_acc_onam(__wrks1, hp->hrec->htyp));
+       return;
+      }
+    }
+  }
+
+ /* allocate and fill internal vclrec */
+ vclp = (struct vclrec_t *) __my_malloc(sizeof(struct vclrec_t));
+ vclp->vclflg = vcl_flags;
+ vclp->vcl_oldstval = ST_STRONGX;
+ /* SJM 11/22/00 - for primitive output terminal must set by gate type */
+ if (hp->hrec->htyp == vpiPrimTerm)
+  {
+   /* flag determines if vpi_ call back monitors strength */
+   /* LOOKATME - minor bug since for mos/buf gates, all stren changes */
+   /* reported */
+   if (vcl_flags == vcl_verilog_strength)
+    vclp->vcl_reason = strength_value_change;
+   else vclp->vcl_reason = logic_value_change;
+  }
+ else vclp->vcl_reason = set_vcl_reason(hp->hrec->hu.hnp, vcl_flags);
+
+ /* LOOKATME - why not make field h_t not handle */
+ vclp->vclobj = (handle) hp;
+ vclp->vcl_cb_rtn = consumer;  
+ vclp->vcl_udata = user_data; 
+ vclp->vclcbp = NULL;
+
+ /* register vpi callback */
+ /* local vars used because always copied here and when cb occurs */
+ cbrec.reason = cbValueChange;
+
+ /* SJM 11/22/00 - need special routine for prim output terminal */
+ if (hp->hrec->htyp == vpiPrimTerm) cbrec.cb_rtn = exec_acc_gateout_vclcb;
+ else cbrec.cb_rtn = exec_acc_vclcb;
+
+ tmptim.type = vpiSimTime;
+ tmptim.high = tmptim.low = 0;
+ cbrec.time = &tmptim;
+ tmpval.format = vpiSuppressVal;
+ /* SJM 11/27/00 - use suppress value since need to get value as part */
+ /* of vcl processing */
+ tmpval.value.str = NULL;
+ cbrec.value = &tmpval;
+
+ cbrec.obj = (vpiHandle) hp;
+ cbrec.user_data = (char *) vclp;
+
+ hp2 = (struct h_t *) vpi_register_cb(&cbrec);
+ __acc_vpi_erroff = TRUE;
+ if (__my_vpi_chk_error())
+  {
+   __acc_err(1749, "acc_vcl_add: error adding value change callback for %s",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   __my_free((char *) vclp, sizeof(struct vclrec_t));
+   return;
+  }
+ vclp->vclcbp = hp2->hrec->hu.hcbp;
+}
+
+/*
+ * check vcl add and vcl object handle
+ * return F is error or already added0
+ */
+static int32 chk_add_del_vclobj(char *rtnnam, struct h_t **hpp,
+ int32 (*consumer)(), char *user_data)
+{
+ vpiHandle loconn, hiconn;
+ struct h_t *hp;
+ char s1[RECLEN];
+
+ strcpy(s1, "");
+ hp = *hpp;
+ /* make sure handle object legal for acc_ vcl callback */
+ switch (hp->hrec->htyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   break;
+  case vpiNetBit: case vpiRegBit:
+   break;
+  case vpiPrimTerm:
+   /* BEWARE must be vpiDirection since this short circuits prop checking */
+   if (__primtermprop_vpiget(hp, vpiDirection) == vpiInput)
+    {
+     __acc_err(1753,
+      "%s: primitive input port can not be monitored by acc_ vcl", rtnnam);
+     return(FALSE);
+    }
+   /* SJM 11/22/00 - now vpi_ cb really goes on output terminal itself */
+   *hpp = hp;
+   break;
+  case vpiPort: case vpiPortBit:
+   /* SJM 03/15/04 - for port acc vcl's was not putting change cb on the */  
+   /* hiconn for input ports */
+   __acc_vpi_erroff = TRUE;
+   if (vpi_get(vpiDirection, (vpiHandle) hp) == vpiInput)
+    {
+     hiconn = vpi_handle(vpiHighConn, (vpiHandle) hp);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1753, "%s: error accessing hiconn of input accPort",
+        rtnnam);
+       return(FALSE);
+      }
+     hp = (struct h_t *) hiconn;
+     *hpp = hp;
+    }
+   else
+    {
+     loconn = vpi_handle(vpiLowConn, (vpiHandle) hp);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1753, "%s: error accessing loconn of ouput/inout accPort",
+        rtnnam);
+       return(FALSE);
+      }
+     hp = (struct h_t *) loconn;
+     *hpp = hp;
+    }
+   break;
+   case vpiRealVar: case vpiNamedEvent:
+   /* WRITEME */
+   /* LOOKATME - does this work in vpi_ */
+   __acc_err(1941, "%s: %s%s object not yet implemented", rtnnam,
+    to_acc_onam(__wrks1, hp->hrec->htyp), s1);
+    return(FALSE);
+  default:
+   __acc_err(1747, "%s: %s%s object can not be monitored by acc_ vcl",
+    rtnnam, to_acc_onam(__wrks1, hp->hrec->htyp), s1);
+   return(FALSE);
+ }
+ /* find and only add if different arguments (not counting vcl_flag) */
+ /* if already added, do not add again */
+ /* SJM 11/28/00 - need separate match routine to find already registered */
+ /* for gate output terminals */
+ if (hp->hrec->htyp == vpiPrimTerm)
+  {
+   if (findmatch_term_vcl_dce(hp, consumer, user_data) != NULL)
+    {
+     __acc_err(1989,
+      "%s failed - identical (all args but vcl_flags) vcl primitive output termininal monitor already added",
+      rtnnam);
+     return(FALSE);
+    }
+  }
+ else
+  {
+   if (findmatch_net_vcl_dce(hp, consumer, user_data) != NULL)
+    {
+     __acc_err(1989,
+      "%s failed - identical (all args but vcl_flags) vcl variable monitor already added",
+      rtnnam);
+     return(FALSE);
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * routine to set vcl call back reason field from net and vcl flag
+ */
+static int32 set_vcl_reason(struct net_t *np, int32 vclflg)
+{
+ int32 reason;
+
+ if (np->nwid == 1)
+  {
+   if (vclflg == vcl_verilog_strength) reason = strength_value_change;
+   else
+    {
+     if (np->ntyp >= NONWIRE_ST) reason = sregister_value_change;
+     else reason = logic_value_change;
+    }
+  }
+ else
+  {
+   if (np->ntyp == N_INT) reason = integer_value_change; 
+   else if (np->ntyp == N_TIME) reason = time_value_change;
+   else 
+    {
+     if (np->ntyp >= NONWIRE_ST) reason = vregister_value_change;
+     else reason = vector_value_change;
+    }
+  }
+ return(reason);
+}
+
+/*
+ * find matching CBR vpi_ dce if has one
+ *
+ * know dce's here are either entire net/reg or one bit
+ */
+static struct vclrec_t *findmatch_net_vcl_dce(struct h_t *hp, int32 (*consumer)(),
+ char *user_data)
+{
+ register struct dcevnt_t *dcep;
+ register struct hrec_t *hrp;
+ int32 cv;
+ struct net_t *np; 
+ struct vclrec_t *vclp;
+ struct h_t *hp2;
+
+ hrp = hp->hrec;
+ np = hrp->hu.hnp;
+ for (dcep = np->dcelst; dcep != NULL; dcep = dcep->dcenxt)
+  {
+   /* eliminate if not vpi callback type */
+   if (dcep->dce_typ != DCE_CBVC && dcep->dce_typ != DCE_RNG_CBVC)   
+    continue;
+
+   /* eliminate if vcl call back routine not match acc_ vcl wrapper */
+   if (dcep->dceu.dce_cbp->cb_rtn != exec_acc_vclcb) continue;
+
+   /* make sure instance and bit ranges match */
+   if (dcep->dce_matchitp != hp->hin_itp) continue;
+   /* if vcl being added to bit - dce must match bit */
+   if (hrp->htyp == vpiNetBit || hrp->htyp == vpiRegBit)
+    {
+     /* vector form never matches bit form */
+     if (dcep->dci1 == -1) continue;
+     if (dcep->dci1 != hrp->hi) continue;
+    }
+   /* found match providing all 3 vcl add args match */
+   /* vpi_ user data is vclrec */
+   vclp = (struct vclrec_t *) dcep->dceu.dce_cbp->cb_user_data;
+   if ((struct h_t *) vclp->vclobj != hp) continue;
+   if (vclp->vcl_cb_rtn != consumer) continue;
+   if (vclp->vcl_udata != user_data) continue;
+
+   hp2 = (struct h_t *) vclp->vclobj;
+   __acc_vpi_erroff = TRUE;
+   cv = vpi_compare_objects((vpiHandle) hp, (vpiHandle) hp2);
+   /* this access error vpi_ error info */  
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1754,
+      "acc_vcl_add problem comparing other added vcl object %s",
+       to_acc_onam(__wrks1, hp2->hrec->htyp));
+     continue;
+    }
+   /* cv 0 if different - if different did not find match */
+   if (cv == 0) continue; 
+   return(vclp);
+  }
+ return(NULL);
+}
+
+/*
+ * find matching gate output terminal vcl triple to see if registered
+ */
+static struct vclrec_t *findmatch_term_vcl_dce(struct h_t *hp,
+ int32 (*consumer)(), char *user_data)
+{
+ register int32 tevpi;
+ int32 gi, cv;
+ struct gate_t *gp;
+ struct mod_t *mdp;
+ struct cbrec_t *cbp; 
+ struct vclrec_t *vclp;
+ struct h_t *hp2;
+
+ /* if this gate terminal has no terminal output value change call backs */ 
+ /* can't match */
+ gp = hp->hrec->hu.hgp; 
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ gi = gp - mdp->mgates;
+ if (mdp->mgateout_cbs == NULL || mdp->mgateout_cbs[gi] == NULL)
+  return(NULL);
+ if ((tevpi = mdp->mgateout_cbs[gi][hp->hin_itp->itinum]) == -1)
+  return(NULL);
+ 
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+  {
+   /* LOOKATME - think this is impossible, removed from list when removed */
+   /* but does not hurt */
+   if (__tevtab[tevpi].te_cancel) continue;
+
+   cbp = __tevtab[tevpi].tu.tehp->hrec->hu.hcbp;
+   /* eliminate if not acc_ call back */
+   if (cbp->cb_rtn != exec_acc_gateout_vclcb) continue;
+
+   /* notice acc specific vcl fields stored in call back user data field */
+   vclp = (struct vclrec_t *) cbp->cb_user_data;
+
+   /* found match providing all 3 vcl add args match */
+   /* LOOKATME - why is this exactly same handle not just same object */
+   if ((struct h_t *) vclp->vclobj != hp) continue;
+   if (vclp->vcl_cb_rtn != consumer) continue;
+   if (vclp->vcl_udata != user_data) continue;
+
+   hp2 = (struct h_t *) vclp->vclobj;
+   __acc_vpi_erroff = TRUE;
+   cv = vpi_compare_objects((vpiHandle) hp, (vpiHandle) hp2);
+   /* this access error vpi_ error info */  
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1754,
+      "acc_vcl_add problem comparing other added primitive output terminal vcl object %s",
+       to_acc_onam(__wrks1, hp2->hrec->htyp));
+     continue;
+    }
+   /* cv 0 if different - if different did not find match */
+   if (cv == 0) continue; 
+   return(vclp);
+  }
+ return(NULL);
+}
+
+/*
+ * routine to execute acc_ vcl callback 
+ *
+ * this is routine executed by vpi_ cb mechanism when variable changed
+ */
+static int32 exec_acc_vclcb(struct t_cb_data *cbp)
+{
+ int32 bi;
+ byte sbv;
+ word32 st0, st1;
+ struct vclrec_t *vclp;
+ struct h_t *hp;
+ struct net_t *np;
+ struct t_vc_record wrkvcl;
+ struct t_strengths wrkstval;
+ struct t_vpi_value tmpval;
+
+ /* suppress vcl callbacks during reset */
+ /* LOOKATME - is this needed */
+ if (__run_state == SS_RESET) return(FALSE); 
+
+ vclp = (struct vclrec_t *) cbp->user_data; 
+ /* DBG remove --- */
+ if (vclp == NULL) __acc_terr(__FILE__, __LINE__);
+ /* --- */
+ hp = (struct h_t *) cbp->obj;
+ np = hp->hrec->hu.hnp;
+
+ /* access value and store in vc record unless vector - add sets right */
+ switch (vclp->vcl_reason) {
+  case logic_value_change: case sregister_value_change:
+   if (np->n_stren)
+    {
+     /* must filter out strength - no callback if non value part change */
+     if (np->n_isavec) bi = hp->hrec->hi; else bi = 0;
+     /* BEWARE - strength internal storage byte vector dependent */
+     sbv = np->nva.bp[np->nwid*hp->hin_itp->itinum + bi];
+     if ((vclp->vcl_oldstval & 3) == (sbv & 3))
+      { vclp->vcl_oldstval = sbv; return(FALSE); }
+     vclp->vcl_oldstval = sbv;
+     wrkvcl.out_value.logic_value = map_to_accvclval((word32) (sbv & 3));
+    }
+   else
+    {
+     __acc_vpi_erroff = TRUE;
+     tmpval.format = vpiScalarVal; 
+     vpi_get_value((vpiHandle) hp, &tmpval);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1756,
+        "acc_add_vcl callback on %s - interal error accessing logic value",
+        to_acc_onam(__wrks1, hp->hrec->htyp));
+       return(FALSE);
+      }
+     wrkvcl.out_value.logic_value
+      = map_vpi_to_accvclval((word32) tmpval.value.scalar);   
+    }
+   break;
+  case strength_value_change:
+   if (np->n_stren)
+    {
+     if (np->n_isavec) bi = hp->hrec->hi; else bi = 0;
+     /* BEWARE - strength internal storage byte vector dependent */
+     sbv = np->nva.bp[np->nwid*hp->hin_itp->itinum + bi];
+
+     wrkstval.logic_value = map_vpi_to_accvclval((word32) (sbv & 3));
+     st0 = __map_tovpi_stren(((((word32) sbv) >> 5) & 7));
+     st1 = __map_tovpi_stren(((((word32) sbv) >> 2) & 7));
+     wrkstval.strength1 = (int32) map_vpi_to_accstren(st0);
+     wrkstval.strength2 = (int32) map_vpi_to_accstren(st1);
+    }
+   else  
+    {
+     __acc_vpi_erroff = TRUE;
+     tmpval.format = vpiScalarVal; 
+     vpi_get_value((vpiHandle) hp, &tmpval);
+     if (__my_vpi_chk_error())
+      {
+       __acc_err(1756,
+        "acc_add_vcl callback on %s - interal error accessing logic value",
+        to_acc_onam(__wrks1, hp->hrec->htyp));
+       return(FALSE);
+      }
+     wrkstval.logic_value 
+      = map_vpi_to_accvclval((word32) tmpval.value.scalar);   
+     wrkstval.strength1 = vclStrong; 
+     wrkstval.strength2 = vclStrong;
+    }
+   /* notice in acc_ struct is record not ptr */
+   wrkvcl.out_value.strengths_s = wrkstval;
+   break;
+  case vector_value_change: case vregister_value_change:
+  case integer_value_change: case time_value_change:
+   wrkvcl.out_value.vector_handle = (handle) hp;
+   break;
+  /* these impossible 
+  case real_value_change: case event_value_change: case realtime_value_change:
+  --- */
+  default: __acc_terr(__FILE__, __LINE__);
+ }
+ /* fill rest of vc record */
+ wrkvcl.vc_reason = vclp->vcl_reason; 
+ wrkvcl.vc_hightime = (int32) ((__simtime >> 32) & WORDMASK_ULL);
+ wrkvcl.vc_lowtime = (int32) (__simtime & WORDMASK_ULL);
+ wrkvcl.user_data = vclp->vcl_udata;
+
+ /* final step exec acc vcl consumer routine */
+ (*(vclp->vcl_cb_rtn))(&wrkvcl);
+ /* all storage automatic (on stack) so no need to free */
+ return(TRUE);
+}
+
+/*
+ * routine to execute acc_ special case prim terminal output vcl callback 
+ *
+ * this is routine executed by vpi_ cb mechanism when gate output driver
+ * changes
+ */
+static int32 exec_acc_gateout_vclcb(struct t_cb_data *cbp)
+{
+ struct vclrec_t *vclp;
+ struct h_t *hp;
+ struct t_vc_record wrkvcl;
+ struct t_strengths wrkstval;
+ struct t_vpi_value tmpval;
+
+ /* suppress vcl callbacks during reset */
+ /* LOOKATME - is this needed */
+ if (__run_state == SS_RESET) return(FALSE); 
+
+ vclp = (struct vclrec_t *) cbp->user_data; 
+ /* DBG remove --- */
+ if (vclp == NULL) __acc_terr(__FILE__, __LINE__);
+ /* --- */
+ hp = (struct h_t *) cbp->obj;
+ /* DBG remove --- */
+ if (hp->hrec->htyp != vpiPrimTerm) __acc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* DBG remove -- */
+ if (cbp->value == NULL) __acc_terr(__FILE__, __LINE__);
+ /* --- */ 
+
+ /* access value and store in vc record unless vector - add sets right */
+ switch (vclp->vcl_reason) {
+  case logic_value_change:
+   __acc_vpi_erroff = TRUE;
+   tmpval.format = vpiScalarVal; 
+   vpi_get_value((vpiHandle) hp, &tmpval);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1756,
+      "acc_add_vcl callback on %s - interal error accessing logic value",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(FALSE);
+    }
+   wrkvcl.out_value.logic_value
+    = map_vpi_to_accvclval((word32) tmpval.value.scalar);   
+   break;
+  case strength_value_change:
+   __acc_vpi_erroff = TRUE;
+   tmpval.format = vpiStrengthVal; 
+   vpi_get_value((vpiHandle) hp, &tmpval);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1756,
+      "acc_add_vcl callback on %s - interal error accessing logic value",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(FALSE);
+    }
+   wrkstval.logic_value = map_vpi_to_accvclval(tmpval.value.strength->logic);
+   wrkstval.strength1 = (int32) map_vpi_to_accstren(tmpval.value.strength->s0);
+   wrkstval.strength2 = (int32) map_vpi_to_accstren(tmpval.value.strength->s1);
+   /* notice in acc_ struct is record not ptr */
+   wrkvcl.out_value.strengths_s = wrkstval;
+   break;
+  default: __acc_terr(__FILE__, __LINE__);
+ }
+ /* fill rest of vc record */
+ wrkvcl.vc_reason = vclp->vcl_reason; 
+ wrkvcl.vc_hightime = (int32) ((__simtime >> 32) & WORDMASK_ULL);
+ wrkvcl.vc_lowtime = (int32) (__simtime & WORDMASK_ULL);
+ wrkvcl.user_data = vclp->vcl_udata;
+
+ /* final step exec acc vcl consumer routine */
+ (*(vclp->vcl_cb_rtn))(&wrkvcl);
+ /* all storage automatic (on stack) so no need to free */
+ return(TRUE);
+}
+
+/*
+ * convert internal cver value to acc vcl value
+ */
+static int32 map_to_accvclval(word32 ival)
+{
+ switch ((byte) ival) {
+  case 0: return(vcl0);
+  case 1: return(vcl1);
+  case 2: return(vclZ);
+  case 3: return(vclX);
+  default: 
+   __acc_err(1992,
+    "illegal internal value %d - unable to map toi vcl value", ival);
+   break;
+ }
+ return(vclX);
+}
+
+/*
+ * convert vpi value to acc vcl value
+ */
+static int32 map_vpi_to_accvclval(word32 vpival)
+{
+ switch ((byte) vpival) {
+  case vpi0: return(vcl0);
+  case vpi1: return(vcl1);
+  case vpiZ: return(vclZ);
+  case vpiX: return(vclX);
+  default:
+   __acc_err(1992,
+    "illegal internal PLI value %d - unable to map to vcl value", vpival);
+   break;
+ }
+ return(vclX);
+}
+
+/*
+ * convert vpi value to acc value
+ * LOOKATME - why is this not used
+ */
+static int32 map_vpi_to_accval(word32 vpival)
+{
+ switch ((byte) vpival) {
+  case vpi0: return(acc0);
+  case vpi1: return(acc1);
+  case vpiZ: return(accZ);
+  case vpiX: return(accX);
+  default:
+   __acc_err(1992,
+    "illegal internal PLI value %d - unable to map to acc value", vpival);
+   break;
+ }
+ return(accX);
+}
+
+/*
+ * convert acc value to vpi value
+ */
+static int32 map_acc_to_vpival(word32 accval)
+{
+ switch ((byte) accval) {
+  case acc0: return(vpi0);
+  case acc1: return(vpi1);
+  case accZ: return(vpiZ);
+  case accX: return(vpiX);
+  default:
+   __acc_err(1992,
+    "illegal acc value %d - unable to map to internal PLI value", accval);
+   break;
+ }
+ return(vpiX);
+}
+
+/*
+ * map from vpi strength values to acc strength
+ */
+static int32 map_vpi_to_accstren(word32 stval)
+{
+ word32 accstval;
+
+ switch ((byte) stval) {
+  case vpiSupplyDrive: accstval = vclSupply; break;
+  case vpiStrongDrive: accstval = vclStrong; break;
+  case vpiPullDrive: accstval = vclPull; break;
+  case vpiWeakDrive: accstval = vclLarge; break;
+  case vpiLargeCharge: accstval = vclWeak; break;
+  case vpiMediumCharge: accstval = vclMedium; break;
+  case vpiSmallCharge: accstval = vclSmall; break;
+  case vpiHiZ: accstval = vclHighZ; break;
+  default:
+   __acc_err(1992,
+    "illegal internal PLI value %d - unable to map to acc strength value",
+    stval);
+   accstval = vclStrong;
+ }
+ return(accstval);
+}
+
+/*
+ * find and remove previously added vcl callback
+ */
+extern void acc_vcl_delete(handle object_p, int32 (*consumer)(),
+ char *user_data, int32 vcl_flags)
+{
+ struct h_t *hp, *hp2;
+ struct gate_t *gp;
+ struct expr_t *xp;
+ struct vclrec_t *vclp;
+
+ acc_error_flag = FALSE;
+ if (__run_state != SS_SIM)
+  { acc_not_sim_err("acc_vcl_delete"); return; } 
+
+ /* check arguments */
+ if (consumer == NULL)
+  {
+   __acc_err(1987,
+    "acc_vcl_delete call illegal - consumer routine must not be NULL");
+   return;
+  }
+
+ hp = (struct h_t *) object_p;
+ if (!validate_acc_handle("acc_vcl_delete", hp)) return; 
+
+ if (hp->hrec->htyp == vpiPrimTerm)
+  {
+   /* SJM 11/28/00 - must change handle to terminal for trans */
+   gp = hp->hrec->hu.hgp; 
+   if (gp->g_class == GC_PULL || gp->g_class == GC_TRAN
+    || gp->g_class == GC_TRANIF)
+    {
+     xp = hp->hrec->hu.hgp->gpins[hp->hrec->hi];
+     /* SJM 11/28/00 - also must change handle to terminal index handle */
+     hp2 = (struct h_t *) __mk_exprclass_handle(xp, hp->hin_itp,
+      hp->hrec->hin_tskp);
+     hp = hp2;
+     vclp = findmatch_net_vcl_dce(hp, consumer, user_data);
+    }
+   else vclp = findmatch_term_vcl_dce(hp, consumer, user_data);
+  }
+ else { vclp = findmatch_net_vcl_dce(hp, consumer, user_data); }
+
+ if (vclp == NULL)
+  {
+   __acc_err(1989,
+    "acc_vcl_delete failed for object %s - no matching vcl change monitor present",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return;
+  }
+ /* remove the vpi_ callback and free the vcl record */
+ __acc_vpi_erroff = TRUE;
+
+ if (!vpi_remove_cb((vpiHandle) vclp->vclcbp->cb_cbhp))
+  {
+bad_rem:
+   __acc_err(1991,
+    "acc_vcl_delete for object %s - internal problem removing change monitor",
+    to_acc_onam(__wrks1, hp->hrec->htyp));
+   return;
+  }
+ if (__my_vpi_chk_error()) goto bad_rem;
+ __my_free((char *) vclp, sizeof(struct vclrec_t));
+}
+
+/*
+ * allow user to get version
+ */
+extern char *acc_version(void)
+{
+ char s1[RECLEN];
+
+ sprintf(s1, "acc_ access routines Version %s%s of %s\n", __vers,
+  __vers2, __ofdt);
+ return(add_accstrbuf(s1));
+}
+
+/*
+ * ROUTINES TO FREE ACC_ OBJECTS FOR RESET
+ */
+
+/*
+ * VPI TO ACC CONSTANT CONVERSION ROUTINES
+ */
+
+/* dense table to map vpi object numbers to acc fulltypes */   
+/* BEWARE - this require first vpi object to be dense */
+/* -1 for vpi objects with no acc type (existance)  */
+static struct vpi_to_acc_t vpi_to_acc[] = {
+ { 0, -1 }, 
+ { vpiAlways, -1 },
+ { vpiAssignStmt, accStatement },
+ { vpiAssignment, accStatement },
+ { vpiBegin, accStatement },
+ { vpiCase, accStatement },
+ { vpiCaseItem, -1 },
+ { vpiConstant, accConstant },
+ { vpiContAssign, -1 },
+ { vpiDeassign, accStatement },
+ { vpiDefParam, -1 },
+ { vpiDelayControl, accStatement },
+ { vpiDisable, accStatement },
+ { vpiEventControl, accStatement },
+ { vpiEventStmt, accStatement },
+ { vpiFor, accStatement },
+ { vpiForce, accStatement },
+ { vpiForever, accStatement },
+ { vpiFork, accStatement },
+ { vpiFuncCall, -1 },
+ { vpiFunction, accFunction },
+ /* primitives in acc are also switches */
+ { vpiGate, accPrimitive },
+ { vpiIf, accStatement },
+ { vpiIfElse, accStatement },
+ { vpiInitial, -1 },
+ { vpiIntegerVar, accIntegerVar },
+ /* this is fulltype in acc */
+ { vpiInterModPath, accInterModPath },
+ { vpiIterator, -1 },
+ { vpiIODecl, -1 },
+ { vpiMemory, accReg },
+ { vpiMemoryWord, accReg },
+ { vpiModPath, accModPath },
+ { vpiModule, accModule },
+ { vpiNamedBegin, accNamedBeginStat },
+ { vpiNamedEvent, accNamedEvent },
+ { vpiNamedFork, accNamedForkStat },
+ { vpiNet, accNet },
+ { vpiNetBit, accNetBit },
+ { vpiNullStmt, accStatement },
+ { vpiOperation, accOperator },
+ { vpiParamAssign, -1 },
+ { vpiParameter, accParameter },
+ { vpiPartSelect, accPartSelect },
+ { vpiPathTerm, accPathTerminal },
+ { vpiPort, accPort },
+ { vpiPortBit, accPortBit },
+ { vpiPrimTerm, accTerminal },
+ { vpiRealVar, accRealVar },
+ { vpiReg, accReg },
+ { vpiRegBit, accRegBit },
+ { vpiRelease, accStatement },
+ { vpiRepeat, accStatement },
+ { vpiRepeatControl, accStatement },
+ { vpiSchedEvent, -1 },
+ { vpiSpecParam, accSpecparam },
+ { vpiSwitch, accPrimitive },
+ /* special case need to distinquish: accSystemFunction, and real form */
+ { vpiSysFuncCall, accSystemFunction },
+ { vpiSysTaskCall, accSystemTask },
+ { vpiTableEntry, -1 },
+ { vpiTask, accTask },
+ { vpiTaskCall, -1 },
+ { vpiTchk, accTchk },
+ { vpiTchkTerm, accTchkTerminal },
+ { vpiTimeVar, accTimeVar },
+ { vpiTimeQueue, -1 },
+ { vpiUdp, accPrimitive },
+ { vpiUdpDefn, -1 },
+ /* special case maps to: accUserFunction, accUserRealFunction */
+ /* LOOKATME - also accSystemTask ?? */
+ { vpiUserSystf, accUserFunction },
+ { vpiVarSelect, accRegBit },
+ { vpiWait, accStatement },
+ { vpiWhile, accStatement }
+};
+
+/* BEWARE if vpi_user.h changes this must change to highest vpi obj val */
+#define LAST_VPIOBJTYP vpiWhile
+
+/*
+ * get acc type - know handle already validated
+ *
+ * must be called with known good (checked) vpi handle 
+ */
+static struct vpi_to_acc_t *get_acc_typerec(struct h_t *hp)
+{
+ struct vpi_to_acc_t *accvpip;
+
+ accvpip = &(vpi_to_acc[hp->hrec->htyp]);
+ /* DBG remove -- */
+ if (accvpip->acc_otyp == -1) __acc_terr(__FILE__, __LINE__);
+ if (accvpip->vpiotyp != hp->hrec->htyp) __acc_terr(__FILE__, __LINE__);
+ /* --- */
+ return(accvpip);
+}
+
+/*
+ * routine to access acc fulltype constant from type
+ *
+ * for most fulltype is same as type
+ */
+static int32 get_acc_fulltype(vpiHandle vpiop, struct vpi_to_acc_t *accvpip)
+{
+ int32 rv;
+ struct h_t *hp; 
+ s_vpi_systf_data systfdat;
+ struct net_t *np;
+ struct mod_pin_t *mpp;
+ struct gate_t *gp;
+ struct primtab_t *ptp;
+ struct st_t *stp;
+ struct tchk_t *tcp;
+ struct mod_t *mdp;
+
+ hp = (struct h_t *) vpiop; 
+
+ if (accvpip->acc_otyp == accUserFunction
+  || accvpip->acc_otyp == accSystemFunction)
+  {
+   /* here need to distinguish real from non real case */
+   __acc_vpi_erroff = TRUE;
+   vpi_get_systf_info(vpiop, &systfdat);
+   if (__my_vpi_chk_error())
+    {
+     __acc_err(1952,
+      "acc_fetch_fulltype unable to access systf_info for %s object",
+      to_acc_onam(__wrks1, hp->hrec->htyp));
+     return(0);
+    }
+   if (systfdat.sysfunctype == vpiRealFunc)
+    {
+     if (hp->hrec->htyp == vpiUserSystf) return(accUserRealFunction);
+     if (hp->hrec->htyp == vpiSysFuncCall) return(accSystemRealFunction);
+     __acc_terr(__FILE__, __LINE__);
+    }
+   if (hp->hrec->htyp == vpiUserSystf) return(accUserFunction);
+   if (hp->hrec->htyp == vpiSysFuncCall) return(accSystemFunction);
+   __acc_terr(__FILE__, __LINE__);
+   return(0);
+  }
+
+ hp = (struct h_t *) vpiop; 
+ switch (accvpip->acc_otyp) {
+  case accModule:
+   mdp = hp->hrec->hu.hmdp;
+   if (mdp->minstnum == 0) return(accTopModule);
+   if (mdp->m_iscell) return(accCellInstance);
+   return(accModuleInstance);
+  case accNet: 
+   np = hp->hrec->hu.hnp;
+   switch ((byte) np->ntyp) {
+    case N_WIRE: rv = accWire; break;
+    case N_TRI: rv = accTri; break;
+    case N_TRI0: rv = accTri0; break;
+    case N_TRI1: rv = accTri1; break;
+    case N_TRIAND: rv = accTriand; break;
+    case N_TRIOR: rv = accTrior; break;
+    case N_TRIREG: rv = accTrireg; break;
+    case N_WA: rv = accWand; break;
+    case N_WO: rv = accWor; break;
+    case N_SUPPLY0: rv = accSupply0; break;
+    case N_SUPPLY1: rv = accSupply1; break;
+    default: rv = -1; __acc_terr(__FILE__, __LINE__);
+   }
+   return(rv);
+  case accParameter: case accSpecparam:
+   np = hp->hrec->hu.hnp;
+   /* DBG remove --- */
+   if (!np->n_isaparam) __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   if (np->ntyp == N_REAL) return(accRealParam);
+   if (np->nu.ct->pstring) return(accStringParam);
+   return(accIntegerParam);
+  case accModPath:
+   /* LOOKATME - where do intermodule paths come from ?? */
+   return(accModPath);
+  case accPathTerminal:
+   if (hp->hrec->htyp2 == vpiModPathIn || hp->hrec->htyp2 == vpiModDataPathIn)
+    return(accPathInput);
+   if (hp->hrec->htyp2 == vpiModPathOut) return(accPathOutput);
+   /* DBG remove --- */
+   __acc_terr(__FILE__, __LINE__);
+   /* --- */
+   break;
+  case accPort:
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
+   if (mpp->mpref->optyp == LCB) return(accConcatPort);
+   if (mpp->mpref->optyp == PARTSEL) return(accPartSelectPort);
+   if (mpp->mpref->optyp == LSB && !mpp->mpref->lu.x->lu.sy->el.enp->n_isarr) 
+    return(accBitSelectPort);
+   if (mpp->mpwide == 1) return(accScalarPort);
+   return(accVectorPort);
+  case accPrimitive:
+   gp = hp->hrec->hu.hgp;
+   if (gp->g_class == GC_UDP)
+    {
+     if (gp->gmsym->el.eudpp->utyp == U_COMB) return(accCombPrim);
+     return(accSeqPrim);
+    }
+   ptp = gp->gmsym->el.eprimp; 
+   switch ((byte) ptp->gateid) {
+    /* LOOKATM - where are pullup/pulldown "gates" */
+    case G_BITREDAND: return(accAndGate);
+    case G_NAND: return(accNandGate);
+    case G_NOR: return(accNorGate);
+    case G_BITREDOR: return(accOrGate);
+    case G_BITREDXOR: return(accXorGate);
+    case G_REDXNOR: return(accXnorGate);
+    case G_BUF: return(accBufGate);
+    case G_NOT: return(accNotGate);
+    case G_BUFIF0: return(accBufif0Gate);
+    case G_BUFIF1: return(accBufif1Gate);
+    case G_NOTIF0: return(accNotif0Gate);
+    case G_NOTIF1: return(accNotif1Gate);
+    case G_NMOS: return(accNmosGate);
+    case G_RNMOS: return(accRnmosGate);
+    case G_PMOS: return(accPmosGate);
+    case G_RPMOS: return(accRpmosGate);
+    case G_CMOS: return(accCmosGate);
+    case G_RCMOS: return(accRcmosGate);
+    case G_TRAN: return(accTranGate);
+    case G_RTRAN: return(accRtranGate);
+    case G_TRANIF0: return(accTranif0Gate);
+    case G_RTRANIF0: return(accRtranif0Gate);
+    case G_TRANIF1: return(accTranif1Gate);
+    case G_RTRANIF1: return(accRtranif1Gate);
+    default: __acc_terr(__FILE__, __LINE__);
+   }
+   break;
+  case accStatement:
+   stp = hp->hrec->hu.hstp;
+   if (stp->stmttyp == S_NAMBLK)
+    {
+     if (stp->st.snbtsk->tsktyp == Begin) return(accNamedBeginStat);
+     if (stp->st.snbtsk->tsktyp == FORK) return(accNamedForkStat);
+     __acc_terr(__FILE__, __LINE__);
+     break;
+    }
+   /* any other statement type, not distinguished in acc */
+   return(accStatement);
+  case accTchk:
+   tcp = hp->hrec->hu.htcp; 
+   switch ((byte) tcp->tchktyp) {
+    case TCHK_SETUP: return(accSetup);
+    case TCHK_HOLD: return(accHold);  
+    case TCHK_WIDTH: return(accWidth);
+    case TCHK_PERIOD: return(accPeriod);
+    case TCHK_SKEW: return(accSkew);
+    case TCHK_RECOVERY: return(accRecovery);
+    case TCHK_NOCHANGE: return(accNoChange);
+    case TCHK_SETUPHOLD: return(accSetuphold);
+    /* SJM 01/16/04 - notice the new 2001 LRM timing checks not in acc_ */
+    default: __acc_terr(__FILE__, __LINE__);
+   }
+   break;
+  case accTerminal:
+   gp = hp->hrec->hu.hgp; 
+   switch (gp->g_class) { 
+    case GC_LOGIC: case GC_UDP: case GC_BUFIF: case GC_MOS: case GC_CMOS:
+     if (hp->hrec->hi > 1) return(accInputTerminal);
+     return(accOutputTerminal);
+    case GC_TRAN: return(accInoutTerminal);
+    case GC_TRANIF:
+     if (hp->hrec->hi >= 2) return(accInputTerminal);
+     return(accInoutTerminal);
+    case GC_PULL: return(accOutputTerminal);
+    default: __acc_terr(__FILE__, __LINE__);
+   }
+   break;
+  case accWirePath: return(accInterModPath); 
+ }
+ /* otherwise full type same as type */
+ return(accvpip->acc_otyp);
+}
+
+/* 
+ * table of acc configuration constants (from acc user .h) 
+ *
+ * table must be sorted but is not dense or numeric ordered 
+ */
+static struct pnamvpi_t accconfig_names[] = {
+ { "accDefaultAttr0", accDefaultAttr0 },
+ { "accDevelopmentVersion", accDevelopmentVersion },
+ { "accDisplayErrors", accDisplayErrors },
+ { "accDisplayWarnings", accDisplayWarnings },
+ { "accEnableArgs", accEnableArgs },
+ { "accMapToMipd", accMapToMipd },
+ { "accMinTypMaxDelays", accMinTypMaxDelays },
+ { "accPathDelayCount", accPathDelayCount },
+ { "accPathDelimStr", accPathDelimStr },
+ { "accToHiZDelay", accToHiZDelay }
+};
+#define NCGFCONS (sizeof(accconfig_names) / sizeof(struct pnamvpi_t))
+
+/*
+ * given configuration constant value - table index
+ * returns -1 if not found
+ *
+ * names sorted but not contiguous values
+ * LOOKATME - using vpi_ tables so maybe should make acc duplicates
+ */
+static char *get_cfgconst_nam(char *s, int32 cfg_connum)
+{
+ register int32 i;
+
+ for (i = 0; i < NCGFCONS; i++)
+  {
+   if (accconfig_names[i].vpiproptyp == cfg_connum)
+    {
+     strcpy(s, accconfig_names[i].vpipropnam);
+     return(s);
+    }
+  }
+ strcpy(s, "**UNKNOWN**");
+ return(s);
+}
+
+/*
+ * ACC VALUE TO NAME CONVERSION ROUTINES
+ */
+
+struct accnam_t accnamtab[] = {
+ { "accModule", accModule },
+ { "accScope", accScope },
+ { "accNet", accNet },
+ { "accReg", accReg },
+ { "accPort", accPort },
+ { "accTerminal", accTerminal },
+ { "accInputTerminal", accInputTerminal },
+ { "accOutputTerminal", accOutputTerminal },
+ { "accInoutTerminal", accInoutTerminal },
+ { "accCombPrim", accCombPrim },
+ { "accSeqPrim", accSeqPrim },
+ { "accAndGate", accAndGate },
+ { "accNandGate", accNandGate },
+ { "accNorGate", accNorGate },
+ { "accOrGate", accOrGate },
+ { "accXorGate", accXorGate },
+ { "accXnorGate", accXnorGate },
+ { "accBufGate", accBufGate },
+ { "accNotGate", accNotGate },
+ { "accBufif0Gate", accBufif0Gate },
+ { "accBufif1Gate", accBufif1Gate },
+ { "accNotif0Gate", accNotif0Gate },
+ { "accNotif1Gate", accNotif1Gate },
+ { "accNmosGate", accNmosGate },
+ { "accPmosGate", accPmosGate },
+ { "accCmosGate", accCmosGate },
+ { "accRnmosGate", accRnmosGate },
+ { "accRpmosGate", accRpmosGate },
+ { "accRcmosGate", accRcmosGate },
+ { "accRtranGate", accRtranGate },
+ { "accRtranif0Gate", accRtranif0Gate },
+ { "accRtranif1Gate", accRtranif1Gate },
+ { "accTranGate", accTranGate },
+ { "accTranif0Gate", accTranif0Gate },
+ { "accTranif1Gate", accTranif1Gate },
+ { "accPullupGate", accPullupGate },
+ { "accPulldownGate", accPulldownGate },
+ { "accIntegerParam", accIntegerParam },
+ { "accRealParam", accRealParam },
+ { "accStringParam", accStringParam },
+ { "accTchk", accTchk },
+ { "accPrimitive", accPrimitive },
+ { "accPortBit", accPortBit },
+ { "accNetBit", accNetBit },
+ { "accRegBit", accRegBit },
+ { "accParameter", accParameter },
+ { "accSpecparam", accSpecparam },
+ { "accTopModule", accTopModule },
+ { "accModuleInstance", accModuleInstance },
+ { "accCellInstance", accCellInstance },
+ { "accModPath", accModPath },
+ { "accWirePath", accWirePath },
+ { "accInterModPath", accInterModPath },
+ { "accScalarPort", accScalarPort },
+ { "accPartSelectPort", accPartSelectPort },
+ { "accVectorPort", accVectorPort },
+ { "accConcatPort", accConcatPort },
+ { "accWire", accWire },
+ { "accWand", accWand },
+ { "accWor", accWor },
+ { "accTri", accTri },
+ { "accTriand", accTriand },
+ { "accTrior", accTrior },
+ { "accTri0", accTri0 },
+ { "accTri1", accTri1 },
+ { "accTrireg", accTrireg },
+ { "accSupply0", accSupply0 },
+ { "accSupply1", accSupply1 },
+ { "accNamedEvent", accNamedEvent },
+ { "accIntegerVar", accIntegerVar },
+ { "accIntVar", accIntVar },
+ { "accRealVar", accRealVar },
+ { "accTimeVar", accTimeVar },
+ { "accScalar", accScalar },
+ { "accVector", accVector },
+ /* LOOKATME - where does this come from */
+ { "accCollapsedNet", accCollapsedNet },
+ { "accExpandedVector", accExpandedVector },
+ { "accUnExpandedVector", accUnExpandedVector },
+ { "accSetup", accSetup },
+ { "accHold", accHold },
+ { "accWidth", accWidth },
+ { "accPeriod", accPeriod },
+ { "accRecovery", accRecovery },
+ { "accSkew", accSkew },
+ { "accNochange", accNochange },
+ { "accSetuphold", accSetuphold },
+ { "accInput", accInput },
+ { "accOutput", accOutput },
+ { "accInout", accInout },
+ { "accMixedIo", accMixedIo },
+ { "accPositive", accPositive },
+ { "accNegative", accNegative },
+ { "accUnknown", accUnknown },
+ { "accPathTerminal", accPathTerminal },
+ { "accPathInput", accPathInput },
+ { "accPathOutput", accPathOutput },
+ { "accDataPath", accDataPath },
+ { "accTchkTerminal", accTchkTerminal },
+ { "accBitSelect", accBitSelect },
+ { "accPartSelect", accPartSelect },
+ { "accTask", accTask },
+ { "accFunction", accFunction },
+ { "accStatement", accStatement },
+ { "accSystemTask", accSystemTask },
+ { "accSystemFunction", accSystemFunction },
+ { "accSystemRealFunction", accSystemRealFunction },
+ { "accUserTask", accUserTask },
+ { "accUserFunction", accUserFunction },
+ { "accUserRealFunction", accUserRealFunction },
+ /* LOOKATME - where are these ??? */
+ { "accNamedBeginStat", accNamedBeginStat },
+ { "accNamedForkStat", accNamedForkStat },
+
+ { "accConstant", accConstant },
+ { "accConcat", accConcat },
+ { "accOperator", accOperator },
+ { "accMinTypMax", accMinTypMax },
+ /* LOOKATME - where as this ??? */
+ { "accModPathHasIfnone", accModPathHasIfnone }
+};
+#define NACC_CONS (sizeof(accnamtab) / sizeof(struct accnam_t))
+
+/*
+ * routine to return name of acc type or fulltype constant
+ *
+ * LOOKATME - could use binary search but should be rare
+ */
+static char *get_accnam(int32 accnum)
+{
+ register int32 i;
+
+ for (i = 0; i < NACC_CONS; i++) 
+  { if (accnamtab[i].accval == accnum) return(accnamtab[i].accnam); }
+ /* nil on no match - caller emits error */
+ return(NULL);
+}
+
+/*
+ * ROUTINES TO ACCESS INTERNAL INFO 
+ */
+
+/*
+ * undocumented (to users) debug routine for showing contents of acc_ handle
+ *
+ * LOOKATME - maybe should dump more information for some object types 
+ * LOOKATME - not portable because of addr cast
+ */
+extern int32 __acc_show_object(handle obj)
+{
+ int32 bad_inst, bad_tsk, first_time, ttyp, tryget_name;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+ struct vpi_to_acc_t *accvpip;
+ char *chp, s1[RECLEN], s2[RECLEN]; 
+
+ __my_fprintf(stdout, ">>> showing acc_ object:\n");
+ hp = (struct h_t *) obj;
+
+ if (!__chk_showobj(hp, &(bad_inst), &(bad_tsk))) return(0);
+ hrp = hp->hrec;
+
+ tryget_name = TRUE;
+ accvpip = &(vpi_to_acc[hrp->htyp]);
+ if (accvpip->acc_otyp <= 0)
+  {
+   /* notice access vpi Name here */
+   __my_fprintf(stdout, 
+    "**acc handle %s invalid (probably vpi_ not acc_) - showing anyway\n",
+    __to_vpionam(__wrks1, hrp->htyp));
+  }
+
+ if (!__validate_otyp(hrp->htyp))
+  {
+   __my_fprintf(stdout,
+    "**object bad: object type %d illegal - showing anyway\n", hrp->htyp);
+   tryget_name = FALSE;
+  }
+ else
+  {
+   __my_fprintf(stdout, "Object type: %s (addr %lx)",
+    __to_vpionam(s1, hrp->htyp), (word32) hp);
+  }
+ if (hrp->htyp2 != 0) 
+  {
+   if (!__validate_otyp(hrp->htyp2))
+    {
+     __my_fprintf(stdout,
+      "\n**object bad: secondary type %d illegal\n", hrp->htyp2);
+     tryget_name = FALSE;
+    }
+   else
+    {
+     __my_fprintf(stdout, " (secondary type: %s)",
+      __to_vpionam(s1, hrp->htyp2));
+    }
+  }
+ if (!bad_inst && !bad_tsk)
+  {
+   if (hp->hin_itp == NULL)
+    {
+     __my_fprintf(stdout, " **no associated instance**");
+    }
+   else
+    {
+     __my_fprintf(stdout, " scope %s", __msg_blditree(s1, hp->hin_itp,
+      hrp->hin_tskp));
+     if (hrp->hin_tskp != NULL)
+      {
+       ttyp = __to_vpi_tasktyp(hrp->hin_tskp->tsktyp); 
+       __my_fprintf(stdout, " (%s)\n", __to_vpionam(s1, ttyp));
+      }
+    }
+  }
+ else if (!bad_inst && bad_tsk)
+  {
+   if (hp->hin_itp != NULL)
+    {
+     __my_fprintf(stdout, " scope %s (**task/func bad**)",
+      __msg2_blditree(s1, hp->hin_itp));
+    }
+   tryget_name = FALSE;
+  }
+ else if (bad_inst && !bad_tsk)
+  {
+   ttyp = __to_vpi_tasktyp(hrp->hin_tskp->tsktyp); 
+   __my_fprintf(stdout, " **bad instance** but in %s %s",
+    __to_vpionam(s1, ttyp), hrp->hin_tskp->tsksyp->synam);
+   tryget_name = FALSE;
+  }
+ else
+  {
+   __my_fprintf(stdout, " **bad instance and bad task scope**");
+   tryget_name = FALSE;
+  }
+
+ /* LOOKATME - maybe should try to get def name if can */
+ if (tryget_name)
+  {
+   __acc_vpi_erroff = TRUE;
+   /* this access error vpi_ error info and turns off vpi error cbs */  
+   /* for objects without names, expect fail here */
+   chp = vpi_get_str(vpiName, (vpiHandle) obj);
+   if (chp != NULL && !__my_vpi_chk_error())
+    {
+     __my_fprintf(stdout, " name=%s", chp); 
+    }
+  }
+ __my_fprintf(stdout, "\n");
+
+ /* build the telltales */
+ strcpy(s2, "  [");
+ first_time = TRUE;
+ if (hrp->hi != -1)
+  {
+   sprintf(s1, "index=%d", hrp->hi);
+   strcat(s2, s1);
+   if (first_time) first_time = FALSE; 
+  }
+ if (hrp->in_iter)
+  {
+   if (!first_time) strcat(s2, ", "); else first_time = FALSE;
+   strcat(s2, "in interator");
+  }
+ if (hrp->free_xpr)
+  {
+   if (!first_time) strcat(s2, ", "); else first_time = FALSE;
+   strcat(s2, "Created object");
+  }
+ if (hrp->htyp == vpiSchedEvent || hrp->htyp == vpiSchedBitEvent)
+  {
+   if (!first_time) strcat(s2, ", "); else first_time = FALSE;
+   sprintf(s1, "Scheduled event done=%d", hrp->evnt_done);
+   strcat(s2, s1);
+  }
+ if (hrp->bith_ndx)
+  {
+   if (!first_time) strcat(s2, ", "); else first_time = FALSE;
+   strcat(s2, "Variable index");
+  }
+
+ if (!first_time) __my_fprintf(stdout, "%s]\n", s2); 
+
+ /* set globals for user to look at in case debugging turned on */
+ __cur_vpi_inst = hp;  
+ __cur_vpi_obj = hrp;
+ return(1);
+}
+
+/*
+ * COMMON ERROR CONDITION ERROR ROUTINES
+ */
+
+/*
+ * emit common compilation in progress (no n.l to traverse) message
+ */
+static void acc_not_sim_err(char *rnam)
+{
+ __acc_err(1748, 
+  "%s routine not callable - simulation not started or reset in progress",
+  rnam);
+}
+
+/*
+ * validate vpi_ handle underneath acc handle
+ */
+static int32 validate_acc_handle(char *rnam, struct h_t *hp) 
+{
+ struct vpi_to_acc_t *accvpip;
+ register struct hrec_t *hrp;
+
+ /* if low value bad since ptr */
+ /* SJM 07/08/01 - high bit can be on and 4 64 bit ptr just look at low 32 */
+ if (hp == NULL || ((word32) hp) < 256)
+  {
+   strcpy(__wrks1, "** NULL OR LOW NUMBER **");
+bad_acc_handle:
+   __acc_err(1947,
+    "%s: handle illegal magic number or object type %s out of range",
+    rnam, __wrks1); 
+   return(FALSE);
+  }
+ hrp = hp->hrec;
+ if (hrp == NULL || ((word32) hrp) < 256 || hrp->h_magic != PVH_MAGIC)
+  {
+   strcpy(__wrks1, "** PTR INTO DATA BASE ILLEGAL **");
+   goto bad_acc_handle;
+  }
+ if (__to_vpionam(__wrks1, hrp->htyp) == NULL || hrp->htyp > LAST_VPIOBJTYP) 
+  {
+   sprintf(__wrks1, "underlying vpi: %d", hrp->htyp);
+   goto bad_acc_handle;
+  }
+ accvpip = &(vpi_to_acc[hrp->htyp]);
+ if (accvpip->acc_otyp <= 0)
+  {
+   /* notice access vpi Name here */
+   __acc_err(1948, "acc handle %s invalid (object probably vpi_ not acc_)",
+    __to_vpionam(__wrks1, hrp->htyp));
+   goto bad_acc_handle;
+  }
+ return(TRUE);
+}
+
+/*
+ * convert acc object to its type name
+ */
+static char *to_acc_onam(char *s, word32 vpioval)
+{
+ int32 accoval;
+
+ if (vpioval < 1 || vpioval > LAST_VPIOBJTYP)
+  {
+out_of_rng:
+   sprintf(s, "**out of range or invalid (vpi_ type %lu)", vpioval);
+   return(s);
+  }
+ if ((accoval = vpi_to_acc[vpioval].acc_otyp) == -1) goto out_of_rng;
+
+ /* once -1 checked for - know this will succeed */
+ strcpy(s, get_accnam(accoval));
+ return(s);
+}
+
+/*
+ * ACC VPI ERROR INTERFACE ROUTINES
+ */
+
+/*
+ * my wrapper around vpi_ check error
+ *
+ * must die on fatal error
+ * this resets vpi error indicator in case acc_ and vpi_ mixed
+ */
+extern int32 __my_vpi_chk_error(void)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+
+ __acc_vpi_erroff = FALSE;
+ if (!vpi_chk_error(&einfotab)) return(FALSE);
+ einfop = &einfotab;
+ /* notices and warning are not acc_ problems */
+ if (einfop->level == vpiNotice || einfop->level == vpiWarning)
+  return(FALSE);
+
+ /* for internal and system errors give up */
+ /* LOOKATME - maybe system should not be fatal */
+ if (einfop->level == vpiInternal || einfop->level == vpiSystem)
+  {
+   /* this never returns */
+   __acc_vpi_terr(einfop->file, einfop->line);
+  }
+ return(TRUE);
+}
+
+/*
+ * ACC ERROR ROUTINES
+ */
+
+/*
+ * emit acc error (statement location know version)
+ * notice user errors emitted with tf_err or tf_warning
+ */
+/*VARARGS*/
+extern void __acc_sferr(int32 id_num, char *fmt, ...)
+{
+ char s1[RECLEN], s2[RECLEN];
+ va_list va, va2, va3;
+
+ __pv_err_cnt++;
+ acc_error_flag = TRUE;
+ if (!__acc_displayerrors) return;
+
+ if (__run_state == SS_SIM)
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+ else strcpy(s1, "");
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   int32 slen;
+   char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**%s(%d) ACC PLI ERROR**%s [%d] ", __in_fils[__sfnam_ind],
+    __slin_cnt, s1, id_num);
+   va_start(va, fmt);
+   vsprintf(vpis2, vpis1, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(ERROR, id_num, vpichp, __in_fils[__sfnam_ind],
+    __slin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+   }
+
+ __my_fprintf(stdout, "**%s(%d) ACC PLI ERROR**%s [%d] ",
+  __in_fils[__sfnam_ind], __slin_cnt, s1, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, fmt);
+ va_start(va3, fmt);
+ __my_vfprintf(stdout, fmt, va2, va3);
+ va_end(va2);
+ va_end(va3);
+
+ my_putc_('\n', stdout);
+ /* no maximum error count*/
+}
+
+/*
+ * emit acc error (location not known)
+ * notice user errors emitted with tf_error or tf_warning
+ */
+/*VARARGS*/
+extern void __acc_err(int32 id_num, char *fmt, ...)
+{
+ va_list va, va2, va3;
+ char s1[RECLEN], s2[RECLEN];
+
+ acc_error_flag = TRUE;
+ __pv_err_cnt++;
+ if (!__acc_displayerrors) return;
+
+ if (__run_state == SS_SIM)
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+ else strcpy(s1, "");
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   int32 slen;
+   char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**ACC PLI ERROR**%s [%d] ", s1, id_num);
+   va_start(va, fmt);
+   vsprintf(vpis2, vpis1, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(WARN, id_num, vpichp, "[NONE]", 0);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+   }
+
+ __my_fprintf(stdout, "**ACC PLI ERROR**%s [%d] ", s1, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, fmt);
+ va_start(va3, fmt);
+ __my_vfprintf(stdout, fmt, va2, va3);
+ va_end(va2);
+ va_end(va3);
+
+ my_putc_('\n', stdout);
+ /* no maximum error count*/
+}
+
+/*
+ * emit acc warn (statement location know version)
+ * notice user errors emitted with tf_err or tf_warn
+ */
+/*VARARGS*/
+extern void __acc_sfwarn(int32 id_num, char *fmt, ...)
+{
+ va_list va, va2, va3;
+ char s1[RECLEN], s2[RECLEN];
+
+ __pv_warn_cnt++;
+ if (!__acc_displaywarnings) return;
+
+ if (__run_state == SS_SIM)
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+ else strcpy(s1, "");
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   int32 slen;
+   char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**%s(%d) ACC PLI WARN**%s [%d] ", __in_fils[__sfnam_ind],
+    __slin_cnt, s1, id_num);
+   va_start(va, fmt);
+   vsprintf(vpis2, vpis1, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(WARN, id_num, vpichp, __in_fils[__sfnam_ind],
+    __slin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+   }
+
+ __my_fprintf(stdout, "**%s(%d) ACC PLI WARN**%s [%d] ",
+  __in_fils[__sfnam_ind], __slin_cnt, s1, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, fmt);
+ va_start(va3, fmt);
+ __my_vfprintf(stdout, fmt, va2, va3);
+ va_end(va2);
+ va_end(va3);
+
+ my_putc_('\n', stdout);
+ /* no maximum error count*/
+}
+
+/*
+ * emit acc warn
+ * notice user errors emitted with tf_err or tf_warn
+ */
+/*VARARGS*/
+extern void __acc_warn(int32 id_num, char *fmt, ...)
+{
+ va_list va, va2, va3;
+ char s1[RECLEN], s2[RECLEN];
+
+ __pv_warn_cnt++;
+ if (!__acc_displaywarnings) return;
+
+ if (__run_state == SS_SIM)
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+ else strcpy(s1, "");
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   int32 slen;
+   char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**ACC PLI WARN**%s [%d] ", s1, id_num);
+   va_start(va, fmt);
+   vsprintf(vpis2, vpis1, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(WARN, id_num, vpichp, "[NONE]", 0);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+   }
+
+ __my_fprintf(stdout, "**ACC PLI WARN**%s [%d] ", s1, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, fmt);
+ va_start(va3, fmt);
+ __my_vfprintf(stdout, fmt, va2, va3);
+ va_end(va2);
+ va_end(va3);
+
+ my_putc_('\n', stdout);
+ /* no maximum error count*/
+}
+
+/*
+ * acc internal fatal error 
+ */
+extern void __acc_terr(char *fnam, int32 lno)
+{
+ __pv_terr(331,
+  "ACC PLI INTERNAL - source line **%s(%d) - maybe at **%s(%d)\n",
+  fnam, lno, __in_fils[__sfnam_ind], __slin_cnt);
+}
+
+/*
+ * acc internal fatal error occurring in vpi_ routine 
+ */
+extern void __acc_vpi_terr(char *fnam, int32 lno)
+{
+ __pv_terr(332,
+  "ACC PLI INTERNAL (IN VPI) - source line **%s(%d) - maybe at **%s(%d)\n",
+  fnam, lno, __in_fils[__sfnam_ind], __slin_cnt);
+}
diff --git a/src/v_cnv.c b/src/v_cnv.c
new file mode 100644
index 0000000..752406f
--- /dev/null
+++ b/src/v_cnv.c
@@ -0,0 +1,6221 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * input/output conversion and bit part selection mechanism routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+#include <ctype.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void disp_toexprline(register struct expr_t *, int32);
+static char *sep_real_fmt(char *, char *, int32);
+static void sdisph(word32 *, word32 *, int32, int32);
+static char bitsto_char(word32, word32, int32);
+static void sdispd(word32 *, word32 *, int32, int32, int32);
+static char get_decxz(word32 *, word32 *, int32);
+static int32 bld_tfmt_val(char *, struct expr_t *, word32 *, word32 *, int32,
+ int32, int32);
+static void sdispo(word32 *, word32 *, int32, int32);
+static void vstr_to_cstr(char *, int32, int32, int32, int32);
+static void disp_ufmt_binval(word32 *, word32 *, int32);
+static void disp_zfmt_binval(word32 *, word32 *, int32);
+static void numexpr_disp(struct expr_t *, int32);
+static void st_regab_disp(byte *, int32);
+static void disp_stvar(struct net_t *, int32, int32);
+static int32 get_ovrsign(struct net_t *, char);
+static void dmp_arr_insts(struct net_t *, int32, int32);
+static void dmp_arr(struct net_t *, int32, int32, int32);
+static void dmp1n_nplst(struct mod_t *, struct net_t *, int32);
+static int32 cnt_nplstels(register struct net_pin_t *);
+static word32 get_dce_edgeval(struct mod_t *, struct dcevnt_t *);
+static int32 bin_trim_abval(word32 *, word32 *, int32);
+static int32 trim_abval(word32 *, word32 *, int32);
+static int32 bithi_is0(word32, int32);
+static int32 trim1_1val(word32 *, int32);
+static int32 vval_isall_xs(word32 *, word32 *, int32);
+static int32 vval_hasx(word32 *, word32 *, int32);
+static long my_strtol(char *, char **, int32, int32 *);
+static void dmp_dig_attr_list(FILE *, struct attr_t *, int32);
+static void dmp_modports(FILE *, struct mod_t *);
+static void dmp_mod_lofp_hdr(FILE *, struct mod_t *);
+static void dmp_decls(FILE *, struct mod_t *);
+static void dmp_1portdecl(FILE *, struct expr_t *);
+static void dmp_1netdecl(FILE *, struct net_t *);
+static int32 nd_iowirdecl(struct net_t *);
+static void dmp_paramdecls(FILE *, struct net_t *, int32, char *);
+static void dmp_defparams(FILE *, struct mod_t *);
+static void dmp_mdtasks(FILE *, struct mod_t *);
+static void dmp_insts(FILE *, struct mod_t *);
+/* DBG */ static void dbg_dmp_insts(FILE *, struct mod_t *);
+static void dmp_1inst(FILE *, struct inst_t *, struct giarr_t *);
+/* DBG */ static void dbg_dmp_1inst(FILE *f, struct inst_t *ip, char *inam);
+static void dmp_pnd_params(FILE *, struct inst_t *, struct mod_t *);
+static int32 impl_pndparams(struct inst_t *, struct mod_t *);
+static void dmp_iports(FILE *, struct inst_t *, struct expr_t **);
+static void dmp_1gate(FILE *, struct gate_t *, struct giarr_t *);
+/* DBG */ static void dbg_dmp_1gate(FILE *f, struct gate_t *gp, char *gnam);
+static void dmp_1conta(FILE *, struct conta_t *);
+static void dmp_1bitconta(FILE *, struct gate_t *);
+static void dmp_ialst(FILE *, struct mod_t *);
+static void dmp_case(FILE *, struct st_t *);
+static void dmp_case_dflt(FILE *, struct csitem_t *);
+static void dmp_fj_stlst(FILE *, struct st_t *);
+static void dmp_task(FILE *, struct task_t *);
+static void dmp_func_decl(FILE *, struct task_t *);
+static void dmp_nblock(FILE *, struct task_t *, char *);
+static void dmp_tfdecls(FILE *, struct task_t *);
+static void dmp_tf_lofp_hdr(FILE *, struct task_t *);
+static void dmp_mdspfy(FILE *, struct mod_t *);
+static void dmp_specpths(FILE *, register struct spcpth_t *);
+static void dmp_pthlst(FILE *, struct spcpth_t *, int32);
+static void dmp_pthel(FILE *, struct pathel_t *);
+static void dmp_tchks(FILE *, register struct tchk_t *);
+static void dmp_tchk_selector(FILE *, word32, struct expr_t *,
+ struct expr_t *);
+static void dmp_mod_grefs(FILE *, struct mod_t *);
+static char *to_glbinfo(char *, struct gref_t *);
+static void dmp_casesel(FILE *, struct st_t *);
+static void dmp_delay(FILE *, union del_u, word32, char *);
+static void dmp_dellst(FILE *, register struct paramlst_t *);
+static void dmp_lstofsts(FILE *, struct st_t *);
+static void tox_wrange(FILE *, struct expr_t *, struct expr_t *);
+static void dmp_expr(FILE *, struct expr_t *);
+static int32 is_simplex(struct expr_t *);
+static void dmp_catexpr(FILE *, struct expr_t *);
+static void dmp_catel(FILE *, struct expr_t *);
+static void dmp_fcallx(FILE *, struct expr_t *);
+static void dmp_evor_chain(FILE *, struct expr_t *);
+static void sdisp_st(struct expr_t *);
+static int32 find_deepest_level(struct optlst_t *);
+static int32 cnt_beg_to_endmark(struct optlst_t *, int32);
+static int32 cnt_level0(struct optlst_t *);
+static void dump_vpi_argv(int32, char **);
+static void dump_nest_vpi_argv(int32, char **);
+static void dmp1_optlst(struct optlst_t *, char *);
+
+
+/* extern prototypes defined elsewhere */
+extern char *__my_realloc(char *, int32, int32);
+extern char *__my_malloc(int32);
+extern char *__mytf_malloc(int32);
+extern char *__pv_stralloc(char *);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char *__msgtox_wrange(char *, struct expr_t *, struct expr_t *);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_wtnam2(char *, word32);
+extern char *__to_ptnam(char *, word32);
+extern char *__to_wrange(char *, struct net_t *);
+extern char *__to_stren_nam(char *, int32, int32);
+extern char *__to_stval_nam(char *, word32);
+extern char *__to_opname(word32);
+extern char *__to_vvstnam(char *, word32);
+extern char *__to_sytyp(char *, word32);
+extern char *__to_tcnam(char *, word32);
+extern char *__to_edgenam(char *, word32);
+extern char *__to_timunitnam(char *, word32);
+extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern char *__xregab_tostr(char *, word32 *, word32 *, int32, struct expr_t *);
+extern char *__strab_tostr(char *, word32 *, int32, int32, int32);
+extern char *__vval_to_vstr(word32 *, int32, int32 *);
+extern char *__to_arr_range(char *, struct net_t *);
+extern char *__to_mpnam(char *, char *);
+extern struct xstk_t *__eval2_xpr(struct expr_t *);
+extern struct xstk_t *__ndst_eval_xpr(struct expr_t *);
+extern char *__to_timstr(char *, word64 *);
+extern char *__to_vvnam(char *, word32);
+extern char *__bld_lineloc(char *, word32, int32);
+extern struct task_t *__find_thrdtsk(struct thread_t *);
+extern char *__alloc_vval_to_cstr(word32 *, int32, int32, int32);
+extern char *__to_sttyp(char *, word32);
+
+extern struct expr_t *__disp_1fmt_to_exprline(char *, struct expr_t *);
+extern struct task_t *__getcur_scope_tsk(void);
+extern void __wrap_puts(char *, FILE *);
+extern void __wrap_putc(int32, FILE *);
+extern void __nl_wrap_puts(char *, FILE *);
+extern void __chg_xprline_size(int32);
+extern void __disp_itree_path(register struct itree_t *, struct task_t *);
+extern void __declcnv_tostr(char *, word32 *, int32, int32);
+extern void __adds(char *);
+extern void __sdispb(register word32 *, register word32 *, int32, int32);
+extern int32 __trim1_0val(word32 *, int32);
+extern void __xline_vval_to_cstr(word32 *, int32, int32, int32, int32);
+extern void __my_free(char *, int32);
+extern void __regab_disp(word32 *, word32 *, int32, int32, int32, int32);
+extern void __trunc_cstr(char *, int32, int32);
+extern int32 __vval_isallzs(word32 *, word32 *, int32);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __by16_ldivmod(word32 *, word32 *, word32 *, word32, int32);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern int32 __v64_to_real(double *, word64 *);
+extern void __cnv_stk_fromreal_toreg32(struct xstk_t *);
+extern void __cnv_stk_fromreg_toreal(struct xstk_t *, int32);
+extern void __rhspsel(register word32 *, register word32 *, register int32,
+ register int32);
+extern void __disp_var(struct net_t *, int32, int32, int32, char);
+extern int32 __cnt_dcelstels(register struct dcevnt_t *);
+extern int32 __get_arrwide(struct net_t *);
+extern void __ld_arr_val(register word32 *, register word32 *, union pck_u,
+ int32, int32, int32);
+extern void __ld_wire_val(register word32 *, register word32 *, struct net_t *);
+extern void __ld_bit(register word32 *, register word32 *, register struct net_t *,
+ int32);
+extern void __ld_psel(register word32 *, register word32 *,
+ register struct net_t *, int32, int32);
+extern void __getarr_range(struct net_t *, int32 *, int32 *, int32 *);
+extern void __dmp1_nplstel(struct mod_t *, struct net_t *, struct net_pin_t *);
+extern void __dmp1_dcelstel(struct mod_t *, struct dcevnt_t *);
+extern int32 __get_dcewid(struct dcevnt_t *, struct net_t *);
+extern void __ld_perinst_val(register word32 *, register word32 *, union pck_u,
+ int32);
+extern int32 __vval_is1(register word32 *, int32);
+extern void __sizchgxs(struct xstk_t *, int32);  
+extern int32 __fr_cap_size(int32);
+extern int32 __get_netwide(struct net_t *);
+extern void __dmp_proc_assgn(FILE *, struct st_t *, struct delctrl_t *, int32);
+extern void __dmp_stmt(FILE *, struct st_t *, int32);
+
+extern void __dmp_nbproc_assgn(FILE *, struct st_t *, struct delctrl_t *);
+extern void __dmp_forhdr(FILE *, struct for_t *);
+extern void __dmp_dctrl(FILE *, struct delctrl_t *);
+extern void __dmp_tskcall(FILE *, struct st_t *);
+extern void __map_16v_to_12vform(word64 *, word64 *);
+extern void __try_reduce_16vtab(word64 *, int32 *);
+extern void __dmp_dcxpr(FILE *, union del_u, word32);
+extern int32 __isleaf(struct expr_t *);
+extern void __getwir_range(struct net_t *, int32 *, int32 *);
+extern int32 __unnormalize_ndx(struct net_t *, int32);
+extern int32 __get_giarr_wide(struct giarr_t *);
+extern char *__get_vkeynam(char *, int32);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern int32 __is_lnegative(word32 *, int32); 
+extern word32 __cp_lnegate(word32 *, register word32 *, int32); 
+
+extern void __cvsim_msg(char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __pv_err(int32, char *, ...);
+extern void __pv_warn(int32, char *,...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __gfterr(int32, word32, int32, char *, ...);
+extern void __pv_terr(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+
+extern word32 __masktab[];
+extern int32 errno;
+extern double __dbl_toticks_tab[];
+
+/* LOOKATME - on mach ten and sunos fmod is drem - but maybe not same */
+/* think ok since only used for know positive and arg1>arg2 case */
+#if defined(__SVR4) || defined(__hpux)
+#define drem fmod
+#endif
+
+/*
+ * VERILOG EXACT DISPLAY ROUTINES - NO LINE HERE
+ */
+
+/*
+ * write $fdisplay output to all files selected by multi-channel desc. 
+ * or 
+ *
+ * important to call write only once per file here
+ * for now this shares line wrap line output code so must save and restore
+ *
+ * axp must be function call comma operator even if only 1 argument
+ */
+extern void __fio_do_disp(register struct expr_t *axp, int32 dflt_fmt, int32 nd_nl,
+ char *namstsk) 
+{
+ register int32 i;
+ word32 mcd; 
+ struct xstk_t *xsp;
+ char s1[RECLEN];
+
+ xsp = __eval_xpr(axp->lu.x);
+ if (xsp->bp[0] != 0L) 
+  {
+   __sgfwarn(611, 
+    "%s file or multi-channel descriptor %s not 32 bit non x/z value - no action",
+    namstsk, __regab_tostr(s1, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+   __pop_xstk();
+   return;
+  }
+ mcd = xsp->ap[0]; 
+ __pop_xstk();
+
+ axp = axp->ru.x; 
+
+ __cur_sofs = 0;
+ disp_toexprline(axp, dflt_fmt);
+
+ /* SJM 09/09/03 - fd case easy because only one stream to write to */
+ if ((mcd & FIO_MSB) == FIO_MSB)
+  {
+   int32 fd;
+
+   fd = (int32) (mcd & ~FIO_MSB);
+   /* if fd does not correspond to open file, just set error indicator */
+   /* AIV 06/27/05 - fd cannot be greater than max file size */
+   if (fd >= MY_FOPEN_MAX || __fio_fdtab[fd] == NULL) 
+    { 
+     errno = EBADF; 
+     __cur_sofs = 0; 
+     return; 
+    }
+   fputs(__exprline, __fio_fdtab[fd]->fd_s);
+   if (nd_nl) fputc('\n', __fio_fdtab[fd]->fd_s);
+   __cur_sofs = 0;
+   return;
+  }
+
+ /* SJM 03/26/00 - mcd 1 now both stdout and std log and vendor 1 must */
+ /* go through call back so can be intercepted */
+ /* bit 0 - mcd 1 is both stdout and stdlog */
+ if ((mcd & 1) != 0)
+  {
+   __cvsim_msg("%s", __exprline);
+   if (nd_nl) __cvsim_msg("\n");
+  }
+
+ for (i = 1; i < 31; i++) 
+  {
+   if (((mcd >> i) & 1L) != 0L)
+    { 
+     if (__mulchan_tab[i].mc_s == NULL)
+      {
+       __sgfwarn(583,
+        "%s multi-channel descriptor bit %d on, but file not open",
+        namstsk, i);  
+      }
+     else
+      {
+       /* FIXME - how are these handled? */
+       fputs(__exprline, __mulchan_tab[i].mc_s);
+       if (nd_nl) fputc('\n', __mulchan_tab[i].mc_s);
+      }
+    }
+  }
+ if (((mcd >> 31) & 1) != 0)
+  {
+   __sgfwarn(583,
+    "%s multi-channel descriptor bit 31 on but file not open - unusable because reserved for new Verilog 2000 file I/O",
+     namstsk);  
+  }
+ __cur_sofs = 0;
+}
+
+/*
+ * $swrite[hdob] version of formatted write into strings
+ * this writes into __exprline - caller handles assign verilog reg
+ *
+ * notice this is write not display so no new line at end
+ */
+extern void __str_do_disp(struct expr_t *axp, int32 dflt_fmt)
+{
+ __cur_sofs = 0;
+ disp_toexprline(axp, dflt_fmt);
+}
+
+/*
+ * write $display output to file f (must be stream)  
+ *
+ * for now this shares line wrap line output code so must save and restore
+ * axp must be function call comma operator even if only 1 argument
+ */
+extern void __do_disp(register struct expr_t *axp, int32 dflt_fmt)
+{
+ __cur_sofs = 0;
+ disp_toexprline(axp, dflt_fmt);
+ __cvsim_msg("%s", __exprline);
+ __cur_sofs = 0;
+}
+
+/*
+ * routine to implement $display type displaying into a expr line string
+ * macros will grow string if needed
+ * starts at place called set __cur_sofs to
+ *
+ * notice this run time routine and any called routines should
+ * not emit messages - exception is round to time if has bits 52-64 on
+ */
+static void disp_toexprline(register struct expr_t *axp, int32 dflt_fmt)
+{
+ register char *chp;
+ int32 base, chlen;
+ char *start_fp;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+
+ for (;axp != NULL;)
+  {
+   xp = axp->lu.x;
+   /* empty parameter adds 1 space */
+   if (xp->optyp == OPEMPTY) { addch_(' '); axp = axp->ru.x; continue; }
+
+   /* literal format string (i.e 1st byte is 1st char of string not \0 */
+   /* cannot be defparam since rhs literal string removed */
+   if (xp->is_string)
+    {
+     /* since just encoding literal, know no leading 0's */
+     chp = __vval_to_vstr(&(__contab[xp->ru.xvi]), xp->szu.xclen, &chlen);
+
+     /* notice since must be literal source text string escapes removed */
+     /* also this string can contain embedded 0's that are printed */
+     /* know literal string has no bval */
+     start_fp = chp;
+
+     /* assuming 8 bit bytes */
+     axp = __disp_1fmt_to_exprline(chp, axp);
+     if (axp != NULL) xp = axp->lu.x; else xp = NULL;
+
+     /* already pointing one past last format string used */
+     __my_free(start_fp, chlen);
+     continue;
+    }
+   /* handle argument that is just printed using default format */
+   /* notice if literal string will not get here and if string var */
+   /* here printed as number - need format */
+   /* here default is base, but display real as real */
+   xsp = __eval_xpr(xp);
+   base = (xp->is_real) ? BDBLE : dflt_fmt;
+   /* always trim here */
+   __regab_disp(xsp->ap, xsp->bp, xsp->xslen, base, FALSE,
+    (xp->has_sign == 1));
+   __pop_xstk();
+   axp = axp->ru.x;
+  }
+ __exprline[__cur_sofs] = '\0';
+}
+
+/*
+ * print into string according to specifications in one format string
+ *
+ * this is called multiple times $swrite and exactly onece for $sformat
+ * chp points to value converted to string
+ */
+extern struct expr_t *__disp_1fmt_to_exprline(char *chp, struct expr_t *axp)
+{
+ int32 trim, fmt_pos, fmt_non_real, blen;
+ word32 *ap, *bp;
+ double d1;
+ char *new_chp;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+ struct task_t *tskp;
+ struct mod_t *mdp;
+ char rfmtstr[RECLEN], s1[RECLEN], s2[RECLEN];
+
+ /* point to 1st format value argument */
+ axp = axp->ru.x;
+ if (axp == NULL) xp = NULL; else xp = axp->lu.x;
+
+ fmt_pos = 0;
+ for (; *chp != '\0'; chp++)
+  {
+   /* notice is escaped by user char in format gets echoed as is */
+   if (*chp != '%') { addch_(*chp); continue; }
+   chp++;
+   fmt_pos++; 
+   /* if non format character just continue */
+   /* needed since xp may be for %[non format] form */
+   trim = FALSE;
+try_fmt_again:
+   fmt_non_real = TRUE;
+   switch (*chp) {
+    case '%':
+     /* interesting but since output always goes through printf */
+     /* this no longer goes through printf so only one needed */
+     addch_('%');
+     continue;
+    case '0':
+     chp++;
+     if (trim) goto c_style_case;
+     trim = TRUE;
+     goto try_fmt_again;
+    case 'm': case 'M':
+     /* if no thread, know in interactive and have scope */
+     if (__cur_thd == NULL) tskp = __scope_tskp; 
+     /* %m defined as "scope" which may be task/func/block/inst */
+     else tskp = __getcur_scope_tsk();
+     __disp_itree_path(__inst_ptr, tskp);
+     /* must not consume an argument */
+     continue;
+    case 'l': case 'L':
+     /* SJM 05/17/04 - FIXME ??? ### need ptr from mod to cfg lib rec def in */
+     mdp = __inst_ptr->itip->imsym->el.emdp;
+     if (mdp->mod_cfglbp != NULL)
+      {
+       sprintf(s1, "%s.%s", mdp->mod_cfglbp->lbname, mdp->msym->synam); 
+      }
+     else
+      {
+       sprintf(s1, "[NO-CONFIG].%s", mdp->msym->synam); 
+      } 
+     __adds(s1);
+     continue;
+
+    case 'h': case 'H': case 'x': case 'X': case 'd': case 'D':
+    case 'o': case 'O': case 'b': case 'B': case 'c': case 'C':
+    case 's': case 'S': case 'v': case 'V':
+    /* SJM 05/17/04 - binary formats added for P1364 2001 */
+    case 'u': case 'U': case 'z': case 'Z':
+     break;
+
+    case 't': case 'T':
+     fmt_non_real = FALSE;
+     break;
+    case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+     fmt_non_real = FALSE;
+     /* F not in C standard and indentical to 'f' */
+     if (*chp == 'F') *chp = 'f';
+     /* trim ignored here and any c style %10.3g (z.b.) example */    
+     strcpy(rfmtstr, "");
+     break;
+    /* for %f/%g only need to parse C style format */
+    /* notice for 0. enter normally, for c legal 00 get here from '0' */
+    case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9': case '.': case '-':
+    case '+': case '#': case ' ':
+c_style_case:
+     /* one of these after percent probably real format */
+     /* if new_chp not 0 points to end format char on return */
+     if ((new_chp = sep_real_fmt(rfmtstr, chp, trim)) == NULL)
+      {
+       addch_('%');
+       if (trim) { addch_('0'); chp--; } else addch_(*chp);
+       continue;
+      }
+     /* got real format */
+     chp = new_chp;
+     fmt_non_real = FALSE;
+     break;
+    default:
+     /* copy %[non format char] case */
+     addch_('%'); 
+     addch_(*chp);
+     /* notice for loop has chp++ inc */
+     continue;
+   }
+
+  /* format needs expr. - check it */
+  /* if nil, treat as ,, */
+  if (xp == NULL)
+   {
+    addch_(' ');
+    continue;
+   }
+
+  if (xp->optyp == OPEMPTY) { addch_(' '); goto nxt_arg; }
+  /* ok for literal string to be printed as value */ 
+  /* need special evaluation for with strength formats */ 
+  if (*chp == 'v' || *chp == 'V') { sdisp_st(xp); goto nxt_arg; }
+
+  /* eval. here uses type of expression to get real or non real val */
+  xsp = __eval_xpr(xp);
+  if (xp->is_real && fmt_non_real) __cnv_stk_fromreal_toreg32(xsp);
+  ap = xsp->ap;
+  bp = xsp->bp;
+  switch (*chp) {
+   case 'h': case 'H': case 'x': case'X':
+    /* for variable accesses correct one */
+    sdisph(ap, bp, xsp->xslen, trim);
+    break;
+   case 'd': case 'D':
+do_dec:
+    sdispd(ap, bp, xp->szu.xclen, trim, (xp->has_sign == 1));
+    break;
+   case 't': case 'T':
+    {
+     char tfmtstr[IDLEN];
+          
+     if (!bld_tfmt_val(tfmtstr, xp, ap, bp, xsp->xslen, trim, fmt_pos))
+      goto do_dec;
+     __adds(tfmtstr);
+    }
+    break;
+   case 'o': case 'O':
+    sdispo(ap, bp, xsp->xslen, trim);
+    break;
+   case 'b': case 'B':
+    __sdispb(ap, bp, xsp->xslen, trim);
+    break;
+   case 's': case 'S':
+    /* %s ignores b part and if non literal str leading 0's trimmed */
+    /* do not need %0s to cause leading (high) 0's to not print */
+    blen = __trim1_0val(ap, xsp->xslen);
+    __xline_vval_to_cstr(ap, blen, FALSE, FALSE, FALSE);
+    break;
+   case 'c': case 'C':
+    /* OVIsim only prints if printable */
+    /* SJM 09/19/03 - must also print new line and tab - isprint does */
+    /* not include new line and tab etc. */
+    if (isprint(ap[0] & 0xff) || (ap[0] & 0xff) == '\n'
+     || (ap[0] & 0xff) == '\r' || (ap[0] & 0xff) == '\t')
+     addch_((char) (ap[0] & 0xff));
+    else addch_(' ');
+    break;
+   case 'u': case 'U':
+    disp_ufmt_binval(ap, bp, xsp->xslen);
+    break;
+   case 'z': case 'Z':
+    disp_zfmt_binval(ap, bp, xsp->xslen);
+    break;
+
+   /* this can only be bit select or scalar */
+   /* notice this reevaluates expression since needs to access st too */
+   case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+    /* tricky case of real that needs c printf - fmt str in rfmtstr */
+    if (!xp->is_real) 
+     {
+      /* this may produce warning if does not fit */
+      __cnv_stk_fromreg_toreal(xsp, (xp->has_sign == 1));
+      ap = xsp->ap;
+      bp = xsp->bp;
+     }
+    /* first build the format string */
+    if (*chp == 'F') *chp = 'f'; 
+    sprintf(s1, "%%%s%c", rfmtstr, *chp);
+    memcpy(&d1, ap, sizeof(double));
+
+    /* know max size of real cannot be more than 30 or so */
+    sprintf(s2, s1, d1);
+    __adds(s2);
+    /* LOOKATME - fall thru under what conditions? */
+   }
+   __pop_xstk();
+nxt_arg:
+   /* know 1 format arguemnt used up, so must move to next */
+   axp = axp->ru.x;
+   if (axp == NULL) xp = NULL; else xp = axp->lu.x;
+  }
+ return(axp);
+}
+
+/*
+ * get the task from the current execing scope 
+ * return NULL if none
+ */
+extern struct task_t *__getcur_scope_tsk(void)
+{
+ struct task_t *tskp;
+
+ if (__fcspi >= 0) tskp = __fcstk[__fcspi];
+ else if (__cur_thd->th_fj) tskp = __find_thrdtsk(__cur_thd);
+ else tskp = __cur_thd->assoc_tsk;
+ return(tskp);
+}
+
+/*
+ * routine to check a display format system task (called from v_fx) 
+ *
+ * this is version of display routine above with all output and evaluation
+ * turned off 
+ */
+extern void __chk_fmt(register struct expr_t *axp, byte *argnonvtab) 
+{
+ register char *chp;
+ int32 trim, fmt_pos, fmt_non_real, chlen, argi;
+ char *new_chp, *start_fp;
+ struct expr_t *xp;
+ char rfmtstr[RECLEN], s1[RECLEN];
+
+ for (fmt_pos = 0, argi = 0; axp != NULL;)
+  {
+   xp = axp->lu.x;
+   /* empty parameter, skip */
+   if (xp->optyp == OPEMPTY) { axp = axp->ru.x; argi++; continue; }
+
+   /* literal format string (i.e 1st byte is 1st char of string no \0 */
+   /* cannot be defparam */
+   if (xp->is_string)
+    {
+     /* since just en-ecoding literal, know no leading 0's */
+     chp = __vval_to_vstr(&(__contab[xp->ru.xvi]), xp->szu.xclen, &chlen);
+     start_fp = chp;
+     /* know literal string has no bval */
+     /* point to 1st format value argument */
+     axp = axp->ru.x;
+     if (axp == NULL) xp = NULL; else { xp = axp->lu.x; argi++; }
+
+     /* notice since must be liternal source text string escapes removed */
+     /* also this string can contain embedded 0's that are printed */
+     for (; *chp != '\0'; chp++)
+      {
+       if (*chp != '%')
+        {
+         if (isprint(*chp) || *chp == '\n' || *chp == '\r' || *chp == '\t'
+          || *chp == '\f') continue;
+         __sgfwarn(561,
+          "format contains non printable character \\%o (%d) (next pos. %d)",
+          *chp, *chp, fmt_pos + 1);
+        }
+       chp++;
+       fmt_pos++; 
+       /* if non format character just continue */
+       /* needed since xp can be %[non format] form */
+       trim = FALSE;
+try_fmt_again:
+       fmt_non_real = TRUE;
+       switch (*chp) {
+        case '%': continue;
+        case '0':
+         chp++;
+         if (trim) goto c_style_case;
+         trim = TRUE;
+         goto try_fmt_again;
+        case 'm': case 'M': continue;
+        case 'l': case 'L': continue;
+
+        case 'v': case 'V':
+         if (argnonvtab != NULL) argnonvtab[argi] = 1;
+         break;
+        case 'h': case 'H': case 'x': case 'X': case 'd': case 'D':
+        case 'o': case 'O': case 'b': case 'B': case 'c': case 'C':
+        case 's': case 'S': case 'u': case 'U': case 'z': case 'Z':
+         break;
+        case 't': case 'T':
+         fmt_non_real = FALSE;
+         break;
+        case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+         fmt_non_real = FALSE;
+         /* F not in C standard and indentical to 'f' */
+         if (*chp == 'F') *chp = 'f';
+         /* trim ignored here and any c style %10.3g (z.b.) example */    
+         break;
+        /* for %f/%g only need to parse C style format */
+        /* notice for 0. enter normally, for c legal 00 get here from '0' */
+        case '1': case '2': case '3': case '4': case '5':
+        case '6': case '7': case '8': case '9': case '.': case '-':
+        case '+': case '#': case ' ':
+c_style_case:
+         /* one of these after percent probably real format */
+         /* if new_chp not 0 points to end format char on return */
+         if ((new_chp = sep_real_fmt(rfmtstr, chp, trim)) == NULL)
+          { if (trim) chp--; continue; }
+         /* got real format */
+         chp = new_chp;
+         fmt_non_real = FALSE;
+         break;
+        default: continue;
+         /* notice for loop has chp++ inc */
+       }
+
+       /* format needs expr. - check it */
+       if (xp == NULL)
+        {
+         __sgferr(719, "argument list exhausted for %%%c format (pos. %d).",
+          *chp, fmt_pos);
+         continue;
+        }
+       if (xp->optyp == OPEMPTY)
+        {
+         __sgfwarn(549,
+          "argument list ,, value - format %%%c (pos. %d) - value is space",
+          *chp, fmt_pos);
+         goto nxt_arg;
+        }
+       if (xp->is_string && *chp != 's' && *chp != 'S')
+        {
+         __sgfwarn(554,
+          "string constant probably incompatible with %%%c format (pos. %d)",
+          *chp, fmt_pos);
+         goto nxt_arg;
+        }
+       /* strengths can be any 1 bit in OVIsim but anything in Cver */
+
+       /* eval. here uses type of expression to get real or non real val */
+       if (xp->is_real && fmt_non_real)
+        {
+         __sgfwarn(552,
+          "%c format but value expression (pos. %d) type real - converted to 32 bit reg",
+          *chp, fmt_pos);
+        }
+       /* only look at things that need checking */
+       switch (*chp) {
+        case 't': case 'T':
+         if (xp->szu.xclen > TIMEBITS)
+          {
+           if (fmt_pos == -1) strcpy(s1, "");
+           else sprintf(s1, " (pos. %d)", fmt_pos);
+           __sgfwarn(520,
+            "%%t or $timeformat%s expression wider than %d bits - high ignored",
+            s1, TIMEBITS);
+          }
+         break;
+
+        /* this can only be bit select or scalar */
+        /* notice this reevaluates expression since needs to access st too */
+        case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+        /* tricky case of real that needs c printf - fmt str in rfmtstr */
+        if (!xp->is_real)
+         {
+          __sgfinform(480,
+            "non real value output with %c format (pos. %d) - conversion needed",
+           *chp, fmt_pos);
+         }
+        }
+nxt_arg:
+       /* know 1 format arguemnt used up, so must move to next */
+       axp = axp->ru.x;
+       if (axp == NULL) xp = NULL; else { argi++; xp = axp->lu.x; }
+      }
+     /* already pointing one past last format string used */
+     __my_free(start_fp, chlen);
+     continue;
+    }
+   axp = axp->ru.x;
+   argi++;
+  }
+}
+
+/*
+ * search currently executing task and up to top of nested created
+ * subthreads for a thread that is a task
+ *
+ * must search up since fork-join threads do not have tasks but
+ * thread that fork-join is subthread of may
+ * this is needed by %m
+ */
+extern struct task_t *__find_thrdtsk(struct thread_t *cur_thp)
+{
+ struct thread_t *thdp;
+
+ for (thdp = cur_thp; thdp != NULL; thdp = thdp->thpar)
+  {
+   if (thdp->assoc_tsk != NULL) return(thdp->assoc_tsk);
+  } 
+ return(NULL);
+}
+
+/*
+ * version os message build itree when know there is no task
+ */
+extern char *__msg2_blditree(char *s, struct itree_t *itp)
+{
+ return(__msg_blditree(s, itp, (struct task_t *) NULL));
+}
+
+/*
+ * version of instance name that builds work string
+ * does start at cur spos over-write anything ? 
+ */
+extern char *__msg_blditree(char *s, struct itree_t *itp, struct task_t *tskp)
+{
+ int32 sav_sofs = __cur_sofs;
+
+ __disp_itree_path(itp, tskp);
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, FALSE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0'; 
+ return(s);
+}
+
+/*
+ * add itree path to __exprline - gets path from value of cur. itp
+ * use glbsycmp work array as work stack
+ * this just writes scope part - if need object name caller must write
+ * allow any length path here
+ */
+extern void __disp_itree_path(register struct itree_t *itp, struct task_t *tskp)
+{
+ register int32 gi;
+ struct symtab_t *sytp;
+ char *chp;
+
+ /* if in task (probably nested block), build from bottom */
+ if (tskp != NULL)
+  {
+   for (sytp = tskp->tsksymtab, gi = 0;;)
+    {
+     /* notice do not need glb x cmps here since symbol is right inst */
+     __glbsycmps[gi] = sytp->sypofsyt;
+     sytp = sytp->sytpar;
+     if (sytp == NULL || sytp->sypofsyt->sytyp == SYM_M) break;
+     if (++gi >= MAXGLBCOMPS)
+      __pv_terr(310,
+       "cannot print instance path name with too many components (%d)",
+       MAXGLBCOMPS);
+    }
+   gi++;
+  }
+ else gi = 0;
+
+ /* fill from front to end - know at least one component */
+ for (;;)
+  {
+   __glbsycmps[gi] = itp->itip->isym;
+   /* virtual tops modules have no up entry */
+   itp = itp->up_it;
+   if (itp == NULL) break;
+   if (++gi >= MAXGLBCOMPS)
+    __pv_terr(310,
+     "cannot print instance path name with too many components (%d)",
+     MAXGLBCOMPS);
+  }
+ /* then fill top end to front - know string nil terminated by last __adds */
+ for (; gi >= 0; gi--)
+  { chp = __glbsycmps[gi]->synam; __adds(chp); if (gi > 0) addch_('.'); }
+}
+
+/*
+ * check for legal c printf style real format string
+ * this is format preprocessing routine
+ * think ascii standard says '-' can go anywhere
+ */
+static char *sep_real_fmt(char *fmtstr, char *chp, int32 trim)
+{
+ int32 i;
+ char *fchp;
+
+ /* first see if can find real format end char within reasonable distance */
+ /* this eliminates literal % followed by real fonmat pun case */
+ for (fchp = chp, i = 1; ; fchp++, i++)
+  {
+   switch (*fchp) {
+    case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+     /* -0dd.ddf is max but allowing 2 extra 0s */
+     if (i > 10) return(NULL);
+     goto got_fmt;
+    case '\0': return(NULL);
+   }
+  }
+ /* know format end fence in string to get here */
+got_fmt:
+ fchp = fmtstr;
+ for (;;)
+  {
+   switch (*chp) {
+    case '-': case '+': case ' ': case '#': break;
+    /* 0 from trim followed by prefix 0 illegal */
+    case '0': if (trim) return(NULL); break;
+    default: goto col_digs;
+   }
+   *fchp++ = *chp++;
+  }
+
+col_digs:
+ /* collect possible digit string */
+ for (;;) { if (!isdigit(*chp)) break; *fchp++ = *chp++; }
+ if (*chp == '.')
+  {
+   *fchp++ = *chp++;
+   for (;;) { if (!isdigit(*chp)) break; *fchp++ = *chp++; }
+  }
+ switch (*chp) {
+  case 'e': case 'E': case 'g': case 'G': case 'f': case 'F': break;
+  default: return(NULL);
+ }
+ *fchp = '\0';
+ /* must return pointer to format char */
+ return(chp);
+}
+
+/*
+ * convert a Verilog value to a printable hex string
+ * if trim false must pad with leading spaces
+ */
+static void sdisph(word32 *ap, word32 *bp, int32 blen, int32 trim)
+{
+ register int32 bi, wi;
+ int32 swlen, bi2, trimmed_blen, highused;
+ word32 tmpa, tmpb;
+ char ch;
+
+ /* short circuit common 1 bit case */
+ if (blen == 1)
+  {
+   tmpa = ap[0] | (bp[0] << 1);
+   if (tmpa < 2) ch = '0' + ((char) tmpa);
+   else if (tmpa == 2) ch = 'z';
+   else ch = 'x';
+   addch_(ch);
+   goto done;
+  }
+ if (trim)
+  {
+   trimmed_blen = trim_abval(ap, bp, blen);
+   if (trimmed_blen == 0) { addch_('0'); goto done; }
+   if (vval_isall_xs(ap, bp, blen)) { addch_('x'); goto done; }
+   if (__vval_isallzs(ap, bp, blen)) { addch_('z'); goto done; }
+  }
+ else trimmed_blen = blen;
+
+ /* think high bits non zero (but same as new high bit will select right) */
+ /* may need to adjust so have 1 entire hex digit */
+ swlen = wlen_(trimmed_blen);
+ bi2 = trimmed_blen & 0x1fL;
+ if (bi2 == 0) bi = WBITS;
+ else bi = WRDBYTES*((bi2 + WRDBYTES - 1)/WRDBYTES);
+ bi -= 4;
+ if ((highused = (bi2 % 4)) == 0) highused = 4;
+ for (wi = swlen - 1; wi >= 0; wi--)
+  {
+   tmpa = ap[wi]; tmpb = bp[wi];
+   for (;bi > 0; bi -= 4)
+    {
+     tmpa = (ap[wi] >> bi) & 0xfL;
+     tmpb = (bp[wi] >> bi) & 0xfL;
+     addch_(bitsto_char(tmpa, tmpb, highused));
+     highused = 4;
+    }
+   /* notice bi will always == 0 here */
+   addch_(bitsto_char((ap[wi] & 0xfL), (bp[wi] & 0xfL), highused));
+   bi = WBITS - 4;
+  }
+ /* need explicit terminator */
+done:
+ __exprline[__cur_sofs] = '\0';
+}
+
+/*
+ * convert hex/oct/bin bit pattern to ascii character
+ * all bits z = lower case else upper case (same for x)
+ */
+static char bitsto_char(word32 a, word32 b, int32 bwid)
+{
+ char ch;
+ word32 mask;
+
+ if (!b) { ch = (char) valtoch_(a); return(ch); }
+ mask = __masktab[bwid];
+ if ((b & mask) == mask)
+  {
+   /* know all control bits on */
+   if (a == 0L) return('z');
+   else if ((a & mask) == mask) return('x');
+   else return('X');
+  }
+ /* some control bits on - if no x's Z else X */
+ if ((a & b) == 0L) return('Z');
+ return('X');
+}
+
+/*
+ * convert a Verilog value to a printable decimal string using c printf
+ * starts fill __exprline at sofs and update sofs
+ * dsigned false for signed value - like %u in c
+ * if caller added [size]'d will never be signed
+ */
+static void sdispd(word32 *ap, word32 *bp, int32 blen, int32 trim, int32 dsigned)
+{
+ register int32 i;
+ int32 ochnum, trimblen, widnumlen;
+ sword32 sval;
+ struct xstk_t *xsp;
+ char ch, *chp, *chp2, s1[RECLEN];
+
+ if (!trim) 
+  {
+   /* need ceil here */
+   ochnum = (int32) (blen*LG2_DIV_LG10 + 0.999999);
+   if (dsigned) ochnum++;
+  }
+ else ochnum = 0;
+
+ /* handle various x/z forms */
+ if ((ch = get_decxz(ap, bp, blen)) != ' ')
+  {
+   /* ? PORTABILITY sprintf(s1, "%*c", ochnum, ch); */
+   for (i = 0; i < ochnum - 1; i++) addch_(' ');
+   addch_(ch);
+   __exprline[__cur_sofs] = '\0';
+   return;
+  }
+ if (blen <= WBITS)
+  {
+   /* for decimal leading untrimmed must be spaces */
+   if (dsigned)
+    {
+     if (blen == WBITS) sprintf(s1, "%ld", (sword32) ap[0]);
+     else
+      {
+       if ((ap[0] & (1 << (blen - 1))) != 0)
+        {
+         /* SJM 10/20/03 - 1 bit width vars can't be signed so works */ 
+         if (blen == 1)
+          {
+           /* AIV 09/15/04 - LOOKATME - should this be -1? */
+           strcpy(s1, "0");
+          }
+         else
+          {
+           sval = ~((int32) ap[0]);
+           sval++;
+           sval &= __masktab[blen - 1];
+           /* AIV 09/15/04 - was wrongly printing - 0 for most negative */
+           if (sval == 0) sprintf(s1, "-%ld", ap[0]);
+           else sprintf(s1, "-%ld", sval);
+          }
+        }
+       else sprintf(s1, "%lu", ap[0]);
+      }
+    }
+   else sprintf(s1, "%lu", ap[0]);
+   for (i = 0; i < ochnum - (int32) strlen(s1); i++) addch_(' ');
+   __adds(s1);
+   return;
+  }
+ /* SJM 05/27/04 - for negative can't trim until negated */
+ if (dsigned && __is_lnegative(ap, blen))
+  {
+   /* compute number of chars required by converted number */
+   /* need ceil here */
+   /* SJM 10/20/03 - since wide can now be signed must use 2's complement */
+   /* this works because know x/z case removed above */
+
+   /* number is negative - compute bit wise not then add 1 */
+   push_xstk_(xsp, blen);
+   __cp_lnegate(xsp->ap, ap, blen);
+
+   trimblen = __trim1_0val(xsp->ap, blen);
+   widnumlen = trimblen*LG2_DIV_LG10 + 0.999999;
+   chp = (char *) __my_malloc(widnumlen + 2);
+   __declcnv_tostr(chp, xsp->ap, trimblen, widnumlen);
+   widnumlen++;
+   for (i = 0; i < ochnum - widnumlen; i++) addch_(' ');
+   addch_('-');
+
+   /* SJM 05/28/04 - widnumlen estimate can be 1 too large must trim front */
+   /* can't just inc chp since must free beginning of area */
+   chp2 = chp;
+   while (*chp2 == ' ') chp2++;
+   __adds(chp2);
+
+   __my_free(chp, widnumlen + 2);
+   __pop_xstk(); 
+   return;
+  }
+ /* case 2: either not signed or positive */
+ trimblen = __trim1_0val(ap, blen);
+ /* handle wide 0 as special case - these need trim on to happen */
+ if (trimblen == 0)
+  {
+   for (i = 0; i < ochnum - 1; i++) addch_(' ');
+   addch_('0');
+   __exprline[__cur_sofs] = '\0';
+   return;
+  }
+ /* next wide that trims to 1 word32 */
+ if (trimblen <= WBITS)
+  {
+   sprintf(s1, "%lu", ap[0]);
+   for (i = 0; i < ochnum - (int32) strlen(s1); i++) addch_(' ');
+   __adds(s1);
+   return;
+  }
+ widnumlen = trimblen*LG2_DIV_LG10 + 0.999999;
+ chp = (char *) __my_malloc(widnumlen + 2);
+ __declcnv_tostr(chp, ap, trimblen, widnumlen);
+ for (i = 0; i < ochnum - widnumlen; i++) addch_(' ');
+ __adds(chp);
+ __my_free(chp, widnumlen + 2);
+}
+
+/*
+ * convert an array of words (word32 contiguous Verilog multiword value)
+ * into a string s known to be wide enough
+ * know blen > WBITS for will not be called
+ * this does not use exprline or a part
+ */
+extern void __declcnv_tostr(char *s, word32 *wp, int32 trimblen, int32 widnumlen)
+{
+ register int32 chi;
+ word32 *quot, *u, r0;
+ int32 wlen;
+ struct xstk_t *xsp;
+
+ wlen = wlen_(trimblen);
+ push_xstk_(xsp, wlen*WBITS/2);
+ quot = xsp->ap;
+ memset(quot, 0, wlen*WRDBYTES);
+ push_xstk_(xsp, wlen*WBITS/2);
+ u = xsp->ap;
+ cp_walign_(u, wp, trimblen);
+ s[widnumlen] = '\0'; 
+ /* repeatedly divide by 10 filling from end to front */
+ for (chi = widnumlen - 1;;)
+  {
+   __by16_ldivmod(quot, &r0, u, (word32) 10, trimblen);
+   s[chi--] = (char) (r0 + '0'); 
+   if (vval_is0_(quot, trimblen)) break;
+   if (chi < 0) __case_terr(__FILE__, __LINE__);
+   /* know value shorter so retrim */
+   trimblen = __trim1_0val(quot, trimblen);
+   cp_walign_(u, quot, trimblen);
+   memset(quot, 0, wlen_(trimblen)*WRDBYTES); 
+  }
+ for (; chi >= 0; chi--) s[chi] = ' ';
+ __pop_xstk();
+ __pop_xstk();
+}
+
+/*
+ * convert a 64 bit time to a decimal string
+ * t must be ticks scaled to value for module if needed
+ */
+extern char *__to_timstr(char *s, word64 *t)
+{
+ /* UNUSED - int32 trimblen, widnumlen; */
+ word64 t1;
+
+ /* hard absolute unit case */
+ if (__nd_timstr_suf && __timstr_mult != 1) t1 = (*t)*__timstr_mult;
+ else t1 = *t;
+ /* LOOKATME - is this portable? */
+ /* LOOKATME - what is sparc and hp format letters for these? */ 
+ sprintf(s, "%llu", t1); 
+
+ /* LOOKATME - can this be eliminated ---
+ if ((t1 >> 32) == 0ULL) sprintf(s, "%lu", (word32) (t1 & WORDMASK_ULL));
+ else
+  {
+   word32 t1a[2];
+
+   -* low at 0th address and high at next *-
+   t1a[0] = (word32) (t1 & WORDMASK_ULL);
+   t1a[1] = (word32) ((t1 >> 32) & WORDMASK_ULL);
+   -* notice this case makes use of c require that fields are in order *-
+   trimblen = __trim1_0val(t1a, TIMEBITS);
+   -* need ceil here *-
+   widnumlen = (int32) (trimblen*LG2_DIV_LG10 + 0.999999);
+   __declcnv_tostr(s, t1a, trimblen, widnumlen);
+  }
+ --- */
+ if (__nd_timstr_suf) strcat(s, __timstr_unitsuf);
+ return(s);
+}
+
+/*
+ * return decimal x/z/X/Z char ' ' for non x/z
+ * could write routine that does not call routines but eliminates
+ */
+static char get_decxz(word32 *ap, word32 *bp, int32 blen)
+{
+ if (vval_is0_(bp, blen)) return(' ');
+ if (vval_isall_xs(ap, bp, blen)) return('x');
+ if (__vval_isallzs(ap, bp, blen)) return('z');
+ /* finally find if any z's and any x's */
+ if (vval_hasx(ap, bp, blen)) return('X');
+ return('Z');
+}
+
+/*
+ * build the time format (real) from $timeformat string
+ * passed expr. is in scaled (mult. by min. units power of 10)
+ * computation here use double so only 53 (52 ieee) bits of accuracy
+ * (ieee) may cause loss of values
+ *
+ * notice value passed here is scaled to units of current module 
+ * i.e. must come from $time (or $stime or $realtime (already double))
+ *
+ * could do some case in exact 64 bit unsigned?
+ * this string never wider than RECLEN and does not use expr line
+ */
+static int32 bld_tfmt_val(char *s, struct expr_t *xp, word32 *ap, word32 *bp,
+ int32 blen, int32 trim, int32 fmt_pos)
+{
+ int32 unit;
+ word64 usertim;
+ double d1;
+ struct mod_t *mdp;
+ char s1[RECLEN];
+
+ if (fmt_pos == -1) strcpy(s1, ""); else sprintf(s1, " (pos. %d)", fmt_pos);
+ /* fill time from expr. - value is already scaled - may unscale */
+ if (xp->is_real) memcpy(&d1, ap, sizeof(double)); 
+ else 
+  { 
+   if (blen <= WBITS)
+    { if (bp[0] != 0L) return(FALSE); d1 = (double) ap[0]; }
+   else
+    {
+     /* this causes decimal style x with no suffix string to be emitted */
+     if (bp[1] != 0L || bp[0] != 0L) return(FALSE);
+     /* SJM 02/03/00 - works because ap[0] word32 */
+     usertim = ((word64) ap[0]) | (((word64) ap[1]) << 32);
+     if (!__v64_to_real(&d1, &usertim))
+      __sgfwarn(572,
+       "%%t or $timeformat%s conversion to real lost precision",
+      s1); 
+    }
+  }  
+ /* know d1 is this module's time unit time */
+ /* if time format units same as modules d1 has ticks */
+ mdp = __inst_mod;
+ if (mdp->mtime_units != __tfmt_units)
+  {
+   if (mdp->mtime_units > __tfmt_units)
+    {
+     /* here d1 module ticks higher exponent (more precision) - divide */  
+     unit = mdp->mtime_units - __tfmt_units;
+     d1 /= __dbl_toticks_tab[unit];
+    }   
+   else
+    {
+     /* here d1 module ticks lower (less precision) - multiply */
+     unit = __tfmt_units - mdp->mtime_units;
+     d1 *= __dbl_toticks_tab[unit];
+    }
+  }
+ /* unscaled time (can have frac. part) in d1 */
+ /* uses the sprintf rounding */ 
+ /* this can never fail */
+ if (!trim)
+  {
+   sprintf(s, "%*.*f%s", (int32) (__tfmt_minfwid - strlen(__tfmt_suf)),
+    (int32) __tfmt_precunits, d1, __tfmt_suf);
+  }
+ else sprintf(s, "%.*f%s", (int32) __tfmt_precunits, d1, __tfmt_suf);
+ return(TRUE);
+}
+
+/*
+ * for tf_ strgetp routines, build value of expr. in number
+ *
+ * return string (nil on error)
+ * this is in convert because calls display formatting routines 
+ * added %v and %g/%f that are not part of standard
+ * conversions to/from real are 32 bit following LRM $display
+ *
+ * tf_ routines malloc memory that user frees when done
+ * know correct itree loc. set here
+ */
+extern char *__alloc_getasfmt(struct expr_t *xp, struct tfrec_t *tfrp,
+ int32 fmtchar)
+{
+ int32 sav_sofs, slen, vsigned, valreal;
+ word32 *wp;
+ double d1;
+ struct xstk_t *xsp;
+ char *chp, s1[RECLEN];
+
+ sav_sofs = __cur_sofs;
+ /* handle argument 0 only for function as special case */
+ if (tfrp != NULL)
+  {
+   if (fmtchar == 'v' || fmtchar == 'V') return(NULL);
+   push_xstk_(xsp, tfrp->fretsiz);
+   wp = (word32 *) tfrp->tfargs[0].arg.awp;
+   /* SJM 12/12/01 - this was wrong was copying over stk ptr */
+   memcpy(xsp->ap, wp, 2*wlen_(tfrp->fretsiz)*WRDBYTES);
+
+   if (tfrp->fretreal) valreal = TRUE; else valreal = FALSE;
+   vsigned = FALSE;
+   goto xl_disp;
+  }
+
+ /* return 32 bit int32 as pointer to string */
+ /* if really literal string format letter ignored */ 
+ if (xp->optyp == NUMBER && xp->is_string)
+  {
+   /* notice even though in cnv uses tf malloc routine */ 
+   chp = __alloc_vval_to_cstr(&(__contab[xp->ru.xvi]), xp->szu.xclen,
+    FALSE, FALSE);
+   /* notice no xstk push to get here */
+   return(chp);
+  }
+
+ /* now fill exprline (on end saving prefix) */
+ /* for strength allow vector but here display routine evals expr */
+ /* if xp is real this will use bit pattern not converted value */ 
+ if (fmtchar == 'v' || fmtchar == 'V') { sdisp_st(xp); goto xl_done; }
+
+ xsp = __eval_xpr(xp);
+ if (xp->is_real) valreal = TRUE; else valreal = FALSE;
+ if (xp->has_sign) vsigned = TRUE; else vsigned = FALSE;
+
+xl_disp:
+ d1 = 0.0;
+ /* do any to/from real conversion if needed */
+ switch ((byte) fmtchar) {
+  case 'g': case 'G': case 'f': case 'F':
+   if (!valreal) __cnv_stk_fromreg_toreal(xsp, vsigned);
+   memcpy(&d1, xsp->ap, sizeof(double));
+   break;
+  default:
+   if (valreal) __cnv_stk_fromreal_toreg32(xsp);
+ }
+
+ /* SJM 08/03/04 - this code was wrongly trimmming leading 0s */
+ /* LRM  requires keeping leading 0s */
+ switch ((byte) fmtchar) {
+  case 'h': case 'H': case 'x': case'X':
+   sdisph(xsp->ap, xsp->bp, xsp->xslen, FALSE);
+   break;
+  case 'd': case 'D':
+   sdispd(xsp->ap, xsp->bp, xsp->xslen, FALSE, vsigned);
+   break;
+  case 'o': case 'O':
+   sdispo(xsp->ap, xsp->bp, xsp->xslen, FALSE);
+   break;
+  case 'b': case 'B':
+   __sdispb(xsp->ap, xsp->bp, xsp->xslen, FALSE);
+   break;
+  case 'g': case 'G': case 'f': case 'F':
+   sprintf(s1, "%g", d1);
+   break;
+  default: __pop_xstk(); return(NULL);
+ }
+ __pop_xstk();
+
+xl_done:
+ slen = __cur_sofs - sav_sofs;
+ chp = __mytf_malloc(slen + 1);
+ strcpy(chp, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = 0;
+ return(chp); 
+}
+
+/*
+ * convert a Verilog value to a printable oct string
+ */
+static void sdispo(word32 *ap, word32 *bp, int32 blen, int32 trim)
+{
+ register int32 bi;
+ word32 psaval, psbval;
+ int32 digs, trimmed_blen, highused, tmp;
+ char ch;
+
+ /* short circuit common 1 bit case */
+ if (blen == 1)
+  {
+   tmp = (int32) (ap[0] | (bp[0] << 1)); 
+   if (tmp < 2) ch = '0' + ((char) tmp);
+   else if (tmp == 2) ch = 'z';
+   else ch = 'x';
+   addch_(ch);
+   goto done;
+  }
+ if (trim)
+  {
+   trimmed_blen = trim_abval(ap, bp, blen);
+   if (trimmed_blen == 0) { addch_('0'); goto done; }
+   if (vval_isall_xs(ap, bp, blen)) { addch_('x'); goto done; }
+   if (__vval_isallzs(ap, bp, blen)) { addch_('z'); goto done; }
+  }
+ else trimmed_blen = blen;
+
+ /* notice -1 correction start at right part of 3 bit field */
+ digs = ((trimmed_blen + 2)/3) - 1;
+
+ /* notice selects required here because bits overlap word32 boundaries */
+ if ((highused = (trimmed_blen % 3)) == 0) highused = 3;
+ for (bi = 3*digs; bi >= 0; bi -= 3)
+  {
+   /* need part select here since word32 overlap */
+   __rhspsel(&psaval, ap, bi, highused);
+   __rhspsel(&psbval, bp, bi, highused);
+   addch_(bitsto_char(psaval, psbval, highused));
+   highused = 3;
+  }
+done:
+ __exprline[__cur_sofs] = '\0';
+}
+
+/*
+ * convert a Verilog value to a printable binary string
+ * if any prefix that must be preserved - sofs points to 1st usable pos.
+ * notice this must be efficient since used for value change dump
+ */
+extern void __sdispb(register word32 *ap, register word32 *bp, int32 blen, int32 trim)
+{
+ register int32 wi, bi;
+ register word32 tmpa, tmpb;
+ int32 swlen, trimmed_blen;
+ char ch;
+
+ /* short circuit common 1 bit case */
+ if (blen == 1)
+  {
+   tmpa = ap[0] | (bp[0] << 1);
+   if (tmpa < 2) ch = '0' + ((char) tmpa);
+   else if (tmpa == 2) ch = 'z';
+   else ch = 'x';
+   addch_(ch);
+   __exprline[__cur_sofs] = '\0';  
+   return;
+  }
+
+ if (trim)
+  {
+   trimmed_blen = bin_trim_abval(ap, bp, blen);
+   if (trimmed_blen == 0) { addch_('0'); goto done; }
+   if (vval_isall_xs(ap, bp, blen)) { addch_('x'); goto done; }
+   else if (__vval_isallzs(ap, bp, blen)) { addch_('z'); goto done; }
+  }
+ else trimmed_blen = blen;
+
+ swlen = wlen_(trimmed_blen);
+ bi = trimmed_blen & 0x1f;
+ if (bi == 0) bi = WBITS - 1; else bi--;
+ for (wi = swlen - 1; wi >= 0; wi--)
+  {
+   tmpa = ap[wi]; tmpb = bp[wi];
+   for (;bi > 0; bi--)
+    {
+     tmpa = (ap[wi] >> bi) & 1L;
+     tmpb = (bp[wi] >> bi) & 1L;
+     if (tmpb != 0L) { if (tmpa != 0L) ch = 'x'; else ch = 'z'; }
+     else ch = '0' + ((char) tmpa);
+     addch_(ch);
+    }
+   /* notice bi always exactly 0 here */
+   tmpa = ap[wi] & 1L;
+   tmpb = bp[wi] & 1L;
+   if (tmpb != 0L) { if (tmpa != 0L) ch = 'x'; else ch = 'z'; }
+   else ch = '0' + ((char) tmpa);
+   addch_(ch);
+   bi = WBITS - 1;
+  }
+ /* need \0 but next char. must over write it */
+done:
+ __exprline[__cur_sofs] = '\0';  
+}
+
+/*
+ * convert a value as Verilog string to printable string
+ * truncating version
+ */
+extern char *__strab_tostr(char *s, word32 *ap, int32 blen, int32 nd_quotes,
+ int32 space_0)
+{
+ int32 sav_sofs = __cur_sofs;
+
+ __xline_vval_to_cstr(ap, blen, nd_quotes, space_0, FALSE);
+ /* here keeps low part if trunc needed */
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, TRUE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[sav_sofs] = '\0';
+ return(s);
+}
+
+/*
+ * convert a value as Verilog string to printable string
+ * non truncating version
+ *
+ * caller must insure big enough 
+ */
+extern char *__strab2_tostr(char *s, word32 *ap, int32 blen, int32 nd_quotes,
+ int32 space_0)
+{
+ int32 sav_sofs = __cur_sofs;
+
+ __xline_vval_to_cstr(ap, blen, nd_quotes, space_0, FALSE);
+ /* here keeps low part if trunc needed */
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[sav_sofs] = '\0';
+ return(s);
+}
+
+/*
+ * construct a Verilog string into line starting at __cur_sofs
+ *
+ * for values that are being printed in some type of display
+ * dmp_expr uses this to add string to accumulating line
+ */
+extern void __xline_vval_to_cstr(word32 *ap, int32 blen, int32 nd_quotes,
+ int32 space_0, int32 esc_esc)
+{
+ int32 chlen;
+ char *chp;
+
+ /* convert to pascal (no ending 0) string  - malloc storage */
+ chp = __vval_to_vstr(ap, blen, &chlen);
+ /* converts to c string with non printable expansion into __exprline */
+ vstr_to_cstr(chp, blen, space_0, nd_quotes, esc_esc);
+ /* free the version in malloced storage */
+ __my_free(chp, chlen);
+}
+
+/*
+ * convert a verilog string to a cstring - substitutes chars and adds \0
+ * and put result in __exprline starting at current place 
+ */
+static void vstr_to_cstr(char *vstr, int32 blen, int32 space_0, int32 nd_quotes,
+ int32 esc_esc)
+{
+ register int32 i; 
+ register char *chp;
+ int32 chlen;
+ char s1[RECLEN];
+
+ /* this will never extend higher than high word32, could have inform if */
+ /* not even 8 bits but no way to locate for user */ 
+ chlen = (blen + 7)/8;
+ /* DBG remove --- */
+ if (vstr[chlen] != '\0') __arg_terr(__FILE__, __LINE__);
+ /* --- */ 
+ if (nd_quotes) addch_('"');
+ for (chp = vstr, i = 0; i < chlen; i++, chp++)
+  {
+   switch (*chp) {
+    case '"': case '\\': addch_('\\'); addch_(*chp); break;
+    case '\n':
+     /* for source output must escape c escape so string contains embedded */
+     if (esc_esc) { addch_('\\'); addch_('n'); } else addch_(*chp);
+     break;
+    case '\t':
+     if (esc_esc) { addch_('\\'); addch_('t'); } else addch_(*chp);
+     break;
+    default:
+     if (!isprint(*chp))
+      {
+       if (space_0 && *chp == '\0') { addch_(' '); break; }
+       sprintf(s1, "%03o", *chp);
+       addch_('\\');
+       __adds(s1);
+       break;
+      }
+     addch_(*chp);
+   }
+  }
+ if (nd_quotes) addch_('"');
+ __exprline[__cur_sofs] = '\0';
+}
+
+/* ---
+INVERSE:
+
+#if (BYTE_ORDER == BIG_ENDIAN)
+   wrd = (b1 & 0xff) | ((b2 & 0xff) << 8) | ((b3 & 0xff) << 16)
+    | ((b4 & 0xff) << 24);
+#else
+   wrd = (b4 & 0xff) | ((b3 & 0xff) << 8) | ((b2 & 0xff) << 16)
+    | ((b1 & 0xff) << 24);
+--- */
+/*
+ * write 'u' format binary 0/1 one word32 using machine's endianness
+ * into __exprline
+ *
+ * for u format output is a words only but if b bit set value is 0
+ */
+static void disp_ufmt_binval(word32 *ap, word32 *bp, int32 blen)
+{
+ register int32 j;
+ register word32 wrd;
+ byte bval;
+ int32 wi;
+  
+ for (wi = 0; wi < wlen_(blen); wi++)
+  {
+   wrd = ap[wi] & (bp[wi] ^ 0xffffffff);
+
+#if (BYTE_ORDER != BIG_ENDIAN)
+   for (j = 24; j >= 0; j -= 8)
+    {
+     bval = (wrd >> j) & 0xff;
+     addch_(bval);
+    }
+#else
+   for (j = 0; j <= 24; j += 8)
+    {
+     bval = (wrd >> j) & 0xff;
+     addch_(bval);
+    }
+#endif
+  }
+}
+
+/*
+ * write 'z' format binary 0/1 two words using machine's endianness
+ * into __exprline
+ *
+ * for z format output is a and b words interleaved
+ */
+static void disp_zfmt_binval(word32 *ap, word32 *bp, int32 blen)
+{
+ register int32 j;
+ int32 wi;
+ byte bval;
+
+ for (wi = 0; wi < wlen_(blen); wi++)
+  {
+#if (BYTE_ORDER != BIG_ENDIAN)
+   for (j = 24; j >= 0; j -= 8)
+    {
+     bval = (ap[wi] >> j) & 0xff;
+     addch_(bval);
+     bval = (bp[wi] >> j) & 0xff;
+     addch_(bval);
+    }
+#else
+   for (j = 0; j <= 24; j += 8)
+    {
+     bval = (ap[wi] >> j) & 0xff;
+     addch_(bval);
+     bval = (bp[wi] >> j) & 0xff;
+     addch_(bval);
+    }
+#endif
+  }
+}
+
+/*
+ * get a string and allocate with malloc
+ *
+ * not for disp routines where string in Verilog must be literal
+ * this will always build some kind of string
+ * this must be called with actual string or number object
+ */
+extern char *__get_eval_cstr(struct expr_t *xp, int32 *chlen)
+{
+ register int32 i;
+ register char *chp; 
+ int32 sav_sofs, slen;
+ struct xstk_t *xsp;
+
+ xsp = __eval_xpr(xp); 
+
+ /* entire string could be \ddd form and 1 char per 8 bits */
+ /* notice here every char can become \ddd where digits are octal */
+ /* puts result in expr line */
+ sav_sofs = __cur_sofs;
+ __xline_vval_to_cstr(xsp->ap, xsp->xslen, FALSE, FALSE, FALSE);
+ __pop_xstk();
+
+ /* final step is trim all leading \000 chars */
+ /* notice if any non \000, must stop */
+ slen = __cur_sofs;
+ for (chp = __exprline; *chp != '\0'; chp += 4)
+  { if (strncmp(chp, "\\000", 4) != 0) break; }
+ /* remove leading 0's if needed */
+ if (chp != __exprline)
+  {
+   slen -= (chp - __exprline); 
+   /* tricky in place copy - strcpy not portable - also copy ending 0 */
+   for (i = 0; i <= slen; i++) __exprline[i] = chp[i];
+  }
+ slen = strlen(&(__exprline[sav_sofs]));
+ chp = __my_malloc(slen + 1);
+ strcpy(chp, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0';
+ *chlen = slen;
+ return(chp);
+}
+
+/*
+ * convert constant string stored as Verilog value to Verilog style string
+ * know b val always 0 and still must convert to C style string for print
+ * copy little endian chars in words, bit endian word32 reg to big endian
+ *
+ * always puts a \0 at end of string in case needed (usually not)
+ * also not Verilog value in sense that high chars are not zeroed
+ *
+ * cannot use to replace value 
+ * all this stuff is not 8 bit clean
+ * loop probably better than the inlining here
+ * notice assuming 8 bit byte
+ * this routines is 32 bit word32 dependent
+ */
+extern char *__vval_to_vstr(word32 *ap, int32 blen, int32 *slen)
+{
+ register int32 si, wi;
+ char *s;
+ int32 wlen, nchs;
+
+ /* make sure one extra character at end, if need to convert to */
+ /* binary style c string for sreadmem */
+ nchs = (blen + 7)/8;
+ wlen = wlen_(8*nchs);
+ /* make this up to 7 bytes larger than strictly needed */
+ *slen = WRDBYTES*(wlen + 1);
+ s = __my_malloc(*slen);
+
+ for (si = nchs - 1, wi = 0; wi < wlen - 1; si -= 4, wi++)
+  {
+   s[si] = (char) (ap[wi] & 0xffL);
+   s[si - 1] = (char) ((ap[wi] >> 8) & 0xffL);
+   s[si - 2] = (char) ((ap[wi] >> 16) & 0xffL);
+   s[si - 3] = (char) ((ap[wi] >> 24) & 0xffL);
+  }
+ if (si < 0) goto done;
+ s[si--] = (char) (ap[wi] & 0xffL);
+ if (si < 0) goto done;
+ s[si--] = (char) ((ap[wi] >> 8) & 0xffL);
+ if (si < 0) goto done;
+ s[si--] = (char) ((ap[wi] >> 16) & 0xffL);
+ if (si < 0) goto done;
+ s[si--] = (char) ((ap[wi] >> 24) & 0xffL);
+ /* format of verilog value string wrong */
+ if (si != -1) __misc_terr(__FILE__, __LINE__);
+done:
+ /* after filled form high end to low put in high ending \0 */
+ s[nchs] = '\0';
+ return(s);
+}
+
+/*
+ * convert strength wire expr. (maybe range) to string 
+ */
+extern char *__strenexpr_tostr(char *s, struct expr_t *xp)
+{
+ int32 sav_sofs = __cur_sofs;
+
+ sdisp_st(xp);
+ /* here keeps low part if trunc needed */
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, TRUE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0';
+ return(s);
+}
+
+/*
+ * display one strength value - can only be scalar or bit select
+ * checks for required simple expr.
+ * this must not leave anything on stack
+ * also fills exprline from current place
+ *
+ * notice for non strength this will add strong
+ * also notice this has standard extension to allow printing vectors
+ */
+static void sdisp_st(struct expr_t *xp)
+{
+ register int32 bi;
+ int32 first_time;
+ byte *sbp; 
+ struct xstk_t *xsp;
+ char s1[10];
+
+ /* eval. the expression - if non strength strong added */
+ xsp = __ndst_eval_xpr(xp); 
+ sbp = (byte *) xsp->ap;
+ for (first_time = TRUE, bi = xsp->xslen/4 - 1; bi >= 0; bi--)
+  {
+   if (first_time) first_time = FALSE; else addch_(' '); 
+   __adds(__to_vvstnam(s1, (word32) sbp[bi]));
+  }
+ __pop_xstk();  
+}
+
+/*
+ * NUMERIC EXPRESSION DISPLAY WORK ROUTINES - EXPR DETERMINES FMT 
+ * INTERNAL INTERFACE TO SAME MECHANISM AS DO_DISP
+ */
+
+/*
+ * truncated string form of num expr to value
+ * this uses high env 
+ */
+extern char *__msgnumexpr_tostr(char *s, struct expr_t *ndp, int32 inum)
+{
+ int32 sav_sofs = __cur_sofs;
+ 
+ numexpr_disp(ndp, inum);
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, FALSE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0'; 
+ return(s);
+}
+
+/*
+ * build a numeric expr. value in exprline - grows if needed
+ * use ndp node info to attempt to reconstruct input string
+ *
+ * does not set cur_sofs - can add into middle, but caller must set it
+ * also if inum not known and IS form - must pass 0
+ */
+static void numexpr_disp(struct expr_t *ndp, int32 inum)
+{
+ word32 *ap, *bp, *wp;
+ int32 wlen, base;
+ double *dp, d1;
+ char s1[RECLEN];
+
+ if (ndp == NULL)
+  {
+   __pv_warn(515, "INTERNAL - trying to print NULL expr.");
+   __adds("NULL expr.");
+   return;
+  }
+ wlen = wlen_(ndp->szu.xclen);
+ switch ((byte) ndp->optyp) {
+  case ISNUMBER:
+   wp = &(__contab[ndp->ru.xvi]);
+   ap = &(wp[2*wlen*inum]);
+   break;
+  case NUMBER:
+   ap = &(__contab[ndp->ru.xvi]);
+   break;
+  case ISREALNUM:
+   /* SJM 05/05/05 - must multiply inum by 2 since real cons now use a/bs */
+   dp = (double *) &(__contab[ndp->ru.xvi + 2*inum]); 
+   d1 = *dp;
+disp_real:
+   sprintf(s1, "%g", d1);
+   __adds(s1);
+   return;
+ case REALNUM:
+   dp = (double *) &(__contab[ndp->ru.xvi]); 
+   d1 = *dp;
+   goto disp_real;
+  default: __case_terr(__FILE__, __LINE__); return;
+ }
+ if (ndp->is_string)
+  {
+   /* if is string on, know will not contain x/z bits, input as ".." */
+   /* know cur sofs saved and restored by caller */
+   __xline_vval_to_cstr(ap, ndp->szu.xclen, TRUE, TRUE, TRUE);
+   return;
+  }
+ bp = &(ap[wlen]);
+ if (__force_base == BNONE) base = ndp->ibase; else base = __force_base;
+ switch ((byte) base) {
+  case BDEC:
+   if ((ndp->unsiznum || ndp->szu.xclen == WBITS)
+    && vval_is0_(bp, ndp->szu.xclen))
+    {
+     /* unsized (no 'd) decimal always signed */
+     sdispd(ap, bp, ndp->szu.xclen, TRUE, TRUE);
+     break;
+    }
+   if (ndp->sizdflt) __adds("'d");
+   else { sprintf(s1, "%d'd", ndp->szu.xclen); __adds(s1); }
+   /* if no. even decimal has 'd, always word32 and trimmed */
+   sdispd(ap, bp, ndp->szu.xclen, TRUE, FALSE);
+   break;
+  case BHEX:
+   /* know rest all word32 */
+   /* [size]'h prefixed number always trimmed */
+   if (ndp->sizdflt) __adds("'h");
+   else { sprintf(s1, "%d'h", ndp->szu.xclen); __adds(s1); }
+   sdisph(ap, bp, ndp->szu.xclen, TRUE);
+   break;
+  case BOCT:
+   if (ndp->sizdflt) __adds("'o");
+   else { sprintf(s1, "%d'o", ndp->szu.xclen); __adds(s1); }
+   sdispo(ap, bp, ndp->szu.xclen, TRUE);
+   break;
+  case BBIN:
+   if (ndp->sizdflt) __adds("'b");
+   else { sprintf(s1, "%d'b", ndp->szu.xclen); __adds(s1); }
+   __sdispb(ap, bp, ndp->szu.xclen, TRUE);
+   break;
+  default:
+   __case_terr(__FILE__, __LINE__);
+   return;
+ }
+}
+
+/*
+ * truncate __exprline to newsize - __cur_sofs points to end
+ * know truncation must be less than RECLEN (512)
+ */
+extern void __trunc_exprline(int32 newsize, int32 from_front)
+{
+ if (__cur_sofs < newsize) return;
+
+ if (from_front)
+  {
+   char s1[RECLEN];
+
+   strcpy(s1, "...");
+   strcat(s1, &(__exprline[__cur_sofs - newsize - 3]));
+   strcpy(__exprline, s1);
+   __cur_sofs = newsize;
+  }
+ else
+  {
+   __cur_sofs = newsize;
+   __exprline[__cur_sofs] = '\0';
+   __exprline[__cur_sofs - 3] = '.';
+   __exprline[__cur_sofs - 2] = '.';
+   __exprline[__cur_sofs - 1] = '.';
+  }
+}
+
+/*
+ * truncate a cstring know new size inside allocated size of string
+ * this removes prefix when truncation needed 
+ * know truncation must be less than RECLEN (512)
+ */
+extern void __trunc_cstr(char *s, int32 newsize, int32 from_front)
+{
+ int32 slen;
+
+ if ((slen = strlen(s)) < newsize) return;
+   
+ if (from_front)
+  {
+   char s1[RECLEN];
+
+   strcpy(s1, "...");
+   /* since string starts at 0 to start at pos. k index is k - 1 */
+   strcat(s1, &(s[slen - newsize - 3 - 1]));
+   strcpy(s, s1);
+  }
+ else
+  {
+   s[slen - 3] = '.';
+   s[slen - 2] = '.';
+   s[slen - 1] = '.';
+   s[slen] = '\0';
+  }
+}
+
+/*
+ * PRINTING COPY INTO STRING INTERFACE ROUTINES TO NORMAL PRINT 
+ */
+
+/*
+ * version of regab to string that gets format from expression
+ * this handles string constants in both forms
+ * LOOKATME - how does this routine differ from num expr disp
+ */
+extern char *__xregab_tostr(char *s, word32 *ap, word32 *bp, int32 blen,
+ struct expr_t *xp)
+{
+ int32 signv, base;
+
+ /* if expr. is string, write as unquoted string */
+ if (xp->is_string)
+  {
+   __strab_tostr(s, ap, xp->szu.xclen, FALSE, TRUE);
+   return(s);
+  }
+ base = BHEX;
+ signv = FALSE;
+ if (xp->is_real) { base = BDBLE; signv = TRUE; }
+ else
+  {  
+   /* can com close to constant number format duplication */
+   if  (xp->optyp == NUMBER || xp->optyp == ISNUMBER)
+    {
+     if (xp->unsiznum) { base = BDEC; signv = TRUE; }   
+     else base = xp->ibase; 
+    }
+   /* notice if simple varible signed, has sign on */
+   if (xp->has_sign) { base = BDEC; signv = TRUE; }
+  }
+ __regab_tostr(s, ap, bp, blen, base, signv);
+ return(s);
+}
+
+/*
+ * version of regab to string that gets format from parameter ncomp record
+ * this handles string constants in both forms
+ */
+extern char *__pregab_tostr(char *s, word32 *ap, word32 *bp, struct net_t *np)
+{
+ int32 signv, base;
+
+ /* DBG remove --- */
+ if (np->nrngrep != NX_CT || !np->n_isaparam)
+  __misc_terr(__FILE__, __LINE__);
+ /* --- */ 
+
+ /* if original param rhs string, write as unquoted string */
+ if (np->nu.ct->pstring)
+  {
+   __strab_tostr(s, ap, np->nwid, FALSE, TRUE);
+   return(s);
+  }
+ base = BHEX;
+ signv = FALSE;
+ if (np->ntyp == N_REAL) { base = BDBLE; signv = TRUE; }
+ else
+  {  
+   base = np->nu.ct->pbase;
+   if (np->n_signed) signv = TRUE; else signv = FALSE;
+  }
+ __regab_tostr(s, ap, bp, np->nwid, base, signv);
+ return(s);
+}
+
+/*
+ * convert reg. ab style value to string - always trim
+ * can always print value by loading to stk and calling this
+ *
+ * notice this prints passed string not chp of next pos.
+ * string passed must be at least RECLEN 
+ */
+extern char *__regab_tostr(char *s, word32 *ap, word32 *bp, int32 blen, int32 base,
+ int32 hassign)
+{
+ int32 sav_sofs = __cur_sofs;
+
+ __regab_disp(ap, bp, blen, base, TRUE, hassign);
+ /* here keeps low part if trunc needed */
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, TRUE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0';
+ return(s);
+}
+
+/*
+ * version of regab to string that allows turning trim off
+ */
+extern char *__regab2_tostr(char *s, word32 *ap, word32 *bp, int32 blen, int32 base,
+ int32 hassign, int32 trim)
+{
+ int32 sav_sofs = __cur_sofs;
+
+ __regab_disp(ap, bp, blen, base, trim, hassign);
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, TRUE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0';
+ return(s);
+}
+
+/*
+ * special display routine that takes base as argrument
+ * but does not output sizes
+ * to print value subrange caller must adjust passed ap and bp and blen
+ *
+ * notice if can be using exprline caller must save
+ */
+extern void __regab_disp(word32 *ap, word32 *bp, int32 blen, int32 base, int32 trim,
+ int32 hassign)
+{
+ char s1[RECLEN];
+
+ switch ((byte) base) {
+  case BBIN: __sdispb(ap, bp, blen, trim); break;
+  case BOCT: sdispo(ap, bp, blen, trim); break;
+  case BDEC: sdispd(ap, bp, blen, trim, hassign); break;
+  case BHEX: sdisph(ap, bp, blen, trim); break;
+  case BDBLE:
+   {
+    double d1;
+
+    memcpy(&d1, ap, sizeof(double));
+    /* here always try to trim to match OVIsim */
+    sprintf(s1, "%g", d1);
+    __adds(s1);
+   }
+   break;
+  default:
+   __pv_err(768, "numeric display format illegal (value %d)", base); 
+ }
+}
+
+/*
+ * convert strength style value to string
+ * can always print value by loading to stk and calling this
+ * s must be at least RECLEN wide
+ */
+extern char *__st_regab_tostr(char *s, byte *sbp, int32 blen)
+{
+ int32 sav_sofs = __cur_sofs;
+
+ st_regab_disp(sbp, blen);
+ /* truncate from front if needed - keep low bits */
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, TRUE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0'; 
+ return(s);
+}
+
+/*
+ * display a strength value into expr line
+ */
+static void st_regab_disp(byte *sbp, int32 blen)
+{
+ register int32 i;
+ char s1[RECLEN];
+
+ /* maybe need some kind of separator here */
+ for (i = blen - 1;; i--)
+  {
+   __adds(__to_vvstnam(s1, (word32) sbp[i]));
+   if (i <= 0) break;
+   addch_(' '); 
+  }
+ __exprline[__cur_sofs] = '\0';
+}
+
+/*
+ * to an expression wire range - x1 must be != NULL
+ * uses end of expr line in case in use 
+ */
+extern char *__msgtox_wrange(char *s, struct expr_t *x1, struct expr_t *x2)
+{
+ int32 sav_sofs = __cur_sofs;
+
+ tox_wrange((FILE *) NULL, x1, x2);
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, FALSE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0'; 
+ return(s);
+}
+
+/*
+ * version of expr to string that truncates for messages
+ * this dumps unevaluated expression not value
+ */
+extern char *__msgexpr_tostr(char *s, struct expr_t *ndp)
+{
+ int32 sav_sofs = __cur_sofs;
+
+ dmp_expr((FILE *) NULL, ndp);
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, FALSE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0'; 
+ return(s);
+}
+
+/*
+ * FOR DEBUGGING VARIABLE DUMP ROUTINES
+ */
+
+/*
+ * load a value
+ */
+
+/*
+ * convert a variable to a string
+ */
+extern char *__var_tostr(char *s, struct net_t *np, int32 i1, int32 i2, int32 base)
+{
+ int32 sav_sofs = __cur_sofs;
+
+ /* use sign from var. */
+ __disp_var(np, i1, i2, base, '?');
+ /* truncate from front if needed - keep low bits */
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, TRUE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0'; 
+ return(s);
+}
+
+/*
+ * display variable (possibly part or bit select range out of [i1,i2]) with
+ * base base and force signed '-' or word32 ' ' or use variable sign
+ * in other case
+ *
+ * for array - may need to be called multiple times but will index one
+ * entire array if i1==i2 and in range
+ *
+ * expects __cur_sofs to be set and builds in expr line 
+ */  
+extern void __disp_var(struct net_t *np, int32 i1, int32 i2, int32 base,
+ char vsign_ovride)
+{
+ int32 arrwid, hassign, netwid;
+ double d1;
+ struct xstk_t *xsp;
+ char s1[RECLEN];
+
+ /* need var. for net wid since may change width for printing below */
+ netwid = np->nwid;
+ /* case 1: strength */
+ if (np->n_stren) { disp_stvar(np, i1, i2); return; } 
+
+ /* case 2: real variable (no arrays of reals) */
+ if (np->ntyp == N_REAL) 
+  {
+   memcpy(&d1, &(np->nva.wp[2*__inum]), sizeof(double));
+   sprintf(s1, "%g", d1);
+   __adds(s1);
+   return;
+  } 
+ hassign = FALSE;
+ /* case 3: array - must be 1 index */
+ if (np->n_isarr)
+  {
+   /* must have exactly one index */
+   arrwid = __get_arrwide(np);
+   if (i1 == i2 && i1 == -1) 
+    {
+     strcpy(s1, "[first of entire array]: ");
+     __adds(s1);
+     i1 = 0;
+    }
+   else
+    {
+     if (i1 < 0 || i1 != i2 || i1 >= arrwid) __arg_terr(__FILE__, __LINE__);
+    }
+   push_xstk_(xsp, netwid);
+   __ld_arr_val(xsp->ap, xsp->bp, np->nva, arrwid, netwid, i1);
+   if (netwid > WBITS) goto do_print;
+   hassign = get_ovrsign(np, vsign_ovride);
+   goto do_print;
+  }
+ /* case 4: scalar or all of vector */
+ /* case 4a: all of variable */
+ if (i1 == -1)
+  {
+   push_xstk_(xsp, netwid); 
+   __ld_wire_val(xsp->ap, xsp->bp, np);
+   if (netwid > WBITS) goto do_print;
+   hassign = get_ovrsign(np, vsign_ovride);
+   goto do_print;
+  } 
+ /* 4b part of var. - must be vector do select */
+ else 
+  {
+   if (!np->n_isavec) __case_terr(__FILE__, __LINE__);
+   /* case 4b-a: bit select */
+   if (i1 == i2)
+    {
+     if (i1 < 0 || i1 >= netwid) __case_terr(__FILE__, __LINE__);
+     push_xstk_(xsp, 1); 
+     __ld_bit(xsp->ap, xsp->bp, np, i1);
+     netwid = 1;
+     goto do_print;
+    }
+   /* case 4b-b: part select */
+   if (i1 < 0 || i2 < 0 || i1 < i2 || i1 >= netwid)
+    __case_terr(__FILE__, __LINE__);
+   push_xstk_(xsp, netwid);
+   /* notice here nwid must be width of net */ 
+   __ld_psel(xsp->ap, xsp->bp, np, i1, i2);
+   /* but display nwid as width of part select */
+   netwid = i1 - i2 + 1;
+  }
+do_print:
+ __regab_disp(xsp->ap, xsp->bp, netwid, base, TRUE, hassign);
+ __pop_xstk();
+} 
+
+/*
+ * display a possible section of a strength variable (from the wire)
+ */
+static void disp_stvar(struct net_t *np, int32 i1, int32 i2)
+{
+ register int32 i;
+ char s1[RECLEN];
+
+ if (i1 == -1) { i1 = np->nwid - 1; i2 = 0; }
+ /* maybe need some kind of separator here */
+ for (i = i1; i >= i2; i--)
+  {
+   __adds(__to_vvstnam(s1, (word32) np->nva.bp[i]));
+   if (i > i2) addch_(' ');
+  }
+ __exprline[__cur_sofs] = '\0'; 
+}
+
+/*
+ * return sign by testing over-ride variable - if not use wire sign
+ */
+static int32 get_ovrsign(struct net_t *np, char ovride)
+{
+ if (ovride == '-') return(TRUE);
+ else if (ovride == ' ') return(FALSE);
+ return(np->n_signed == 1);
+}
+
+/*
+ * dump all of a array for inst ifr to ito
+ * only called if debug on and inst ptr set
+ *
+ */
+extern void __dmp_arr_all(struct net_t *np, int32 ifr, int32 ito)
+{
+ if (!np->n_isarr) __arg_terr(__FILE__, __LINE__);
+ dmp_arr_insts(np, ifr, ito);
+}
+
+/*
+ * dmp instance ifr to ito of arr var. np from mfr to mto
+ * mfr and mto assume normalized h:0 form not actual range
+ */
+static void dmp_arr_insts(struct net_t *np, int32 ifr, int32 ito)
+{
+ register int32 i;
+ int32 ri1, ri2, arrwid;
+
+ if (!np->n_isarr) __arg_terr(__FILE__, __LINE__);
+ __getarr_range(np, &ri1, &ri2, &arrwid);
+ for (i = ifr; i <= ito; i++) dmp_arr(np, ri1, ri2, i);
+}
+
+/*
+ * dump an array from index mifr to mito for instance inum
+ */
+static void dmp_arr(struct net_t *np, int32 mifr, int32 mito, int32 inum)
+{
+ register int32 mi;
+ int32 arrwid, ri1, ri2, h0_arri;
+ struct xstk_t *xsp;
+
+ if (!np->n_isarr) __arg_terr(__FILE__, __LINE__);
+ __getarr_range(np, &ri1, &ri2, &arrwid);
+
+ __push_wrkitstk(__inst_mod, inum);
+ push_xstk_(xsp, np->nwid);
+ for (mi = mifr; mi <= mito; mi++)
+  {
+   /* FIXME - think this is wrong should unnormalize? */ 
+   h0_arri = normalize_ndx_(mi, ri1, ri2);
+   __ld_arr_val(xsp->ap, xsp->bp, np->nva, arrwid, np->nwid, h0_arri);
+   __dbg_msg("array %s inst %d width %d index %d = %s\n", np->nsym->synam,
+    inum, np->nwid, mi, __regab_tostr(__xs, xsp->ap, xsp->bp, np->nwid,
+    BHEX, FALSE));
+  }
+ __pop_xstk();
+ __pop_wrkitstk();
+}
+
+/*
+ * FOR DEBUGGING ROUTINES TO DUMP NET PIN LISTS
+ */
+
+/*
+ * dump the np and dce lists for one module 
+ * only called if debug flag on
+ */
+extern void __dmpmod_nplst(struct mod_t *mdp, int32 dces_only)
+{
+ register int32 ni;
+ register struct net_t *np;
+ register struct task_t *tskp;
+
+ /* DBG remove ---
+ --   int32 ii;
+ if (__debug_flg)
+  {
+   for (ii = 0; ii < __numtopm; ii++) __dmp_itree(__it_roots[ii]);
+  }
+ --- */
+
+ if (dces_only)
+  __dbg_msg("++> module %s event list\n", mdp->msym->synam);
+ else __dbg_msg("++> module %s net pin and event lists\n", mdp->msym->synam);
+
+ if (mdp->mnnum != 0)
+  {
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+    dmp1n_nplst(mdp, np, dces_only);
+  }
+ for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt) 
+  {
+   __dbg_msg("**> task %s net pin list\n", tskp->tsksyp->synam);
+   if (tskp->trnum != 0)
+    {
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      dmp1n_nplst(mdp, np, dces_only);
+    }
+  }
+}
+
+/*
+ * dump the net pin list elements for 1 net
+ */
+static void dmp1n_nplst(struct mod_t *mdp, struct net_t *np, int32 dces_only)
+{
+ register struct net_pin_t *npp;
+ register struct dcevnt_t *dcep;
+ int32 first_time;
+ char s1[RECLEN];
+
+ if (np->ntyp == N_EVENT)
+  {
+   __dbg_msg("==> event %s - no net loads and no drivers\n",
+    np->nsym->synam);
+   __dbg_msg("==> %s %s size %d with %d event ctrls:\n",
+    __to_wtnam(s1, np), np->nsym->synam, np->nwid,
+    __cnt_dcelstels(np->dcelst));
+   goto try_dces;
+  }
+
+ __dbg_msg("==> %s %s size %d with %d drivers, %d loads and %d event ctrls:\n",
+  __to_wtnam(s1, np), np->nsym->synam, np->nwid,
+  cnt_nplstels(np->ndrvs), cnt_nplstels(np->nlds),
+  __cnt_dcelstels(np->dcelst));
+
+ if (dces_only) goto try_dces;
+
+ first_time = TRUE;
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   if (first_time) { __dbg_msg("  ++drivers ->\n"); first_time = FALSE; }
+   __dmp1_nplstel(mdp, np, npp);
+  }
+ first_time = TRUE;
+ for (npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   if (first_time) { __dbg_msg("  ++loads ->\n"); first_time = FALSE; }
+   __dmp1_nplstel(mdp, np, npp);
+  }
+
+try_dces:
+ first_time = TRUE;
+ /* notice #<num> delays are just scheduled no triggering */
+ for (dcep = np->dcelst; dcep != NULL; dcep = dcep->dcenxt)
+  {
+   if (dcep->dce_off) continue;
+
+   if (first_time)
+    { __dbg_msg("  ++event controls ->\n"); first_time = FALSE; }
+   __dmp1_dcelstel(mdp, dcep);
+  }
+}
+
+/*
+ * count drivers or loads (inst. specific counted for each inst.)
+ * SJM 07/25/01 - although MIPD is a load, it is not counted
+ */
+static int32 cnt_nplstels(register struct net_pin_t *npp)
+{ 
+ int32 i;
+
+ for (i = 0; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->npntyp != NP_MIPD_NCHG) i++;
+  }
+ return(i);
+}
+
+/*
+ * count delay control/dump vars events
+ */
+extern int32 __cnt_dcelstels(register struct dcevnt_t *dcep)
+{ 
+ int32 i;
+
+ for (i = 0; dcep != NULL; dcep = dcep->dcenxt)
+  {
+   if (dcep->dce_off) continue;
+   i++;
+  }
+ return(i);
+}
+
+/*
+ * dump 1 net pin list element
+ *
+ * includes the removed after tran chan build removed npps
+ * mdp only need for mod port or instance conns npps
+ */
+extern void __dmp1_nplstel(struct mod_t *mdp, struct net_t *np,
+ struct net_pin_t *npp)
+{
+ word32 stval;
+ struct inst_t *ip;
+ struct gate_t *gp;
+ struct mod_t *imdp, *tmp_mdp;
+ struct conta_t *cap;
+ struct tfrec_t *tfrp;
+ struct tchk_t *tcp;
+ struct spcpth_t *pthp;
+ struct npaux_t *npauxp;
+ struct itree_t *itp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[RECLEN];
+
+ if ((npauxp = npp->npaux) != NULL && npauxp->nbi1 != -1)
+  {
+   if (npauxp->lcbi1 == -1)
+    __dbg_msg("    [%d:%d]: ", npauxp->nbi1, npauxp->nbi2.i);
+   else __dbg_msg("    [%d:%d] (lhs cat rhs [%d:%d]): ",
+    npauxp->nbi1, npauxp->nbi2.i, npauxp->lcbi1, npauxp->lcbi2);
+  }
+ else __dbg_msg("    ");
+
+ /* handle proc type - need a module (can by any) */
+ switch ((byte) npp->npproctyp) {
+  case NP_PROC_INMOD:
+   tmp_mdp = mdp;
+   sprintf(s3, "(IN=%s)", tmp_mdp->msym->synam); break;
+  case NP_PROC_GREF:
+   tmp_mdp = npauxp->npu.npgrp->gin_mdp;
+   sprintf(s3, "(XMR %s mod=%s)", npauxp->npu.npgrp->gnam,
+    tmp_mdp->msym->synam);
+   break;
+  case NP_PROC_FILT:
+   itp = npauxp->npdownitp;
+   tmp_mdp = itp->itip->imsym->el.emdp;
+   sprintf(s3, "(INST-LOC=%s(%s))", __msg2_blditree(__xs, itp),
+    tmp_mdp->msym->synam);
+   break;
+  default: __case_terr(__FILE__, __LINE__); return;
+ }
+ switch ((byte) npp->np_xmrtyp) {
+  case XNP_LOC: strcpy(s4, "-LOCAL-"); break;
+  case XNP_DOWNXMR: strcpy(s4, "-DOWNXMR-"); break;
+  case XNP_RTXMR: strcpy(s4, "-RTXMR-"); break;
+  case XNP_UPXMR: strcpy(s4, "-UPXMR-"); break;
+  default: __case_terr(__FILE__, __LINE__); return;
+ }
+ switch ((byte) npp->npntyp) {
+  case NP_ICONN: case NP_BIDICONN:
+   /* current mod is target but need ref module (of first inst?) */
+   /* DBG remove -- */
+   if (npp->elnpp.eii >= tmp_mdp->minum || tmp_mdp->minum == 0)
+    __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   /* notice normally actual instance relative to itree place */
+   ip = &(tmp_mdp->minsts[npp->elnpp.eii]); 
+   __dbg_msg("inst. %s type %s %s %s port %d at %s\n", ip->isym->synam,
+    ip->imsym->synam, s3, s4, npp->obnum + 1,
+    __bld_lineloc(__xs, ip->isym->syfnam_ind, ip->isym->sylin_cnt));
+   break;
+  case NP_PB_ICONN:
+   ip = &(tmp_mdp->minsts[npp->elnpp.eii]); 
+   __dbg_msg("inst. %s type %s %s %s port %d bit %d at %s\n",
+    ip->isym->synam, ip->imsym->synam, s3, s4, npp->obnum + 1,
+    npp->pbi, __bld_lineloc(__xs, ip->isym->syfnam_ind, ip->isym->sylin_cnt));
+   break;
+  case NP_GATE: case NP_TRANIF: case NP_TRAN:
+   gp = npp->elnpp.egp;
+   __dbg_msg("gate %s type %s %s %s port %d at %s\n", gp->gsym->synam,
+    gp->gmsym->synam, s3, s4, npp->obnum + 1, __bld_lineloc(__xs,
+    gp->gsym->syfnam_ind, gp->gsym->sylin_cnt));
+   break;
+  case NP_CONTA:
+   cap = npp->elnpp.ecap;
+   if (cap->ca_pb_sim)
+    {
+     __dbg_msg("per bit continuous assign bit %d at %s %s %s\n", npp->pbi,
+      __bld_lineloc(__xs, cap->casym->syfnam_ind, cap->casym->sylin_cnt),
+      s3, s4);
+    }
+   else
+    {
+     __dbg_msg("continuous assign at %s %s %s\n", __bld_lineloc(__xs,
+      cap->casym->syfnam_ind, cap->casym->sylin_cnt), s3, s4);
+    }
+   break;
+  case NP_TFRWARG:
+   tfrp = npp->elnpp.etfrp;
+   if (tfrp->tf_func) strcpy(s1, "function"); else strcpy(s1, "task");
+   __dbg_msg("tf_ %s %s read/write argument (pos. %d) at %s\n", s3, s4,
+    npp->obnum, __bld_lineloc(__xs, tfrp->tffnam_ind, tfrp->tflin_cnt));
+   break;
+  case NP_VPIPUTV:
+   if (npp->npaux == NULL || npp->npaux->nbi1 == -1)
+    strcpy(__xs, "vpiWireDriver");
+   else strcpy(__xs, "vpiWireBitDriver");
+   __dbg_msg("vpi_ added %s for net %s %s %s\n", __xs, np->nsym->synam, s3,
+    s4);
+   break;
+  case NP_MDPRT: case NP_BIDMDPRT:
+   imdp = npp->elnpp.emdp;
+   __dbg_msg("module %s %s %s %s port %s (pos. %d) at %s\n", imdp->msym->synam,
+    s3, s4, __to_ptnam(s1, np->iotyp),
+    __to_mpnam(s2, imdp->mpins[npp->obnum].mpsnam), npp->obnum + 1,
+    __bld_lineloc(__xs, mdp->msym->syfnam_ind, mdp->msym->sylin_cnt));
+   break;
+  case NP_PB_MDPRT: 
+   imdp = npp->elnpp.emdp;
+   __dbg_msg("module %s %s %s %s port %s (pos. %d) bit %d at %s\n",
+    imdp->msym->synam, s3, s4, __to_ptnam(s1, np->iotyp),
+    __to_mpnam(s2, imdp->mpins[npp->obnum].mpsnam), npp->obnum + 1,
+    npp->pbi, __bld_lineloc(__xs, mdp->msym->syfnam_ind,
+    mdp->msym->sylin_cnt));
+   break;
+  case NP_MIPD_NCHG:
+   __dbg_msg("MIPD delay device in module %s for %s %s\n",
+    mdp->msym->synam, __to_ptnam(s1, np->iotyp), np->nsym->synam);
+   break;
+  case NP_PULL:
+   gp = npp->elnpp.egp;
+   stval = gp->g_stval << 2;
+   if (npp->pullval == 1) stval |= 1; 
+   __dbg_msg("%s to %s on %s at %s\n",
+    gp->gmsym->synam, __to_vvstnam(s1, (word32) stval),  
+    __msgexpr_tostr(__xs, gp->gpins[npp->obnum]), __bld_lineloc(__xs2,
+    gp->gsym->syfnam_ind, gp->gsym->sylin_cnt));
+   break;
+  case NP_TCHG:
+   switch ((byte) npp->chgsubtyp) {
+    case NPCHG_TCSTART: 
+     tcp = npp->elnpp.etchgp->chgu.chgtcp;
+     __dbg_msg("%s timing check first (reference) change line %s\n",
+      __to_tcnam(__xs, tcp->tchktyp), __bld_lineloc(__xs2,
+      tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt));
+     break;
+    case NPCHG_TCCHK:
+     tcp = npp->elnpp.echktchgp->startchgp->chgu.chgtcp;
+     __dbg_msg("%s timing check 2nd (check) change line %s\n",
+      __to_tcnam(__xs, tcp->tchktyp), __bld_lineloc(__xs2,
+      tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt));
+     break;
+    case NPCHG_PTHSRC:
+     pthp = npp->elnpp.etchgp->chgu.chgpthp;
+     __dbg_msg("delay path source change line %s\n",
+      __bld_lineloc(__xs, pthp->pthsym->syfnam_ind,
+      pthp->pthsym->sylin_cnt));
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   break;
+  default:
+   __gfterr(302, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+    "unknown net pin value %d", npp->npntyp);
+ }
+}
+
+/*
+ * dump 1 net pin list element
+ *
+ * this does not dump base dvcodes because caller does not know if net
+ * in task or module
+ */
+extern void __dmp1_dcelstel(struct mod_t *mdp, struct dcevnt_t *dcep)
+{
+ struct st_t *stp; 
+ struct delctrl_t *dctp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (dcep->dce_edge)
+  {
+   /* access value */
+   sprintf(s1, " %s (first instance old value %s)",
+    __to_edgenam(s2, dcep->dce_edgval), __to_vvnam(s3,
+    get_dce_edgeval(mdp, dcep)));
+  }
+ else strcpy(s1, "");
+ if (dcep->dce_off) __dbg_msg("*OFF*");
+ switch ((byte) dcep->dce_typ) {
+  case DCE_RNG_INST: case DCE_INST:
+   __dbg_msg("    [%d:%d]: event control net %s trigger: %s",
+    dcep->dci1, dcep->dci2.i, dcep->dce_np->nsym->synam, s1);
+   dctp = dcep->st_dctrl;
+   /* DBG remove --- */
+   if (dctp->dctyp < DC_EVENT || dctp->dctyp > DC_WAITEVENT)
+    __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   stp = dcep->st_dctrl->actionst;
+   if (stp == NULL) __dbg_msg("\n");
+   else __dbg_msg(" at %s\n", __bld_lineloc(s2, stp->stfnam_ind,
+    stp->stlin_cnt));
+   break;
+  case DCE_RNG_MONIT:
+  case DCE_MONIT:
+   /* maybe need more info here */
+   __dbg_msg("    [%d:%d]: monitor net %s trigger\n", dcep->dci1,
+    dcep->dci2.i, dcep->dce_np->nsym->synam); 
+   /* FIXME - only defined for monitor - should also dump for rng form */
+   /* LOOKATME - can this happen since no more col. */
+   if (dcep->dce_1inst)
+    {
+     __dbg_msg("   (xmr match: target %s - down src: %s)\n", 
+      __msg2_blditree(s1, dcep->dce_matchitp), __msg2_blditree(s2,
+      dcep->dce_refitp));
+    }
+   break;
+  case DCE_RNG_QCAF: case DCE_QCAF:
+   __dbg_msg("    [%d:%d]: quasi-continuous assign or force load net %s\n",
+    dcep->dci1, dcep->dci2.i, dcep->dce_np->nsym->synam); 
+   break;
+  case DCE_RNG_PVC: case DCE_PVC:
+   __dbg_msg("    [%d:%d]: tf_ parameter value change load net %s\n",
+    dcep->dci1, dcep->dci2.i, dcep->dce_np->nsym->synam); 
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * load a dce edge value with strength removed if attached to stren wire
+ * know 1 bit and does not use itree loc. - gets from 1st instance
+ */
+static word32 get_dce_edgeval(struct mod_t *mdp, struct dcevnt_t *dcep)
+{
+ struct net_t *np;
+ int32 dcewid;
+ byte *sbp;
+ word32 val, aw, bw;
+ struct xstk_t *xsp;
+ 
+ /* here edge always 1 bit */
+ if (dcep->dce_expr != NULL)
+  {
+   __push_wrkitstk(mdp, 0);
+   ld_scalval_(&aw, &bw, dcep->dce_expr->bp);
+   val = (aw & 1L) | ((bw << 1) & 2L);
+   __pop_wrkitstk();
+  }
+ else
+  {
+   np = dcep->dce_np;
+   /* this is low bit of 1st inst. */
+   if (np->n_stren) { sbp = dcep->prevval.bp; val = (word32) (sbp[0] & 3); }
+   else
+    {
+     /* since edge, know low bit used for range */
+     dcewid = __get_dcewid(dcep, np);
+
+     __push_wrkitstk(mdp, 0);
+     /* special case load of perinst value */
+     push_xstk_(xsp, dcewid);
+     __ld_perinst_val(xsp->ap, xsp->bp, dcep->prevval, dcewid);
+     val = (xsp->ap[0] & 1L) | ((xsp->bp[0] << 1) & 2L);
+     __pop_xstk();
+     __pop_wrkitstk();
+    }
+  }
+ return(val);
+}
+
+/*
+ * MISC. VALUE CONVERSION ROUTINES TOO COMPLICATED TO BE MACROS
+ * USED FOR VALUE CONVERSION EVERYWHERE
+ */
+
+/*
+ * trim binary value by changing length (for binary only)
+ * so if all left bits 0, x, or z compute new length
+ *
+ * if all highs 0, trim to highest non 0, if 0 make 1
+ * if all high x or z trim so include 1 high x or z bit
+ * return new trimmed length
+ *
+ * this maybe would be better converting to blen and using that
+ */
+static int32 bin_trim_abval(word32 *ap, word32 *bp, int32 blen)
+{
+ int32 ahigh0, bhigh0;
+ int32 wlen, ubits, trimalen, trimblen;
+
+ /* this adjusts 0 to WBITS */
+ wlen = wlen_(blen);
+ ubits = ubits_(blen);
+ if (ubits == 0) ubits = WBITS;
+ /* notice range for bits is [32:1] */
+ if (bithi_is0(ap[wlen - 1], ubits)) ahigh0 = TRUE; else ahigh0 = FALSE;
+ if (bithi_is0(bp[wlen - 1], ubits)) bhigh0 = TRUE; else bhigh0 = FALSE;
+ /* if high bit 1, cannot trim */
+ if (bhigh0 && !ahigh0) return(blen);
+
+ /* if high bit 0 - len is width where non 0 high a and non 0 highb */
+ /* if high bit z - len is width where non 0 high a and non 1 highb */
+ /* if high bit x - len is width where non 1 high a and non 1 highb */
+ if (ahigh0) trimalen = __trim1_0val(ap, blen);
+ else trimalen = trim1_1val(ap, blen);
+ if (bhigh0) trimblen = __trim1_0val(bp, blen);
+ else trimblen = trim1_1val(bp, blen);
+ blen = (trimalen >= trimblen) ? trimalen : trimblen;
+
+ /* if all 0s, x's, or z's, make 1 bit */
+ if (blen == 0) return(1);
+
+ /* if trimmed x or z always need high x or z */ 
+ if (!bhigh0) return(blen + 1);
+
+ /* trimmed 0's to something */
+ /* if trim 0's to x or z - need the to inc for one extra high 0 */ 
+ wlen = wlen_(blen);
+ ubits = ubits_(blen);
+ if (ubits == 0) ubits = WBITS;
+ /* notice range for bits is [32:1] */
+ /* if trimmed 0's to 1, do not need extra high 1 */
+ if (!bithi_is0(bp[wlen - 1], ubits)) return(blen + 1);
+
+ /* if trimmed 0's to 1, then no extra high 0 */
+ return(blen);
+}
+
+/*
+ * trim a value by changing length so if all left bits 0, x, or z compute
+ * if all highs 0, trim to highest non 0, if 0 make 1
+ * if all high x or z trim so include 1 high x or z bit
+ * return new trimmed length
+ *
+ * this maybe would be better converting to blen and using that
+ */
+static int32 trim_abval(word32 *ap, word32 *bp, int32 blen)
+{
+ int32 ahigh0, bhigh0;
+ int32 wlen, ubits, trimalen, trimblen;
+
+ /* this adjusts 0 to WBITS */
+ wlen = wlen_(blen);
+ ubits = ubits_(blen);
+ if (ubits == 0) ubits = WBITS;
+ /* notice range for bits is [32:1] */
+ if (bithi_is0(ap[wlen - 1], ubits)) ahigh0 = TRUE; else ahigh0 = FALSE;
+ if (bithi_is0(bp[wlen - 1], ubits)) bhigh0 = TRUE; else bhigh0 = FALSE;
+ /* if high bit 1, cannot trim */
+ if (bhigh0 && !ahigh0) return(blen);
+
+ if (ahigh0) trimalen = __trim1_0val(ap, blen);
+ else trimalen = trim1_1val(ap, blen);
+ if (bhigh0) trimblen = __trim1_0val(bp, blen);
+ else trimblen = trim1_1val(bp, blen);
+ blen = (trimalen >= trimblen) ? trimalen : trimblen;
+ /* if all 0s, make 1 bit */
+ if (blen == 0) return(1);
+
+ /* if x or z extension, need 1 extra bit */
+ if (!ahigh0 || !bhigh0) return(blen + 1);
+ return(blen);
+}
+
+/*
+ * return T if bit i is 0 (32 >= i >= 1)
+ */
+static int32 bithi_is0(word32 val, int32 ubits)
+{
+ word32 mask;
+
+ mask = 1L << (ubits - 1);
+ if ((mask & val) == 0L) return(TRUE);
+ return(FALSE);
+}
+
+/* table used by count leading zeros macro */
+static byte clz_tab[] =
+{
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+};
+
+/* notice this routine in 32 bit word32 dependent */
+extern int32 __count_leading_zeros(register word32 xr)
+{
+ register word32 a;
+ register int32 count;
+
+ a = xr < (1L << 16) ? (xr < (1L << 8) ? 0 : 8) : (xr < (1L << 24) ? 16: 24);
+ count = 32 - (clz_tab[xr >> a] + a);
+ return(count);
+}
+
+/*
+ * trim a 0 value - returns new length that is 0 if all 0's
+ * else new trimmed length - know all high unsued bits 0
+ *
+ * this works on either a or b part but not both at once - caller must
+ * combine
+ */
+extern int32 __trim1_0val(word32 *wp, int32 blen)
+{
+ register int32 swi;
+ int32 hbits, wlen;
+
+ /* adjust so blen value as if all bits in high word32 used */
+ wlen = wlen_(blen);
+ /* notice this works from high word32 toward low */
+ for (swi = wlen - 1; swi >= 0; swi--)
+  {
+   if (wp[swi] != 0L)
+    {
+     hbits = __count_leading_zeros(wp[swi]);
+     return(WBITS*(swi + 1) - hbits);
+    }
+  }
+ return(0);
+}
+
+/*
+ * trim a 1 value - returns new length that is 0 if all 1's
+ * know all high unsued bits 1 in value with new length
+ */
+static int32 trim1_1val(word32 *wp, int32 blen)
+{
+ register int32 swi;
+ word32 tmp;
+ int32 wlen, hbits, ubits;
+
+ wlen = wlen_(blen);
+ ubits = ubits_(blen);
+ /* if some bits unused, use mask when inverting for zero count */
+ if (ubits != 0)
+  {
+   wlen--;
+   tmp = ~wp[wlen] & __masktab[ubits];
+   if (tmp != 0L)
+    { hbits = __count_leading_zeros(tmp); return(WBITS*(wlen + 1) - hbits); }
+  }
+ /* notice this works from high word32 toward low */
+ for (swi = wlen - 1; swi >= 0; swi--)
+  {
+   if ((tmp = ~wp[swi]) != 0L)
+    {
+     hbits = __count_leading_zeros(tmp);
+     return(WBITS*(swi + 1) - hbits);
+    }
+  }
+ return(0);
+}
+
+/*
+ * return T if value is all z's
+ */
+extern int32 __vval_isallzs(word32 *ap, word32 *bp, int32 blen)
+{
+ int32 v1, v2;
+
+ /* v1, v2 here for debugging only */
+ v1 = vval_is0_(ap, blen);
+ if (!v1) return(FALSE);
+ v2 = __vval_is1(bp, blen);
+ return(v2);
+}
+
+/*
+ * return T for strength value that is all z's
+ * <0:0=z (i.e. 00000010) is only z value
+ */
+extern int32 __st_vval_isallzs(byte *sbp, int32 blen)
+{
+ register int32 i;
+
+ for (i = 0; i < blen; i++) if (*sbp != 3) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * return T if value is all x's
+ */
+static int32 vval_isall_xs(word32 *ap, word32 *bp, int32 blen)
+{
+ if (!__vval_is1(ap, blen)) return(FALSE);
+ if (!__vval_is1(bp, blen)) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * return T is has any x's, even 1 x implies X, else Z
+ * notice half word32 here ok
+ */
+static int32 vval_hasx(word32 *ap, word32 *bp, int32 blen)
+{
+ register int32 wi;
+
+ for (wi = 0; wi < wlen_(blen); wi++)
+  {
+   if ((ap[wi] & bp[wi]) != 0L) return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * return T if value is all 1's (processes either a or b value not both)
+ * notice half word32 blen here ok
+ */
+extern int32 __vval_is1(register word32 *wp, int32 blen)
+{
+ register int32 i;
+ register word32 mask;
+ int32 wlen;
+
+ wlen = wlen_(blen);
+ for (i = 0; i < wlen - 1; i++) if (wp[i] != ALL1W) return(FALSE);
+ mask = __masktab[ubits_(blen)];
+ if ((wp[wlen - 1] & mask) != mask) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * return T if value is all 0's (processes either a or b value)
+ * passed with 2 word32 length for both a and b values
+ * only for values wider than WBITS
+ * notice must be word32 since 2 word32 length possible
+ *
+ * this is invoked from a macro
+ */
+extern int32 __wide_vval_is0(register word32 *wp, int32 blen)
+{
+ register int32 i;
+
+ for (i = 0; i < wlen_(blen); i++) if (*wp++ != 0L) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * REAL CONVERSION ROUTINES
+ */
+
+/*
+ * convert a 64 bit ver. word32  to a ieee double real value
+ * return F on error - caller can emit warning - d1 as good as possible
+ *
+ * FIXME - since tim now word32 64, maybe can just assign
+ * PORTABLE - assumes IEEE floating point
+ */
+extern int32 __v64_to_real(double *d1, word64 *tim)
+{
+ int32 good;
+ register word32 w0, w1, mask;
+ double dbase;
+
+ /* easy case, fit in 32 bits */
+ w0 = (word32) ((*tim) & WORDMASK_ULL);
+ w1 = (word32) (((*tim) >> 32) & WORDMASK_ULL);
+ if (w1 == 0L) { *d1 = (double) w0; return(TRUE); }
+
+ good = TRUE;
+ /* must fit in mantissa or will lose precision */
+ mask = __masktab[WBITS - (_DEXPLEN + 1)];
+ if ((w1 & ~mask) != 0L) good = FALSE;
+ dbase = ((double) (0xffffffff)) + 1.0; 
+ /* cannot use base 2**32 because conversion to double assumes int32 */
+ /* even if value is word32 */
+ /* conversion from double to word32 works if double is positive */
+ *d1 = (double) w0 + dbase*((double) w1);
+ return(good); 
+}
+
+/*
+ * convert a stack value to a real and 
+ */
+extern double __cnvt_stk_to_real(struct xstk_t *xsp, int32 is_signed)
+{
+ int32 i;
+ word32 u;
+ word64 tim;
+ double d1;
+ 
+ if (!vval_is0_(xsp->bp, xsp->xslen))
+  {
+not_real:
+   __sgfwarn(618,
+    "expression value %s cannot be represented as real - 0.0 used", 
+    __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, is_signed));
+   return(0.0);
+  }
+ if (xsp->xslen > WBITS)
+  {
+   if (xsp->xslen > WBITS && !vval_is0_(&(xsp->ap[2]), xsp->xslen - 64))
+    goto not_real;
+   tim = ((word64) xsp->ap[0]) | (((word64) xsp->ap[1]) << 32);
+   __v64_to_real(&d1, &tim);
+  }
+ else
+  {
+   if (is_signed) { i = (int32) xsp->ap[0]; d1 = (double) i; }
+   else { u = (word32) xsp->ap[0]; d1 = (double) u; } 
+  }
+ return(d1);
+}
+
+/*
+ * routine to unscale from ticks to user time as double
+ * this routine changes value of real
+ * only called if know need to scale
+ */
+extern double __unscale_realticks(word64 *ticksval, struct mod_t *mdp)
+{
+ word32 unit;
+ double d1;
+
+ if (!__v64_to_real(&d1, ticksval))
+  {
+   __sgfwarn(575,
+    "conversion from internal time %s to time as real lost precision",
+    __to_timstr(__xs, ticksval));
+  }
+
+ if (!mdp->mno_unitcnv)
+  {
+   unit = __des_timeprec - mdp->mtime_units;
+   d1 /= __dbl_toticks_tab[unit];
+  }
+ return(d1);
+}
+
+/*
+ * return result of scale function
+ * this must return a double value
+ * even though this does not return xstk, must leave on expr. stack
+ */
+extern void __exec_scale(struct expr_t *fax)
+{
+ int32 unit;
+ double d1; 
+ word64 tval;
+ struct xstk_t *xsp;
+ struct mod_t *from_mdp, *to_mdp;
+   
+ xsp = __eval_xpr(fax);
+ if (xsp->xslen != TIMEBITS) __sizchgxs(xsp, TIMEBITS);  
+ if (xsp->bp[0] != 0L || xsp->bp[1] != 0)
+  {
+   __sgfwarn(629, "$scale time argument bits x or z - scaled to 0.0");
+   d1 = 0.0;
+   goto done;
+  }
+ tval = ((word64) xsp->ap[0]) | (((word64) xsp->ap[1]) << 32);
+ if (!__v64_to_real(&d1, &tval))
+  {
+   __sgfwarn(575,
+    "conversion from $scale time %s to time as real lost precision",
+    __to_timstr(__xs, &tval));
+  }
+ to_mdp = __inst_mod;
+ from_mdp = fax->ru.grp->targmdp;
+ if (from_mdp->mtime_units != to_mdp->mtime_units)
+  {
+   if (from_mdp->mtime_units > to_mdp->mtime_units)
+    {
+     /* here from module more precise (high exponent) - divide */  
+     unit = from_mdp->mtime_units - to_mdp->mtime_units;
+     d1 /= __dbl_toticks_tab[unit];
+    }   
+   else
+    {
+     /* here from module less precise (low exponent) - multiply */  
+     unit = to_mdp->mtime_units - from_mdp->mtime_units;
+     d1 *= __dbl_toticks_tab[unit];
+    }
+  }
+done:
+ memcpy(xsp->ap, &d1, sizeof(double));
+}
+
+/*
+ * wrapper for cnv stk from real to reg32 when reading source
+ * purpose to set up right source line
+ */
+extern void __src_rd_cnv_stk_fromreal_toreg32(struct xstk_t *xsp)
+{
+ int32 sav_slin_cnt, sav_sfnam_ind;
+
+ /* can assign specparam value immediately */
+ /* SJM 06/17/99 - needs to run in run/fixup mode - statement loc set */
+ sav_slin_cnt = __slin_cnt;
+ sav_sfnam_ind = __sfnam_ind;
+ __sfnam_ind = __cur_fnam_ind;
+ __slin_cnt = __lin_cnt;
+
+ __cnv_stk_fromreal_toreg32(xsp);
+
+ /* must put back in case reading iact source */
+ __slin_cnt = sav_slin_cnt;
+ __sfnam_ind = sav_sfnam_ind;
+}
+
+/*
+ * convert an evaluated tos value from real to reg 32 (maybe signed) 
+ * know real will always be WBITS with b part part of real
+ * this routine is 32 bit dependent
+ *
+ * algorith converts real to int32 (32 bit) then move bit pattern to reg32
+ * notice output can be signed
+ */
+extern void __cnv_stk_fromreal_toreg32(struct xstk_t *xsp)
+{
+ double d1; 
+ int32 i;
+
+ memcpy(&d1, xsp->ap, sizeof(double)); 
+ i = ver_rint_(d1);
+ xsp->ap[0] = (word32) i;
+ xsp->bp[0] = 0L;
+}
+
+/*
+ * wrapper for cnv stk from reg to realwhen reading source
+ * purpose to set up right source line
+ */
+extern void __src_rd_cnv_stk_fromreg_toreal(struct xstk_t *xsp, int32 src_signed)
+{
+ int32 sav_slin_cnt, sav_sfnam_ind;
+
+ /* can assign specparam value immediately */
+ /* SJM 06/17/99 - needs to run in run/fixup mode - statement loc set */
+ sav_slin_cnt = __slin_cnt;
+ sav_sfnam_ind = __sfnam_ind;
+ __sfnam_ind = __cur_fnam_ind;
+ __slin_cnt = __lin_cnt;
+
+ __cnv_stk_fromreg_toreal(xsp, src_signed);
+
+ /* must put back in case reading iact source */
+ __slin_cnt = sav_slin_cnt;
+ __sfnam_ind = sav_sfnam_ind;
+}
+
+/*
+ * convert a tos evaluated value from reg to real
+ * need run time warning if does not fit - since if high bits 0 ok
+ * this is real width and word32 width dependent
+ */ 
+extern void __cnv_stk_fromreg_toreal(struct xstk_t *xsp, int32 src_signed)
+{
+ int32 i;
+ word32 w;
+ double d1;
+
+ if ((xsp->xslen > WBITS && !vval_is0_(&(xsp->ap[1]), xsp->xslen - WBITS)) 
+  || !vval_is0_(xsp->bp, xsp->xslen))
+  {
+   __sgfwarn(518,
+    "conversion of %s to real width %d too wide or x/z - converted to 0.0",
+    __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE),
+    xsp->xslen);
+   d1 = 0.0;
+   goto done;
+  }
+ if (src_signed) { i = (int32) xsp->ap[0]; d1 = (double) i;  }
+ else { w = xsp->ap[0]; d1 = (double) w; }
+
+ /* next must adjust stack - know will have enough room */
+done:
+ xsp->bp = &(xsp->ap[1]);
+ xsp->xslen = WBITS;
+ memcpy(xsp->ap, &d1, sizeof(double));
+}
+
+/*
+ * ROUTINES TO IMPLEMENT VERILOG SPECIFIC OR UNPORTABLE MATH LIB
+ */
+
+#define MY_MAXDOUBLE 1.797693134862315708e+308
+/* #define MY_MAXDOUBLE 1.79e+308 */
+#define MY_MINDOUBLE 4.9406564584124654e-324
+#define MY_LONG_MAX 0x7fffffff
+#define MY_LONG_MIN 0x80000000
+
+/*
+ * convert nptr to a double - modified verision of lib. strtod
+ * If endptr is not nil, endptr contains addr of 1 afer end
+ * notice here error EINVAL set even no digits - standard just sets to 0
+ */
+extern double __my_strtod(char *nptr, char **endptr, int32 *errnum)
+{
+ register char *s;
+ short int sign;
+ long int tmpexp;
+ int32 got_dot, got_digit, save;
+ long int exponent;
+ double num;
+ char *end;
+
+ if (nptr == NULL) goto noconv;
+ s = nptr;
+ if (*s == '\0') goto noconv;
+
+ /* skip - know *s is a char from system getc type routinm */
+ while (isspace(*s)) s++;
+ /* get sign */
+ sign = *s == '-' ? -1 : 1;
+ if (*s == '-' || *s == '+') s++;
+
+ num = 0.0;
+ got_dot = 0;
+ got_digit = 0;
+ exponent = 0;
+ for (;; s++)
+  {
+   if (isdigit(*s))
+    {
+     got_digit = 1;
+     /* if too many digits for double rep., ignore but need for for exp */
+     if (num > MY_MAXDOUBLE * 0.1) exponent++;
+      else num = 10.0*num + (*s - '0');
+     /* count digits after exponent */
+     if (got_dot) exponent--;
+    }
+   /* indicate dot seen */
+   else if (!got_dot && *s == '.') got_dot = 1;
+   else break;
+  }
+ /* must be at least 1 digit */
+ if (!got_digit) goto noconv;
+ /* get the exp. */
+ *errnum = 0;
+ if (*s == 'e' || *s == 'E')
+  {
+   save = *errnum;
+   s++;
+   tmpexp = my_strtol(s, &end, TRUE, errnum);
+   if (*errnum == ERANGE)
+    {
+     /* overflow certainly means double exp. limit also exceeded */
+     if (endptr != NULL) *endptr = end;
+     if (tmpexp < 0) goto underflow; else goto overflow;
+    }
+   /* no exponent (e was end of number) */
+   else if (end == s) end = (char *) s - 1;
+   errno = save;
+   s = end;
+   exponent += tmpexp;
+  }
+ if (endptr != NULL) *endptr = s;
+ if (num == 0.0) return(0.0);
+
+ /* multiply int32 part by 10 to exponent as power */ 
+ if (exponent < 0)
+  { if (num < MY_MINDOUBLE * pow(10.0, (double) -exponent)) goto underflow; }
+ else if (exponent > 0)
+  { if (num > MY_MAXDOUBLE * pow(10.0, (double) -exponent)) goto overflow; }
+ num *= pow(10.0, (double) exponent);
+ return(sign*num);
+
+overflow:
+ *errnum = ERANGE;
+ return(sign*MY_MAXDOUBLE);
+
+underflow:
+ if (endptr != NULL) *endptr = nptr;
+ *errnum = ERANGE;
+ return(0.0);
+
+noconv:
+ if (endptr != NULL) *endptr = nptr;
+ *errnum = EINVAL;
+ return(0.0);
+}
+
+/*
+ * convert string to word32 long
+ */
+extern word32 __my_strtoul(char *nptr, char **endptr, int *errnum)
+{
+ word32 ul;
+
+ ul = (word32) my_strtol(nptr, endptr, FALSE, errnum);
+ return(ul);
+}
+
+/*
+ * convert string at nptr to long int and point endptr to 1 past end
+ * notice here error EINVAL set even no digits - standard just sets to 0
+ */
+static long my_strtol(char *nptr, char **endptr, int32 sign, int32 *errnum)
+{
+ register char *s;
+ register unsigned char c;
+ register word32 i;
+ int32 negative;
+ word32 cutoff;
+ word32 cutlim;
+ char *save;
+ int32 overflow;
+
+ s = nptr;
+ /* skip white space */
+ while (isspace(*s)) ++s;
+ if (*s == '\0') goto noconv;
+
+ /* check for a sign */
+ if (*s == '-')
+  {
+   /* word32 can not have sign prefix - maybe should allow and convert */
+   if (!sign) goto noconv;
+   negative = 1;
+   s++;
+  }
+ else if (*s == '+') { negative = 0; s++; }
+ else negative = 0;
+
+ /* save pointer to test for no digits */
+ save = s;
+ /* this is word32 max */
+ cutoff = ALL1W / (word32) 10;
+ cutlim = ALL1W % (word32) 10;
+ for (overflow = 0, i = 0, c = *s; c != '\0'; c = *++s)
+  {
+   if (isdigit(c)) c -= '0'; else break;
+   /* check for overflow */
+   if (i > cutoff || (i == cutoff && c > cutlim)) overflow = 1;
+   else { i *= 10; i += c; }
+  }
+ /* if no progress, error */
+ if (s == save) goto noconv;
+ /* store endptr if user passed non nil */
+ if (endptr != NULL) *endptr = (char *) s;
+
+ /* check for in word32 but outside long int */
+ /* FIXME - what is this supposed to do? */
+ if (sign)
+  {
+   if (i > (negative ? - (word32) MY_LONG_MIN
+    : (unsigned long int) MY_LONG_MAX)) overflow = 1;
+   if (overflow)
+    { *errnum = ERANGE; return(negative ? MY_LONG_MIN : MY_LONG_MAX); }
+  }
+ *errnum = 0;
+ return (negative ? - i : i);
+
+noconv:
+ *errnum = EINVAL;
+ if (endptr != NULL) *endptr = (char *) nptr;
+ return(0L);
+}
+
+/*
+ * ASCII RECONSTRUCTED SOURCE DUMP ROUTINES
+ */
+
+/*
+ * not dumping cap charges
+ * f must not be nil
+ * this requires a current instance (call be in loop for all)
+ */
+extern void __dmp_mod(FILE *f, struct mod_t *mdp)
+{
+ char s1[RECLEN];
+
+ if (f == NULL) __arg_terr(__FILE__, __LINE__);
+ /* if precision changed dump new */
+ if (__cur_units != mdp->mtime_units || __cur_prec != mdp->mtime_prec)
+  {
+   /* replace with new current and write */
+   __cur_units = mdp->mtime_units;
+   __cur_prec = mdp->mtime_prec;
+
+   sprintf(s1, "\n`timescale %s / %s", __to_timunitnam(__xs, __cur_units),
+    __to_timunitnam(__xs2, __cur_units + __cur_prec));
+   __nl_wrap_puts(s1, f);
+  }
+
+ __push_wrkitstk(mdp, 0);
+
+ __pv_stlevel = 0;
+ __outlinpos = 0;
+ __cur_sofs = 0;
+ __wrap_putc('\n', f);
+ /* 04/01/00 SJM - for Verilog 2000 need to dmp digital attributes */
+ if (mdp->mattrs != NULL) { dmp_dig_attr_list(f, mdp->mattrs, TRUE); }
+ __wrap_puts("module ", f);
+ __wrap_puts(mdp->msym->synam, f);
+
+ if (mdp->mod_lofp_decl) dmp_mod_lofp_hdr(f, mdp);
+ else dmp_modports(f, mdp);
+
+ /* know I/O port decls will come first */
+ dmp_decls(f, mdp);
+
+ dmp_paramdecls(f, mdp->mprms, mdp->mprmnum, "parameter");
+ if (mdp->mprms != NULL) { __wrap_putc('\n', f); __outlinpos = 0; }
+
+ dmp_defparams(f, mdp);
+
+ dmp_mdtasks(f, mdp);
+
+ if (mdp->mtasks != NULL) { __wrap_putc('\n', f); __outlinpos = 0; }
+ dbg_dmp_insts(f, mdp);
+
+ if (mdp->mcells != NULL && __outlinpos != 0)
+  { __wrap_putc('\n', f); __outlinpos = 0; }
+ dmp_ialst(f, mdp);
+ if (mdp->ialst != NULL) { __wrap_putc('\n', f); __outlinpos = 0; }
+
+
+ if (mdp->mspfy != NULL)
+  {
+   dmp_mdspfy(f, mdp);
+   if (__outlinpos != 0) { __wrap_putc('\n', f); __outlinpos = 0; }
+  }
+ __nl_wrap_puts("endmodule", f);
+
+ __pv_stlevel = 0;
+ if (__debug_flg)
+  {
+   /* if regression dumping first symbol tables and global tables */
+   dmp_mod_grefs(f, mdp);
+  }
+ __cur_sofs = 0;
+ __pop_wrkitstk();
+}
+
+/*
+ * routine to dump an attribute_instance
+ */
+static void dmp_dig_attr_list(FILE *f, struct attr_t *attr_hd, int32 nd_nl)
+{
+ register struct attr_t *attrp;
+ int32 first_time = TRUE;
+
+ if (nd_nl && __outlinpos != 0) __nl_wrap_puts("", f);
+ __wrap_puts("(* ", f);
+ for (attrp = attr_hd; attrp != NULL; attrp = attrp->attrnxt)
+  {
+   if (first_time) first_time = FALSE; else __wrap_puts(", ", f);
+   __wrap_puts(attrp->attrnam, f);
+   if (attrp->attr_xp != NULL)
+    {
+     __wrap_puts(" = ", f);
+     dmp_expr(f, attrp->attr_xp);
+    }
+  }
+ __wrap_puts(" *)", f);
+ if (nd_nl && __outlinpos != 0) __nl_wrap_puts("", f);
+ else __wrap_puts(" ", f);
+}
+
+/*
+ * dump module ports
+ */
+static void dmp_modports(FILE *f, struct mod_t *mdp)
+{
+ register int32 pi;
+ register struct mod_pin_t *mpp;
+ int32 first_time, pnum;
+
+ first_time = TRUE;
+ __pv_stlevel++;
+ if ((pnum = mdp->mpnum) != 0)
+  {
+   for (pi = 0, mpp = &(mdp->mpins[0]); pi < pnum; pi++, mpp++)
+    {
+     if (first_time) { __wrap_putc('(', f); first_time = FALSE; }
+     else __wrap_puts(", ", f);
+     if (mpp->mp_explicit)
+      {
+       /* un-named but explicit module port stored wrong */
+       /* DBG remove ---
+       if (mpp->mpsnam == NULL)
+        __misc_gfterr( __FILE__, __LINE__, mdp->msym->syfnam_ind,
+         mdp->msym->sylin_cnt);
+       --- */
+       __wrap_putc('.', f);
+       __wrap_puts(mpp->mpsnam, f);
+       __wrap_putc('(', f);
+       dmp_expr(f, mpp->mpref);
+       /* this makes sure (..) always on 1 line */
+      __wrap_putc(')', f);
+      }
+     else dmp_expr(f, mpp->mpref);
+    }
+  }
+ if (!first_time) __wrap_putc(')', f);
+ __nl_wrap_puts(";", f);
+ __pv_stlevel--;
+}
+
+/*
+ * dump new list of ports module ports header
+ */
+static void dmp_mod_lofp_hdr(FILE *f, struct mod_t *mdp)
+{
+ register int32 pi;
+ register struct mod_pin_t *mpp;
+ int32 first_time, pnum;
+ struct net_t *np;
+ char s1[RECLEN];
+
+ first_time = TRUE;
+ __pv_stlevel++;
+ if ((pnum = mdp->mpnum) == 0)
+  {
+   if (!first_time) __wrap_putc(')', f);
+   __nl_wrap_puts(";", f);
+   __pv_stlevel--;
+  }
+
+ for (pi = 0, mpp = &(mdp->mpins[0]); pi < pnum; pi++, mpp++)
+  {
+   if (first_time) { __wrap_putc('(', f); first_time = FALSE; }
+   else __wrap_puts(", ", f);
+
+   /* DBG remove -- */
+   if (mpp->mpref->optyp != ID) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   np = mpp->mpref->lu.sy->el.enp;
+
+   if (np->nattrs != NULL) dmp_dig_attr_list(f, np->nattrs, FALSE);
+
+   __wrap_puts(__to_ptnam(s1, np->iotyp), f);
+
+   if (np->ntyp != N_WIRE)
+    {
+     __wrap_putc(' ', f);
+     __wrap_puts(__to_wtnam(s1, np), f);
+    }
+
+   if (np->n_signed && (np->ntyp != N_INT && np->ntyp != N_REAL
+    && np->ntyp != N_TIME))
+    {
+     __wrap_puts(" signed", f); 
+    }
+
+   /* for special types no range but will have internal range */
+   if (!np->n_isavec || np->ntyp == N_INT || np->ntyp == N_TIME
+    || np->ntyp == N_REAL) strcpy(s1, "");
+   else { __to_wrange(s1, np); __wrap_putc(' ', f); __wrap_puts(s1, f); }
+
+   __wrap_putc(' ', f);
+   __wrap_puts(np->nsym->synam, f);
+  }
+ if (!first_time) __wrap_putc(')', f);
+ __nl_wrap_puts(";", f);
+ __pv_stlevel--;
+}
+
+/* 
+ * dump all i/o and wire declarations for module
+ */
+static void dmp_decls(FILE *f, struct mod_t *mdp)
+{
+ register struct net_t *np;
+ register int32 i;
+ int32 pnum;
+ struct mod_pin_t *mpp;
+
+ __pv_stlevel++;
+ /* first mark all wires not emitted */
+ if (mdp->mnnum != 0)
+  { 
+   for (i = 0, np = &(mdp->mnets[0]); i < mdp->mnnum; np++, i++)
+    np->n_mark = FALSE;
+  }
+
+ if ((pnum = mdp->mpnum) != 0 && !mdp->mod_lofp_decl)
+  {
+   for (i = 0, mpp = &(mdp->mpins[0]); i < pnum; i++, mpp++)
+    dmp_1portdecl(f, mpp->mpref);
+  }
+ if (mdp->mnnum != 0)
+  {
+   /* if use ptr must be sure at least one */
+   /* do not emit decl. for any added nets */
+   for (i = 0, np = &(mdp->mnets[0]); i < mdp->mnnum; i++, np++)
+    dmp_1netdecl(f, np);
+  }
+ __outlinpos = 0;
+ __pv_stlevel--;
+}
+
+/*
+ * dump the required I/O direction declaration for one port net
+ * must declare every wire in expr. as I/O port
+ */
+static void dmp_1portdecl(FILE *f, struct expr_t *ndp)
+{
+ register struct expr_t *catndp;
+ struct net_t *np;
+ char s1[RECLEN];
+
+ switch ((byte) ndp->optyp) {
+  case ID:
+   np = ndp->lu.sy->el.enp;
+emit_decl:
+   /* just a mark here */
+
+   if (!np->n_mark)
+    {
+     __wrap_puts(__to_ptnam(s1, np->iotyp), f);
+     __wrap_putc(' ', f);
+     __wrap_puts(np->nsym->synam, f);
+     __nl_wrap_puts(";", f);
+    }
+   np->n_mark = TRUE;
+   break;
+  case LSB:
+  case PARTSEL:
+   np = ndp->lu.x->lu.sy->el.enp;
+   goto emit_decl;
+  case LCB:
+   {
+    for (catndp = ndp->ru.x; catndp != NULL; catndp = catndp->ru.x)
+     dmp_1portdecl(f, catndp->lu.x);
+   }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * dump 1 net's declarations - may need I/O and wire
+ */
+static void dmp_1netdecl(FILE *f, struct net_t *np)
+{
+ char wnam[RECLEN], s1[IDLEN], s2[RECLEN];
+
+ __outlinpos = 0;
+ strcpy(wnam, "");
+ /* if I/O port is normal wire, do not need wire declaration */
+ if (np->iotyp != NON_IO)
+  {
+   if (__inst_mod->mod_lofp_decl) return;
+   if (!nd_iowirdecl(np)) return;
+  }
+ 
+ /* 04/01/00 SJM - for Verilog 2000 need to dmp digital attributes */
+ if (np->nattrs != NULL) dmp_dig_attr_list(f, np->nattrs, FALSE);
+
+ __wrap_puts(__to_wtnam(wnam, np), f);
+ /* know wire type will be trireg for cap. strength here */
+ if (np->n_capsiz != CAP_NONE)
+  {
+   __wrap_putc(' ', f);
+   __wrap_puts(__to_stren_nam(s1, __fr_cap_size((int32) np->n_capsiz),
+    ST_STRONG), f);
+  }
+ /* never emit scalared/vectored for reg */
+ if (np->n_isavec && np->ntyp < NONWIRE_ST)
+  {
+   if (np->nrngrep == NX_CT)
+    {
+     if (np->nu.ct->n_spltstate == SPLT_SCAL) __wrap_puts(" scalared", f);
+     else if (np->nu.ct->n_spltstate == SPLT_VECT)
+      __wrap_puts(" vectored", f);
+    }
+   else { if (!np->vec_scalared) __wrap_puts(" vectored", f); }
+  }
+
+ /* SJM 10/06/03 - signed if present after vec/scalar */
+ if (np->n_signed && (np->ntyp != N_INT && np->ntyp != N_REAL
+  && np->ntyp != N_TIME))
+  {
+   __wrap_puts(" signed", f); 
+  }
+
+ /* for special types no range but will have internal range */
+ if (!np->n_isavec || np->ntyp == N_INT || np->ntyp == N_TIME
+  || np->ntyp == N_REAL) strcpy(s1, "");
+ else { __to_wrange(s1, np); __wrap_putc(' ', f); __wrap_puts(s1, f); }
+
+ /* these only write something if delay present */
+ if (np->nrngrep == NX_CT) dmp_delay(f, np->nu.ct->n_dels_u,
+  (word32) DT_CMPLST, "#");
+ else if (np->nrngrep == NX_DWIR)
+  dmp_delay(f, np->nu.rngdwir->n_du, np->nu.rngdwir->n_delrep, "#");
+
+ __wrap_putc(' ', f);
+ __wrap_puts(np->nsym->synam, f);
+ if (np->n_isarr) __wrap_puts(__to_arr_range(s2, np), f);
+ __nl_wrap_puts(";", f);
+
+}
+
+/*
+ * return T if need wire decl. for I/O port
+ * know wire only trireg wire type can have strength and need decl.
+ *
+ * default wire type in Verilog already handled because undeclared wires
+ * will be assigned default wire type
+ */
+static int32 nd_iowirdecl(struct net_t *np)
+{
+ if (np->n_isavec || np->n_isarr || np->nattrs != NULL) return(TRUE);
+
+ /* SJM 10/06/03 - if signed but not integer/real/time, need signed decl */ 
+ if (np->n_signed && (np->ntyp != N_INT && np->ntyp != N_REAL
+  && np->ntyp != N_TIME)) return(TRUE);
+
+ if (np->nrngrep == NX_CT)
+  {
+   /* scalared is the default and impossible for regs */
+   if (np->nu.ct->n_spltstate == SPLT_VECT) return(TRUE);
+   if (np->nu.ct->n_dels_u.pdels != NULL) return(TRUE);
+  }
+ else
+  {
+   if (!np->vec_scalared) return(TRUE);
+   if (np->nrngrep == NX_DWIR && np->nu.rngdwir->n_delrep != DT_PTHDST)
+    return(TRUE);
+  }
+ if (np->ntyp != N_WIRE) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * dump locally declared param declarations
+ * this does not work if f == NULL - does nothing
+ */
+static void dmp_paramdecls(FILE *f, struct net_t *parm_nptab, int32 pnum,
+ char *pclassnam)
+{
+ register int32 pi;
+ int32 varwid, base;
+ struct net_t *parm_np;
+ struct xstk_t *xsp;
+ char s1[RECLEN], s2[RECLEN];
+
+ __pv_stlevel++;
+ for (pi = 0; pi < pnum; pi++)
+  {
+   parm_np = &(parm_nptab[pi]);
+
+   __wrap_puts(pclassnam, f);
+   /* FIXME - should emit according to exact source */
+   if (parm_np->nu.ct->ptypdecl || parm_np->nu.ct->prngdecl)
+    {
+     /* always emit vector declaration even if not in source */
+     if (parm_np->nu.ct->ptypdecl)
+      {
+       /* SJM 10/06/03 - know signed keyword can't have been used for these */
+       if (parm_np->ntyp == N_REAL) strcpy(s1, " real");
+       else if (parm_np->ntyp == N_INT) strcpy(s1, " integer");
+       else if (parm_np->ntyp == N_TIME) strcpy(s1, " time");
+       else __case_terr(__FILE__, __LINE__);
+       __wrap_puts(s1, f);
+      }
+     else if (parm_np->nu.ct->prngdecl)
+      {
+       /* SJM 10/06/03 - signed and range can be declared together */ 
+       if (parm_np->nu.ct->psigndecl) __wrap_puts(" signed", f);
+       if (parm_np->n_isavec)
+        {
+         __wrap_putc(' ', f);
+         __to_wrange(s1, parm_np);
+         __wrap_puts(s1, f);
+        }
+      } 
+    }
+   /* SJM 10/06/03 - signed without range possible - rhs range used */
+   else if (parm_np->nu.ct->psigndecl) __wrap_puts(" signed", f);
+
+   __wrap_putc(' ', f);
+   __wrap_puts(parm_np->nsym->synam, f);
+   /* for specify never array and only array if decled */
+   if (parm_np->n_isarr)
+    {
+     __wrap_puts(__to_arr_range(s2, parm_np), f);
+     __wrap_puts(" = ", f);
+     dmp_expr(f, parm_np->nu.ct->n_dels_u.d1x);
+     __nl_wrap_puts(";", f);
+     continue;
+    }
+
+   __wrap_puts(" = ", f);
+   /* should probably dump wire range here */
+   varwid = __get_netwide(parm_np);
+   push_xstk_(xsp, varwid);
+   __ld_wire_val(xsp->ap, xsp->bp, parm_np);
+   
+   /* since need to parse this if x/z, need [size]'b form */
+   if (parm_np->nu.ct->pstring)
+    {
+     __xline_vval_to_cstr(xsp->ap, xsp->xslen, TRUE, TRUE, FALSE);
+    }
+   else
+    {
+     base = parm_np->nu.ct->pbase;
+     __regab_disp(xsp->ap, xsp->bp, xsp->xslen, base, TRUE,
+      (parm_np->n_signed == 1));
+    }
+   __pop_xstk();
+   __wrap_puts(__exprline, f);
+
+   __nl_wrap_puts(";", f);
+   /* know f not nil or will not get here */
+   __cur_sofs = 0;
+  }
+ __pv_stlevel--;
+}
+
+
+/*
+ * dump defparam statements (module items)
+ * if output time becomes a problem could build index since in order
+ */
+static void dmp_defparams(FILE *f, struct mod_t *mdp)
+{
+ register int32 i;
+ struct dfparam_t *dfpp;
+ struct itree_t *itp;
+
+ __pv_stlevel++;
+ for (dfpp = __dfphdr; dfpp != NULL; dfpp = dfpp->dfpnxt)
+  {
+   if (dfpp->in_mdp != mdp) continue;
+   __wrap_puts("defparam ", f);
+   if (dfpp->dfp_local) __wrap_puts(dfpp->gdfpnam, f);
+   else
+    {
+     /* this prints the after splitting form */
+     /* always printed rooted but source may have been downward */
+     itp = __it_roots[dfpp->dfpiis[0]];
+     for (i = 0;;)
+      {
+       if (i > 0) __wrap_putc('.', f);
+       /* must be on one line no matter how long */
+       __wrap_puts(itp->itip->isym->synam, f);
+       if (++i > dfpp->last_dfpi) break;
+       itp = &(itp->in_its[dfpp->dfpiis[i]]);
+      }
+     if (i > 0) __wrap_putc('.', f);
+     __wrap_puts(dfpp->targsyp->synam, f);
+     /* must be on one line no matter how long */
+    }
+   __wrap_puts(" = ", f);
+   dmp_expr(f, dfpp->dfpxrhs);
+   __nl_wrap_puts(";", f);
+  }
+ __pv_stlevel--;
+}
+
+/*
+ * dump tasks and functions - named blocks dumped inline
+ */
+static void dmp_mdtasks(FILE *f, struct mod_t *mdp)
+{
+ register struct task_t *tskp;
+
+ for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+   if (tskp->tsktyp == FUNCTION || tskp->tsktyp == TASK) dmp_task(f, tskp);
+  }
+}
+
+/*
+ * dump module instances and gates
+ * notice by here cells gone and split into insts and gates
+ *
+ * normal version that dumps g/i arrays as vectors
+ */
+static void dmp_insts(FILE *f, struct mod_t *mdp)
+{
+ register int32 ii, gi, cai;
+ register struct giarr_t *giap;
+ struct gate_t *gp;
+ register struct conta_t *cap;
+ struct inst_t *ip;
+
+ __outlinpos = 0;
+ __pv_stlevel++;
+ for (ii = 0; ii < mdp->minum;)
+  {
+   if (mdp->miarr != NULL && (giap = mdp->miarr[ii]) != NULL)
+    {
+     ip = &(mdp->minsts[ii]);
+     dmp_1inst(f, ip, giap);
+     ii += __get_giarr_wide(giap);
+    }
+   else
+    {
+     dmp_1inst(f, &(mdp->minsts[ii]), NULL);
+     ii++;
+    }
+  }
+ for (gi = 0; gi < mdp->mgnum;)
+  {
+   if (mdp->mgarr != NULL && (giap = mdp->mgarr[gi]) != NULL)
+    {
+     gp = &(mdp->mgates[gi]);
+     dmp_1gate(f, gp, giap);
+     gi += __get_giarr_wide(giap);
+    }
+   else
+    {
+     dmp_1gate(f, &(mdp->mgates[gi]), NULL);
+     gi++;
+    } 
+  }
+ for (cap = &(mdp->mcas[0]), cai = 0; cai < mdp->mcanum; cai++, cap++)
+  dmp_1conta(f, cap);
+ __pv_stlevel--;
+}
+
+
+/*
+ * dump 1 module instance
+ */
+static void dmp_1inst(FILE *f, struct inst_t *ip, struct giarr_t *giap)
+{
+ struct mod_t *imdp;
+ char s1[RECLEN];
+
+ __wrap_puts(ip->imsym->synam, f);
+ /* this writes nothing if no # style passed set defparams */
+ imdp = ip->imsym->el.emdp;
+ if (ip->ipxprtab != NULL) dmp_pnd_params(f, ip, imdp);
+
+ /* know modules always named */
+ __wrap_putc(' ', f);
+ __wrap_puts(ip->isym->synam, f);
+
+ /* if giap non nil - emit range */
+ if (giap != NULL)
+  {
+   if (__debug_flg)
+    {
+     sprintf(s1, " [%d:%d]", giap->gia1, giap->gia2);
+     __wrap_puts(s1, f);
+    }
+   else
+    {
+     __wrap_puts(" [", f);
+     dmp_expr(f, giap->giax1);
+     __wrap_putc(':', f);
+     dmp_expr(f, giap->giax2);
+     __wrap_putc(']', f);
+    }
+   dmp_iports(f, ip, giap->giapins);
+  }
+ else dmp_iports(f, ip, ip->ipins);
+}
+
+/*
+ * dump instance pound params
+ */
+static void dmp_pnd_params(FILE *f, struct inst_t *ip, struct mod_t *imdp)
+{
+ register int32 pi;
+ int32 first_time;
+ struct expr_t *pxp;
+ struct net_t *modnp;
+
+ __force_base = BDEC;
+ __wrap_puts(" #(", f);
+ if (impl_pndparams(ip, imdp))
+  {
+   for (first_time = TRUE, pi = 0; pi < imdp->mprmnum; pi++) 
+    {
+     pxp = ip->ipxprtab[pi];
+     /* this handles missing tail params */
+     if (pxp == NULL) break;
+     modnp = &(imdp->mprms[pi]);
+
+     if (first_time) first_time = FALSE; else __wrap_puts(", ", f);
+     if (__debug_flg)
+      {
+       int32 wid, base;
+       struct xstk_t *xsp;
+       char s1[RECLEN];
+   
+       wid = __get_netwide(modnp);
+       push_xstk_(xsp, wid);
+       __ld_wire_val(xsp->ap, xsp->bp, modnp);
+
+       /* since need to parse this if x/z, need [size]'b form */
+       if (modnp->nu.ct->pstring)
+        {
+         __xline_vval_to_cstr(xsp->ap, xsp->xslen, TRUE, TRUE, FALSE);
+        }
+       else
+        {
+         base = modnp->nu.ct->pbase;
+         if (base == BHEX)
+          { sprintf(s1, "%d'h", xsp->xslen); __wrap_puts(s1, f); }
+         __regab_disp(xsp->ap, xsp->bp, xsp->xslen, base, TRUE,
+          (modnp->n_signed == 1));
+        }
+       __pop_xstk();
+       __wrap_puts(__exprline, f);
+       /* know f not nil or will not get here */
+       __cur_sofs = 0;
+      }
+     else dmp_expr(f, pxp);
+    }
+  }
+ else
+  {
+   for (first_time = TRUE, pi = 0; pi < imdp->mprmnum; pi++) 
+    {
+     pxp = ip->ipxprtab[pi];
+     /* this handles missing embedded or tail */
+     if (pxp == NULL) continue;
+     modnp = &(imdp->mprms[pi]);
+
+     if (first_time) first_time = FALSE; else __wrap_puts(", ", f);
+     __wrap_putc('.', f);
+     __wrap_puts(modnp->nsym->synam, f);
+     __wrap_putc('(', f);
+     if (__debug_flg)
+      {
+       int32 wid, base;
+       struct xstk_t *xsp;
+       char s1[RECLEN];
+   
+       wid = __get_netwide(modnp);
+       push_xstk_(xsp, wid);
+       __ld_wire_val(xsp->ap, xsp->bp, modnp);
+
+       /* since need to parse this if x/z, need [size]'b form */
+       if (modnp->nu.ct->pstring)
+        {
+         __xline_vval_to_cstr(xsp->ap, xsp->xslen, TRUE, TRUE, FALSE);
+        }
+       else
+        {
+         base = modnp->nu.ct->pbase;
+         if (base == BHEX)
+          { sprintf(s1, "%d'h", xsp->xslen); __wrap_puts(s1, f); }
+         __regab_disp(xsp->ap, xsp->bp, xsp->xslen, base, TRUE,
+          (modnp->n_signed == 1));
+        }
+       __pop_xstk();
+       __wrap_puts(__exprline, f);
+       /* know f not nil or will not get here */
+       __cur_sofs = 0;
+      }
+     else dmp_expr(f, pxp);
+     __wrap_putc(')', f);
+    }
+  }
+ __wrap_putc(')', f);
+ __force_base = BNONE;
+}
+
+/*
+ * return T if can use implicit form for instance pound params 
+ *
+ * only called if at least 1 pound param
+ * either all present in ip expr table or only tail missing
+ */
+static int32 impl_pndparams(struct inst_t *ip, struct mod_t *imdp)
+{
+ register int32 pi, pi2;
+ struct expr_t *pxp;
+
+ imdp = ip->imsym->el.emdp; 
+ for (pi2 = imdp->mprmnum - 1; pi2 >= 0; pi2--)
+  {
+   pxp = ip->ipxprtab[pi2];
+   if (pxp != NULL) break;
+  }  
+ /* DBG remove --- */
+ if (pi2 < 0) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ for (pi = 0; pi < pi2; pi++)
+  {
+   pxp = ip->ipxprtab[pi];
+   /* once missing tail sequence eliminated, if any missing need explicit */
+   if (pxp == NULL) return(FALSE); 
+  }
+ return(TRUE);
+}
+
+/*
+ * dump module instances and gates
+ * unused DBG version that dump each bit
+ */
+/* DBG --- */ 
+static void dbg_dmp_insts(FILE *f, struct mod_t *mdp)
+{
+ register int32 ii, gi, cai;
+ register struct conta_t *cap;
+ int32 slen;
+ struct gate_t *gp;
+ struct inst_t *ip;
+ char *chp, s1[IDLEN];
+
+ __outlinpos = 0;
+ __pv_stlevel++;
+ for (ii = 0; ii < mdp->minum; ii++)
+  {
+   ip = &(mdp->minsts[ii]);
+   /* 04/01/00 SJM - for Verilog 2000 need to dmp digital attributes */
+   if (ip->iattrs != NULL) dmp_dig_attr_list(f, ip->iattrs, FALSE);
+   if (mdp->miarr != NULL && mdp->miarr[ii] != NULL)
+    {
+     strcpy(s1, ip->isym->synam);
+     if ((chp = strrchr(s1, '[')) == NULL) __arg_terr(__FILE__, __LINE__);
+     *chp = '$'; 
+     slen = strlen(s1);
+     s1[slen - 1] = '$';
+    }
+   else strcpy(s1, ip->isym->synam);
+   dbg_dmp_1inst(f, ip, s1);
+  }
+ for (gi = 0; gi < mdp->mgnum; gi++)
+  {
+   gp = &(mdp->mgates[gi]);
+   /* 04/01/00 SJM - for Verilog 2000 need to dmp digital attributes */
+   if (gp->gattrs != NULL) dmp_dig_attr_list(f, gp->gattrs, FALSE);
+
+   if (mdp->mgarr != NULL && mdp->mgarr[gi] != NULL)
+    {
+     strcpy(s1, gp->gsym->synam);
+     if ((chp = strrchr(s1, '[')) == NULL) __arg_terr(__FILE__, __LINE__);
+     *chp = '$'; 
+     slen = strlen(s1);
+     s1[slen - 1] = '$';
+    }
+   else strcpy(s1, gp->gsym->synam);
+
+   dbg_dmp_1gate(f, gp, s1);
+  }
+ for (cap = &(mdp->mcas[0]), cai = 0; cai < mdp->mcanum; cai++, cap++)
+  dmp_1conta(f, cap);
+ __pv_stlevel--;
+}
+
+/* --- */
+
+/*
+ * dump 1 module instance
+ */
+/* DBG --- */ 
+static void dbg_dmp_1inst(FILE *f, struct inst_t *ip, char *inam)
+{
+ struct mod_t *imdp;
+
+ __wrap_puts(ip->imsym->synam, f);
+ imdp = ip->imsym->el.emdp;
+ if (ip->ipxprtab != NULL) dmp_pnd_params(f, ip, imdp);
+
+ __wrap_putc(' ', f);
+ __wrap_puts(inam, f);
+ dmp_iports(f, ip, ip->ipins);
+}
+/* --- */
+
+/*
+ * dump an instance port connection list
+ */
+static void dmp_iports(FILE *f, struct inst_t *ip, struct expr_t **iptab)
+{
+ register int32 pi;
+ register struct mod_pin_t *mpp;
+ int32 first_time, pnum;
+ struct expr_t *cxp;
+ struct mod_t *mdp;
+
+ __wrap_putc('(', f);
+ first_time = TRUE;
+ mdp = ip->imsym->el.emdp;
+ if ((pnum = mdp->mpnum) == 0) { __nl_wrap_puts(");", f); return; }
+
+ mpp = &(mdp->mpins[0]);
+ if (ip->ip_explicit)
+  {
+   for (pi = 0; pi < pnum; pi++, mpp++)
+    {
+     if (first_time) first_time = FALSE; else __wrap_puts(", ", f);
+     /* even if explicit, if error and no info make implicit */
+     cxp = iptab[pi];
+     if (mpp->mpsnam != NULL)
+      {
+       __wrap_putc('.', f); 
+       __wrap_puts(mpp->mpsnam, f);
+       __wrap_putc('(', f); 
+       dmp_expr(f, cxp);
+       __wrap_putc(')', f);
+      }
+     else dmp_expr(f, cxp);
+    }
+  }
+ else
+  {
+   for (pi = 0; pi < pnum; pi++)
+    {
+     if (first_time) first_time = FALSE; else __wrap_puts(", ", f);
+     /* even if explicit, if error and no info make implicit */
+     cxp = iptab[pi];
+     dmp_expr(f, cxp);
+    }
+  }
+ __nl_wrap_puts(");", f);
+}
+
+/*
+ * dump 1 gate - source dumping after output net/bit setting in v_fx
+ */
+static void dmp_1gate(FILE *f, struct gate_t *gp, struct giarr_t *giap)
+{
+ register int32 pi;
+ int32 gid, first_time;
+ char s1[RECLEN];
+
+ /* 1 bit continous assign simulated as gate must be dumped as ca */
+ if (gp->g_class == GC_LOGIC)
+  {
+   gid = gp->gmsym->el.eprimp->gateid;
+   if (gid == G_ASSIGN) { dmp_1bitconta(f, gp); return; }
+  }
+
+ /* normal primitive */
+ __wrap_puts(gp->gmsym->synam, f);
+ /* know by here if strength on mod. inst. will have emitted error */
+ if (gp->g_hasst)
+  {
+   __wrap_putc(' ', f);
+   __wrap_puts(__to_stval_nam(s1, gp->g_stval), f);
+  }
+ dmp_delay(f, gp->g_du, gp->g_delrep, "#");
+
+ /* if unnamed (system generated name) do not emit inst. name */
+ if (!gp->g_unam)
+  {
+   __wrap_putc(' ', f);
+   __wrap_puts(gp->gsym->synam, f);
+  }
+
+ if (giap != NULL)
+  {
+   if (__debug_flg)
+    {
+     sprintf(s1, " [%d:%d]", giap->gia1, giap->gia2);
+     __wrap_puts(s1, f);
+    }
+   else
+    {
+     __wrap_puts(" [", f);
+     dmp_expr(f, giap->giax1);
+     __wrap_putc(':', f);
+     dmp_expr(f, giap->giax2);
+     __wrap_putc(']', f);
+    }
+  }
+ __wrap_putc('(', f);
+ for (first_time = TRUE, pi = 0; pi < (int32) gp->gpnum; pi++)
+  {
+   if (first_time) first_time = FALSE; else __wrap_puts(", ", f);
+   if (giap != NULL) dmp_expr(f, giap->giapins[pi]);
+   else dmp_expr(f, gp->gpins[pi]);
+  }
+ __nl_wrap_puts(");", f);
+}
+
+/*
+ * dbg dump 1 gate - source dumping after output net/bit setting in v_fx
+ */
+/* DBG --- */
+static void dbg_dmp_1gate(FILE *f, struct gate_t *gp, char *gnam)
+{
+ register int32 pi;
+ int32 gid, first_time;
+ char s1[RECLEN];
+
+ if (gp->g_class == GC_LOGIC)
+  {
+   gid = gp->gmsym->el.eprimp->gateid;
+   if (gid == G_ASSIGN) { dmp_1bitconta(f, gp); return; }
+  }
+
+ __wrap_puts(gp->gmsym->synam, f);
+ if (gp->g_hasst)
+  {
+   __wrap_putc(' ', f);
+   __wrap_puts(__to_stval_nam(s1, gp->g_stval), f);
+  }
+ dmp_delay(f, gp->g_du, gp->g_delrep, "#");
+
+ if (!gp->g_unam)
+  {
+   __wrap_putc(' ', f);
+   __wrap_puts(gnam, f);
+  }
+ __wrap_putc('(', f);
+ for (first_time = TRUE, pi = 0; pi < (int32) gp->gpnum; pi++)
+  {
+   if (first_time) first_time = FALSE; else __wrap_puts(", ", f);
+   /* this dumps post expanded pins */
+   dmp_expr(f, gp->gpins[pi]);
+  }
+ __nl_wrap_puts(");", f);
+}
+/* --- */
+
+/*
+ * dump 1 cont. assign
+ */
+static void dmp_1conta(FILE *f, struct conta_t *cap)
+{
+ char s1[RECLEN];
+
+ /* continous assign:  assign #(delay) lhs = rhs; */
+ __wrap_puts("assign", f);
+ if (cap->ca_hasst)
+  {
+   __wrap_putc(' ', f);
+   __wrap_puts(__to_stval_nam(s1, cap->ca_stval), f);
+  }
+ dmp_delay(f, cap->ca_du, cap->ca_delrep, "#");
+ __wrap_putc(' ', f);
+
+ dmp_expr(f, cap->lhsx);
+ __wrap_puts(" = ", f);
+ dmp_expr(f, cap->rhsx);
+ __nl_wrap_puts(";", f);
+}
+
+/*
+ * dump a 1 bit continuous assign strored as a gate
+ */
+static void dmp_1bitconta(FILE *f, struct gate_t *gp)
+{
+ char s1[RECLEN];
+
+ /* continous assign:  assign #(delay) lhs = rhs; */
+ __wrap_puts("assign", f);
+ if (gp->g_hasst)
+  { __wrap_putc(' ', f); __wrap_puts(__to_stval_nam(s1, gp->g_stval), f); }
+ dmp_delay(f, gp->g_du, gp->g_delrep, "#");
+ __wrap_putc(' ', f);
+ dmp_expr(f, gp->gpins[0]);
+ __wrap_puts(" = ", f);
+ dmp_expr(f, gp->gpins[1]);
+ __nl_wrap_puts(";", f);
+}
+
+/*
+ * routine to dump all initial and always statements
+ */
+static void dmp_ialst(FILE *f, struct mod_t *mdp)
+{
+ struct ialst_t *ialp;
+
+ for (ialp = mdp->ialst; ialp != NULL; ialp = ialp->ialnxt)
+  {
+   if (__outlinpos != 0) __nl_wrap_puts("", f);
+   __pv_stlevel++;
+   if (ialp->iatyp == ALWAYS) __wrap_puts("always ", f);
+   else __wrap_puts("initial ", f);
+   dmp_lstofsts(f, ialp->iastp);
+   __pv_stlevel--;
+  }
+}
+
+/*
+ * routine to reconstruct and write one statement
+ * this routine can take nill to build entire statement in string
+ *
+ * notice this cannot be called with f== nil
+ */
+extern void __dmp_stmt(FILE *f, struct st_t *stp, int32 nd_nl)
+{
+ struct st_t *stp2;
+ struct for_t *frs;
+ struct task_t *tskp;
+ struct st_t *gtstp;
+
+ if (f == NULL) __arg_terr(__FILE__, __LINE__);
+ if (nd_nl == NL && __outlinpos != 0) __nl_wrap_puts("", f);
+ switch ((byte) stp->stmttyp) {
+  case S_NULL:
+   __wrap_putc(';', f);
+   if (__debug_flg) __wrap_puts("** S_NULL **", f);
+   break;
+  case S_STNONE:
+   /* none is place holder for empty block, emit nothing */
+   if (__debug_flg) __wrap_puts("** S_STNONE **", f);
+   break;
+  case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA:
+   __dmp_proc_assgn(f, stp, (struct delctrl_t *) NULL, FALSE);
+   break;
+  case S_NBPROCA:
+   __dmp_nbproc_assgn(f, stp, (struct delctrl_t *) NULL);
+   break;
+  case S_IF:
+   __wrap_puts("if (", f);
+   dmp_expr(f, stp->st.sif.condx);
+   __wrap_puts(") ", f);
+   dmp_lstofsts(f, stp->st.sif.thenst);
+   if (stp->st.sif.elsest != NULL)
+    {
+     if (f != NULL && __outlinpos != 0) __nl_wrap_puts("", f); 
+     __wrap_puts("else ", f);
+     dmp_lstofsts(f, stp->st.sif.elsest);
+    }
+   break;
+  case S_CASE:
+   dmp_case(f, stp);
+   break;
+  case S_FOREVER:
+   __wrap_puts("forever ", f);
+   dmp_lstofsts(f, stp->st.swh.lpst);
+   break;
+  case S_REPEAT:
+   __wrap_puts("repeat (", f);
+   dmp_expr(f, stp->st.srpt.repx);
+   __wrap_puts(") ", f);
+   dmp_lstofsts(f, stp->st.srpt.repst);
+   break;
+  case S_WHILE:
+   __wrap_puts("while (", f);
+   dmp_expr(f, stp->st.swh.lpx);
+   __wrap_puts(") ", f);
+   dmp_lstofsts(f, stp->st.swh.lpst);
+   break;
+  case S_WAIT:
+   __wrap_puts("wait (", f);
+   dmp_expr(f, stp->st.swait.lpx);
+   __wrap_puts(") ", f);
+   dmp_lstofsts(f, stp->st.swait.lpst);
+   break;
+  case S_FOR:
+   frs = stp->st.sfor;
+   __dmp_forhdr(f, frs);
+   dmp_lstofsts(f, frs->forbody);
+   break;
+  case S_DELCTRL:
+   __dmp_dctrl(f, stp->st.sdc);
+   break;
+  case S_NAMBLK:
+   /* indent block and statements within */
+   __pv_stlevel++;
+   tskp = stp->st.snbtsk;
+   dmp_task(f, tskp);
+   __pv_stlevel--;
+   break;
+  case S_UNBLK:
+   if (f != NULL && nd_nl == NONL && __outlinpos != 0) __nl_wrap_puts("", f);
+   __pv_stlevel++;
+   if (f != NULL) __nl_wrap_puts("begin", f);
+   __pv_stlevel++;
+   for (stp2 = stp->st.sbsts; stp2 != NULL; stp2 = stp2->stnxt) 
+    __dmp_stmt(f, stp2, NL);
+   __pv_stlevel--;
+   if (f != NULL && __outlinpos != 0) __nl_wrap_puts("", f);
+   __nl_wrap_puts("end", f);
+   __pv_stlevel--;
+   break;
+  case S_UNFJ:
+   /* only place unnamed blocks (not statements lists) is fork-join */  
+   if (f != NULL && nd_nl == NONL && __outlinpos != 0) __nl_wrap_puts("", f);
+   __pv_stlevel++;
+   if (f != NULL) __nl_wrap_puts("fork", f);
+   __pv_stlevel++;
+   dmp_fj_stlst(f, stp);
+   __pv_stlevel--;
+   if (f != NULL && __outlinpos != 0) __nl_wrap_puts("", f);
+   __nl_wrap_puts("join", f);
+   __pv_stlevel--;
+   break;
+  case S_TSKCALL:
+   __dmp_tskcall(f, stp);
+   break;
+  case S_QCONTA:
+   if (stp->st.sqca->qcatyp == ASSIGN) __wrap_puts("assign ", f);
+   else __wrap_puts("force ", f);
+   dmp_expr(f, stp->st.sqca->qclhsx);
+   __wrap_puts(" = ", f);
+   dmp_expr(f, stp->st.sqca->qcrhsx);
+   __wrap_putc(';', f);
+   break;
+  case S_QCONTDEA:
+   if (stp->st.sqcdea.qcdatyp == DEASSIGN) __wrap_puts("deassign ", f);
+   else __wrap_puts("release ", f);
+   dmp_expr(f, stp->st.sqcdea.qcdalhs);
+   __wrap_putc(';', f);
+   break;
+  case S_CAUSE:
+   __wrap_puts("->", f);
+   /* this will print global ref. if needed */
+   dmp_expr(f, stp->st.scausx);
+   __wrap_putc(';', f);
+   break;
+  case S_DSABLE:
+   __wrap_puts("disable ", f);
+   dmp_expr(f, stp->st.sdsable.dsablx);
+   __wrap_putc(';', f);
+   break;
+  case S_REPSETUP:
+   if (__debug_flg) __wrap_puts("**added setup for repeat**", f);
+   break;
+  case S_REPDCSETUP:
+   if (__debug_flg) __wrap_puts("**added repeat event control setup**", f);
+   break;
+  case S_GOTO:
+   if (__debug_flg)
+    {
+     char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[RECLEN];
+
+     gtstp = stp->st.sgoto;
+     /* DBG remove -- */
+     if (gtstp == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     sprintf(s1,
+      "** add goto at %s [lpend=%0d,dc=%0d,lstend=%0d,dst=%0d] targ %s at %s [lpend=%0d,dc=%0d,lstend=%0d,dst=%0d]",
+      __bld_lineloc(s2, stp->stfnam_ind, stp->stlin_cnt),
+      stp->lpend_goto, stp->dctrl_goto, stp->lstend_goto, stp->lpend_goto_dest,
+      __to_sttyp(s3, gtstp->stmttyp),
+      __bld_lineloc(s4, gtstp->stfnam_ind, gtstp->stlin_cnt),
+      gtstp->lpend_goto, gtstp->dctrl_goto, gtstp->lstend_goto,
+      gtstp->lpend_goto_dest);
+     __wrap_puts(s1, f);
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+  }
+}
+
+/*
+ * dump a case statement
+ * notice that now only place for expr lst is case selector lists
+ * notice this routine cannot take f == nil, not need and tricky formatting
+ */
+static void dmp_case(FILE *f, struct st_t *stp)
+{
+ register struct csitem_t *csip;
+ register struct exprlst_t *xplp;
+ int32 first_time;
+ struct csitem_t *dflt_csip;
+
+ /* dump the case selector */
+ dmp_casesel(f, stp);
+ dflt_csip = stp->st.scs.csitems;
+ csip = dflt_csip->csinxt;
+ __pv_stlevel++;
+ for (; csip != NULL; csip = csip->csinxt)
+  {
+   if (__outlinpos != 0) { __wrap_putc('\n', f); __outlinpos = 0; }
+   first_time = TRUE;
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     if (first_time) first_time = FALSE; else __wrap_puts(", ", f);
+     dmp_expr(f, xplp->xp);
+    }
+   __wrap_putc(':', f);
+   dmp_lstofsts(f, csip->csist);
+  }
+ if (__outlinpos != 0) { __wrap_putc('\n', f); __outlinpos = 0; }
+ if (dflt_csip->csist != NULL) dmp_case_dflt(f, dflt_csip);
+ __pv_stlevel--;
+ if (__outlinpos != 0) __nl_wrap_puts("", f);
+ __nl_wrap_puts("endcase", f);
+}
+
+/*
+ * dump default
+ */
+static void dmp_case_dflt(FILE *f, struct csitem_t *dflt_csip)
+{
+ __outlinpos = 0;
+ __wrap_puts("default:", f);
+ if (dflt_csip->csist != NULL) dmp_lstofsts(f, dflt_csip->csist);
+}
+
+/*
+ * dump a fj statement list - enclosing stuff done elsewhere
+ */
+static void dmp_fj_stlst(FILE *f, struct st_t *stp)
+{
+ register int32 fji;
+ register struct st_t *fjstp;
+
+ for (fji = 0;; fji++)
+  {
+   if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+
+   /* SJM 09/24/01 - can have 2 stmt if for assign and other inserted */
+   if (fjstp->rl_stmttyp == S_REPSETUP || fjstp->rl_stmttyp == S_FORASSGN
+    || fjstp->rl_stmttyp == S_REPDCSETUP) fjstp = fjstp->stnxt;
+
+   __dmp_stmt(f, fjstp, NL);
+  }
+}
+
+/*
+ * dump a task or function declartion
+ */
+static void dmp_task(FILE *f, struct task_t *tskp)
+{
+ struct sy_t *syp;
+
+ syp = tskp->tsksyp;
+ switch ((byte) tskp->tsktyp) {
+  case TASK:
+   if (__outlinpos != 0) __nl_wrap_puts("", f);
+   __nl_wrap_puts("", f);
+   __wrap_puts("task ", f);
+   __wrap_puts(syp->synam, f);
+
+   if (tskp->tf_lofp_decl) dmp_tf_lofp_hdr(f, tskp);
+   __wrap_putc(';', f);
+
+   dmp_tfdecls(f, tskp);
+   dmp_paramdecls(f, tskp->tsk_prms, tskp->tprmnum, "parameter");
+   dmp_lstofsts(f, tskp->tskst);
+   if (__outlinpos != 0) __nl_wrap_puts("", f);
+   __nl_wrap_puts("endtask", f);
+   break;
+  case FUNCTION:
+   dmp_func_decl(f, tskp);
+   break;
+  /* named task */
+  case Begin:
+  case FORK:
+   dmp_nblock(f, tskp, syp->synam);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * dump a function declaration
+ */
+static void dmp_func_decl(FILE *f, struct task_t *tskp)
+{
+ struct net_t *np;
+ char ftyp[RECLEN], s1[RECLEN];
+
+ if (__outlinpos != 0) __nl_wrap_puts("", f);
+ __nl_wrap_puts("", f);
+ np = tskp->tskpins->tpsy->el.enp;
+ /* set function type */
+ if (np->ntyp == N_REAL) strcpy(ftyp, "real");
+ else if (np->ntyp == N_INT) strcpy(ftyp, "integer");
+ else if (np->ntyp == N_TIME) strcpy(ftyp, "time");
+ else __to_wrange(ftyp, np);
+ sprintf(s1, "function %s ", ftyp);
+ __wrap_puts(s1, f);
+ __wrap_puts(tskp->tsksyp->synam, f);
+
+ /* for new Ver 2001, if function args declared in header, emit in hdr */
+ if (tskp->tf_lofp_decl) dmp_tf_lofp_hdr(f, tskp);
+
+ __nl_wrap_puts(";", f);
+
+ dmp_tfdecls(f, tskp);
+ dmp_paramdecls(f, tskp->tsk_prms, tskp->tprmnum, "parameter");
+ dmp_lstofsts(f, tskp->tskst);
+ if (__outlinpos != 0) __nl_wrap_puts("", f);
+ __nl_wrap_puts("endfunction", f);
+}
+
+/*
+ * for named block either begin : [n] - end or fork-join blocks
+ * even if one statement need begin-join block
+ */
+static void dmp_nblock(FILE *f, struct task_t *tskp, char *bnam)
+{
+ struct st_t *stp2;
+
+ __pv_stlevel++;
+ if (tskp->tsktyp == FORK) __wrap_puts("fork : ", f);
+ else __wrap_puts("begin : ", f);
+ __wrap_puts(bnam, f);
+ __nl_wrap_puts("", f);
+ dmp_tfdecls(f, tskp);
+ dmp_paramdecls(f, tskp->tsk_prms, tskp->tprmnum, "parameter");
+ __pv_stlevel++;
+ if (tskp->tsktyp == FORK) dmp_fj_stlst(f, tskp->tskst);
+ else
+  { 
+   for (stp2 = tskp->tskst; stp2 != NULL; stp2 = stp2->stnxt)
+    __dmp_stmt(f, stp2, NL);
+  }
+ __pv_stlevel--;
+ if (__outlinpos != 0) __nl_wrap_puts("", f);
+ if (tskp->tsktyp == FORK) __nl_wrap_puts("join", f); 
+ else __nl_wrap_puts("end", f);
+ __pv_stlevel--;
+}
+
+/*
+ * dump tf declares
+ */
+static void dmp_tfdecls(FILE *f, struct task_t *tskp)
+{
+ register int32 i;
+ register struct task_pin_t *tpp;
+ register struct net_t *regp;
+ struct sy_t *syp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (__outlinpos != 0) __nl_wrap_puts("", f);
+ if (!tskp->tf_lofp_decl)
+  {
+   /* SJM 05/26/04 - only dump tf port if they were not declared in hdr */ 
+   for (tpp = tskp->tskpins; tpp != NULL; tpp = tpp->tpnxt)
+    {
+     /* 1st parameter for function is required return value */
+     if (tskp->tsktyp == FUNCTION && tpp == tskp->tskpins) continue;
+
+     syp = tpp->tpsy;
+     regp = syp->el.enp;
+     if (!regp->n_isavec || regp->ntyp == N_TIME || regp->ntyp == N_INT
+      || regp->ntyp == N_REAL) strcpy(s1, "");
+     else __to_wrange(s1, regp);
+
+     /* notice __to_wrange truncated to max of RECLEN - ok since only no.s */
+     sprintf(s3, " %s%s ", __to_ptnam(s2, tpp->trtyp), s1);
+     __wrap_puts(s3, f);
+     __wrap_puts(syp->synam, f);
+     __nl_wrap_puts(";", f);
+    }
+  }
+
+ if (tskp->trnum == 0) return;
+ for (i = 0, regp = &(tskp->tsk_regs[0]); i < tskp->trnum; i++, regp++)
+  {
+   if (regp->ntyp == N_REG && regp->iotyp != NON_IO) continue;
+
+   if (!regp->n_isavec || regp->ntyp == N_TIME || regp->ntyp == N_INT
+    || regp->ntyp == N_REAL) strcpy(s1, "");
+   else __to_wrange(s1, regp);
+
+   sprintf(s3, " %s%s ", __to_wtnam(s2, regp), s1);
+   __wrap_puts(s3, f);
+   __wrap_puts(regp->nsym->synam, f);
+   __nl_wrap_puts(";", f);
+  }
+}
+
+/*
+ * dump tf list of ports header task port decls
+ */
+static void dmp_tf_lofp_hdr(FILE *f, struct task_t *tskp)
+{
+ register struct task_pin_t *tpp;
+ int32 first_time;
+ struct sy_t *syp;
+ struct net_t *regp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ __wrap_putc('(', f);
+ first_time = TRUE;
+ for (tpp = tskp->tskpins; tpp != NULL; tpp = tpp->tpnxt)
+  {
+   /* 1st parameter for function is required return value */
+   if (tskp->tsktyp == FUNCTION && tpp == tskp->tskpins) continue;
+
+   if (!first_time) __wrap_puts(", ", f); else first_time = FALSE;
+
+   syp = tpp->tpsy;
+   regp = syp->el.enp;
+   if (!regp->n_isavec || regp->ntyp == N_TIME || regp->ntyp == N_INT
+    || regp->ntyp == N_REAL) strcpy(s1, "");
+   else __to_wrange(s1, regp);
+
+   /* notice __to_wrange truncated to max of RECLEN - ok since only no.s */
+   sprintf(s3, "%s%s ", __to_ptnam(s2, tpp->trtyp), s1);
+   __wrap_puts(s3, f);
+   __wrap_puts(syp->synam, f);
+  }
+ __wrap_putc(')', f);
+}
+
+/*
+ * SPECIFY SECTION SOURCE DUMP ROUTINES
+ * NULL FILE ILLEGAL FOR FILL STRING ILLEGAL
+ */
+
+/*
+ * dump module specify section - will not be called if not persent
+ */
+static void dmp_mdspfy(FILE *f, struct mod_t *mdp)
+{ 
+ struct spfy_t *spfp;
+
+ __pv_stlevel = 1;
+ if (__outlinpos != 0) __nl_wrap_puts("", f);
+ __nl_wrap_puts("", f);
+ __outlinpos = 0;
+ __nl_wrap_puts("specify", f);
+
+ spfp = mdp->mspfy;
+ /* parameters - this indents by 1 level */
+ dmp_paramdecls(f, spfp->msprms, spfp->sprmnum, "specparam");
+
+ __pv_stlevel = 2;
+ /* delay paths */
+ dmp_specpths(f, spfp->spcpths);
+ /* timing checks */
+ dmp_tchks(f, spfp->tchks);
+ __pv_stlevel = 1;
+ __nl_wrap_puts("endspecify", f);
+ __pv_stlevel = 0;
+}
+
+/*
+ * dump specify section paths
+ * (<pth lst> [=*]> <pth lst>) = (<delay list>); 
+ * edge dependent paths will parse but not stored, simulated or dmped
+ */
+static void dmp_specpths(FILE *f, register struct spcpth_t *pthp)
+{
+ char s1[RECLEN];
+
+ for (; pthp != NULL; pthp = pthp->spcpthnxt) 
+  {
+   if (pthp->pth_gone) continue;
+
+   /* dump sdpd (state dependent path desc.) if present */
+   if (pthp->pthcondx != NULL)
+    { 
+     __wrap_puts("if (", f);
+     dmp_expr(f, pthp->pthcondx);
+     __wrap_puts(") ", f);
+    }
+   else if (pthp->pth_ifnone) __wrap_puts("ifnone ", f);
+   if (pthp->datasrcx == NULL)
+    { 
+     __wrap_putc('(', f);
+     dmp_pthlst(f, pthp, TRUE);
+     __wrap_putc(' ', f);
+     if (pthp->pthpolar != POLAR_NONE)
+      {
+      if (pthp->pthpolar == POLAR_PLUS) __wrap_putc('+', f);
+       else __wrap_putc('-', f);
+      }
+     if (pthp->pthtyp == PTH_FULL) __wrap_puts("*> ", f);
+     else __wrap_puts("=> ", f); 
+     dmp_pthlst(f, pthp, FALSE);
+    }
+   else
+    {
+     __wrap_putc('(', f);
+     if (pthp->pthedge != NOEDGE) 
+      {
+       __wrap_puts(__to_edgenam(s1, pthp->pthedge), f);
+       __wrap_putc(' ', f);
+      }
+     dmp_pthlst(f, pthp, TRUE);
+     __wrap_putc(' ', f);
+     if (pthp->pthpolar != POLAR_NONE)
+      {
+       if (pthp->pthpolar == POLAR_PLUS) __wrap_putc('+', f);
+       else __wrap_putc('-', f);
+      }
+     if (pthp->pthtyp == PTH_FULL) __wrap_puts("*> ", f);
+     else __wrap_puts("=> ", f); 
+     /* edge sensitive path output form */
+     __wrap_putc('(', f);
+     dmp_pthlst(f, pthp, FALSE);
+     __wrap_putc(' ', f);
+     if (pthp->dsrc_polar != POLAR_NONE)
+      {
+       if (pthp->dsrc_polar == POLAR_PLUS) __wrap_putc('+', f);
+       else __wrap_putc('-', f);
+      }
+     __wrap_puts(": ", f);
+     /* this can be fcall comma form, does it work by itself ? */
+     dmp_expr(f, pthp->datasrcx);
+     __wrap_putc(')', f);
+    }
+   __wrap_puts(") = ", f);
+   /* notice delay always start with ' ' and if only 1 value no parens */
+   dmp_delay(f, pthp->pth_du, pthp->pth_delrep, "");
+   __nl_wrap_puts(";", f);
+  }
+}
+
+/*
+ * dump a path list
+ */
+static void dmp_pthlst(FILE *f, struct spcpth_t *pthp, int32 is_pein)
+{
+ register int32 pthi;
+
+ if (is_pein)
+  {
+   for (pthi = 0; pthi <= pthp->last_pein; pthi++)
+    {
+     if (pthi != 0) __wrap_puts(", ", f);
+     dmp_pthel(f, &(pthp->peins[pthi]));
+    }
+  } 
+ else
+  {
+   for (pthi = 0; pthi <= pthp->last_peout; pthi++)
+    {
+     if (pthi != 0) __wrap_puts(", ", f);
+     dmp_pthel(f, &(pthp->peouts[pthi]));
+    }
+  }
+}
+
+/*
+ * dump a preped path element form
+ */
+static void dmp_pthel(FILE *f, struct pathel_t *pelp)
+{
+ char s1[RECLEN];
+
+ __wrap_puts(pelp->penp->nsym->synam, f);
+ if (pelp->pthi1 == -1) return;
+
+ if (pelp->pthi1 == pelp->pthi2) sprintf(s1, "[%d]", pelp->pthi1);
+ else sprintf(s1, "[%d:%d]", pelp->pthi1, pelp->pthi2);
+ __wrap_puts(s1, f);
+}
+
+/*
+ * dump specify section timing checks 
+ * $setup(<data event>, <reference event>, limit, <opt. notifier>)
+ */
+static void dmp_tchks(FILE *f, register struct tchk_t *tcp)
+{
+ char s1[RECLEN];
+
+ for (; tcp != NULL; tcp = tcp->tchknxt)
+  {
+   /* when dumping only emit hold (same conn. order half with right name) */
+   if (tcp->tc_gone || tcp->tc_supofsuphld || tcp->tc_recofrecrem) continue; 
+
+   __wrap_puts(__to_tcnam(s1, tcp->tchktyp), f);
+   __wrap_putc('(', f); 
+   /* dump an event */
+   dmp_tchk_selector(f, tcp->startedge, tcp->startxp, tcp->startcondx);
+   if (tcp->tchktyp != TCHK_PERIOD && tcp->tchktyp != TCHK_WIDTH) 
+    { 
+     __wrap_puts(", ", f);
+     dmp_tchk_selector(f, tcp->chkedge, tcp->chkxp, tcp->chkcondx);
+    }
+   /* dump a delay - know will never be list form */
+   __wrap_puts(", ", f); 
+   dmp_delay(f, tcp->tclim_du, tcp->tc_delrep, "");
+   if (tcp->tc_haslim2)
+    {
+     __wrap_puts(", ", f); 
+     dmp_delay(f, tcp->tclim2_du, tcp->tc_delrep2, "");
+    }
+   /* need , place holder if no limit 2 but notifier */
+   if (tcp->ntfy_np != NULL)
+    {
+     __wrap_puts(", ", f);
+     __wrap_puts(tcp->ntfy_np->nsym->synam, f); 
+    } 
+   __nl_wrap_puts(");", f);
+  }
+}
+
+/*
+ * dump a timing check selector expression form
+ */
+static void dmp_tchk_selector(FILE *f, word32 edgval, struct expr_t *xp,
+ struct expr_t *condx)
+{
+ char s1[RECLEN];
+
+ if (edgval != NOEDGE) 
+  { __wrap_puts(__to_edgenam(s1, edgval), f); __wrap_putc(' ', f); }
+ dmp_expr(f, xp);
+ if (condx != NULL) { __wrap_puts(" &&& ", f); dmp_expr(f, condx); }
+}
+
+/*
+ * dump one gref entry
+ */
+static void dmp_mod_grefs(FILE *f, struct mod_t *mdp)
+{
+ register int32 gri;
+ register struct gref_t *grp;
+ char s1[RECLEN];
+
+ if (mdp->mgrnum == 0) return;
+
+ __pv_stlevel = 0;
+ if (__outlinpos != 0) __nl_wrap_puts("", f);
+ __wrap_puts("/* ==> hierarchical path occurring in ", f);
+ __wrap_puts(mdp->msym->synam, f);
+ __nl_wrap_puts(":", f);
+ for (gri = 0, grp = &(mdp->mgrtab[0]); gri < mdp->mgrnum; gri++, grp++)
+  {
+   if (grp->gr_gone) continue;
+   
+   __wrap_puts(grp->gnam, f);  
+   __wrap_puts(to_glbinfo(s1, grp), f);
+   __nl_wrap_puts("", f); 
+   /* -- could dump target symbol contents */
+   /* -- could dump expr. containing gref */
+  }
+ __nl_wrap_puts("=== end of globals. */", f);
+}
+
+/*
+ * convert global reference entry to info line
+ */
+static char *to_glbinfo(char *s, struct gref_t *grp)
+{
+ struct sy_t *syp;
+ char s1[RECLEN], s2[RECLEN];
+
+ sprintf(s, "<target %s", grp->targmdp->msym->synam);
+ /* this is symbol corresponding to symbol table target in */
+ if (grp->targtskp != NULL)
+  {
+   syp = grp->targtskp->tsksyp;
+   sprintf(s1, " in %s %s", __to_sytyp(s2, syp->sytyp), syp->synam);
+   strcat(s, s1);
+  }
+ sprintf(s1, " %s)", __bld_lineloc(s2, grp->grfnam_ind, grp->grflin_cnt));
+ strcat(s, s1);
+ strcat(s, ">");
+ return(s);
+}
+
+/*
+ * ROUTINES THAT CAN BE CALLED WITH NULL F TO GO IN EXPRLINE
+ */
+
+/*
+ * dump the case selector
+ */
+static void dmp_casesel(FILE *f, struct st_t *stp)
+{
+ char s1[RECLEN];
+
+ if (stp->st.scs.castyp == CASEZ) strcpy(s1, "casez");
+ else if (stp->st.scs.castyp == CASEX) strcpy(s1, "casex");
+ else strcpy(s1, "case");
+ __wrap_puts(s1, f);
+ __wrap_puts(" (", f);
+ dmp_expr(f, stp->st.scs.csx);
+ __wrap_putc(')', f);
+}
+
+/*
+ * for delays already converted to scaled sim. form
+ * know by this representation if number will not be x/z
+ *
+ * handles no delay case (its a union) and if writes insert leading space 
+ * notice dumping delays always just emits the 1st
+ */
+static void dmp_delay(FILE *f, union del_u du, word32 drep, char *sharps)
+{
+ register int32 i; 
+ int32 ndels; 
+ word32 t1a[2], t1b[2];
+ word64 tarr[16], tlist[16], *timp; 
+ char s1[RECLEN];
+
+ /* think ,, form will work right here for timing checks */
+ if (drep == DT_PTHDST || drep == DT_NONE || (drep == DT_CMPLST
+  && du.pdels == NULL)) goto done;
+
+ if (strcmp(sharps, "") != 0)
+  { __wrap_putc(' ', f); __wrap_puts(sharps, f); }
+ t1b[0] = t1b[1] = 0L;
+ 
+ switch ((byte) drep) {
+  case DT_1V:
+   /* 1 v is a ptr to an 8 byte rec., is1v is ptr to array but use 1st */
+   t1a[0] = (word32) ((*du.d1v) & WORDMASK_ULL);
+   t1a[1] = (word32) (((*du.d1v) >> 32) & WORDMASK_ULL);
+   __regab_disp(t1a, t1b, TIMEBITS, BDEC, TRUE, FALSE);
+   if (f != NULL) { __wrap_puts(__exprline, f); __cur_sofs = 0; }
+   break;
+  case DT_IS1V:
+   /* 1 v is a ptr to an 8 byte rec., is1v is ptr to array but use 1st */
+   t1a[0] = (word32) (du.dis1v[0] & WORDMASK_ULL);
+   t1a[1] = (word32) ((du.dis1v[0] >> 32) & WORDMASK_ULL);
+   __regab_disp(t1a, t1b, TIMEBITS, BDEC, TRUE, FALSE);
+   if (f != NULL) { __wrap_puts(__exprline, f); __cur_sofs = 0; }
+   break;
+  case DT_IS1V1:
+   sprintf(s1, "%lu", (word32) du.dis1v1[0]);
+   __wrap_puts(s1, f);
+   break;
+  case DT_IS1V2:
+   sprintf(s1, "%lu", (word32) du.dis1v2[0]);
+   __wrap_puts(s1, f);
+   break;
+  case DT_4V: timp = du.d4v; goto do4;
+  case DT_IS4V:
+   timp = du.dis4v;
+do4:
+   /* for IS 4 v linear array of groups of 4 so just use first */
+   __wrap_putc('(', f);
+   t1a[0] = (word32) (timp[1] & WORDMASK_ULL);
+   t1a[1] = (word32) ((timp[1] >> 32) & WORDMASK_ULL);
+
+   __regab_disp(t1a, t1b, TIMEBITS, BDEC, TRUE, FALSE);
+   if (f != NULL) { __wrap_puts(__exprline, f); __cur_sofs = 0; }
+   __wrap_puts(", ", f);
+   t1a[0] = (word32) (timp[0] & WORDMASK_ULL);
+   t1a[1] = (word32) ((timp[0] >> 32) & WORDMASK_ULL);
+   __regab_disp(t1a, t1b, TIMEBITS, BDEC, TRUE, FALSE);
+   if (f != NULL) { __wrap_puts(__exprline, f); __cur_sofs = 0; }
+   __wrap_puts(", ", f);
+   t1a[0] = (word32) (timp[2] & WORDMASK_ULL);
+   t1a[1] = (word32) ((timp[2] >> 32) & WORDMASK_ULL);
+   __regab_disp(t1a, t1b, TIMEBITS, BDEC, TRUE, FALSE);
+   if (f != NULL) { __wrap_puts(__exprline, f); __cur_sofs = 0; }
+   __wrap_putc(')', f);
+   break;
+  case DT_IS4V1:
+   /* for IS 4 v linear array of groups of 4 so just use first */
+   sprintf(s1, "(%lu, %lu, %lu)", (word32) du.dis4v1[1],
+    (word32) du.dis4v1[0], (word32) du.dis4v1[2]);
+   __wrap_puts(s1, f);
+   break;
+  case DT_IS4V2:
+   /* for IS 4 v linear array of groups of 4 so just use first */
+   sprintf(s1, "(%lu, %lu, %lu)", (word32) du.dis4v2[1],
+    (word32) du.dis4v2[0], (word32) du.dis4v2[2]);
+   __wrap_puts(s1, f);
+   break;
+  /* notice all the 6 forms are really size 16 tables */
+  case DT_16V: timp = du.d16v; goto do16;
+  case DT_IS16V:
+   timp = du.dis16v;
+do16:
+   for (i = 0; i < 16; i++) tarr[i] = timp[i];
+try_reduce:
+   /* first step, reorder internal 16 table to 12 values */
+   __map_16v_to_12vform(tlist, tarr);
+   __try_reduce_16vtab(tlist, &ndels); 
+   __wrap_putc('(', f);
+   for (i = 0; i < ndels; i++) 
+    {
+     if (i != 0) __wrap_puts(", ", f);
+     t1a[0] = (word32) (tlist[i] & WORDMASK_ULL);
+     t1a[1] = (word32) ((tlist[i] >> 32) & WORDMASK_ULL);
+     __regab_disp(t1a, t1b, TIMEBITS, BDEC, TRUE, FALSE);
+     if (f != NULL) { __wrap_puts(__exprline, f); __cur_sofs = 0; }
+    }
+   __wrap_putc(')', f);
+   break;
+  case DT_IS16V1:
+   for (i = 0; i < 16; i++) { tarr[i] = (word64) du.dis16v1[i]; }
+   goto try_reduce;
+  case DT_IS16V2:
+   for (i = 0; i < 16; i++) { tarr[i] = (word64) du.dis16v2[i]; }
+   goto try_reduce;
+  case DT_1X:
+   __wrap_putc('(', f);
+   dmp_expr(f, du.d1x);
+   __wrap_putc(')', f);
+   break;
+  case DT_4X:
+   __wrap_putc('(', f);
+   dmp_expr(f, du.d4x[1]);
+   __wrap_puts(", ", f);
+   dmp_expr(f, du.d4x[0]);
+   if (du.d4x[2] != NULL) { __wrap_puts(", ", f); dmp_expr(f, du.d4x[2]); }
+   __wrap_putc(')', f);
+   break;
+  case DT_CMPLST:
+   dmp_dellst(f, du.pdels);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+done:
+ if (f != NULL) __cur_sofs = 0; else __exprline[__cur_sofs] = '\0';
+}
+
+/*
+ * dump a delay or module instance parameter list
+ * this must handle no delay case
+ */
+static void dmp_dellst(FILE *f, register struct paramlst_t *pmp)
+{
+ int32 first_time;
+ struct expr_t *xp;
+
+ __force_base = BDEC;
+ if (pmp->pmlnxt == NULL)
+  {
+   xp = pmp->plxndp;
+   switch ((byte) xp->optyp) {
+    case NUMBER: case REALNUM: case ISNUMBER: case ISREALNUM: case ID:
+     dmp_expr(f, pmp->plxndp);
+     __force_base = BNONE;
+     return;
+    }
+  }
+ /* for even 1 expr. need parentheses - also for global here */
+ __wrap_putc('(', f);
+ for (first_time = TRUE; pmp != NULL; pmp = pmp->pmlnxt)
+  {
+   if (first_time) first_time = FALSE; else __wrap_puts(", ", f);
+   dmp_expr(f, pmp->plxndp);
+  }
+ __wrap_putc(')', f);
+ __force_base = BNONE;
+}
+
+/*
+ * dump the for header part
+ */
+extern void __dmp_forhdr(FILE *f, struct for_t *frs)
+{
+ int32 sav_debug_flg;
+
+ sav_debug_flg = __debug_flg;
+ __debug_flg = TRUE;
+ __wrap_puts("for (", f);
+ /* ending ; will be written */
+ __dmp_proc_assgn(f, frs->forassgn, (struct delctrl_t *) NULL, TRUE);
+ __wrap_putc(' ', f);
+ dmp_expr(f, frs->fortermx);
+ __wrap_puts("; ", f);
+ /* cannot use dmp procedural assign because of trailing ; */
+ dmp_expr(f, frs->forinc->st.spra.lhsx);
+ __wrap_puts(" = ", f);
+ dmp_expr(f, frs->forinc->st.spra.rhsx);
+ __wrap_puts(") ", f);
+ __debug_flg = sav_debug_flg;
+}
+
+/*
+ * dump a procedural assignment statement
+ * for rhs delay control statement is dctrl action statement
+ */
+extern void __dmp_proc_assgn(FILE *f, struct st_t *stp, struct delctrl_t *dctp,
+ int32 force_for)
+{
+ /* for assign moved to before for, but must not emit */
+ if (!force_for && stp->stmttyp == S_FORASSGN && stp->stnxt != NULL
+  && stp == stp->stnxt->st.sfor->forassgn) return;
+
+ dmp_expr(f, stp->st.spra.lhsx);
+ __wrap_puts(" = ", f);
+
+ if (dctp != NULL)
+  {
+   if (dctp->repcntx != NULL)
+    {
+     __wrap_puts("repeat (", f);
+     dmp_expr(f, dctp->repcntx);
+     __wrap_puts(") ", f);
+    }
+   __dmp_dctrl(f, dctp);
+  }
+ dmp_expr(f, stp->st.spra.rhsx);
+ __wrap_puts(";", f);
+ /* here may have added goto for rhs form */
+ if (dctp != NULL && dctp->actionst != NULL)
+  __dmp_stmt(f, dctp->actionst, FALSE);
+}
+
+/*
+ * dump a non blocking procedural assignment statement
+ * for rhs delay control statement is dctrl action statement
+ */
+extern void __dmp_nbproc_assgn(FILE *f, struct st_t *stp,
+ struct delctrl_t *dctp)
+{
+ dmp_expr(f, stp->st.spra.lhsx);
+ __wrap_puts(" <= ", f);
+ /* know this dctrl will not have action statement */
+ if (dctp != NULL)
+  {
+   if (dctp->repcntx != NULL)
+    {
+     __wrap_puts("repeat (", f);
+     dmp_expr(f, dctp->repcntx);
+     __wrap_puts(") ", f);
+    }
+   __dmp_dctrl(f, dctp);
+  }
+ dmp_expr(f, stp->st.spra.rhsx);
+ __wrap_puts(";", f);
+}
+
+/*
+ * dump a delay control
+ */
+extern void __dmp_dctrl(FILE *f, struct delctrl_t *dctp)
+{
+ struct delctrl_t tmpdctp;
+
+ switch ((byte) dctp->dctyp) {
+  case DC_EVENT:
+   __wrap_putc('@', f);
+non_rhs:
+   /* continue on same line */
+   __dmp_dcxpr(f, dctp->dc_du, dctp->dc_delrep);
+   /* this can be list because of added goto if debug flag on */
+   if (dctp->actionst != NULL) dmp_lstofsts(f, dctp->actionst);
+   break;
+  case DC_DELAY:
+   __wrap_putc('#', f);
+   goto non_rhs;
+  case DC_RHSEVENT:
+  case DC_RHSDELAY:
+   if (dctp->dctyp == DC_RHSEVENT) tmpdctp.dctyp = DC_EVENT;
+   else tmpdctp.dctyp = DC_DELAY;
+   tmpdctp.actionst = NULL;
+   /* notice since this is read only just sharing previous expr */
+   tmpdctp.dc_delrep = dctp->dc_delrep;
+   tmpdctp.dc_du = dctp->dc_du;
+   tmpdctp.repcntx = dctp->repcntx;
+
+   if (dctp->actionst->stmttyp == S_NBPROCA)
+    __dmp_nbproc_assgn(f, dctp->actionst, &tmpdctp);
+   else if (dctp->actionst->stmttyp == S_RHSDEPROCA)
+    __dmp_proc_assgn(f, dctp->actionst, &tmpdctp, FALSE);
+   else __case_terr(__FILE__, __LINE__);
+   /* if dumping source - maybe goto as actionst next */ 
+   if (__run_state != SS_SIM && dctp->actionst->stnxt != NULL)
+    {
+     /* notice set off during wire init and no statemnt exec there */
+     if (dctp->actionst->stnxt->stmttyp != S_GOTO)
+      __misc_terr(__FILE__, __LINE__);
+     __dmp_stmt(f, dctp->actionst->stnxt, NONL);
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ if (f == NULL) __exprline[__cur_sofs] = '\0';
+}
+
+/*
+ * dump the actual delay
+ * can be used during compilation or after prep. where ticks (scaled) dumped 
+ */
+extern void __dmp_dcxpr(FILE *f, union del_u du, word32 drep)
+{
+ int32 leaf;
+ struct expr_t *dxp;
+
+ __force_base = BDEC;
+ if (drep != DT_CMPLST)
+  {
+   dmp_delay(f, du, drep, "");
+   __wrap_putc(' ', f); 
+  }
+ else
+  {
+   dxp = du.pdels->plxndp;  
+   leaf = __isleaf(dxp);
+   if (!leaf) __wrap_putc('(', f);
+   dmp_expr(f, dxp);
+   if (!leaf) __wrap_putc(')', f);
+   /* needed to make sure exprline for f nil terminated */ 
+   __wrap_putc(' ', f);
+  }
+ if (f == NULL) __exprline[__cur_sofs] = '\0';
+ __force_base = BNONE;
+}
+
+/*
+ * dump a task call
+ * should dump task call global name
+ */
+extern void __dmp_tskcall(FILE *f, struct st_t *stp)
+{
+ register struct expr_t *xp;
+ int32 first_time;
+
+ dmp_expr(f, stp->st.stkc.tsksyx);
+ first_time = TRUE;
+ for (xp = stp->st.stkc.targs; xp != NULL; xp = xp->ru.x)
+  {
+   if (first_time) { __wrap_putc('(', f); first_time = FALSE; }
+   else __wrap_puts(", ", f);
+   dmp_expr(f, xp->lu.x);
+  }
+ if (!first_time) __wrap_putc(')', f);
+ /* need null terminated string */
+ __wrap_puts(";", f);
+}
+
+/*
+ * dump a statement list
+ */
+static void dmp_lstofsts(FILE *f, struct st_t *hdstp)
+{
+ register struct st_t *stp;
+
+ if (hdstp->st_unbhead)
+  {
+   if (__outlinpos != 0) __nl_wrap_puts("", f);
+   __pv_stlevel++;
+   __wrap_puts("begin", f);
+   __pv_stlevel++;
+   for (stp = hdstp; stp != NULL; stp = stp->stnxt)
+    __dmp_stmt(f, stp, NL);
+   if (__outlinpos != 0) __nl_wrap_puts("", f);
+   __pv_stlevel--;
+   __nl_wrap_puts("end", f);
+   __pv_stlevel--;
+   return;
+  }
+ /* added control statements if being printed go on same line */
+ for (stp = hdstp; stp != NULL; stp = stp->stnxt)
+  __dmp_stmt(f, stp, NONL);
+}
+
+/*
+ * build an array range expression from a net
+ * assume comp. time representation
+ *
+ * notice this uses expr line so cannot be called from expr_tostr
+ * but does call it
+ */
+extern char *__to_arr_range(char *s, struct net_t *np)
+{
+ int32 r1, r2, awid;
+
+ if (np->n_isarr)
+  {
+   if (np->nrngrep == NX_CT)
+    __msgtox_wrange(s, np->nu.ct->ax1, np->nu.ct->ax2);
+   else
+    {
+     __getarr_range(np, &r1, &r2, &awid);
+     sprintf(s, "[%d:%d]", r1, r2);
+    }
+  }
+ else strcpy(s, "");
+ return(s);
+}
+
+/*
+ * build a wire range expression from a net
+ * silently trucates if > RECLEN
+ *
+ * this is for ranges in messages - ok since will be numbers, if expr.
+ * will use other routine
+ */
+extern char *__to_wrange(char *s, struct net_t *np)
+{
+ int32 r1, r2;
+
+ if (np->n_isavec)
+  {
+   if (np->nrngrep == NX_CT)
+    __msgtox_wrange(s, np->nu.ct->nx1, np->nu.ct->nx2);
+   else
+    {
+
+     /* if this is a vector and not compile time rep, know will be range */
+     __getwir_range(np, &r1, &r2);
+     sprintf(s, "[%d:%d]", r1, r2);
+    }
+  }
+ else strcpy(s, "");
+ return(s);
+}
+
+/*
+ * build a range expression in expr line
+ * must terminate string in exprline if nil
+ * this can be nil
+ */
+static void tox_wrange(FILE *f, struct expr_t *x1, struct expr_t *x2)
+{
+ __force_base = BDEC;
+ if (x1 == NULL) return;
+ __wrap_putc('[', f);
+ dmp_expr(f, x1);
+ __wrap_putc(':', f);
+ dmp_expr(f, x2);
+ __wrap_putc(']', f);
+ if (f == NULL) __exprline[__cur_sofs] = '\0';
+ __force_base = BNONE;
+}
+
+
+/*
+ * ROUTINES TO DUMP VERILOG EXPRESSIONS TO SOURCE FORMAT
+ */
+
+/*
+ * either write a string through dmp puts path (wraps lines) if f not nil 
+ * or else collect in __exprline starting at __cur_sofs (make big enough) 
+ *
+ * must write immediately for dumping source to get line wrapping right
+ * note this requires current itree place - will crash otherwise
+ * if f is not nil, __cur_sofs must be set to 0 since used as work area
+ */
+static void dmp_expr(FILE *f, struct expr_t *ndp)
+{
+ int32 indv, ind1, ind2, nd_par, sav_spos;
+ word32 *wp;
+ struct net_t *np;
+ char *chp;
+ char s1[RECLEN];
+
+ /* expr. pointer while converting to string bad */
+ if (ndp == NULL || ndp->optyp == 0 || ndp->optyp == UNDEF)
+  __misc_terr(__FILE__, __LINE__);
+
+ switch ((byte) ndp->optyp) {
+  case ID:
+   /* if empty symbol - emit empty string here - for wire ranges */
+   if (ndp->lu.sy == NULL) return; 
+   if (ndp->locqualnam) chp = ndp->ru.qnchp; else chp = ndp->lu.sy->synam;
+   __wrap_puts(chp, f);
+   return;
+  case GLBREF:
+   /* know gref always have name - first expr. image during parsing */
+   /* then image with instance array selectors folded to numbers */
+   /* once parsing complete xmrs convert to gnam so if global */
+   /* select is xmr that expr will resolved to gnam before here */
+   chp = ndp->ru.grp->gnam;
+   __wrap_puts(chp, f);
+   return;
+  case XMRID:
+   /* special case during global resolution xmr name - no symbol */ 
+   chp = ndp->ru.qnchp;
+   __wrap_puts(chp, f);
+   return;
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM:
+   /* if empty do not emit anything, else fill with constant value  */
+   /* this knows about all number forms but IS is 0th only */
+   if (f == NULL) numexpr_disp(ndp, 0);
+   else
+    { 
+     sav_spos = __cur_sofs;
+     numexpr_disp(ndp, 0);
+     __wrap_puts(&(__exprline[sav_spos]), f);
+     __cur_sofs = sav_spos; 
+     __exprline[__cur_sofs] = '\0'; 
+    }
+   return;
+  case LSB:
+   if (ndp->lu.x->optyp == XMRID) dmp_expr(f, ndp->lu.x);
+   else if (ndp->lu.x->lu.sy != NULL) dmp_expr(f, ndp->lu.x);
+   __wrap_putc('[', f);
+   /* convert to original value (not h:0 new adjusted) if needed */
+   if (ndp->ru.x->ind_noth0 && ndp->lu.x->lu.sy != NULL)
+    {
+     /* notice for dumping - convention is to use IS 0th */
+     wp = &(__contab[ndp->ru.x->ru.xvi]);
+     indv = __unnormalize_ndx(ndp->lu.x->lu.sy->el.enp, (int32) wp[0]);
+     sprintf(s1, "%d", indv);
+     __wrap_puts(s1, f);
+     __wrap_putc(']', f);
+    }
+   else { dmp_expr(f, ndp->ru.x); __wrap_putc(']', f); }
+   if (f == NULL) __exprline[__cur_sofs] = '\0'; 
+   return;
+  case PARTSEL:
+   if (ndp->lu.x->lu.sy != NULL) dmp_expr(f, ndp->lu.x);
+   __wrap_putc('[', f);
+   /* convert to original value (not h:0 new adjusted) if needed */
+   if (ndp->ru.x->lu.x->ind_noth0 && ndp->lu.x->lu.sy != NULL)
+    {
+     np = ndp->lu.x->lu.sy->el.enp;
+     /* know part select range never IS form */
+     wp = &(__contab[ndp->ru.x->lu.x->ru.xvi]);
+     ind1 = __unnormalize_ndx(np, (int32) wp[0]);
+     wp = &(__contab[ndp->ru.x->ru.x->ru.xvi]);
+     ind2 = __unnormalize_ndx(np, (int32) wp[0]);
+     sprintf(s1, "%d:%d]", ind1, ind2);
+     __wrap_puts(s1, f);
+    }
+   else
+    {
+     dmp_expr(f, ndp->ru.x->lu.x);
+     __wrap_putc(':', f);
+     dmp_expr(f, ndp->ru.x->ru.x);
+     __wrap_putc(']', f);
+     if (f == NULL) __exprline[__cur_sofs] = '\0'; 
+    }
+   return;
+  case QUEST:
+   /* for now need parentheses around these or cannot parse */
+   __wrap_putc('(', f);
+   dmp_expr(f, ndp->lu.x);
+   __wrap_putc(')', f);
+   __wrap_puts(" ? ", f);
+   dmp_expr(f, ndp->ru.x->lu.x);
+   __wrap_puts(" : ", f);
+   dmp_expr(f, ndp->ru.x->ru.x);
+   return;
+  case LCB:
+   /* l of expr. node empty */
+   dmp_catexpr(f, ndp);
+   return;
+  case FCALL:
+   dmp_fcallx(f, ndp);
+   return;
+  /* dumping empty is write nothing */
+  case OPEMPTY:
+   return;
+  /* event or cannot be parenthesisized or nested */ 
+  case OPEVOR: case OPEVCOMMAOR:
+   /* SJM 06/01/04 - current scheme is 2 ops that print different but same */
+   dmp_evor_chain(f, ndp);
+   return;
+  /* FALLTHRU */
+ }
+ /* know this is operator - unary has right subtree nil */
+ if (ndp->ru.x == NULL)
+  {
+   __wrap_puts(__to_opname(ndp->optyp), f);
+   if (!is_simplex(ndp->lu.x) && ndp->lu.x->ru.x != NULL) nd_par = TRUE;
+   else nd_par = FALSE;
+   if (nd_par) __wrap_putc('(', f);
+  
+   dmp_expr(f, ndp->lu.x);
+   if (nd_par) __wrap_putc(')', f);
+   if (f == NULL) __exprline[__cur_sofs] = '\0'; 
+   return;
+  }
+ /* DBG remove --- */
+ if (ndp->lu.x == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ /* know this is binary */
+ if (!is_simplex(ndp->lu.x)) nd_par = TRUE; else nd_par = FALSE; 
+ if (nd_par) __wrap_putc('(', f);
+ dmp_expr(f, ndp->lu.x);
+ if (nd_par) __wrap_putc(')', f);
+ __wrap_putc(' ', f);
+ __wrap_puts(__to_opname(ndp->optyp), f);
+ __wrap_putc(' ', f);
+ if (!is_simplex(ndp->ru.x)) nd_par = TRUE; else nd_par = FALSE; 
+ if (nd_par) __wrap_putc('(', f);
+ dmp_expr(f, ndp->ru.x);
+ if (nd_par) __wrap_putc(')', f); 
+ if (f == NULL) __exprline[__cur_sofs] = '\0'; 
+}
+
+/*
+ * return T if is simple object expr. leaf, concat, or fcall
+ * that does not need parenthesis
+ */
+static int32 is_simplex(struct expr_t *xp)
+{
+ if (__isleaf(xp)) return(TRUE);
+ switch (xp->optyp) {
+  case LSB: case PARTSEL: case LCB: case FCALL: return(TRUE); 
+ }
+ return(FALSE);
+}
+
+/*
+ * dump a concatenate
+ * this really needs to have new lines and indentation added
+ */
+static void dmp_catexpr(FILE *f, struct expr_t *ndp)
+{
+ int32 first_time;
+
+ __wrap_putc('{', f);
+ /* know { operator left always unused */
+ for (first_time = TRUE, ndp = ndp->ru.x; ndp != NULL; ndp = ndp->ru.x)
+  {
+   if (!first_time) __wrap_puts(", ", f); else first_time = FALSE;
+   dmp_catel(f, ndp->lu.x);
+  }
+ __wrap_putc('}', f);
+ if (f == NULL) __exprline[__cur_sofs] = '\0';
+}
+
+/*
+ * dump a concatenate element
+ */
+static void dmp_catel(FILE *f, struct expr_t *ndp)
+{
+ if (ndp->optyp == CATREP)
+  {
+   __wrap_putc('(', f);
+   dmp_expr(f, ndp->lu.x);
+   __wrap_putc(')', f);
+   dmp_catexpr(f, ndp->ru.x);
+  }
+ else dmp_expr(f, ndp);
+}
+
+/*
+ * dump a function call
+ */
+static void dmp_fcallx(FILE *f, struct expr_t *ndp)
+{
+ int32 first_time;
+ char paren;
+
+ dmp_expr(f, ndp->lu.x);
+ if (ndp->ru.x == NULL) return;
+
+ paren = '(';
+
+ __wrap_putc(paren, f);
+ if (ndp->ru.x == NULL) return;
+ /* know fcall operator left always unused */
+ for (first_time = TRUE, ndp = ndp->ru.x; ndp != NULL; ndp = ndp->ru.x)
+  {
+   if (!first_time) __wrap_puts(", ", f); else first_time = FALSE;
+   dmp_expr(f, ndp->lu.x);
+  }
+ if (paren == '<') __wrap_putc('>', f); else __wrap_putc(')', f);
+ if (f == NULL) __exprline[__cur_sofs] = '\0';
+}
+
+/*
+ * dump an event evor expression 
+ * syntax allow ([edge] [expr] or ([normal expression]) and
+ * ([event expr] or [event expr] or [] ) - stylized chain only 
+ *
+ * LOOKATME:
+ * but associating to left for some reason - works since just list that
+ * each of which gets added to dcelst as dcevnt
+ * maybe needed because rhs section can be complicated expr. not just chain
+ * as in concat case
+ */
+static void dmp_evor_chain(FILE *f, struct expr_t *ndp) 
+{
+ if (ndp->lu.x->optyp == OPEVOR || ndp->lu.x->optyp == OPEVCOMMAOR)
+  {
+   dmp_evor_chain(f, ndp->lu.x);
+  }
+ else dmp_expr(f, ndp->lu.x);
+
+ if (ndp->lu.x->optyp == OPEVOR) __wrap_puts(" or ", f);
+ else __wrap_puts(", ", f);
+
+ dmp_expr(f, ndp->ru.x); 
+}
+
+/*
+ * put a string for source statement dumping handles line wrap and
+ * statement level indenting
+ */
+extern void __wrap_puts(char *s, FILE *f)
+{
+ int32 ll;
+
+ ll = strlen(s);
+ if (f == NULL)
+  {
+   if (__cur_sofs + ll >= __exprlinelen - 1) __chg_xprline_size(ll + 1);
+   strcpy(&(__exprline[__cur_sofs]), s);
+   __cur_sofs += ll;
+   return;    
+  }
+ 
+ /* case 1: at beginning of line, just need statement indent */
+ if (__outlinpos == 0)
+  {
+   if (__pv_stlevel > 0)
+    {
+     __blnkline[__pv_stlevel] = '\0'; 
+     __cvsim_msg(__blnkline);
+     __blnkline[__pv_stlevel] = ' '; 
+    }
+   /* always print s no matter how wide - cannot break inside objs */
+   __outlinpos = __pv_stlevel + ll;
+  
+   __cvsim_msg("%s", s);
+   return;
+  }
+
+ /* case 2: try continuation on current line */
+ /* if string <= 2 make this line slightly too long (for ,[space]) */
+ if ((__outlinpos += ll) > OUTLINLEN)
+  {
+   /* various ending punctuation (short fields) should go on same line */
+   if ((ll > 3 || (!ispunct(s[0]) && s[0] != ' '))
+    || __outlinpos > OUTLINLEN + 6)
+    {
+     __cvsim_msg("\n");
+
+     __blnkline[__pv_stlevel + 1] = '\0'; 
+     __cvsim_msg("%s", __blnkline);
+     __blnkline[__pv_stlevel + 1] = ' '; 
+     __outlinpos = __pv_stlevel + ll + 1;
+    }
+  }
+ /* cannot use printf here since must emit format with % as is */
+ __cvsim_msg("%s", s);
+}
+
+/*
+ * source statement put char analog of put string above 
+ */
+extern void __wrap_putc(int32 c, FILE *f)
+{
+ if (f == NULL) { addch_(c); return; }
+
+ if (__outlinpos == 0)
+  {
+   if (__pv_stlevel > 0)
+    {
+     __blnkline[__pv_stlevel] = '\0'; 
+     __cvsim_msg("%s", __blnkline);
+     __blnkline[__pv_stlevel] = ' '; 
+    }
+   __outlinpos = __pv_stlevel + 1;
+   __cvsim_msg("%c", c);
+   return;
+  }
+
+ /* if string <= 2 make this line slightly too long (for ,[space]) */
+ if (++__outlinpos > OUTLINLEN)
+  {
+   /* various ending punctuation (short fields) should go on same line */
+   if ((!ispunct(c) && c != ' ') || __outlinpos > OUTLINLEN + 6)
+    {
+     __cvsim_msg("\n");
+
+     __blnkline[__pv_stlevel + 1] = '\0'; 
+     __cvsim_msg("%s", __blnkline);
+     __blnkline[__pv_stlevel + 1] = ' '; 
+     __outlinpos = __pv_stlevel + 2;
+    }
+  }
+ __cvsim_msg("%c", c);
+}
+
+/*
+ * wrap form of puts that adds new line
+ * notice macro does nothing if called with f == nil
+ */
+extern void __nl_wrap_puts(char *s, FILE *f)
+{
+ if (f != NULL)
+  {
+   if (*s != '\0') __wrap_puts(s, f);
+   __wrap_putc('\n', f);
+   __outlinpos = 0;
+  }
+ else __cur_sofs = 0;
+}
+
+/*
+ * add string to current place in __exprline
+ * notice this always leaves line null terminated but addch_ macros does not 
+ */
+extern void __adds(char *s)
+{
+ int32 slen;
+
+ slen = strlen(s);
+ if (__cur_sofs + slen >= __exprlinelen - 1) __chg_xprline_size(slen + 1);
+ strcpy(&(__exprline[__cur_sofs]), s);
+ __cur_sofs += slen; 
+}
+
+/*
+ * change the length of a partially filled expr string line
+ * if need to increase increase by needed amount plus large (1024) piece
+ * requires that __exprline always be \0 terminated before calling this
+ */
+extern void __chg_xprline_size(int32 slen)
+{
+ int32 newlen;
+
+ newlen = slen + ((__exprlinelen < 4*IDLEN) ? __exprlinelen + IDLEN
+  : __exprlinelen + BIG_ALLOC_SIZE);
+ __exprline = __my_realloc(__exprline, __exprlinelen, newlen);
+ __exprlinelen = newlen;
+}
+
+/*
+ * ROUTINES TO BUILD VPI_ ARGV ARRAY
+ */
+
+/*
+ * convert opthdr from to vpi_ recursive argv
+ *
+ * only called once first time needed (vpi argv nil)
+ * LOOKATME - this always copies and reallocates but maybe not needed
+ */
+extern void __bld_vpi_argv(void)
+{
+ register int32 lev, i;
+ register struct optlst_t *olp;
+ int32 maxlev, argnum, nbytes;
+ struct optlst_t *bmark_olp;
+ char **down_argv;
+
+ maxlev = find_deepest_level(__opt_hdr);
+ /* process bottom up replacing BMARK to EMARK with sub argv ** */
+ for (lev = maxlev; lev >= 1; lev--) 
+  {
+   for (olp = __opt_hdr; olp != NULL; olp = olp->optlnxt)
+    {
+     if (olp->argv_done) continue;
+     if (olp->optlev != lev || !olp->is_bmark) continue;
+
+     /* found right level BMARK */
+     argnum = cnt_beg_to_endmark(olp, olp->optlev);
+     down_argv = (char **) __my_malloc(argnum*sizeof(char *));
+     down_argv[0] = __pv_stralloc(__in_fils[olp->optfnam_ind]);
+     /* starting one after bmark */
+     bmark_olp = olp;
+     for (olp = olp->optlnxt, i = 1;; olp = olp->optlnxt)
+      {
+       if (olp->argv_done) continue;
+       if (olp->optlev != lev) __misc_terr(__FILE__, __LINE__);
+       /* case 1: insert in down argv (first -f) */
+       if (olp->is_argv)
+        {
+         if (!olp->is_bmark) __misc_terr(__FILE__, __LINE__);
+         down_argv[i++] = __pv_stralloc("-f");
+         down_argv[i++] = (char *) olp->dargv;
+         olp->dargv = NULL;
+         olp->is_argv = FALSE;
+         olp->argv_done = TRUE;
+         continue;
+        }
+       /* case 2: end mark - add nil terminator and done */
+       if (olp->is_emark)
+        {
+         olp->argv_done = TRUE;
+         down_argv[i++] = NULL;
+         break;
+        }
+       /* case 3: normal option (must remove -f by itself) */
+       if (strcmp(olp->opt, "-f") != 0)
+        {
+         down_argv[i++] = __pv_stralloc(olp->opt);
+        }
+       olp->argv_done = TRUE;
+      }
+     bmark_olp->dargv = down_argv;
+     bmark_olp->is_argv = TRUE;
+     bmark_olp->optlev--;
+    }
+  }
+ /* top level is special case because of normal OS argc */
+ /* special count that counts anything - no bmark-emark needed */
+ argnum = cnt_level0(__opt_hdr);
+ /* need 0th that is invoking Cver file name */
+ __vpi_argc = argnum + 1;
+ nbytes = __vpi_argc*(sizeof(char **));
+ __vpi_argv = (char **) __my_malloc(nbytes);
+ /* need to set simulator name from OS argv[0] */
+ __vpi_argv[0] = __vpi_argv0;
+ /* notice top uses argc - no ending nil */
+ for (i = 1, olp = __opt_hdr; olp != NULL; olp = olp->optlnxt)
+  {
+   if (olp->argv_done) continue;
+   /* case 1: down argv - need to add -f */
+   if (olp->is_argv)
+    {
+     if (!olp->is_bmark) __misc_terr(__FILE__, __LINE__);
+     __vpi_argv[i++] = __pv_stralloc("-f");
+     __vpi_argv[i++] = (char *) olp->dargv;
+     continue;
+    }
+   /* case 2: normal option (must reomve -f not followed by openable file) */ 
+   if (strcmp(olp->opt, "-f") != 0)
+    {
+     __vpi_argv[i++] = __pv_stralloc(olp->opt);
+    } 
+  }
+ /* DBG remove ---
+ dump_vpi_argv(__vpi_argc, __vpi_argv);
+ --- */
+}
+
+/*
+ * find highest (deepest level) because convert bottom up to PLI **argv tabs
+ */
+static int32 find_deepest_level(struct optlst_t *olphd)
+{
+ register struct optlst_t *olp;
+ int32 level;
+
+ for (level = 0, olp = olphd; olp != NULL; olp = olp->optlnxt)
+  { if (olp->optlev > level) level = olp->optlev; }
+ return(level);
+}
+
+/*
+ * count number of options from begin to end know olp points to beg
+ * and ignores any argv_done elements
+ *
+ * level passed for checking - all counted must be at level lev or internal err
+ * BMARK counted for file name and EMARK counted for ending NULL
+ */
+static int32 cnt_beg_to_endmark(struct optlst_t *olp, int32 lev)
+{
+ int32 onum;
+
+ if (!olp->is_bmark) __arg_terr(__FILE__, __LINE__);
+ olp = olp->optlnxt;
+ for (onum = 1; olp != NULL; olp = olp->optlnxt)
+  {
+   if (olp->argv_done) continue;
+   /* empty file will have count of 0 */
+   if (olp->is_emark) return(onum + 1);
+   if (olp->optlev != lev) __arg_terr(__FILE__, __LINE__);
+
+   if (olp->is_argv) onum += 2;
+   else
+    {
+     /* must not count -f not followed by openable file */
+     if (strcmp(olp->opt, "-f") != 0) onum++;
+    }
+  }
+ /* must always see EMARK */
+ __arg_terr(__FILE__, __LINE__);
+ return(-1);
+}
+
+/*
+ * count top level (0) non argv done olps
+ */
+static int32 cnt_level0(struct optlst_t *olp)
+{
+ int32 onum;
+
+ for (onum = 0; olp != NULL; olp = olp->optlnxt)
+  {
+   if (olp->argv_done) continue;
+   /* only remaining must be level 0 */
+   if (olp->optlev != 0) __arg_terr(__FILE__, __LINE__);
+   if (olp->is_argv) onum += 2;
+   else
+    {
+     /* must not count -f not followed by openable file */  
+     if (strcmp(olp->opt, "-f") != 0) onum++;
+    }
+  }
+ return(onum);
+}
+
+/*
+ * dump a vpi argv/argc d.s.
+ */
+static void dump_vpi_argv(int32 argc, char **argv)
+{
+ register int32 i;
+
+ __dbg_msg("TOP ARGC: %d\n", argc);
+ for (i = 0; i < argc; i++) 
+  {
+   /* know if see -f, will be followed by sub argv */
+   if (strcmp(argv[i], "-f") == 0)
+    {
+     __dbg_msg("LEVEL 0: arg %d: -f\n", i);
+     __dbg_msg("LEVEL 0: arg %d: NESTED ARGV\n", i + 1);
+     dump_nest_vpi_argv(1, (char **) argv[i + 1]);
+     i++;
+    }
+   else __dbg_msg("LEVEL 0: arg %d: %s\n", i, argv[i]);
+  }
+}
+
+/*
+ * dump a contained nested file
+ */
+static void dump_nest_vpi_argv(int32 lev, char **argv)
+{
+ register int32 i;
+
+ __dbg_msg("LEVEL %d: arg 0: file %s\n", lev, argv[0]);
+ for (i = 1;; i++)
+  {
+   if (argv[i] == NULL) break;
+   /* know if see -f, will be followed by sub argv */
+   if (strcmp(argv[i], "-f") == 0)
+    {
+     __dbg_msg("LEVEL %d: arg %d: -f\n", lev, i);
+     __dbg_msg("LEVEL %d: arg %d: NESTED ARGV\n", lev, i + 1);
+     dump_nest_vpi_argv(lev + 1, (char **) argv[i + 1]);
+     i++;
+    }
+   else __dbg_msg("LEVEL %d: arg %d: %s\n", lev, i, argv[i]);
+  }
+ __dbg_msg("LEVEL %d: **NULL**\n", lev);
+}
+
+/*
+ * dump one oplst_t record
+ */
+static void dmp1_optlst(struct optlst_t *olp, char *emsg)
+{
+ char s1[RECLEN];
+
+ if (olp->is_bmark && olp->is_emark) __misc_terr(__FILE__, __LINE__);
+ if (olp->is_bmark) strcpy(s1, "BMARK");
+ else if (olp->is_emark) strcpy(s1, "EMARK");
+ else strcpy(s1, "NONE");
+ __dbg_msg("**%s: file %s line %d: mark %s optnum %d optlev %d opt %s\n",
+  emsg, __in_fils[olp->optfnam_ind], olp->optlin_cnt, s1, olp->optnum,
+  olp->optlev, olp->opt);  
+}
diff --git a/src/v_dbg.c b/src/v_dbg.c
new file mode 100644
index 0000000..9564595
--- /dev/null
+++ b/src/v_dbg.c
@@ -0,0 +1,3576 @@
+/* Copyrght (c) 1993-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * debugger - interactive environment
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef __linux__
+#include <sys/types.h>
+#include <sys/wait.h>
+#endif
+
+#include <signal.h>
+
+#include <unistd.h>
+#include <setjmp.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void rem_escape_newlines(register char *);
+static void snap_finish(void);
+static void setup_interactive(void);
+static void add_iahist(void);
+static int32 get_iahcmdnum(void);
+static void grow_iahtab(void);
+static void rd_exec_iact_stmt(int32);
+static void chk_iact_grefs(int32);
+static void init_iahctrl(struct hctrl_t *);
+static void init_sched_iathd(struct hctrl_t *);
+static struct thread_t *bld_immed_iathrd(struct st_t *);
+static void free_iact_glbs(struct gref_t *, int32);
+static void renumber_1stmt(struct st_t *, int32, int32);
+static void renumber_csitemlst(register struct csitem_t *, int32, int32);
+static void renumber_stlst(register struct st_t *, int32, int32);
+static int32 prt1_iahist_cmd(int32);
+static void free_done_iact_control(struct hctrl_t *, int32);
+static int32 do_dbg_cmd(void);
+static void cmd_illegal_msg(char *);
+static int32 dbcmd_prefix_rep(register int32, char *, int32, struct namlst_t *, int32);
+static void do_dbg_help(void);
+static void wr_dbg_hlpmsg(char **);
+static void wr_dbg_lstofcmds(struct namlst_t *, int32);
+static void dbg_print(void);
+static char *dbg_bld_expr_val(char *, struct expr_t *, int32, int32, int32);
+static void dbg_display(void);
+static void prt_all_disp_exprs(void);
+static char *bld_prtbasecode(char *, int32, int32, int32);
+static void do_dbg_expris(void);
+static char *bld_expr_telltale(char *, struct expr_t *);
+static void do_dbg_varis(void);
+static void print_iddecl_ref(struct sy_t *, struct sy_t *);
+static void do_dbg_whatis(void);
+
+/* extern prototypes (maybe defined in this module) */
+extern char *__my_malloc(int32);
+extern FILE *__tilde_fopen(char *, char *);
+extern char *__pv_stralloc(char *);
+extern struct task_t *__find_thrdtsk(struct thread_t *);
+extern void __set_dbentry_listline(void);
+extern void __call_misctfs_iact(void);
+extern void __vpi_enteriact_trycall(void);
+extern void __call_misctfs_scope(void);
+extern void __vpi_iactscopechg_trycall(void);
+extern int32 __rd_ialine(void);
+extern void __my_fclose(FILE *);
+extern void __call_misctfs_finish(void);
+extern void __vpi_endsim_trycall(void);
+extern void __get_vtok(void);
+extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern void __vpi_exitiact_trycall(void);
+extern int32 __chk_extra_atend(int32);
+extern char *__prt_vtok(void);
+extern void __do_iact_disable(struct hctrl_t *, int32);
+extern char *__to_timstr(char *, word64 *);
+extern void __write_snapshot(int32);
+extern void __my_ftime(time_t *, time_t *);
+extern void __prt_end_msg(void);
+extern void __add_infil(char *);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern char *__my_realloc(char *, int32, int32);
+extern void __grow_tevtab(void);
+extern struct st_t *__rd_stmt(void);
+extern void __chk_lstofsts(struct st_t *);
+extern void __chk_nodel_lstofsts(struct st_t *);
+extern struct st_t *__prep_lstofsts(struct st_t *, int32, int32);
+extern void __free_1stmt(struct st_t *);
+extern void __free_dceauxlst(struct dceauxlst_t *, int32);
+extern void __free_dceauxs_only(struct dceauxlst_t *);
+extern struct st_t *__brktr_exec_1stmt(struct st_t *);
+extern void __my_free(char *, int32);
+extern void __ia_warn(int32, char *, ...);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern struct thread_t *__alloc_thrd(void);
+extern void __add_ev_to_front(register i_tev_ndx);
+extern void __free_1glb_flds(struct gref_t *);
+extern char *__get_eval_cstr(struct expr_t *, int32 *);
+extern void __free_thd_list(struct thread_t *);
+extern void __free_1thd(struct thread_t *);
+extern int32 __get_dbcmdnum(char *, struct namlst_t *, int32);
+extern char *__bld_ambiguous_list(char *, char *, struct namlst_t *, int32);
+extern void __prt_where_msg(register struct thread_t *);
+extern void __do_dbg_list(void);
+extern void __do_dbg_set(void);
+extern void __do_dbg_info(void);
+extern void __do_dbg_dis_enable(int32);
+extern void __dbg_undisplay(void);
+extern int32 __get_dbg_val(void);
+extern void __do_dbg_history(void);
+extern void __do_dbg_emptyhistory(void);
+extern void __do_dbg_brkpt(int32);
+extern void __do_dbg_ibrkpt(int32);
+extern int32 __do_dbg_nextb(void);
+extern void __do_dbg_delbrkdis(void);
+extern void __do_dbg_scope(void);
+extern void __dbg_brk_ignore(void);
+extern void __dbg_brk_cond(void);
+extern void __wrap_puts(char *, FILE *);
+extern void __wrap_putc(int32, FILE *);
+extern struct expr_t *__rd_iact_expr(void);
+extern int32 __colto_eol(void);
+extern void __free_xtree(struct expr_t *);
+extern char *__strenexpr_tostr(char *, struct expr_t *);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern int32 __trim1_0val(word32 *, int32);
+extern char *__strab_tostr(char *, word32 *, int32, int32, int32);
+extern char *__regab2_tostr(char *, word32 *, word32 *, int32, int32, int32, int32);
+extern void __bld_xtree(int32);
+extern int32 __chk_rhsexpr(struct expr_t *, int32);
+extern int32 __bld_expnode(void);
+extern void __set_xtab_errval(void);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char *__to_opname(word32);
+extern char *__to_sytyp(char *, word32);
+extern char *__bld_showvars_prefix(char *, struct net_t *,
+ struct gref_t *grp);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern int32 __do_vpi_stop(int32);
+extern void __do_vpi_reset(int32, int32, int32);
+extern void __emit_vpi_noiact_warn(void);
+extern void __emit_vpi_iniact_warn(void);
+extern void __emit_stsk_endmsg(void);
+extern struct gref_t *__alloc_grtab(struct gref_t *, int32);
+extern void __init_mod(struct mod_t *, struct sy_t *);
+extern void __my_dv_flush(void);
+extern void __wr_dvtimstr(void);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern void __free_dce_prevval(struct dcevnt_t *, int32, int32);
+extern int32 __get_dcewid(struct dcevnt_t *, struct net_t *);
+extern int32 __get_pcku_chars(int32, int32);
+
+
+extern void __cv_msg(char *, ...);
+extern void __cvsim_msg(char *, ...);
+extern void __cvsim2_msg(char *, ...);
+extern void __cvsim3_msg(char *, ...);
+extern void __pv_warn(int32, char *,...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __pv_terr(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __my_exit(int32, int32);
+extern void __ia_err(int32 id_num, char *s, ...);
+
+extern char __pv_ctab[];
+
+/*
+ * STARTUP SIGNAL INITIALIZATION ROUTINES
+ */
+
+/*
+ * signal handler during compilation
+ * should put in alarm here
+ */
+extern void __comp_sigint_handler(void)
+{
+ char s1[RECLEN];
+
+ /* ignore ^c signal in here */ 
+ signal(SIGINT, SIG_IGN);
+ __cvsim2_msg(
+  "\nInterrupt (^C) occurred during translate/load, really quit? (y/n) ");
+ if (fgets(s1, RECLEN, stdin) == NULL) goto done;
+
+ if (s1[0] == 'y' || s1[0] == 'Y')
+  {
+   /* put back called signal */
+#if defined(INTSIGS)
+   signal(SIGINT, __old_int_sig);
+#else
+   signal(SIGINT, (void (*)()) __old_int_sig);
+#endif
+   __pv_terr(311, "translate/load terminated by interrupt (^C) signal");
+  }
+done:
+ /* why need to reset signal handler */
+#if defined(INTSIGS)
+ signal(SIGINT, __comp_sigint_handler);
+#else
+ signal(SIGINT, (void (*)()) __comp_sigint_handler);
+#endif
+}
+
+/*
+ * signal during execution 
+ * just set flag here - must be run to top level before catching
+ *
+ * all this does is set switch - caller must reset internal switch 
+ * when processed or ignored
+ */
+extern void __sim_sigint_handler(void)
+{
+ /* SJM 07/31/01 - think need message to indicate interrupt */
+ /* DBG remove -- */
+ __cvsim2_msg( "<INTERRUPT>\n");
+ /* --- */
+ __pending_enter_iact = TRUE;
+ __iact_reason = IAER_CTRLC;
+ /* if stepping, disable as if step completed */
+ __single_step = FALSE; 
+ __step_rep_cnt = 0;
+ __step_lini = -1;
+ __step_ifi = -1;
+/* REMOVEME - no longer supporting SunOS - maybe needed for hpux? */
+#if (defined(__sparc) && defined(__SVR4))
+ /* LOOKATME _ not sure why needed iact ^c leaves EINTR uncleared ?? */ 
+ if (__cmd_s != NULL) clearerr(__cmd_s);
+ clearerr(stdin);
+#endif
+#if (defined(__i386__) && defined(__SVR4))
+ /* LOOKATME _ not sure why needed iact ^c leaves EINTR uncleared ?? */ 
+ if (__cmd_s != NULL) clearerr(__cmd_s);
+ clearerr(stdin);
+#endif
+}
+
+/*
+ * interface to (only way program quits) to reset callers signal handler
+ *
+ * normally do_exit true but to return to caller called with do exit F 
+ */
+extern void __my_exit(int32 rc, int32 do_exit)
+{
+ int32 i;
+
+
+ /* put back entry signal */
+#ifdef INTSIGS
+   signal(SIGINT, __old_int_sig);
+#else
+   signal(SIGINT, (void (*)()) __old_int_sig);
+#endif
+
+ /* for antrim flush buffers */
+ /* always flush here in case of $finish */
+ if (__dv_fd != -1)
+  {
+   /* SJM 10/08/99 - need to write time at end for some wave form viewers */ 
+   __wr_dvtimstr();
+   __my_dv_flush();
+  }
+ if (__log_s != NULL) fflush(__log_s);
+ if (__tr_s != NULL) fflush(__tr_s);
+ for (i = 0; i < 31; i++) 
+  {
+   if (__mulchan_tab[i].mc_s != NULL) fflush(__mulchan_tab[i].mc_s);
+  }
+ if (do_exit) exit(rc);
+ return;
+}
+
+/*
+ * INTERACTIVE SETUP ROUTINES
+ */
+
+/*
+ * initialize interactive environment just before simulation begins
+ * but after all initialization wire evaluation finished
+ *
+ * since various interactive system tasks can appear in normal source
+ * this initializes those things - when interactive called real init done
+ * notice this is run with __iact_state off
+ */
+extern void __init_interactive(void)
+{ 
+ register int32 i;
+ struct sy_t *syp;
+
+ /* set up listing file - nothing open and no line pos. file cached */
+ __filpostab = NULL;
+ __list_cur_fd = -1;
+ /* use can change this with :set - number is one less than no. to list */
+ /* since prt src lines is from - to */ 
+ __list_cur_listnum = 9;
+ /* start at 1st top level */
+ /* force setting on first :l command */
+ __list_cur_ifi = -1;
+ __nxt_bpnum = 1; 
+ __bphdr = NULL;
+ __dispxhdr = NULL;
+ __nxt_dispxnum = 1;
+ __single_step = FALSE;
+ __step_rep_cnt = 0;
+ __step_from_thread = FALSE;
+ __step_match_itp = NULL;
+ __step_lini = -1;
+ __step_ifi = -1;
+ __verbose_step = FALSE;
+ __last_iasytp = NULL;
+
+ __last_stepitp = NULL;
+ __last_steptskp = NULL;
+ __last_stepifi = -1;
+ __last_brktime = 0xffffffffffffffffULL;
+
+ /* $scope start at first top level module - no old scope to push */
+ __scope_ptr = __it_roots[0];
+ __scope_tskp = NULL;
+
+ /* allocate interactive module - re-initialized each time iact entered */
+ /* 08/18/99 - for now only expr tab and glb tab fields used */
+ __iact_mdp = (struct mod_t *) __my_malloc(sizeof(struct mod_t)); 
+
+ syp = (struct sy_t *) __my_malloc(sizeof(struct sy_t));
+ syp->synam = __pv_stralloc("**IACT WORK**");
+ syp->sydecl = TRUE;
+
+ __init_mod(__iact_mdp, syp);
+ __iact_mdp->flatinum = 1;
+ syp->el.emdp = __iact_mdp;
+
+ /* default is now, use scope of entry in interactive, :set to use old */ 
+ __iact_scope_chg = TRUE; 
+ __dbg_dflt_base = BHEX;
+
+ /* notice line count and :list command line are unrelated - line count is */
+ /* source line number or command history number */
+ __lin_cnt = 1;
+ /* this forces getc to read from read interactive line */
+ __in_s = NULL;
+ __file_just_op = FALSE;
+ __first_linetok = FALSE; 
+ __cmd_fnam = NULL;
+ __cmd_s = NULL;
+
+ /* special code in get_env_sym so no environment here */
+ __venviron[0] = NULL;
+ 
+ /* LOOKATME - should read .[cverdbinit?] with history off */
+ __iahwrklen = 2*IDLEN + 8;
+ __iahwrkline = __my_malloc(__iahwrklen);
+ __hist_cur_listnum = 20;
+ __echo_iactcmds_tolog = TRUE;
+
+ /* setup history */
+ /* FIXME - need to wrap table not continue growing without limit */
+ __iahsiz = IAHISTSIZ;
+ __iahtab = (struct iahist_t *) __my_malloc(__iahsiz*sizeof(struct iahist_t));
+ /* must start with 0 since first add moves to real 1 start */
+ __iah_lasti = 0;
+ /* indexed from 1 but initialize from 0 */
+ for (i = 0; i < __iahsiz; i++)
+  { __iahtab[i].iah_lp = NULL; __iahtab[i].iah_hcp = NULL; }
+ __hctrl_hd =__hctrl_end = NULL;
+}
+
+/*
+ * INTERACTIVE DEBUGGER ROUTINES
+ */
+
+/*
+ * execute the interactive control loop
+ *
+ * unless -<num> or <num> form or not history on put into history list
+ * only break (ctrl-c), $stop, or -s command option tranfer control to here
+ * continue (.) does not return here unless ctrl-c or $stop() execed
+ * when events exhausted looks like $finish hit
+ * commands executed from here return to here
+ *
+ * debugger commands are not added to the history list 
+ * this runs with ctrl-c (int32) disabled
+ * upon entry, interrupt signal is SIGIGN
+ * also no current thread - run between processed events
+ * if entry from interactive non immediate $stop, no scope or file change
+ */
+extern void __do_interactive_loop(void)
+{
+ int32 histcmd_num, hist_rexec, rv, sav_lin_cnt, sav_cur_fnam_ind;
+ int32 chg_scope, still_stepping;
+ FILE *sav_cmd_s, *f;
+ char *sav_cmd_fnam;
+ struct iahist_t *iahp;
+ struct task_t *tskp;
+ struct sy_t *syp;
+ char s1[RECLEN], s2[RECLEN];
+
+ /* where call finish callbacks and exit when interactive turned off */
+ signal(SIGINT, SIG_IGN);
+
+ /* things needed on any entry to interactive */
+ /* if interactive mode off, just finish */
+ __iact_state = TRUE;
+ __pending_enter_iact = FALSE;
+ if (__no_iact) snap_finish();
+ /* if first time do some setup - not done after :reset or $reset */ 
+ if (!__iasetup)
+  {
+   setup_interactive(); 
+   __iasetup = TRUE;
+   __cvsim2_msg("Type :help for help\n");
+  }
+ if (!__ia_entered)
+  {
+   if (__cmd_start_fnam != NULL)
+    {
+     /* this was opened once to check but may be problem since then */
+     if ((f = __tilde_fopen(__cmd_start_fnam, "r")) == NULL)
+      {
+       __pv_warn(505, 
+        "now cannot open -i startup interactive input file %s - using stdin",
+        __cmd_start_fnam);
+      }
+     else
+      {
+       __cmd_s = f;
+       __cmd_fnam = __pv_stralloc(__cmd_start_fnam);
+      }  
+    }
+   __ia_entered = TRUE;
+  }
+ hist_rexec = FALSE;
+ sav_cmd_s = NULL;
+ sav_cmd_fnam = NULL; 
+ sav_cur_fnam_ind = -1;
+ sav_lin_cnt = -1;
+
+ /* for entry from iact ($stop?), use original scope of interactive */
+ /* unless turned off or sim not started, use entry proc. scope as scope */
+ if (__iact_scope_chg && __suspended_thd != NULL)
+  {
+   /* scheme if that is last thread (pending) was in task move to task */
+   /* if enterered from ^c but evaling event, may want scope change */
+   if (__fcspi >= 0) tskp = __fcstk[__fcspi];
+   else if (__suspended_thd->th_fj) tskp = __find_thrdtsk(__suspended_thd);
+   else tskp = __suspended_thd->assoc_tsk;
+   /* this pushes scope since iact flag on */
+   __scope_ptr = __suspended_itp;
+   __scope_tskp = tskp;
+   chg_scope = TRUE;
+  }
+ else chg_scope = FALSE;
+ /* whenever enter iact, must push scope (needs to be in inst. ptr) */ 
+ __push_itstk(__scope_ptr);
+
+ /* notice list line and scope now unrelated - but always can set from */
+ /* suspended thread next statement */
+ __set_dbentry_listline();
+
+ /* if stepping repeat count, decrement and continue execing */ 
+ still_stepping = FALSE;
+ if (__iact_reason == IAER_STEP && --__step_rep_cnt > 0)
+  {
+   /* save moved to line but continue stepping */
+   __single_step = TRUE;
+   __verbose_step = TRUE;
+   if (__suspended_thd == NULL || __suspended_thd->thnxtstp == NULL)
+    __step_from_thread = FALSE;
+   still_stepping = TRUE;
+   goto do_ret;
+  }
+ if (__tfrec_hdr != NULL) __call_misctfs_iact();
+ if (__have_vpi_actions) __vpi_enteriact_trycall();
+
+ if (chg_scope)
+  {
+   if (__tfrec_hdr != NULL) __call_misctfs_scope();
+   if (__have_vpi_actions) __vpi_iactscopechg_trycall();
+  }
+ /* process and pending display commands */
+ if (__dispxhdr != NULL) prt_all_disp_exprs();
+
+again:
+ /* hist rexec requires command and line no. from history - put back here */ 
+ /* re-execed history and now re-entering debugger so must change */
+ /* to input line world */
+ if (hist_rexec)
+  {
+   __cmd_s = sav_cmd_s;
+   __cmd_fnam = sav_cmd_fnam; 
+   __cur_fnam_ind  = sav_cur_fnam_ind;
+   __cur_fnam = __in_fils[__cur_fnam_ind];
+   __lin_cnt = sav_lin_cnt;
+   hist_rexec = FALSE;
+  }
+
+ /* write prompt if to screen if needed and/or to log file if exists */ 
+ /* here need to use next history location even though net yet filled */
+ if (__cmd_s == NULL && isatty(fileno(stdin)))
+  __cvsim2_msg("C%d > ", __iah_lasti + 1); 
+ /* LOOKATME - log file output only because typed in from terminal */
+ if (__echo_iactcmds_tolog && __log_s != NULL) 
+  __cvsim3_msg("C%d > ", __iah_lasti + 1); 
+
+ /* first read the entire command (possible multiple \[new line] lines */
+ /* notice only $finish gets out of this loop */
+ if (__vin_top > 0) __misc_terr(__FILE__, __LINE__);
+ rv =__rd_ialine();
+ if (rv == TEOF)
+  {
+   if (__cmd_s != NULL)
+    {
+     /* LOOKATME - think this is unneeded */
+     clearerr(__cmd_s);
+     __my_fclose(__cmd_s);
+     __cmd_s = NULL;
+     __cmd_fnam = NULL;
+     __cur_fnam = __in_fils[1];
+     __cur_fnam_ind = __cmd_ifi;
+     /* after close file must emit prompt */
+    }
+   else
+    {
+     if (isatty(fileno(stdin))) 
+      {
+       __ia_err(1403,
+        "EOF (^D or ^C) read from tty stdin - use :q or $finish; to exit program");
+       clearerr(stdin); 
+       goto again;
+      }
+     /* cver run from batch file - on eof of stdin execute $finish */
+     __ia_err(1406,
+      "EOF on non tty stdin (simulation run from script) - $finish executed");
+     if (__tfrec_hdr != NULL) __call_misctfs_finish();
+     if (__have_vpi_actions) __vpi_endsim_trycall();
+     __my_exit(2, TRUE);
+    }
+  }
+ /* if no $input (or -i) file, line is command number */
+ if (__cmd_s == NULL) __lin_cnt = __iah_lasti;
+num_reenable:
+ __visp->vichp = __iahwrkline;
+ /* since keywords ok in interactive, set beginning of line */
+ __first_num_eol = TRUE;
+
+ /* this is command parsing that requires tokenization */
+ __get_vtok(); 
+ if (__toktyp == TEOF) goto again;
+
+ switch ((byte) __toktyp) {
+  case TEOF: __case_terr(__FILE__, __LINE__); break; 
+  case COLON:
+   __get_vtok();
+   if (__toktyp == TEOF) 
+    {
+     if (__scope_tskp != NULL) syp = __scope_tskp->tsksyp; 
+     else syp = __scope_ptr->itip->imsym;
+     __cvsim_msg("scope: %s (at %s and :list at %s)\n",
+      __msg_blditree(__xs, __scope_ptr, __scope_tskp),
+      __bld_lineloc(s1, syp->syfnam_ind, syp->sylin_cnt),
+      __bld_lineloc(s2, (word32) __list_cur_ifi, __list_arg_lini));
+     goto again;
+    }
+   /* : debugger commands always go on history list unless hist re-exec */
+   if (__history_on && !hist_rexec) add_iahist();
+   /* implement : [debugger command] - handles errors */
+   if (!do_dbg_cmd())
+    {
+     /* if debug command some kind of step, if rexeced restore iact loc. */
+     if (hist_rexec)
+      {
+       __cmd_s = sav_cmd_s;
+       __cmd_fnam = sav_cmd_fnam; 
+       __cur_fnam_ind  = sav_cur_fnam_ind;
+       __cur_fnam = __in_fils[__cur_fnam_ind];
+       __lin_cnt = sav_lin_cnt;
+       hist_rexec = FALSE;
+      }
+     /* here even if re-exec dot, still treat as new step */ 
+     __step_lini = -1;
+     __step_ifi = -1;
+     goto do_ret;
+    }
+   else goto again;
+  case DOT:
+   __step_lini = -1;
+   __step_ifi = -1;
+do_ret:
+   if (!still_stepping && __have_vpi_actions) __vpi_exitiact_trycall();
+
+   __iact_state = FALSE;
+   /* if ^c hit in interactive debugger, unless command handles just ignore */ 
+   /* this is needed to stop, from immediate statement dbg enter */
+   /* on entry always push a scope, but must pop away before running again */
+   __pop_itstk();
+  /* need to enable sim sigint32 handler since turned off in iact loop */
+#if defined(INTSIGS)
+   signal(SIGINT, __sim_sigint_handler);
+#else
+   signal(SIGINT, (void (*)()) __sim_sigint_handler);
+#endif
+   __pending_enter_iact = FALSE;
+   __iact_reason = IAER_UNKN;
+   return;
+  case SEMI:
+   if (__optimized_sim)
+    {
+     /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
+     cmd_illegal_msg("';' step with no trace (use '.')");
+     goto again;
+    }
+
+   /* ; statement step with no trace */  
+step_setup:
+   __single_step = TRUE;
+   __step_rep_cnt = 1;
+   if (__iact_reason == IAER_CTRLC || __suspended_thd == NULL
+    || __suspended_thd->thnxtstp == NULL) __step_from_thread = FALSE;
+   __chk_extra_atend(TRUE);
+   goto do_ret;
+  case COMMA:
+   if (__optimized_sim)
+    {
+     /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
+     cmd_illegal_msg("',' step with trace (use '.')");
+     goto again;
+    }
+   /* , statement step with debugger trace */
+   /* notice -t tracing additional and independent */
+   __verbose_step = TRUE;
+   goto step_setup;
+  case MINUS:
+   __get_vtok();
+   if (__toktyp != NUMBER)
+    {
+     __ia_err(1410, "minus disable command number expected: %s read",
+      __prt_vtok());
+     goto again;
+    }
+   /* this emits own error */
+   if ((histcmd_num = get_iahcmdnum()) == -1) goto again;
+
+   iahp = &(__iahtab[histcmd_num]);
+   if (iahp->iah_hcp == NULL)
+    {
+     __ia_err(1412, "-%d disable failed: command already completed",
+      histcmd_num);
+     goto again;
+    }
+   /* disable the command and free control record */
+   __do_iact_disable(iahp->iah_hcp, FALSE);
+   goto again;
+  case NUMBER:
+   /* this emits own error */
+   if ((histcmd_num = get_iahcmdnum()) == -1) goto again;
+   /* since need eventual history support, free if needed and reparse */
+   if (__iahtab[histcmd_num].iah_hcp != NULL)
+    {
+     __ia_err(1416, "attempt to re-execute C%d failed: command not completed",
+      histcmd_num);
+     goto again;
+    }
+   /* must copy since can edit new and new probably goes in history */
+   strcpy(__iahwrkline, __iahtab[histcmd_num].iah_lp);
+   rem_escape_newlines(__iahwrkline);
+   /* save all line loc. state and set to history command no. */
+   sav_cmd_s = __cmd_s;
+   __cmd_s = NULL;
+   sav_cmd_fnam = __cmd_fnam;
+   __cmd_fnam = NULL;
+   sav_cur_fnam_ind = __cur_fnam_ind;
+   __cur_fnam_ind = __cmd_ifi;
+   __cur_fnam = __in_fils[1];
+   sav_lin_cnt = __lin_cnt; 
+   __lin_cnt = histcmd_num;
+   hist_rexec = TRUE;
+   goto num_reenable;
+  default:
+   /* schedule non immediate but never leave debugger from Verilog cmd */
+   rd_exec_iact_stmt(hist_rexec);
+   goto again;
+ }
+}
+
+/*
+ * when reparsing from history list must remove all escaped new lines
+ * since need to emit error message with only loc. history
+ */
+static void rem_escape_newlines(register char *lp)
+{
+ for (; *lp != '\0'; lp++)
+  {
+   if (*lp == '\\') { if (lp[1] == '\n') { *lp = ' '; lp[1] = ' '; lp++; } }
+  }
+}
+
+/*
+ * emit error if extra characters at end of line
+ * return F if more on line
+ */
+extern int32 __chk_extra_atend(int32 emit_err)
+{
+ register char *chp; 
+
+ chp = __visp->vichp;
+ while (vis_white_(*chp)) chp++;
+ if (*chp != '\0')
+  {
+   if (emit_err)
+    {
+     __ia_err(1413,
+      "interactive command extra characters [%s] at end discarded", chp);
+    }
+   return(FALSE);
+  }
+ return(TRUE);
+} 
+
+/*
+ * routine to write snapshot and quit on interrupt for debugging
+ * notice may not be scope when this called
+ */
+static void snap_finish(void)
+{
+ char s1[RECLEN];
+
+ __call_misctfs_finish();
+ if (__have_vpi_actions) __vpi_endsim_trycall();
+
+ /* return from interrupt signal handler */
+ __cvsim_msg(
+  "\nSimulation terminated by interrupt (^C) now %s (interactive debugger disabled)\n",
+  __to_timstr(s1, &__simtime));
+ if (__intsig_prt_snapshot)
+  {
+   /* DBG FIXME - for now just using large number */
+   if (__debug_flg) __write_snapshot(1000);
+   else __write_snapshot(DFLT_SNAP_EVS);
+  }
+
+ if (__verbose)
+  {
+   __my_ftime(&__end_time, &__end_mstime);
+   __prt_end_msg();
+  } 
+ __my_exit(0, TRUE);
+}
+
+/*
+ * setup the interactive loop - called first time interactive started only
+ * once setup just leave special interactive file on visp stack
+ */
+static void setup_interactive(void)
+{
+ /* input looks like reading from macro that is read ia line */
+ /* this justs stays present during simulation */
+ __visp = __vinstk[__vin_top];
+ __visp->vilin_cnt = 0;
+ __visp->vifnam_ind = __cmd_ifi;
+ __visp->vi_s = NULL;
+ /* this is set after each line is read */
+ __visp->vichp = NULL;
+
+ if (__cmd_s == NULL)
+  {
+   /* file is stdin */
+   __cur_fnam = __in_fils[1];
+   __cur_fnam_ind = __cmd_ifi;
+   /* line count will be set to command no. each time */
+   __lin_cnt = 0;
+  }
+ else
+  { 
+   /* start reading from -i interactive file */
+   __add_infil(__cmd_fnam);
+   __cur_fnam_ind = __last_inf;
+   __cmd_fnam = __in_fils[__cur_fnam_ind];
+   __lin_cnt = 0;
+  }
+ __lasttoktyp = UNDEF;
+ return;
+
+ /* -- FIXME - ADD KEY (for now no key file)
+ -* first entry to interactive - open key file if possible *-
+ if (__key_fnam != NULL)
+  {
+   if ((__key_s = __tilde_fopen(__key_fnam, "w")) == NULL)
+    {
+     __ia_err(1414,
+      "cannot open -k interactive input key file %s - trying default",
+      __key_fnam);
+     __my_free(__key_fnam, strlen(__key_fnam) + 1);
+     __key_fnam = NULL;
+     goto no_explicit;
+    }
+   return;
+  }
+
+no_explicit:
+ if ((__key_s = __tilde_fopen(DFLTKEYFNAM, "w")) == NULL)
+  {
+   __ia_err(1415, "cannot open default key file %s - no key file",
+    DFLTKEYFNAM);
+   return;
+  }
+ __key_fnam = __my_malloc(strlen(DFLTKEYFNAM) + 1);
+ strcpy(__key_fnam, DFLTKEYFNAM);
+ --- */
+}
+
+/*
+ * add a new entry to history queue - even if error entry must
+ * go in queue so can be edited
+ * this must be called after command read
+ *
+ * FIXME - ksh style editing not yet implemented
+ */
+static void add_iahist(void)
+{
+ struct iahist_t *iahp;
+
+ if (++__iah_lasti >= __iahsiz) grow_iahtab();
+ iahp = &(__iahtab[__iah_lasti]);
+ iahp->iah_lp = __pv_stralloc(__iahwrkline);
+ iahp->iah_hcp = NULL;
+ iahp->iah_itp = NULL;
+}
+
+/*
+ * check command number - message and F returned on error
+ * cannot use nd_ndxnum because no IS forms here and just need value
+ * notice both iahtab and command number start at 1 (0 unused)
+ */
+static int32 get_iahcmdnum(void)
+{
+ int32 base, cno;
+
+ if (__itoklen > WBITS)
+  {
+   if (!vval_is0_(&(__acwrk[1]), __itoklen - WBITS)
+    || !vval_is0_(__bcwrk, __itoklen))
+    {
+     base = BHEX;
+prt_err:
+     __ia_err(1418, "command history number %s invalid or out of range",
+      __regab_tostr(__xs, __acwrk, __bcwrk, __itoklen, base, FALSE)); 
+     return(-1);
+    }
+  }
+ else
+  {
+    if (!vval_is0_(__bcwrk, __itoklen)) { base = BHEX; goto prt_err; } 
+  }
+ cno = (int32) __acwrk[0];
+ if (cno < 1 || cno - 1 > __iah_lasti) { base = BDEC; goto prt_err; }
+ return(cno);
+}
+
+/*
+ * grow the interactive history table - no freeing and wrap for now
+ */
+static void grow_iahtab(void)
+{
+ register int32 i;
+ int32 old_iahsiz, osize, nsize;
+
+ old_iahsiz = __iahsiz;
+ osize = old_iahsiz*sizeof(struct iahist_t);
+ __iahsiz = (3*__iahsiz)/2; 
+ nsize = __iahsiz*sizeof(struct iahist_t);
+ __iahtab = (struct iahist_t *) __my_realloc((char *) __iahtab, osize,
+  nsize);
+ for (i = old_iahsiz; i < __iahsiz; i++)
+  { __iahtab[i].iah_lp = NULL; __iahtab[i].iah_hcp = NULL; }
+}
+/*
+ * ROUTINES TO IMPLMENT VERILOG STATEMENT EXECUTION DEBUGGER
+ */
+
+/* special external for setjmp environment - only used in v_ms.c */
+jmp_buf __iact_jmpbuf;
+jmp_buf __reset_jmpbuf;
+
+/*
+ * read and execute a Verilog interactive statement
+ * errors here go into total but maybe should not
+ *
+ * must execute statement with delay as named block with no vars
+ */
+static void rd_exec_iact_stmt(int32 hist_rexec)
+{
+ int32 sav_err_cnt, sav_sfnam_ind, sav_slin_cnt, immed_exec;
+ int32 sav_itspi, sav_st_trace, sfnind, slcnt, first_stmt;
+ struct st_t *stp, *stp2, *stp3;
+ struct iahist_t *iahp;
+ struct hctrl_t *hcp;
+
+ /* free any globals from immediate exec unless monitor/strobe sys task */
+ __iact_can_free = TRUE;
+
+ /* DBG remove -- */
+ if (__iact_dcehdr != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ sav_sfnam_ind = __sfnam_ind;
+ sav_slin_cnt = __slin_cnt;
+ __sfnam_ind = __cur_fnam_ind;
+ __slin_cnt = __lin_cnt;
+ sav_err_cnt = __pv_err_cnt;
+
+ /* on setup returns 0, if get here from call to long jump, all done */
+ if (setjmp(__iact_jmpbuf) != 0)
+  {
+   /* get here only on error - must skip and read token or macro vinstk */
+   /* will not be popped back to 0 */
+   for (;;) { if (__toktyp == TEOF) break; __get_vtok(); }
+   /* possible that parse error occured with something pushed back */
+   __lasttoktyp = UNDEF;
+   /* LOOKATME - may be minor memory leak for compound stmt with errors */
+   goto free_ds;
+  }
+ __iact_stmt_err = FALSE;
+ first_stmt = TRUE;
+more_stmts:
+ /* if error almost certainly with go to setdump code */
+ /* unless undeclared problem */
+ if ((stp = __rd_stmt()) == NULL) { __iact_stmt_err = TRUE; goto free_ds; }
+ 
+ if (__pv_err_cnt != sav_err_cnt)
+  { __iact_stmt_err = TRUE; goto free_stmts_done; }
+
+ /* since know syntax good errors here, do not return */
+ __cur_tsk = NULL;
+ __iact_must_sched = FALSE;
+ __chk_lstofsts(stp);
+ if (__pv_err_cnt != sav_err_cnt)
+  { __iact_stmt_err = TRUE; goto free_stmts_done; }
+ __nbsti = -1;
+ __task_has_delay = FALSE;
+ __task_has_tskcall = FALSE;
+ /* $stop or any loop in interactive requires scheduling */
+ __chk_nodel_lstofsts(stp);
+ if (__pv_err_cnt != sav_err_cnt)
+  { __iact_stmt_err = TRUE; goto free_stmts_done; }
+ if (__task_has_delay || __task_has_tskcall || __iact_must_sched)
+  immed_exec = FALSE;
+ else immed_exec = TRUE;
+
+ /* notice always re-execing from history in current scope */
+ /* so to reenable an edge or change breakpoint user must insure either */
+ /* uses rooted names or scope is set to right place */  
+ /* check and emit warning for non rooted interactive globals if from */
+ /* history re-exec since no way to tell if from same itree loc. */
+ chk_iact_grefs(hist_rexec);
+
+ /* delay times are tfmt time units not time unit from current scope */
+ __sav_mtime_units = __inst_mod->mtime_units;
+ __inst_mod->mtime_units = __tfmt_units;
+ /* rest of fields used from curr scope itree location */ 
+ __prpsti = 0;
+ __nbsti = -1;
+ __prpstk[0] = NULL;
+ __iact_dcehdr = NULL;
+ stp = __prep_lstofsts(stp, FALSE, FALSE);
+ 
+ if (__pv_err_cnt != sav_err_cnt)
+  {
+   __iact_stmt_err = TRUE;
+free_stmts_done:
+   /* interactive always exactly 1 inst. */
+   if (__iact_can_free)
+    {
+     for (stp2 = stp; stp2 != NULL;)
+      { stp3 = stp2->stnxt; __free_1stmt(stp2); stp2 = stp3; }
+    }
+free_ds:
+   /* SJM 01/02/03 - since never gening iops for interactive - ok because */
+   /* only get here on error */
+   if (__iact_can_free && __iact_dcehdr != NULL)
+    {
+     __free_dceauxlst(__iact_dcehdr, 1);
+     __iact_dcehdr = NULL;
+    }
+
+   if (__grwrknum > 0)
+    {
+     register int32 gri;
+     int32 osize, nsize;
+     struct gref_t *grp; 
+
+     /* for monitor/strobe must add globals to iact mod table */
+     if (__iact_can_free)
+      {
+       grp = &(__grwrktab[0]); 
+       for (gri = 0; gri < __grwrknum; gri++, grp++) __free_1glb_flds(grp); 
+      }
+     else
+      {
+       /* need to copy grefs to iact module gr table so when interactive */
+       /* scheduled statement executes can access grefs */
+       if (__iact_mdp->mgrnum == 0)  
+        {
+         __iact_mdp->mgrtab = (struct gref_t *)
+           __my_malloc(__grwrknum*sizeof(struct gref_t));
+         memcpy(__iact_mdp->mgrtab, __grwrktab,
+          __grwrknum*sizeof(struct gref_t));
+        }
+       else
+        {
+         osize = __iact_mdp->mgrnum*sizeof(struct gref_t);
+         nsize = (__iact_mdp->mgrnum + __grwrknum)*sizeof(struct gref_t);
+         __iact_mdp->mgrtab = (struct gref_t *)
+          __my_realloc((char *) __inst_mod->mgrtab, osize, nsize);
+
+         memcpy(&(__iact_mdp->mgrtab[__iact_mdp->mgrnum]), __grwrktab,
+          __grwrknum*sizeof(struct gref_t));
+        } 
+       __iact_mdp->mgrnum += __grwrknum;
+       /* then fix up expr ptrs for all */
+       grp = &(__iact_mdp->mgrtab[0]);
+       for (gri = 0; gri < __iact_mdp->mgrnum; gri++, grp++)
+        { grp->gxndp->ru.grp = grp; }
+      }
+     __grwrknum = 0;
+    }
+   goto done;
+  }
+
+ if (immed_exec)
+  {
+   /* DBG remove -- */
+   if (__iact_dcehdr != NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   if (__history_on && !hist_rexec && first_stmt) add_iahist();
+   /* in case exit with ^c (infinite loop?) restore entry itree loc. */
+   sav_itspi = __itspi;
+   /* must never trace immediate debugger commands */
+   sav_st_trace = __st_tracing; 
+   __st_tracing = FALSE;
+   /* notice normally no thread while in interactive mode */
+   __cur_thd = bld_immed_iathrd(stp);
+   __cur_thd->th_itp = __scope_ptr;
+   for (;;)
+    {
+     stp = __brktr_exec_1stmt(stp);
+     if (stp == NULL) break;
+     if (__pending_enter_iact)  
+      {
+       __cvsim2_msg(
+        "\nInterrupt (^C) during immediate interactive execution, reenter debugger? (y/n) ");
+       if (fgets(__xs, RECLEN, stdin) != NULL
+        && (__xs[0] == 'y' || __xs[0] == 'Y'))
+        {
+         __pending_enter_iact = FALSE;
+         /* may be executing xmr func. when ^c hit */
+         __itspi = sav_itspi;
+         break; 
+        }
+      }
+    }
+   __st_tracing = sav_st_trace; 
+   /* DBG remove --- */
+   if (__cur_thd == NULL) __misc_terr(__FILE__, __LINE__);
+   /* ---*/
+   /* notice thread just used as dummy place holder so nothing used */
+   __my_free((char *) __cur_thd, sizeof(struct thread_t)); 
+   __cur_thd = NULL;
+   goto free_stmts_done;
+  }
+
+ /* build and link on to history list the ia statement */
+ hcp = (struct hctrl_t *) __my_malloc(sizeof(struct hctrl_t));
+ init_iahctrl(hcp);
+
+ sfnind = __cmd_ifi;
+ if (hist_rexec)
+  {
+   iahp = &(__iahtab[__lin_cnt]);
+   hcp->hc_lini = __lin_cnt;
+   iahp->iah_hcp = hcp;
+   hcp->hc_ifi = __cmd_ifi;
+   hcp->hc_iahp = iahp;
+   slcnt = __lin_cnt;
+  } 
+ else if (__history_on)
+  {
+   add_iahist();
+   iahp = &(__iahtab[__iah_lasti]);
+   hcp->hc_lini = __iah_lasti;
+   iahp->iah_hcp = hcp;
+   hcp->hc_ifi = __cmd_ifi;
+   hcp->hc_iahp = iahp;
+   slcnt = __iah_lasti;
+  }
+ else slcnt = 1; 
+
+ /* always put on end of doubly linked list */
+ renumber_1stmt(stp, sfnind, slcnt);
+
+ hcp->hc_stp = stp;
+ hcp->hc_itp = __scope_ptr;
+ if (__hctrl_hd == NULL) __hctrl_hd = __hctrl_end = hcp;
+ else
+  { 
+   __hctrl_end->hc_nxt = hcp;
+   hcp->hc_prev = __hctrl_end;
+   __hctrl_end = hcp;
+  }
+ hcp->hc_dcelst = __iact_dcehdr;   
+ __iact_dcehdr = NULL;
+
+ /* allocate new gref table for later use if command in history list execed */ 
+ /* only freed if statement removed from history list */
+ if (__grwrknum > 0)
+  {
+   hcp->hc_grtab = __alloc_grtab(__grwrktab, __grwrknum);
+   hcp->hc_numglbs = __grwrknum;
+   __grwrknum = 0;
+  }
+
+ init_sched_iathd(hcp);
+
+done:;
+ if (!__iact_stmt_err && !__chk_extra_atend(FALSE))
+  {
+   first_stmt = FALSE;
+   __get_vtok(); 
+   /* DBG remove --- */
+   if (__toktyp == TEOF) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   goto more_stmts;
+  }
+ /* only way to exit exec iact stmt routine */
+ __inst_mod->mtime_units = __sav_mtime_units;
+ __sfnam_ind = sav_sfnam_ind;
+ __slin_cnt = sav_slin_cnt;
+}
+
+/*
+ * check all xmr's from this statement
+ */
+static void chk_iact_grefs(int32 hist_rexec)
+{
+ register int32 gri;
+ register struct gref_t *grp;
+
+ grp = &(__grwrktab[0]);
+ for (gri = 0; gri < __grwrknum; gri++, grp++)
+  {
+   if (grp->gr_gone || grp->gr_err) continue;
+   if (hist_rexec)
+    {
+     if (!grp->is_rooted)
+      {
+       __ia_warn(1601,
+        "statement has non rooted global %s - scope instance %s may differ from original",
+        grp->gnam, __msg2_blditree(__xs, __inst_ptr));
+      }
+    }
+  }
+}
+
+/*
+ * initialize an history suspended statement record 
+ */
+static void init_iahctrl(struct hctrl_t *hcp)
+{
+ hcp->hc_stp = NULL;
+ hcp->hc_thp = NULL;
+ hcp->hc_itp = NULL;
+ hcp->hc_lini = 0;
+ hcp->hc_ifi = 0;
+ hcp->hc_nxt = hcp->hc_prev = NULL;
+ hcp->hc_iahp = NULL;
+ hcp->hc_dcelst = NULL;
+ hcp->hc_grtab = NULL;
+ hcp->hc_numglbs = 0;
+}
+
+/*
+ * build the interactive statement thread and schedule event
+ * this runs in current interactive scope itp
+ * when finishes just terminates like any other thread - maybe in 0 time
+ */
+static void init_sched_iathd(struct hctrl_t *hcp)
+{
+ struct thread_t *thp;
+ i_tev_ndx tevpi;
+ 
+ /* allocate thread and event and fill links */
+ alloc_tev_(tevpi, TE_THRD, hcp->hc_itp, __simtime);
+ thp = __alloc_thrd();
+ thp->th_hctrl = hcp;
+ thp->thdtevi = tevpi;
+ thp->thenbl_sfnam_ind = __cmd_ifi;
+ thp->thenbl_slin_cnt = __iah_lasti;
+ thp->th_itp = hcp->hc_itp;
+ __tevtab[tevpi].tu.tethrd = thp;
+ thp->thnxtstp = hcp->hc_stp;
+ thp->thpar = NULL;
+ hcp->hc_thp = thp; 
+
+ /* here can just add to front of event list - best to get started */ 
+ /* LOOKATME - notice no longer need to add to front - just more coherent */
+ __add_ev_to_front(tevpi);
+}
+
+/*
+ * for immediate exec, allocate and set dummy current thread
+ */
+static struct thread_t *bld_immed_iathrd(struct st_t *stp)
+{
+ struct thread_t *thp;
+
+ thp = __alloc_thrd();
+ thp->thenbl_sfnam_ind = __cmd_ifi;
+ thp->thenbl_slin_cnt = __iah_lasti;
+ thp->thnxtstp = stp; 
+ thp->thpar = NULL;
+ return(thp);
+}
+
+/*
+ * free iact globals
+ * notice caller sets iact gref table to empty
+ */
+static void free_iact_glbs(struct gref_t *grtab, int32 grnum)
+{
+ register int32 gri;
+ register struct gref_t *grp; 
+ 
+ for (gri = 0, grp = &(grtab[0]); gri < grnum; gri++, grp++)
+  { __free_1glb_flds(grp); }
+ __my_free((char *) grtab, grnum*sizeof(struct gref_t));
+}
+
+/*
+ * free a list dce's (for monit/fmonit, qcaf and tf_ parameter change)
+ * if optimized sim on and no syntax error, nd regen T else F
+ * only called when free interactive dce list vpi_ call back lists
+ *
+ * caller may need to set header to nil
+ * this works (does nothing) if called with nil dcehdr 
+ * LOOKATME - if doubly linked would be faster
+ *
+ * SJM 06/21/02 - now only PLI and reset call this to remove from dce list
+ * LOOKATME - think assuming trigger set to regen iops called
+ *
+ * SJM 12/30/02 - must not call this routine except on interactive debugger
+ * syntax error if -O on
+ *
+ * LOOKATME - here removing monit dce's because only freed if added
+ * from interactive mode
+ */
+extern void __free_dceauxlst(struct dceauxlst_t *dcehdr, int32 numinsts)
+{
+ register struct dceauxlst_t *dclp;
+ register struct dcevnt_t *dcep2;
+ struct dcevnt_t *dcep, *last_dcep;
+ struct net_t *np;
+
+  /* DBG remove -- must not call if -O used */
+  if (__optimized_sim) __misc_terr(__FILE__, __LINE__);
+  /* -- */
+
+ /* remove all dc events that were added for this delay control event */
+ for (dclp = dcehdr; dclp != NULL; dclp = dclp->dclnxt)
+  {
+   /* get the dce to free */
+   dcep = dclp->ldcep; 
+
+   /* since list not doubly linked must search thru list saving last */
+   /* BEWARE - except for dmpv on front removable dces can be put anywhere */
+   /*          on list so can not optimize this */
+   np = dcep->dce_np;
+
+   last_dcep = NULL;
+   for (dcep2 = np->dcelst; dcep2 != NULL; dcep2 = dcep2->dcenxt)
+    {
+     if (dcep == dcep2)
+      {
+       if (last_dcep == NULL)
+        {
+         np->dcelst = dcep->dcenxt;
+         /* SJM - 06/30/00 - dce list now empty - deactivate ev ctrl wakeups */
+         /* LOOKATME - can this really ever happen */
+         if (np->dcelst == NULL)
+          {
+           /* SJM 07/24/00 - may be off if reg - turning off again ok */
+           np->nchg_has_dces = FALSE;
+           if (np->nlds == NULL && !np->n_hasdvars)
+            np->nchg_nd_chgstore = FALSE;
+           /* notice do not use all changed always on optimization here */
+          }
+        }
+       else last_dcep->dcenxt = dcep->dcenxt;
+
+       /* now that linked out, can regen net's list */
+       /* for XMR, may need to move to different mod */
+       /* if remove last, still regen to free and does not stop recording */
+
+       /* if no dce value, does nothing */
+       __free_dce_prevval(dcep, numinsts, __get_dcewid(dcep, np));
+       __my_free((char *) dcep, sizeof(struct dcevnt_t));
+       dcep = NULL;
+       goto nxt_dce;
+      }
+     last_dcep = dcep2;
+    }
+   __misc_terr(__FILE__, __LINE__);
+nxt_dce:;
+  }
+ /* finally free the dce list - know dce of element already freed */ 
+ __free_dceauxs_only(dcehdr);
+}
+
+/*
+ * free a dce list - know dce of each element already freed
+ */
+extern void __free_dceauxs_only(struct dceauxlst_t *dcehdr)
+{
+ register struct dceauxlst_t *dclp, *dclp2;
+
+ for (dclp = dcehdr; dclp != NULL;)
+  {
+   dclp2 = dclp->dclnxt;
+   __my_free((char *) dclp, sizeof(struct dceauxlst_t));  
+   dclp = dclp2;
+  }
+}
+
+/*
+ * free a dce previous value field 
+ * if none, does nothing
+ */
+extern void __free_dce_prevval(struct dcevnt_t * dcep, int32 insts, int32 dcewid)
+{
+ int32 totchars;
+ struct net_t *np;
+
+ /* SJM 05/05/03 - for rooted XMR dce - only 1 inst allocated */
+ if (dcep->dce_1inst) insts = 1;
+ if (dcep->dce_expr != NULL && dcep->dce_expr->mast_dcep == dcep) 
+  {
+   totchars = __get_pcku_chars(dcewid, insts);
+   __my_free((char *) dcep->dce_expr->bp, totchars);
+   dcep->dce_expr->bp = NULL;
+  }
+
+ /* if dce on array or entire non wire (reg), will not have saved val. */
+ if (dcep->prevval.wp == NULL) return;
+
+ np = dcep->dce_np;
+ if (np->n_stren) totchars = dcewid*insts;
+ else totchars = __get_pcku_chars(dcewid, insts);
+ __my_free((char *) dcep->prevval.bp, totchars);
+ dcep->prevval.bp = NULL;
+}
+
+/*
+ * ROUTINES TO RENUMBER STATEMENTS
+ */
+
+/*
+ * renumber a statement - for use when adding to commnd history
+ * statement can be head of compound
+ */
+static void renumber_1stmt(struct st_t *stp, int32 sfnind, int32 slcnt)
+{
+ int32 fji;
+ struct for_t *frp;
+ struct st_t *fjstp;
+
+ if (stp == NULL) return;
+
+ /* always set statement body line */
+ stp->stfnam_ind = (word32) sfnind;
+ stp->stlin_cnt = slcnt;
+
+ switch ((byte) stp->stmttyp) {
+  /* simple statement just set number */
+  case S_NULL: case S_STNONE:
+  case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA: case S_NBPROCA:
+  case S_TSKCALL: case S_QCONTA: case S_QCONTDEA: case S_CAUSE:
+  case S_DSABLE: case S_REPSETUP: case S_REPDCSETUP: case S_GOTO:
+   break;
+  case S_IF:
+   renumber_stlst(stp->st.sif.thenst, sfnind, slcnt);
+   renumber_stlst(stp->st.sif.elsest, sfnind, slcnt);
+   break;
+  case S_CASE:
+   /* first always default or place holder for missing default */
+   renumber_csitemlst(stp->st.scs.csitems->csinxt, sfnind, slcnt);
+   /* if has default, know has default statement */
+   if (stp->st.scs.csitems->csist != NULL)
+    renumber_stlst(stp->st.scs.csitems->csist, sfnind, slcnt);
+   break;
+  case S_REPEAT:
+   renumber_stlst(stp->st.srpt.repst, sfnind, slcnt);
+   break;
+  case S_FOREVER:
+  case S_WHILE:
+   renumber_stlst(stp->st.swh.lpst, sfnind, slcnt);
+   break;
+  case S_WAIT:
+   /* LOOKATME - is there a action statement that needs to be renumbered */
+   renumber_stlst(stp->st.swait.lpst, sfnind, slcnt);
+   break;
+  case S_FOR:
+   frp = stp->st.sfor;
+   /* notice for assign already freed */
+   renumber_1stmt(frp->forinc, sfnind, slcnt);
+   renumber_stlst(frp->forbody, sfnind, slcnt);
+   break;
+  case S_DELCTRL:
+   if (stp->st.sdc->actionst != NULL)
+    renumber_stlst(stp->st.sdc->actionst, sfnind, slcnt);
+   break;
+  case S_UNBLK:
+   renumber_stlst(stp->st.sbsts, sfnind, slcnt);
+   break;
+  case S_UNFJ:
+   /* renumber statement ptr table each of which may be st list */
+   for (fji = 0;; fji++)
+    {
+     if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+     renumber_stlst(fjstp, sfnind, slcnt);
+    }
+   break;
+  /* notice named block non freeable (at least for now) */
+  default: __case_terr(__FILE__, __LINE__);
+  }
+}
+
+/*
+ * renumber case item list statements
+ */
+static void renumber_csitemlst(register struct csitem_t *csip, int32 sfnind,
+ int32 slcnt)
+{
+ for (;csip != NULL; csip = csip->csinxt)
+  { renumber_stlst(csip->csist, sfnind, slcnt); }
+}
+
+/*
+ * renumber each statement of a list to same history statement list number
+ */
+static void renumber_stlst(register struct st_t *stp, int32 sfnind, int32 slcnt)
+{
+ for (; stp != NULL; stp = stp->stnxt) renumber_1stmt(stp, sfnind, slcnt);
+}
+
+/*
+ * INTERACTIVE COMMAND EXECUTION ROUTINES
+ */
+
+/*
+ * escape from debugging environment to unix shell
+ * for now no system task - can use $input
+ *
+ * know interactive environment always run with SIG_IGN but shell needs
+ * default so ^c get out of shell
+ */
+extern void __escape_to_shell(char *argchp)
+{
+ int32 rc, status, pid;
+ char *chp, *usersh;
+
+ /* signal(SIGINT, SIG_DFL); */ 
+
+ if ((usersh = (char *) getenv ("SHELL")) == NULL) usersh = "/bin/sh";
+ if ((chp = strrchr(usersh, '/')) == NULL) chp = usersh; else chp++;
+ if ((pid = fork()) == 0)
+  {
+   if (*argchp == '\0') execl(usersh, chp, (char *) 0);
+   else execl(usersh, chp, "-c", argchp, (char *) 0);
+   if (__iact_state)
+    __ia_err(983, "OS Failure - user shell escape execl system call failed");
+   else __sgferr(983,
+    "OS Failure - user shell escape execl system call failed");
+   return;
+  }
+ if (pid != -1) { while ((rc = wait(&status)) != pid && rc != -1) ; }
+ else
+  {
+   if (__iact_state)
+    __ia_err(983, "OS Failure - user shell escape fork system call failed");
+   else __sgferr(983,
+    "OS Failure - user shell escape fork system call failed");
+  }
+/* need to enable sim sigint32 handler even if called from :shell */  
+/* ---
+#if defined(INTSIGS)
+ signal(SIGINT, __sim_sigint_handler);
+#else
+ signal(SIGINT, (void (*)()) __sim_sigint_handler);
+#endif
+--- */
+}
+
+/*
+ * exec the $input for interactive command input source system task
+ * here open cmd file and closes previous - new file is chained not nested
+ * if this appears in source, just change for next time enter interactive
+ */
+extern void __exec_input_fnamchg(struct expr_t *axp)
+{
+ int32 slen;
+ FILE *tmp_s;
+ char *chp;
+
+ /* msgexpr uses __exprline but if error not filled anyway */
+ chp = __get_eval_cstr(axp->lu.x, &slen);
+ if ((tmp_s = __tilde_fopen(chp, "r")) == NULL)
+  {
+   __sgferr(1241, "cannot open $input interactive command file %s", chp);
+   goto done;  
+  }
+ if (__cmd_s != NULL) __my_fclose(__cmd_s);
+ __cmd_s = tmp_s;
+ if (feof(__cmd_s))
+  {
+   __sgfwarn(610, "$input interactive command file %s empty", chp);
+   /* here just go back to stdin */
+   __cmd_s = NULL;
+   __cmd_fnam = NULL;
+   __cur_fnam = __in_fils[1];
+   __cur_fnam_ind = __cmd_ifi;
+   __lin_cnt = __iah_lasti;
+   goto done;
+  }
+ __add_infil(chp);
+ __cur_fnam_ind = __last_inf;
+ __cmd_fnam = __in_fils[__cur_fnam_ind];
+ __lin_cnt = 0;
+ if (__verbose)
+  __cv_msg("  Reading interactive commands from file \"%s\".\n", __cur_fnam);
+
+done:
+ __my_free(chp, slen + 1);
+} 
+
+/*
+ * execute the $history list system task
+ * extension allows optional number (how many to list) arg
+ * prompt after 20 lines (including embedded new lines) except finish 
+ */
+extern void __exec_history_list(int32 num)
+{
+ register int32 i;
+ int32 h_start, nlines;
+ char s1[RECLEN];
+
+ if (num == 0) h_start = 1;
+ else { if ((h_start = __iah_lasti - num + 1) <= 1) h_start = 1; }
+ for (nlines = 0, i = h_start; i <= __iah_lasti; i++)
+  {
+   nlines += prt1_iahist_cmd(i);
+   if (nlines > __hist_cur_listnum)
+    {
+     nlines = 0;
+     __cvsim2_msg("Press return to continue:");
+     fgets(s1, RECLEN, stdin);
+    }
+  }
+}
+
+/*
+ * print one history entry - may be muliple line (with embedded new lines)  
+ * returns number of lines listed (for mulitple line)
+ */
+static int32 prt1_iahist_cmd(int32 iahi)
+{
+ int32 first_time, prmplen, numlines;
+ struct iahist_t *iahp;
+ char c, save_ch, *chp, *chp2, s1[RECLEN];
+
+ numlines = 1;
+ iahp = &(__iahtab[iahi]);
+ /* notice when non immediate statement finishes, disable turned on */ 
+ if (iahp->iah_hcp != NULL) c = '*'; else c = ' ';
+ sprintf(s1, "C%d%c ", iahi, c);
+ __cvsim_msg(s1);
+
+ prmplen = strlen(s1);
+ __blnkline[prmplen] = '\0';
+ for (chp = iahp->iah_lp, first_time = TRUE;;) 
+  {
+   if ((chp2 = strchr(chp, '\\')) != NULL)
+    {
+     chp2++;
+     if (*chp2 == '\n')
+      {
+       chp2++;
+       save_ch = *chp2;
+       *chp2 = '\0';
+       /* notice this has the \\\n */
+       if (first_time) { __cvsim_msg("%s", chp); first_time = FALSE; }
+       else __cvsim_msg("%s%s", __blnkline, chp);
+       *chp2 = save_ch;
+       chp = chp2;
+       numlines++;
+       continue;
+      }
+    }
+   /* notice no ending \n */
+   if (first_time) __cvsim_msg("%s\n", chp);
+   else __cvsim_msg("%s%s\n", __blnkline, chp);
+   break;
+  }
+ __blnkline[prmplen] = ' ';
+ return(numlines);
+}
+
+/* 
+ * ROUTINES FOR INTERACTIVE DISABLE AND THREAD FREEING
+ */
+
+/*
+ * exec disable of interactive thread
+ * this disables and free entire statement 
+ */
+extern void __do_iact_disable(struct hctrl_t *hcp, int32 lv_ctrl)
+{
+ struct thread_t *thp;
+
+ thp = hcp->hc_thp;
+ /* if any active down threads, task enables or fjs - free/disable all */
+ if (thp->thofs != NULL) __free_thd_list(thp->thofs);
+ free_done_iact_control(hcp, lv_ctrl);
+ thp->th_dctp = NULL;
+ /* thread frees cancel any pending events - no parent */
+ __free_1thd(thp);
+}
+
+/*
+ * remove interactive thread and statement list
+ *
+ * also removes any globals associated with statement
+ */
+static void free_done_iact_control(struct hctrl_t *hcp, int32 lv_ctrl)
+{
+ register struct st_t *stp;
+ struct st_t *stp2;
+
+ /* free statements, if reenbled must parse again */
+ __push_wrkitstk(__iact_mdp, 0);
+ for (stp = hcp->hc_stp; stp != NULL;)
+  { stp2 = stp->stnxt; __free_1stmt(stp); stp = stp2; }
+ /* free any dces - know only 1 iact inst. */
+ if (hcp->hc_dcelst != NULL)
+  {
+   /* know can only be called once sim started SIM STATE */
+   __free_dceauxlst(hcp->hc_dcelst, 1);
+   /* but always remove from list */ 
+   hcp->hc_dcelst = NULL;
+  }
+ if (hcp->hc_numglbs > 0)
+  { 
+   free_iact_glbs(hcp->hc_grtab, hcp->hc_numglbs);
+   hcp->hc_grtab = NULL;
+   hcp->hc_numglbs = 0;
+  }
+ __pop_wrkitstk();
+
+ /* thread freed by caller, lv ctrl when all freed at once above */ 
+ if (!lv_ctrl)
+  {
+   if (hcp->hc_nxt != NULL) hcp->hc_nxt->hc_prev = hcp->hc_prev;
+   else
+    {
+     __hctrl_end = hcp->hc_prev;
+     if (__hctrl_end != NULL) __hctrl_end->hc_nxt = NULL;
+    }
+   if (hcp->hc_prev != NULL) hcp->hc_prev->hc_nxt = hcp->hc_nxt;
+   else
+    {
+     __hctrl_hd = hcp->hc_nxt;
+     if (__hctrl_hd != NULL) __hctrl_hd->hc_prev = NULL;
+    }  
+  }
+
+ /* if on history, free and mark inactive */
+ if (hcp->hc_iahp != NULL) hcp->hc_iahp->iah_hcp = NULL;
+ if (!lv_ctrl) __my_free((char *) hcp, sizeof(struct hctrl_t)); 
+}
+
+/*
+ * ROUTINES TO IMPLEMENTED EXTENDED : DEBUGGER COMMANDS
+ */
+
+/* table of debugger commands values */
+#define DB_HELP 0
+#define DB_SH 1
+#define DB_QUIT 2
+#define DB_WHERE 3
+#define DB_PRINT 4 
+#define DB_RESET 5
+#define DB_EXPRIS 6
+#define DB_VARIS 7
+#define DB_WHATIS 8
+#define DB_LIST 9
+#define DB_SET 10
+#define DB_INFO 11
+#define DB_SCOPE 12
+#define DB_BRKPT 13
+#define DB_IBRKPT 14
+#define DB_DELBRKDIS 15
+#define DB_BPDIS_ENABLE 16
+#define DB_BPDIS_DISABLE 17
+#define DB_STEP 18
+#define DB_ISTEP 19
+#define DB_HIST 20
+#define DB_EMPTHIST 21
+#define DB_DISPLAY 22
+#define DB_UNDISPLAY 23
+#define DB_TBRKPT 24
+#define DB_TIBRKPT 25
+#define DB_IGNORE 26
+#define DB_COND 27
+#define DB_SNAPSHOT 28
+#define DB_NEXTB 29
+
+/* debugger command name table (unordered) */
+static struct namlst_t dbcmds[] = {
+ { DB_HELP, ":help" }, 
+ { DB_SH, ":shell" },
+ { DB_QUIT, ":quit" },
+ { DB_WHERE, ":where" },
+ { DB_PRINT, ":print" },
+ { DB_RESET, ":reset" },
+ { DB_EXPRIS, ":expris" },
+ { DB_VARIS, ":varis" },
+ { DB_WHATIS, ":whatis" },
+ { DB_LIST, ":list" }, 
+ { DB_SET, ":set" }, 
+ { DB_INFO, ":info" }, 
+ { DB_SCOPE, ":scope" },
+ { DB_BRKPT, ":breakpoint" },
+ { DB_IBRKPT, ":ibreakpoint" },
+ { DB_DELBRKDIS, ":delete" },
+ { DB_BPDIS_ENABLE, ":enable" }, 
+ { DB_BPDIS_DISABLE, ":disabl" }, 
+ { DB_STEP, ":step" },
+ { DB_ISTEP, ":istep" },
+ { DB_HIST, ":history" },
+ { DB_EMPTHIST, ":emptyhistory" },
+ { DB_DISPLAY, ":display" },
+ { DB_UNDISPLAY, ":undisplay" },
+ { DB_TBRKPT, ":tbreakpoint" },
+ { DB_TIBRKPT, ":tibreakpoint" },
+ { DB_IGNORE, ":ignore" },
+ { DB_COND, ":cond" },
+ { DB_SNAPSHOT, ":snapshot" },
+ { DB_NEXTB, ":nextb" }
+};
+#define NDBCMDS (sizeof(dbcmds) / sizeof(struct namlst_t))
+
+/*
+ * process a colon command
+ *
+ * this must handle history updating - returns F on exit interactive 
+ * know : followed by non white space to get here and command token read 
+ */
+static int32 do_dbg_cmd(void)
+{
+ int32 rv, tmp;
+ char s1[IDLEN];
+
+ if (__toktyp != ID)
+  { 
+   sprintf(s1, ":%s", __prt_vtok());
+bad_colon_cmd:
+   __ia_err(1421, "undefined extended :[command] debugger command %s", s1); 
+   return(TRUE);   
+  }
+
+ strcpy(s1, ":");
+ strcat(s1, __token);
+
+ rv = __get_dbcmdnum(s1, dbcmds, NDBCMDS);
+ switch (rv) {
+  case -1: goto bad_colon_cmd;
+  case -2:
+   __ia_err(1422, "%s ambiguous debugger command: %s", s1,
+    __bld_ambiguous_list(__xs, s1, dbcmds, NDBCMDS));
+   break;
+  case DB_HELP:
+   do_dbg_help();
+chk_end:
+   __chk_extra_atend(TRUE);
+   break;
+  case DB_SH: 
+   if (__cmd_s != NULL) 
+    { 
+     __ia_err(1424,
+      "debugger shell escape cannot be invoked from $input file");
+     break;
+    }
+   /* must pass rest of line */
+   __escape_to_shell(__visp->vichp);
+   break;
+  case DB_QUIT:
+   __chk_extra_atend(TRUE);
+
+   if (__tfrec_hdr != NULL) __call_misctfs_finish();
+   if (__have_vpi_actions) __vpi_endsim_trycall();
+   __my_exit(0, TRUE);
+  case DB_WHERE:
+   /* write the trace back using suspended thread */
+   if (__suspended_thd == NULL)
+    __ia_err(1496,
+     ":where failed - no procedural context, single step and try again");
+   else
+    {
+     __cvsim_msg("Procedural thread trace back:\n");
+     __prt_where_msg(__suspended_thd);
+    }
+   goto chk_end; 
+  case DB_SNAPSHOT:
+   __write_snapshot(5);
+   goto chk_end;
+  case DB_PRINT:
+   dbg_print();
+   break;
+  case DB_RESET:
+   /* here do not change reset count or value and only enter interactive */
+   __get_vtok(); 
+   __dbg_stop_before = 100; 
+   if (__toktyp != TEOF)
+    {
+     if (__toktyp == ID && (strcmp(__token, "s") == 0
+      || strcmp(__token, "st") == 0 || strcmp(__token, "sto") == 0
+      || strcmp(__token, "stop") == 0)) __dbg_stop_before = 101;
+     else
+      {
+       __ia_err(1486, ":reset command argument %s not expected s or stop",
+        __prt_vtok());
+      } 
+    }
+   __cvsim2_msg("Simulation begun, really reset to start over? (y/n) ");
+   if (fgets(s1, RECLEN, stdin) == NULL || (s1[0] != 'y' && s1[0] != 'Y'))
+    break;
+   /* leaving interactive - and go back to compile ^c handler */
+   __iact_state = FALSE;
+   /* reenable the normal ^c signal handler */
+#if defined(INTSIGS)
+   signal(SIGINT, __comp_sigint_handler);
+#else
+   signal(SIGINT, (void (*)()) __comp_sigint_handler);
+#endif
+   __pop_itstk();
+   __reset_count--;
+   longjmp(__reset_jmpbuf, 1);
+   break;
+  case DB_EXPRIS:
+   do_dbg_expris();
+   break;
+  case DB_VARIS:
+   do_dbg_varis();
+   break;
+  case DB_WHATIS:
+   do_dbg_whatis();
+   break;
+  case DB_LIST:
+   __do_dbg_list();
+   break;
+  case DB_SET:
+   __do_dbg_set();
+   break;
+  case DB_INFO:
+   __do_dbg_info();
+   break;
+  case DB_SCOPE:
+   __do_dbg_scope();
+   break;
+  case DB_BRKPT:
+   if (__optimized_sim)
+    {
+     /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
+     cmd_illegal_msg(s1);
+     break;
+    }
+   __do_dbg_brkpt(FALSE);
+   break;
+  case DB_TBRKPT:
+   if (__optimized_sim)
+    {
+     /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
+     cmd_illegal_msg(s1);
+     break;
+    }
+   __do_dbg_brkpt(TRUE);
+   break;
+  case DB_IBRKPT:
+   if (__optimized_sim)
+    {
+     /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
+     cmd_illegal_msg(s1);
+     break;
+    }
+   __do_dbg_ibrkpt(FALSE);
+   break;
+  case DB_TIBRKPT:
+   if (__optimized_sim)
+    {
+     /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
+     cmd_illegal_msg(s1);
+     break;
+    }
+   __do_dbg_ibrkpt(TRUE);
+   break;
+  case DB_NEXTB:
+   if (__optimized_sim)
+    {
+     /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
+     cmd_illegal_msg(s1);
+     break;
+    }
+   if (!__do_dbg_nextb()) return(FALSE);
+   break;
+  case DB_DELBRKDIS:
+   __do_dbg_delbrkdis();
+   break;
+  case DB_BPDIS_DISABLE:
+   __do_dbg_dis_enable(FALSE);
+   break;
+  case DB_BPDIS_ENABLE:
+   __do_dbg_dis_enable(TRUE);
+   break;
+  case DB_DISPLAY:
+   dbg_display();
+   break;
+  case DB_UNDISPLAY: 
+   __dbg_undisplay();
+   break;
+  case DB_STEP:
+   __get_vtok(); 
+   if (__toktyp == TEOF) __step_rep_cnt = 1;
+   else
+    {
+     if ((tmp = __get_dbg_val()) == -1 || tmp < 1)
+      {
+       __ia_err(1470, ":istep command repeat count %s illegal", __prt_vtok());
+       break;
+      } 
+     __step_rep_cnt = tmp;
+    }
+   __single_step = TRUE;
+   __verbose_step = TRUE;
+   if (__iact_reason == IAER_CTRLC || __suspended_thd == NULL
+    || __suspended_thd->thnxtstp == NULL) __step_from_thread = FALSE;
+   __chk_extra_atend(TRUE);
+   return(FALSE); 
+  case DB_ISTEP:
+   if (__optimized_sim)
+    {
+     /* SJM 02/03/03 - breakpoint and ste cmds illegal if optimizer on */
+     cmd_illegal_msg(s1);
+     break;
+    }
+   __get_vtok(); 
+   if (__toktyp == TEOF) __step_rep_cnt = 1;
+   else
+    {
+     if ((tmp = __get_dbg_val()) == -1 || tmp < 1)
+      {
+       __ia_err(1470, ":step command repeat count %s illegal", __prt_vtok());
+       break;
+      } 
+     __step_rep_cnt = tmp;
+    }
+   __single_step = TRUE;
+   __verbose_step = TRUE;
+   if (__iact_reason == IAER_CTRLC || __suspended_thd == NULL
+    || __suspended_thd->thnxtstp == NULL) __step_from_thread = FALSE;
+   __step_match_itp = __scope_ptr;
+   __chk_extra_atend(TRUE);
+   return(FALSE); 
+  case DB_HIST: 
+   __do_dbg_history();
+   break;
+  case DB_EMPTHIST:
+   __do_dbg_emptyhistory();
+   break;
+  case DB_IGNORE:
+   __dbg_brk_ignore();
+   break;
+  case DB_COND:
+   __dbg_brk_cond();
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(TRUE); 
+}
+
+/*
+ * find a db style command
+ * algorithm is that any unique prefix is sufficient
+ * also need algorithm that does not require full table search each time
+ *
+ * this needs alias mechanism ala gdb
+ */
+extern int32 __get_dbcmdnum(char *aval, struct namlst_t *cmdtab, int32 cmdnum)
+{
+ register int32 i;
+ int32 alen, alen2;
+
+ /* first search for normal option (if arg white space separated) */ 
+ alen = strlen(aval); 
+ for (i = 0; i < cmdnum; i++)
+  {
+   alen2 = strlen(cmdtab[i].lnam);
+   if (alen2 > alen) alen2 = alen;
+   if (strncmp(aval, cmdtab[i].lnam, alen2) == 0)
+    { 
+     if (dbcmd_prefix_rep(i + 1, aval, alen2, cmdtab, cmdnum)) return(-2);
+     return(cmdtab[i].namid);
+    }
+  }
+ return(-1);
+}
+
+/*
+ * return T if find match in remaining part of db command table
+ */
+static int32 dbcmd_prefix_rep(register int32 i, char *aval, int32 alen,
+ struct namlst_t *cmdtab, int32 cmdnum)
+{
+ for (; i < cmdnum; i++)
+  { if (strncmp(aval, cmdtab[i].lnam, alen) == 0) return(TRUE); }
+ return(FALSE);
+}
+
+/*
+ * given a comman prefix where know ambiguous, built table of all possibilities
+ */
+extern char *__bld_ambiguous_list(char *s, char *aval, struct namlst_t *cmdtab,
+ int32 cmdnum)
+{
+ register int32 i; 
+ int32 first_time, alen;
+
+ alen = strlen(aval);
+ for (first_time = TRUE, i = 0; i < cmdnum; i++)
+  {
+   if (strncmp(aval, cmdtab[i].lnam, alen) == 0)
+    {
+     if (first_time) { strcpy(s, cmdtab[i].lnam); first_time = FALSE; }
+     else { strcat(s, ", "); strcat(s, cmdtab[i].lnam); }
+    }
+  }
+ return(s);
+}
+
+/*
+ * emit message for command illegal when running with -O
+ *
+ * all traces and steps
+ */
+static void cmd_illegal_msg(char *s)
+{
+ __ia_err(1417,
+  "%s illegal when -O optimized (compiled) simulation selected", s);
+}
+
+/*
+ * DEBUGGER HELP SCREEN LINE TABLES
+ */
+
+/*
+ * define debugger general topic help screen
+ */ 
+static char *dbg_topic_hlp[] = {
+ "Type ':help [topic]' or ':help :[debugger command]' to print specific help",
+ "message.  Any name can be abbreviated by a unique prefix within : debugger.",
+ "Colon is required for command name help but not allowed for help topics.",
+ " ",
+ "Help topics:",
+ "  debugging:  Entering and supplying input for interactive debugging.",
+ "  optimizer: debugging limitations when -O optimized simulation selected", 
+ "  tracing:  Separate batch tracing system for debugging.",
+ "  differences:  Debugger differences from Verilog standard.",
+ "  statements:  Using traditional interactive Verilog statement debugger.",
+ "  data:  Examining variables and expressions.",
+ "  source:  Listing source and navigating between files.",
+ "  scope:  Setting and navigating between instance and task scopes.",
+ "  break points:  Behavioral statement breakpoints and single stepping.",
+ "  changes breaking:  Breaking on net changes and edges.",
+ "  history:  Command history and history number command enable/disable.",
+ "  info:  Determining and setting debugger status and settings.",
+ "  tasks:  System task and functions useful for interactive debugging.",
+ "  commands:  A list of :[command] debugger commands.", 
+ "" 
+};
+
+static char *dbg_dbg_hlp[] = { 
+ "Debugging:",  
+ "  Both the standard Verilog statement debugger and a command based debugger",
+ "  are supported.  Input is typed from the terminal or read from a file.",
+ "  Input is terminated with a new line.  For multi-line commands, all",
+ "  but the last line ends with a back slash escaped new line.  The new",
+ "  command debugger commands begin with a colon as part of the name and",
+ "  cannot be executed from Verilog source.  All interactive commands are",
+ "  echoed to the log file unless ':set noecholog' is used to to suppress log",
+ "  file command echoing (':set echolog' re-enables).",
+ " ",
+ "  The debugger is entered by pressing the interrupt key (^c), by calling",
+ "  the $stop system task, by the -s command line option, by completing a",
+ "  step command, or by hitting a breakpoint.", 
+ " ",
+ "  The $input(\"[file]\") system task causes debugger commands to be read",
+ "  from [file] the first time interactive mode is entered (by -s?).  $input",
+ "  files do not nest, instead $input in a file causes $input to chain to the",
+ "  new file.  Output is written to the screen and the log file.  stderr is",
+ "  not used.  All typed user input including command prompts and $input",
+ "  commands is written to the log file.  $nolog and $log plus",
+ "  $nokeepcommands and $keepcommands can minimize $input script output.",
+ "  +nokeepcommands option disables history saving.  It is useful if",
+ "  simulation is run from a shell script.",
+ ""
+}; 
+
+static char *dbg_optimizer_hlp[] = { 
+ "Optimizer:",  
+ "  When -O optimized simulation (compiled byte code simulation) is used,",
+ "  breakpoints and single stepping is not possible because statements",
+ "  are converted to basic blocks, i.e. statement separation is lost.",
+ "  Even when optimizatin is on, you still can use the debugger because",
+ "  the byte code compiler is incremental and recompiles code required",
+ "  by debugger Verilog statements.  The debugger can be entered by executing",
+ "  $stop system task either from Verilog source or from statements",
+ "  entered as debugger commands, i.e. debugger can be entered by $stop",
+ "  system task, -s command option, or $stop entered as debugger command",
+ "  (such as '@(posedge clk) $stop;' statement), or by pressing ^c (interrupt",
+ "  key).  All printing, scope and info commands work.  Also, $input", 
+ "  system task and -i command line options to load commands into debugger",
+ "  are legal when debugger is used with optimized simulation.",
+ " ",
+ "  For designs that do not move time (mostly procedural without time",
+ "  movement and event scheduling), there may be a delay after interrupt",
+ "  key is pressed before interactive debugger is entered.",
+ " ", 
+ "  Debugger can only be exited by the dot ('.') continue command when used",
+ "  with optimized simulation.  Use of step (';' or ',') and all break point",
+ "  commands are illegal.  Error message is emitted and command is ignored.",
+ "  Also, $dumpvars can not be called from interactive mode during optimized",
+ "  simulation.",
+ ""
+}; 
+
+static char *dbg_trc_hlp[] = { 
+ "Debugging using the tracing mechanism:", 
+ "  An alternative non interactive tracing mechanism is supported.",
+ "  Behavioral statement tracing is started with the -t option or $settrace",
+ "  system task and stopped by calling $cleartrace.  Event tracing is started", 
+ "  with the -et option or $setevtrace system task and stopped by calling",
+ "  $clearevtrace.  The -et option allows pre time 0 initialization events",
+ "  to be traced.  Trace output is written to stdout and the log file unless",
+ "  the +tracefile [file name] option or $settracefile([string]) system task",
+ "  are used to direct trace output to a separate file.  The trace mechanism",
+ "  is intended to allow debugging of parallel activity by searching trace",
+ "  output with a debugger.",
+ " ",
+ "  Trace statements and gates are reconstructed source with parameters",
+ "  replaced by numeric values.  Interactive debugger breakpoint and step",
+ "  tracing also emit source lines.  To avoid duplicate output if tracing",
+ "  and the interactive debugger are used, redirect trace output.",
+ ""
+}; 
+
+static char *dbg_dif_hlp[] =  { 
+ "Debugger differences from standard:",
+ "  1) Multiple line interactive debugger commands must end with escaped new",
+ "  lines.  Verilog statements still require the ending semicolon.",
+ "  2) The standard $settrace system task (also -t) are divided into the two",
+ "  tracing classes: $settrace and $setevtrace (-t and -et).",
+ "  3) By default when interactive mode is entered the $scope interactive",
+ "  scope is set to the current scope.  This allows examination of local",
+ "  variables on step or break but may require entering $scope command on",
+ "  every interactive entry to run standard scripts.  In functions, named",
+ "  blocks do not have scope so function scope remains.  Interactivbe variable",
+ "  access in function named block must use qualified reference from function",
+ "  scope.  To duplicate standard behavior in which interactive scope can only",
+ "  be changed by $scope system task, type: ':set noscopechange' inside the",
+ "  interactive debugger.  When re-enabling commands from the history list,",
+ "  either the command must use rooted names or the scope must be the same",
+ "  as the scope when the command was originally entered.",
+ "  4) Delay back annotation by specparam assignments not supported, and",
+ "  $updatetiming, but similar standard SDF (LABEL form and PLI 2.0 assignment",
+ "  to defparams and specparam before delay elaboration supported.",
+ ""
+}; 
+
+static char *dbg_stmt_hlp[] =  { 
+ "Interactive Verilog statement execution:",
+ "  Any Verilog statement can be entered at the interactive mode prompt (or",
+ "  in an $input file) except named blocks and initial or always statements.",
+ "  No new variables can be declared and all identifiers are accessed using",
+ "  the current scope (entry scope or change $scope location).  Compound",
+ "  statements and statements with delay or event controls are legal.",
+ "  Commands are:",
+ " ",
+ "   '.'   Exit the debugger and continue execution (event processing).",
+ "   ':'   Print the current instance and possibly task scope plus location",
+ "         of scope and current :list current location.  Prints scope and",
+ "         listing location, use :where for procedural execution location.", 
+ "   ';'   Silently step through next procedural statement and process all",
+ "         events and time movement up to the next procedural statement. The",
+ "         current location for the :list command is not changed.  Tasks and",
+ "         functions are stepped into.",
+ "   ','   Step through next statement and print next source statement.  Same",
+ "         as ';' except the next source line to execute is printed.",
+ "   -[number]  Disable history command [number] if it has not yet completed.",
+ "         The $history task indicates commands that are active with a '*'",
+ "   [number]  Re-execute command [number] from the history list only if the",
+ "         command has finished (no '*' mark when printed with $history).",
+ "         Commands are re-executed in the current scope so if a command sets",
+ "         a change or edge breakpoint, it must contain rooted names or be",
+ "         executed from the same scope as it's original entry.", 
+ ""
+}; 
+
+static char *dbg_data_hlp[] =  { 
+ "Displaying internal circuit values:",
+ "  In addition to the normal $display (or $write) system tasks to display",
+ "  values use :print to override declared expression base or width (type",
+ "  ':help :print' for legal values). Use :display to define expressions that",
+ "  are printed whenever interactive mode is entered.  :display and :print",
+ "  take same format and width modifiers.  :expris [expr] to determine the",
+ "  width and type of an expression.  Use :varis [var.] to determine type,",
+ "  width and declaration keywords of a variable.  Use :whatis [name] to",
+ "  determine all uses of an identifier name.  Entire qualified path from",
+ "  function scope required for accessing variables in named blocks in", 
+ "  functions.",
+ ""
+}; 
+
+static char *dbg_src_hlp[] =  { 
+ "Listing source statements:", 
+ "  The normal $list([scope]) system task can list all of any task or module.",
+ "  The :list command lists 10 lines from a selected location that can be",
+ "  a scope or a [file:][line] reference or argument relative to last listed",
+ "  line.  Type ':set listsize [number]' to change the number of lines listed.",
+ "  The current listing location is independent of current scope except when",
+ "  :scope or $scope is executed, the current list line is set to the first",
+ "  line of the scope.  Also since ',' and :[i]step and hitting a breakpoint",
+ "  print a source line, those commands change the current list line.", 
+ "  The explicit [file:][line] list command lists in a new file and :list ++",
+ "  lists the beginning of the next source file (:list -- the previous end).",
+ "  Only these three commands can change listing file.  Type ':help :list'",
+ "  for the format of the various :list command options.", 
+ ""
+}; 
+
+static char *dbg_scope_hlp[] =  { 
+ "Setting interactive scope:",
+ "  The $scope([scope xmr]) system task changes interactive scope.  The :scope",
+ "  command also changes scope but allows a more general reference.  The",
+ "  :breakpoint command takes a scope reference argument.  Format is:",
+ " ",
+ "  [file:][line] - first instance of scope determined by [file:][line].",
+ "       [file] can be source file, -y or -v path or any path tail if it is",
+ "       unique.  [line] must be between module - endmodule.  Any ':' in",
+ "       [file] name must be escaped with a back slash.  Scope set to type or",
+ "       first instance but other command argument may select instance for",
+ "       :breakpoint.  Scope list line set to first line of scope not [line].", 
+ "       [line] is same as [file:][line] where [file] is current file.",
+ " .. or .u - upward scope first line - if scope in task - one up task or",
+ "       instance containing task (not up instance).",
+ " .d - first line of scope of first contained instance (not contained task).",
+ " [module name]  - first instance of module unless name declared as instance",
+ "       in current scope, then normal downward hierarchical reference.",
+ " [hierarchical ref.] - first line of instance - same as $scope argument.",
+ "" 
+}; 
+
+static char *dbg_brkpt_hlp[] = { 
+ "Behavioral statement breakpoints:",
+ "  Use the :breakpoint or :ibreakpoint commands to set a breakpoint at a",
+ "  specific source statement.  The break occurs before statement execution.",
+ "  :breakpoint breaks in all instances and :ibreakpoint breaks only in the",
+ "  specified instance.  The :breakpoint argument can be any scope or line",
+ "  reference.  If no line reference is given the break is at the first",
+ "  initial, always or task statement of the scope.  For :ibreakpoint the",
+ "  argument must be an instance reference that may optionally be followed by",
+ "  a ',' and a line reference.  For a line reference, the breakpoint is set",
+ "  at the first procedural statement at or following the line in the scope.", 
+ " ",
+ "  Type ':help :breakpoint' or ':help :ibreakpoint' for other options and",
+ "  argument format.  Use ':info breakpoints' to print a list of breakpoints",
+ "  ':delete [number]' to delete breakpoint [number] (no argument deletes all),",
+ "  ':disabl [number]' to temporarily disable breakpoint and ':enable [number]'",
+ "  to re-enable.  :tbreakpoint and :tibreakpoint are identical to :ibreak",
+ "  and :break except breakpoint removed when hit.  :cond adds expression to",
+ "  breakpoint that must be true to cause stop. :ignore adds count of how many",
+ "  hits to ignore before halting.",
+ ""
+}; 
+
+static char *dbg_chgbrk_hlp[] = {
+ "Breaking on net changes:",
+ "  Enter a delay or event control followed by the $stop system task to",
+ "  enter interactive mode on value change.  Normally the event control",
+ "  statement will be in a loop (probably a forever) because otherwise the",
+ "  break is disabled after each trigger.  Also when interactive mode is",
+ "  entered from an interactive $stop, a step (',', ':', :step, or :istep)",
+ "  command must be entered before using [number] to re-enable a history",
+ "  statement.  For example: 'forever @(posedge clock) $stop;' is usually",
+ "  better than '@(posedge clock) $stop;'",
+ ""
+};
+
+static char *dbg_hist_hlp[] = { 
+ "History mechanism:",
+ "  A command is re-executed by entering its history number.  A uncompleted",
+ "  command (such as a Verilog wait or delay control) is disabled by entering",
+ "  -[number] where [number] is command's assigned number in history list.",
+ " ",
+ "  The $history system task prints the most recent 20 (or histlistsize if",
+ "  different) history entries.  The debugger :history [optional number]",
+ "  command is more flexible because if an optional number argument appears,",
+ "  that many elements are printed (0 for all).  The interactive command",
+ "  prompt is 'C[number] >' where [number] is a command's history number.",
+ "  The one character, [number] to execute, [-][number] to disable and",
+ "  incorrect (such as mistyped Verilog statement entered interactively)",
+ "  commands are not added to the history list.",
+ " ",
+ "  All commands input during a run are retained.  Use $nokeepcommands to",
+ "  suppress history accumulation and $keepcommands to re-enable in $input",
+ "  scripts.  +nokeepcomands command line option disables history saving for",
+ "  programs that run a simulation by supplying command input through a pipe.",
+ "  :emptyhistory command discards all retained history commands and resets",
+ "  command number to one.  If any history commands are enabled (have not yet", 
+ "  completed or been disabled), :emptyhistory will fail.  When an interactive",
+ "  Verilog statement is executed, if it can be executed immediately (no", 
+ "  delays, events or tasks enables), it is executed from inside debugger and",
+ "  control remains in interactive mode.  Non immediate statements are",
+ "  scheduled after already scheduled events and resumes.  $stop or the", 
+ "  interrupt signal (^c) must then be used to reenter interactive mode.  Use",
+ "  ':set histlistsize' to set default number of history commands to list and",
+ " ':info histlistsize' to see current number.", 
+ ""
+}; 
+
+static char *dbg_info_hlp[] = { 
+ "Determining and setting internal debugger state values:",
+ "  The ':info [debugger value name]' command prints the current value of",
+ "  a debugger value.  The ':set [debugger value name] [value]' command",
+ "  changes a debugger value.  Type ':help :info' or ':help :set' for the list",
+ "  of debugger info value names.",
+ ""
+}; 
+
+static char *dbg_stsks_hlp[] = { 
+ "The following system tasks may be useful during interactive debugging:",
+ "   $finish;  Terminate simulation.",
+ "   $list([scope reference]);  list source lines of scope (:list is",
+ "      alternative).  $list does not print variables values, use $showvars",
+ "      or :print <expr> for that.  Also $list does not mark source lines",
+ "      with pending events.",
+ "   $system(\"[OS command string]\");  Escape to a sub shell and execute the",
+ "      command string (alternative is :shell [command string]).  Use empty",
+ "      string (\"\") to invoke an interactive sub-shell.",
+ "   $flushlog;  Call OS flush of buffers for log file and trace file.  Can",
+ "      then use :shell to invoke your editor to inspect output.",
+ "   $history;  Print history list to stdout and log file.  Contrary to XL,",
+ "      '$history;' prints last 20 (or histlistsize) commands.  Use",
+ "      ':history <num>' to print <num> commands.  <num> 0 prints all. :set",
+ "      sets and :info prints debugger histlistsize parameter that determines",
+ "      number of commands to list.",
+ " $keepcommands;, $nokeepcommands;  Enable (or disable) saving of commands",
+ "      entered interactively to history list.  Default is $keepcommands.",
+ "      Use the +nokeepcommands command line option to disable saving of",
+ "      commands to the history list unless '$keepcommands;' is executed.",
+ "   $input([string]);  Process interactive commands from [string] file.",
+ "   $nolog;, $log;  All commands in $input scripts will be copied to the",
+ "      log file unless $nolog is used.  To re-enable log file output, use",
+ "      $log; with no argument.  To change log file use $log([string]).",
+ "   $reset;, $reset_count;, $reset_value;  During debugging reset to start",
+ "      of simulation.  :reset command is better during debugging since it",
+ "      returns to time 0 leaving the reset count unaffected and allows stop.",
+ "   $scope;  Change interactive environment scope to avoid a need to type",
+ "      full paths for variable names.  :scope and automatic scope tracking",
+ "      are intended to lessen need to set explicit interactive scopes.",
+ "      $scope can set scope to function named block but next ineractive entry",
+ "      (from step?) will change scope to function body scope.",
+ "   $showallinstances;  Print all instances in design with source file and",
+ "      line location.  Useful to find module whose name is forgotten.",
+ "      +printstats and +printallstats give more detailed information.", 
+ "      If no other window is available, use $flushlog; and :shell to view.",
+ "   $showscopes;  Used to show scopes in current interactive scope.  Can be",
+ "      called with non zero argument to list entire design scope map.", 
+ "   $showvariables;, $showvars  Print all variables in current scope. :print",
+ "      is more terse but $showvars prints more for multiple fan-in wires.",
+ "   $shapshot; print up to 5 pending procedural and 5 pending declarative",
+ "      events and status of every interactive thread.  Same as :snapshot.",
+ "   $display, $write  Write values.  Alternative :print is more flexible but",
+ "      these tasks allow formatted output.",
+ "" 
+}; 
+
+/* table of debugger help topic values */
+#define HLP_DBG 0
+#define HLP_OPTIM 1
+#define HLP_TRC 2
+#define HLP_DIF 3
+#define HLP_STMT 4
+#define HLP_DAT 5
+#define HLP_SRC 6
+#define HLP_SCP 7
+#define HLP_BP 8
+#define HLP_CHGBP 9
+#define HLP_HIST 10
+#define HLP_INF 11
+#define HLP_TSK 12
+#define HLP_CMD 13
+
+/* debugger help topic name table */
+/* index and pos. in this table must be identical */
+static struct namlst_t hlptoptab[] = {
+ { HLP_DBG, "debugging" },
+ { HLP_OPTIM, "optimizer" },
+ { HLP_TRC, "tracing" },
+ { HLP_DIF, "differences" },
+ { HLP_STMT, "statements" },
+ { HLP_DAT, "data" },
+ { HLP_SRC, "source" },
+ { HLP_SCP, "scope" },
+ { HLP_BP, "breakpoints" },
+ { HLP_CHGBP, "changes" }, 
+ { HLP_HIST, "history" },
+ { HLP_INF, "info" },
+ { HLP_TSK, "tasks" },
+ { HLP_CMD, "commands" }
+};
+#define NHLPTOPS (sizeof(hlptoptab) / sizeof(struct namlst_t))
+
+/* per help topic line tables - size is same help topices */
+/* index and pos. in this table must be identical */
+static struct hlplst_t hlp_topics[] = { 
+ { HLP_DBG, dbg_dbg_hlp },
+ { HLP_OPTIM, dbg_optimizer_hlp },
+ { HLP_TRC, dbg_trc_hlp },
+ { HLP_DIF, dbg_dif_hlp },
+ { HLP_STMT, dbg_stmt_hlp },
+ { HLP_DAT, dbg_data_hlp },
+ { HLP_SRC, dbg_src_hlp },
+ { HLP_SCP, dbg_scope_hlp },
+ { HLP_BP, dbg_brkpt_hlp },
+ { HLP_CHGBP, dbg_chgbrk_hlp },
+ { HLP_HIST, dbg_hist_hlp },
+ { HLP_INF, dbg_info_hlp },
+ { HLP_TSK, dbg_stsks_hlp },
+ /* here must call special command list routine */ 
+ { HLP_CMD, NULL, }
+};
+
+/* 
+ * DEBUGGER INDIVIDUAL COMMAND HELP SCREEN LINE TABLES
+ */
+
+static char *help_msg[] = { 
+ ":help [optional topic or :[command] name prefix]", 
+ "   Print help message.",
+ ""
+}; 
+
+static char *shell_msg[] = { 
+ ":shell [rest of line is OS command]",
+ "   Execute rest of line as OS command in sub-shell.  Notice no quotes needed.",
+ "   Empty rest of line to spawn interactive shell.  Equivalent to",
+ "   '$system([quotes OS command string]);' system task.",
+ ""
+}; 
+
+static char *snapshot_msg[] = { 
+ ":snapshot",
+ "   Print snapshot of current procedural location and list of statement at",
+ "   which each procedural (per instance) thread suspended at.  Also lists",
+ "   pending events on head of event list.  May be long so one way to view it",
+ "   is to type: $flushlog; then ':sh [evoke editor on verilog.log file]'.",
+ ""
+}; 
+
+static char *where_msg[] = { 
+ ":where",
+ "   Print back trace of most recently suspended control thread including all",
+ "   upward thread enables with source and scope locations.  To see a listing",
+ "   of all pending scheduled event activity and thread states use $snapshot;",
+ "   or :snapshot.  :where corresponds as closely as possible to normal",
+ "   call stack trace back.  ':' prints instance scope and last source",
+ "   listing location.  If :where fails, suspension was from declarative code.",
+ "   Try single step and entering :where again.",
+ ""
+}; 
+
+static char *quit_msg[] = { 
+ ":quit",
+ "   Exit.  Equivalent to $finish;", 
+ ""
+};
+
+static char *print_msg[] = { 
+ ":print [/format][#width] [expression]",
+ "   Evaluate and print expression.  If [/format] is present, interpret the",
+ "   value according to format.  Formats are:  'd' (decimal), 'u' (unsigned),",
+ "   'b' (binary), 'h' or 'x' (hex), 's' (string), or 'c' (1 character).  If",
+ "   the [/format] is omitted, use current default unless the expression is a",
+ "   string or real.  Starting default base is hex, but use ':set printbase'",
+ "   to set different default base.  /u format prints bit pattern as unsigned.",
+ "   If [#width] value is present, interpret as [width] wide, instead of width",
+ "   computed from operator width rules.  Any format or width are ignored for",
+ "   reals, use $realtobits to view bit pattern.",
+ ""
+};
+
+static char *reset_msg[] = { 
+ ":reset [stop]",
+ "   Reset simulation back to time 0 and restart simulation.  Interactive mode",
+ "   must be explicitly entered by interrupt (^c), calling $stop or [stop]",
+ "   option.  If a -i startup file was given it is executed on interactive",
+ "   entry.  $reset_count and $reset_value are not changed.  If optional",
+ "   :reset stop argument is present, stop just before simulation, else rerun",
+ "   without stopping even if -s option was given on command line.  Equivalent",
+ "   to $reset system task but can be used to restart for debugging models",
+ "   that use the $reset system task.  The $reset system task uses the -s",
+ "   option unless the first argument is non zero and stops before simulation.",
+ "   All uncompleted interactive statements are disabled by either :reset",
+ "   or $reset.  They are re-enabled by typing history command number or",
+ "   running -i start up interactive file.  Debugger state : breakpoints",
+ "   (left enabled) and history are preserved.",
+ ""
+};
+
+static char *expris_msg[] = { 
+ ":expris [expression]",
+ "   Print type and width of expression.  Use to determine Verilog width and",
+ "   property rules for complex expressions.",
+ ""
+};
+
+static char *varis_msg[] = { 
+ ":varis [variable]",
+ "   Print type and width and declaration keywords of variable.",
+ ""
+};
+
+static char *whatis_msg[] = { 
+ ":whatis [identifier]",
+ "   Print symbol information for every use of identifier.  Also, emits one",
+ "   instance reference for each use, so a breakpoint can be set.",
+ ""
+};
+
+static char *list_msg[] = { 
+ ":list [range]",
+ "   List source within [range] lines.  Some [range]s are relative to last",
+ "   printed line.  Any scope change or $list or previous :list command",
+ "   changes the last printed line.  Legal [range]s are:",
+ " ",
+ "     + or [empty]             10 lines starting with last printed.",
+ "     +0                       10 lines around current line.",
+ "     -                        10 lines ending 1 before previous first line.",
+ "     ++                       First 10 lines of next file.",
+ "     --                       Last 10 lines of previous file.",
+ "     [file]:[number]          10 lines around [number] in file [file].",
+ "     [number]                 10 lines around [number] in current file.",
+ "     [+/-][offset]            10 lines starting [offset] from current.",
+ "     [+/-][num1],[+/-][num2]  Range, if [+/-] offset from current line.",
+ "     [scope reference]        First 10 lines starting at [scope].",
+ " ", 
+ "   By default 10 lines are list, use ':set listsize [number]' to change",
+ "   number of printed lines to [number].  Notice stepping with ';' does not",
+ "   change last printed line.  Use [file]:[number] to list inside `include",
+ "   files.  ++ and -- exit to file and line of first inclusion of file.",
+ "   Read library files are same as source files.",
+ ""
+};
+
+static char *set_msg[] = { 
+ ":set [debugger parameter] [value]",
+ "   Set debugger internal parameter to [value].  Legal set parameters are:",
+ " ",     
+ "   :set listsize [number]     Default is 10 lines to list.",
+ "   :set histlistsize [number] Default is 20 history commands to list.",
+ "   :set noscopechange         Disable automatic scope setting on entry to",
+ "                              interactive mode.",
+ "   :set scopechange           Re-enable automatic scope setting on.  Scope",
+ "                              not set to named blocks in functions.",
+ "   :set printbase [base]      Set default :print command base, values: hex",
+ "                              (default), decimal, octal binary.",
+ "   :set nologecho             Turn off writing of input interactive commands",
+ "                              the log file (default).",
+ "   :set logecho               Turn on writing of input commands.",
+ ""
+};
+
+static char *info_msg[] = { 
+ ":info [debugger parameter]",
+ "   Show value of debugger state or parameter setting.  Legal info parameters",
+ "   are: listsize, histlistsize, scopechange, breakpoints, displays,",
+ "   printbase and logecho.  For breakpoints and auto-display expressions",
+ "   prints status information for each.",
+ ""
+};
+
+static char *scope_msg[] = { 
+ ":scope [scope reference]",
+ "   Change interactive scope to [scope reference] location.  Type",
+ "   ':help scope' for list of legal scope selection forms.  Any [line] is",
+ "   used only to determine surrounding scope.  Scope only applies to",
+ "   interactive mode and system tasks that explicitly are defined to use the",
+ "   interactive scope.   Extended version of $scope system task.  If scope",
+ "   set to function named block scope, next interactive entry will change", 
+ "   scope to function body scope (assuming scopechange mode active).", 
+ ""
+};
+
+static char *breakpoint_msg[] = { 
+ ":breakpoint [scope reference] or none",
+ "   Set statement breakpoint at all instances of [scope reference].  Type", 
+ "   ':help scope' for a list of legal [scope reference] forms.  If the",
+ "   reference selects an instance, only the type of the instance is used.",
+ "   If the [scope reference] is not a [file:][line] reference, use first",
+ "   initial, always or task statement of scope.  If no argument, set at",
+ "   last :list argument (first if range, closest if backward) that must be",
+ "   within task, function or initial or always block.  Setting a breakpoint",
+ "   at a line means the first procedural statement at or after the line (but",
+ "   must be within scope).  Type ':help breakpoints' for discussion of other",
+ "   breakpoint commands.",
+ "", 
+}; 
+
+static char *ibreakpoint_msg[] = { 
+ ":ibreakpoint [scope reference][,[file:][line]] or none",
+ "   Set statement breakpoint at instances of [scope reference] file [file]",
+ "   and [line] line.  Type ':help scope' for a list of legal [scope ref.]s,",
+ "   but here only explicit instance scope references are legal.  If the",
+ "   ',[file:][line]' argument is omitted, use first statement of first",
+ "   initial, always, or task (for task scope).  If ',[line]' but no [file]",
+ "   is given, use first or only file of scope.  If no scope reference and",
+ "   only ',[file:][line]' is given, use current scope.  No argument means",
+ "   set at last :list argument (first if range, closest if backward)",
+ "   that must be within task, function, or initial or always block.",
+ "   Type ':help breakpoints' for discussion of other breakpoint commands.",
+ "", 
+}; 
+
+static char *delete_msg[] = { 
+ ":delete [optional type] [number]",
+ "   Delete breakpoint or display expression with number [number] or all if",
+ "   number is omitted.  [optional type] is breakpoints or displays (default",
+ "   if omitted is breakpoints).  Type 'info breakpoints' or 'info displays'",
+ "   to determine breakpoint or auto-display number.  If [number] is omitted,",
+ "   delete all breakpoints or auto-display expressions.", 
+ ""
+};
+
+static char *disable_msg[] = { 
+ ":disabl [optional type] [number]",
+ "   Temporarily disable breakpoint or display with number [number].",
+ "   [optional type] is breakpoints or displays (breakpoints is default if",
+ "   omitted) and can be abbreviated to first letter. Type 'info breakpoints'",
+ "   or 'info displays' to determine breakpoint or auto-display number and",
+ "   enable state.  Notice final e must not appear to avoid conflict with",
+ "   Verilog disable keyword (any unique prefix such as 'disa' works).  Also",
+ "   notice that :disabl disables an added : debugger breakpoint, but disable",
+ "   statement or -[number] disables simulation of a Verilog statement.",
+ ""
+};
+
+static char *enable_msg[] = { 
+ ":enable [optional type] [number]",
+ "   Enable breakpoint or display with number [number].  [optional type]",
+ "   is either breakpoints or displays (breakpoints is default if omitted) and",
+ "   can be abbreviated to first letter.  Type 'info breakpoints' or",
+ "   'info displays' to determine breakpoint or auto-display expression",
+ "   number and enable state.",
+ ""
+};
+
+static char *step_msg[] = { 
+ ":step [optional repeat count]",
+ "   Step to next procedural line.  Execute one statement or statements on",
+ "   current line, stop before first statement of next line.  May process",
+ "   pending declarative events before stepping.  Execution steps into any",
+ "   task or function.  Equivalent to ',' interactive Verilog command.",
+ "   Always prints location after stopping.  if optional repeat count, step",
+ "   that many times before stopping and printing message.  If interrupt (^c)", 
+ "   or breakpoint hit during stepping, stop stepping and enter interactive",
+ "   mode.",
+ ""
+};
+
+static char *istep_msg[] = { 
+ ":istep [optional repeat count]",
+ "   Step to next procedural statement that is in same instance tree location.",
+ "   Otherwise identical to :step.  If debugger entered by interrupt, use one",
+ "   :step before :istep since scope may have been in module without any", 
+ "   procedural statements.  :istep uses currently executing instance not",
+ "   interactive scope set by $scope.",
+ ""
+};
+
+static char *hist_msg[] = { 
+ ":history [optional number]",
+ "   Print 20 (or value of histlistsize info debugger parameter) commands.",
+ "   If [number] appears, print [number] (0 means all) history commands.",
+ "   Pauses and prompts for CR every histlistsize lines.",
+ "" 
+};
+
+static char *empthist_msg[] = { 
+ ":emptyhistory",
+ "   If all history commands have completed or are disabled with (-[number]",
+ "   command), discard retained history and set next history command to 1.",
+ "" 
+};
+
+static char *disp_msg[] = { 
+ ":display [/format][#width] [expression]",
+ "   Set up [expression] in display table so that it is displayed on every",
+ "   entry to interactive mode.  Arguments are identical to :print command.",  
+ "   Use ':delete display' or ':undisplay' to delete all auto-display",
+ "   expressions.  If either is followed by a number, delete that numbered",
+ "   display only.  Use ':info display' to list current displays.  ':display'",
+ "   with no arguments displays all current auto-display expressions.",
+ "   Use 'enable display' and 'disabl display' to temporarily turn off or on",
+ "   an auto-display expression.",  
+ ""
+};
+
+static char *undisp_msg[] = { 
+ ":undisplay [optional number]",
+ "   Delete [number] auto-display expression or all current if [number] is",
+ "   not present.  Same as ':delete display' command.",
+ ""
+};
+
+static char *tbreakpoint_msg[] = { 
+ ":tbreakpoint [scope reference] or none",
+ "   Command identical to :breakpoint except breakpoint is temporary and",
+ "   removed after it is hit the first time.  To avoid tracing in task or", 
+ "   function (approximate DBX/GDB next command), use the :nextb command.",
+ "   It sets a :tibreak at the next line and executes a '.' command.  Because",
+ "   of delay and event controls, other threads may be executed before break",
+ "   is hit.  The :ignore command can be used with :tbreakpoint.  After",
+ "   ignore count hits, the break point is taken and then removed.",
+ ""
+};
+
+static char *tibreakpoint_msg[] = { 
+ ":tibreakpoint [scope reference][,[file:][line]] or none",
+ "   Command identical to :ibreakpoint except breakpoint is temporary and",
+ "   removed after it his the first time (see :tbreakpoint help).  Only", 
+ "   stops in instance that is same as scope reference instance.", 
+ ""
+};
+
+static char *nextb_msg[] = { 
+ ":nextb",
+ "   Abbreviation for :tibreak [line number of next thread statement]",
+ "   followed by '.'.  Analog of DBX/GDB next command steps over current",
+ "   statement.  Break point is visible and can be removed before it is hit.",
+ "   If no next statement in thread, temporary break point not set and error",
+ "   message emitted.  :nextb over task enable may execute other threads",
+ "   before stopping if the task contains event or delay controls.  :nextb",
+ "   and for that matter any temporary break point do not use up a break",
+ "   point number unless a new break point is set before temporary break",
+ "   point is hit.  See ':help :tbreakpoint' and ':help statements' for",
+ "   more information.", 
+ ""
+};
+
+static char *ignorebrk_msg[] = { 
+ ":ignore [breakpoint number] [ignore count]",
+ "   Do not stop at break point [number] until [ignore count] hits of the",
+ "   break point have occurred.  Ignore count assumes last hit was 0th.",
+ "   To remove an :ignore count, use 'ignore [break number] 0'.  Use", 
+ "   ':info breakpoints' to determine number of hits and any pending ignore",
+ "   count.",
+ ""
+};
+
+static char *condbrk_msg[] = { 
+ ":cond [breakpoint number] [optional condition expression]",
+ "   Do not stop at break point [number] unless [expression] evaluates to",
+ "   a positive non x/z value (i.e. true).  Expression will be checked and",
+ "   evaluated in instance and task/function or named block scope of break",
+ "   point.  Since Verilog variables persist, :cond expression variable always",
+ "   have values.  Conditions are evaluated before ignore counts so if",
+ "   condition is false hit count does not rise.  Use ':cond [break number]'",
+ "   to remove condition.",
+ ""
+};
+
+/* per command help line tables - size is same as dbcmds */
+/* this table must have value and index same (same order as constants) */
+static struct hlplst_t hlpcmds[] = { 
+ { DB_HELP, help_msg }, 
+ { DB_SH, shell_msg },
+ { DB_QUIT, quit_msg },
+ { DB_WHERE, where_msg },
+ { DB_PRINT, print_msg },
+ { DB_RESET, reset_msg },
+ { DB_EXPRIS, expris_msg },
+ { DB_VARIS, varis_msg },
+ { DB_WHATIS, whatis_msg },
+ { DB_LIST, list_msg }, 
+ { DB_SET, set_msg }, 
+ { DB_INFO, info_msg }, 
+ { DB_SCOPE, scope_msg },
+ { DB_BRKPT, breakpoint_msg },
+ { DB_IBRKPT, ibreakpoint_msg },
+ { DB_DELBRKDIS, delete_msg },
+ { DB_BPDIS_ENABLE, enable_msg },
+ { DB_BPDIS_DISABLE, disable_msg },
+ { DB_STEP, step_msg },
+ { DB_ISTEP, istep_msg },
+ { DB_HIST, hist_msg },
+ { DB_EMPTHIST, empthist_msg },
+ { DB_DISPLAY, disp_msg },
+ { DB_UNDISPLAY, undisp_msg },
+ { DB_TBRKPT, tbreakpoint_msg },
+ { DB_TIBRKPT, tibreakpoint_msg },
+ { DB_IGNORE, ignorebrk_msg },
+ { DB_COND, condbrk_msg },
+ { DB_SNAPSHOT, snapshot_msg },
+ { DB_NEXTB, nextb_msg }
+};
+
+/*
+ * ROUTINES TO IMPLEMENT DEBUGGER HELP SYSTEM
+ */
+
+/*
+ * write the debugger help screens
+ * format is :help or :help [topic] where [topic] is special topic or
+ * :[command]
+ */
+static void do_dbg_help(void)
+{
+ int32 rv;
+ char s1[RECLEN];
+
+ /* number error here, but make sure not allocated */
+ __get_vtok();
+ /* case 1: no argument, emit topic list */ 
+ if (__toktyp == TEOF) { wr_dbg_hlpmsg(dbg_topic_hlp); return; }
+ /* case 2: argument is : debugger command */
+ if (__toktyp == COLON)
+  {
+   __get_vtok();
+   if (__toktyp != ID || strlen(__token) > 40)
+    {
+bad_cmd:
+     __ia_err(1438,
+      ":help argument :%s illegal - not a : debugger command", __prt_vtok()); 
+     return;
+    }
+   strcpy(s1, ":");
+   strcat(s1, __token);
+   rv = __get_dbcmdnum(s1, dbcmds, NDBCMDS);
+   if (rv == -1) goto bad_cmd; 
+   if (rv == -2)
+    {
+     __ia_err(1422, ":help %s - ambiguous : debugger command: %s", s1,
+      __bld_ambiguous_list(__xs, s1, dbcmds, NDBCMDS));
+     return;
+    }
+   /* notice rv is found in command table but indexes hlpcmds table */
+   /* therefore the 2 tables must be kept in indentical order */
+   wr_dbg_hlpmsg(hlpcmds[rv].hmsgtab);
+   goto done;
+  }
+ /* case 3: argument is help topic */
+ if (__toktyp != ID)
+  {
+bad_topic:
+   __ia_err(1439, ":help topic %s unrecognized", __prt_vtok()); 
+   goto done;
+  }
+ rv = __get_dbcmdnum(__token, hlptoptab, NHLPTOPS);
+ if (rv == -1) goto bad_topic; 
+ if (rv == -2)
+  {
+   __ia_err(1422, ":help %s - ambiguous topic: %s", s1,
+    __bld_ambiguous_list(__xs, s1, hlptoptab, NHLPTOPS));
+   goto done;
+  }
+ /* for help command topic, routine to list all commands */
+ /* hlptoptab and hlp_topics tables must be kept in identical order */
+ if (rv == HLP_CMD) wr_dbg_lstofcmds(dbcmds, NDBCMDS);
+ else wr_dbg_hlpmsg(hlp_topics[rv].hmsgtab);
+
+done:
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * write a debugger help message to standard output and log file
+ */
+static void wr_dbg_hlpmsg(char **dbgmsg)
+{
+ register int32 i; 
+
+ for (i = 0; *dbgmsg[i] != '\0'; i++) __cvsim_msg("%s\n", dbgmsg[i]); 
+}
+
+/*
+ * write the list of debugger commands
+ */
+static void wr_dbg_lstofcmds(struct namlst_t *cmdtab, int32 cmdnum)
+{
+ register int32 i;
+
+ if (__outlinpos != 0) __misc_terr(__FILE__, __LINE__);
+ __pv_stlevel = 0;
+ __wrap_puts(":[command] debugger commands:  ", stdout); 
+ for (i = 0; i < cmdnum; i++)
+  {
+   __wrap_puts(cmdtab[i].lnam, stdout);
+   if (i != cmdnum - 1) __wrap_puts(", ", stdout);
+  }
+ if (__outlinpos != 0) __wrap_putc('\n', stdout);
+ __outlinpos = 0;
+}
+
+/*
+ * ROUTINES TO IMPLEMENT DEBUGGER EXPRESSION EVALUATION
+ */
+
+/*
+ * print an expression value - know :print read 
+ *
+ * format - :print/[d,u,b,h(x),s,c]#[bits] <expr> - default h and expr width
+ * p#42 - p/d#52
+ * notice no f - since will always print real as real
+ */
+static void dbg_print(void)
+{
+ int32 prtfmt, prtwidth, force_unsign;
+ struct expr_t *prtx;
+
+ prtfmt = BNONE;
+ prtwidth = -1;
+ force_unsign = FALSE;
+ /* handle optional /[format letter] */
+ __get_vtok();
+ if (__toktyp == DIV)
+  {
+   __get_vtok();
+   if (__toktyp == ID)
+    {
+     if (strlen(__token) > 1)
+      {
+bad_prt_typ:
+       __ia_err(1425, ":print type selector /%s illegal", __token); 
+       return;
+      }
+     switch (__token[0]) {
+      case 'd': prtfmt = BDEC; break; 
+      case 'u': prtfmt = BDEC; force_unsign = TRUE; break; 
+      case 'o': prtfmt = BOCT; break;
+      case 'b': prtfmt = BBIN; break; 
+      case 'h': case 'x': prtfmt = BHEX; break;
+      case 's': prtfmt = BSTR; break; 
+      case 'c': prtfmt = BCHAR; break;
+      default: goto bad_prt_typ;
+     }
+    }
+   else
+    {
+     __ia_err(1426,
+      ":print type selector / not followed by format letter - %s read",
+      __prt_vtok());
+     return;
+    }
+   __get_vtok();
+  }
+ /* handle optional #<width> */ 
+ if (__toktyp == SHARP)
+  {
+   __get_vtok();
+   if (__toktyp != NUMBER || __itoklen > WBITS || __bcwrk[0] != 0L)  
+    { 
+     __ia_err(1427, ":print width override # not followed by legal number");
+     return;
+    }
+   prtwidth = (int32) __acwrk[0];
+   __get_vtok();
+  }
+ /* if collect returns F, if NULL, know error emitted in routine */
+ /* notice here if value, cannot free - need the iatok ptr allocated value */
+ if ((prtx = __rd_iact_expr()) == NULL) return;
+ /* know this will fit in RECLEN and truncates for readabililty for */
+ /* very wide values */
+ dbg_bld_expr_val(__xs, prtx, prtfmt, prtwidth, force_unsign);
+ __cvsim_msg("%s\n", __xs);
+
+ /* can free expr. */
+ __free_xtree(prtx);
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * print an expression value for :print or :display commands
+ */
+static char *dbg_bld_expr_val(char *s, struct expr_t *prtx, int32 prtfmt,
+ int32 prtwidth, int32 force_unsign)
+{
+ int32 blen;
+ word32 av, bv;
+ double d1;
+ struct xstk_t *xsp;
+ char s1[IDLEN];
+
+ /* strength only emitted if no strength override */
+ if (prtx->x_stren && prtfmt == BNONE && prtwidth == -1)
+  { __strenexpr_tostr(s, prtx); return(s); }
+
+ xsp = __eval_xpr(prtx);
+ /* always print real as double - can use system task to get bit pattern */ 
+ if (prtx->is_real)
+  {
+   memmove(&d1, xsp->ap, sizeof(double));
+   sprintf(s, "%g", d1);
+   goto do_prt;
+  }
+ 
+ /* print as character ignore any print width */ 
+ if (prtfmt == BCHAR)
+  {
+   /* if has x/z, print as 8 bit binary x/z value */
+   av = xsp->ap[0] & 0xff;
+   bv = xsp->bp[0] & 0xff;
+   if (bv != 0)
+    {
+     __regab_tostr(s1, &av, &bv, 8, BBIN, FALSE);
+     sprintf(s, "char: [%s]", s1);
+    }
+   /* if non printable, print as escaped */
+   /* SJM 09/19/03 - must also print new line and tab - isprint does */
+   /* not include new line and tab etc. */
+   else if (isprint(av) || av == '\n' || av == '\r' || av == '\t')
+    sprintf(s, "\\%x", (int32) av);
+   else sprintf(s, "%c", (char) av);
+   goto do_prt;
+  }
+ /* force print as string */
+ if (prtfmt == BSTR)
+  {
+   /* if explicit width use it and do not trim, else trim leading 0's */
+   if (prtwidth == -1) blen = __trim1_0val(xsp->ap, xsp->xslen);
+   else blen = prtwidth; 
+   /* convert to string with escape octal for non printable */
+   __strab_tostr(s, xsp->ap, blen, FALSE, FALSE);
+   goto do_prt;
+  }
+ /* finally print according to values */
+ if (prtwidth == -1) blen = xsp->xslen; else blen = prtwidth;
+ if (prtfmt == BNONE) prtfmt = __dbg_dflt_base;
+ __regab2_tostr(s, xsp->ap, xsp->bp, blen, prtfmt,
+  (!force_unsign) ? TRUE : FALSE, (prtwidth == -1) ? TRUE : FALSE);
+
+do_prt:
+ __pop_xstk();
+ return(s);
+}
+
+/*
+ * read and parse an interactive debugger expression
+ * expects first token to have been read
+ * this must be run in right scope
+ */
+extern struct expr_t *__rd_iact_expr(void)
+{
+ int32 sav_err_cnt;
+ struct expr_t *xp;
+
+ if (!__colto_eol()) return(NULL); 
+ /* LOOKATME - needed because iact errors counted - maybe should not */ 
+ sav_err_cnt = __pv_err_cnt;
+ __bld_xtree(0);
+ xp = __root_ndp;
+ /* if already error, do not check expr. */ 
+ if (__pv_err_cnt == sav_err_cnt) __chk_rhsexpr(xp, 0);
+ if (__pv_err_cnt != sav_err_cnt)
+  {
+   __ia_err(1423, "invalid syntax in debugger expression");
+   return(NULL);
+  }
+ return(xp);
+}
+
+/*
+ * for debugger collect expression to end of line
+ * expects 1st token to have been read
+ * if in file or interactive tty, same eof on end of line
+ */
+extern int32 __colto_eol(void)
+{
+ for (__last_xtk = -1;;)
+  {
+   if (__toktyp == TEOF) return(TRUE);
+   if (__toktyp == SEMI)
+    {
+     __ia_err(1487, "semicolon illegal end of interactive expression");
+     goto bad_end;  
+    }
+   if (!__bld_expnode()) goto bad_end;
+   __get_vtok();
+  }
+
+bad_end:
+ __set_xtab_errval();
+ return(FALSE);
+}
+
+/*
+ * ROUTINES TO IMPLEMENT DISPLAY COMMANDS
+ */
+
+/*
+ * set up display of expr on any interactive entry - know :display read 
+ *
+ * always print on start
+ * format - :display/[d,u,b,h(x),s,c]#[bits] <expr> 
+ */
+static void dbg_display(void)
+{
+ int32 prtfmt, prtwidth, force_unsign;
+ struct expr_t *prtx;
+ struct dispx_t *dxp;
+
+ __get_vtok();
+ if (__toktyp == TEOF)
+  {
+   /* display all current non disable display expressions */
+   prt_all_disp_exprs();
+   return;
+  }
+
+ prtfmt = BNONE;
+ prtwidth = -1;
+ force_unsign = FALSE;
+ if (__toktyp == DIV)
+  {
+   __get_vtok();
+   if (__toktyp == ID)
+    {
+     if (strlen(__token) > 1)
+      {
+bad_prt_typ:
+       __ia_err(1425, ":display type selector /%s illegal", __token); 
+       return;
+      }
+     switch (__token[0]) {
+      case 'd': prtfmt = BDEC; break; 
+      case 'u': prtfmt = BDEC; force_unsign = TRUE; break; 
+      case 'o': prtfmt = BOCT; break;
+      case 'b': prtfmt = BBIN; break; 
+      case 'h': case 'x': prtfmt = BHEX; break;
+      case 's': prtfmt = BSTR; break; 
+      case 'c': prtfmt = BCHAR; break;
+      default: goto bad_prt_typ;
+     }
+    }
+   else
+    {
+     __ia_err(1426,
+      ":display type selector / not followed by format letter - %s read",
+      __prt_vtok());
+     return;
+    }
+   __get_vtok();
+  }
+ /* handle optional #<width> */ 
+ if (__toktyp == SHARP)
+  {
+   __get_vtok();
+   if (__toktyp != NUMBER || __itoklen > WBITS || __bcwrk[0] != 0L)  
+    { 
+     __ia_err(1427, ":display width override # not followed by legal number");
+     return;
+    }
+   prtwidth = (int32) __acwrk[0];
+   __get_vtok();
+  }
+ /* if collect returns F, if NULL, know error emitted in routine */
+ /* notice here if value, cannot free - need the iatok ptr allocated value */
+ if ((prtx = __rd_iact_expr()) == NULL) return;
+
+ /* add to display list but do not print anything */
+ dxp = (struct dispx_t *) __my_malloc(sizeof(struct dispx_t));
+ dxp->dsp_enable = TRUE;
+ dxp->dsp_frc_unsign = force_unsign;
+ dxp->dsp_num = __nxt_dispxnum++;
+ dxp->dsp_prtfmt = prtfmt; 
+ dxp->dsp_prtwidth = prtwidth; 
+ dxp->dsp_xp = prtx;
+ /* need to eval. in this instance (or use as start pt. for xmr) */
+ dxp->dsp_itp = __inst_ptr;
+ dxp->dsp_tskp = __scope_tskp;
+ /* behavior is to print last first so need to put on front */
+ dxp->dsp_nxt = __dispxhdr;
+ __dispxhdr = dxp;
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * print all expressions for display - prints nothing if none
+ */
+static void prt_all_disp_exprs(void)
+{
+ struct dispx_t *dxp;
+ char s1[RECLEN];
+
+ for (dxp = __dispxhdr; dxp != NULL; dxp = dxp->dsp_nxt) 
+  {
+   /* if disabled, do not print anything */
+   if (!dxp->dsp_enable) continue;
+
+   __push_itstk(dxp->dsp_itp);
+   dbg_bld_expr_val(__xs, dxp->dsp_xp, dxp->dsp_prtfmt,
+    dxp->dsp_prtwidth, (dxp->dsp_frc_unsign) ? TRUE : FALSE);
+   __cvsim_msg("%d:%s %s = %s\n", dxp->dsp_num, 
+    bld_prtbasecode(s1, dxp->dsp_prtfmt, (dxp->dsp_frc_unsign) ? TRUE : FALSE,
+    dxp->dsp_prtwidth), __msgexpr_tostr(__xs2, dxp->dsp_xp), __xs);
+   __pop_itstk();
+  }
+}
+
+/*
+ * convert debug base code and width to string or empty string if none
+ */
+static char *bld_prtbasecode(char *s, int32 bcod, int32 force_unsign, int32 prtwidth)
+{
+ char s1[RECLEN];
+
+ switch ((byte) bcod) {
+  case BBIN: strcpy(s, " /b"); break;
+  case BHEX: strcpy(s, " /x"); break;
+  case BDEC: 
+   if (force_unsign) strcpy(s, " /u");
+   else strcpy(s, " /d"); break;
+  case BOCT: strcpy(s, " /o"); break;
+  case BSTR: strcpy(s, " /s"); break;
+  case BCHAR: strcpy(s, " /c"); break;
+  case BNONE: strcpy(s, ""); break;
+  default: strcpy(s, "?"); __case_terr(__FILE__, __LINE__); 
+ }
+ if (prtwidth == -1) return(s);
+ strcpy(s1, s);
+ sprintf(s, "%s #%d", s1, prtwidth);
+ return(s);
+}
+
+/*
+ * MISCELLANEOUS DEBUGGER EXPRESSION ROUTINES
+ */
+
+/*
+ * emit description of expression information
+ * notice expression must be variable not scope - no way to parse and
+ * distinguish case where numeric expr. or scope can be mixed in Verilog
+ */
+static void do_dbg_expris(void)
+{
+ struct expr_t *prtx;
+ char s1[RECLEN];
+
+ __get_vtok();
+ if ((prtx = __rd_iact_expr()) == NULL) return;
+ __cvsim_msg("%s\n", bld_expr_telltale(s1, prtx));
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * build an expression tell tale
+ */
+static char *bld_expr_telltale(char *s, struct expr_t *xp)
+{
+ sprintf(s, "<top operator %s width %d", __to_opname(xp->optyp),
+  xp->szu.xclen);
+ if (xp->has_sign) strcat(s, " signed");
+ if (xp->optyp == NUMBER || xp->optyp == ISNUMBER)
+  {
+   if (xp->is_string) strcat(s, " string");
+   if (!xp->unsiznum) strcat(s, " explicit width");
+   if (xp->sizdflt) strcat(s, " default width");
+  } 
+ if (xp->is_real) strcat(s, " real"); 
+ if (xp->x_multfi) strcat(s, " fi>1 or tran wire");
+ if (xp->x_stren) strcat(s, " has strength wire");
+ if (xp->tf_isrw) strcat(s, " tf_ argument lvalue");
+ if (xp->locqualnam) strcat(s, " local qualified name");
+ strcat(s, ">");
+ return(s);
+}
+
+/*
+ * emit description of variable information
+ */
+static void do_dbg_varis(void)
+{ 
+ struct net_t *np;
+ struct expr_t *prtx;
+ struct sy_t *scope_syp;
+
+ __get_vtok();
+ if ((prtx = __rd_iact_expr()) == NULL) return;
+ if (prtx->optyp != ID)
+  {
+   __ia_err(1465, ":varis argument %s illegal - must be variable name",
+    __msgexpr_tostr(__xs, prtx));
+   return;
+  }
+ np = prtx->lu.sy->el.enp;
+ if (__last_iasytp == NULL) __misc_terr(__FILE__, __LINE__);
+ scope_syp = __last_iasytp->sypofsyt;
+ print_iddecl_ref(np->nsym, scope_syp);
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * print out a variable information line
+ *
+ * for module or system tf, scope is nil 
+ * for variable, scope is declaration symbol table (mod or task)
+ * for user task/funct, scope is containing module (or task/func/named block) 
+ * for symbol declared in named block
+ */
+static void print_iddecl_ref(struct sy_t *syp, struct sy_t *scope_syp)
+{
+ int32 nd_inst;
+ struct net_t *np;
+ struct mod_t *mdp;
+ struct symtab_t *sytp;
+ struct task_t *tskp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ mdp = NULL;
+ np = NULL;
+ tskp = NULL;
+ nd_inst = TRUE;
+ switch ((byte) syp->sytyp) {
+  case SYM_M: case SYM_PRIM: case SYM_UDP: case SYM_STSK: case SYM_SF:
+   /* DBG remove --- */
+   if (scope_syp != NULL) __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   nd_inst = FALSE;
+   sprintf(s1, "%s %s", __to_sytyp(s2, syp->sytyp), syp->synam);
+   if (syp->sy_giabase) strcat(s1, " (array of primitives base)");
+   break;
+  case SYM_I: case SYM_TSK: case SYM_F:
+   /* DBG remove --- */
+   if (scope_syp == NULL) __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   sprintf(s1, "%s %s", __to_sytyp(s2, syp->sytyp), syp->synam);
+   if (syp->sy_giabase) strcat(s1, " (instance array base)");
+   if (scope_syp->sytyp == SYM_M) mdp = scope_syp->el.emdp;
+   else mdp = scope_syp->el.eip->imsym->el.emdp;
+   break;
+  case SYM_LB:
+   /* DBG remove --- */
+   if (scope_syp == NULL) __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   sprintf(s1, "%s %s", __to_sytyp(s2, syp->sytyp), syp->synam);
+   /* for named block, can be inside task or other named block */
+   if (scope_syp->sytyp == SYM_M) mdp = scope_syp->el.emdp; 
+   else
+    {
+     tskp = scope_syp->el.etskp;
+     for (sytp = tskp->tsksymtab;; sytp = sytp->sytpar)
+      {
+       /* DBG remove --- */
+       if (sytp == NULL) __misc_terr(__FILE__, __LINE__);
+       /* --- */
+       if (sytp->sypofsyt->sytyp == SYM_M) break;
+      }
+     mdp = sytp->sypofsyt->el.emdp;
+    }
+   break; 
+  case SYM_N:
+   /* DBG remove --- */
+   if (scope_syp == NULL) __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   np = syp->el.enp;
+   __bld_showvars_prefix(s1, np, NULL);
+   if (scope_syp->sytyp == SYM_M) mdp = scope_syp->el.emdp;
+   else
+    {
+     tskp = scope_syp->el.etskp;
+     for (sytp = tskp->tsksymtab;; sytp = sytp->sytpar)
+      {
+       /* DBG remove --- */
+       if (sytp == NULL) __misc_terr(__FILE__, __LINE__);
+       /* --- */
+       if (sytp->sypofsyt->sytyp == SYM_M) break;
+      }
+     mdp = sytp->sypofsyt->el.emdp;
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ if (scope_syp == NULL) { __cvsim_msg(" %s (top level object)\n", s1); }
+ else
+  {
+   __cvsim_msg("%s in %s %s %s\n", s1,
+    __to_sytyp(s2, scope_syp->sytyp), scope_syp->synam,
+    __bld_lineloc(s3, syp->syfnam_ind, syp->sylin_cnt));
+   if (nd_inst)
+    {
+     __cvsim_msg("  [one instance: %s.%s]\n", 
+      __msg_blditree(s2, mdp->moditps[0], tskp), syp->synam);
+    }
+  }
+}
+
+/*
+ * emit information on every declaration of variable 
+ */
+static void do_dbg_whatis(void)
+{ 
+ register struct mod_t *mdp;  
+ register struct task_t *tskp;
+ int32 not_defed;
+ struct sy_t *syp;
+
+ not_defed = TRUE;
+ __get_vtok();
+ if (__toktyp != ID)
+  {
+   __ia_err(1465, ":whatis argument %s illegal - must be legal identifier",
+    __prt_vtok());
+   return;
+  }
+ /* first look in top level symbol tables (top level object) */
+ if ((syp = __get_sym(__token, __modsyms)) != NULL)
+  { print_iddecl_ref(syp, (struct sy_t *) NULL); not_defed = FALSE; }
+
+ /* look in system functions and tasks */
+ if ((syp = __get_sym(__token, __syssyms)) != NULL)
+  { print_iddecl_ref(syp, (struct sy_t *) NULL); not_defed = FALSE; }
+
+ /* next look in each module's symbol table */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if ((syp = __get_sym(__token, mdp->msymtab)) != NULL)
+    {
+     print_iddecl_ref(syp, mdp->msym);
+     not_defed = FALSE;
+    }
+  }
+ /* finally look at tasks and functions in every module */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if ((syp = __get_sym(__token, tskp->tsksymtab)) != NULL)
+      {
+       print_iddecl_ref(syp, tskp->tsksyp);
+       not_defed = FALSE;
+      }
+    }
+  }
+ if (not_defed) __cvsim_msg("%s undefined\n", __token);
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * ROUTINES TO IMPLEMENT VPI_ SIM CONTROL INTERACTIVE ROUTINES  
+ */
+
+/*
+ * execute $stop (schedule it) from user vpi_ code 
+ */
+extern int32 __do_vpi_stop(int32 diag_level)
+{
+ if (__no_iact)
+  {
+   __emit_vpi_noiact_warn();
+   return(TRUE);
+  }
+ if (__iact_state)
+  {
+   __emit_vpi_iniact_warn();
+   return(FALSE);
+  }
+ if (diag_level >= 1)
+  {
+   if (!__quiet_msgs) __cv_msg("\n");
+   __cv_msg("vpi_control vpiStop executed at time %s.\n",
+    __to_timstr(__xs, &__simtime));
+  }
+ if (diag_level >= 2) __emit_stsk_endmsg();
+
+ /* must leave signal on - if ^c hit before stop, same effect */
+ /* but entry reason different and lost */
+ __pending_enter_iact = TRUE;
+ __iact_reason = IAER_STOP;
+ return(TRUE);
+}
+
+/*
+ * do a reset from user vpi_ code (it's immediate)
+ */
+extern void __do_vpi_reset(int32 stop_val, int32 reset_val, int32 diag_level)
+{
+ int32 enter_iact;
+
+ if (diag_level >= 1)
+  {
+   if (!__quiet_msgs) __cv_msg("\n");
+   __cv_msg("vpi_control vpiReset executed at time %s.\n",
+    __to_timstr(__xs, &__simtime));
+  }
+ if (diag_level >= 2) __emit_stsk_endmsg();
+
+ /* enter interactive unless reset value non zero */
+ if (stop_val != 0) enter_iact = FALSE; else enter_iact = TRUE;
+ if (enter_iact) __stop_before_sim = TRUE; else __stop_before_sim = FALSE;
+
+ /* record state changes caused by arguments */
+ __reset_value = reset_val;
+
+ /* reenable the normal ^c signal handler - when variables reset */
+ /* sim will replace with sim handler for entering interactive */
+#if defined(INTSIGS)
+ signal(SIGINT, __comp_sigint_handler);
+#else
+ signal(SIGINT, (void (*)()) __comp_sigint_handler);
+#endif
+
+ /* this does not return - uses lng jmp */
+ longjmp(__reset_jmpbuf, 1);
+}
diff --git a/src/v_dbg2.c b/src/v_dbg2.c
new file mode 100644
index 0000000..093952c
--- /dev/null
+++ b/src/v_dbg2.c
@@ -0,0 +1,3955 @@
+/* Copyright (c) 1993-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * debugger - 2nd file most listing and break point routines 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <signal.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+/* REMOVEME - no longer supporting SunOS - maybe needed for hpux? */
+#if defined(__sparc) && !defined(__SVR4)  
+extern int32 tolower(int32);
+extern int32 sscanf(char *, char *, ...); 
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void get_middle_linrng(int32, int32 *, int32 *);
+static struct incloc_t *find_incloc(register int32);
+static int32 change_srcfile(int32);
+static int32 get_lastfillin(int32);
+static int32 bld_filpostab(int32);
+static void prt_brkpts(void);
+static char *to_brkptnam(char *, word32);
+static char *to_basename(char *, int32);
+static void dbg_info_disp(void);
+static int32 parse_scope_ref(struct itree_t **, struct task_t **, int32 *,
+ int32 *, int32 *);
+static int32 try_get_fillin_ref(char *, int32 *, int32 *, char **, char **);
+static int32 local_scope_ref(char *, struct itree_t **, struct task_t **);
+static int32 find_infil_ind(char *);
+static int32 fil_lin_toscope(int32, int32, struct itree_t **, struct task_t **);
+static int32 scope_lini_inrng(int32, int32, int32, int32, int32, int32);
+static struct incloc_t *find2_incloc(int32);
+static void set_scope_loc(struct itree_t *, struct task_t *, int32 *, int32 *);
+static int32 get_ibrk_linref(struct itree_t *, struct task_t *, int32 *, int32 *);
+static void init_brkpt(struct brkpt_t *);
+static void insert_brkpt(struct brkpt_t *);
+static struct st_t *conv_line_tostmt(struct mod_t *, struct task_t *, int32,
+ int32);
+static struct st_t *find_nxtstp(struct st_t *, int32, int32);
+static struct st_t *find_lstofsts_stp(struct st_t *, int32, int32);
+static struct incloc_t *find3_incloc(int32, int32);
+static struct st_t *find_case_stp(struct st_t *, int32, int32);
+static struct st_t *find_afterdflt(struct csitem_t *);
+static void del_all_brkpts(void);
+static void del_brkpt_num(int32);
+static int32 cnt_same_brkpts(int32, int32, struct brkpt_t **);
+static void del_all_disps(void);
+static void del_disp_num(void);
+static struct brkpt_t *rd_brkpt_num(char *, int32);
+static struct brkpt_t *find_bpp(int32);
+static int32 elim_brkpt_fromcond(struct brkpt_t *);
+static void reinit_vars_and_state(void);
+static void wr_1ev_trace(int32, i_tev_ndx);
+static void fill_near_evtab(int32, int32);
+static struct telhdr_t *tfind_btnode_after(struct bt_t *, word64);
+static int32 try_add_wrkevtab(i_tev_ndx, int32, int32 *, int32);
+static int32 get_var_scope(struct itree_t **, struct task_t **, int32 *);
+
+/* extern prototypes (maybe defined in this module) */
+extern void __do_scope_list(void);
+extern void __do_dbg_list(void);
+extern void __prt_src_lines(int32, int32, int32);
+extern void __do_dbg_set(void);
+extern int32 __get_dbg_val(void);
+extern void __do_dbg_info(void);
+extern void __do_dbg_scope(void);
+extern void __set_dbentry_listline(void);
+extern void __set_scopchg_listline(void);
+extern void __do_dbg_history(void);
+extern void __do_dbg_emptyhistory(void);
+extern int32 __do_dbg_nextb(void);
+extern void __do_dbg_brkpt(int32);
+extern void __do_dbg_ibrkpt(int32);
+extern void __do_dbg_delbrkdis(void);
+extern void __dbg_undisplay(void);
+extern void __do_dbg_dis_enable(int32);
+extern void __dbg_brk_ignore(void);
+extern void __dbg_brk_cond(void);
+extern int32 __process_brkpt(struct st_t *);
+extern void __reset_to_time0(void);
+extern void __write_snapshot(int32);
+extern void __prt_where_msg(register struct thread_t *);
+extern void __dmp_tskthrds(void);
+extern void __dmp_tskthd(struct task_t *, struct mod_t *);
+extern void __dmp_initalw_thrd_tree(void);
+extern void __dmp_thrd_tree(register struct thread_t *);
+extern void __dmp_thrd_info(struct thread_t *);
+extern void __dmp_all_thrds(void);
+
+extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
+extern void __get_vtok(void);
+extern char *__prt_vtok(void);
+extern int32 __chk_extra_atend(int32);
+extern int32 __tilde_open(char *, int32);
+extern void __my_free(char *, int32);
+extern char *__my_malloc(int32);
+extern char *__my_realloc(char *, int32, int32);
+extern int32 __get_dbcmdnum(char *, struct namlst_t *, int32);
+extern char *__bld_ambiguous_list(char *, char *, struct namlst_t *, int32);
+extern char *__schop(char *, char *);
+extern char *__to_tsktyp(char *, word32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern void __call_misctfs_scope(void);
+extern void __vpi_iactscopechg_trycall(void);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern int32 __is_scope_sym(struct sy_t *);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern void __exec_history_list(int32);
+extern struct task_t *__find_thrdtsk(struct thread_t *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern struct expr_t *__rd_iact_expr(void);
+extern int32 __colto_eol(void);
+extern void __bld_xtree(int32);
+extern void __free_xtree(struct expr_t *);
+extern char *__to_timstr(char *, word64 *);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern int32 __cvt_lngbool(word32 *, word32 *, int32); 
+extern void __free_thd_list(struct thread_t *);
+extern void __free_1thd(struct thread_t *);
+extern void __do_iact_disable(struct hctrl_t *, int32);
+extern void __free_telhdr_tevs(register struct telhdr_t *);
+extern void __free_btree(struct bt_t *);
+extern void __free_1tev(i_tev_ndx);
+extern char *__pv_stralloc(char *);
+extern void __my_fclose(FILE *);
+extern void __my_close(int32);
+extern void __reinit_tfrecs(void);
+extern void __reinit_vpi(void);
+extern void __reinit_sim(void);
+extern void __reinitialize_vars(struct mod_t *);
+extern void __initialize_dces(struct mod_t *);
+extern void __set_init_gstate(struct gate_t *, int32, int32);
+extern void __set_nchgaction_bits(void);
+extern void __set_init_udpstate(struct gate_t *, int32, int32);
+extern void __allocinit_perival(union pck_u *, int32, int32, int32);
+extern void __reinit_mipd(struct mod_pin_t *, struct mod_t *);
+extern char *__gstate_tostr(char *, struct gate_t *, int32);
+extern char *__to_evtrcanam(char *, struct conta_t *, struct itree_t *);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __ld_perinst_val(register word32 *, register word32 *, union pck_u,
+ int32);
+extern void __st_standval(register byte *, register struct xstk_t *, byte);
+extern char *__st_regab_tostr(char *, byte *, int32);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern char *__bld_valofsched(char *, struct tev_t *);
+extern char *__to_evtrwnam(char *, struct net_t *, int32, int32, struct itree_t *);
+extern char *__to_vvstnam(char *, word32);
+extern void __ld_bit(register word32 *, register word32 *,
+ register struct net_t *, int32);
+extern char *__to_vvnam(char *, word32);
+extern char *__to_mpnam(char *, char *);
+extern char *__xregab_tostr(char *, word32 *, word32 *, int32, struct expr_t *);
+extern char *__get_tfcellnam(struct tfrec_t *);
+extern char *__to_tetyp(char *, word32);
+extern char *__to_dcenam(char *, word32);
+extern char *__to_sytyp(char *, word32);
+extern void __init_mod(struct mod_t *, struct sy_t *);
+extern void __free_1glb_flds(struct gref_t *);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern char *__to_ptnam(char *, word32);
+
+extern void __cv_msg(char *, ...);
+extern void __cvsim_msg(char *, ...);
+extern void __cvsim2_msg(char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __ia_err(int32 id_num, char *s, ...);
+
+extern char __pv_ctab[];
+
+/*
+ * ROUTINES TO IMPLEMENT SOURCE LISTING 
+ */
+
+/*
+ * do the entire scope list for $list command
+ * know current scope needs to be listed - caller set and restores 
+ *
+ * leave list line at end but if different scope form will be restored there 
+ */
+extern void __do_scope_list(void)
+{
+ register int32 ifi;
+ int32 fr_ifi, to_ifi, fr_lini, to_lini, maxlini;
+ struct mod_t *mdp;
+
+ if (__scope_tskp != NULL)
+  {
+   fr_ifi = (int32) __scope_tskp->tsksyp->syfnam_ind;
+   fr_lini = __scope_tskp->tsksyp->sylin_cnt;
+   to_ifi = __scope_tskp->tsk_last_ifi;
+   to_lini =  __scope_tskp->tsk_last_lini;
+  }
+ else
+  {
+   mdp = __scope_ptr->itip->imsym->el.emdp;
+   fr_ifi = (int32) mdp->msym->syfnam_ind;
+   fr_lini = mdp->msym->sylin_cnt;
+   to_ifi = mdp->mod_last_ifi;
+   to_lini = mdp->mod_last_lini;
+  }
+ /* normal case - all in one file - current file will include scope by here */
+ 
+ if (fr_ifi == to_ifi)
+  {
+   __cvsim_msg("  Listing \"%s\" type %s file: %s\n",
+    __msg_blditree(__xs, __scope_ptr, __scope_tskp),
+    __scope_ptr->itip->imsym->synam, __in_fils[fr_ifi]);  
+   __prt_src_lines(fr_ifi, fr_lini, to_lini);
+   return;
+  }
+
+ __cvsim_msg("  File: %s\n", __in_fils[fr_ifi]);  
+ if ((maxlini = get_lastfillin(fr_ifi)) == -1) return; 
+ __prt_src_lines(fr_ifi, fr_lini, maxlini);
+ /* print intermediate files */
+ for (ifi = fr_ifi + 1; ifi < to_ifi; ifi++) 
+  {
+   __cvsim_msg("  File: %s\n", __in_fils[ifi]);  
+   if ((maxlini = get_lastfillin(ifi)) == -1) return; 
+   __prt_src_lines(ifi, 1, maxlini);
+  }
+ __cvsim_msg("  File: %s\n", __in_fils[to_ifi]);  
+ __prt_src_lines(to_ifi, 1, to_lini);
+ /* this leave current list line after last listed */
+}
+
+/*
+ * execute a list command
+ * caller checks for any wrong extra characters at end
+ *
+ * current file is always file where header line of current scope is.
+ * can give explist [file]:num list - which does not change current file
+ * :l or ":l +" - list next ten lines (keep track of current list line)
+ * :l- (list 10 lines to previous first
+ * :l [+/-] number (list 10 lines with current in middle) 
+ *   use :l +0 to list -5 to + 5 around current line 
+ * :l [+/-][line1], [+/-][line2] or :l ,[+/-][line2] or :l [+/-][line1], 
+ * :l ++/:l -- (move to next/prev. file) 
+ * :l [file]:[line] (does not need to be in scope)
+ * :l [scope] (first line of scope)
+ *
+ * this does not change scope
+ */
+extern void __do_dbg_list(void)
+{
+ int32 ltmp, lno1, lno2, rel_val, maxifi, maxlini, ifi, lini;
+ struct task_t *tskp;
+ struct itree_t *itp;
+ struct sy_t *syp;
+ struct incloc_t *ilp;
+ char *savchp, *endchp;
+
+ rel_val = ' ';
+ /* here savchp is 1st char after leading white space - endchp first after */
+ /* return F on error, if is [file]:[line] form ifi not -1 */
+ if (!try_get_fillin_ref(__visp->vichp, &ifi, &lini, &savchp, &endchp))
+  return;
+
+ /* [file]:[line] is lines around loc. */
+ if (ifi != -1)
+  {
+   if ((maxlini = get_lastfillin(ifi)) == -1) return; 
+   if (lini > maxlini)
+    {
+     __ia_err(1469,
+      "[file]:[line] reference line number %d too large - %s has %d lines",
+      lini, __in_fils[ifi], maxlini);
+     return;
+    }
+   __visp->vichp = endchp;
+   __list_arg_lini = lini;
+   get_middle_linrng(lini, &lno1, &lno2);
+   __prt_src_lines(ifi, lno1, lno2);
+   goto done;
+  }
+
+ /* parse from beginning of line */
+ __visp->vichp = savchp;
+ /* case 1: :l or ":l +" lists next 10 lines */
+ __get_vtok();
+ if (__toktyp == TEOF) 
+  {
+do_l:
+   /* here for :br, line current before list */
+   __list_arg_lini = __list_cur_lini;
+   __prt_src_lines(__list_cur_ifi, __list_cur_lini, __list_cur_lini
+    + __list_cur_listnum);
+   return;
+  }
+
+ /* if starts with letter or _ or $ must be scope */
+ /* this is not around since want to see scope */
+ if (__toktyp == ID)
+  {
+   /* this reads xmr if needed */
+   if (!get_var_scope(&itp, &tskp, &ltmp)) return;
+
+   if (tskp != NULL) syp = tskp->tsksyp; else syp = itp->itip->imsym;
+   ifi = (int32) syp->syfnam_ind;
+   lno1 = syp->sylin_cnt; 
+   __list_arg_lini = lno1;
+   __prt_src_lines(ifi, lno1, lno1 + __list_cur_listnum + 1); 
+   goto done;
+  }
+
+ if (__toktyp == PLUS)
+  { 
+   __get_vtok();
+
+   /* :l ++ - move to next file if part of same scope - use task if set */
+   /* notice always have dbg current file and line */
+   if (__toktyp == PLUS)
+    {
+     /* if in include file exit to first included from place */
+     if ((ilp = find_incloc(__list_cur_ifi)) != NULL)
+      {
+       __list_arg_lini = ilp->incfrom_lcnt;
+       /* list from include line forward */
+       __prt_src_lines(ilp->incfrom_fnind, __list_arg_lini,
+        __list_arg_lini + __list_cur_listnum + 1);
+       goto done;
+      }
+
+     maxifi = __last_srcf;
+     if (__list_cur_ifi >= maxifi)
+      {
+       __ia_err(1461, "':list ++' failed - no next source input file");    
+       return;
+      }
+     /* notice this changes __list_cur_ifi and list cur fd if succeeds */
+     __list_arg_lini = 1;
+     __prt_src_lines(__list_cur_ifi + 1, 1, __list_cur_listnum + 1);
+     goto done;
+    }
+   if (__toktyp == TEOF) goto do_l;
+   rel_val = '+';
+  }
+ /* case 1a: "l -" lists previous 10 before the ten just listed */
+ else if (__toktyp == MINUS)
+  {
+   __get_vtok();
+   /* :l ++ - move to next file if part of same scope - use task if set */
+   /* notice always have dbg current file and line */
+   if (__toktyp == MINUS)
+    {
+     /* if in include file list back from first included from place */
+     if ((ilp = find_incloc(__list_cur_ifi)) != NULL)
+      {
+       __list_arg_lini = ilp->incfrom_lcnt - __list_cur_listnum;
+       if (__list_arg_lini < 1) __list_arg_lini = 1;
+       /* list from include line forward */
+       __prt_src_lines(ilp->incfrom_fnind, __list_arg_lini,
+        ilp->incfrom_lcnt);
+       goto done;
+      }
+
+     /* first source file is 2 */
+     if (__list_cur_ifi <= 2)
+      {
+       __ia_err(1462, "':list --' failed - no previous source input file");
+       return;
+      }
+     maxlini = get_lastfillin(__list_cur_ifi - 1); 
+     __list_arg_lini = maxlini - __list_cur_listnum;  
+     if (__list_arg_lini < 1) __list_arg_lini = 1;
+     __prt_src_lines(__list_cur_ifi - 1, __list_arg_lini, maxlini);
+     goto done;
+    }
+   if (__toktyp == TEOF) 
+    {
+     /* here :br argument is one before current line - place list ends */ 
+     ltmp = __list_cur_lini - 2*(__list_cur_listnum + 1);
+     __list_arg_lini = ltmp + __list_cur_listnum + 1;
+     if (__list_arg_lini < 1) __list_arg_lini = 1;
+     __prt_src_lines(__list_cur_ifi, ltmp, ltmp + __list_cur_listnum);
+     return;
+    }
+   rel_val = '-';
+  }
+
+ /* know in current file */
+ maxlini = get_lastfillin(__list_cur_ifi); 
+ if (__toktyp == COMMA)  
+  {
+   if (rel_val != ' ')
+    {
+     __ia_err(1444, ":list command %c,[number] form illegal", rel_val); 
+     return;
+    }
+   lno1 = -2;
+   goto get_2nd_rng;
+  }
+ /* get 1st range */
+ if ((ltmp = __get_dbg_val()) == -1) 
+  {
+   __ia_err(1445, ":list command first range value %s illegal", __prt_vtok());  
+   return;
+  } 
+
+ /* know dbg current line in range - silently fix relative lines */
+ if (rel_val == '-') lno1 = __list_cur_lini - ltmp; 
+ else if (rel_val == '+') lno1 = __list_cur_lini + ltmp;
+ else
+  {
+   /* but fix line must be in range */
+   if (ltmp < 1 || ltmp > maxlini) 
+    {
+bad_lin_loc:
+     __ia_err(1463, ":list line %d impossible - %s has %d lines", ltmp,
+      __in_fils[__list_cur_ifi], maxlini); 
+     return;
+    }
+   lno1 = ltmp;
+  }
+
+ /* case 2: :l [+/-][number] form */
+ __get_vtok();
+ if (__toktyp == TEOF)
+  {
+   __list_arg_lini = lno1;
+   get_middle_linrng(lno1, &lno1, &lno2);
+   __prt_src_lines(__list_cur_ifi, lno1, lno2);
+   return;
+  }
+ if (__toktyp != COMMA)
+  {
+   __ia_err(1446,
+    ":list command line number range separator expected - %s read",
+    __prt_vtok());
+   return;
+  }
+ /* case 3: [num], form */
+get_2nd_rng:
+ __get_vtok();
+ if (__toktyp == TEOF)
+  {
+   if (lno1 == -2)
+    {
+     __ia_err(1447,
+      ":list command line number range comma by itself illegal");
+     return;
+    }
+   lno2 = lno1 + __list_cur_listnum;
+   __list_arg_lini = lno1;
+   __prt_src_lines(__list_cur_ifi, lno1, lno2);
+   return;
+  }
+ if (__toktyp == PLUS || __toktyp == MINUS)
+  {
+   if (__toktyp == PLUS) rel_val = '+'; else rel_val = '-';
+   __get_vtok();
+  }
+ else rel_val = ' ';
+ /* get 2nd range */
+ if ((ltmp = __get_dbg_val()) == -1) 
+  {
+   __ia_err(1448, ":list command second range value %s illegal", __prt_vtok()); 
+   return;
+  } 
+ if (rel_val == '-') lno2 = __list_cur_lini - ltmp;
+ else if (rel_val == '+') lno2 = __list_cur_lini + ltmp - 1;
+ else
+  {
+   /* but fix line must be in range */
+   if (ltmp < 1 || ltmp > maxlini) goto bad_lin_loc;
+   lno2 = ltmp; 
+  }
+ /* correct for ,[num] form */
+ if (lno1 == -1) lno1 = lno2 - __list_cur_listnum;
+ if (lno1 > lno2)
+  {
+   __ia_err(1464, ":list %d,%d - first range element larger than second",
+    lno1, lno2);
+   return;
+  }
+ __list_arg_lini = lno1;
+ __prt_src_lines(__list_cur_ifi, lno1, lno2);
+
+done:
+ /* if did not read eof, need to check for nothing els on line */ 
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * compute range given line in middle and global number to list
+ */
+static void get_middle_linrng(int32 mid, int32 *rng1, int32 *rng2)
+{
+ int32 ltmp;
+
+ if ((__list_cur_listnum % 2) == 0) ltmp = mid - __list_cur_listnum/2;
+ else ltmp = mid - __list_cur_listnum/2 - 1;
+ *rng1 = ltmp;
+ *rng2 = ltmp + __list_cur_listnum;
+}
+
+/*
+ * given an in_fils index that may be included find included loc record
+ * returns nil if not included file
+ */
+static struct incloc_t *find_incloc(register int32 ifi)
+{
+ register struct incloc_t *ilp;
+
+ for (ilp = __inclst_hdr; ilp != NULL; ilp = ilp->inclocnxt) 
+  if (ilp->inc_fnind == ifi) return(ilp);
+ return(NULL);
+}
+
+/*
+ * print from frlini to stoplini in file fd (will open if needed) 
+ * this uses same logic as gnu gdb list command
+ *
+ * frlini starts at 1 for first line
+ * for listing of multiple files, caller must decompose 
+ * FIXME - need to output OS returned message
+ */
+extern void __prt_src_lines(int32 ifi, int32 frlini, int32 stoplini)
+{
+ register int32 c;
+ int32 ctrlc_stop, nlines, cnt;
+ char ctab[8];
+ struct filpos_t *fposp;
+
+ /* no source printing from interactive history event */ 
+ /* DBG remove --- */
+ if (ifi == 1) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ /* *** if (ifi == 1) return; */
+
+ /* change source file if needed */
+ if (__list_cur_ifi != ifi)
+  {
+   /* this emits error on file problem */
+   if (!change_srcfile(ifi)) return;
+  }
+ if (stoplini - frlini > 20) ctrlc_stop = TRUE; else ctrlc_stop = FALSE;
+
+ /* know file line start pos. cache built and current file open to get here */
+ fposp = &(__filpostab[__list_cur_ifi]);
+
+ /* adjust range, if absolute line list argument, must check above */
+ if (frlini < 1) frlini = 1;
+ if (stoplini < 1) stoplini = 1;
+ if (stoplini > fposp->nlines) stoplini = fposp->nlines;
+ if (frlini > fposp->nlines) frlini = fposp->nlines;
+ __list_cur_lini = frlini;
+ /* notice 0 means 1 line */
+ nlines = stoplini - frlini;
+
+ /* seek to line */
+ if ((cnt = lseek(__list_cur_fd, (off_t) fposp->lpostab[__list_cur_lini - 1],
+   0)) < 0)
+  {
+   __ia_err(1437, "unable to locate source line %d in %s",
+     frlini, __in_fils[__list_cur_ifi]);
+   return;
+  }
+
+ while (nlines-- >= 0)
+  {
+   if ((cnt = read(__list_cur_fd, ctab, 1)) != 1) break; 
+   __cvsim_msg("%d\t", __list_cur_lini++);
+
+   do {
+    c = ctab[0];
+    if (c < 040 && c != '\t' && c != '\n' && c != '\r')
+     __cvsim_msg("^%c", c + 0100);
+    else if (c == 0177) __cvsim_msg("^?");
+    else __cvsim_msg("%c", c);
+    /* notice this handles any system */
+    /* under emx (dos vcpi and os2) sometimes will see return sometime not */
+    /* return sometimes appears after using ^c a few times */ 
+   } while (c != '\n' && (cnt = read(__list_cur_fd, ctab, 1)) == 1);
+   /* for long lists, must allow ^c to stop */ 
+   if (ctrlc_stop && __pending_enter_iact && __iact_reason == IAER_CTRLC)
+    {
+     __pending_enter_iact = FALSE;
+     __iact_reason = IAER_UNKN;
+     __cvsim_msg("Printing halted because interrupt (Ctrl-c) pressed.\n");
+     break;
+    }
+  }
+}
+
+/*
+ * chnage current source file - open new current and if needed build 
+ * the line pos. tab for source
+ * return F on error and do not change file
+ *
+ * only called if new_ifi different from current
+ * know there will always be current source file in fils index
+ */
+static int32 change_srcfile(int32 new_ifi)
+{
+ int32 fd;
+ struct filpos_t *fposp;
+ struct stat st;
+
+ /* if char pos of source lines table not built - build it and return */
+ if (__filpostab == NULL) fposp = NULL;
+ else fposp = &(__filpostab[new_ifi]); 
+ /* build file line start char pos. table */ 
+ if (fposp == NULL || fposp->lpostab == NULL)
+  {
+   /* if this fails, do not change current file */
+   if ((fd = bld_filpostab(new_ifi)) == -1) return(FALSE); 
+   goto good_end;
+  }
+
+ /* otherwise just open the file */
+ if ((fd = __tilde_open(__in_fils[new_ifi], O_RDONLY)) < 0)
+  {
+op_err:
+   __ia_err(1428,
+    "unable to open or access new current debugger source file %s",
+    __in_fils[new_ifi]);
+   return(FALSE);
+  }
+ if (fstat(fd, &st) < 0) goto op_err;
+ if (__start_time <= st.st_mtime)
+  __ia_err(1429, "source file %s changed after simulation started",
+   __in_fils[new_ifi]);
+ 
+ /* know succeeded */
+good_end:
+ if (__list_cur_fd != -1)
+  {
+   /* LOOKATME - do not know name of source file here */
+   /* still change even if cannot close */
+   if (close(__list_cur_fd) != 0) 
+    __ia_err(1451, "unable to close old current debugger source file");
+  }
+ __list_cur_ifi = new_ifi; 
+ __list_cur_fd = fd;
+ return(TRUE);
+}
+
+/*
+ * get last line in file
+ * this uses file position table - file can remain closed
+ */
+static int32 get_lastfillin(int32 ifi)
+{
+ struct filpos_t *fposp;
+
+ /* if char pos of source lines table not built - build it and return */
+ if (__filpostab == NULL) fposp = NULL;
+ else fposp = &(__filpostab[ifi]); 
+ /* build file line start char pos. table */ 
+ if (fposp == NULL || fposp->lpostab == NULL)
+  {
+   /* if this fails, do not change current file */
+   if (bld_filpostab(ifi) == -1) return(-1); 
+  }
+ return(fposp->nlines);
+}
+
+/*
+ * build the line character position in file table for one file  
+ * ifi is index of file in input file table
+ * return file descriptor number on success or -1 on error
+ * if success,  leaves file open
+ *
+ * know line char pos table not built and this adds to processed 
+ * could free other linpostab when this built but now leaving all
+ * know file not open
+ */
+static int32 bld_filpostab(int32 ifi)
+{
+ register int32 i, buf_base, buf_size, fsize, nlines; 
+ int32 fd, bytes, alloc_lines;
+ int32 osize, nsize;
+ int32 *linpostab;
+ struct stat st;
+ char buf[RDBUFSIZ];
+
+ if ((fd = __tilde_open(__in_fils[ifi], O_RDONLY)) < 0)
+  {
+op_err:
+   __ia_err(1428, "unable to open or access debugger current source file %s",
+    __in_fils[ifi]);
+   return(-1);
+  }
+ if (fstat(fd, &st) < 0) goto op_err;
+ if (__start_time <= st.st_mtime)
+  __ia_err(1429, "source file %s changed after simulation started", __in_fils[ifi]);
+ fsize = (int32) st.st_size;
+ linpostab = NULL;
+ for (buf_base = 0, alloc_lines = 0, nlines = 0;;)
+  {
+   if (buf_base + RDBUFSIZ <= fsize) buf_size = RDBUFSIZ; 
+   else buf_size = fsize - buf_base;
+
+   if ((bytes = read(fd, buf, buf_size)) != buf_size)
+    {
+     __ia_err(1433,
+      "error reading source file %s when building line position table",
+      __in_fils[ifi]);
+     if (alloc_lines != 0) __my_free((char *) linpostab,
+      sizeof(int32)*alloc_lines);
+     if (close(fd) != 0) 
+      __ia_err(1458, "unable to close source file %s after read error",
+       __in_fils[ifi]);
+     return(-1);
+    }
+   if (alloc_lines == 0)
+    {
+     alloc_lines = 1000;
+     linpostab = (int32 *) __my_malloc(alloc_lines*sizeof(int32));
+     linpostab[0] = 0;
+     nlines = 1;
+    }
+   for (i = 0; i < buf_size;) 
+    {
+     /* a newline at the end of file does not start a new line */
+     if (buf[i++] == '\n' && i < buf_size)
+      {
+       if (nlines == alloc_lines)
+        {
+         osize = (word32) alloc_lines*sizeof(int32);
+         alloc_lines *= 2;
+         linpostab = (int32 *) __my_realloc((char *) linpostab, osize, 
+          alloc_lines*sizeof(int32)); 
+        } 
+       linpostab[nlines++] = buf_base + i;
+      }
+    }
+   if ((buf_base += buf_size) == fsize) break;
+  } 
+ 
+ /* final step is to allocate and fill parallel to __in_fils array of */
+ /* file line info */ 
+ if (__filpostab == NULL) 
+  {
+   __filpostab = (struct filpos_t *)
+    __my_malloc((__last_srcf + 1)*sizeof(struct filpos_t));
+   for (i = 0; i <= __last_srcf; i++)
+    {
+     __filpostab[i].nlines = 0;
+     __filpostab[i].lpostab = NULL;
+    }
+  }
+ /* know line table not built or will not be called */
+ if (__filpostab[ifi].lpostab != NULL) __arg_terr(__FILE__, __LINE__);
+ /* must adjust allocated line table down to right size if needed */
+ if (nlines != alloc_lines)
+  {
+   osize = (word32) (alloc_lines*sizeof(int32));
+   nsize = (word32) (nlines*sizeof(int32));
+   linpostab = (int32 *) __my_realloc((char *) linpostab, osize, nsize);
+  }
+ __filpostab[ifi].lpostab = linpostab; 
+ __filpostab[ifi].nlines = nlines; 
+ return(fd);
+}
+
+/*
+ * ROUTINES TO IMPLEMENT COLON DEBUGGER SET COMMANDS
+ */
+
+#define SET_LSIZE 0
+#define SET_HLSIZE 1
+#define SET_SCHG 2
+#define SET_NOSCHG 3
+#define SET_PRTBASE 4 
+#define SET_LOGECHO 5
+#define SET_NOLOGECHO 6
+
+/* set command options table */
+static struct namlst_t setargs[] = {
+ { SET_LSIZE, "listsize" }, 
+ { SET_HLSIZE, "histlistsize" }, 
+ { SET_SCHG, "scopechange" },
+ { SET_NOSCHG, "noscopechange" },
+ { SET_PRTBASE, "printbase" },
+ { SET_LOGECHO, "logecho" },
+ { SET_NOLOGECHO, "nologecho" }
+};
+#define NSETARGS (sizeof(setargs) / sizeof(struct namlst_t))
+
+/*
+ * execute debug set command - for now only :set listsize [number]
+ */
+extern void __do_dbg_set(void)
+{
+ char blet;
+ int32 rv, lines;
+
+ __get_vtok();
+ if (__toktyp != ID)
+  {
+bad_setval:
+   __ia_err(1441, ":set %s - debugger set parameter illegal or unknown",
+    __prt_vtok());
+   return;
+  }
+ rv = __get_dbcmdnum(__token, setargs, NSETARGS);
+ switch (rv) {
+  case -1: goto bad_setval;
+  case -2:
+   __ia_err(1422, "ambiguous :set %s parameter: %s", __token,
+    __bld_ambiguous_list(__xs, __token, setargs, NSETARGS));
+   return;
+  case SET_LSIZE:
+   __get_vtok();
+   if ((lines = __get_dbg_val()) == -1) 
+    { 
+     __ia_err(1442,
+      ":set listsize required number of lines value expected - %s read",
+      __prt_vtok());
+     return;
+    }
+   __list_cur_listnum = lines - 1;
+   break;
+  case SET_HLSIZE:
+   __get_vtok();
+   if ((lines = __get_dbg_val()) == -1) 
+    { 
+     __ia_err(1442,
+      ":set histlistsize required command number value expected - %s read",
+      __prt_vtok());
+     return;
+    }
+   __hist_cur_listnum = lines;
+   break;
+  case SET_SCHG: __iact_scope_chg = TRUE; break;
+  case SET_NOSCHG: __iact_scope_chg = FALSE; break;
+  case SET_PRTBASE:
+   __get_vtok();
+   if (__toktyp != ID)
+    { 
+bad_base:
+     __ia_err(1449,
+      ":set printbase required default :print command base %s unrecognized",
+      __prt_vtok());
+     return;
+    }
+   blet = (isupper(__token[0])) ? tolower(__token[0]) : __token[0];
+   if (blet == 'b') __dbg_dflt_base = BBIN; 
+   else if (blet == 'o') __dbg_dflt_base = BOCT;
+   else if (blet == 'h') __dbg_dflt_base = BHEX; 
+   else if (blet == 'd') __dbg_dflt_base = BDEC;
+   else goto bad_base;
+   break;
+  case SET_NOLOGECHO: __echo_iactcmds_tolog = FALSE; break;
+  case SET_LOGECHO: __echo_iactcmds_tolog = TRUE; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * get debugger value - return -1 on error - caller must emit message
+ * this is only for positive values and expects token to have been read
+ * this expects first token to have been read
+ *
+ * LOOKATME - notice slight memory link if error is string will not be freed
+ */
+extern int32 __get_dbg_val(void)
+{
+ int32 val;
+
+ if (__toktyp != NUMBER || __itoklen > WBITS || __bcwrk[0] != 0L) return(-1);  
+ val = (int32) __acwrk[0];
+ if (val < -1) return(-1);  
+ return(val);
+}
+
+/*
+ * ROUTINES TO IMPLEMENT INFO COMMAND
+ */
+#define INFO_LSIZE 0
+#define INFO_HLSIZE 1
+#define INFO_SCHG 2
+#define INFO_BRKPT 3
+#define INFO_PRTBASE 4
+#define INFO_LOGECHO 5
+#define INFO_DISPLAY 6
+
+/* info command options table */
+static struct namlst_t infoargs[] = {
+ { INFO_LSIZE, "listsize" }, 
+ { INFO_HLSIZE, "histlistsize" }, 
+ { INFO_SCHG, "scopechange" },
+ { INFO_BRKPT, "breakpoints" },
+ { INFO_PRTBASE, "printbase" },
+ { INFO_LOGECHO, "logecho" },
+ { INFO_DISPLAY, "displays" }
+};
+#define NINFOARGS (sizeof(infoargs) / sizeof(struct namlst_t))
+
+/*
+ * execute debug info command 
+ */
+extern void __do_dbg_info(void)
+{
+ int32 rv;
+ char s1[RECLEN];
+ 
+ __get_vtok();
+ if (__toktyp != ID)
+  {
+bad_infoval:
+   __ia_err(1443, ":info command parameter %s unknown", __prt_vtok());
+   return;
+  }
+
+ rv = __get_dbcmdnum(__token, infoargs, NINFOARGS);
+ switch (rv) {
+  case -1: goto bad_infoval;
+  case -2:
+   __ia_err(1422, "ambiguous info %s command parameter: %s", __token,
+    __bld_ambiguous_list(__xs, __token, infoargs, NINFOARGS));
+   return;
+  case INFO_LSIZE:
+   __cvsim_msg("number of lines to list is %d\n", __list_cur_listnum + 1);
+   break;
+  case INFO_HLSIZE:
+   __cvsim_msg("number of history commands to list is %d\n",
+    __hist_cur_listnum);
+   break;
+  case INFO_SCHG:
+   if (__iact_scope_chg)
+    __cvsim_msg("interactive scope set on debugger entry\n");
+   else __cvsim_msg("interactive scope only changed by $scope\n");
+   break;
+  case INFO_BRKPT:
+   prt_brkpts();
+   break;
+  case INFO_PRTBASE:
+   __cvsim_msg("default numeric base for :print command is %s\n",
+    to_basename(s1, __dbg_dflt_base));
+   break;
+  case INFO_LOGECHO:
+   if (__echo_iactcmds_tolog)
+    __cvsim_msg("interactive input commands echoed to log file\n");
+   else __cvsim_msg("interactive input command echo to log file off\n");
+   break;
+  case INFO_DISPLAY:
+   dbg_info_disp();
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * routine to print the current breakpoints
+ */
+static void prt_brkpts(void)
+{
+ register struct brkpt_t *bpp;
+ char s1[RECLEN], s2[RECLEN];
+
+ if (__bphdr == NULL)
+  {
+   __cvsim_msg("No Breakpoints.\n");
+   return;
+  }
+
+ __cvsim_msg("Breakpoints:\n");
+ __cvsim_msg("Number  Disp Filter  Source-Instance Location\n");
+ for (bpp = __bphdr; bpp != NULL; bpp = bpp->bpnxt) 
+  {
+   if (bpp->bp_enable)
+    { if (bpp->bp_rm_when_hit) strcpy(s1, "del "); else strcpy(s1, "keep"); }
+   else strcpy(s1, "dis ");
+   __cvsim_msg("%-6d  %-4s  %-5s", bpp->bp_num, s1,
+    to_brkptnam(s2, bpp->bp_type));
+   __cvsim_msg("  %-s:%d", __schop(s1,
+     __in_fils[bpp->bp_stp->stfnam_ind]), (int32) bpp->bp_stp->stlin_cnt);
+   /* form is :[file]:[line]([inst or type]) */
+   if (bpp->bp_itp == NULL) __arg_terr(__FILE__, __LINE__); 
+   
+   if (bpp->bp_type == BP_INST)
+    __cvsim_msg("(%s)\n", __msg_blditree(s1, bpp->bp_itp, bpp->bp_tskp));
+   else
+    {
+     if (bpp->bp_tskp == NULL)
+      __cvsim_msg("(in %s)\n", bpp->bp_itp->itip->imsym->synam);  
+     else __cvsim_msg("(in %s %s: %s)\n",
+      bpp->bp_itp->itip->imsym->synam, __to_tsktyp(s1, bpp->bp_tskp->tsktyp),
+      bpp->bp_tskp->tsksyp->synam);  
+    }
+   if (bpp->bp_condx != NULL) __cvsim_msg("        stop if: %s\n",
+     __msgexpr_tostr(__xs, bpp->bp_condx));
+  
+   if (bpp->bp_hit_cnt > 0)
+    __cvsim_msg("        breakpoint now hit %d times\n", bpp->bp_hit_cnt);
+   if (bpp->bp_ignore_cnt - bpp->bp_hit_cnt > 0)
+    __cvsim_msg("        ignore next %d hits\n",
+     bpp->bp_ignore_cnt - bpp->bp_hit_cnt);
+  }
+}
+
+/*
+ * convert breakpoint type value to its name
+ */
+static char *to_brkptnam(char *s, word32 bptyp)
+{
+ switch ((byte) bptyp) {
+  case BP_INST: strcpy(s, "Inst"); break; 
+  case BP_TYPE: strcpy(s, "Type"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+/*
+ * convert base code to letter
+ */
+static char *to_basename(char *s, int32 base)
+{
+ switch ((byte) base) {
+  case BBIN: strcpy(s, "binary"); break;
+  case BHEX: strcpy(s, "hex"); break;
+  case BOCT: strcpy(s, "octal"); break;
+  case BDEC: strcpy(s, "decimal"); break;
+  default: strcpy(s, "?"); __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * print info lines for all breakpoints 
+ */
+static void dbg_info_disp(void)
+{
+ struct dispx_t *dxp;
+ char s1[RECLEN];
+
+ if (__dispxhdr == NULL)
+  {
+   __cvsim_msg("No auto-display expressions.\n");
+   return;
+  }
+ __cvsim_msg("Number  Enable Expression-(instance)\n");
+ for (dxp = __dispxhdr; dxp != NULL; dxp = dxp->dsp_nxt) 
+  {
+   if (dxp->dsp_enable) strcpy(s1, "y"); else strcpy(s1, "n");
+   __cvsim_msg("%-7d   %s     %s (%s)\n", dxp->dsp_num, s1,
+    __msgexpr_tostr(__xs, dxp->dsp_xp), __msg_blditree(__xs2, dxp->dsp_itp,
+    dxp->dsp_tskp));
+  }
+}
+
+/*
+ * ROUTINES TO PARSE A SCOPE REFERNENCE
+ */
+
+/*
+ * : debugger :scope command normal scope except allow [file]:[line] form
+ * where first instance is implied - other wide argument is normal scope
+ * :sc [file]:[line], .u (..) .d , normal xmr
+ * returns T if parsed all of args even if error 
+ *
+ * notice scheme is to maybe use line to determine scope but then always
+ * set at first line of scope not entered line?
+ * ihea is that probably want to start by listing header and initial always
+ * are ||
+ */
+extern void __do_dbg_scope(void)
+{
+ int32 ifi, lini, iref;
+ struct itree_t *in_itp; 
+ struct task_t *in_tskp;
+
+ /* if cannot parse scope location, error emitted in routine */
+ if (!parse_scope_ref(&in_itp, &in_tskp, &ifi, &lini, &iref)) return;
+ /* do the scope change - implies current line change */
+ /* notice even if ifi and line set, not used */
+ __scope_ptr = in_itp;
+ __scope_tskp = in_tskp;
+ /* replace top of inst. stack */
+ __pop_itstk();
+ __push_itstk(__scope_ptr);
+ __set_scopchg_listline();
+
+ if (__tfrec_hdr != NULL) __call_misctfs_scope();
+ if (__have_vpi_actions) __vpi_iactscopechg_trycall();
+
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * routine to get scope line location for breakpoints and printing 
+ * return F on error
+ * this may set values but invalid unless returns T 
+ * if T know all 5 return by ref. values set 
+ * for breakpoints - determines if one instance ref only (iref T)
+ * because of file form this does not use get_vtok but access vichp 
+ * for scope but not line ref. sets ref_ifi and ref_lini to -1
+ *
+ * forms: .. .u .d scope change => scope,task,file,1st line
+ *        [file]:[line] or [line] (current file) - scope,task,[file],[line] 
+ *        [module name] => scope 1st inst,no task, file,first line 
+ *        xmr => scope,task,file,1st line
+ *
+ * notice no spaces allowed in reference
+ */
+static int32 parse_scope_ref(struct itree_t **ref_itp, struct task_t **ref_tskp,
+ int32 *ref_ifi, int32 *ref_lini, int32 *iref)
+{
+ register char *chp;
+ int32 ifi, lini, maxlini;
+ struct itree_t *itp;
+ struct task_t *tskp;
+ char *savchp, *endchp, sref[RECLEN];
+
+ /* assume instance ref. */
+ *iref = TRUE;
+ /* here savchp is 1st char of token - endchp first after */
+ /* return F on error, if is not [file]:[line] ref - ifi is -1 */
+ if (!try_get_fillin_ref(__visp->vichp, &ifi, &lini, &savchp, &endchp))
+  return(FALSE);
+
+ if (ifi != -1)
+  {
+set_line_scope:
+   if ((maxlini = get_lastfillin(ifi)) == -1) return(FALSE); 
+   if (lini > maxlini)
+    {
+     __ia_err(1469,
+      "[file]:[line] reference line number %d too large - %s has %d lines",
+      lini, __in_fils[ifi], maxlini);
+     return(FALSE);
+    }
+
+   if (!fil_lin_toscope(ifi, lini, ref_itp, ref_tskp))
+    {
+     __ia_err(1454,
+      "scope reference %s:%d illegal - line not inside any module",
+      __in_fils[ifi], lini);
+     return(FALSE);
+    } 
+   *ref_ifi = ifi;
+   *ref_lini = lini;
+   /* if has line number, not an instance ref. */ 
+   *iref = FALSE;
+   /* current get tok place is just after [file]:[line] ref. */
+   __visp->vichp = endchp;
+   return(TRUE);
+  }
+
+ /* know not [file]:[line] ref - try scope or special abbrev. */
+ /* build the token */
+ strncpy(sref, savchp, endchp - savchp); 
+ sref[endchp - savchp] = '\0';  
+ /* assume will match local scope ref. or [number] implied file form */
+ __visp->vichp = endchp;
+ /* maybe special local .. form */
+ if (sref[0] == '.')
+  {
+   *ref_ifi = -1;
+   *ref_lini = -1;
+   return(local_scope_ref(sref, ref_itp, ref_tskp));
+  }
+
+ /* does not have : not [file]:[line] but maybe [line] */
+ if (isdigit(sref[0]))
+  {
+   for (chp = sref; *chp != '\0'; chp++)
+    {
+     if (!isdigit(*chp))
+      {
+bad_lin:
+       __ia_err(1452, "scope reference [line] form %s illegal format", sref);
+       return(FALSE);
+      }
+    } 
+   if (sscanf(sref, "%d", &lini) != 1) goto bad_lin; 
+   ifi = __list_cur_ifi;
+   goto set_line_scope;
+  }
+
+ /* must be identifier - need get vtok to check and parse GLBREF */
+ /* put back and parse */
+ __visp->vichp = savchp;
+ 
+ /* know file form elminated before here */
+ __get_vtok(); 
+ if (__toktyp != ID)
+  {
+   __ia_err(1467, "scope reference %s illegal", __prt_vtok());
+   return(FALSE);
+  }
+ if (!get_var_scope(&itp, &tskp, iref)) return(FALSE);
+ *ref_itp = itp;  
+ *ref_tskp = tskp;
+ *ref_ifi = -1;
+ *ref_lini = -1;
+ return(TRUE);
+}
+
+/*
+ * attempt to read a file and line reference form
+ * return F on error
+ * set ifi to -1 if turns out not to be [file]:[line] form
+ * lini and endchp only good if ifi not -1
+ */
+static int32 try_get_fillin_ref(char *st_chp, int32 *ifi, int32 *lini,
+ char **sav_chp, char **endchp)
+{
+ register char *chp;
+ int32 rlen, arglen, rv;
+ char *chp1, *sref, *argref;
+ char s1[RECLEN];
+
+ /* skip any leading white space */
+ argref = NULL;
+ arglen = 0;
+ rv = TRUE;
+ *ifi = *lini = -1;
+ for (chp = st_chp;; chp++) { if (!vis_white_(*chp)) break; }
+ *sav_chp = chp;
+
+ /* separate scope reference into separate string in case file:line form */
+ /* tricky because anything except \0 can go in file name */
+ chp1 = chp;
+ for (;; chp++)
+  {
+   /* any escaped cannot end */
+   if (*chp == '\\') { chp++; continue; }
+   if (vis_white_(*chp) || *chp == '\0') break; 
+  }
+ rlen = chp - chp1;
+ sref = __my_malloc(rlen + 1);
+ strncpy(sref, chp1, rlen);
+ sref[rlen] = '\0'; 
+
+ /* set vichp to continuation place in case more arguments */
+ *endchp = chp;
+ /* have scope ref. in sref - rule if has unescaped : line, else scope */ 
+ /* escaped ID always scope ref */
+ if (sref[0] == '\\') goto done;
+ /* if no : cannot be [file]:[line] form - [line] form handled elsewhere */
+ if ((chp = strrchr(sref, ':')) == NULL) goto done;
+ chp--;
+ /* if last : escaped no possible number following */
+ if (*chp == '\\')  goto done;
+ chp++;
+ arglen = chp - sref + 1;
+ argref = __my_malloc(arglen);
+ strncpy(argref, sref, chp - sref);
+ argref[chp - sref] = '\0';
+ /* must be all digits after : */
+ chp++;
+ for (chp1 = chp; *chp1 != '\0'; chp1++)
+  {
+   if (!isdigit(*chp1))
+    {
+bad_fil_lin:
+     __ia_err(1468, "[file]:[line] form %s illegal format", sref);
+     rv = FALSE;
+     goto done;
+    }
+  }
+ strcpy(s1, chp);
+ if (sscanf(s1, "%d", lini) != 1 || *lini < 1) goto bad_fil_lin; 
+ if ((*ifi = find_infil_ind(argref)) == -1)
+  {
+   __ia_err(1453,
+    "scope reference file, path or path tail \"%s\" unrecognized", argref);
+   rv = FALSE;
+  }
+done:
+ __my_free(sref, rlen + 1);
+ if (argref != NULL) __my_free(argref, arglen);
+ return(rv);
+}
+
+/*
+ * get a ID or GLBREF expr. (know read token ID) scope location
+ * 
+ * this reads to EOL - no other way to know end because of inst. array sel.
+ *
+ *
+ * need to run with current module for counting any allocated globals
+ * may alloc some globals in grwrk tab - need to free fields and empty tab
+ */
+static int32 get_var_scope(struct itree_t **itpp, struct task_t **tskpp,
+ int32 *iref)
+{
+ int32 gri, rv, sav_ecnt;
+ struct sy_t *syp;
+ struct gref_t *grp;
+ struct expr_t *glbndp;
+ struct expridtab_t *xidp;
+ struct mod_t wrkmod;
+ struct sy_t wrksym;
+ char s1[RECLEN];
+
+ rv = TRUE;
+ syp = NULL;
+ /* collect to end of line (TEOF) */
+ if (!__colto_eol())
+  {
+   __ia_err(1434, "scope reference bad format - extra tokens at end(?)");
+   return(FALSE); 
+  }
+
+ /* allow [module name] form if not instance name - not legal source xmr */
+ /* must handle this before parsing since it is an error */
+ if (__last_xtk == 0 && __exprtab[0]->optyp == ID)
+  {
+   xidp = __expr_idtab[0];
+
+   /* know this has one component */
+   /* case 1: not defined in cur. module or not scope in cur. mod */
+   if ((syp = __get_sym(xidp->idnam,
+    __scope_ptr->itip->imsym->el.emdp->msymtab)) == NULL
+    || !__is_scope_sym(syp))
+    {
+     /* can scope to any module (implied first instance) */
+     /* udp's are in mod syms */
+     if ((syp = __get_sym(xidp->idnam, __modsyms)) != NULL
+      && syp->sytyp == SYM_M)
+      {
+       *tskpp = NULL;  
+       *itpp = syp->el.emdp->moditps[0];
+       /* if top then this is iref need for ibreak where required */
+       if (syp->el.emdp->minstnum == 0) *iref = TRUE; else *iref = FALSE;
+       return(TRUE);
+      }
+     /* must be some kind of one component global or maybe error */
+    }
+  }
+
+ wrksym.synam = s1;
+ wrksym.sydecl = TRUE;
+ strcpy(wrksym.synam, "** DBG SCOPE WRK**"); 
+ __init_mod(&wrkmod, &wrksym);
+ wrkmod.flatinum = 1;
+ wrksym.el.emdp = &wrkmod;
+ __push_wrkitstk(&wrkmod, 0);
+
+ /* try global - can be one component downward relative xmr */
+ /* if fails will be set to x number */
+ sav_ecnt = __pv_err_cnt;
+ __allow_scope_var = TRUE;
+ __bld_xtree(0);
+ __allow_scope_var = FALSE;
+ glbndp = __root_ndp;
+ if (__pv_err_cnt > sav_ecnt) { rv = FALSE; goto done; }
+
+ /* if local task/func/named block reference - just change task */
+ /* if local reference may have been converted back to ID */
+ if (glbndp->optyp == ID)
+  {
+   if (!__is_scope_sym(glbndp->lu.sy))
+    {
+     __ia_err(1440, "scope reference to non scope symbol %s type %s",
+      glbndp->lu.sy->synam,  __to_sytyp(__xs, glbndp->lu.sy->sytyp));
+     rv = FALSE;
+     goto done;
+    }
+
+   /* know scope ptr always on top of inst. stack here */
+   *itpp = __scope_ptr; 
+   *tskpp = glbndp->lu.sy->el.etskp;
+   rv = TRUE;
+   goto done;
+  }
+
+ if (glbndp->optyp != GLBREF) 
+  {
+   __ia_err(1411, "scope reference illegal hierarchical reference");
+   return(FALSE);
+  }
+ grp = glbndp->ru.grp;
+ if (grp->gr_err) { rv = FALSE; goto done; }
+
+ /* convert from gref reference to itree target location */
+ __xmrpush_refgrp_to_targ(grp);
+ *itpp = __inst_ptr;
+ __pop_itstk();
+
+ if (glbndp->lu.sy->sytyp != SYM_I && glbndp->lu.sy->sytyp != SYM_M)
+  *tskpp = glbndp->lu.sy->el.etskp;
+ else *tskpp = NULL;
+
+done:
+ if (__grwrknum > 0)
+  {
+   grp = &(__grwrktab[0]);
+   for (gri = 0; gri < __grwrknum; grp++, gri++) __free_1glb_flds(grp);
+   __grwrknum = 0;
+  }
+ __free_xtree(glbndp);
+ __pop_wrkitstk();
+ return(rv);
+}
+
+/*
+ * get a local form scope reference
+ * know 1st token read
+ */
+static int32 local_scope_ref(char *refnam, struct itree_t **ref_itp,
+ struct task_t **ref_tskp)
+{
+ struct itree_t *itp;
+ struct task_t *tskp;
+ struct symtab_t *sytp;
+
+ if (refnam[1] == '.')
+  {
+   if (refnam[2] != '\0') goto bad_locchg;
+
+do_up:
+   /* if in task, up is to next task up or enclosing named block */
+   tskp = __scope_tskp;
+   itp = __scope_ptr;
+   if ((tskp = __scope_tskp) != NULL)
+    {
+     /* see what parent symbol table symbol of is */
+     sytp = tskp->tsksymtab->sytpar;
+     if (sytp == NULL) __misc_terr(__FILE__, __LINE__);
+     /* if task top in module up is module scope */
+     if (sytp->sypofsyt->sytyp == SYM_M) tskp = NULL;
+     else tskp = sytp->sypofsyt->el.etskp;
+    } 
+   else
+    {
+     if (__scope_ptr->up_it == NULL)
+      {
+       __ia_err(1455,
+        "scope reference .. (up) change impossible - already at top level");
+       return(FALSE);
+      }
+     itp = __scope_ptr->up_it;
+     tskp = NULL;
+    }
+   goto do_change;
+  }
+ /* :scope .[dir. letter] */
+ if ((refnam[1] != 'u' && refnam[1] != 'd') || refnam[2] != '\0')
+  {
+bad_locchg:
+   __ia_err(1459,
+    "illegal scope reference local change argument %s", refnam);
+   return(FALSE);
+  }
+ if (refnam[1] == 'u') goto do_up; 
+ /* down case - even if current task scope ignore */
+ if (__scope_ptr->in_its == NULL)
+  {
+   __ia_err(1456,
+    "scope reference local .d move down impossible - scope has no instances");
+    return(FALSE);
+  }
+ itp = &(__scope_ptr->in_its[0]);
+ tskp = NULL;
+
+do_change:
+ *ref_itp = itp;
+ *ref_tskp = tskp;
+ return(TRUE);
+}
+
+/*
+ * given a file name or path, convert to in_fils index number
+ * return -1 if no match
+ */
+static int32 find_infil_ind(char *nam)
+{
+ register int32 i;
+ char *chp;
+ 
+ /* file spec. if path - must match path exactly */
+ if ((chp = strrchr(nam, '/')) != NULL)
+  {
+   /* 0 and 1 used for place holders */
+   for (i = 2; i <= __last_srcf; i++) 
+    { if (strcmp(nam, __in_fils[i]) == 0) return(i); }
+   return(-1);
+  }
+ /* simple file, first try to match exactly */
+ for (i = 2; i <= __last_srcf; i++)
+  { if (strcmp(nam, __in_fils[i]) == 0) return(i); }
+ /* then try tails of paths */
+ for (i = 2; i <= __last_srcf; i++)
+  {
+   if ((chp = strrchr(__in_fils[i], '/')) == NULL) continue;
+   if (strcmp(++chp, __in_fils[i]) == 0) return(i);
+  }
+ return(-1);
+}
+
+/*
+ * find scope from line number
+ * do not need file pos. table for this
+ */
+static int32 fil_lin_toscope(int32 ifi, int32 lini, struct itree_t **in_itp,
+ struct task_t **in_tskp)
+{
+ register struct mod_t *mdp; 
+ register struct task_t *tskp;
+ struct mod_t *in_mdp;
+
+ /* module in means from first to last */
+ for (in_mdp = NULL, mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (scope_lini_inrng(lini, ifi, mdp->msym->sylin_cnt,
+    (int32) mdp->msym->syfnam_ind, mdp->mod_last_lini, mdp->mod_last_ifi))
+    {
+     in_mdp = mdp;
+     break;
+    }
+  }
+ if (in_mdp == NULL) return(FALSE);
+ *in_itp = in_mdp->moditps[0];
+ /* next see if within task or function but not named block */
+ /* since named blocks nests must handle as normal statements */  
+ *in_tskp = NULL;
+ for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+   /* notice must include named blocks as well as task/funcs in scope */
+   if (scope_lini_inrng(lini, ifi, tskp->tsksyp->sylin_cnt,
+    (int32) tskp->tsksyp->syfnam_ind, tskp->tsk_last_lini, tskp->tsk_last_ifi))
+    { *in_tskp = tskp; break; }
+  } 
+ return(TRUE);
+}
+
+/*
+ * determine if line inside module scope - scope can span multiple files 
+ *
+ * here line can be anywhere in module scope providing followed by procedural
+ * statement
+ */
+static int32 scope_lini_inrng(int32 lini, int32 ifi, int32 st_lini, int32 st_ifi,
+ int32 last_lini, int32 last_ifi)
+{
+ struct incloc_t *ilp;
+
+ /* if ifi included (first) file ilp is non included location */
+ /* that is right location for which to do in range check */
+ if ((ilp = find2_incloc(ifi)) != NULL) 
+  { ifi = ilp->incfrom_fnind; lini = ilp->incfrom_lcnt; }
+
+ /* debugger current location in file outside scope files */
+ if (ifi < st_ifi || ifi > last_ifi) return(FALSE);
+
+ /* in first (usually only) file of scope */
+ if (ifi == st_ifi)
+  {
+   if (lini < st_lini) return(FALSE);
+   if (last_ifi > ifi) return(TRUE);
+   return(lini <= last_lini);
+  }
+ /* in last file of scope where scope spans files */
+ if (ifi == last_ifi) return(lini <= last_lini);
+ /* if in not first or last spanned file, then know in range */
+ return(TRUE);
+}
+
+/*
+ * find incloc that is non included file
+ * for multiply included this returns location of outermost
+ */
+static struct incloc_t *find2_incloc(int32 ifi)
+{
+ struct incloc_t *ilp, *ilp2; 
+
+ if ((ilp2 = find_incloc(ifi)) == NULL) return(NULL);
+ /* know included trace outward until finding one not included and */
+ /* return that ilp */
+ for (;;)
+  {
+   ifi = ilp2->incfrom_fnind;
+   ilp = ilp2;
+   if ((ilp2 = find_incloc(ifi)) == NULL) break;
+  }
+ return(ilp);
+}
+
+/*
+ * set list line to suspended thread next statement first line if possible
+ * else to first line of scope
+ */
+extern void __set_dbentry_listline(void)
+{
+ int32 lini, ifi;
+ struct st_t *stp;
+
+ if (__suspended_thd == NULL || __suspended_thd->thnxtstp == NULL)
+  {
+   __set_scopchg_listline();
+   goto done;
+  }
+
+ stp = __suspended_thd->thnxtstp;
+ ifi = (int32) stp->stfnam_ind;
+ /* never change dbg list line to interactive history */
+ if (ifi == __cmd_ifi) goto done;
+ lini = stp->stlin_cnt;
+ __list_arg_lini = __list_cur_lini = lini;
+ if (__list_cur_ifi != ifi)
+  {
+   /* this emits error on file problem */
+   if (!change_srcfile(ifi)) return;
+  }
+ done:;
+  /* DBG REMOVED ---
+  if (__debug_flg)
+   {
+   __dbg_msg("=== IACT entry at %s scope %s\n",
+    __bld_lineloc(__xs, (word32) __list_cur_ifi, __list_cur_lini), 
+    __msg_blditree(__xs2, __scope_ptr, __scope_tskp));
+   }
+ --- */
+}
+
+/*
+ * set a scope change list line - for interactive only
+ */
+extern void __set_scopchg_listline(void)
+{
+ int32 lini, ifi;
+ struct sy_t *syp;
+
+ /* no suspended thread use first line of scope */
+ if (__scope_tskp != NULL) syp = __scope_tskp->tsksyp;
+ else syp = __scope_ptr->itip->imsym;
+ ifi = (int32) syp->syfnam_ind;
+ /* start with list arg same as scope */
+ lini = syp->sylin_cnt;
+ __list_arg_lini = __list_cur_lini = lini;
+ /* this emits error on file problem */
+ if (__list_cur_ifi != ifi) change_srcfile(ifi);
+}
+
+/*
+ * print history list - :history [number] command
+ */
+extern void __do_dbg_history(void)
+{
+ int32 hnum;
+
+ __get_vtok(); 
+ if (__toktyp == TEOF) { __exec_history_list(__hist_cur_listnum); return; }
+ /* notice since history starts at 1, last is same as size */
+ if ((hnum = __get_dbg_val()) == -1 || hnum < 0)
+  { __ia_err(1477, ":history %s argument illegal", __prt_vtok()); return; } 
+ __exec_history_list(hnum);
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * empty the history list if possible
+ */
+extern void __do_dbg_emptyhistory(void)
+{
+ register int32 iahi;
+ struct iahist_t *iahp;
+ int32 llen;
+
+ /* first check to make sure nothing pending */ 
+ for (iahi = 1; iahi <= __iah_lasti; iahi++) 
+  {
+   iahp = &(__iahtab[iahi]);
+   /* notice when non immediate statement finishes, disable turned on */ 
+   if (iahp->iah_hcp != NULL)
+    {
+     __ia_err(1483,
+      ":emptyhistory impossible because command %d not completed or disabled",
+      iahi); 
+     return;
+    }
+  }
+ for (iahi = 1; iahi <= __iah_lasti; iahi++) 
+  {
+   iahp = &(__iahtab[iahi]);
+   if (iahp->iah_hcp != NULL || iahp->iah_lp == NULL)
+    __misc_terr(__FILE__, __LINE__);
+   llen = strlen(iahp->iah_lp);
+   __my_free(iahp->iah_lp, llen + 1);
+   __my_free((char *) iahp, sizeof(struct iahist_t));
+   __iahtab[iahi].iah_hcp = NULL;
+   __iahtab[iahi].iah_lp = NULL;
+  } 
+ __iah_lasti = 0;
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * ROUTINES TO IMPLEMENT BREAK POINTS
+ */
+
+/*
+ * : debugger command to stop over current statement
+ * abbreviation for :tibreak [next line] if exists, '.'
+ */
+extern int32 __do_dbg_nextb(void)
+{
+ struct thread_t *thp;
+ struct st_t *stp;
+ struct brkpt_t *bpp;
+ struct task_t *tskp;
+
+ /* need to have started execution to use :nextb */
+ if ((thp = __suspended_thd) == NULL)
+  {  
+   __ia_err(1494,
+    ":nextb impossible exection not started - start with ',' or :step");
+   return(TRUE);
+  }  
+ if ((stp = thp->thnxtstp) == NULL || stp->stnxt == NULL)
+  {
+   __ia_err(1494,
+    ":nextb impossible no next statement - set manual :tbreak");
+   return(TRUE);
+  }
+ if (stp->stnxt->rl_stmttyp == S_REPEAT) stp = stp->stnxt;
+ /* DBG remove --- */
+ if (stp == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */  
+
+ bpp = (struct brkpt_t *) __my_malloc(sizeof(struct brkpt_t));
+ init_brkpt(bpp);
+ bpp->bp_type = BP_INST;
+ bpp->bp_num = __nxt_bpnum++;
+ bpp->bp_stp = stp->stnxt;
+ bpp->bp_itp = thp->th_itp;
+
+ if (__fcspi >= 0) tskp = __fcstk[__fcspi];
+ else if (thp->th_fj) tskp = __find_thrdtsk(thp);
+ else tskp = thp->assoc_tsk;
+ bpp->bp_tskp = tskp;
+ bpp->bp_rm_when_hit = TRUE;
+ insert_brkpt(bpp);
+ return(FALSE);
+}
+
+/*
+ * : debugger command to set a breakpoint that applies to all insts of type
+ */
+extern void __do_dbg_brkpt(int32 is_tmp)
+{
+ int32 ifi, lini, iref;
+ struct brkpt_t *bpp;
+ struct itree_t *in_itp; 
+ struct task_t *in_tskp;
+ struct mod_t *mdp;
+ struct st_t *stp, *stp2;
+ char *sav_chp;
+ char s1[RECLEN], s2[RECLEN];
+ 
+ if (is_tmp) strcpy(s1, ":tbreakpoint"); else strcpy(s1, ":breakpoint");
+ sav_chp = __visp->vichp;
+ __get_vtok(); 
+ if (__toktyp == TEOF)
+  {
+   /* here always use last printed file line type location - know exists */
+   ifi = __list_cur_ifi;
+   if (__list_arg_lini < 1)
+    {
+     __ia_err(1485, "%s no argument form failed - no last list line", s1);
+     return;
+    }
+   lini = __list_arg_lini;
+   if (!fil_lin_toscope(ifi, lini, &in_itp, &in_tskp))
+    {
+     __ia_err(1472,
+      "%s not set at list location %s:%d - outside procedural region of scope",
+      s1, __in_fils[ifi], lini);
+     return;
+    } 
+   iref = FALSE;
+   __visp->vichp = sav_chp; 
+  }
+ else 
+  {
+   __visp->vichp = sav_chp; 
+   if (!parse_scope_ref(&in_itp, &in_tskp, &ifi, &lini, &iref)) return;
+
+   /* must have line number which is first procedural statement of scope */
+   if (ifi == -1) set_scope_loc(in_itp, in_tskp, &ifi, &lini);
+  }
+
+ /* convert to statement, if scope form, line and file will be set to 1st */
+ /* first build the new breakpoint */
+ mdp = in_itp->itip->imsym->el.emdp; 
+ if ((stp = conv_line_tostmt(mdp, in_tskp, ifi, lini)) == NULL)
+  {
+   __ia_err(1473, 
+    "%s reference location %s:%d outside task or initial/always block", s1,
+    __in_fils[ifi], lini); 
+   return;
+  }
+
+ /* can't set stmt breakpoint on delay control must go on action stmt */
+ if (stp->stmttyp == S_DELCTRL) 
+  {
+   stp2 = stp->st.sdc->actionst;
+   if (stp2 == NULL) 
+    {
+     __ia_err(1488,
+      "statement %s only on delay control with action statement", s1);
+     return;
+    }
+   stp = stp2;
+  }
+
+ bpp = (struct brkpt_t *) __my_malloc(sizeof(struct brkpt_t));
+ init_brkpt(bpp);
+ bpp->bp_type = BP_TYPE;
+ bpp->bp_num = __nxt_bpnum++;
+ bpp->bp_stp = stp;
+ bpp->bp_itp = in_itp;
+ bpp->bp_tskp = in_tskp;
+ if (is_tmp) bpp->bp_rm_when_hit = TRUE;
+ insert_brkpt(bpp);
+ 
+ if (bpp->bp_tskp == NULL) strcpy(s1, "");
+ else sprintf(s1, " %s: %s", __to_tsktyp(__xs, bpp->bp_tskp->tsktyp),
+  bpp->bp_tskp->tsksyp->synam); 
+ if (is_tmp) strcpy(s2, " (temp)"); else strcpy(s2, "");
+
+ __cvsim_msg("Breakpoint%s %d set at %s in %s%s\n", s2,
+  bpp->bp_num, __bld_lineloc(__xs, bpp->bp_stp->stfnam_ind,
+  bpp->bp_stp->stlin_cnt), bpp->bp_itp->itip->imsym->synam, s1);
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * set a scope starting line number - for non line number forms
+ * takes itp and tskp inputs, and sets addrs ref_ifi and ref_lini
+ */
+static void set_scope_loc(struct itree_t *itp, struct task_t *tskp, 
+ int32 *ref_ifi, int32 *ref_lini)
+{
+ struct mod_t *mdp;
+
+ if (tskp != NULL)
+  {
+   *ref_ifi = (int32) tskp->tskst->stfnam_ind;
+   *ref_lini = tskp->tskst->stlin_cnt;
+   return;
+  }
+ mdp = itp->itip->imsym->el.emdp; 
+ if (mdp->ialst == NULL)
+  {
+   __ia_err(1484,
+    "scope %s module %s no initial always blocks - no procedural location",
+    __msg2_blditree(__xs, itp), mdp->msym->synam);
+   /* must use first line of scope - probably later another error */
+   *ref_ifi = (int32) itp->itip->imsym->syfnam_ind; 
+   *ref_lini = itp->itip->imsym->sylin_cnt; 
+   return;
+  }
+ *ref_lini = mdp->ialst->ia_first_lini;
+ *ref_ifi = mdp->ialst->ia_first_ifi;
+}
+
+/*
+ * : debugger command to set a breakpoint that applies to all insts of type
+ */
+extern void __do_dbg_ibrkpt(int32 is_tmp)
+{
+ int32 ifi, lini, iref;
+ struct brkpt_t *bpp;
+ struct itree_t *in_itp; 
+ struct task_t *in_tskp;
+ struct mod_t *mdp;
+ struct st_t *stp, *stp2;
+ struct sy_t *syp;
+ char *savchp;
+ char s1[RECLEN];
+
+ if (is_tmp) strcpy(s1, ":tibreakpoint"); else strcpy(s1, ":ibreakpoint");
+ savchp = __visp->vichp;
+ __get_vtok(); 
+ /* case 1: no argument use current list and scope locations */
+ if (__toktyp == TEOF)
+  {
+   /* here if not in scope instance use first instance of scope */
+   ifi = __list_cur_ifi;
+   if (__list_arg_lini < 1)
+    {
+     __ia_err(1485,
+      "%s no argument form failed - no last list line", s1);
+     return;
+    }
+   lini = __list_arg_lini;
+   if (!fil_lin_toscope(ifi, lini, &in_itp, &in_tskp))
+    {
+     __ia_err(1474,
+      "%s set at scope first line - list location %s:%d not in scope", s1,
+      __in_fils[ifi], lini);
+     in_itp = NULL;
+    } 
+   if (in_itp != NULL)
+    {
+     if (in_itp->itip->imsym->el.emdp != __scope_ptr->itip->imsym->el.emdp) 
+      {
+       __ia_err(1476,
+        "%s set at scope first line - list location %s:%d outside current scope",
+         s1, __in_fils[ifi], lini);
+       in_itp = NULL;
+      }
+    }
+   __visp->vichp = savchp; 
+   /* problem with line - use first line of scope */
+   if (in_itp == NULL)
+    {
+     if (__scope_tskp != NULL) syp = __scope_tskp->tsksyp;
+     else syp = __scope_ptr->itip->imsym;
+     ifi = (int32) syp->syfnam_ind;
+     lini = syp->sylin_cnt; 
+     in_itp = __scope_ptr;
+     in_tskp = __scope_tskp;
+    }
+   __visp->vichp = savchp; 
+  }
+ else
+  {
+   /* case 3: scope ref, maybe ,[line ref.] */
+   __visp->vichp = savchp; 
+   __get_vtok();
+   /* :ib ,[line ref] form legal */
+   if (__toktyp == COMMA)
+    {
+     /* notice either need to use scope ptr here or scope from inst */
+     in_itp = __scope_ptr; 
+     in_tskp = __scope_tskp;
+     goto got_comma;  
+    }
+
+   __visp->vichp = savchp;
+   if (!parse_scope_ref(&in_itp, &in_tskp, &ifi, &lini, &iref)) return;
+   if (!iref)
+    {
+     __ia_err(1478,
+      "%s cannot be set - instance reference required", s1);
+     return;
+    }
+   __get_vtok(); 
+got_comma:
+   /* see if optional ,[file]:[line] form present - use for line */ 
+   if (__toktyp == COMMA)
+    { if (!get_ibrk_linref(in_itp, in_tskp, &ifi, &lini)) return; }
+   /* else use first procedural statement line of scope not arg lini */
+   else set_scope_loc(in_itp, in_tskp, &ifi, &lini);
+  }
+ /* convert to statement, if scope form, line and file will be set to 1st */
+ /* first build the new breakpoint */
+ mdp = in_itp->itip->imsym->el.emdp; 
+ if ((stp = conv_line_tostmt(mdp, in_tskp, ifi, lini)) == NULL)
+  {
+   __ia_err(1475, 
+    "%s reference location %s:%d outside task or initial/always block", s1,
+    __in_fils[ifi], lini); 
+   return;
+  }
+ /* can't set stmt breakpoint on delay control must go on action stmt */
+ if (stp->stmttyp == S_DELCTRL) 
+  {
+   stp2 = stp->st.sdc->actionst;
+   if (stp2 == NULL) 
+    {
+     __ia_err(1488,
+      "statement %s only on delay control with action statement", s1);
+     return;
+    }
+   stp = stp2;
+  }
+ 
+ bpp = (struct brkpt_t *) __my_malloc(sizeof(struct brkpt_t));
+ init_brkpt(bpp);
+ bpp->bp_type = BP_INST;
+ bpp->bp_num = __nxt_bpnum++;
+ bpp->bp_stp = stp;
+ bpp->bp_itp = in_itp;
+ bpp->bp_tskp = in_tskp;
+ if (is_tmp) bpp->bp_rm_when_hit = TRUE;
+ insert_brkpt(bpp);
+
+ if (is_tmp) strcpy(s1, " (temp)"); else strcpy(s1, "");
+ __cvsim_msg("Breakpoint%s (inst) %d set at %s in %s\n", s1,
+  bpp->bp_num, __bld_lineloc(__xs, bpp->bp_stp->stfnam_ind,
+  bpp->bp_stp->stlin_cnt), __msg_blditree(__xs, bpp->bp_itp, bpp->bp_tskp));
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * get the [line ref. after , in ibreakpoint
+ * know , read and reads end of [line] or [file]:[line] reference
+ * return F on error
+ */
+static int32 get_ibrk_linref(struct itree_t *itp, struct task_t *tskp,
+ int32 *ifi, int32 *lini) 
+{
+ register char *chp;
+ struct sy_t *syp;
+ struct mod_t *mdp;
+ char *savchp, *endchp;
+ char sref[RECLEN];
+
+ /* return F on error, if not [file]:[line], ifi set to -1 */
+ if (!try_get_fillin_ref(__visp->vichp, ifi, lini, &savchp, &endchp))
+  return(FALSE);
+
+ if (*ifi != -1) __visp->vichp = endchp;
+ else
+  { 
+   /* know not [file]:[line] ref - must be line by itself */
+   strncpy(sref, savchp, endchp - savchp); 
+   sref[endchp - savchp] = '\0';  
+   __visp->vichp = endchp;
+   /* does not have : not [file]:[line] but maybe [line] */
+   if (!isdigit(sref[0]))
+    {
+bad_lin_num:
+     __ia_err(1481, ":ibreakpoint ,[number] expected - %s read", sref);
+     return(FALSE);
+    }
+   for (chp = sref; *chp != '\0'; chp++)
+    { if (!isdigit(*chp)) goto bad_lin_num; } 
+   if (sscanf(sref, "%d", lini) != 1) goto bad_lin_num; 
+   if (tskp != NULL) syp = tskp->tsksyp; else syp = itp->itip->imsym;
+    /* have [line] form - file is first in scope */
+   *ifi = (int32) syp->syfnam_ind;
+  }
+ /* make sure in range */
+ if (tskp != NULL)
+  {
+   if (!scope_lini_inrng(*lini, *ifi, tskp->tsksyp->sylin_cnt,
+    (int32) tskp->tsksyp->syfnam_ind, tskp->tsk_last_lini, tskp->tsk_last_ifi))
+    {
+out_of_rng:
+     __ia_err(1482, ":ibreakpoint %s:%d not before statement in scope %s",
+      __in_fils[*ifi], *lini, __msg_blditree(__xs, itp, tskp));
+     return(FALSE);
+    }
+   return(TRUE);
+  }
+ /* must be in scope with initial/always and before last */
+ mdp = itp->itip->imsym->el.emdp;
+ if (!scope_lini_inrng(*lini, *ifi, mdp->msym->sylin_cnt,
+  (int32) mdp->msym->syfnam_ind, mdp->mod_last_lini, mdp->mod_last_ifi))
+  goto out_of_rng;
+ if (mdp->ialst == NULL) goto out_of_rng;
+ /* if after last - error later */
+ return(TRUE);   
+}
+
+/*
+ * initialize a breakpoint 
+ */
+static void init_brkpt(struct brkpt_t *bpp)
+{
+ bpp->bp_type = BP_UNKN;
+ bpp->bp_can_halt = TRUE;
+ bpp->bp_enable = TRUE;
+ /* unused for now */
+ bpp->bp_prttyp = 0;
+ bpp->bp_dup = FALSE;
+ bpp->bp_rm_when_hit = FALSE;
+ bpp->bp_num = -1;
+ bpp->bp_ignore_cnt = 0;
+ bpp->bp_hit_cnt = 0;
+ bpp->bp_stp = NULL;
+ bpp->bp_itp = NULL;
+ bpp->bp_tskp = NULL;
+ bpp->bp_condx = NULL;
+ bpp->bpnxt = NULL;
+} 
+
+/*
+ * insert the breakpoint with duplicate same loc. flag setting 
+ * this traverses to end of list - know new number is one higher than last
+ */
+static void insert_brkpt(struct brkpt_t *bpp)
+{
+ register struct brkpt_t *bpp2;
+ struct brkpt_t *bpp_last;
+ int32 seen_same_line;
+
+ seen_same_line = FALSE;
+ for (bpp_last = NULL, bpp2 = __bphdr; bpp2 != NULL; bpp2 = bpp2->bpnxt) 
+  {
+   /* set dup if same line number seen */
+   if (bpp->bp_stp->stfnam_ind == bpp2->bp_stp->stfnam_ind
+    && bpp->bp_stp->stlin_cnt == bpp2->bp_stp->stlin_cnt)
+    {
+     if (!seen_same_line)
+      {
+       __cvsim_msg("Note: other statement breakpoint(s) set at %s\n",
+        __bld_lineloc(__xs, bpp->bp_stp->stfnam_ind, bpp->bp_stp->stlin_cnt));
+       seen_same_line = TRUE;
+      }
+     bpp2->bp_dup = bpp->bp_dup = TRUE;
+    }
+   bpp_last = bpp2;
+  }
+ /* insert on end - bpp last is recomputed tmp */ 
+ if (__bphdr == NULL) __bphdr = bpp;
+ else
+  {
+   /* SJM 08/02/01 - add if to keep lint happy */
+   if (bpp_last != NULL) bpp_last->bpnxt = bpp;
+  }
+ /* finally arm breakpoint */
+ if (!bpp->bp_dup) 
+  {
+   /* DBG - remove */
+   if (bpp->bp_stp->stmttyp == S_BRKPT) __misc_terr(__FILE__, __LINE__);
+   bpp->bp_stp->stmttyp = S_BRKPT;
+  }
+}
+
+/*
+ * routine to find statement given ifi and lini 
+ * returns NULL on error
+ * if not [file]:[line] - know will match first line if any exists
+ * finds first statement after line - error if not found in scope
+ * tricky because scope can extend across multiple files
+ */
+static struct st_t *conv_line_tostmt(struct mod_t *in_mdp,
+ struct task_t *in_tskp, int32 ifi, int32 lini)
+{
+ register struct ialst_t *ialp; 
+ struct st_t *stp, *stp2;
+ struct incloc_t *ilp;
+ int32 st_ifi, st_lini, ifi2, lini2;
+
+ /* if in included file, must use line included form in range tests */ 
+ if ((ilp = find2_incloc(ifi)) != NULL) 
+  { ifi2 = ilp->incfrom_fnind; lini2 = ilp->incfrom_lcnt; }
+ else { ifi2 = ifi; lini2 = lini; } 
+
+ /* if task, know will have statements and use last if after */
+ if (in_tskp != NULL)
+  {
+   stp = in_tskp->tskst; 
+   /* know will always be at least an NONE - ; by itself */
+   if (stp == NULL) __misc_terr(__FILE__, __LINE__);
+   st_ifi = (int32) stp->stfnam_ind;
+   st_lini = stp->stlin_cnt;
+   /* if location in task and before first statement - use first statement */
+   if (ifi2 <= st_ifi && lini2 <= st_lini) return(stp);
+
+   /* here must use included file/line */
+   if ((stp2 = find_lstofsts_stp(stp, ifi, lini)) != NULL) return(stp2);
+   /* since know in task and not before any statement - must be after last */
+   /* change to last */
+   /* if after last - not found since know in scope becomes last */
+   return(__blklast_stp);
+  }
+ /* in module, look through ia blocks - must be from 1st to last statement */ 
+ /* after 1st part of last statement to end will be error not last stmt */
+ for (ialp = in_mdp->ialst; ialp != NULL; ialp = ialp->ialnxt)
+  {
+   stp = ialp->iastp;
+   /* if location before, begin of initial/always skip */
+   if (ifi2 < ialp->ia_first_ifi || (ifi2 == ialp->ia_first_ifi
+    && lini2 < ialp->ia_first_lini)) continue;
+   /* if location after, end of initial/always skip */
+   if (ifi2 > (int32) ialp->ia_last_ifi || (ifi2 == ialp->ia_last_ifi
+    && lini2 > ialp->ia_last_lini)) continue;
+
+   /* here must match include line */
+   if ((stp2 = find_lstofsts_stp(stp, ifi, lini)) != NULL) return(stp2);
+   /* if after last in init/always, just use last - know muat be there */
+   return(__blklast_stp);
+  }
+ return(NULL);
+}
+
+/*
+ * for searching source file, find next statement
+ * passed last statement which know line number after (also file)
+ * and before or equal to next statement (stnxt) if there is one 
+ *
+ * return match or NULL if at last
+ * know line after last_stp and before next statement
+ * look inside statement if possible
+ */
+static struct st_t *find_nxtstp(struct st_t *last_stp, int32 ifi, int32 lini)
+{
+ int32 fji;
+ byte styp; 
+ int32 st_ifi, st_lini, has_else;
+ struct st_t *tmpstp, *stp2, *fjstp;
+ struct task_t *tskp;
+ 
+again:
+ styp = (byte) last_stp->stmttyp;
+brk_again:
+ switch (styp) {
+  case S_IF:
+   /* know after if ( ) and before next stmtm */
+   /* if no else, only look in if */
+   if (last_stp->st.sif.elsest == NULL)
+    {
+     has_else = FALSE;
+try_then:
+     if ((tmpstp = find_lstofsts_stp(last_stp->st.sif.thenst, ifi, lini))
+      != NULL) return(tmpstp);
+     if (has_else) return(last_stp->st.sif.elsest);
+     break;
+    }
+   /* has else */
+   tmpstp = last_stp->st.sif.elsest;
+   st_ifi = (int32) tmpstp->stfnam_ind;
+   st_lini = (int32) tmpstp->stlin_cnt;
+   /* if match else statement, return it */
+   if (ifi == st_ifi && lini == st_lini) return(tmpstp);
+   if (ifi < st_ifi || (ifi == st_ifi && lini < st_lini))
+    { has_else = TRUE; goto try_then; }
+   /* can only in else or next statement */
+   return(find_lstofsts_stp(last_stp->st.sif.elsest, ifi, lini));
+  case S_FOR:
+   return(find_lstofsts_stp(last_stp->st.sfor->forbody, ifi, lini));
+  case S_FOREVER: case S_WHILE:
+   return(find_lstofsts_stp(last_stp->st.swh.lpst, ifi, lini));
+  case S_REPEAT:
+   return(find_lstofsts_stp(last_stp->st.srpt.repst, ifi, lini));
+  case S_WAIT:
+   return(find_lstofsts_stp(last_stp->st.swait.lpst, ifi, lini));
+
+  /* lists that need to be searched */
+  case S_CASE:
+   /* tricky since default can be anywhere - must find defl. insert loc */ 
+   return(find_case_stp(last_stp, ifi, lini));
+  case S_DELCTRL:
+   /* know does not match location of # or @ <something> */
+   /* if no action statement, done */
+   if ((tmpstp = last_stp->st.sdc->actionst) == NULL) break;
+   return(find_lstofsts_stp(tmpstp, ifi, lini));
+  case S_NAMBLK:
+   /* see if in name block, handles any where between begin and end */ 
+   /* if inside name block must succeed */
+   tskp = last_stp->st.snbtsk;
+   if (scope_lini_inrng(lini, ifi, tskp->tsksyp->sylin_cnt,
+    (int32) tskp->tsksyp->syfnam_ind, tskp->tsk_last_lini, tskp->tsk_last_ifi))
+    {
+     tmpstp = tskp->tskst; 
+     /* if location in task and before first sttt - use first statement */
+     if (ifi <= (int32) tmpstp->stfnam_ind && lini <= tmpstp->stlin_cnt)
+      return(tmpstp);
+
+     /* this will set last if past last in block statement */
+     if ((stp2 = find_lstofsts_stp(tmpstp, ifi, lini)) != NULL) return(stp2);
+     return(__blklast_stp);
+    }
+   break;
+  case S_UNBLK:
+   /* know after begin */
+   return(find_lstofsts_stp(last_stp->st.sbsts, ifi, lini));
+  case S_UNFJ:
+   /* know after fork */
+   for (fji = 0;; fji++)
+    {
+     if ((fjstp = last_stp->st.fj.fjstps[fji]) == NULL) break;
+
+     /* if find, done */
+     if ((tmpstp = find_lstofsts_stp(fjstp, ifi, lini)) != NULL)
+      return(tmpstp);
+    }
+   /* know after last - matches next one up */
+   break;
+  /* special simulation control statements */
+  case S_REPSETUP:
+   /* this must be invisible - has same line as next stmt */
+   last_stp = last_stp->stnxt;
+   goto again;
+  case S_REPDCSETUP:
+   /* this must be invisible - has same line as next stmt */
+   last_stp = last_stp->stnxt;
+   goto again;
+  case S_GOTO:
+   /* here there will never be a next */
+   if (last_stp->stnxt != NULL) __misc_terr(__FILE__, __LINE__);
+   break; 
+  case S_BRKPT:
+   styp = (byte) last_stp->rl_stmttyp;
+   goto brk_again;
+  default: break;
+ }
+ return(NULL);
+}
+
+/*
+ * find next statement in list 
+ * can be before first in which case return first, if after last, return nil
+ */
+static struct st_t *find_lstofsts_stp(struct st_t *hdrstp, int32 ifi, int32 lini)
+{
+ register struct st_t *stp; 
+ int32 st_ifi, st_lini, ifi2, lini2; 
+ struct st_t *stp2;
+ struct incloc_t *ilp;
+
+ for (__blklast_stp = NULL, stp = hdrstp; stp != NULL; stp = stp->stnxt)
+  {
+   /* know does not match header */
+   st_ifi = (int32) stp->stfnam_ind;
+   st_lini = (int32) stp->stlin_cnt;
+   /* if line and statement in same file use if before or at */ 
+   if (ifi == st_ifi && lini <= st_lini) return(stp);
+
+   /* if next statement is inside include use it if before include point */
+   /* notice if includes nested must find include line in current file */
+   /* which may be included itself */
+   if ((ilp = find3_incloc(st_ifi, ifi)) != NULL) 
+    { 
+     ifi2 = ilp->incfrom_fnind;
+     lini2 = ilp->incfrom_lcnt;
+     /* if before or at include use first statement of include */
+     if (ifi < ifi2 || (ifi == ifi2 && lini <= lini2)) return(stp);
+    }
+   else 
+    {
+     /* normal rule: if before or at next loop statement return it */
+     if (ifi < st_ifi || (ifi == st_ifi && lini <= st_lini)) return(stp);
+    }
+   /* this statement may be block or other complicated */
+   if ((stp2 = find_nxtstp(stp, ifi, lini)) != NULL) return(stp2);
+   /* after current and any substatement structure */
+   __blklast_stp = stp;
+  }
+ /* after block - will probably be at next statement */ 
+ return(NULL);
+}
+
+/*
+ * find incloc that is non included file
+ * for multiply included this returns location of outermost or caller if
+ * caller is itself an included file 
+ */
+static struct incloc_t *find3_incloc(int32 ifi, int32 call_ifi)
+{
+ struct incloc_t *ilp, *ilp2; 
+
+ if ((ilp2 = find_incloc(ifi)) == NULL) return(NULL);
+ /* know included trace outward until finding one not included and */
+ /* return that ilp */
+ for (;;)
+  {
+   ifi = ilp2->incfrom_fnind;
+   if (ifi == call_ifi) return(ilp2);
+   ilp = ilp2;
+   if ((ilp2 = find_incloc(ifi)) == NULL) break;
+  }
+ return(ilp);
+}
+
+/*
+ * find statement inside (or after case)
+ * know after case header and can have default case somwwhere
+ * each case statement or default can be list (begin elided)
+ */
+static struct st_t *find_case_stp(struct st_t *last_stp, int32 ifi, int32 lini)
+{
+ register struct csitem_t *csip;
+ struct st_t *stp, *tmpstp, *stp_after_dflt;
+ struct csitem_t *dflt_csip; 
+
+ dflt_csip = last_stp->st.scs.csitems;
+ if (dflt_csip->csist != NULL) stp_after_dflt = find_afterdflt(dflt_csip);
+ else stp_after_dflt = NULL;
+ for (csip = dflt_csip->csinxt; csip != NULL; csip = csip->csinxt)
+  {
+   stp = csip->csist;
+   
+   /* if this case statement list after default, see if in default range */
+   /* only T if has default, i.e. no stp non nil so will never match */
+   if (stp_after_dflt == stp)
+    {
+     if ((tmpstp = find_lstofsts_stp(dflt_csip->csist, ifi, lini)) != NULL)
+      return(tmpstp);
+     /* if after default end, look at next case */
+    }
+   /* see if in this case range */
+   if ((tmpstp = find_lstofsts_stp(stp, ifi, lini)) != NULL) return(tmpstp);
+  }
+ /* this will move up stack to connect ending stnxt to next exec. place */
+ if (dflt_csip->csist != NULL && stp_after_dflt == NULL)
+  return(find_lstofsts_stp(dflt_csip->csist, ifi, lini));
+ return(NULL);
+}
+
+/*
+ * find case statement immediately after default 
+ * only called if has default
+ * returns nil on common default at end case
+ */
+static struct st_t *find_afterdflt(struct csitem_t *dflt_csip)
+{
+ register struct csitem_t *csip;
+ int32 st_ifi, st_lini, dflt_ifi, dflt_lini;
+ struct st_t *dfltstp, *stp;
+
+ dfltstp = dflt_csip->csist;
+ dflt_ifi = (int32) dfltstp->stfnam_ind;
+ dflt_lini = dfltstp->stlin_cnt;
+ 
+ /* key is that know all case items except default in source order */
+ /* also one after default is always first in source order */
+ for (csip = dflt_csip->csinxt; csip != NULL; csip = csip->csinxt)
+  {
+   stp = csip->csist;
+   st_ifi = (int32) stp->stfnam_ind;
+   st_lini = stp->stlin_cnt;
+   if (st_ifi > dflt_ifi || (st_ifi == dflt_ifi && st_lini >= dflt_lini))
+    return(stp);
+  }
+ return(NULL);
+}
+
+#define TYP_BRKPTS 0
+#define TYP_DISP 1
+
+/* info command options table */
+static struct namlst_t dtyparg[] = {
+ { TYP_BRKPTS, "breakpoints" },
+ { TYP_DISP, "displays" } 
+};
+#define NTYPARGS (sizeof(dtyparg) / sizeof(struct namlst_t))
+
+/*
+ * : debugger breakpint32 delete command
+ */
+extern void __do_dbg_delbrkdis(void)
+{
+ int32 bpnum, deltyp;
+
+ __get_vtok();
+ if (__toktyp == ID)
+  { deltyp = __get_dbcmdnum(__token, dtyparg, NTYPARGS); __get_vtok(); }
+ else deltyp = TYP_BRKPTS;
+
+ if (deltyp == TYP_BRKPTS)
+  {
+   if (__toktyp == TEOF) del_all_brkpts();
+   else
+    {
+     if ((bpnum = __get_dbg_val()) == -1 || bpnum < 1)
+      {
+       __ia_err(1471, "breakpoint number %s illegal - can not delete",
+        __prt_vtok());
+       return;
+      } 
+     del_brkpt_num(bpnum);
+     __chk_extra_atend(TRUE);
+    }
+  }
+ else
+  {
+   if (__toktyp == TEOF) del_all_disps();
+   else { del_disp_num(); __chk_extra_atend(TRUE); }
+  }
+}
+
+/*
+ * delete all breakpoints 
+ */
+static void del_all_brkpts(void)
+{
+ register struct brkpt_t *bpp, *bpp2;
+ char s1[RECLEN];
+
+ if (__bphdr == NULL)
+  { __ia_err(1466, "no breakpoints to delete"); return; }
+ __cvsim2_msg("Delete all breakpoints? (y/n) ");
+ /* FIXME - how read input from vendor 1 side */
+ if (fgets(s1, RECLEN, stdin) == NULL || (s1[0] != 'y' && s1[0] != 'Y'))
+  return;
+ for (bpp = __bphdr; bpp != NULL;)
+  {
+   bpp2 = bpp->bpnxt;
+   /* if triggered, untrigger */
+   if (bpp->bp_stp->stmttyp == S_BRKPT)
+    bpp->bp_stp->stmttyp = bpp->bp_stp->rl_stmttyp; 
+   __my_free((char *) bpp, sizeof(struct brkpt_t));  
+   bpp = bpp2;
+  }
+ __bphdr = NULL;
+}
+
+/*
+ * delete break in globals tok typ and token
+ */
+static void del_brkpt_num(int32 bpnum)
+{
+ register struct brkpt_t *bpp;
+ struct brkpt_t *last_bpp, *bpp2;
+ int32 bpcnt;
+
+ /* delete break numbered bpnum */
+ for (last_bpp = NULL, bpp = __bphdr; bpp != NULL; bpp = bpp->bpnxt)
+  {
+   if (bpp->bp_num == bpnum)
+    {
+     if (last_bpp == NULL) __bphdr = bpp->bpnxt; 
+     else last_bpp->bpnxt = bpp->bpnxt;
+
+     /* for temporary break points reuse number if last */
+     if (bpp->bp_rm_when_hit)
+      { if (bpp->bp_num == __nxt_bpnum - 1) __nxt_bpnum--; } 
+
+     /* notice by here one to delete removed from list */
+     bpcnt = cnt_same_brkpts((int32) bpp->bp_stp->stfnam_ind,
+      bpp->bp_stp->stlin_cnt, &bpp2);
+     /* if no more at this location and triggered, untrigger */
+     if (bpcnt == 0 && bpp->bp_stp->stmttyp == S_BRKPT)
+      bpp->bp_stp->stmttyp = bpp->bp_stp->rl_stmttyp; 
+     /* if only one left at location unset the dup flag */ 
+     if (bpcnt == 1) bpp2->bp_dup = FALSE;
+     /* final step is to free the bp */
+     __my_free((char *) bpp, sizeof(struct brkpt_t)); 
+     return;
+    }
+   last_bpp = bpp;
+  }
+ __ia_err(1471, "no breakpoint number %d", bpnum);
+}
+
+/*
+ * count number of breakpoints at same location
+ */
+static int32 cnt_same_brkpts(int32 ifi, int32 lini, struct brkpt_t **last_bpp)
+{
+ int32 cnt;
+ register struct brkpt_t *bpp;
+ 
+ cnt = 0;
+ *last_bpp = NULL;
+ for (bpp = __bphdr; bpp != NULL; bpp = bpp->bpnxt) 
+  {
+   if (ifi == (int32) bpp->bp_stp->stfnam_ind && lini == bpp->bp_stp->stlin_cnt)
+    {
+     cnt++;
+     *last_bpp = bpp;
+    }
+  }
+ return(cnt);
+}
+
+/*
+ * undisplay breakpoints - same as delete display [optional number]  
+ */
+extern void __dbg_undisplay(void)
+{
+ __get_vtok();
+ if (__toktyp == TEOF) del_all_disps();
+ else { del_disp_num(); __chk_extra_atend(TRUE); }
+}
+
+/*
+ * delete all auto-display points 
+ */
+static void del_all_disps(void)
+{
+ register struct dispx_t *dxp, *dxp2;
+ char s1[RECLEN];
+
+ if (__dispxhdr == NULL)
+  { __ia_err(1466, "no displays to delete"); return; }
+ __cvsim2_msg("Delete all displays? (y/n) ");
+ if (fgets(s1, RECLEN, stdin) == NULL || (s1[0] != 'y' && s1[0] != 'Y'))
+  return;
+ for (dxp = __dispxhdr; dxp != NULL;)
+  {
+   dxp2 = dxp->dsp_nxt;
+   __my_free((char *) dxp, sizeof(struct dispx_t));  
+   dxp = dxp2;
+  }
+ __dispxhdr = NULL;
+}
+
+/*
+ * delelete a display by number from tok typ and token 
+ * know token read before calling this
+ */
+static void del_disp_num(void)
+{
+ register struct dispx_t *dxp;
+ struct dispx_t *last_dxp;
+ int32 disnum;
+
+ if ((disnum = __get_dbg_val()) == -1 || disnum < 1)
+  {
+   __ia_err(1471, "auto-display number %s illegal - can not delete",
+    __prt_vtok());
+   return;
+  } 
+ /* delete auto-display numbered disnum */
+ for (last_dxp = NULL, dxp = __dispxhdr; dxp != NULL; dxp = dxp->dsp_nxt)
+  {
+   if (dxp->dsp_num == disnum)
+    {
+     if (last_dxp == NULL) __dispxhdr = dxp->dsp_nxt; 
+     else last_dxp->dsp_nxt = dxp->dsp_nxt;
+
+     /* final step is to free the bp */
+     __my_free((char *) dxp, sizeof(struct dispx_t)); 
+     return;
+    }
+   last_dxp = dxp;
+  }
+ __ia_err(1471, "no auto-display number %d", disnum);
+}
+
+/*
+ * disable or enable a breakpoint or display
+ */
+extern void __do_dbg_dis_enable(int32 do_enable)
+{
+ register struct brkpt_t *bpp;
+ register struct dispx_t *dxp;
+ int32 denum, disentyp;
+ char s1[RECLEN];
+
+ if (do_enable) strcpy(s1, "enable"); else strcpy(s1, "disable");
+ __get_vtok();
+ if (__toktyp == ID)
+  {
+   disentyp = __get_dbcmdnum(__token, dtyparg, NTYPARGS);
+   __get_vtok();
+  }
+ else disentyp = TYP_BRKPTS;
+
+ if (disentyp == TYP_BRKPTS)
+  {
+   if (__toktyp == TEOF) denum = -2; 
+   else
+    {
+     if ((denum = __get_dbg_val()) == -1 || denum < 1)
+      {
+       __ia_err(1477, ":%s expected breakpoint number %s illegal", s1,
+        __prt_vtok());
+       return;
+      }
+    }
+   /* delete break numbered bpnum */
+   for (bpp = __bphdr; bpp != NULL; bpp = bpp->bpnxt)
+    {
+     if (denum == -2 || bpp->bp_num == denum)
+      {
+       bpp->bp_enable = (do_enable) ? TRUE : FALSE;
+       if (denum != -2) goto done;
+      }
+    }
+   if (denum == -2) goto done; 
+   __ia_err(1479, ":%s breakpoint failed - no breakpoint number %d",
+     s1, denum); 
+   return;
+  }
+ /* display case */
+ if (__toktyp == TEOF) denum = -2; 
+ else
+  {
+   if ((denum = __get_dbg_val()) == -1 || denum < 1)
+    {
+     __ia_err(1477, ":%s expected auto-display number %s illegal", s1,
+      __prt_vtok());
+     return;
+    }
+  }
+ /* delete break numbered bpnum */
+ for (dxp = __dispxhdr; dxp != NULL; dxp = dxp->dsp_nxt)
+  {
+   if (denum == -2 || dxp->dsp_num == denum)
+    {
+     dxp->dsp_enable = (do_enable) ? TRUE : FALSE;
+     if (denum != -2) goto done;
+    }
+  }
+ if (denum == -2) goto done;
+ __ia_err(1479, ":%s displays failed - no auto-display number %d",
+  s1, denum); 
+ return;
+
+done:
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * set ignore count for a break point (add to current hit count)
+ *
+ * :cond [bp num] [ingore count]
+ * ignore next count breakpoints before breaking
+ */
+extern void __dbg_brk_ignore(void)
+{
+ int32 icnt;
+ struct brkpt_t *bpp;
+
+ __get_vtok();
+ if ((bpp = rd_brkpt_num(":ignore", 1)) == NULL) return; 
+ __get_vtok();
+ if (__toktyp == TEOF)
+  {
+   __ia_err(1491,
+    ":ignore second argument (number of hits to ignore) missing");
+   return;
+  }
+ if ((icnt = __get_dbg_val()) == -1 || icnt < 0)
+  { 
+   __ia_err(1492,
+    ":ignore second argument (number of hits to ignore) illegal - %s read",
+    __prt_vtok());
+   return;
+  }
+
+ /* ignore count value in brk pt record is number from current hit number */  
+ /* count is number to ignore so 0 is next, 1 is skip 1, and stop on next */ 
+ /* and so on */
+ bpp->bp_ignore_cnt = bpp->bp_hit_cnt + icnt;  
+ if (icnt == 0)
+  __cvsim_msg("Stopping next time breakpoint %d is reached.\n", bpp->bp_num);
+ else __cvsim_msg("Ignoring next %d crossings of breakpoint %d.\n", icnt,
+  bpp->bp_num);
+}
+
+/*
+ * read a break point number argument and return break point record
+ * returns nil on error
+ * expects number token to have been read and reads no more
+ */
+static struct brkpt_t *rd_brkpt_num(char *cmdnam, int32 argnum)
+{
+ int32 bpnum;
+ struct brkpt_t *bpp;
+
+ if (__toktyp == TEOF)
+  {
+   __ia_err(1491,
+    "%s argument number %d (break point number) missing", cmdnam, argnum);
+   return(NULL);
+  }
+ if ((bpnum = __get_dbg_val()) == -1)
+  { 
+   __ia_err(1492, "%s argument number %d break point number %s illegal",
+    cmdnam, argnum, __prt_vtok());
+   return(NULL);
+  }
+ if ((bpp = find_bpp(bpnum)) == NULL) 
+  {
+   __ia_err(1493,
+    "there is no break point number %d (argument %d)", bpnum, argnum);
+   return(NULL);
+  }
+ return(bpp);
+}
+
+/*
+ * set up condition filter expresson for break point
+ : :cond [bp num] [cond expr]
+ */
+extern void __dbg_brk_cond(void)
+{
+ struct itree_t *sav_scope_ptr;
+ struct task_t *sav_scope_tskp;
+ struct expr_t *xp;
+ struct brkpt_t *bpp;
+
+ __get_vtok();
+ if ((bpp = rd_brkpt_num(":cond", 1)) == NULL) return;
+
+ /* if collect returns nil, know error emitted in routine */
+ __get_vtok();
+ /* ":cond [number]" turns off condition */
+ if (__toktyp == TEOF)
+  {
+   __cvsim_msg("Breakpoint %d now unconditional.\n", bpp->bp_num);
+   xp = NULL;
+  }
+ else
+  {
+   sav_scope_ptr = __scope_ptr;
+   sav_scope_tskp = __scope_tskp;
+   __scope_ptr = bpp->bp_itp;
+   __scope_tskp = bpp->bp_tskp; 
+   __push_itstk(__scope_ptr);
+   xp = __rd_iact_expr();
+   __pop_itstk();
+   __scope_ptr = sav_scope_ptr;
+   __scope_tskp = sav_scope_tskp; 
+   if (xp == NULL) return;
+  }
+ bpp->bp_condx = xp;
+ __chk_extra_atend(TRUE);
+}
+
+/*
+ * find a break point given its number 
+ */
+static struct brkpt_t *find_bpp(int32 bpnum)
+{
+ register struct brkpt_t *bpp;
+
+ for (bpp = __bphdr; bpp != NULL; bpp = bpp->bpnxt)
+  { if (bpp->bp_num == bpnum) return(bpp); }
+ return(NULL);
+}
+
+/*
+ * process a breakpoint
+ *
+ * called from v_ex using exec itree loc.
+ * tricky because possibly multiple breaks at one statement
+ * if returns FALSE, does not enter iact and execs and reenables stmt brk
+ * whenever statement with break execed, rearms but setting type to S BRK 
+ *
+ * complicated breakpoint logic - every hit stmt breakpoint must change to
+ * can not halt so will be execed 
+ */
+extern int32 __process_brkpt(struct st_t *stp)
+{
+ register struct brkpt_t *bpp;
+ int32 stop_from_dup;
+ struct brkpt_t *brk_bpp, *bpp2, *first_hitbpp;
+
+ /* always find first in list */
+ brk_bpp = NULL;
+ first_hitbpp = NULL;
+ for (bpp = __bphdr; bpp != NULL; bpp = bpp->bpnxt)
+  { if (bpp->bp_stp == stp) goto found_stmt_match; }
+ /* if have statement with type breakpoint must be in table */ 
+ __arg_terr(__FILE__, __LINE__);
+
+found_stmt_match:
+ brk_bpp = bpp;
+ /* if any on same line in not can halt state all are, cont from break, */
+ /* scheme is once exec of SBRK stmt, turn off can halt so next time */
+ /* stmt execed not S BRK */
+ if (!brk_bpp->bp_can_halt)
+  {
+   /* rearm (all on line if needed) and return F - will exec stmt. */
+   /* notice brk_bpp is first on stmt */
+   if (brk_bpp->bp_dup)
+    {
+     for (bpp = brk_bpp; bpp != NULL; bpp = bpp->bpnxt)
+      { if (bpp->bp_stp == stp) bpp->bp_can_halt = TRUE; }
+    }
+   else brk_bpp->bp_can_halt = TRUE;
+   /* now all breakpoints at statement armed and will exec statement */
+   return(FALSE);
+  } 
+
+ /* found breakpoints on line - see if filters eliminate stop */
+ if (!brk_bpp->bp_dup)
+  {
+   if (elim_brkpt_fromcond(brk_bpp))
+    {
+     /* make sure stmt gets execed next time it is execed */
+     /* when hit stmt does not get advanced, go thru here first */
+     brk_bpp->bp_can_halt = TRUE;
+     return(FALSE);
+    }
+   first_hitbpp = brk_bpp;
+  }  
+ else
+  {
+   stop_from_dup = FALSE;
+   for (bpp = brk_bpp; bpp != NULL; bpp = bpp->bpnxt)
+    {
+     if (bpp->bp_stp != stp) continue;
+     /* if find any that stop, must stop */ 
+     if (!elim_brkpt_fromcond(bpp))
+      {
+       stop_from_dup = TRUE;
+       if (first_hitbpp == NULL) first_hitbpp = bpp;
+      }
+    }
+   if (!stop_from_dup)
+    {
+     /* all are filtered out, no stop */
+     for (bpp = brk_bpp; bpp != NULL; bpp = bpp->bpnxt)
+      { if (bpp->bp_stp == stp) bpp->bp_can_halt = TRUE; }
+     return(FALSE);
+    }
+  }
+
+ /* mark all as cannot stop for next exec and inc count on all */
+ if (!brk_bpp->bp_dup) brk_bpp->bp_can_halt = FALSE;
+ else
+  {
+   for (bpp = brk_bpp; bpp != NULL; bpp = bpp->bpnxt)
+    { if (bpp->bp_stp != stp) continue; bpp->bp_can_halt = FALSE; }
+  }
+ /* need to indicate at this line in case step since have hit this line */
+ __step_lini = stp->stlin_cnt;
+ __step_ifi = (int32) stp->stfnam_ind;
+
+ /* hit breakpoint - write message and setup suspend into interactive dbger */
+ __cvsim_msg("\nBreakpoint %d scope %s", first_hitbpp->bp_num,
+  __msg_blditree(__xs, __inst_ptr, first_hitbpp->bp_tskp)); 
+ __cvsim_msg(" (%s line %d)", __in_fils[stp->stfnam_ind], stp->stlin_cnt);
+ if (__last_brktime != __simtime)
+  {
+   __cvsim_msg(" time %s\n", __to_timstr(__xs, &__simtime));
+   __last_brktime = __simtime;
+  }
+ else __cvsim_msg("\n");
+ __prt_src_lines((int32) stp->stfnam_ind, stp->stlin_cnt, stp->stlin_cnt);
+
+ /* remove all temp (t) breaks at this statement */
+ /* know break always put on first statement of line */
+ if (brk_bpp->bp_dup)
+  {
+   for (bpp = brk_bpp; bpp != NULL;)
+    {
+     bpp2 = bpp->bpnxt;
+     if (bpp->bp_stp == stp)
+      { if (bpp->bp_rm_when_hit) del_brkpt_num(bpp->bp_num); }
+     bpp = bpp2;
+    }
+  }
+ else { if (brk_bpp->bp_rm_when_hit) del_brkpt_num(brk_bpp->bp_num); }
+
+ /* must not suspend thread here since when hit enter iact test will */
+ /* supsend, suspend on entry needed in case ^c entry to interact */
+ /* even if interrupt (^c) received, doing again does not hurt */
+ signal(SIGINT, SIG_IGN);
+
+ __pending_enter_iact = TRUE;
+ __iact_reason = IAER_BRKPT;  
+ return(TRUE);
+}
+
+/*
+ * process all conditions that disable stopping from a break point
+ * returns T if break point eliminated (i.e. not stopped at)
+ * F => break hit need to enter iact mode
+ */
+static int32 elim_brkpt_fromcond(struct brkpt_t *bpp)
+{
+ struct xstk_t *xsp;
+ word32 tmp;
+
+ /* handle all not dup cases */
+ if (!bpp->bp_enable || (bpp->bp_type == BP_INST
+   && bpp->bp_itp != __inst_ptr)) return(TRUE);
+
+ /* evaluate conditional expression if present */
+ if (bpp->bp_condx != NULL)
+  {
+   __push_itstk(bpp->bp_itp);
+   xsp = __eval_xpr(bpp->bp_condx);
+   /* normal loop T condition, if any bit 1, then T (non zero) */
+   if (xsp->xslen <= WBITS)
+    {
+     /* SJM 07/20/00 - must convert to real if real */
+     if (bpp->bp_condx->is_real)
+      {
+       double d1;
+
+       memcpy(&d1, xsp->ap, sizeof(double));
+       tmp = (d1 != 0.0);
+      }
+     else tmp = ((xsp->ap[0] & ~xsp->bp[0]) != 0L);
+    } 
+   else tmp = (__cvt_lngbool(xsp->ap, xsp->bp, wlen_(xsp->xslen)) == 1);
+   __pop_xstk();
+   __pop_itstk();
+   /* non 1 (F) so routine returns T to cancel */
+   if (!tmp) return(TRUE);
+  }
+ /* must always increment hit count before checking ignore count */
+ /* otherwide will never advance to ignore count */
+ (bpp->bp_hit_cnt)++;
+  
+ /* being ignored because not yet hit enough times */
+ /* if hit is 0, and ignore is 1, 1st time here will both be 1 */
+ /* so not hit, 2nd time hit will be 2, so hit */ 
+ /* DBG remove ---
+ __dbg_msg("=== hit count for break %d is %d and ignore count is %d ===\n",
+  bpp->bp_num, bpp->bp_hit_cnt, bpp->bp_ignore_cnt);
+ --- */
+
+ if (bpp->bp_hit_cnt <= bpp->bp_ignore_cnt) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * ROUTINES TO RESET STATE TO START OF SIM 
+ */
+
+/*
+ * reset simulation back to time 0
+ * LOOKATME - could just save after initializing values then just reload
+ */
+extern void __reset_to_time0(void)
+{
+ register int32 i;
+ register struct thread_t *thp;
+ char *chp;
+ struct telhdr_t *telp;
+ struct thread_t *thp2;
+ struct fmonlst_t *fmonp, *fmonp2;
+ struct dceauxlst_t *dclp;
+ struct mdvmast_t *mdvp, *mdvp2;
+ struct dvchgnets_t *dvchgp, *dvchg_last;
+ struct hctrl_t *hcp, *hcp2;
+ struct strblst_t *strbp;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+ struct brkpt_t *bpp;
+
+ /* --- debug remove --
+ -* if (__debug_flg) __dmp_tskthrds(); *-
+ if (__debug_flg) __dmp_all_thrds();
+ --- */
+
+ /* free the procedural threads and subthreads */
+ /* this mark events so must be done first */
+ /* know here thread always top level */
+ for (thp = __initalw_thrd_hdr; thp != NULL;)
+  { 
+   thp2 = thp->thright;
+   /* free thp and all underneath */ 
+   if (thp->thofs != NULL) __free_thd_list(thp->thofs);
+   thp->th_ialw = FALSE;
+   __free_1thd(thp);
+   thp = thp2;
+  }
+ __initalw_thrd_hdr = NULL;
+ /* disable all active interactive statements */
+ for (hcp = __hctrl_hd; hcp != NULL;)
+  {
+   hcp2 = hcp->hc_nxt;
+   /* unlink interactive leaving hcp since can just free element without */
+   /* unlinking */
+   __do_iact_disable(hcp, TRUE);
+   __my_free((char *) hcp, sizeof(struct hctrl_t));
+   hcp = hcp2;
+  }
+ /* DBG remove - check to make sure all tasks freed */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if (tskp->tsktyp == FUNCTION) 
+      {
+       if (tskp->tthrds != NULL) __misc_terr(__FILE__, __LINE__);
+       continue;
+      }
+     for (i = 0; i < mdp->flatinum; i++) 
+      { if (tskp->tthrds[i] != NULL) __misc_terr(__FILE__, __LINE__); }
+    }
+  }
+ /* --- */
+
+ __hctrl_hd = __hctrl_end = NULL;
+ /* any breakpoints halted but not yet continued from reset, reenable */
+ /* when breakpoint counts added, will reset here */
+ for (bpp = __bphdr; bpp != NULL; bpp = bpp->bpnxt) 
+  {
+   bpp->bp_can_halt = TRUE;
+   bpp->bp_ignore_cnt = 0; 
+  }
+
+ /* free timing wheel and overflow queue - __twhsize index el fence left */
+ /* this is needed because need to free guts of events and need to leave */
+ /* tevtab action cb elements */ 
+ for (i = 0; i < __twhsize; i++)
+  { telp = __twheel[i]; __free_telhdr_tevs(telp); }
+
+ /* after here overflow q empty, ready to be rebuilt - events freed elsewhere */
+ if (__btqroot != NULL) __free_btree(__btqroot);
+ __btqroot = NULL;
+ __topi = 0;
+
+ /* cur te hdr/end is same as one of twheel lists if hdr non nil */ 
+ __cur_te_hdri = __cur_te_endi = -1;  
+
+ /* but no timing wheel te hdr corresponds to #0s */ 
+ if (__p0_te_hdri != -1)
+  {
+   register i_tev_ndx tevpi, tevp2i;
+
+   for (tevpi = __p0_te_hdri; tevpi != -1;)
+    {
+     tevp2i = __tevtab[tevpi].tenxti;
+     __free_1tev(tevpi);
+     tevpi = tevp2i; 
+    }
+   __p0_te_hdri = __p0_te_endi = -1;  
+
+   for (tevpi = __nb_te_hdri; tevpi != -1;)
+    {
+     tevp2i = __tevtab[tevpi].tenxti;
+     __free_1tev(tevpi);
+     tevpi = tevp2i; 
+    }
+   __nb_te_hdri = __nb_te_endi = -1;
+  }
+
+ /* free pending strobes for this time slot - if none added does nothing */
+ if (__strobe_hdr != NULL)
+  {
+   /* must mark any seen but not output strobe as not seen */
+   for (strbp = __strobe_hdr; strbp != NULL; strbp = strbp->strbnxt) 
+    strbp->strbstp->strb_seen_now = FALSE;
+
+   __strobe_end->strbnxt = __strb_freelst;
+   __strb_freelst = __strobe_hdr;
+  } 
+ __strobe_hdr = __strobe_end = NULL;
+
+ /* free pending dce list  */
+ /* notice here dcevnts turned off when needed net dcelst's turned off */
+ for (fmonp = __fmon_hdr; fmonp != NULL;) 
+  {
+   fmonp2 = fmonp->fmonnxt;
+   /* free all fmon aux list since only on if re-added after reset */
+   for (dclp = fmonp->fmon_dcehdr; dclp != NULL; dclp = dclp->dclnxt)
+    {
+     /* AIV 11/26/02 dc events now built during elaboration and not freed */
+     dclp->ldcep->dce_off = TRUE;
+    }
+   __my_free((char *) fmonp, sizeof(struct fmonlst_t));
+   fmonp = fmonp2;
+  }
+ __fmon_hdr = __fmon_end = NULL; 
+
+ /* free any activated but not yet executed slot end fmonitors */
+ if (__fmonse_hdr != NULL)
+  {
+   __fmonse_end->fmsenxt = __fmse_freelst;
+   __fmse_freelst = __fmonse_hdr;
+  } 
+
+ /* free monitor - same as call to $monitor with no arguments */
+ /* know only 1 inst. */
+ /* indcate no pending monitor */
+ /* SJM 06/21/02 - never free monit dces - just turn off - but free list */
+ for (dclp = __monit_dcehdr; dclp != NULL; dclp = dclp->dclnxt)
+  {
+   /* turn off the dce but do not free */
+   /* AIV 11/26/02 dc events now built during elaboration and not freed */
+   dclp->ldcep->dce_off = TRUE;
+  }
+ if (__monit_dcehdr != NULL) __monit_dcehdr = NULL;
+ __monit_stp = NULL;
+ __monit_itp = NULL;
+
+ /* re-initialize vars and state and the dce list for each wire */
+ /* dce list both scheduled events tables reset and triggered dmpv bits */
+ reinit_vars_and_state();
+ /* DBG remove ---
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   __dmpmod_nplst(mdp, TRUE);
+   __pop_wrkitstk();
+  }
+ --- */
+
+ /* free dumpvars setup master records - will be setup again */ 
+ for (mdvp = __dv_hdr; mdvp != NULL;)
+  {
+   mdvp2 = mdvp->mdvnxt;
+   __my_free((char *) mdvp, sizeof(struct mdvmast_t));
+   mdvp = mdvp2;
+  }
+ __dv_hdr = __dv_end = NULL;
+ /* close any open dumpvars file */ 
+ if (strcmp(__dv_fnam, DFLTDVFNAM) != 0)
+  {
+   __my_free(__dv_fnam, strlen(__dv_fnam) + 1);
+   __dv_fnam = __pv_stralloc(DFLTDVFNAM);
+  }
+ /* close any dv file, if running gets to dv will then overwrite */
+ if (__dv_fd != -1L) { __my_close(__dv_fd); __dv_fd = -1; }
+
+ /* add any pending until slot end tim chk changes to free list */
+ if (__tcpendlst_end != NULL)
+  {
+   __tcpendlst_end->tc_plnxt = __tcpendfreelst; 
+   __tcpendfreelst = __tcpendlst_hdr;
+   __tcpendlst_hdr = __tcpendlst_end = NULL; 
+  }
+
+ /* free any pending but unprocessed net change records */ 
+ if (__nchg_futend != NULL)
+  {
+   __nchg_futend->nchglnxt = __nchgfreelst;
+   __nchgfreelst = __nchg_futhdr;
+  }
+
+ /* add any pending dumpvars changes to end of free list for next time */
+ if (__dv_chgnethdr != NULL)
+  {
+   dvchg_last = NULL;
+   for (dvchgp = __dv_chgnethdr; dvchgp != NULL; dvchgp = dvchgp->dvchgnxt)
+    dvchg_last = dvchgp;
+
+   /* SJM 08/02/01 - add if to keep lint happy */
+   if (dvchg_last != NULL) dvchg_last->dvchgnxt = __dv_netfreelst;
+   __dv_netfreelst = __dv_chgnethdr;
+   __dv_chgnethdr = NULL;
+  }
+ /* must close any open multi-channel descriptors and turn bit off */
+ /* initialize the multichannel descriptor table */
+ /* SJM 03/26/00 - bit 3 (value 4) no longer log file - lumped with stdout */ 
+ /* leave stdout (1) and stderr (2) */
+ for (i = 2; i < 31; i++)
+  {
+   if (__mulchan_tab[i].mc_s == NULL) continue;
+    
+   __my_fclose(__mulchan_tab[i].mc_s);
+   chp = __mulchan_tab[i].mc_fnam;
+   __my_free(chp, strlen(chp) + 1);
+   __mulchan_tab[i].mc_s = NULL;
+   __mulchan_tab[i].mc_fnam = NULL;
+  }
+ /* free all tfrec for tf_ tasks and functions to initial state */
+ __reinit_tfrecs();
+ /* putv records reinitialized during wire reset */
+ __reinit_vpi(); 
+
+ /* can leave any pending repeat counts since will be reset when entered */
+ /* rerun initialize to propagate all initial events */
+ __reinit_sim();
+ /* must leave any breakpoints and debugger states */
+ /* will start up as previous so if -s set, will again enter interactive */
+}
+
+/*
+ * re-initialize variables and state information 
+ * traverse static circuit freeing all values and pending scheduled values
+ */
+static void reinit_vars_and_state(void)
+{
+ register int32 gi, i, bi;
+ register struct conta_t *cap, *pbcap;
+ register struct mod_pin_t *mpp;
+ register struct mod_t *mdp;
+ int32 cai, insts;
+ struct gate_t *gp;
+ i_tev_ndx *itevpp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   /* turn off dumpvars in mod here and in caller */
+   mdp->mod_hasdvars = FALSE;
+   __reinitialize_vars(mdp);
+   __pop_wrkitstk();
+  }
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   /* turn off dumpvars in mod here and in caller */
+   mdp->mod_hasdvars = FALSE;
+
+   insts = mdp->flatinum;
+   /* since can't init dces until cgen .bss .so linking done - same as init */
+   __initialize_dces(mdp);
+   for (gi = 0; gi < mdp->mgnum; gi++)
+    {
+     gp = &(mdp->mgates[gi]);
+     /* no scheduled event table if no delay */ 
+     if ((itevpp = gp->schd_tevs) != NULL)
+      { for (i = 0; i < insts; i++) itevpp[i] = -1; }
+
+     if (gp->g_class == GC_UDP) __set_init_udpstate(gp, insts, FALSE);
+     else
+      {
+       if (gp->g_class == GC_PULL || gp->g_class == GC_TRAN) goto nxt_mod;
+       /* if output unc. (OPEMPTY), changes are not seen (do not propagate) */
+       if (gp->g_class != GC_TRANIF && gp->gpins[0]->optyp == OPEMPTY)
+        goto nxt_mod;
+
+       __set_init_gstate(gp, insts, FALSE);
+      }
+    }
+   for (cai = 0, cap = &(mdp->mcas[0]); cai < mdp->mcanum; cai++, cap++)
+    {
+     if (!cap->ca_pb_sim)
+      {
+       if (cap->lhsx->x_multfi || cap->ca_delrep != DT_NONE)
+        __allocinit_perival(&(cap->ca_drv_wp), insts, cap->lhsx->szu.xclen,
+         FALSE);
+       if (cap->ca_delrep != DT_NONE)
+        {
+         __allocinit_perival(&(cap->schd_drv_wp), insts, cap->lhsx->szu.xclen,
+          FALSE);
+         if ((itevpp = cap->caschd_tevs) != NULL)
+         { for (i = 0; i < insts; i++) itevpp[i] = -1; }
+        }
+      }
+     else
+      { 
+       for (bi = 0; bi < cap->lhsx->szu.xclen; bi++) 
+        {
+         pbcap = &(cap->pbcau.pbcaps[bi]);
+         /* DBG remove */
+         if (pbcap->lhsx->szu.xclen != 1) __misc_terr(__FILE__, __LINE__);
+         /* -- */
+         /* SJM 09/28/02 - notice if any PB fi>1 or del, need drv for each */ 
+         if (cap->lhsx->x_multfi || cap->ca_delrep != DT_NONE)
+          __allocinit_perival(&(pbcap->ca_drv_wp), insts, 1, FALSE);
+         if (cap->ca_delrep != DT_NONE)
+          {
+           __allocinit_perival(&(pbcap->schd_drv_wp), insts, 1, FALSE);
+           if ((itevpp = pbcap->caschd_tevs) != NULL)
+            { for (i = 0; i < insts; i++) itevpp[i] = -1; }
+          }
+        }
+      }
+    }
+   if (mdp->mod_has_mipds)
+    {
+     for (i = 0; i < mdp->mpnum; i++)
+      {
+       mpp = &(mdp->mpins[i]);
+       if (!mpp->has_mipd) continue;
+
+       __reinit_mipd(mpp, mdp);
+      }
+    }
+nxt_mod:
+   __pop_wrkitstk();
+  }
+ __set_nchgaction_bits();
+}
+
+/*
+ * NON DEBUGGER ONLY ROUTINES
+ */
+
+/*
+ * ROUTINES TO IMPLEMENT PENDING EVENT TRACE  
+ */
+
+/*
+ * write event location trace - assume basic event message already printed
+ * for active thread could actually give trace back of enables
+ * may be no scope here
+ */
+extern void __write_snapshot(int32 pend_num)
+{
+ int32 i;
+ i_tev_ndx tevpi;
+ struct thread_t *thp;
+
+ __cvsim_msg("*** Activity snapshot at %s ***\n", __to_timstr(__xs,
+  &__simtime));
+ if (__cur_tevpi == -1)
+  {
+   if (__inst_ptr == NULL) strcpy(__xs, "<none>");
+   else __msg2_blditree(__xs, __inst_ptr);
+
+   if (__sfnam_ind <= 0)
+    __cvsim_msg("Current event: <none> last scope %s - no last statement\n",
+      __xs);
+   else __cvsim_msg(
+    "Current event: <none> last scope %s - last statement %s\n", __xs,
+    __bld_lineloc(__xs2, (word32) __sfnam_ind, __slin_cnt));
+   if (__suspended_thd != NULL)
+    {
+     __cvsim_msg("Trace back of just suspended statements:\n");  
+     __prt_where_msg(__suspended_thd);
+    }
+  }
+ else
+  {
+   /* current event is one being processed now */
+   if (__tevtab[__cur_tevpi].tetyp == TE_THRD)
+    {
+     thp = __tevtab[__cur_tevpi].tu.tethrd;
+     __cvsim_msg("Trace back of enabled statements:\n");  
+     __prt_where_msg(thp);
+    }
+   else
+    {
+     /* this write the end new line */
+     wr_1ev_trace(-1, __cur_tevpi);
+    }
+  }
+ /* FIXME - think this is wrong for CG thrd but rarely used feature */
+ fill_near_evtab(pend_num, TE_THRD);
+ if (__last_wevti >= 0)
+  __cvsim_msg("\nNext %d pending procedural events:\n", __last_wevti + 1); 
+
+ for (i = 0; i <= __last_wevti; i++)  
+  {
+   tevpi = __wrkevtab[i];
+   wr_1ev_trace(i, tevpi);
+  }
+ fill_near_evtab(pend_num, TE_G);
+ if (__last_wevti >= 0)
+  __cvsim_msg("\nNext %d pending declarative events:\n", __last_wevti + 1); 
+ for (i = 0; i <= __last_wevti; i++)  
+  {
+   tevpi = __wrkevtab[i];
+   wr_1ev_trace(i, tevpi);
+  }
+ __dmp_all_thrds();
+ __cvsim_msg("*** End of snapshot ***\n");
+}
+
+/*
+ * print where message
+ * LOOKATME - maybe this should not use global __fcspi
+ */
+extern void __prt_where_msg(register struct thread_t *thp)
+{
+ register int32 i;
+ struct st_t *stp;
+ struct task_t *tskp;
+ struct thread_t *down_thp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (__fcspi >= 0) tskp = __fcstk[__fcspi];
+ else if (thp->th_fj) tskp = __find_thrdtsk(thp);
+ else tskp = thp->assoc_tsk;
+
+ if ((stp = thp->thnxtstp) == NULL) strcpy(s1, "**END**"); 
+ else __bld_lineloc(s1, (word32) stp->stfnam_ind, stp->stlin_cnt);
+ __cvsim_msg("In scope %s next statement at %s\n",
+  __msg_blditree(s2, thp->th_itp, tskp), s1);
+
+ if (__fcspi >= 0)
+  {
+   for (i = __fcspi - 1; i >= 0; i--)
+    {
+     tskp = __fcstk[i];
+     __cvsim_msg(" -- function %s\n", __msg_blditree(s1,
+     thp->th_itp, tskp));
+    }
+   i = 0; 
+  }
+ else i = 1;
+ down_thp = thp;
+ for (thp = down_thp->thpar; thp != NULL; thp = thp->thpar, i++) 
+  {
+   if (down_thp->th_fj) tskp = __find_thrdtsk(down_thp);
+   else tskp = down_thp->assoc_tsk;
+   if (tskp == NULL) strcpy(s1, "");
+   else sprintf(s1, " %s", __to_tsktyp(s2, tskp->tsktyp));
+   if (down_thp->th_itp == NULL) __misc_terr(__FILE__, __LINE__);
+   __msg_blditree(s3, down_thp->th_itp, tskp);
+
+   __cvsim_msg("%2d)%s enabled from %s in %s\n", i, s1,
+    __bld_lineloc(s2, down_thp->thenbl_sfnam_ind, down_thp->thenbl_slin_cnt),
+    s3);
+   down_thp = thp;
+  }
+ __cvsim_msg("%2d) started from initial/always at %s in %s\n", i,
+  __bld_lineloc(s1, down_thp->thenbl_sfnam_ind, down_thp->thenbl_slin_cnt),
+  __msg_blditree(s2, down_thp->th_itp, (struct task_t *) NULL));
+}
+
+/*
+ * ROUTINES TO WRITE THREAD TRACE BACK
+ */
+
+/*
+ * write trace of 1 thread event
+ * for procedural scheduled but not active
+ */
+static void wr_1ev_trace(int32 i, i_tev_ndx tevpi)
+{
+ int32 lhslen, bi, wlen;
+ byte *sbp;
+ word32 *wp, av, bv;
+ struct tev_t *tevp;
+ struct conta_t *cap;
+ struct gate_t *gp;
+ struct net_t *np;
+ struct thread_t *thp;
+ struct tfrec_t *tfrp;
+ struct st_t *stp;
+ struct itree_t *sav_tritp;
+ struct xstk_t *xsp, *xsp2;
+ struct task_t *tskp;
+ struct tedputp_t *tedp;
+ struct expr_t *xp;
+ struct tfarg_t *tfap;
+ char s1[RECLEN], s2[RECLEN];
+
+ tevp = &(__tevtab[tevpi]);
+ sav_tritp = __last_tritp;
+ __last_tritp = NULL;
+ if (i == -1) __cvsim_msg("Current event: ");
+ else __cvsim_msg("  %2d) time %s ", i + 1, __to_timstr(__xs, &(tevp->etime)));
+ if (tevp->te_cancel) __cvsim_msg("[canceled] ");
+ __push_itstk(tevp->teitp);
+ switch ((byte) tevp->tetyp) {
+  case TE_THRD:
+   /* SJM 03/15/01 - now using normal stmt thread mechanism */ 
+   /* ithrd interpreter use stmt ithrd cod ptr */
+   thp = tevp->tu.tethrd;  
+   stp = thp->thnxtstp;
+   /* here may have hit breakpoint in func. so ok */ 
+   if (thp->th_fj) tskp = __find_thrdtsk(thp); else tskp = thp->assoc_tsk;
+   __cvsim_msg("procedural event in %s resume", __msg_blditree(__xs,
+    __inst_ptr, tskp));
+   if (stp == NULL) __cvsim_msg(" **at end**\n");
+   else __cvsim_msg(" %s\n", __bld_lineloc(__xs, stp->stfnam_ind,
+    stp->stlin_cnt)); 
+   __cvsim_msg("      enabled from %s\n", __bld_lineloc(__xs,
+    thp->thenbl_sfnam_ind, thp->thenbl_slin_cnt));
+   break;
+  case TE_G:
+   gp = tevp->tu.tegp;
+   __cvsim_msg("gate line %s:\n", __bld_lineloc(__xs,
+    gp->gsym->syfnam_ind, gp->gsym->sylin_cnt));
+   __cvsim_msg("        %s\n", __gstate_tostr(__xs2, gp, TRUE));   
+   break;
+  case TE_CA:
+   /* SJM 09/28/02 - notice for decomposed into per bit, this is PB el */
+   cap = tevp->tu.tecap;
+   __cvsim_msg("%s:\n", __to_evtrcanam(__xs, cap, tevp->teitp));
+   lhslen = cap->lhsx->szu.xclen;
+   push_xstk_(xsp, lhslen);
+   /* notice will never be called unless drv_wp exists - else no event */
+   __ld_perinst_val(xsp->ap, xsp->bp, cap->ca_drv_wp, lhslen);
+   /* build a conta driving string - may need to add strength */ 
+   if (cap->ca_hasst)
+    {
+     push_xstk_(xsp2, 4*lhslen);
+     sbp = (byte *) xsp2->ap;
+     __st_standval(sbp, xsp, cap->ca_stval);
+     __st_regab_tostr(s1, sbp, lhslen);
+     __pop_xstk();
+    }
+   else __regab_tostr(s1, xsp->ap, xsp->bp, lhslen, BBIN, FALSE);
+   __pop_xstk();
+   xsp = __eval_xpr(cap->rhsx);
+   /* notice for conta if 0 delay fi==1, never get here */
+   __cvsim_msg("      %s = %s %s\n", s1, 
+    __regab_tostr(__xs, xsp->ap, xsp->bp, cap->rhsx->szu.xclen, BBIN,
+     FALSE), __bld_valofsched(__xs2, tevp));
+   __pop_xstk();
+   break;
+  case TE_WIRE: case TE_BIDPATH:
+   np = tevp->tu.tenp->tenu.np;
+   bi = tevp->tu.tenp->nbi;
+   if (tevp->tetyp == TE_WIRE) strcpy(s2, "wire event");
+   else strcpy(s2, "inout path dest. event");
+   __cvsim_msg("%s %s declared line %s\n",
+    __to_evtrwnam(__xs, np, bi, bi, __inst_ptr), s2,
+    __bld_lineloc(__xs2, np->nsym->syfnam_ind, np->nsym->sylin_cnt));
+   if (np->n_stren)
+    { get_stwire_addr_(sbp, np); __to_vvstnam(s1, (word32) sbp[bi]); }
+   else
+    { __ld_bit(&av, &bv, np, bi); __to_vvnam(s1, (word32) (av | (bv << 1))); }
+   __cvsim_msg("       value %s %s\n", s1, __bld_valofsched(__xs2, tevp));
+   break;
+  case TE_MIPD_NCHG: 
+   /* FIXME - maybe add info so can print port bit too */
+   np = tevp->tu.tenp->tenu.np;
+   bi = tevp->tu.tenp->nbi;
+   __cvsim_msg("MIPD on %s net %s\n", __to_ptnam(__xs2, np->iotyp),
+    __to_evtrwnam(__xs, np, bi, bi, __inst_ptr));
+   break;
+  case TE_NBPA:
+   stp = tevp->tu.tenbpa->nbastp;
+   __cvsim_msg("non blocking assign event in %s line %s",
+    __msg2_blditree(__xs, __inst_ptr), __bld_lineloc(__xs2, stp->stfnam_ind,
+    stp->stlin_cnt));
+   if (stp->st.sdc->repcntx != NULL)
+    {
+     sprintf(__xs, "waiting for repeat count events (now %s)\n",
+      __to_timstr(__xs2, &(tevp->etime)));
+    }
+   else sprintf(__xs, "assign at %s\n", __to_timstr(__xs2, &(tevp->etime)));
+   wp = tevp->tu.tenbpa->nbawp;
+   /* SJM 08/08/99 - use copied lhs expr. with ndxes converted to con if set */
+   if ((xp = tevp->tu.tenbpa->nblhsxp) == NULL) xp = stp->st.spra.lhsx;
+
+   lhslen = xp->szu.xclen;
+   wlen = wlen_(lhslen);
+   __cvsim_msg("       new value %s %s\n",
+    __xregab_tostr(s1, wp, &(wp[wlen]), lhslen, xp), __xs);
+   break;
+  case TE_TFSETDEL: 
+   tfrp = tevp->tu.tetfrec;
+   __cvsim_msg("tf_ set delay misctf call of %s in %s at %s\n",
+    __get_tfcellnam(tfrp), __msg_blditree(__xs, __inst_ptr, tfrp->tf_intskp),
+    __bld_lineloc(__xs2, tfrp->tffnam_ind, tfrp->tflin_cnt));
+   break;
+  case TE_SYNC:
+   tfrp = tevp->tu.tetfrec;
+   __cvsim_msg("tf_ #0 synchronize misctf call of %s in %s at %s\n",
+    __get_tfcellnam(tfrp), __msg_blditree(__xs, __inst_ptr, tfrp->tf_intskp),
+    __bld_lineloc(__xs2, tfrp->tffnam_ind, tfrp->tflin_cnt));
+   break;
+  case TE_TFPUTPDEL:
+   tedp = tevp->tu.tedputp;
+   tfrp = tedp->tedtfrp;
+   __cvsim_msg("tf_ strdel putp assign to arg %d of %s in %s at %s\n",
+    tedp->tedpnum, __get_tfcellnam(tfrp), __msg_blditree(__xs, __inst_ptr,
+    tfrp->tf_intskp), __bld_lineloc(__xs2, tfrp->tffnam_ind, tfrp->tflin_cnt));
+
+   tfap = &(tfrp->tfargs[tedp->tedpnum]);
+   if (tfap->anp->ntyp >= NONWIRE_ST) strcpy(__xs, "procedural assign of"); 
+   else strcpy(__xs, "tf_ driver is"); 
+   xp = tfap->arg.axp;
+   wp = tedp->tedwp;
+   lhslen = xp->szu.xclen;
+   wlen = wlen_(lhslen);
+   __cvsim_msg("       %s %s\n", __xs, __xregab_tostr(s1, wp,
+    &(wp[wlen]), lhslen, xp));
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ __last_tritp = sav_tritp; 
+ __pop_itstk();
+}
+
+/*
+ * routine to fill table (known big enough) with future events
+ * starts with next event must match event type to passed number
+ *
+ * puts in global table __wrkevtab index __last_wevti size __size_wrkevtab
+ * this must skip current event
+ */
+static void fill_near_evtab(int32 ntevs, int32 tefilt)
+{
+ register i_tev_ndx tevpi; 
+ int32 evnum, osize, twi, added_pnd0s;
+ word64 t1, t2;
+ struct telhdr_t *ovfl_telp, *twp;
+
+ /* make sure work event table allocated and large enough */
+ if (__wrkevtab == NULL)
+  {
+   __wrkevtab = (i_tev_ndx *) __my_malloc(ntevs*sizeof(i_tev_ndx)); 
+   __size_wrkevtab = ntevs;
+  }
+ else
+  {
+   if (ntevs > __size_wrkevtab)
+    {
+     osize = __size_wrkevtab*sizeof(i_tev_ndx);
+     __wrkevtab = (i_tev_ndx *) __my_realloc((char *) __wrkevtab, osize,
+      ntevs*sizeof(i_tev_ndx)); 
+     __size_wrkevtab = ntevs; 
+    }
+  }
+ __last_wevti = -1;
+ evnum = 0;
+
+ /* first rest of current list */
+ /* if not in pound 0's, first rest of current slot list */ 
+ added_pnd0s = FALSE;
+ if (!__processing_pnd0s)
+  {
+   /* if cur tevp index set, 1st pending event must be next */
+   if (__cur_tevpi != -1) tevpi = __tevtab[__cur_tevpi].tenxti;
+   else tevpi = __cur_te_hdri;
+   for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+    {
+     if (!try_add_wrkevtab(tevpi, ntevs, &evnum, tefilt)) return;
+    }
+   /* add pnd0's or nb pnd0's if no pnd0s */
+   if (__p0_te_hdri != -1) { tevpi = __p0_te_hdri; added_pnd0s = TRUE; }
+   else tevpi = __nb_te_hdri;
+  }
+ else
+  {
+   /* SJM - also add nb's if no pound 0's */
+   if (__cur_tevpi != -1) tevpi = __tevtab[__cur_tevpi].tenxti;
+   else if (__p0_te_hdri != -1) { added_pnd0s = TRUE; tevpi = __p0_te_hdri; }
+   else tevpi = __nb_te_hdri;
+  }
+ /* next try pound 0's */
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+  {
+   if (!try_add_wrkevtab(tevpi, ntevs, &evnum, tefilt)) return;
+
+   /* if processing pnd0s and added pnd0's, must also add any nb pnd0s */
+   /* before moving forward in time */
+   if (tevpi == -1 && added_pnd0s)
+    {
+     added_pnd0s = FALSE;
+     tevpi = __nb_te_hdri;
+    }
+  }
+ 
+ /* t1 is one time unit afer now */
+ t1 = __simtime + 1;
+ /* first overflow q location must be set before processing wheel */
+ if (__btqroot != NULL) ovfl_telp = tfind_btnode_after(__btqroot, t1);
+ else ovfl_telp = NULL;
+ if (__num_twhevents > 0)
+  {
+   /* go through timing wheel to end (know all events here in wheel) */ 
+   /* and not in overflow q */
+   for (twi = __cur_twi + 1; twi < __twhsize; twi++)
+    {
+     twp = __twheel[twi];
+     if (twp->te_hdri != -1) 
+      {
+       for (tevpi = twp->te_hdri; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+        { if (!try_add_wrkevtab(tevpi, ntevs, &evnum, tefilt)) return; }
+      }
+    }
+   for (twi = 0; twi < __cur_twi; twi++)
+    {
+     twp = __twheel[twi];
+     /* know twi at least as early as any overflow queue event */
+     /* do next timing wheel events, if any */
+     if (twp->te_hdri != -1) 
+      {
+       for (tevpi = twp->te_hdri; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+        { if (!try_add_wrkevtab(tevpi, ntevs, &evnum, tefilt)) return; }
+      }
+     if (ovfl_telp != NULL)
+      {
+       /* t2 is index + 1 of time of wrap around current slot */
+       t2 = (word64) (twi + 1);
+       /* t1 is time of wheel position */
+       t1 = __whetime + t2;
+       if (twp->te_hdri != -1 && t1 != __tevtab[twp->te_hdri].etime)
+        __misc_terr(__FILE__, __LINE__);
+
+       tevpi = ovfl_telp->te_hdri;
+       if (t1 == __tevtab[tevpi].etime)  
+        {
+         for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+          if (!try_add_wrkevtab(tevpi, ntevs, &evnum, tefilt)) return;
+         /* move to next overflow tree place */
+         t1++;
+         ovfl_telp = tfind_btnode_after(__btqroot, t1);
+        }
+      }
+    }
+  }
+ if (ovfl_telp == NULL) return;
+ for (;;)
+  {
+   tevpi = ovfl_telp->te_hdri;
+   t1 = __tevtab[tevpi].etime; 
+   for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+    if (!try_add_wrkevtab(tevpi, ntevs, &evnum, tefilt)) return;
+   t1++;
+   if ((ovfl_telp = tfind_btnode_after(__btqroot, t1)) == NULL) return;
+  }
+}
+
+/*
+ * find btree node after or same as tim 
+ */
+static struct telhdr_t *tfind_btnode_after(struct bt_t *btphdr, word64 tim)
+{
+ register struct bt_t *btp;
+ struct telhdr_t *telp;
+
+ if (btphdr->bttyp == BTFRNGE)
+  { 
+   for (btp = btphdr; btp != NULL; btp = btp->btnxt)
+    { if (btp->btltim >= tim) return(btp->ofsu.telp); }
+   return(NULL);
+  }
+ for (btp = btphdr; btp != NULL; btp = btp->btnxt)
+  {
+   if ((telp = tfind_btnode_after(btp->ofsu.btofs, tim)) != NULL)
+    return(telp);
+  }
+ return(NULL);
+} 
+
+/*
+ * add to work ev tab if not elminated by filter
+ * filter is threads only or all but thread
+ * this return FALSE when table full
+ */
+static int32 try_add_wrkevtab(i_tev_ndx tevpi, int32 ntevs, int32 *evnum,
+ int32 tefilt)
+{
+ struct tev_t *tevp;
+
+ tevp = &(__tevtab[tevpi]);
+ if (tefilt != -1)
+  {
+   /* FIXME for new cg threads this looks wrong but maybe return T right */
+   if (tefilt == TE_THRD)
+    { if (tevp->tetyp != TE_THRD) return(TRUE); }
+   else if (tevp->tetyp == TE_THRD) return(TRUE);
+  }
+ if (++(*evnum) > ntevs) return(FALSE);
+ __wrkevtab[++__last_wevti] = tevpi;
+ return(TRUE);
+}
+
+/*
+ * TASK THREAD DUMP ROUTINES
+ */
+
+extern void __dmp_all_thrds()
+{
+ __dmp_initalw_thrd_tree();
+ __dmp_tskthrds();
+}
+
+extern void __dmp_tskthrds(void)
+{
+ register struct mod_t *mdp;
+ register struct task_t *tskp;
+ int32 first_time = TRUE;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mtasks == NULL) continue;
+   if (first_time) { __cv_msg("\n"); first_time = FALSE; }
+
+   __cvsim_msg("Task threads in module %s:\n", mdp->msym->synam);
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+
+     __dmp_tskthd(tskp, mdp);
+    } 
+  }
+}
+
+/*
+ * dump 1 task thread
+ */
+extern void __dmp_tskthd(struct task_t *tskp, struct mod_t *mdp)
+{
+ register int32 i;
+ register struct tskthrd_t *ttp;
+
+ if (tskp->tsktyp == FUNCTION) 
+  {
+   if (tskp->tthrds != NULL) __misc_terr(__FILE__, __LINE__);
+   return;
+  }
+ for (i = 0; i < mdp->flatinum; i++) 
+  {
+   if ((ttp = tskp->tthrds[i]) == NULL)
+    {
+     if (__debug_flg)
+      __dbg_msg("*** task %s instance %d has no task threads\n", 
+       tskp->tsksyp->synam, i);
+     continue;
+    }
+   __cvsim_msg("*** dumping threads for task %s (%s)\n",
+    tskp->tsksyp->synam, __msg_blditree(__xs, mdp->moditps[i],
+    (struct task_t *) NULL));
+   for (; ttp != NULL; ttp = ttp->tthd_r) __dmp_thrd_info(ttp->tthrd);
+  }
+}
+
+/*
+ * dump top level init/always thread tree
+ */
+extern void __dmp_initalw_thrd_tree(void)
+{
+ register struct thread_t *thp;
+
+ __cvsim_msg("Initial/always threads:\n");
+ for (thp = __initalw_thrd_hdr; thp != NULL; thp = thp->thright)
+  {
+   if (thp->thdtevi == -1 && thp->th_dctp == NULL && thp->thofscnt == 0)
+    {
+     __cvsim_msg("   initial/always thread enabled at %s completed\n",
+      __bld_lineloc(__xs, thp->thenbl_sfnam_ind, thp->thenbl_slin_cnt));
+     continue;
+    }
+   __dmp_thrd_info(thp);
+   if (thp->thofs != NULL) __dmp_thrd_tree(thp->thofs); 
+  }
+ __cvsim_msg("  *** end of initial/always threads ***\n");
+}
+
+extern void __dmp_thrd_tree(register struct thread_t *thp)
+{
+ for (; thp != NULL; thp = thp->thright)
+  {
+   __dmp_thrd_info(thp);
+   if (thp->thofs != NULL) __dmp_thrd_tree(thp->thofs); 
+  } 
+}
+
+extern void __dmp_thrd_info(struct thread_t *thp)
+{
+ i_tev_ndx tevpi;
+ struct delctrl_t *dctp;
+ struct tev_t *tevp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (thp->thnxtstp == NULL) strcpy(s2, "**at end");
+ else __bld_lineloc(s2, thp->thnxtstp->stfnam_ind, thp->thnxtstp->stlin_cnt);
+
+ __cvsim_msg("   enabled %s statement %s in %s\n",
+  __bld_lineloc(s1, thp->thenbl_sfnam_ind, thp->thenbl_slin_cnt), s2,
+  __msg_blditree(s3, thp->th_itp, thp->assoc_tsk));
+
+ if ((tevpi = thp->thdtevi) != -1)
+  {
+   tevp = &(__tevtab[tevpi]);
+   __cvsim_msg("   [%s event for time %s cancel=%d]\n",
+    __to_tetyp(s1, tevp->tetyp), __to_timstr(s2, &(tevp->etime)),
+    tevp->te_cancel);
+  }
+ if ((dctp = thp->th_dctp) != NULL)
+  {
+   if (dctp->actionst != NULL) 
+    sprintf(s1, "%s action at %s", __to_dcenam(s2, dctp->dctyp),
+    __bld_lineloc(s3, dctp->actionst->stfnam_ind, dctp->actionst->stlin_cnt));
+   else sprintf(s1, "%s no action", __to_dcenam(s2, dctp->dctyp));
+  } 
+ else strcpy(s1, "not waiting for event ctrl");
+ __cvsim_msg("   [has task outs=%d, disable=%d, fork=%d, %s]\n",
+   thp->tsk_stouts, thp->th_dsable, thp->th_fj, s1);
+}
diff --git a/src/v_del.c b/src/v_del.c
new file mode 100644
index 0000000..680fef3
--- /dev/null
+++ b/src/v_del.c
@@ -0,0 +1,2861 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * Verilog delay preparation and changing routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void delx_to_deltim(word64 *, struct expr_t *, struct xstk_t *);
+static void emit_reprepdev_verbmsg(struct gate_t *, struct gate_t *,
+ struct mod_t *, struct itree_t *, int32);
+static void emit_reprepconta_verbmsg(struct conta_t *, struct gate_t *,
+ struct mod_t *, struct itree_t *, int32);
+static void emit_reprepnet_verbmsg(struct net_t *, struct gate_t *,
+ struct mod_t *, struct itree_t *, int32);
+static void emit_reprepstmt_verbmsg(struct st_t *, struct gate_t *,
+ struct mod_t *, struct itree_t *, int32);
+static void emit_reprepiopath_verbmsg(struct spcpth_t *, struct gate_t *,
+ struct mod_t *, struct itree_t *, int32);
+static void emit_repreptclim_verbmsg(struct tchk_t *, struct gate_t *,
+ struct mod_t *, struct itree_t *, word32, int32);
+static void prep2_delay(struct gate_t *, struct paramlst_t *, int32, int32);
+static void nonis_to_delval(word64 *, struct expr_t *);
+static void prep_1delform(struct gate_t *, struct expr_t *);
+static void convert_trireg_1vto4v(struct gate_t *);
+static void prep_prim_is_dels(struct gate_t *, struct expr_t **, int32, int32);
+static void prep_path_is_dels(struct gate_t *, struct expr_t **, int32);
+static void fill_1col_isdel(word64 *, int32, struct expr_t *, int32);
+static void chg1vform_1instdel(struct gate_t *, struct itree_t *,
+ struct gate_t *);
+static void set_1is1val(struct gate_t *, int32, int32, word64 *, int32);
+static void chg4vform_1instdel(struct gate_t *, struct itree_t *,
+ struct gate_t *);
+static void set_1is416val(struct gate_t *, int32, int32, word64 *, int32);
+static void chg16vform_1instdel(struct gate_t *, struct itree_t *,
+ struct gate_t *);
+static void cnv_1is_to_4is(struct gate_t *, int32, int32, int32);
+static void cnv_1is_to_16is(struct gate_t *, int32, int32, int32);
+static void create_disv(struct gate_t *, int32, int32, word64 *, int32);
+static int32 get_ispack(word64);
+static void unpack_isv1_to_isv2(struct gate_t *, int32, int32);
+static void unpack_isv1_to_isv(struct gate_t *, int32, int32);
+static void unpack_isv2_to_isv(struct gate_t *, int32, int32);
+static void zero_unused_16v(word64 *);
+static void real_to_ticks(word64 *, double, struct mod_t *);
+
+/* extern prototypes (maybe defined in this module) */
+extern void __hizstrengate_getdel(word64 *, register struct gate_t *);
+extern void __get_del(register word64 *, register union del_u, word32);
+extern int32 __real_to_v64tim(word64 *, double);
+extern void __cnv_ticks_tonum64(word64 *, word64, struct mod_t *);
+extern void __re_prep_dels(struct net_t *, struct itree_t *, struct mod_t *,
+ int32);
+extern void __prep_delay(struct gate_t *, struct paramlst_t *, int32, int32, char *, int32, struct sy_t *, int32);
+extern void __free_del(union del_u, word32, int32);
+extern void __free_dellst(struct paramlst_t *);
+extern void __fill_4vconst(word64 *, word64 *, word64 *, word64 *, int32, int32);
+extern void __fill_16vconst(word64 *, word64 *, int32);
+extern void __chg_1inst_del(struct gate_t *, struct itree_t *, struct gate_t *);
+extern char *__bld_delay_str(char *, union del_u, word32);
+extern void __extract_delval(word64 *, int32 *, union del_u, word32);
+extern void __map_16v_to_12vform(word64 *, word64 *);
+extern void __try_reduce_16vtab(word64 *, int32 *);
+extern void __do_showdel_stask(struct expr_t *, char *);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char *__to_timstr(char *, word64 *);
+extern int32 __v64_to_real(double *, word64 *);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern char *__to_tcnam(char *, word32);
+extern struct paramlst_t *__copy_dellst(struct paramlst_t *);
+extern int32 __chk_delparams(struct paramlst_t *, char *, int32);
+extern void __chk_spec_delay(struct expr_t *, char *);
+extern char *__my_malloc(int32);
+extern void __my_free(char *, int32);
+extern struct expr_t *__copy_expr(struct expr_t *);
+extern void __free_xtree(struct expr_t *);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern int32 __is_lnegative(word32 *, int32); 
+
+extern void __cv_msg(char *, ...);
+extern void __gfwarn(int32, word32, int32, char *, ...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+
+extern int32 errno;
+extern word32 __masktab[];
+
+#if defined(__SVR4) || defined(__hpux)
+#define drem fmod
+#endif
+
+double __dbl_toticks_tab[] = { 1.0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+ 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10, 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15 };
+
+/*
+ * DELAY ACCESS ROUTINES
+ */
+
+/*
+ * get a primitive delay for a gate that drives highz[01]
+ * this is only called if g_hasst T
+ *
+ * primitive gate delays always determined solely by new value
+ * and since wire (not gate) driven to z because of strength use wire for
+ * delay
+ */
+extern void __hizstrengate_getdel(word64 *gdel, register struct gate_t *gp)
+{ 
+ register word32 save_val, stren0;
+   
+ save_val = __new_gateval;
+ /* know one or other must be 0 strength */
+ stren0 = (gp->g_stval >> 3) & 7;
+ if (stren0 == 0) { if (save_val == 0) __new_gateval = 2; }
+ else { if (save_val == 1) __new_gateval = 2; } 
+ __get_del(gdel, gp->g_du, gp->g_delrep);
+ __new_gateval = save_val;
+}
+
+/*
+ * get the delay value needed for transition to global __new_gateval
+ * know no delay case already handled
+ *
+ * know 4 array already set with right values if gate or conta
+ * global new gateval must be set to new value (0-3) (0,1,z,x) and
+ * for continuous assign (know > 1) must be corrected (0 if all 0's,
+ * (2 if all z's, else 1 (rise)
+ *
+ * notice this can return a 0 delay that needs to be on pound 0 queue
+ * also these have all been scaled
+ *
+ * need to remove all but low 3 bits because can be used for strenght vals
+ */
+extern void __get_del(register word64 *gdel, register union del_u du,
+ word32 drep)
+{
+ register int32 ind;
+ word64 dv1, dv0;
+ struct xstk_t *xsp;
+ struct expr_t *dxp;
+ struct thread_t *sav_curthp;
+
+ /* -- DBG remove
+  extern void __dbg_dump_del(union del_u, word32);
+
+ if (__debug_flg) __dbg_dump_del(du, drep);
+ -- */
+ 
+ switch ((byte) drep) {
+  case DT_1V: *gdel = du.d1v[0]; break;
+  case DT_IS1V: *gdel = du.dis1v[__inum]; break;
+  case DT_IS1V1:
+   *gdel = (word64) du.dis1v1[__inum];
+   break;
+  case DT_IS1V2:
+   *gdel = (word64) du.dis1v2[__inum];
+   break;
+  case DT_4V:
+   /* notice here the array has precomputed the delay for the new value */
+   /* including min comp. for x/z */
+   *gdel = du.d4v[__new_gateval & 3];
+   break;
+  case DT_IS4V:
+   /* this is time width 32 bit dependent */
+   *gdel = du.d4v[4*__inum + (__new_gateval & 3)];
+   break;
+  case DT_IS4V1:
+   *gdel = (word64) du.dis4v1[4*__inum + (__new_gateval & 3)];
+   break;
+  case DT_IS4V2:
+   *gdel = (word64) du.dis4v2[4*__inum + (__new_gateval & 3)];
+   break;
+  case DT_16V:
+   ind = ((__new_gateval & 3) << 2 | (__old_gateval & 3)) & 0xf;
+   *gdel = du.d16v[ind];
+   break;
+  case DT_IS16V:
+   /* notice size is 16 since x->x transition needed for strengths only chg */
+   ind = 16*__inum
+    + ((((__new_gateval & 3) << 2) | (__old_gateval & 3)) &0xf);
+   *gdel = du.dis16v[ind];
+   break;
+  case DT_IS16V1:
+   ind = 16*__inum
+    + ((((__new_gateval & 3) << 2) | (__old_gateval & 3)) & 0xf);
+   *gdel = (word64) du.dis16v1[ind];
+   break;
+  case DT_IS16V2:
+   ind = 16*__inum
+    + ((((__new_gateval & 3) << 2) | (__old_gateval & 3)) & 0xf);
+   *gdel = (word64) du.dis16v2[ind];
+   break;
+  case DT_1X:
+   /* must run delay expr. eval without context thread */
+   sav_curthp = __cur_thd;
+   __cur_thd = NULL;
+
+   xsp = __eval_xpr(du.d1x);
+   /* this handles required scaling */
+   delx_to_deltim(gdel, du.d1x, xsp);
+   __pop_xstk();
+   __cur_thd = sav_curthp;
+   break;
+  case DT_4X:
+   /* know at least 2 delays */
+   /* trick here is do not know expr. ordering so can't precompute to z */ 
+   /* must run delay expr. eval without context thread */
+   sav_curthp = __cur_thd;
+   __cur_thd = NULL;
+   dxp = du.d4x[__new_gateval];
+   if (dxp == NULL)
+    {
+     dxp = du.d4x[0];
+     xsp = __eval_xpr(dxp);
+     delx_to_deltim(&dv0, dxp, xsp);
+     __pop_xstk();
+     dxp = du.d4x[1];
+     xsp = __eval_xpr(dxp);
+     
+     delx_to_deltim(&dv1, dxp, xsp);
+     __pop_xstk();
+     *gdel = (dv1 <= dv0) ? dv1 : dv0;
+     __cur_thd = sav_curthp;
+     return;
+    }
+   xsp = __eval_xpr(dxp);
+   delx_to_deltim(gdel, dxp, xsp);
+   __pop_xstk();
+   __cur_thd = sav_curthp;
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * DELAY CONVERSION ROUTINES
+ */
+
+/*
+ * given a delay expression - scale and convert to word64 delay value
+ * no checking - 64 bits 
+ */
+static void delx_to_deltim(word64 *dval, struct expr_t *dxp,
+ struct xstk_t *xsp)
+{
+ word64 t;
+ double d1;
+ struct mod_t *mdp;
+
+ mdp = __inst_mod;
+ if (dxp->is_real)
+  {
+   memcpy(&d1, xsp->ap, sizeof(double));
+   real_to_ticks(dval, d1, mdp);
+   return;
+  }
+ if (xsp->bp[0] != 0L)
+  {
+   __sgfwarn(565, "delay expression #(%s) evaluates to x/z changed to #0",
+    __msgexpr_tostr(__xs, dxp));
+   t = 0ULL; 
+   *dval = t;
+   return;
+  }
+ t = (word64) xsp->ap[0];
+ if (xsp->xslen > WBITS) t |= (((word64) xsp->ap[1]) << 32);
+
+ if (!mdp->mno_unitcnv) cnv_num64to_ticks_(*dval, t, mdp);
+ else *dval = t;
+}
+
+/*
+ * convert a real to ticks - here must scale (multiply before) conversion
+ * rule is: multiply to get ticks, round, then convert to time 
+ *
+ * notice this is only routine that is called even for mods that do not
+ * need scaling
+ */ 
+static void real_to_ticks(word64 *tim, double d1, struct mod_t *mdp)
+{
+ int32 unit;
+
+ if (!mdp->mno_unitcnv)
+  {
+    unit = __des_timeprec - mdp->mtime_units;
+    d1 *= __dbl_toticks_tab[unit];
+  }
+ if (!__real_to_v64tim(tim, d1))
+  __sgfwarn(563, "error in conversion of real %g to 64 bit time - set to %s",
+   d1, __to_timstr(__xs, tim));
+} 
+
+/*
+ * convert a real value to a 64 bit word32 time
+ * uses normal Verilog rounding from 0.5
+ * return F if error in conversion but still set some time value
+ * illegal if called with negative real
+ *
+ * this now assumes that that double to word32 conversion works
+ * used to not work on Machten 
+ */
+extern int32 __real_to_v64tim(word64 *tim, double dv)
+{
+ *tim = (word64) (dv + 0.500000);
+ return(TRUE);
+
+ /* ---
+ double d1, d2, d3, dbase;
+ int32 expbits, good;
+
+ good = TRUE;
+ tim->th = tim->tl = 0L;
+ if (dv < 0.0) return(FALSE);
+ -* see if value fits in 31 bits *-
+ if (dv <= (double) 0x7fffffff)
+  {
+   -* cannot use c compiler rounding since verilog is to higher magnitude *-
+   tim->tl = ver_rword(dv);
+   return(TRUE);
+  }
+
+ -* first catch overflow *-
+ d1 = frexp(dv, &expbits);
+ if (errno != 0) good = FALSE;
+ -* know since 0.5 <= d1 < 1.0 will be no bigger than 2*62 - 1 *-  
+ if (expbits > 64) return(FALSE);
+ dv += 0.500000000;
+ -* base is 2**32 *-
+ dbase = ((double) ((word32) 0xffffffff)) + 1.0; 
+ d1 = floor(dv/dbase);
+ d2 = drem(dv, dbase);
+ tim->th = (word32) d1; 
+ tim->tl = (word32) d2; 
+ -* DBG remove ---
+ __v64_to_real(&d3, tim);
+ if (fabs(dv - d3) >= EPSILON) __misc_terr(__FILE__, __LINE__);
+ --- *-
+ return(good);
+ -- */
+}
+
+/*
+ * convert from ticks to a module's user time - divide by units pow 10 diff
+ * only called for modules where time needs unscaling
+ * know this will always succeed
+ */
+extern void __cnv_ticks_tonum64(word64 *usertim, word64 tickstim,
+ struct mod_t *mdp)
+{ 
+ word64 quot, rem, tscale;
+ int32 unit;
+
+ /* this subtract backwards here */
+ unit = __des_timeprec - mdp->mtime_units;
+
+ tscale = __itoticks_tab[unit];
+ rem = tickstim % tscale;  
+ quot = tickstim/tscale;  
+ if (rem != 0ULL) 
+  {
+   /* divide scale period by 2 */
+   tscale = tscale/2;
+   if (rem >= tscale) quot++;
+  }
+ *usertim = quot;
+}
+
+/*
+ * DELAY PREPARATION ROUTINES
+ */
+
+/*
+ * after parameter change during SDF annotation re-prepare delays
+ *
+ * for each parameter parm npp list contains each RHS delay expr.
+ * reference to parameter - afer change re-prep each delay again
+ */
+extern void __re_prep_dels(struct net_t *parmnp, struct itree_t *itp,
+ struct mod_t *mdp, int32 from_vpi)
+{
+ register struct parmnet_pin_t *pnpp;  
+ int32 sav_declobj;
+ struct gate_t gwrk;
+ struct net_t *np;
+ struct gate_t *gp;
+ struct conta_t *cap;
+ struct st_t *stp;
+ struct delctrl_t *dctp;
+ struct sy_t tmpsym;
+ struct spcpth_t *pthp;
+ struct tchk_t *tcp;
+ char s1[RECLEN];
+
+ __push_wrkitstk(mdp, 0);
+ for (pnpp = (struct parmnet_pin_t *) parmnp->nlds; pnpp != NULL;
+  pnpp = pnpp->pnpnxt)
+  { 
+   switch ((byte) pnpp->pnptyp) {
+    case PNP_GATEDEL:
+     gp = pnpp->elpnp.egp;
+     __prep_delay(&gwrk, pnpp->pnplp, FALSE, FALSE, "prim delay annotate",
+      FALSE, gp->gsym, FALSE);
+     if (__nd_neg_del_warn)
+      {
+       __gferr(972, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+        "gate %s annotated delay negative (0 used)", gp->gsym->synam);
+        __nd_neg_del_warn = FALSE;
+      } 
+     /* free old */
+     __free_del(gp->g_du, gp->g_delrep, mdp->flatinum);
+     gp->g_du = gwrk.g_du;
+     gp->g_delrep = gwrk.g_delrep;
+     if (__sdf_verbose && (!from_vpi || __debug_flg))
+      emit_reprepdev_verbmsg(gp, &gwrk, mdp, itp, from_vpi);
+     break;
+    case PNP_CONTADEL:
+     /* SJM 09/28/02 - know reprep list always master even if per bit */
+     cap = pnpp->elpnp.ecap;
+      
+     __prep_delay(&gwrk, pnpp->pnplp, FALSE, FALSE,
+      "continuous assignment delay", FALSE, cap->casym, FALSE);
+     if (__nd_neg_del_warn)
+      {
+       __gferr(973, cap->casym->syfnam_ind, cap->casym->sylin_cnt,
+        "annotated continuous assign delay negative (0 used)");
+        __nd_neg_del_warn = FALSE;
+      } 
+     __free_del(cap->ca_du, cap->ca_delrep, mdp->flatinum);
+     cap->ca_du = gwrk.g_du;
+     cap->ca_delrep = gwrk.g_delrep;
+     if (__sdf_verbose && (!from_vpi || __debug_flg))
+      emit_reprepconta_verbmsg(cap, &gwrk, mdp, itp, from_vpi);
+     break;
+    case PNP_NETDEL:
+     np = pnpp->elpnp.enp;
+     __prep_delay(&gwrk, pnpp->pnplp, FALSE,
+      (np->ntyp == N_TRIREG), "annotated path delay", TRUE, np->nsym, FALSE); 
+ 
+     if (__nd_neg_del_warn)
+      {
+       __gferr(971, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+        "annotated wire %s delay negative (0 used)", np->nsym->synam);
+       __nd_neg_del_warn = FALSE;
+      } 
+     __free_del(np->nu.rngdwir->n_du, np->nu.rngdwir->n_delrep, mdp->flatinum);
+     np->nu.rngdwir->n_delrep = gwrk.g_delrep;
+     np->nu.rngdwir->n_du = gwrk.g_du;
+     if (__sdf_verbose && (!from_vpi || __debug_flg))
+      emit_reprepnet_verbmsg(np, &gwrk, mdp, itp, from_vpi);
+     break;
+    case PNP_PROCDCTRL:
+     dctp = pnpp->elpnp.edctp;
+     /* 01/25/00 SJM - fixed s now d not need stmt (maybe not around) */
+     /* but pointing to dctrl and using actionst if present */
+     if (dctp->actionst != NULL) stp = dctp->actionst; else stp = NULL;
+     if (stp != NULL)
+      {
+       tmpsym.syfnam_ind = stp->stfnam_ind;
+       tmpsym.sylin_cnt = stp->stlin_cnt;
+      }
+     else { tmpsym.syfnam_ind = 0; tmpsym.sylin_cnt = 0; }
+     
+     __prep_delay(&gwrk, pnpp->pnplp, FALSE, FALSE,
+      "defparam annotate to procedural delay control", FALSE, &tmpsym, FALSE);
+     if (__nd_neg_del_warn)
+      {
+       __sgferr(974,
+        "defparam delay control annotate negative delay illegal (0 used)");
+       __nd_neg_del_warn = FALSE;
+      } 
+     __free_del(dctp->dc_du, dctp->dc_delrep, mdp->flatinum);
+     dctp->dc_delrep = gwrk.g_delrep;
+     dctp->dc_du = gwrk.g_du;
+     if (__sdf_verbose && (!from_vpi || __debug_flg))
+      emit_reprepstmt_verbmsg(stp, &gwrk, mdp, itp, from_vpi);
+     break;
+    case PNP_PATHDEL:
+     sav_declobj = __cur_declobj;
+     __cur_declobj = SPECIFY;
+     pthp = pnpp->elpnp.epthp;
+     /* prepare the delay - notice this uses inst mod */
+     __prep_delay(&gwrk, pnpp->pnplp, TRUE, FALSE, "path delay annotate",
+      TRUE, pthp->pthsym, TRUE);
+     if (__nd_neg_del_warn)
+      {
+      __gferr(981, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt, 
+        "annotate path delay negative (used 0)");
+       __nd_neg_del_warn = FALSE;
+      } 
+     __free_del(pthp->pth_du, pthp->pth_delrep, mdp->flatinum);
+     pthp->pth_delrep = gwrk.g_delrep;
+     pthp->pth_du = gwrk.g_du;
+     if (__sdf_verbose && (!from_vpi || __debug_flg))
+      emit_reprepiopath_verbmsg(pthp, &gwrk, mdp, itp, from_vpi);
+     __cur_declobj = sav_declobj;
+     break;
+    case PNP_TCHKP1:
+     strcpy(s1, "annotate first timing check limit");
+     goto ano_tchk;
+    case PNP_TCHKP2:
+     strcpy(s1, "annotate second timing check limit");
+ano_tchk:
+     sav_declobj = __cur_declobj;
+     __cur_declobj = SPECIFY;
+     tcp = pnpp->elpnp.etcp;
+     __prep_delay(&gwrk, pnpp->pnplp, FALSE, FALSE, s1, TRUE, tcp->tcsym,
+      TRUE);
+     if (__nd_neg_del_warn)
+      {
+       __gfwarn(601, tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt,
+        "%s negative delay changed to 0 (ok for timing verifier)", s1);
+       __nd_neg_del_warn = FALSE;
+      }
+     if (pnpp->pnptyp == PNP_TCHKP1)
+      {
+       __free_del(tcp->tclim_du, tcp->tc_delrep, mdp->flatinum);
+       tcp->tc_delrep = gwrk.g_delrep;
+       tcp->tclim_du = gwrk.g_du;
+      }
+     else
+      {
+       __free_del(tcp->tclim2_du, tcp->tc_delrep2, mdp->flatinum);
+       tcp->tc_delrep2 = gwrk.g_delrep;
+       tcp->tclim2_du = gwrk.g_du;
+      }
+     if (__sdf_verbose && (!from_vpi || __debug_flg))
+      emit_repreptclim_verbmsg(tcp, &gwrk, mdp, itp, pnpp->pnptyp, from_vpi);
+     __cur_declobj = sav_declobj;
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+  }
+ __pop_wrkitstk();
+}
+       
+/*
+ * emit changed param new primitive delay
+ */
+static void emit_reprepdev_verbmsg(struct gate_t *gp, struct gate_t *ogp,
+ struct mod_t *mdp, struct itree_t *itp, int32 from_vpi)
+{
+ struct itree_t *itp2;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[10];
+
+ if (itp == NULL) { itp2 = mdp->moditps[0]; sprintf(s1, "'*' first"); }
+ else { __msg2_blditree(s1, itp); itp2 = itp; }
+ if (from_vpi) strcpy(s4, "VPI_ PLI"); else strcpy(s4, "SDF"); 
+ __push_itstk(itp2);
+ __cv_msg(
+  "  %s changed defparam: delay set to (%s) prim %s %s at %s in %s\n", s4,
+  __bld_delay_str(s2, ogp->g_du, ogp->g_delrep), gp->gmsym->synam,
+  gp->gsym->synam, __bld_lineloc(s3, gp->gsym->syfnam_ind,
+  gp->gsym->sylin_cnt), s1); 
+ __pop_itstk();
+}
+
+/*
+ * emit changed param new continuous assign delay
+ */
+static void emit_reprepconta_verbmsg(struct conta_t *cap, struct gate_t *ogp,
+ struct mod_t *mdp, struct itree_t *itp, int32 from_vpi)
+{
+ struct itree_t *itp2;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[10];
+
+ if (itp == NULL) { itp2 = mdp->moditps[0]; sprintf(s1, "'*' first"); }
+ else { __msg2_blditree(s1, itp); itp2 = itp; }
+ if (from_vpi) strcpy(s4, "VPI_ PLI"); else strcpy(s4, "SDF"); 
+
+ __push_itstk(itp2);
+ __cv_msg(
+  "  %s changed defparam: delay set to (%s) cont. assign at %s in %s\n", s4,
+  __bld_delay_str(s2, ogp->g_du, ogp->g_delrep), __bld_lineloc(s3,
+  cap->casym->syfnam_ind, cap->casym->sylin_cnt), s1);
+ __pop_itstk();
+}
+
+/*
+ * emit changed param new net delay
+ */
+static void emit_reprepnet_verbmsg(struct net_t *np, struct gate_t *ogp,
+ struct mod_t *mdp, struct itree_t *itp, int32 from_vpi)
+{
+ struct itree_t *itp2;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[10];
+
+ if (itp == NULL) { itp2 = mdp->moditps[0]; sprintf(s1, "'*' first"); }
+ else { __msg2_blditree(s1, itp); itp2 = itp; }
+ if (from_vpi) strcpy(s4, "VPI_ PLI"); else strcpy(s4, "SDF"); 
+
+ __push_itstk(itp2);
+ __cv_msg(
+  "  %s changed defparam: delay set to (%s) net %s in %s at %s\n", s4,
+  __bld_delay_str(s2, ogp->g_du, ogp->g_delrep), np->nsym->synam, s1,
+  __bld_lineloc(s3, np->nsym->syfnam_ind, np->nsym->sylin_cnt));
+ __pop_itstk();
+}
+
+/*
+ * emit changed param new statement procedural delay control
+ */
+static void emit_reprepstmt_verbmsg(struct st_t *stp, struct gate_t *ogp,
+ struct mod_t *mdp, struct itree_t *itp, int32 from_vpi)
+{
+ struct itree_t *itp2;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[10];
+
+ if (itp == NULL) { itp2 = mdp->moditps[0]; sprintf(s1, "'*' first"); }
+ else { __msg2_blditree(s1, itp); itp2 = itp; }
+ if (from_vpi) strcpy(s4, "VPI_ PLI"); else strcpy(s4, "SDF"); 
+ __push_itstk(itp2);
+ if (stp != NULL)
+  {
+   __cv_msg(
+    "  %s changed defparam: delay set to (%s) statement at %s in %s\n", s4,
+    __bld_delay_str(s3, ogp->g_du, ogp->g_delrep),
+    __bld_lineloc(s2, stp->stfnam_ind, stp->stlin_cnt), s1);
+  }
+ else
+  {
+   __cv_msg(
+    "  %s changed defparam: delay set to (%s) statement in %s\n", s4,
+    __bld_delay_str(s3, ogp->g_du, ogp->g_delrep), s1);
+  }
+ __pop_itstk();
+}
+
+/*
+ * emit changed param new iopath delay
+ */
+static void emit_reprepiopath_verbmsg(struct spcpth_t *pthp,
+ struct gate_t *ogp, struct mod_t *mdp, struct itree_t *itp, int32 from_vpi)
+{
+ struct itree_t *itp2;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[10];
+
+ if (itp == NULL) { itp2 = mdp->moditps[0]; sprintf(s1, "'*' first"); }
+ else { __msg2_blditree(s1, itp); itp2 = itp; }
+ if (from_vpi) strcpy(s4, "VPI_ PLI"); else strcpy(s4, "SDF"); 
+
+ __push_itstk(itp2);
+ __cv_msg("  %s changed specparam: delay set to (%s) path at %s in %s\n", s4,
+  __bld_delay_str(s3, ogp->g_du, ogp->g_delrep), __bld_lineloc(s2,
+  pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt), s1);
+ __pop_itstk();
+}
+
+/*
+ * emit changed param new timing check (either first or 2nd) 
+ */
+static void emit_repreptclim_verbmsg(struct tchk_t *tcp, struct gate_t *ogp,
+ struct mod_t *mdp, struct itree_t *itp, word32 pnptyp, int32 from_vpi)
+{
+ struct itree_t *itp2;
+ char s1[RECLEN], s2[10], s3[RECLEN], s4[RECLEN], s5[10];
+
+ if (itp == NULL) { itp2 = mdp->moditps[0]; sprintf(s1, "'*' first"); }
+ else { __msg2_blditree(s1, itp); itp2 = itp; }
+ if (pnptyp == PNP_TCHKP1) strcpy(s2, ""); else strcpy(s2, " 2nd");
+ if (from_vpi) strcpy(s5, "VPI_ PLI"); else strcpy(s5, "SDF"); 
+
+ __push_itstk(itp2);
+ __cv_msg(
+  "  %s changed specparam:%s limit set to %s for %s timing check at %s in %s\n",
+  s5, s2, __bld_delay_str(s4, ogp->g_du, ogp->g_delrep), __to_tcnam(s3,
+  tcp->tchktyp), __bld_lineloc(s4, tcp->tcsym->syfnam_ind,
+  tcp->tcsym->sylin_cnt), s1);
+ __pop_itstk();
+}
+
+/*
+ * ROUTINES TO PREP DELAYS
+ */
+
+/*
+ * wrapper around prep delay that copies, checks again, and frees
+ *
+ * needed because can change parameters in delay expressions multiple
+ * times so much copy each time fold and check copy (maybe newly wrong) and
+ * use copy for delay expr. but then can change later so need to do again
+ */
+extern void __prep_delay(struct gate_t *gp, struct paramlst_t *dhdr,
+ int32 ispath, int32 is_trireg, char *emsg, int32 mustbeconst, struct sy_t *dsym, 
+ int32 is_spec)
+{
+ register struct paramlst_t *pmp;
+ int32 sav_nowarns, sav_noinforms, sav_lcnt, sav_fnind, sav_ecnt;
+ struct paramlst_t *dhdr2;
+
+ /* any warns or informs already emitted */ 
+ sav_nowarns = __no_warns;
+ sav_noinforms = __no_informs;
+ __no_warns = TRUE;
+ __no_informs = TRUE;
+ sav_lcnt = __slin_cnt;
+ sav_fnind = __sfnam_ind;
+ __sfnam_ind = (int32) dsym->syfnam_ind;
+ __slin_cnt = dsym->sylin_cnt;
+ sav_ecnt = __pv_err_cnt;
+ 
+ dhdr2 = __copy_dellst(dhdr);
+ if (!is_spec) __chk_delparams(dhdr2, emsg, mustbeconst);
+ else
+  {
+   for (pmp = dhdr2; pmp != NULL; pmp = pmp->pmlnxt)
+    { __chk_spec_delay(pmp->plxndp, emsg); }
+  }
+ __no_warns = sav_nowarns;
+ __no_informs = sav_noinforms;
+ __slin_cnt = sav_lcnt;
+ __sfnam_ind = sav_fnind;
+ if (__pv_err_cnt == sav_ecnt) prep2_delay(gp, dhdr2, ispath, is_trireg);
+ __free_dellst(dhdr2);
+}
+
+/*
+ * prepare gate and continuous assignment preprocessed delay arrays
+ * this changes representation for gate del_u field
+ * also used for wire delays
+ *
+ * this routine assumes at least dummy module context set
+ *
+ * know delay list already checked and if error will not get here
+ * also no scaling or conversion from reals performed by fix_nl 
+ *
+ * if is trireg, then know will be exactly 3 values in list 
+ * that are constants
+ *
+ * for path delays only DT_1V and DT_16V forms possible because
+ * of table look up algorithm (user may code 1,2,3,6,12) 
+ */
+static void prep2_delay(struct gate_t *gp, struct paramlst_t *dhdr,
+ int32 ispath, int32 is_trireg)
+{
+ register int32 i;
+ register struct paramlst_t *pmp;
+ int32 nparams, has_xpr, has_is;
+ word64 rise, fall, toz;
+ word64 *dtab, xt[16];
+ struct expr_t *xa[12], *xp1;
+
+ /* DBG remove --
+ extern void __dbg_dump_del(union del_u, word32);
+ --- */
+
+ /* no delays */
+ if (dhdr == NULL) { gp->g_du.d1v = NULL; gp->g_delrep = DT_NONE; return; }
+
+ /* assume no negative delay constant expr. */
+ __nd_neg_del_warn = FALSE;
+
+ /* case 1: one delay special case */
+ /* also 1x form handled here */
+ if (dhdr->pmlnxt == NULL)
+  {
+   xp1 = dhdr->plxndp;
+   prep_1delform(gp, xp1);
+   /* trireg 1 value must be converted to 4v since need special toz decay */
+   if (is_trireg) convert_trireg_1vto4v(gp); 
+   goto done;
+  }
+
+ /* figure out representation needed */
+ has_xpr = FALSE;
+ has_is = FALSE;
+ for (pmp = dhdr, nparams = 0; pmp != NULL; pmp = pmp->pmlnxt, nparams++)
+  {
+   xa[nparams] = pmp->plxndp;
+   switch ((byte) xa[nparams]->optyp) {
+    case NUMBER: case REALNUM: break;
+    case ISNUMBER: case ISREALNUM: has_is = TRUE; break;
+    default: has_xpr = TRUE;
+   }  
+  }
+
+ /* case 2: has expression - cannot be path case */
+ if (has_xpr)
+  {
+   /* DBG remove --- */
+   if (ispath) __arg_terr(__FILE__, __LINE__);
+   /* -- */
+
+   /* if at least one expr, all must evaluate at run time - leave xpr */
+   gp->g_du.d4x = (struct expr_t **) __my_malloc(4*sizeof(struct expr_t *));
+   /* since indexing by new 2 bit value order is f, r, z, x */
+   gp->g_du.d4x[0] = __copy_expr(xa[1]);
+   /* must fold all of these this is point where copy is fixed (elaborated) */
+   gp->g_du.d4x[1] = __copy_expr(xa[0]);
+   if (nparams == 2) gp->g_du.d4x[2] = NULL;
+   else 
+    {
+     gp->g_du.d4x[2] = __copy_expr(xa[2]);
+    }
+   gp->g_du.d4x[3] = NULL;
+   gp->g_delrep = DT_4X;
+   goto done;
+  }
+ 
+ /* case 3: IS form more than 1 val (if any IS all must be) */
+ if (has_is)
+  {
+   if (ispath) prep_path_is_dels(gp, xa, nparams);
+   else prep_prim_is_dels(gp, xa, nparams, is_trireg); 
+   goto done;
+  }
+
+ /* case 4a: non IS path form and more than 1 value */
+ /* here must be 16V form */
+ if (ispath)
+  {
+   /* first evaluate expr., prep. constant delay form */
+   for (i = 0; i < nparams; i++) nonis_to_delval(&(xt[i]), xa[i]);
+
+   dtab = (word64 *) __my_malloc(16*sizeof(word64));
+   /* know not 1 value but can be no convert to number 2,3,6, or 12 */
+   __fill_16vconst(dtab, xt, nparams);
+   gp->g_du.d16v = dtab;
+   gp->g_delrep = DT_16V;
+   goto done;
+  }
+ /* case 4b: non IS primitive form */
+ /* DBG remove ---
+ if (nparams > 3) __arg_terr(__FILE__, __LINE__);  
+ --- */
+ dtab = (word64 *) __my_malloc(4*sizeof(word64));
+ /* fill the 3 values with scaled ticks */
+ nonis_to_delval(&rise, xa[0]);
+ nonis_to_delval(&fall, xa[1]);
+ if (nparams == 2) toz = 0ULL; else nonis_to_delval(&toz, xa[2]);
+ /* this handles special processing for tri reg if needed */
+ __fill_4vconst(dtab, &rise, &fall, &toz, nparams, is_trireg);
+ gp->g_du.d4v = dtab;
+ gp->g_delrep = DT_4V;
+
+done:;
+ /* --- DBG remove
+ if (__debug_flg) __dbg_dump_del(gp->g_du, gp->g_delrep);
+ --- */ 
+}
+
+/*
+ * convert 1 non is form to a delay value
+ * this takes a num expression checked else so is only for delay prep.
+ */
+static void nonis_to_delval(word64 *ticksval, struct expr_t *xp)
+{
+ double *dp, d1;
+ word32 *wp;
+ word64 delval;
+
+ if (xp->optyp == REALNUM)
+  {
+   dp = (double *) &(__contab[xp->ru.xvi]);
+   d1 = *dp;
+   if (d1 < 0.0)
+    {
+neg_del:
+     *ticksval = 0ULL;
+     __nd_neg_del_warn = TRUE;
+     return;
+    }
+   real_to_ticks(ticksval, d1, __inst_mod);
+   return;
+  }
+ wp = &(__contab[xp->ru.xvi]);
+ delval = (word64) wp[0];
+ /* * SJM 08/17/04 - now any value can be signed - need warning */
+ if (xp->szu.xclen > WBITS)
+  {
+   if (__is_lnegative(wp, xp->szu.xclen)) goto neg_del; 
+   delval |= (((word64) wp[1]) << 32);
+  }
+ else
+  {
+   if (xp->has_sign && (wp[0] & (1 << (xp->szu.xclen - 1))) != 0)
+    goto neg_del;
+  }
+ if (!__inst_mod->mno_unitcnv)
+  cnv_num64to_ticks_(*ticksval, delval, __inst_mod);
+ else *ticksval = delval;
+}
+
+/*
+ * free one delay - lots of forms
+ * union is 4 bytes in record, so do not need to free union
+ * this is for after preparation freeing
+ */
+extern void __free_del(union del_u du, word32 drep, int32 numinsts)
+{
+ register int32 i;
+
+ switch ((byte) drep) {
+  case DT_1V:
+   __my_free((char *) du.d1v, sizeof(word64));
+   break;
+  case DT_IS1V:
+   __my_free((char *) du.dis1v, numinsts*sizeof(word64));
+   break;
+  case DT_IS1V1:
+   __my_free((char *) du.dis1v1, numinsts);
+   break;
+  case DT_IS1V2:
+   __my_free((char *) du.dis1v2, 2*numinsts);
+   break;
+  case DT_4V:
+   __my_free((char *) du.d4v, 4*sizeof(word64));
+   break;
+  case DT_IS4V:
+   __my_free((char *) du.dis4v, 4*numinsts*sizeof(word64));
+   break;
+  case DT_IS4V1:
+   __my_free((char *) du.dis4v1, 4*numinsts);
+   break;
+  case DT_IS4V2:
+   __my_free((char *) du.dis4v2, 4*2*numinsts);
+   break;
+  case DT_16V: __my_free((char *) du.d16v, 16*sizeof(word64)); break;
+  case DT_IS16V:
+   __my_free((char *) du.dis16v, 16*numinsts*sizeof(word64));
+   break;
+  case DT_IS16V1:
+   __my_free((char *) du.dis16v1, 16*numinsts);
+   break;
+  case DT_IS16V2:
+   __my_free((char *) du.dis16v2, 16*2*numinsts);
+   break;
+  case DT_1X:
+   __free_xtree(du.d1x);
+   break;
+  case DT_4X:
+   /* notice this is array of 4 expression pointers (ptr to ptrs) */
+   for (i = 0; i < 3; i++) __free_xtree(du.d4x[i]);
+   __my_free((char *) du.d4x, 4*sizeof(struct expr_t *));
+   break;
+  case DT_CMPLST:
+   __free_dellst(du.pdels);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * free a delay parameter list
+ */
+extern void __free_dellst(struct paramlst_t *dhdr)
+{
+ register struct paramlst_t *pmp;
+ struct paramlst_t *pmp2;
+
+ for (pmp = dhdr; pmp != NULL;)
+  {
+   pmp2 = pmp;
+   pmp = pmp2->pmlnxt;
+   __free_xtree(pmp2->plxndp);
+   __my_free((char *) pmp2, sizeof(struct paramlst_t));
+  }
+}
+
+/*
+ * prepare all 1 delay value cases
+ */
+static void prep_1delform(struct gate_t *gp, struct expr_t *xp1)
+{
+ register int32 ii;
+ int32 minsiz, nbytes;
+ word32 *wp, *wp2, w1;
+ double d1, *dp;
+ word64 *dtab, *dtab2, ticksval, delval;
+
+ dtab = NULL;
+ /* know both double and 64 bit time take 8 bytes dependent */
+ nbytes = sizeof(word64)*__inst_mod->flatinum;     
+ switch ((byte) xp1->optyp) {
+  case NUMBER:
+  case REALNUM:
+   nonis_to_delval(&ticksval, xp1);
+   gp->g_du.d1v = (word64 *) __my_malloc(sizeof(word64));
+   *(gp->g_du.d1v) = ticksval;
+   gp->g_delrep = DT_1V;
+   break;
+  case ISNUMBER:
+   /* this is common because of back annotation for gate arrays */
+   /* step 1 build the 8 byte case */
+   /* LOOKATME - can dtab not be nil? */
+   if (dtab == NULL) dtab = (word64 *) __my_malloc(nbytes);
+   /* notice never x/z delays by here no matter what */
+   if (xp1->szu.xclen > WBITS)
+    {
+     wp = &(__contab[xp1->ru.xvi]); 
+     for (ii = 0; ii < __inst_mod->flatinum; ii++)
+      {
+       /* SJM 08/17/04 - now any value can be signed - need warning */
+       if (__is_lnegative(wp, xp1->szu.xclen)) 
+        {
+         __nd_neg_del_warn = TRUE;
+         dtab[ii] = 0ULL;
+         continue;
+        }
+       dtab[ii] = ((word64) wp[2*ii]) | (((word64) wp[2*ii + 1]) << 32);
+       if (!__inst_mod->mno_unitcnv)
+	{
+         delval = dtab[ii];
+         cnv_num64to_ticks_(dtab[ii], delval, __inst_mod);
+        }
+      }
+    }
+   else
+    {
+     wp = &(__contab[xp1->ru.xvi]); 
+     for (ii = 0; ii < __inst_mod->flatinum; ii++)
+      {
+       wp2 = &(wp[2*ii]);
+
+       /* SJM 08/17/04 - now any value can be signed - need warning */
+       if (xp1->has_sign && (wp2[0] & (1 << (xp1->szu.xclen - 1))) != 0)
+        {
+         __nd_neg_del_warn = TRUE;
+         dtab[ii] = 0ULL;
+         continue;
+        }
+
+       dtab[ii] = (word64) wp2[0];
+       if (!__inst_mod->mno_unitcnv)
+	{
+         delval = dtab[ii];
+         cnv_num64to_ticks_(dtab[ii], delval, __inst_mod);
+        }
+      }
+    }
+try_narrow:
+   /* next determine if can be smaller - assume all fit in 1 byte */
+   for (minsiz = 1, ii = 0; ii < __inst_mod->flatinum; ii++)
+    {
+     if (dtab[ii] > WORDMASK_ULL) { minsiz = 8; break; }
+     w1 = (word32) (dtab[ii] & WORDMASK_ULL);
+     if ((w1 & 0xffffff00L) == 0L) continue;
+     if ((w1 & 0xffff0000L) == 0L) { minsiz = 2; continue; }
+    }
+   if (minsiz > 2)
+    {
+     dtab2 = (word64 *) __my_malloc(nbytes);
+     memcpy(dtab2, dtab, nbytes);
+
+     gp->g_du.dis1v = dtab2;
+     gp->g_delrep = DT_IS1V;
+     break;
+    }
+   if (minsiz == 1)
+    {
+     gp->g_du.dis1v1 = (byte *) __my_malloc(__inst_mod->flatinum);
+     for (ii = 0; ii < __inst_mod->flatinum; ii++)
+      gp->g_du.dis1v1[ii] = (byte) dtab[ii]; 
+     gp->g_delrep = DT_IS1V1;
+    }
+   else 
+    {
+     gp->g_du.dis1v2 = (hword *) __my_malloc(2*__inst_mod->flatinum);
+     for (ii = 0; ii < __inst_mod->flatinum; ii++)
+      gp->g_du.dis1v2[ii] = (hword) dtab[ii]; 
+     gp->g_delrep = DT_IS1V2;
+    }
+   break;
+  case ISREALNUM: 
+   /* here if value too big - silently truncates to mod 64 bits */
+   if (dtab == NULL) dtab = (word64 *) __my_malloc(nbytes);
+   dp = (double *) &(__contab[xp1->ru.xvi]);
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    {
+     /* for reals know fits and non x/z but must scale before conversion */
+     d1 = dp[ii];
+     if (d1 < 0.0) { dtab[ii] = 0ULL; __nd_neg_del_warn = TRUE; }
+     else
+      { 
+       real_to_ticks(&ticksval, d1, __inst_mod);
+       dtab[ii] = ticksval;
+      } 
+    }
+   goto try_narrow;
+  default:
+   /* expr. that must be evaluated each time */
+   /* must copy since delay parm list including expr. will be freed */
+   gp->g_du.d1x = __copy_expr(xp1); 
+   gp->g_delrep = DT_1X;
+  }
+ if (dtab != NULL) __my_free((char *) dtab, nbytes);
+}
+
+/*
+ * for trireg convert 1v or is1v forms to 4v or is4v 
+ */
+static void convert_trireg_1vto4v(struct gate_t *gp)
+{
+ register int32 ii;
+ int32 ninsts;
+ word64 *dtab;
+ byte *btab;
+ hword *htab;
+
+ ninsts = __inst_mod->flatinum;
+ switch ((byte) gp->g_delrep) {
+  case DT_1V:
+   dtab = gp->g_du.d4v;
+   gp->g_du.d4v = (word64 *) __my_malloc(4*sizeof(word64));
+   gp->g_du.d4v[0] = dtab[0];
+   gp->g_du.d4v[1] = dtab[0];
+   gp->g_du.d4v[3] = dtab[0];
+   gp->g_du.d4v[2] = 0ULL;
+   __my_free((char *) dtab, sizeof(word64));
+   break;
+  case DT_IS1V:
+   dtab = gp->g_du.dis1v;
+   gp->g_du.dis4v = (word64 *) __my_malloc(4*ninsts*sizeof(word64));
+   for (ii = 0; ii < ninsts; ii++) 
+    {
+     gp->g_du.dis4v[4*ii] = dtab[ii];
+     gp->g_du.dis4v[4*ii + 1] = dtab[ii]; 
+     gp->g_du.dis4v[4*ii + 3] = dtab[ii]; 
+     gp->g_du.dis4v[4*ii + 2] = 0ULL;
+    }
+   __my_free((char *) dtab, ninsts*sizeof(word64));
+   break;
+  case DT_IS1V1:
+   btab = gp->g_du.dis1v1;
+   gp->g_du.dis4v1 = (byte *) __my_malloc(4*ninsts);
+   for (ii = 0; ii < ninsts; ii++) 
+    {
+     gp->g_du.dis4v1[4*ii] = btab[ii];
+     gp->g_du.dis4v1[4*ii + 1] = btab[ii]; 
+     gp->g_du.dis4v1[4*ii + 3] = btab[ii]; 
+     gp->g_du.dis4v1[4*ii + 2] = 0;
+    }
+   __my_free((char *) btab, 1*ninsts);
+   break;
+  case DT_IS1V2:
+   htab = gp->g_du.dis1v2;
+   gp->g_du.dis4v2 = (hword *) __my_malloc(4*2*ninsts);
+   for (ii = 0; ii < ninsts; ii++) 
+    {
+     gp->g_du.dis4v2[4*ii] = htab[ii];
+     gp->g_du.dis4v2[4*ii + 1] = htab[ii]; 
+     gp->g_du.dis4v2[4*ii + 3] = htab[ii]; 
+     gp->g_du.dis4v2[4*ii + 2] = 0;
+    }
+   __my_free((char *) htab, 2*ninsts);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * fill 4v constant where some values require 64 bit amount
+ * idea is to fill d4v array with delays according to algorithm
+ *
+ * 4v only for primitive and wire delays
+ */
+extern void __fill_4vconst(word64 *dv4, word64 *rise, word64 *fall,
+ word64 *toz, int32 nparams, int32 is_trireg)
+{
+ word64 ltmp;
+
+ /* 4 value array first is fall (destination state as index) */
+ dv4[0] = *fall;
+ dv4[1] = *rise;
+ /* 2 delay case, use minimum for both to-x and to-z */
+ if (nparams == 2)
+  {
+   if (is_trireg)
+    {
+     if (dv4[0] <= dv4[1]) dv4[3] = dv4[0]; else dv4[3] = dv4[1];
+     dv4[2] = 0ULL; 
+    }
+   else
+    {
+     if (dv4[0] <= dv4[1]) dv4[3] = dv4[2] = dv4[0];
+     else dv4[3] = dv4[2] = dv4[1];
+    }
+  }
+ else
+  {
+   dv4[2] = *toz;
+   /* for trireg to x is smallest of rise and fall */ 
+   if (is_trireg)
+    { if (dv4[0] <= dv4[1]) ltmp = dv4[0]; else ltmp = dv4[1]; }
+   else
+    {
+     /* index 3 (to-x) is minimum of all 3 */
+     if (dv4[0] <= dv4[1] && dv4[0] <= dv4[2]) ltmp = dv4[0];
+     else
+      { if (dv4[1] < dv4[2]) ltmp = dv4[1]; else ltmp = dv4[2]; }
+    }
+   dv4[3] = ltmp;
+  }
+ /* LOOKATME */
+ /* form LRM for wider than 1 cont. assign, v[0] is to-0, v[1] is other */
+ /* and v[3] is to-z */
+ /* according to LRM this should be overriden to 1, but OVIsim uses fast */
+ /* as possible to x (wrong just low bit but still uses it */ 
+ /* *** if (lhswid > 1) dv4[3] = dv4[1]; */
+}
+
+/* ---
+12 form: (0->1, 1->0, 0->z, z->1, 1->z, z->0,
+          0->x, x->1, 1->x, x->0, x->z, z->x)  
+0000 --
+0001 1->0 - 1 
+0010 z->0 - 5
+0011 x->0 - 9
+0100 0->1 - 0
+0101 --
+0110 z->1 - 3
+0111 x->1 - 7
+1000 0->z - 2
+1001 1->z - 4
+1010 ---
+1011 x->z - 10
+1100 0->x - 6
+1101 1->x - 8
+1110 z->x - 11
+--- */
+
+/*
+ * fill a 16v table from table of expressions  
+ * know need 16v because specify and nparams 2,3,6, or 12
+ */
+extern void __fill_16vconst(word64 *dtab, word64 *xt, int32 nparams)
+{
+ /* have all values just rearrange into nnoo form */
+ if (nparams == 12)
+  {
+move_to_dtab:
+   /* FIXME - why needed - same value can happen? */
+   dtab[0] = 0ULL; 
+   dtab[5] = dtab[10] = dtab[15] = dtab[0];
+   dtab[1] = xt[1]; dtab[2] = xt[5]; dtab[3] = xt[9]; dtab[4] = xt[0];
+   dtab[6] = xt[3]; dtab[7] = xt[7]; dtab[8] = xt[2]; dtab[9] = xt[4];
+   dtab[11] = xt[10]; dtab[12] = xt[6]; dtab[13] = xt[8];
+   dtab[14] = xt[11];
+   return;
+  }
+
+ /* must convert separately from building nnoo dtab */
+ if (nparams == 2) { xt[2] = xt[3] = xt[0]; xt[4] = xt[5] = xt[1]; }
+ else if (nparams == 3)
+  { 
+   /* 0 thru 2 (rise, fall, toz) good */
+   /* z->1 is rising */
+   xt[3] = xt[0];
+   /* 1->z is toz */
+   xt[4] = xt[2];
+   /* z->0 is falling */
+   xt[5] = xt[1];
+  }
+ /* 6 value case is (0->1, 1->0, 0->z, z->1, 1->z, z->0) */
+
+ /* here know 0-5 values of xt filled - next fill 6-11 x transitions */ 
+ /* 0->x min(0->1, 0->z) */ 
+ xt[6] = (xt[0] < xt[2]) ? xt[0] : xt[2]; 
+ /* 1->x min(1->0, 1->z) */ 
+ xt[8] = (xt[1] < xt[4]) ? xt[1] : xt[4]; 
+ /* z->x min(z->0, z->1) */ 
+ xt[11] = (xt[5] < xt[3]) ? xt[5] : xt[3]; 
+ /* x->0 max(1->0, z->0) */ 
+ xt[9] = (xt[1] > xt[5]) ? xt[1] : xt[5]; 
+ /* x->1 max(z->1, 0->1) */ 
+ xt[7] = (xt[3] > xt[0]) ? xt[3] : xt[0]; 
+ /* x->z max(1->z, 0->z) */ 
+ xt[10] = (xt[4] > xt[2]) ? xt[4] : xt[2]; 
+ goto move_to_dtab;
+}
+
+/*
+ * handle the primitive non path IS 2v and 3v cases
+ * this always builds an IS4V table
+ */
+static void prep_prim_is_dels(struct gate_t *gp, struct expr_t **xa,
+ int32 nparams, int32 is_trireg)
+{ 
+ register int32 ii;
+ int32 minsiz, nbytes;
+ word32 w1;
+ byte *btab;
+ hword *htab;
+ word64 ticksval;
+ word64 *dtab, *dtab2;
+
+ if (nparams > 3) __arg_terr(__FILE__, __LINE__);
+
+ /* if some NUBMER and some IS then all must be IS */
+ nbytes = 4*sizeof(word64)*__inst_mod->flatinum;
+ dtab = (word64 *) __my_malloc(nbytes);
+ fill_1col_isdel(dtab, 0, xa[0], 4);
+ fill_1col_isdel(dtab, 1, xa[1], 4);
+ /* if 3 fill column, if 2 zero toz column */
+ if (nparams == 3) fill_1col_isdel(dtab, 2, xa[2], 4);
+ else
+  {
+   ticksval = 0ULL;
+   for (ii = 0; ii < __inst_mod->flatinum; ii++) dtab[4*ii + 2] = ticksval;
+  } 
+ gp->g_delrep = DT_IS4V;
+ /* arrange 4 values table for look up - applies missing values rules */  
+ /* to each row of IS form column */ 
+ for (ii = 0; ii < __inst_mod->flatinum; ii++)
+  {
+   __fill_4vconst(&(dtab[4*ii]), &(dtab[4*ii]), &(dtab[4*ii + 1]),
+    &(dtab[4*ii + 2]), nparams, is_trireg); 
+  }
+
+ /* now know inum by 4 table filled */
+ /* attempt to change form */
+ for (minsiz = 1, ii = 0; ii < 4*__inst_mod->flatinum; ii++) 
+  {
+   if (dtab[ii] > WORDMASK_ULL) { minsiz = 8; break; }
+   w1 = (word32) (dtab[ii] & WORDMASK_ULL);
+   if ((w1 & 0xffffff00) == 0L) continue;
+   if ((w1 & 0xffff0000) == 0L) { minsiz = 2; continue; }
+  }
+ if (minsiz > 2)
+  {
+   dtab2 = (word64 *) __my_malloc(nbytes);
+   memcpy(dtab2, dtab, nbytes);
+   gp->g_du.dis4v = dtab2;
+   gp->g_delrep = DT_IS4V;
+   goto done;
+  }
+
+ if (minsiz == 1)
+  {
+   btab = (byte *) __my_malloc(4*__inst_mod->flatinum);
+   for (ii = 0; ii < 4*__inst_mod->flatinum; ii++)
+    btab[ii] = (byte) dtab[ii];
+   gp->g_du.dis4v1 = btab;
+   gp->g_delrep = DT_IS4V1;
+  }
+ else 
+  {
+   htab = (hword *) __my_malloc(4*2*__inst_mod->flatinum);
+   for (ii = 0; ii < 4*__inst_mod->flatinum; ii++)
+    htab[ii] = (hword) dtab[ii];
+   gp->g_du.dis4v2 = htab;
+   gp->g_delrep = DT_IS4V2;
+  }
+done:
+ __my_free((char *) dtab, nbytes);
+}
+
+/*
+ * prep the IS 16 value (4 bit change table look up) forms
+ * know 1 delay case handled elsewhere (do not need 16V) 
+ *
+ *
+ * possibilities are 2, 3, 6, 12
+ * dtab is 16 by flatinum table (need 0 delays for strength only change)
+ */
+static void prep_path_is_dels(struct gate_t *gp, struct expr_t **xa,
+ int32 nparams)
+{
+ register int32 ii;
+ int32 minsiz, nbytes;
+ byte *btab;
+ hword *htab;
+ word32 w1;
+ word64 tim1, tim2;
+ word64 *dtab, *dtab2;
+
+ /* build big enough table */
+ nbytes = 16*sizeof(word64)*__inst_mod->flatinum;
+ dtab = (word64 *) __my_malloc(nbytes);
+ /* have 16 columns to fill */
+
+ /* step 1: zero entire table */
+ memset((char *) dtab, 0, nbytes);
+ /* case 1: 12 (all except for 3 unused coded) */
+ if (nparams == 12)
+  {
+   fill_1col_isdel(dtab, 1, xa[1], 16);
+   fill_1col_isdel(dtab, 2, xa[5], 16);
+   fill_1col_isdel(dtab, 3, xa[9], 16);
+   fill_1col_isdel(dtab, 4, xa[0], 16);
+   fill_1col_isdel(dtab, 6, xa[3], 16);
+   fill_1col_isdel(dtab, 7, xa[7], 16);
+   fill_1col_isdel(dtab, 8, xa[2], 16);
+   fill_1col_isdel(dtab, 9, xa[4], 16);
+   fill_1col_isdel(dtab, 11, xa[10], 16);
+   fill_1col_isdel(dtab, 12, xa[6], 16);
+   fill_1col_isdel(dtab, 13, xa[8], 16);
+   fill_1col_isdel(dtab, 14, xa[11], 16);
+   goto minimize;
+  }
+
+ /* case 2: 6 coded delays */
+ if (nparams == 6)
+  {
+   fill_1col_isdel(dtab, 4, xa[0], 16);
+   fill_1col_isdel(dtab, 1, xa[1], 16);
+   fill_1col_isdel(dtab, 8, xa[2], 16);
+   fill_1col_isdel(dtab, 6, xa[3], 16);
+   fill_1col_isdel(dtab, 9, xa[4], 16);
+   fill_1col_isdel(dtab, 2, xa[5], 16);
+  }
+ /* case 3: handle similar 2 and 3 value case */
+ /* dtab is 16 position nnoo index form */ 
+ /* for 2,3 and 6 cases first fill dtab 6 transitions not involving x */
+ else if (nparams == 2)
+  {
+   /* first of 2 is all rising transitions */
+   /* fill dtab[4] - xa[0] (0->1) */
+   fill_1col_isdel(dtab, 4, xa[0], 16);
+   /* fill dtab[8] - xa[2] (0->z) */
+   /* fill dtab[6] - xa[3] (z->1) */
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    dtab[16*ii + 8] = dtab[16*ii + 6] = dtab[16*ii + 4];
+
+   /* 2nd of 2 is all falling transitions */
+   /* fill dtab[1] - xa[1] (1->0) */
+   fill_1col_isdel(dtab, 1, xa[1], 16);
+   /* fill dtab[9] - xa[4] (1->z) */
+   /* fill dtab[2] - xa[5] (z->0) */
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    dtab[16*ii + 9] = dtab[16*ii + 2] = dtab[16*ii + 1];
+  }
+ else if (nparams == 3)
+  {
+   /* rising of 3 */
+   /* fill dtab[4] - xa[0] (0->1) */
+   fill_1col_isdel(dtab, 4, xa[0], 16);
+   /* fill dtab[6] - xa[3] (0->1) */
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    dtab[16*ii + 6] = dtab[16*ii + 4];
+
+   /* falling of 3 */
+   /* fill dtab[1] - xa[1] (1->0) */
+   fill_1col_isdel(dtab, 1, xa[1], 16);
+   /* fill dtab[2] - xa[5] (z->0) */
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    dtab[16*ii + 2] = dtab[16*ii + 1];
+
+   /* to z */
+   /* fill dtab[8] - xa[2] (0->z) */
+   fill_1col_isdel(dtab, 8, xa[2], 16);
+   /* fill dtab[9] - xa[4] (1->z) */
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    dtab[16*ii + 9] = dtab[16*ii + 8];
+  }
+ /* next row by row (per inst.) */
+ for (ii = 0; ii < __inst_mod->flatinum; ii++)
+  {
+   /* dtab columns for low 6 filled by here */
+   /* 0->x min(0->1, 0->z) */ 
+   tim1 = dtab[16*ii + 4];
+   tim2 = dtab[16*ii + 8];
+   dtab[16*ii + 12] = (tim1 < tim2) ? tim1 : tim2;
+   /* 1->x min(1->0, 1->z) */ 
+   tim1 = dtab[16*ii + 1];
+   tim2 = dtab[16*ii + 9];
+   dtab[16*ii + 13] = (tim1 < tim2) ? tim1 : tim2;
+   /* z->x min(z->0, z->1) */ 
+   tim1 = dtab[16*ii + 2];
+   tim2 = dtab[16*ii + 6];
+   dtab[16*ii + 14] = (tim1 < tim2) ? tim1 : tim2;
+   /* x->0 max(1->0, z->0) */ 
+   tim1 = dtab[16*ii + 1];
+   tim2 = dtab[16*ii + 2];
+   dtab[16*ii + 3] = (tim1 > tim2) ? tim1 : tim2; 
+   /* x->1 max(z->1, 0->1) */ 
+   tim1 = dtab[16*ii + 6];
+   tim2 = dtab[16*ii + 4];
+   dtab[16*ii + 7] = (tim1 > tim2) ? tim1 : tim2; 
+   /* x->z max(1->z, 0->z) */ 
+   tim1 = dtab[16*ii + 9];
+   tim2 = dtab[16*ii + 8];
+   dtab[16*ii + 11] = (tim1 > tim2) ? tim1 : tim2; 
+  }
+
+ /* now know inum by 16 table filled */
+ /* attempt to change form */
+minimize:
+ for (minsiz = 1, ii = 0; ii < 16*__inst_mod->flatinum; ii++) 
+  {
+   if (dtab[ii] > WORDMASK_ULL) { minsiz = 8; break; }
+   w1 = (word32) (dtab[ii] & WORDMASK_ULL);
+   if ((w1 & 0xffffff00) == 0L) continue;
+   if ((w1 & 0xffff0000) == 0L) { minsiz = 2; continue; }
+  }
+ if (minsiz > 2)
+  {
+   dtab2 = (word64 *) __my_malloc(nbytes);
+   memcpy(dtab2, dtab, nbytes);
+   gp->g_du.dis16v = dtab2;
+   gp->g_delrep = DT_IS16V;
+   goto done;
+  }
+
+ if (minsiz == 1)
+  {
+   btab = (byte *) __my_malloc(16*__inst_mod->flatinum);
+   for (ii = 0; ii < 16*__inst_mod->flatinum; ii++)
+    btab[ii] = (byte) dtab[ii];
+   gp->g_du.dis16v1 = btab;
+   gp->g_delrep = DT_IS16V1;
+  }
+ else 
+  {
+   htab = (hword *) __my_malloc(16*2*__inst_mod->flatinum);
+   for (ii = 0; ii < 16*__inst_mod->flatinum; ii++)
+    htab[ii] = (hword) dtab[ii];
+   gp->g_du.dis16v2 = htab;
+   gp->g_delrep = DT_IS16V2;
+  }
+done: 
+ __my_free((char *) dtab, nbytes);
+}
+
+/*
+ * fill one column of the flatinum deep delay table
+ */
+static void fill_1col_isdel(word64 *dtab, int32 coli, struct expr_t *xp,
+ int32 stride)
+{
+ register int32 ii;
+ word32 *wp;
+ word64 ticksval, delval;
+ double d1, *dp;
+
+ switch ((byte) xp->optyp) {
+  case REALNUM:
+  case NUMBER:
+   nonis_to_delval(&ticksval, xp);
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    dtab[stride*ii + coli] = ticksval;
+   break;
+  case ISREALNUM:
+   dp = (double *) &(__contab[xp->ru.xvi]);
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    {
+     d1 = dp[ii];
+     if (d1 < 0.0)
+      {
+       ticksval = 0ULL;
+       __nd_neg_del_warn = TRUE;
+      }
+     else real_to_ticks(&ticksval, d1, __inst_mod);
+     dtab[stride*ii + coli] = ticksval;
+    }
+   break;
+  case ISNUMBER:
+   if (xp->szu.xclen > WBITS)
+    {
+     wp = &(__contab[xp->ru.xvi]);
+     for (ii = 0; ii < __inst_mod->flatinum; ii++)
+      {
+       /* SJM 08/17/04 - now for ver 2001 any width can be signed */
+       if (__is_lnegative(wp, xp->szu.xclen))
+        {
+         __nd_neg_del_warn = TRUE;
+         ticksval = 0ULL;
+        }
+       else
+        {
+         ticksval = ((word64) wp[2*ii]) | (((word64) wp[2*ii + 1]) << 32);
+         if (!__inst_mod->mno_unitcnv)
+	  {
+           delval = ticksval;
+           cnv_num64to_ticks_(ticksval, delval, __inst_mod);
+          }
+        }
+       dtab[stride*ii + coli] = ticksval;
+      }
+    }
+   else
+    {
+     wp = &(__contab[xp->ru.xvi]);
+     for (ii = 0; ii < __inst_mod->flatinum; ii++)
+      {
+       ticksval = (word64) wp[2*ii];
+
+       /* SJM 08/17/04 - now for ver 2001 any width can be signed */
+       if (xp->has_sign && (wp[0] & (1 << (xp->szu.xclen - 1))) != 0)
+        {
+         ticksval = 0ULL;
+         __nd_neg_del_warn = TRUE;
+        }
+       else if (!__inst_mod->mno_unitcnv)
+	{
+         delval = ticksval;
+         cnv_num64to_ticks_(ticksval, delval, __inst_mod);
+        }
+       dtab[stride*ii + coli] = ticksval;
+      }
+    }
+   break;
+   default: __case_terr(__FILE__, __LINE__);
+  }
+}
+
+/*
+ * DELAY REPRESENTATION CHANGE ROUTINES 
+ */
+
+/*
+ * change one instance delay form
+ *
+ * this merges the 1 inst into IS form
+ * know new delay is not IS form since for 1 instance
+ * this does not need itree loc. on itree stack uses passed value
+ */
+extern void __chg_1inst_del(struct gate_t *mgp, struct itree_t *mastitp,
+ struct gate_t *ngp)
+{
+ switch ((byte) ngp->g_delrep) {
+  case DT_1V: chg1vform_1instdel(mgp, mastitp, ngp); break;
+  case DT_4V: chg4vform_1instdel(mgp, mastitp, ngp); break;
+  case DT_16V: chg16vform_1instdel(mgp, mastitp, ngp); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * change one instance delay form when new is DT_1V form
+ * know mgp always is form after here
+ * can be called from any form either prim or path delay
+ */
+static void chg1vform_1instdel(struct gate_t *mgp, struct itree_t *mastitp,
+ struct gate_t *ngp)
+{
+ register int32 i;
+ int32 numinsts, tmp, mwid;
+ word64 ntim[16], mtim[16];
+
+ numinsts = mastitp->itip->imsym->el.emdp->flatinum;
+ ntim[0] = ngp->g_du.d1v[0];
+ switch ((byte) mgp->g_delrep) {
+  case DT_1V:
+   /* if values same, nothing to do */
+   mtim[0] = mgp->g_du.d1v[0];
+   if (mtim[0] == ntim[0]) break;
+
+   __my_free((char *) mgp->g_du.d1v, sizeof(word64));
+   /* attempt to store in packed form */
+   mwid = get_ispack(ntim[0]);
+   tmp = get_ispack(mtim[0]);
+   if (tmp > mwid) mwid = tmp;
+   create_disv(mgp, numinsts, 1, mtim, mwid);
+   /* set the new value */
+   set_1is1val(mgp, mastitp->itinum, 1, ntim, mwid);
+   break;
+  case DT_4V:
+   for (i = 0; i < 4; i++) mtim[i] = mgp->g_du.d4v[i];
+   for (i = 0; i < 4; i++) { if (mtim[i] != ntim[0]) goto nd_is4v; }
+   break;
+nd_is4v:  
+   __my_free((char *) mgp->g_du.d4v, 4*sizeof(word64));
+   mwid = get_ispack(ntim[0]);
+   for (i = 0; i < 4; i++) 
+    { tmp = get_ispack(mtim[i]); if (tmp > mwid) mwid = tmp; }
+   create_disv(mgp, numinsts, 4, mtim, mwid);
+   set_1is1val(mgp, mastitp->itinum, 4, ntim, mwid);
+   break;
+  case DT_16V: 
+   for (i = 0; i < 16; i++) mtim[i] = mgp->g_du.d16v[i];
+   for (i = 1; i < 16; i++)
+    {
+     if (i == 5 || i == 10 || i == 15) continue;  
+     if (mtim[i] != ntim[0]) goto nd_is16v;
+    }
+   break;
+nd_is16v:  
+   __my_free((char *) mgp->g_du.d16v, 16*sizeof(word64));
+   mwid = get_ispack(ntim[0]);
+   for (i = 1; i < 16; i++) 
+    {
+     if (i == 5 || i == 10 || i == 15) continue;
+     tmp = get_ispack(mtim[i]);
+     if (tmp > mwid) mwid = tmp;
+    }
+   create_disv(mgp, numinsts, 16, mtim, mwid);
+   set_1is1val(mgp, mastitp->itinum, 16, ntim, mwid);
+   break;
+  case DT_IS1V: 
+   mgp->g_du.dis1v[mastitp->itinum] = ntim[0];
+   /* slight possibility that could now narrow but rare */
+   break;
+  case DT_IS1V1: 
+   mwid = get_ispack(ntim[0]); 
+   if (mwid == 1)
+    { mgp->g_du.dis1v1[mastitp->itinum] = (byte) ntim[0]; break; }
+   if (mwid == 2) 
+    {
+     unpack_isv1_to_isv2(mgp, numinsts, 1);
+     mgp->g_du.dis1v2[mastitp->itinum] = (hword) ntim[0];
+     break;
+    }
+   unpack_isv1_to_isv(mgp, numinsts, 1);
+   mgp->g_du.dis1v[mastitp->itinum] = ntim[0];
+   break;
+  case DT_IS1V2:
+   mwid = get_ispack(ntim[0]); 
+   if (mwid < 8) mgp->g_du.dis1v2[mastitp->itinum] = (hword) ntim[0];
+   else
+    {
+     unpack_isv2_to_isv(mgp, numinsts, 1);
+     mgp->g_du.dis1v[mastitp->itinum] = ntim[0];
+    }
+   break;
+  case DT_IS4V:
+   for (i = 0; i < 4; i++) mgp->g_du.dis4v[4*mastitp->itinum + i] = ntim[0];
+   /* slight possibility that could now narrow but rare */
+   break;
+  case DT_IS4V1: 
+   mwid = get_ispack(ntim[0]); 
+   if (mwid == 1)
+    {
+     for (i = 0; i < 4; i++)
+      mgp->g_du.dis4v1[4*mastitp->itinum + i] = (byte) ntim[0];
+     break;
+    }
+   if (mwid == 2) 
+    {
+     unpack_isv1_to_isv2(mgp, numinsts, 4);
+     for (i = 0; i < 4; i++)
+      mgp->g_du.dis4v2[4*mastitp->itinum + i] = (hword) ntim[0];
+     break;
+    }
+   unpack_isv1_to_isv(mgp, numinsts, 4);
+   for (i = 0; i < 4; i++)
+    mgp->g_du.dis4v[4*mastitp->itinum + i] = ntim[0];
+   break;
+  case DT_IS4V2:
+   mwid = get_ispack(ntim[0]); 
+   if (mwid < 8)
+    {
+     for (i = 0; i < 4; i++)
+      mgp->g_du.dis4v2[4*mastitp->itinum + i] = (hword) ntim[0];
+    }
+   else
+    {
+     unpack_isv2_to_isv(mgp, numinsts, 4);
+     for (i = 0; i < 4; i++)
+      mgp->g_du.dis4v[4*mastitp->itinum + i] = ntim[0];
+    }
+   break;
+  case DT_IS16V:
+   for (i = 0; i < 16; i++)
+    mgp->g_du.dis16v[16*mastitp->itinum + i] = ntim[0];
+   zero_unused_16v(&(mgp->g_du.dis16v[16*mastitp->itinum]));
+   /* slight possibility that could now narrow but rare */
+   break;
+  case DT_IS16V1: 
+   mwid = get_ispack(ntim[0]); 
+   if (mwid == 1)
+    {
+     for (i = 0; i < 16; i++)
+      {
+       if (i == 0 || i == 5 || i == 10 || i == 15)  
+        { mgp->g_du.dis16v1[16*mastitp->itinum + i] = 0; continue; } 
+       mgp->g_du.dis16v1[16*mastitp->itinum + i] = (byte) ntim[0];
+      }
+     break;
+    }
+   if (mwid == 2) 
+    {
+     unpack_isv1_to_isv2(mgp, numinsts, 16);
+     for (i = 0; i < 16; i++)
+      {
+       if (i == 0 || i == 5 || i == 10 || i == 15)  
+        { mgp->g_du.dis16v2[16*mastitp->itinum + i] = 0; continue; } 
+       mgp->g_du.dis16v2[16*mastitp->itinum + i] = (hword) ntim[0];
+      }
+     break;
+    }
+   unpack_isv1_to_isv(mgp, numinsts, 16);
+   for (i = 0; i < 16; i++)
+    mgp->g_du.dis16v[16*mastitp->itinum + i] = ntim[0];
+   zero_unused_16v(&(mgp->g_du.dis16v[16*mastitp->itinum]));
+   break;
+  case DT_IS16V2:
+   mwid = get_ispack(ntim[0]); 
+   if (mwid < 8)
+    {
+     for (i = 0; i < 16; i++)
+      {
+       if (i == 0 || i == 5 || i == 10 || i == 15)  
+        { mgp->g_du.dis16v2[16*mastitp->itinum + i] = 0; continue; } 
+       mgp->g_du.dis16v2[16*mastitp->itinum + i] = (hword) ntim[0];
+      }
+    }
+   else
+    {
+     unpack_isv2_to_isv(mgp, numinsts, 16);
+     for (i = 0; i < 16; i++)
+      mgp->g_du.dis16v[16*mastitp->itinum + i] = ntim[0];
+     zero_unused_16v(&(mgp->g_du.dis16v[16*mastitp->itinum]));
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * routine to set 1 instance of IS form value
+ * here know only 0th element of ntim used since previous known 1 value
+ */
+static void set_1is1val(struct gate_t *gp, int32 iti, int32 nvals, word64 *ntim, 
+ int32 mwid)
+{
+ register int32 i, ivalnum;
+
+ /* set the new value */
+ ivalnum = nvals*iti;
+ if (mwid == 1)
+  {
+   for (i = 0; i < nvals; i++)
+    {
+     if (nvals == 16)
+      {
+       if (i == 0 || i == 5 || i == 10 || i == 15) 
+        gp->g_du.dis16v1[ivalnum + i] = 0;
+       else gp->g_du.dis16v1[ivalnum + i] = (byte) ntim[0];
+      }
+     else gp->g_du.dis4v1[ivalnum + i] = (byte) ntim[0];
+    }
+  }
+ else if (mwid == 8)
+  {
+   for (i = 0; i < nvals; i++) gp->g_du.dis16v[ivalnum + i] = ntim[0];
+   if (nvals == 16) zero_unused_16v(&(gp->g_du.dis16v[ivalnum]));
+  }
+ else
+  {
+   for (i = 0; i < nvals; i++)
+    {
+     if (nvals == 16)
+      {
+       if (i == 0 || i == 5 || i == 10 || i == 15)
+        gp->g_du.dis16v2[ivalnum + i] = 0;
+       else gp->g_du.dis16v2[ivalnum + i] = (hword) ntim[0];
+      }
+     /* since all ptrs to array of hwords use 4v2 form, could use any */
+     else gp->g_du.dis4v2[ivalnum + i] = (hword) ntim[0];
+    }
+  }
+}
+
+/*
+ * change one instance delay form when new is DT_4V form
+ * know old can only be 1v or 4v form since 16v impossible for prim delay
+ */
+static void chg4vform_1instdel(struct gate_t *mgp, struct itree_t *mastitp,
+ struct gate_t *ngp)
+{
+ register int32 i;
+ int32 numinsts, tmp, mwid;
+ word64 ntim[16], mtim[16];
+
+ numinsts = mastitp->itip->imsym->el.emdp->flatinum;
+ for (i = 0; i < 4; i++) ntim[i] = ngp->g_du.d4v[i];
+ switch ((byte) mgp->g_delrep) {
+  case DT_1V:
+   /* new is 4 value, master is 1 value */
+   /* since new is 4v always need at least 4v */
+   mtim[0] = mgp->g_du.d1v[0];
+   /* if all 4 new same as same as 1v, leave 1 v */ 
+   for (i = 0; i < 4; i++) { if (mtim[0] != ntim[i]) goto nd_is1v4v; }
+   break;
+nd_is1v4v:
+   /* duplicate 1 to all of master times */
+   mtim[1] = mtim[2] = mtim[3] = mtim[0];
+   __my_free((char *) mgp->g_du.d1v, sizeof(word64));
+   mwid = get_ispack(mtim[0]);
+   for (i = 0; i < 4; i++)
+    { tmp = get_ispack(ntim[i]); if (tmp > mwid) mwid = tmp; }
+   create_disv(mgp, numinsts, 4, mtim, mwid);
+   set_1is416val(mgp, mastitp->itinum, 4, ntim, mwid);
+   break;
+  case DT_4V:
+   /* master is 4 and new is 4 */
+   for (i = 0; i < 4; i++) mtim[i] = mgp->g_du.d4v[i];
+   for (i = 0; i < 4; i++) { if (mtim[i] != ntim[i]) goto nd_is4v; }
+   break;
+nd_is4v:  
+   __my_free((char *) mgp->g_du.d1v, 4*sizeof(word64));
+   mwid = get_ispack(ntim[0]);
+   for (i = 1; i < 4; i++) 
+    { tmp = get_ispack(ntim[i]); if (tmp > mwid) mwid = tmp; }
+   for (i = 0; i < 4; i++) 
+    { tmp = get_ispack(mtim[i]); if (tmp > mwid) mwid = tmp; }
+   /* notice only difference from 1v here is mtim has 4 different vals */
+   create_disv(mgp, numinsts, 4, mtim, mwid);
+   set_1is416val(mgp, mastitp->itinum, 4, ntim, mwid);
+   break;
+  case DT_IS1V: 
+   /* new is 4 value, master is 1 IS form */
+   /* convert 1 IS to 4 IS */
+   cnv_1is_to_4is(mgp, numinsts, 8, 8); 
+   /* SJM 08/14/01 - was wrongly filling is1v case - other 3 not filled */
+   for (i = 0; i < 4; i++) 
+    mgp->g_du.dis1v[4*mastitp->itinum + i] = ntim[i];
+   /* slight possibility that could now narrow but rare */
+   break;
+  case DT_IS1V1: 
+   /* master is 1 byte 1 value IS and new time is 4v */
+   mwid = get_ispack(ntim[0]); 
+   for (i = 1; i < 4; i++) 
+    { tmp = get_ispack(ntim[i]); if (tmp > mwid) mwid = tmp; }
+   if (mwid == 1)
+    {
+     cnv_1is_to_4is(mgp, numinsts, 1, 1);  
+     for (i = 0; i < 4; i++) 
+      mgp->g_du.dis4v1[4*mastitp->itinum + i] = (byte) ntim[i];
+     break;
+    }
+   if (mwid == 2) 
+    {
+     cnv_1is_to_4is(mgp, numinsts, 1, 2);  
+     for (i = 0; i < 4; i++) 
+      mgp->g_du.dis4v2[4*mastitp->itinum + i] = (hword) ntim[i];
+     break;
+    }
+   cnv_1is_to_4is(mgp, numinsts, 1, 8);  
+   for (i = 0; i < 4; i++) 
+    mgp->g_du.dis4v[4*mastitp->itinum + i] = ntim[i];
+   break;
+  case DT_IS1V2:
+   mwid = get_ispack(ntim[0]); 
+   for (i = 1; i < 4; i++) 
+    { tmp = get_ispack(ntim[i]); if (tmp > mwid) mwid = tmp; }
+   if (mwid < 8)
+    {
+     cnv_1is_to_4is(mgp, numinsts, 2, 2);  
+     for (i = 0; i < 4; i++) 
+      mgp->g_du.dis4v2[4*mastitp->itinum + i] = (hword) ntim[i];
+     break;
+    }
+   cnv_1is_to_4is(mgp, numinsts, 2, 8);  
+   for (i = 0; i < 4; i++) 
+    mgp->g_du.dis4v2[4*mastitp->itinum + i] = (hword) ntim[i];
+   break;
+  case DT_IS4V:
+   /*  new 4v and master 4v is */
+   for (i = 0; i < 4; i++) mgp->g_du.dis4v[4*mastitp->itinum + i] = ntim[i];
+   /* slight possibility that could now narrow but rare */
+   break;
+  case DT_IS4V1: 
+   mwid = get_ispack(ntim[0]); 
+   for (i = 1; i < 4; i++) 
+    { tmp = get_ispack(ntim[i]); if (tmp > mwid) mwid = tmp; }
+   if (mwid == 1)
+    {
+     for (i = 0; i < 4; i++)
+      mgp->g_du.dis4v1[4*mastitp->itinum + i] = (byte) ntim[i];
+     break;
+    }
+   if (mwid == 2) 
+    {
+     unpack_isv1_to_isv2(mgp, numinsts, 4);
+     for (i = 0; i < 4; i++)
+      mgp->g_du.dis4v2[4*mastitp->itinum + i] = (hword) ntim[i];
+     break;
+    }
+   unpack_isv1_to_isv(mgp, numinsts, 4);
+   for (i = 0; i < 4; i++)
+    mgp->g_du.dis4v[4*mastitp->itinum + i] = ntim[i];
+   break;
+  case DT_IS4V2:
+   mwid = get_ispack(ntim[0]); 
+   for (i = 1; i < 4; i++) 
+    { tmp = get_ispack(ntim[i]); if (tmp > mwid) mwid = tmp; }
+   if (mwid < 8)
+    {
+     for (i = 0; i < 4; i++)
+      mgp->g_du.dis4v2[4*mastitp->itinum + i] = (hword) ntim[i];
+    }
+   else
+    {
+     unpack_isv2_to_isv(mgp, numinsts, 4);
+     for (i = 0; i < 4; i++)
+      mgp->g_du.dis4v[4*mastitp->itinum + i] = ntim[i];
+    }
+   break;
+  /* all 16 v forms here are impossible */
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * routine to set 1 instance of IS form value where ntim has right
+ * width and nvals assigned for 1 changed instance
+ */
+static void set_1is416val(struct gate_t *gp, int32 iti, int32 nvals, word64 *ntim, 
+ int32 mwid)
+{
+ register int32 i, ivalnum;
+
+ /* set the new value */
+ ivalnum = nvals*iti;
+ if (mwid == 1)
+  {
+   for (i = 0; i < nvals; i++)
+    {
+     if (nvals == 16)
+      {
+       if (i == 0 || i == 5 || i == 10 || i == 15)
+        gp->g_du.dis16v1[ivalnum + i] = 0;
+       else gp->g_du.dis16v1[ivalnum + i] = (byte) ntim[i];
+      }
+     else gp->g_du.dis4v1[ivalnum + i] = (byte) ntim[i];
+    }
+  }
+ else if (mwid == 8)
+  {
+   for (i = 0; i < nvals; i++)
+    gp->g_du.dis16v[ivalnum + i] = ntim[i];
+   if (nvals == 16) zero_unused_16v(&(gp->g_du.dis16v[ivalnum]));
+  }
+ else
+  {
+   for (i = 0; i < nvals; i++)
+    {
+     if (nvals == 16)
+      {
+       if (i == 0 || i == 5 || i == 10 || i == 15)
+        gp->g_du.dis16v2[ivalnum + i] = 0;
+       else gp->g_du.dis16v2[ivalnum + i] = (hword) ntim[i];
+      }
+     else gp->g_du.dis4v2[ivalnum + i] = (hword) ntim[i];
+    }
+  }
+}
+
+/*
+ * change one instance of IS delay form when new is DT_16V form
+ * here old 4v form impossible since must be path delay
+ */
+static void chg16vform_1instdel(struct gate_t *mgp, struct itree_t *mastitp,
+ struct gate_t *ngp)
+{
+ register int32 i;
+ int32 numinsts, tmp, mwid;
+ word64 tmptim, ntim[16], mtim[16];
+
+ numinsts = mastitp->itip->imsym->el.emdp->flatinum;
+ for (i = 0; i < 16; i++) ntim[i] = ngp->g_du.d16v[i];
+ switch ((byte) mgp->g_delrep) {
+  case DT_1V:
+   /* new is 16 value, master is 1 value */
+   mtim[0] = mgp->g_du.d1v[0];
+   for (i = 1; i < 16; i++)
+    {
+     if (i == 5 || i == 10 || i == 15) continue;
+     if (mtim[0] != ntim[i]) goto nd_is1v16v;
+    }
+   break;
+nd_is1v16v:
+   /* duplicate 1 to all of master times */
+   tmptim = mtim[0];
+   for (i = 1; i < 16; i++) mtim[i] = tmptim; 
+   zero_unused_16v(mtim);
+   __my_free((char *) mgp->g_du.d1v, sizeof(word64));
+   mwid = get_ispack(mtim[0]);
+   for (i = 1; i < 16; i++)
+    {
+     if (i == 5 || i == 10 || i == 15) continue;
+     tmp = get_ispack(ntim[i]);
+     if (tmp > mwid) mwid = tmp;
+    }
+   create_disv(mgp, numinsts, 16, mtim, mwid);
+   set_1is416val(mgp, mastitp->itinum, 16, ntim, mwid);
+   break;
+  case DT_16V: 
+   /* new 16 values, master 16 */
+   for (i = 0; i < 16; i++) mtim[i] = mgp->g_du.d16v[i];
+   for (i = 0; i < 16; i++) { if (mtim[i] != ntim[i]) goto nd_is16v; }
+   break;
+nd_is16v:  
+   /* must look at 12 master's and 4 news */
+   mwid = get_ispack(ntim[1]);
+   for (i = 2; i < 16; i++) 
+    { 
+     if (i == 5 || i == 10 || i == 15) continue;
+     tmp = get_ispack(ntim[i]); if (tmp > mwid) mwid = tmp;
+    }
+   for (i = 1; i < 16; i++) 
+    {
+     if (i == 5 || i == 10 || i == 15) continue;
+     tmp = get_ispack(mtim[i]); if (tmp > mwid) mwid = tmp;
+    }
+   /* set the new value */
+   create_disv(mgp, numinsts, 16, mtim, mwid);
+   set_1is416val(mgp, mastitp->itinum, 16, ntim, mwid);
+   break;
+  case DT_IS1V: 
+   /* new is 16 value, master is 1 IS form */
+   /* convert 1 is to 16 IS and set to dummy value */
+   cnv_1is_to_16is(mgp, numinsts, 8, 8);  
+   /* SJM 08/14/01 - was wrongly filling is1v case - other 15 not filled */
+   for (i = 0; i < 16; i++) 
+    mgp->g_du.dis16v[16*mastitp->itinum + i] = ntim[i];
+   /* slight possibility that could now narrow but rare */
+   break;
+  case DT_IS1V1: 
+   /* master is 1 byte 1 value IS and new time is 16v */
+   mwid = get_ispack(ntim[1]); 
+   for (i = 2; i < 16; i++) 
+    {
+     if (i == 5 || i == 10 || i == 15) continue;
+     tmp = get_ispack(ntim[i]);
+     if (tmp > mwid) mwid = tmp;
+    }
+   if (mwid == 1)
+    {
+     cnv_1is_to_16is(mgp, numinsts, 1, 1);  
+     for (i = 0; i < 16; i++) 
+      mgp->g_du.dis16v1[16*mastitp->itinum + i] = (byte) ntim[i];
+     break;
+    }
+   if (mwid == 2) 
+    {
+     cnv_1is_to_16is(mgp, numinsts, 1, 2);  
+     for (i = 0; i < 16; i++) 
+      mgp->g_du.dis16v2[16*mastitp->itinum + i] = (hword) ntim[i];
+     break;
+    }
+   cnv_1is_to_16is(mgp, numinsts, 1, 8);  
+   for (i = 0; i < 16; i++) 
+    mgp->g_du.dis16v[16*mastitp->itinum + i] = ntim[i];
+   break;
+  case DT_IS1V2:
+   mwid = get_ispack(ntim[1]); 
+   for (i = 2; i < 16; i++) 
+    {
+     if (i == 5 || i == 10 || i == 15) continue;
+     tmp = get_ispack(ntim[i]); if (tmp > mwid) mwid = tmp;
+    }
+   if (mwid < 8)
+    {
+     cnv_1is_to_16is(mgp, numinsts, 2, 2);  
+     for (i = 0; i < 16; i++) 
+      mgp->g_du.dis16v2[16*mastitp->itinum + i] = (hword) ntim[i];
+     break;
+    }
+   cnv_1is_to_16is(mgp, numinsts, 2, 8);  
+   for (i = 0; i < 16; i++) 
+    mgp->g_du.dis16v[16*mastitp->itinum + i] = ntim[i];
+   break;
+  case DT_IS16V:
+   /*  new 16v and master 16v is */
+   for (i = 0; i < 16; i++)
+    mgp->g_du.dis16v[16*mastitp->itinum + i] = ntim[i];
+   /* slight possibility that could now narrow but rare */
+   break;
+  case DT_IS16V1: 
+   mwid = get_ispack(ntim[1]); 
+   for (i = 2; i < 16; i++) 
+    {
+     if (i == 5 || i == 10 || i == 15) continue;
+     tmp = get_ispack(ntim[i]); if (tmp > mwid) mwid = tmp;
+    }
+   if (mwid == 1)
+    {
+     for (i = 0; i < 16; i++)
+      mgp->g_du.dis16v1[16*mastitp->itinum + i] = (byte) ntim[i];
+     break;
+    }
+   if (mwid == 2) 
+    {
+     unpack_isv1_to_isv2(mgp, numinsts, 16);
+     for (i = 0; i < 16; i++)
+      mgp->g_du.dis16v2[16*mastitp->itinum + i] = (hword) ntim[i];
+     break;
+    }
+   unpack_isv1_to_isv(mgp, numinsts, 16);
+   for (i = 0; i < 16; i++)
+    mgp->g_du.dis16v[16*mastitp->itinum + i] = ntim[i];
+   break;
+  case DT_IS16V2:
+   mwid = get_ispack(ntim[1]); 
+   for (i = 2; i < 16; i++) 
+    {
+     if (i == 5 || i == 15) continue;
+     tmp = get_ispack(ntim[i]);
+     if (tmp > mwid) mwid = tmp;
+    }
+   if (mwid < 8)
+    {
+     for (i = 0; i < 16; i++)
+      mgp->g_du.dis16v2[16*mastitp->itinum + i] = (hword) ntim[i];
+    }
+   else
+    {
+     unpack_isv2_to_isv(mgp, numinsts, 16);
+     for (i = 0; i < 16; i++)
+      mgp->g_du.dis16v[16*mastitp->itinum + i] = ntim[i];
+    }
+   break;
+  /* 4v forms illegal here */
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * convert 1 IS packed opck size to 4 IS form packed npck
+ */
+static void cnv_1is_to_4is(struct gate_t *gp, int32 numinsts, int32 opck, int32 npck)
+{
+ register int32 ii, i;
+ union del_u sav_du;
+ word64 ntim[16];
+
+ for (i = 0; i < 4; i++) ntim[i] = 0ULL; 
+ sav_du = gp->g_du;
+ /* build nvals value packed acording to new value */
+ create_disv(gp, numinsts, 4, ntim, npck);
+
+ for (ii = 0; ii < numinsts; ii++)
+  {
+   for (i = 0; i < 4; i++)
+    {
+     if (opck == 1) ntim[i] = (word64) sav_du.dis1v1[ii];
+     else if (opck == 2) ntim[i] = (word64) sav_du.dis1v2[ii];
+     else ntim[i] = sav_du.dis1v[ii];  
+    }
+   if (npck == 1)
+    {
+     for (i = 0; i < 4; i++)
+      gp->g_du.dis4v1[4*ii + i] = (byte) ntim[i];
+    }
+   else if (npck == 2)
+    {
+     for (i = 0; i < 4; i++)
+      gp->g_du.dis4v2[4*ii + i] = (hword) ntim[i];
+    }
+   else
+    { for (i = 0; i < 4; i++) gp->g_du.dis4v[4*ii + i] = ntim[i]; }
+  }
+ if (opck == 1) __my_free((char *) sav_du.dis1v1, numinsts);
+ else if (opck == 2) __my_free((char *) sav_du.dis1v2, 2*numinsts);
+ else __my_free((char *) sav_du.dis1v, sizeof(word64)*numinsts);
+}
+
+/*
+ * convert 1 IS packed opck size to 6 IS form packed npck
+ * separate routine becase 0, 5, 10 must be 0
+ */
+static void cnv_1is_to_16is(struct gate_t *gp, int32 numinsts, int32 opck, int32 npck)
+{
+ register int32 ii, i;
+ union del_u sav_du;
+ word64 ntim[16];
+
+ for (i = 0; i < 4; i++) ntim[i] = 0ULL;
+ sav_du = gp->g_du;
+ /* build nvals value packed according to npck */
+ create_disv(gp, numinsts, 16, ntim, npck);
+
+ for (ii = 0; ii < numinsts; ii++)
+  {
+   for (i = 1; i < 16; i++)
+    {
+     if (i == 5 || i == 10) continue;
+
+     if (opck == 1) ntim[i] = (word64) sav_du.dis1v1[ii];
+     else if (opck == 2) ntim[i] = (word64) sav_du.dis1v2[ii];
+     else ntim[i] = sav_du.dis1v[ii];  
+    }
+   if (npck == 1)
+    {
+     for (i = 0; i < 16; i++)
+      gp->g_du.dis16v1[16*ii + i] = (byte) ntim[i];
+    }
+   else if (npck == 2)
+    {
+     for (i = 0; i < 16; i++)
+      gp->g_du.dis16v2[16*ii + i] = (hword) ntim[i];
+    }
+   else
+    { for (i = 0; i < 16; i++) gp->g_du.dis16v[16*ii + i] = ntim[i]; }
+  }
+ if (opck == 1) __my_free((char *) sav_du.dis1v1, numinsts);
+ else if (opck == 2) __my_free((char *) sav_du.dis1v2, 2*numinsts);
+ else __my_free((char *) sav_du.dis1v, sizeof(word64)*numinsts);
+}
+
+/*
+ * change from dv? to dis?v
+ * nvals of tim must be filled
+ * this always uses 16v form since just pointer to alloced array
+ */
+static void create_disv(struct gate_t *gp, int32 numinsts, int32 nvals,
+ word64 *tim, int32 wid)
+{
+ register int32 ii, i;
+
+ if (wid == 1)
+  {
+   gp->g_du.dis16v1 = (byte *) __my_malloc(nvals*numinsts);
+   for (ii = 0; ii < numinsts; ii++)
+    {
+     for (i = 0; i < nvals; i++)
+      gp->g_du.dis16v1[nvals*ii + i] = (byte) tim[i];
+    }
+   gp->g_delrep = (nvals == 1) ? DT_IS1V1
+    : ((nvals == 4) ? DT_IS4V1 : DT_IS16V1);
+   return;
+  }
+ if (wid == 8)
+  {
+   gp->g_du.dis16v = (word64 *) __my_malloc(nvals*numinsts*sizeof(word64));
+   for (ii = 0; ii < numinsts; ii++)
+    { for (i = 0; i < nvals; i++) gp->g_du.dis16v[nvals*ii + i] = tim[i]; }
+   gp->g_delrep = (nvals == 1) ? DT_IS1V : ((nvals == 4) ? DT_IS4V : DT_IS16V);
+   return;
+  }
+ /* final rare fits in 2 bytes case */
+ gp->g_du.dis16v2 = (hword *) __my_malloc(2*nvals*numinsts);
+ for (ii = 0; ii < numinsts; ii++)
+  {
+   for (i = 0; i < nvals; i++)
+    gp->g_du.dis16v2[nvals*ii + i] = (hword) tim[i];
+  }
+ gp->g_delrep = (nvals == 1) ? DT_IS1V2
+  : ((nvals == 4) ? DT_IS4V2 : DT_IS16V2);
+}
+
+/*
+ * get width
+ */
+static int32 get_ispack(word64 tim)
+{
+ register word32 w1;
+
+ w1 = (word32) (tim & WORDMASK_ULL);
+ if (tim > WORDMASK_ULL || (w1 & 0xffff0000) != 0) return(8);
+ if ((w1 & 0xffffff00) != 0) return(2);
+ return(1);
+}
+
+/*
+ * unpack from isv1 to isv2, nvals determines if 1, 4, or 16 value form 
+ * caller must insure unpack will fit 
+ * uses 16v form since just pointer to array 
+ */
+static void unpack_isv1_to_isv2(struct gate_t *gp, int32 numinsts, int32 nvals)
+{
+ register int32 ii, i;
+ union del_u sav_du;
+
+ sav_du = gp->g_du;
+ gp->g_du.dis16v2 = (hword *) __my_malloc(2*numinsts*nvals);
+ for (ii = 0; ii < numinsts; ii++)
+  {
+   for (i = 0; i < nvals; i++) 
+    gp->g_du.dis16v2[nvals*ii + i] = (hword) sav_du.dis16v1[nvals*ii + i];
+  }
+ __my_free((char *) sav_du.dis16v1, numinsts*nvals);
+ gp->g_delrep = (nvals == 1) ? DT_IS1V2
+  : ((nvals == 4) ? DT_IS4V2 : DT_IS16V2);
+}
+
+/*
+ * unpack from isv1 to isv, nvals determines if 1, 4, or 16 value form 
+ * caller must insure unpack will fit 
+ */
+static void unpack_isv1_to_isv(struct gate_t *gp, int32 numinsts, int32 nvals)
+{
+ register int32 ii, i;
+ union del_u sav_du;
+
+ sav_du = gp->g_du;
+ gp->g_du.dis16v = (word64 *) __my_malloc(sizeof(word64)*numinsts*nvals);
+ for (ii = 0; ii < numinsts; ii++)
+  {
+   for (i = 0; i < nvals; i++) 
+    {
+     gp->g_du.dis16v[nvals*ii + i] = (word64) sav_du.dis16v1[nvals*ii + i];
+    }
+  }
+ __my_free((char *) sav_du.dis16v1, numinsts*nvals);
+ gp->g_delrep = (nvals == 1) ? DT_IS1V : ((nvals == 4) ? DT_IS4V : DT_IS16V);
+}
+
+/*
+ * unpack from isv2 to isv, nvals determines if 1, 4, or 16 value form 
+ * caller must insure unpack will fit 
+ * uses 16v form since just ptr to array
+ */
+static void unpack_isv2_to_isv(struct gate_t *gp, int32 numinsts, int32 nvals)
+{
+ register int32 ii, i;
+ union del_u sav_du;
+
+ sav_du = gp->g_du;
+ gp->g_du.dis16v = (word64 *) __my_malloc(sizeof(word64)*numinsts*nvals);
+ for (ii = 0; ii < numinsts; ii++)
+  {
+   for (i = 0; i < nvals; i++) 
+    {
+     gp->g_du.dis16v[nvals*ii + i] = (word64) sav_du.dis16v2[nvals*ii + i];
+    }
+  }
+ __my_free((char *) sav_du.dis16v2, 2*numinsts*nvals);
+ gp->g_delrep = (nvals == 1) ? DT_IS1V : ((nvals == 4) ? DT_IS4V : DT_IS16V);
+}
+
+/*
+ * zero unused 16v values
+ */
+static void zero_unused_16v(word64 *tim)
+{
+ tim[0] = 0ULL;
+ tim[5] = 0ULL;
+ tim[10] = 0ULL;
+}
+
+/*
+ * build a delay using current itree loc.
+ *
+ * can not be called until delays prepared
+ * uses current itree loc for instance if delay per inst. 
+ */
+extern char *__bld_delay_str(char *s, union del_u du, word32 drep)
+{
+ register int32 i;
+ int32 ndels, sav_nd_timstr_suf;
+ word64 tim[12], timval;
+ struct mod_t *mdp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ sav_nd_timstr_suf = __nd_timstr_suf;
+ __nd_timstr_suf = FALSE;
+ __extract_delval(tim, &ndels, du, drep);
+ mdp =__inst_mod;
+ if (ndels > 0 && !mdp->mno_unitcnv)
+  {
+   for (i = 0; i < ndels; i++)
+    { __cnv_ticks_tonum64(&timval, tim[i], mdp); tim[i] = timval; }
+  }
+ switch ((byte) drep) {
+  case DT_1V: case DT_IS1V: case DT_IS1V1: case DT_IS1V2:
+   sprintf(s, "%s", __to_timstr(s1, &(tim[0])));
+   break;
+  case DT_4V: case DT_IS4V: case DT_IS4V1: case DT_IS4V2:
+   sprintf(s, "%s, %s, %s", __to_timstr(s1, &(tim[0])),
+    __to_timstr(s2, &(tim[1])), __to_timstr(s3, &(tim[2])));
+   break;
+  case DT_16V: case DT_IS16V: case DT_IS16V1: case DT_IS16V2:
+   for (i = 0; i < ndels; i++)
+    {
+     if (i == 0) { sprintf(s, "%s", __to_timstr(s1, &(tim[0]))); continue; } 
+     sprintf(s1, ", %s", __to_timstr(s2, &(tim[i])));
+     strcat(s, s1);
+    } 
+   break;
+  case DT_1X:
+   sprintf(s, "**EXPR: %s", __to_timstr(s1, &(tim[0]))); break;
+  case DT_4X:
+   if (ndels == 3)
+    {
+     sprintf(s, "**EXPR: %s, %s, %s", __to_timstr(s1, &(tim[0])),
+     __to_timstr(s2, &(tim[1])), __to_timstr(s3, &(tim[2])));
+    }
+   else
+    {
+     sprintf(s, "**EXPR: %s, %s", __to_timstr(s1, &(tim[0])),
+     __to_timstr(s2, &(tim[1])));
+    }
+   break;
+  case DT_CMPLST: strcpy(s, "**WRONG SOURCE FORM LIST**"); break;
+  case DT_PTHDST: strcpy(s, "**PATH DESTIONATION PLACE HOLDER**"); break;
+  case DT_NONE: strcpy(s, "**NO DELAY**"); break; 
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ __nd_timstr_suf = sav_nd_timstr_suf;
+ return(s);
+}
+
+/*
+ * extract delays and fill passed tim array
+ *
+ * caller must push itree loc.
+ * errors odd delays, and scaling processed by caller above
+ * only for delays during sim
+ * can return 1,3,6, or 12 delays
+ * (or 0 for DT NONE - used for SDF or vpi_ annotate adding new)
+ *
+ * SJM 02/03/00 - cast to word64 word32 because packed form always unsigned
+ */
+extern void __extract_delval(word64 *tim, int32 *ndels, union del_u du,
+ word32 drep)
+{
+ struct xstk_t *xsp;
+
+ switch ((byte) drep) {
+  case DT_NONE: *ndels = 0; break;
+  case DT_1V: tim[0] = du.d1v[0]; *ndels = 1; break;
+  case DT_IS1V:
+   tim[0] = du.dis1v[__inum];
+   *ndels = 1;
+   break;
+  case DT_IS1V1:
+   tim[0] = (word64) du.dis1v1[__inum];
+   *ndels = 1;
+   break;
+  case DT_IS1V2:
+   tim[0] = (word64) du.dis1v2[__inum];
+   *ndels = 1;
+   break;
+  case DT_4V:
+   /* (rise, fall, toz) */
+   tim[0] = du.d4v[1]; tim[1] = du.d4v[0]; tim[2] = du.d4v[2];
+   *ndels = 3;
+   break;
+  case DT_IS4V:
+   /* (rise, fall, toz) */
+   tim[0] = du.dis4v[4*__inum + 1];
+   tim[1] = du.dis4v[4*__inum + 0];
+   tim[2] = du.dis4v[4*__inum + 2];
+   *ndels = 3;
+   break;
+  case DT_IS4V1:
+   /* (rise, fall, toz) */
+   tim[0] = (word64) du.dis4v1[4*__inum + 1];
+   tim[1] = (word64) du.dis4v1[4*__inum + 0];
+   tim[2] = (word64) du.dis4v1[4*__inum + 2];
+   *ndels = 3;
+   break;
+  case DT_IS4V2:
+   /* (rise, fall, toz) */
+   tim[0] = (word64) du.dis4v2[4*__inum + 1];
+   tim[1] = (word64) du.dis4v2[4*__inum + 0];
+   tim[2] = (word64) du.dis4v2[4*__inum + 2];
+   *ndels = 3;
+   break;
+  /* notice all the 6 forms are really size 16 tables */
+  case DT_16V: 
+   /* map from 16v table to 12 input list form */
+   __map_16v_to_12vform(tim, du.d16v);
+   __try_reduce_16vtab(tim, ndels); 
+   break;
+  case DT_IS16V:
+   tim[0] = du.dis16v[16*__inum + 4];
+   tim[1] = du.dis16v[16*__inum + 1];
+   tim[2] = du.dis16v[16*__inum + 8];
+   tim[3] = du.dis16v[16*__inum + 6];
+   tim[4] = du.dis16v[16*__inum + 9];
+   tim[5] = du.dis16v[16*__inum + 2];
+   tim[6] = du.dis16v[16*__inum + 12];
+   tim[7] = du.dis16v[16*__inum + 7];
+   tim[8] = du.dis16v[16*__inum + 13];
+   tim[9] = du.dis16v[16*__inum + 3];
+   tim[10] = du.dis16v[16*__inum + 11];
+   tim[11] = du.dis16v[16*__inum + 14];
+   __try_reduce_16vtab(tim, ndels); 
+   break;
+  case DT_IS16V1:
+   tim[0] = (word64) du.dis16v1[16*__inum + 4];
+   tim[1] = (word64) du.dis16v1[16*__inum + 1];
+   tim[2] = (word64) du.dis16v1[16*__inum + 8];
+   tim[3] = (word64) du.dis16v1[16*__inum + 6];
+   tim[4] = (word64) du.dis16v1[16*__inum + 9];
+   tim[5] = (word64) du.dis16v1[16*__inum + 2];
+   tim[6] = (word64) du.dis16v1[16*__inum + 12];
+   tim[7] = (word64) du.dis16v1[16*__inum + 7];
+   tim[8] = (word64) du.dis16v1[16*__inum + 13];
+   tim[9] = (word64) du.dis16v1[16*__inum + 3];
+   tim[10] = (word64) du.dis16v1[16*__inum + 11];
+   tim[11] = (word64) du.dis16v1[16*__inum + 14];
+   __try_reduce_16vtab(tim, ndels); 
+   break;
+  case DT_IS16V2:
+   tim[0] = (word64) du.dis16v2[16*__inum + 4];
+   tim[1] = (word64) du.dis16v2[16*__inum + 1];
+   tim[2] = (word64) du.dis16v2[16*__inum + 8];
+   tim[3] = (word64) du.dis16v2[16*__inum + 6];
+   tim[4] = (word64) du.dis16v2[16*__inum + 9];
+   tim[5] = (word64) du.dis16v2[16*__inum + 2];
+   tim[6] = (word64) du.dis16v2[16*__inum + 12];
+   tim[7] = (word64) du.dis16v2[16*__inum + 7];
+   tim[8] = (word64) du.dis16v2[16*__inum + 13];
+   tim[9] = (word64) du.dis16v2[16*__inum + 3];
+   tim[10] = (word64) du.dis16v2[16*__inum + 11];
+   tim[11] = (word64) du.dis16v2[16*__inum + 14];
+   __try_reduce_16vtab(tim, ndels); 
+   break;
+  case DT_1X:
+   xsp = __eval_xpr(du.d1x);
+   tim[0] = (word64) xsp->ap[0];
+   if (xsp->xslen > WBITS) tim[0] |= (((word64) xsp->ap[1]) << 32);
+   *ndels = 1;
+   __pop_xstk();
+   break;
+  case DT_4X:
+   xsp = __eval_xpr(du.d4x[1]);
+   tim[0] = (word64) xsp->ap[0]; 
+   if (xsp->xslen > WBITS) tim[0] |= (((word64) xsp->ap[1]) << 32);
+   __pop_xstk(); 
+   xsp = __eval_xpr(du.d4x[0]);
+   tim[1] = (word64) xsp->ap[0]; 
+   if (xsp->xslen > WBITS) tim[1] |= (((word64) xsp->ap[1]) << 32);
+   __pop_xstk(); 
+   if (du.d4x[2] != NULL)
+    {
+     xsp = __eval_xpr(du.d4x[2]);
+     tim[2] = (word64) xsp->ap[0]; 
+     if (xsp->xslen > WBITS) tim[2] |= (((word64) xsp->ap[1]) << 32);
+     __pop_xstk(); 
+     *ndels = 3;
+    }
+   else
+    {
+     /* LOOKATME - is this right */
+     if (tim[0] < tim[1]) tim[2] = tim[0]; else tim[2] = tim[1];
+     *ndels = 2;
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__); *ndels = 0;
+ }
+}
+
+/*
+ * map from 16 delay internal table to 12v input form list
+ */
+extern void __map_16v_to_12vform(word64 *ntim, word64 *tim)
+{
+ ntim[0] = tim[4]; ntim[1] = tim[1]; ntim[2] = tim[8];
+ ntim[3] = tim[6]; ntim[4] = tim[9]; ntim[5] = tim[2];
+ ntim[6] = tim[12]; ntim[7] = tim[7]; ntim[8] = tim[13];
+ ntim[9] = tim[3]; ntim[10] = tim[11]; ntim[11] = tim[14];
+}
+
+/*
+ * try to reduce a 16 value tim form to 2, 3, 6 if possible
+ * this sets nnvals to number of values after reductions
+ * for tim narrow just ignore higher values
+ * reducible to 1 value will never be 16v in first place
+ */
+extern void __try_reduce_16vtab(word64 *tim, int32 *nvals)
+{
+ word64 tmin, tmax;
+
+ /* know already mapped to 12v form */ 
+ /* see if can reduce to 6 form */
+ *nvals = 12;
+ /* 0->x min(0->1, 0->z) */ 
+ tmin = tim[0];
+ if (tim[2] < tmin) tmin = tim[2];  
+ if (tmin != tim[6]) return;
+
+ /* 1->x min(1->0, 1->z) */ 
+ tmin = tim[1];
+ if (tim[4] < tmin) tmin = tim[4];  
+ if (tmin != tim[8]) return;
+
+ /* z->x min(z->0, z->1) */ 
+ tmin = tim[5];
+ if (tim[3] < tmin) tmin = tim[3];  
+ if (tmin != tim[11]) return;
+
+ /* x->0 max(1->0, z->0) */ 
+ tmax = tim[1];
+ if (tim[5] > tmax) tmax = tim[5];  
+ if (tmax != tim[9]) return;
+
+ /* x->1 max(z->1, 0->1) */ 
+ tmax = tim[3];
+ if (tim[0] > tmax) tmax = tim[0];  
+ if (tmax != tim[7]) return;
+
+ /* x->z max(1->z, 0->z) */ 
+ tmax = tim[4];
+ if (tim[2] > tmax) tmax = tim[2];  
+ if (tmax != tim[10]) return;
+
+ /* see if 6 can reduce to 2 */ 
+ *nvals = 6; 
+ if (tim[0] == tim[2] && tim[2] == tim[3] && tim[1] == tim[4]
+  && tim[4] == tim[5])
+  { *nvals = 2; return; }
+ /* see if 6 can reduce to 3 */
+ if ((tim[0] != tim[3]) || (tim[1] != tim[5]) || (tim[2] != tim[4])) return; 
+ *nvals = 3;
+}
+
+
+/*
+ * DELAY DEBUGGING ROUTINES
+ */
+
+/*
+ * dump all 16 (really 12) delay transitions
+ * DBG only routine
+ */
+/* ---
+extern void __dbg_dump_del(union del_u du, word32 drep)
+{
+ register int32 i;
+ struct xstk_t *xsp;
+ struct expr_t *dxp;
+ word64 dtab[16], tdel, dv0, dv1, dvx, dvz;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ switch ((byte) drep) {
+  case DT_1V:
+   for (i = 0; i < 16; i++) dtab[i] = du.d1v[0];
+   break;
+  case DT_IS1V:
+   for (i = 0; i < 16; i++) dtab[i] = du.dis1v[__inum];
+   break;
+  case DT_IS1V1:
+   for (i = 0; i < 16; i++)
+    { dtab[i] = (word64) du.dis1v1[__inum]; }
+   break;
+  case DT_IS1V2:
+   for (i = 0; i < 16; i++)
+    { dtab[i] = (word64) du.dis1v2[__inum]; }
+   break;
+  case DT_4V:
+   dtab[0x1] = du.d4v[0]; dtab[0x2] = du.d4v[0]; dtab[0x3] = du.d4v[0];
+   dtab[0x4] = du.d4v[1]; dtab[0x6] = du.d4v[1]; dtab[0x7] = du.d4v[1];
+   dtab[0x8] = du.d4v[2]; dtab[0x9] = du.d4v[2]; dtab[0xb] = du.d4v[2];
+   dtab[0xc] = du.d4v[3]; dtab[0xe] = du.d4v[3]; dtab[0xd] = du.d4v[3];
+   break;
+  case DT_IS4V:
+   tdel = du.d4v[4*__inum + 0];
+   dtab[0x1] = tdel; dtab[0x2] = tdel; dtab[0x3] = tdel;
+   tdel = du.d4v[4*__inum + 1];
+   dtab[0x4] = tdel; dtab[0x6] = tdel; dtab[0x7] = tdel;
+   tdel = du.d4v[4*__inum + 2];
+   dtab[0x8] = tdel; dtab[0x9] = tdel; dtab[0xb] = tdel;
+   tdel = du.d4v[4*__inum + 3];
+   dtab[0xc] = tdel; dtab[0xe] = tdel; dtab[0xd] = tdel;
+   break;
+  case DT_IS4V1:
+   tdel = (word64) du.dis4v1[4*__inum + 0];
+   dtab[0x1] = tdel; dtab[0x2] = tdel; dtab[0x3] = tdel;
+   tdel = (word64) du.dis4v1[4*__inum + 1];
+   dtab[0x4] = tdel; dtab[0x6] = tdel; dtab[0x7] = tdel;
+   tdel = (word64) du.dis4v1[4*__inum + 2];
+   dtab[0x8] = tdel; dtab[0x9] = tdel; dtab[0xb] = tdel;
+   tdel = (word64) du.dis4v1[4*__inum + 3];
+   dtab[0xc] = tdel; dtab[0xe] = tdel; dtab[0xd] = tdel;
+   break;
+  case DT_IS4V2:
+   tdel = (word64) du.dis4v2[4*__inum + 0];
+   dtab[0x1] = tdel; dtab[0x2] = tdel; dtab[0x3] = tdel;
+   tdel = (word64) du.dis4v1[4*__inum + 1];
+   dtab[0x4] = tdel; dtab[0x6] = tdel; dtab[0x7] = tdel;
+   tdel = (word64) du.dis4v1[4*__inum + 2];
+   dtab[0x8] = tdel; dtab[0x9] = tdel; dtab[0xb] = tdel;
+   tdel = (word64) du.dis4v1[4*__inum + 3];
+   dtab[0xc] = tdel; dtab[0xe] = tdel; dtab[0xd] = tdel;
+   break;
+  case DT_16V:
+   for (i = 0; i < 16; i++) dtab[i] = du.d16v[i];
+   break;
+  case DT_IS16V:
+   for (i = 0; i < 16; i++) dtab[i] = du.dis16v[16*__inum + i];
+   break;
+  case DT_IS16V1:
+   for (i = 0; i < 16; i++)
+    {
+     dtab[i] = (word64) du.dis16v1[16*__inum + i];
+    }
+   break;
+  case DT_IS16V2:
+   for (i = 0; i < 16; i++)
+    {
+     dtab[i] = (word64) du.dis16v2[16*__inum + i];
+    }
+   break;
+  case DT_1X:
+   xsp = __eval_xpr(du.d1x);
+   delx_to_deltim(&tdel, du.d1x, xsp);
+   for (i = 0; i < 16; i++) dtab[i] = tdel;
+   __pop_xstk();
+   break;
+  case DT_4X:
+   dxp = du.d4x[0];
+   xsp = __eval_xpr(dxp);
+   delx_to_deltim(&dv0, dxp, xsp);
+   __pop_xstk();
+   dxp = du.d4x[1];
+   xsp = __eval_xpr(dxp);
+   delx_to_deltim(&dv1, dxp, xsp);
+   __pop_xstk();
+   if (du.d4x[2] == NULL) dvz = (dv1 < dv0) ? dv1 : dv0;
+   else
+    {
+     dxp = du.d4x[2];
+     xsp = __eval_xpr(dxp);
+     delx_to_deltim(&dvz, dxp, xsp);
+     __pop_xstk();
+    }
+   if (du.d4x[2] == NULL) dvx = (dv1 < dv0) ? dv1 : dv0;
+   else
+    {
+     if (dv0 < dv1) { dvx = (dv0 < dvz) ? dv0 : dvz; }
+     else { dvx = (dv1 < dvz) ? dv1 : dvz; }
+    }
+   dtab[0x1] = dv0; dtab[0x2] = dv0; dtab[0x3] = dv0;
+   dtab[0x4] = dv1; dtab[0x6] = dv1; dtab[0x7] = dv1;
+   dtab[0x8] = dvz; dtab[0x9] = dvz; dtab[0xb] = dvz;
+   dtab[0xc] = dvx; dtab[0xe] = dvx; dtab[0xd] = dvx;
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ __dbg_msg(":: to 0 transitions: 1->0 = %s, z->0 = %s , x->0 = %s\n",
+  __to_timstr(s1, &(dtab[0x1])), __to_timstr(s2, &(dtab[0x2])),
+  __to_timstr(s3, &(dtab[0x3])));
+ __dbg_msg(":: to 1 transitions: 0->1 = %s, z->1 = %s , x->1 = %s\n",
+  __to_timstr(s1, &(dtab[0x4])), __to_timstr(s2, &(dtab[0x6])),
+  __to_timstr(s3, &(dtab[0x7])));
+ __dbg_msg(":: to z transitions: 0->z = %s, 1->z = %s , x->z = %s\n",
+  __to_timstr(s1, &(dtab[0x8])), __to_timstr(s2, &(dtab[0x9])),
+  __to_timstr(s3, &(dtab[0xb])));
+ __dbg_msg(":: to x transitions: 0->x = %s, 1->x = %s , z->x = %s\n",
+  __to_timstr(s1, &(dtab[0xc])), __to_timstr(s2, &(dtab[0xd])),
+  __to_timstr(s3, &(dtab[0xe])));
+}
+--- */
diff --git a/src/v_ex.c b/src/v_ex.c
new file mode 100644
index 0000000..e9f8bcb
--- /dev/null
+++ b/src/v_ex.c
@@ -0,0 +1,8470 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * run time execution routines - statements but not expression eval
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <setjmp.h>
+#include <math.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <signal.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void tr_resume_msg(void);
+static void exec_stmts(register struct st_t *);
+static void thrd_done_cleanup(register struct thread_t *);
+static void brktr_exec_stmts(register struct st_t *);
+static void step_exec_stmt(register struct st_t *);
+static int32 stepped_to_new_loc(struct st_t *);
+static void eval_tskassign_rhsexpr(register struct xstk_t *, register int32,
+ register int32, register int32, register int32);
+static void tr_proc_assign(struct st_t *, struct xstk_t *);
+static void tr_nbproc_assign(struct st_t *, struct xstk_t *);
+static struct st_t *exec_rep_ectl_setup(struct st_t *stp);
+static int32 exec_dctrl(struct st_t *);
+static void sched_proc_delay(struct delctrl_t *, word32 *, int32);
+static void sched_nbproc_delay(struct delctrl_t *, struct xstk_t *,
+ struct st_t *);
+static void arm_event_dctrl(struct delctrl_t *, register word32 *, int32);
+static void arm_nbevent_dctrl(struct delctrl_t *, struct xstk_t *,
+ struct st_t *);
+static struct st_t *exec_case(struct st_t *);
+static struct st_t *exec_real_case(struct st_t *);
+static void tr_case_st(struct xstk_t *, int32);
+static struct st_t *exec_casex(struct st_t *);
+static struct st_t *exec_casez(struct st_t *);
+static int32 exec_wait(register struct st_t *);
+static int32 for_not_done(struct for_t *);
+static void exec_namblk(struct st_t *);
+static struct thread_t *sched_fj_subthread(struct st_t *stp);
+static void init_thrd(register struct thread_t *);
+static void tradd_tf_argval(int32, struct net_t *, struct xstk_t *);
+static void store_tskcall_outs(struct st_t *);
+static void grow_fcstk(void);
+static void exec_count_drivers(struct expr_t *);
+static void exec_testplusargs(struct expr_t *);
+static void exec_scanplusargs(struct expr_t *);
+static void exec_1arg_transcendental(int32, struct expr_t *);
+static void exec_transcendental_int(struct expr_t *);
+static void exec_transcendental_sign(struct expr_t *);
+static void exec_transcendental_powsign(int32, struct expr_t *);
+static void exec_transcendental_minmax(int32, struct expr_t *);
+static void exec_transcendental_atan2(struct expr_t *);
+static void exec_transcendental_hypot(struct expr_t *);
+static void exec_cause(struct st_t *);
+static struct thread_t *find_hgh_sametskthrd(struct thread_t *);
+static int32 thread_above_cur(struct thread_t *);
+static void free_thd_stuff(struct thread_t *);
+static void unlink_tskthd(struct thread_t *);
+static int32 chk_strobe_infloop(struct st_t *, struct sy_t *);
+static void mcd_do_fclose(struct expr_t *);
+static word32 bld_open_mcd(void);
+static word32 mc_do_fopen(struct expr_t *);
+static void do_showvars_stask(struct expr_t *);
+static void do_warn_supp_chg(char *, struct expr_t *, int32);
+static void do_reset(struct expr_t *);
+static void do_showscopes(struct expr_t *);
+static void prt_1m_scopelist(struct itree_t *);
+static void prt_1tsk_scopelist(struct task_t *, int32);
+static void prt_1m_nestscopes(struct itree_t *);
+static void prt_1tsk_nestscopes(struct symtab_t *);
+static void exec_qfull(struct expr_t *);
+static void do_q_init(struct expr_t *);
+static struct q_hdr_t *find_q_from_id(int32);
+static void init_q(struct q_hdr_t *);
+static void do_q_add(struct expr_t *);
+static void do_q_remove(struct expr_t *);
+static void do_q_examine(struct expr_t *);
+static void cmp_mean_interarriv_tim(word64 *, struct q_hdr_t *);
+static void cmp_max_wait(word64 *, struct q_hdr_t *);
+static void cmp_mean_wait_tim(word64 *, struct q_hdr_t *);
+static void exec_prttimscale(struct expr_t *);
+static void exec_timefmt(struct expr_t *);
+static int32 get_opt_starg(struct expr_t *, int32);
+static void exec_log_fnamchg(struct expr_t *);
+static void exec_trace_fnamchg(struct expr_t *);
+static void exec_expr_schg(struct expr_t *);
+static void free_thd_subtree(struct thread_t *);
+static void suspend_curthd(struct st_t *);
+
+static word32 fio_do_fopen(struct expr_t *, struct expr_t *);
+static word32 fio_fopen(char *, char *);
+static int32 chk_cnvt_fd_modes(char *, char *);
+static void fio_do_fclose(struct expr_t *);
+static int32 chk_get_mcd_or_fd(struct expr_t *, int32 *);
+static void fio_fflush(struct expr_t *);
+static int32 fio_ungetc(struct expr_t *, struct expr_t *);
+static int32 chk_get_ver_fd(struct expr_t *);
+static int32 fio_fgets(struct expr_t *, struct expr_t *);
+static int32 fio_rewind(struct expr_t *);
+static int32 fio_fseek(struct expr_t *, struct expr_t *, struct expr_t *);
+static int32 fio_ferror(struct expr_t *, struct expr_t *);
+static void fio_swrite(struct expr_t *, int32);
+static void fio_sformat(struct expr_t *);
+static int32 fio_fscanf(struct expr_t *);
+static int32 fio_sscanf(struct expr_t *);
+static int32 fio_exec_scanf(FILE *, struct expr_t *);
+static int32 fio_fread(struct expr_t *);
+static void fread_onto_stk(struct xstk_t *, byte *, int32);
+static int32 fio_arr_fread(struct expr_t *, int32, struct expr_t *,
+ struct expr_t *);
+static int32 scanf_getc(FILE *);
+static void scanf_ungetc(int32, FILE *);
+static int32 chk_scanf_fmt(char *);
+static int32 collect_scanf_num(int32 *, FILE *, int32, int32, int32);
+static int32 collect_scanf_realnum(double *, FILE *, int32, int32, int32);
+static struct xstk_t *collect_ufmt_binval(FILE *, struct expr_t *, int32);
+static struct xstk_t *collect_zfmt_binval(FILE *, struct expr_t *, int32 );
+static int32 cnvt_scanf_stnam_to_val(char *); 
+extern void __str_do_disp(struct expr_t *, int32);
+extern word32 __inplace_lnegate(register word32 *, int32);
+
+/* extern prototypes (maybe defined in this module) */
+extern int32 __comp_sigint_handler(void);
+extern char *__my_malloc(int32);
+extern char *__pv_stralloc(char *);
+extern char *__my_realloc(char *, int32, int32);
+extern struct xstk_t *__eval_assign_rhsexpr(register struct expr_t *,
+ register struct expr_t *);
+extern struct thread_t *__setup_tsk_thread(struct task_t *);
+extern void __sched_fork(struct st_t *);
+extern i_tev_ndx __bld_nb_tev(struct st_t *, struct xstk_t *, word64);
+extern int32 __lhsexpr_var_ndx(register struct expr_t *);
+extern void __eval_lhsexpr_var_ndxes(register struct expr_t *);
+extern struct st_t *__brktr_exec_1stmt(struct st_t *);
+extern struct thread_t *__alloc_thrd(void);
+extern struct st_t *__exec_tskcall(struct st_t *);
+extern struct xstk_t *__eval2_xpr(struct expr_t *);
+extern struct expr_t *__copy_expr(struct expr_t *);
+extern struct expr_t *__sim_copy_expr(struct expr_t *);
+extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
+extern struct expr_t *__bld_rng_numxpr(word32, word32, int32);
+extern void __free_xtree(struct expr_t *);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern char *__xregab_tostr(char *, word32 *, word32 *, int32, struct expr_t *);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char *__to_idnam(struct expr_t *);
+extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern char *__to_timunitnam(char *, word32);
+extern char *__to_timstr(char *, word64 *);
+extern char *__to_tetyp(char *, word32); 
+extern char *__to_tsktyp(char *, word32);
+extern double __unscale_realticks(word64 *, struct mod_t *);
+extern FILE *__tilde_fopen(char *, char *);
+extern struct xstk_t *__ld_wire_driver(register struct net_pin_t *);
+extern struct xstk_t *__ld_stwire_driver(register struct net_pin_t *);
+extern int32 __has_vpi_driver(struct net_t *, struct net_pin_t *);
+extern char *__schop(char *, char *);
+extern char *__to_dcenam(char *, word32);
+extern struct xstk_t *__cstr_to_vval(char *);
+extern struct task_t *__getcur_scope_tsk(void);
+extern word32 __mc1_fopen(char *, int32, int32);
+extern word32 __close_mcd(word32, int32);
+extern void __wrap_puts(char *, FILE *);
+extern void __wrap_putc(int32, FILE *);
+extern void __evtr_resume_msg(void);
+extern void __do_iact_disable(struct hctrl_t *, int32);
+extern void __dmp_thrd_info(struct thread_t *);
+extern void __dmp_tskthd(struct task_t *, struct mod_t *);
+extern void __my_free(char *, int32);
+extern void __exec2_proc_assign(struct expr_t *, register word32 *,
+ register word32 *);
+extern int32 __cvt_lngbool(word32 *, word32 *, int32);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern void __exec_qc_assign(struct st_t *, int32);
+extern void __exec_qc_wireforce(struct st_t *);
+extern void __exec_qc_deassign(struct st_t *, int32);
+extern void __exec_qc_wirerelease(struct st_t *);
+extern int32 __process_brkpt(struct st_t *);
+extern void __prt_src_lines(int32, int32, int32);
+extern void __cnv_stk_fromreg_toreal(struct xstk_t *, int32);
+extern void __cnv_stk_fromreal_toreg32(struct xstk_t *);
+extern void __sizchgxs(struct xstk_t *, int32);  
+extern void __narrow_to1wrd(register struct xstk_t *);
+extern void __narrow_sizchg(register struct xstk_t *, int32);
+extern void __sizchg_widen(register struct xstk_t *, int32);
+extern void __sgn_xtnd_wrd(register struct xstk_t *, int32);
+extern void __sgn_xtnd_widen(struct xstk_t *, int32);
+extern void __dmp_proc_assgn(FILE *, struct st_t *, struct delctrl_t *, int32);
+extern void __trunc_exprline(int32, int32);
+extern void __dmp_nbproc_assgn(FILE *, struct st_t *, struct delctrl_t *);
+extern void __dmp_dctrl(FILE *, struct delctrl_t *);
+extern void __chg_xprline_size(int32);
+extern void __dmp_dcxpr(FILE *, union del_u, word32);
+extern void __get_del(register word64 *, register union del_u, word32);
+extern void __insert_event(register i_tev_ndx);
+extern void __dmp_forhdr(FILE *, struct for_t *);
+extern void __add_ev_to_front(register i_tev_ndx);
+extern void __dmp_tskcall(FILE *, struct st_t *);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern void __adds(char *);
+extern void __chg_st_val(struct net_t *, register word32 *, register word32 *);
+extern void __st_val(struct net_t *, register word32 *, register word32 *);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __grow_tevtab(void);
+extern void __ld_wire_val(register word32 *, register word32 *, struct net_t *);
+extern void __do_interactive_loop(void);
+extern void __cnv_ticks_tonum64(word64 *, word64, struct mod_t *);
+extern void __exec_sfrand(struct expr_t *);
+extern void __exec_scale(struct expr_t *);
+extern void __pli_func_calltf(struct expr_t *);
+extern void __vpi_sysf_calltf(struct expr_t *);
+extern void __get_bidnpp_sect(struct net_t *, struct net_pin_t *, int32 *,
+ int32 *);
+extern char *__get_eval_cstr(struct expr_t *, int32 *);
+extern void __free_1thd(struct thread_t *);
+extern struct st_t *__exec_stsk(struct st_t *, struct sy_t *,
+ struct tskcall_t *);
+extern void __free_thd_list(struct thread_t *);
+extern int32 __exec_disable(struct expr_t *);
+extern void __do_disp(register struct expr_t *, int32);
+extern void __fio_do_disp(register struct expr_t *, int32, int32, char *); 
+extern void __start_fmonitor(struct st_t *);
+extern void __dmpmod_nplst(struct mod_t *, int32);
+extern void __start_monitor(struct st_t *);
+extern void __exec_readmem(struct expr_t *, int32);
+extern void __exec_sreadmem(struct expr_t *, int32);
+extern void __exec_dumpvars(struct expr_t *);
+extern int32 __get_eval_word(struct expr_t *, word32 *);
+extern void __exec_input_fnamchg(struct expr_t *);
+extern void __exec_history_list(int32);
+extern void __do_scope_list(void);
+extern void __exec_sdf_annotate_systsk(struct expr_t *);
+extern void __call_misctfs_finish(void);
+extern void __vpi_endsim_trycall(void);
+extern void __emit_stsk_endmsg(void);
+extern void __maybe_open_trfile(void);
+extern void __escape_to_shell(char *);
+extern void __write_snapshot(int32);
+extern void __prt2_mod_typetab(int32);
+extern void __pli_task_calltf(struct st_t *);
+extern void __vpi_syst_calltf(struct st_t *);
+extern void __my_fclose(FILE *);
+extern void __emit_1showvar(struct net_t *, struct gref_t *);
+extern void __prt_top_mods(void);
+extern void __disp_itree_path(struct itree_t *, struct task_t *);
+extern void __set_scopchg_listline(void);
+extern void __call_misctfs_scope(void);
+extern void __vpi_iactscopechg_trycall(void);
+extern void __my_ftime(time_t *, time_t *);
+extern void __prt_end_msg(void);
+extern void __exec_dist_uniform(struct expr_t *);
+extern void __exec_dist_stdnorm(struct expr_t *);
+extern void __exec_dist_exp(struct expr_t *);
+extern void __exec_dist_poisson(struct expr_t *);
+extern void __exec_chi_square(struct expr_t *);
+extern void __exec_dist_t(struct expr_t *);
+/* ??? extern void __dmp_event_tab(void); */
+extern void __my_dv_flush(void);
+extern void __add_nchglst_el(register struct net_t *);
+extern void __add_dmpv_chglst_el(struct net_t *);
+extern void __wakeup_delay_ctrls(register struct net_t *, register int32,
+ register int32);
+extern void __dmp_all_thrds(void);
+extern double __cnvt_stk_to_real(struct xstk_t *, int32);
+extern int32 __enum_is_suppressable(int32);
+extern int32 __trim1_0val(word32 *, int32);
+extern char *__vval_to_vstr(word32 *, int32, int32 *);
+extern void __vstr_to_vval(word32 *, char *, int32);
+extern int32 __is_vdigit(int32, int32);
+extern void __to_dhboval(int32, int32);
+extern double __my_strtod(char *, char **, int32 *);
+extern void __add_pnd0_nonblk_list(i_tev_ndx);
+
+extern struct expr_t *__disp_1fmt_to_exprline(char *, struct expr_t *);
+extern void __getarr_range(struct net_t *, int32 *, int32 *, int32 *);
+extern void __st_arr_val(union pck_u, int32, int32, int32, register word32 *,
+ register word32 *);
+extern void __chg_st_arr_val(union pck_u, int32, int32, int32,
+ register word32 *, register word32 *);
+extern int32 __fd_do_fclose(int32);
+extern void __add_select_nchglst_el(register struct net_t *, register int32,
+ register int32);
+
+extern void __tr_msg(char *, ...);
+extern void __cv_msg(char *, ...);
+extern void __cvsim_msg(char *, ...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __misc_sgfterr(char *, int32);
+extern void __my_exit(int32, int32);
+extern void __my_fprintf(FILE *, char *, ...);
+
+/* reset mechanism long jump buffer */
+extern jmp_buf __reset_jmpbuf;
+
+/* system stuff */
+extern int32 errno;
+
+/* some general evaluation tables */
+word32 __masktab[] = {
+ /* since 0 is the same as all used, mask must be entire word32 */
+ 0xffffffffL, 0x00000001L, 0x00000003L, 0x00000007L,
+ 0x0000000fL, 0x0000001fL, 0x0000003fL, 0x0000007fL,
+ 0x000000ffL, 0x000001ffL, 0x000003ffL, 0x000007ffL,
+ 0x00000fffL, 0x00001fffL, 0x00003fffL, 0x00007fffL,
+ 0x0000ffffL, 0x0001ffffL, 0x0003ffffL, 0x0007ffffL,
+ 0x000fffffL, 0x001fffffL, 0x003fffffL, 0x007fffffL,
+ 0x00ffffffL, 0x01ffffffL, 0x03ffffffL, 0x07ffffffL,
+ 0x0fffffffL, 0x1fffffffL, 0x3fffffffL, 0x7fffffffL,
+ /* special for places where mask uses length i.e. 32 bits */
+ 0xffffffffL
+};
+
+extern double __dbl_toticks_tab[];
+
+/*
+ * ROUTINES TO PROCESS PROCEDURAL EVENTS AND EXECUTE BEHAVIORAL STATEMENTS
+ */
+
+/*
+ * execute a control thread from one event suspension until next
+ * need to handle rhs delay control and => proc. assignment
+ *
+ * when thread completes just removes and continues with other threads
+ * know if this suspends or hits ctrl-c will always build and schedule new ev
+ * possible for thread next statement to be nil to terminate thread 
+ * and here must be left and terminated after suspend
+ */
+extern void __process_thrd_ev(register struct tev_t *tevp)
+{
+ register struct st_t *stp;
+ struct st_t *stp2;
+ struct thread_t *parthp;
+
+ __proc_thrd_tevents++;
+ __suspended_thd = NULL;
+ __suspended_itp = NULL;
+ /* set current thread and remove connection of thread to event */
+ __cur_thd = tevp->tu.tethrd;
+ __cur_thd->thdtevi = -1;
+
+ /* if not func. must have change itree to right one for thread */
+ /* NO - this will not be be true if invoked xmr task - inst ptr. diff */  
+ /* but will be put back when xmr task done so ok */ 
+ /* DBG remove -- 
+ if (__fcspi == -1 && __cur_thd->th_itp != __inst_ptr)
+  __misc_terr(__FILE__, __LINE__);
+ --- */
+ stp = __cur_thd->thnxtstp;
+
+ /* possible to remove thread even though no more statements to exec */
+ if (stp != NULL && (__st_tracing || __ev_tracing))
+  {
+   __slin_cnt = stp->stlin_cnt;
+   __sfnam_ind = stp->stfnam_ind;
+
+   if (__st_tracing) tr_resume_msg(); else __evtr_resume_msg();
+   __tr_msg("-- resuming at statement %s\n",
+    __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt));
+  }
+
+ /* for each completed thread continue in parent without schd */
+ /* loop because continues until thread tree done or suspend */
+ for (__stmt_suspend = FALSE;;)
+  {
+   /* keep executing behavioral stmts until done or hit timing control */
+   if (stp != NULL) 
+    {
+     /* even if single stepping must not see iact threads */
+     /* since this always either hits end of thread or suspends */
+     if (__single_step && __cur_thd->th_hctrl == NULL)
+      {
+       step_exec_stmt(stp);
+      }
+     /* but batch tracing traces */
+     else if (__st_tracing) brktr_exec_stmts(stp);
+     else exec_stmts(stp);
+
+     /* on suspend event itree location is right for exec */
+     /* if no suspend but current ctrl thread (init/always/task) got to end */ 
+     /* fall thru and try to immediately exec parent */
+     if (__stmt_suspend) break;
+    }
+
+   /* DBG remove --- */
+   if (__cur_thd->thdtevi != -1) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* this thread tree done if nil - can only be interactive or init/always */
+   /* this handles all freeing because entire thread tree done */
+   if ((parthp = __cur_thd->thpar) == NULL)
+    {
+     /* if interactive thread - free and set possible history disabled */
+     if (__cur_thd->th_hctrl != NULL)
+      __do_iact_disable(__cur_thd->th_hctrl, FALSE);
+     __stmt_suspend = TRUE;
+     break;
+    }
+
+   /* know if task has outs will always have parent */
+   /* store parameters if needed */
+   if (__cur_thd->tsk_stouts)
+    { 
+     /* DBG remove --- */ 
+     if (!parthp->th_postamble) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     /* if disabled do not store parameters, but still adjust nxt stp */
+     /* not parent must be set to continue at tsk call for storing outs */
+     if (!__cur_thd->th_dsable) store_tskcall_outs(parthp->thnxtstp);
+ 
+     /* SJM 08/18/02 - must fixup including skip of non loop end gotos */
+     /* now that store of tsk outs finished */
+     stp2 = parthp->thnxtstp;
+     if (stp2 != NULL) stp2 = stp2->stnxt;
+     if (stp2 == NULL) parthp->thnxtstp = NULL;
+     else if (stp2->stmttyp != S_GOTO) parthp->thnxtstp = stp2;
+     else if (stp2->lpend_goto) parthp->thnxtstp = stp2;
+     else
+      {
+       for (;;)
+        {
+         /* know here stp2 is non loop end goto - moves to goto first */
+         if ((stp2 = stp2->st.sgoto) == NULL || stp2->stmttyp != S_GOTO)
+          { parthp->thnxtstp = stp2; break; }
+         if (stp2->lpend_goto) { parthp->thnxtstp = stp2; break; }
+        }
+      }
+     /* ??? REPLACED parthp->thnxtstp = parthp->thnxtstp->stnxt; */
+     parthp->th_postamble = FALSE;
+    }   
+
+   /* DBG remove --- */
+   if (__cur_thd->th_ialw) __misc_terr(__FILE__, __LINE__); 
+   if (parthp->thofscnt == 0) __misc_terr(__FILE__, __LINE__);
+   if (__debug_flg)
+    { __dbg_msg("*** thread finished:\n"); __dmp_thrd_info(__cur_thd); }
+   /* --- */
+
+   /* this thread finished - remove it from control thread d.s. */
+   thrd_done_cleanup(parthp);
+
+   /* more fork-join subthreads to complete */
+   if (parthp->thofscnt > 0) { __stmt_suspend = TRUE; break; }
+
+   /* all subthreads finished, continue with parent */
+   /* for enabled task (not named block), know out arg. store phase done */
+   parthp->thofs = NULL;
+   /* continue with parent by executing next statement */
+   /* no suspend here */
+   __cur_thd = parthp;
+   __pop_itstk();
+   __push_itstk(__cur_thd->th_itp);
+   stp = __cur_thd->thnxtstp;
+  }
+ /* DBG remove
+ if (!__stmt_suspend) __misc_terr(__FILE__, __LINE__);
+ --- */
+ /* only have current thread when evaling thread event */
+ __cur_thd = NULL;
+}
+
+
+/*
+ * routine to clean up linked thread control structure after thread done
+ *
+ * thread finished - clean up and try to continue in parent
+ * this removes various connected stuff but leave thread fields
+ *
+ * when done no current thread caller must set if needed
+ */
+static void thrd_done_cleanup(register struct thread_t *parthp)
+{
+ free_thd_stuff(__cur_thd);
+
+ /* move up and continue in parent */
+ parthp->thofscnt -= 1;
+ /* one thread of fork/join done - link it out after redundant cnt dec */
+ if (__cur_thd->thleft != NULL)
+  __cur_thd->thleft->thright = __cur_thd->thright;
+ /* adjust parent's thread ofset if removing first in list */
+ else parthp->thofs = __cur_thd->thright;
+
+ if (__cur_thd->thright != NULL)
+  __cur_thd->thright->thleft = __cur_thd->thleft;
+ /* free stuff already removed and events canceled so just free */
+ __my_free((char *) __cur_thd, sizeof(struct thread_t));
+ __cur_thd = NULL; 
+
+ /* RELEASE remove ---
+ if (parthp->thofscnt == 1)
+  {
+   if (parthp->thofs->thright != NULL
+    || parthp->thofs->thleft != NULL) __misc_terr(__FILE__, __LINE__);
+  }
+ --- */
+}
+
+/*
+ * print out trace location and time states
+ *
+ * no leading new line may need to have separate trace file if user output
+ * leaves unfinished lines.
+ *
+ * for statement tracing only change file name when module changes
+ * so line number will be in same * file
+ */
+static void tr_resume_msg(void)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ if (__inst_ptr != __last_tritp)
+  {
+   __tr_msg("==> tracing in %s (%s) line %s\n",
+    __msg2_blditree(s1, __inst_ptr), __inst_ptr->itip->imsym->synam,
+    __bld_lineloc(s2, (word32) __sfnam_ind, __slin_cnt));
+   __last_tritp = __inst_ptr;
+  }
+ if (__last_trtime != __simtime)
+  {
+   /* this should go through time format ? */
+   __tr_msg("<<< tracing at time %s\n", __to_timstr(s1, &__simtime));
+   __last_trtime = __simtime;
+  }
+}
+
+/*
+ * execute statement list
+ * called from thrd event processing routine and return when blocked or done
+ * execute until fall off end (thread done) or schedule wake up event
+ */
+static void exec_stmts(register struct st_t *stp)
+{
+ register word32 val;
+ register struct xstk_t *xsp;
+ int32 tmp, wlen;
+ struct st_t *stp2;
+ struct for_t *forp;
+ struct expr_t *cntx;
+
+ /* notice one pass through loop executes exactly 1 statement */
+ for (;;)
+  {
+   __slin_cnt = stp->stlin_cnt;
+   __sfnam_ind = stp->stfnam_ind;
+   __num_execstmts++;
+   /* DBG remove --
+   if (__cur_thd == NULL || __cur_thd->th_itp != __inst_ptr)
+    __misc_terr(__FILE__, __LINE__);
+   --- */
+
+   switch ((byte) stp->stmttyp) {
+    /* SJM - 02/08/02 - should not count empties as exec stmts */
+    case S_NULL: case S_STNONE: __num_execstmts--; break;
+    case S_FORASSGN:
+     __num_addedexec++; 
+     /* FALLTHRU */
+    case S_PROCA:
+     xsp = __eval_assign_rhsexpr(stp->st.spra.rhsx, stp->st.spra.lhsx);
+     __exec2_proc_assign(stp->st.spra.lhsx, xsp->ap, xsp->bp);
+     __pop_xstk();
+     break;
+    case S_NBPROCA:
+     /* only non delay form non blocking assign exec here - implied #0 */
+     xsp = __eval_assign_rhsexpr(stp->st.spra.rhsx, stp->st.spra.lhsx);
+     sched_nbproc_delay((struct delctrl_t *) NULL, xsp, stp);
+     __pop_xstk();
+     break;
+    case S_RHSDEPROCA:
+     /* notice this statement never executed directly - delctrl execed */ 
+     /* then after block - results execed here */
+     wlen = wlen_(stp->st.spra.lhsx->szu.xclen);
+     /* know rhs width here same as lhs width */
+     __exec2_proc_assign(stp->st.spra.lhsx, __cur_thd->th_rhswp,
+      &(__cur_thd->th_rhswp[wlen]));
+     /* must reset and free pending saved rhs over schedule */
+     __my_free((char *) __cur_thd->th_rhswp, 2*wlen*WRDBYTES);
+     __cur_thd->th_rhswp = NULL;
+     __cur_thd->th_rhswlen = -1;
+     __cur_thd->th_rhsform = FALSE;
+     break;
+    case S_IF:
+     xsp = __eval_xpr(stp->st.sif.condx);
+     /* condition T (non zero) only if at least 1, 1 */
+     if (xsp->xslen <= WBITS)
+      {
+       /* SJM 07/20/00 - must convert to real if real */
+       if (stp->st.sif.condx->is_real)
+        {
+         double d1;
+ 
+         memcpy(&d1, xsp->ap, sizeof(double));
+         tmp = (d1 != 0.0);
+        }
+       else tmp = ((xsp->ap[0] & ~xsp->bp[0]) != 0L);
+      }
+     else tmp = (__cvt_lngbool(xsp->ap, xsp->bp, wlen_(xsp->xslen)) == 1);
+     __pop_xstk();
+     if (tmp) stp = stp->st.sif.thenst;
+     else if (stp->st.sif.elsest != NULL) stp = stp->st.sif.elsest;
+     else stp = stp->stnxt;
+     goto nxt_stmt;
+    case S_CASE:
+     /* notice Verilog cases cannot fall thru */
+     if ((stp2 = exec_case(stp)) == NULL) break;
+     stp = stp2;
+     goto nxt_stmt;
+    case S_FOREVER: stp = stp->st.swh.lpst; goto nxt_stmt;
+    case S_REPSETUP:
+     /* know repeat stmt follows rep setup */
+     __num_addedexec++; 
+     cntx = stp->stnxt->st.srpt.repx;
+     xsp = __eval_xpr(cntx);
+     /* SJM 04/02/02 - real count must be converted to word/int32 */
+     if (cntx->is_real) __cnv_stk_fromreal_toreg32(xsp);
+     /* SJM 12/05/04 - ### ??? FIXME - what if wide and low word good? */
+     if (xsp->xslen > WBITS) __narrow_to1wrd(xsp);
+     if (xsp->ap[1] != 0L)
+      {
+       __sgfwarn(645,
+        "repeat loop in %s count has x/z expression value - loop skipped",
+        __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+       val = 0;
+      }
+     else
+      {
+       /* SJM 04/02/02 - if repeat count signed and negative, never exec */ 
+       if (cntx->has_sign && ((int32) xsp->ap[0]) <= 0) val = 0;
+       else val = xsp->ap[0];
+      }
+     __pop_xstk();
+     /* notice count must be converted to word32 with neg set to 0 */
+     /* set to 0 so after inced here and initial repeat exec dec, */
+     stp->stnxt->st.srpt.reptemp[__inum] = ++val;
+     break;
+    case S_REPEAT:
+     if ((val = --(stp->st.srpt.reptemp[__inum])) == 0L) break; 
+     stp = stp->st.srpt.repst;
+     goto nxt_stmt;
+    case S_WHILE:
+     xsp = __eval_xpr(stp->st.swh.lpx);
+     if (xsp->xslen <= WBITS)
+      {
+       /* SJM 07/20/00 - must convert to real if real */
+       if (stp->st.swh.lpx->is_real)
+        {
+         double d1;
+  
+         memcpy(&d1, xsp->ap, sizeof(double));
+         __pop_xstk();
+         /* must not emit informs from val if real */
+         if (d1 != 0.0) { stp = stp->st.swh.lpst; goto nxt_stmt; }
+         break;
+        }
+       val = xsp->bp[0];
+       if ((xsp->ap[0] & ~val) != 0L)
+        {
+         if (val != 0) 
+          {
+           __sgfinform(403, "while in %s condition true but some bits x/z",
+            __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+          }
+         __pop_xstk();
+         stp = stp->st.swh.lpst;
+         goto nxt_stmt;
+        }
+       /* notice any 1 implies true so will not get here */
+       if (val != 0)
+        {
+         __sgfinform(402,
+          "while loop in %s terminating false condition value has x/z bits",
+          __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+        }
+       __pop_xstk();
+       break;
+      } 
+     if ((tmp = __cvt_lngbool(xsp->ap, xsp->bp, wlen_(xsp->xslen))) == 1)
+      {
+       if (!vval_is0_(xsp->bp, xsp->xslen))
+        {
+         __sgfinform(403, "while condition in %s true but some bits x/z",
+          __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+        }
+       __pop_xstk();
+       stp = stp->st.swh.lpst;
+       goto nxt_stmt;
+      }
+     __pop_xstk();
+     /* notice any 1 implies true so will not get here */
+     if (tmp == 3)
+      {
+       __sgfinform(402,
+        "while loop terminating false condition in %s value has x/z bits",
+        __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+     }
+     break;
+    case S_WAIT:
+     /* on true expression, returns true */
+     if (exec_wait(stp)) { stp = stp->st.swait.lpst; goto nxt_stmt; }
+     /* is this unnecessary since action stmt points back to wait */
+     __cur_thd->thnxtstp = stp;
+     __stmt_suspend = TRUE;
+     return;
+    case S_FOR:
+     /* when loop done, for returns NULL as next stmt else 1st body st. */
+     forp = stp->st.sfor;
+     /* F when done */
+     if (!for_not_done(forp))
+      {
+       break;
+      }
+     stp = forp->forbody;
+     goto nxt_stmt;
+    case S_REPDCSETUP:
+     stp = exec_rep_ectl_setup(stp);
+     goto nxt_stmt;
+    case S_DELCTRL:
+     /* this returns F, for suspend, non blocking returns T */
+     /* 10/27/00 SJM - for repeat rhs ectrl count x/z <= 0 assign */
+     /* immediate so also return T */
+     if (exec_dctrl(stp)) { stp = __cur_thd->thnxtstp; goto nxt_stmt; }
+     __stmt_suspend = TRUE;
+     return;
+    case S_NAMBLK:
+     /* for function only, just continue in named block */
+     if (__fcspi >= 0) { stp = stp->st.snbtsk->tskst; goto nxt_stmt; }
+     exec_namblk(stp);
+     stp = __cur_thd->thnxtstp;
+     goto nxt_stmt;
+    case S_UNBLK:
+     stp = stp->st.sbsts;
+     goto nxt_stmt;
+    case S_UNFJ:
+     /* this is unnamed fork-join only */ 
+     __sched_fork(stp);
+     __cur_thd->thnxtstp = stp->stnxt;
+     __stmt_suspend = TRUE;
+     return;
+    case S_TSKCALL:
+     /* if system task, NULL will suspend, else continue in down thread */
+     if ((stp2 = __exec_tskcall(stp)) == NULL) return;
+     stp = stp2;
+     goto nxt_stmt;
+    case S_QCONTA:
+     if (stp->st.sqca->qcatyp == ASSIGN) __exec_qc_assign(stp, FALSE);
+     else
+      {
+       /* force of reg, is like assign except overrides assign */
+       if (stp->st.sqca->regform) __exec_qc_assign(stp, TRUE);
+       else __exec_qc_wireforce(stp);
+      }
+     break;
+    case S_QCONTDEA:
+     if (stp->st.sqcdea.qcdatyp == DEASSIGN) __exec_qc_deassign(stp, FALSE);
+     else
+      {
+       if (stp->st.sqcdea.regform) __exec_qc_deassign(stp, TRUE);
+       else __exec_qc_wirerelease(stp);
+      } 
+     break;
+    case S_CAUSE:
+     exec_cause(stp);
+     break;
+    case S_DSABLE:
+     /* if function, disable means continue with statement after block */ 
+     /* if disable of func. next statement is nil, so done with func. */
+     if (__fcspi >= 0) { stp = stp->st.sdsable.func_nxtstp; goto nxt_stmt; }
+
+     if (__exec_disable(stp->st.sdsable.dsablx)) goto thread_done;
+     /* disable elsewhere in control tree means just continue here */
+     break;
+    case S_GOTO:
+     stp = stp->st.sgoto;
+     /* notice goto of nil, ok just means done */ 
+     __num_addedexec++; 
+     goto nxt_stmt;
+    case S_BRKPT:
+     /* returns T on need to break */
+     if (__process_brkpt(stp)) goto nxt_stmt;
+
+     /* not a break for some reason - restore stmt type and exec 1 stmt */
+     /* if bp halt off 2nd time through after break, this execs */
+     stp->stmttyp = stp->rl_stmttyp;
+     /* execute the broken on stmt */
+     stp2 = __brktr_exec_1stmt(stp);
+     /* put back break pt. and make returned next stp as stp */
+     stp->stmttyp = S_BRKPT;
+     /* if nil will check to see if suspend or end of thread */
+     stp = stp2;
+     goto nxt_stmt;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   stp = stp->stnxt;
+nxt_stmt:
+   if (stp == NULL) break;
+   /* entry from exec of interactive command only if ctrl c hit */
+   if (__pending_enter_iact)  
+    { __stmt_suspend = TRUE; suspend_curthd(stp); return; }
+  }
+ /* when done with current function just return */
+ if (__stmt_suspend || __fcspi >= 0) return;
+thread_done:
+ __stmt_suspend = FALSE;
+ __cur_thd->thnxtstp = NULL;
+}
+
+/*
+ * tracing and break point processing version of exec statements
+ * called from thrd event processing routine and return when blocked or done
+ * execute until fall off end (thread done) or schedule wake up event
+ */
+static void brktr_exec_stmts(register struct st_t *stp)
+{
+ /* notice one pass through loop executes exactly 1 statement */
+ for (;;)
+  {
+   /* here if nil returned force suspend - exec set thread next statement */
+   stp = __brktr_exec_1stmt(stp);
+   if (stp == NULL) break;
+   /* if done with thread, will detect enter iact flag in higher routine */ 
+   if (__pending_enter_iact)  
+    { __stmt_suspend = TRUE; suspend_curthd(stp); return; }
+  }
+ if (__stmt_suspend) return;
+ __cur_thd->thnxtstp = NULL;
+}
+
+/*
+ * exec statements while stepping
+ * special case if break hit in here
+ * called from thrd event processing routine and return when blocked or done
+ * execute until fall off end (thread done) or schedule wake up event
+ */
+static void step_exec_stmt(register struct st_t *stp)
+{
+ /* notice one pass through loop executes exactly 1 statement */
+ for (;;)
+  {
+   /* if step command when iact entered from iact thread or ^c step to 1st */
+   /* of new thread not one more statement */
+   if (__step_from_thread) stp = __brktr_exec_1stmt(stp);
+   else __step_from_thread = TRUE;
+
+   /* if hit break point while stepping, disable stepping and return */
+   /* suspend already done */
+   if (__pending_enter_iact && __iact_reason == IAER_BRKPT)
+    {
+     __single_step = FALSE;
+     __step_rep_cnt = 0;  
+     __step_match_itp = NULL; 
+     __verbose_step = FALSE;
+     /* since rexec stmt, must have current thread */
+     /* DBG remove --- */
+     if (stp == NULL || __cur_thd == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     __last_stepitp = __cur_thd->th_itp;
+     __last_steptskp = __cur_thd->assoc_tsk;
+     __last_stepifi = (int32) stp->stfnam_ind;
+     __step_lini = stp->stlin_cnt;
+     __step_ifi = (int32) stp->stfnam_ind;
+     /* must suspend */
+     __stmt_suspend = TRUE;
+     suspend_curthd(stp);
+     return;
+    }
+   /* must exit loop since done with this thread */
+   if (stp == NULL)
+    {
+     if (!__stmt_suspend)
+      { __step_lini = -1; __step_ifi = -1; __cur_thd->thnxtstp = NULL; }
+     return;
+    }
+
+   /* if istep (within cur. itree inst. only) continue if different */
+   if (__step_match_itp != NULL && __inst_ptr != __step_match_itp)
+    continue;
+   /* in same instance, make sure move to next line - keep exec ing */
+   if (stp->stlin_cnt == __step_lini && (int32) stp->stfnam_ind == __step_ifi)
+    continue;
+   /* hit step point, need to enter iact */
+   break;
+  }
+ /* hit step stop know step non nil, suspend and return */
+ /* set current step line in case in loop - most move to next line */
+ __step_lini = stp->stlin_cnt;
+ __step_ifi = (int32) stp->stfnam_ind;
+ /* stepped to something to stop at */
+ if (stepped_to_new_loc(stp))
+  {
+   __last_stepitp = __inst_ptr;
+   __last_steptskp = __cur_thd->assoc_tsk;
+   __last_stepifi = (int32) stp->stfnam_ind; 
+
+    /* FIXME - is this __tr_s tracing ??? */
+   __cvsim_msg("%s (%s line %d)", __msg_blditree(__xs, __last_stepitp,
+    __last_steptskp), __in_fils[__last_stepifi], stp->stlin_cnt);
+   if (__last_brktime != __simtime)
+    {
+     __cvsim_msg(" time %s\n", __to_timstr(__xs, &__simtime));
+     __last_brktime = __simtime;
+    }
+   else __cvsim_msg("\n");
+  }
+ /* notice only change list location if print */
+ if (__verbose_step)
+  __prt_src_lines((int32) stp->stfnam_ind, stp->stlin_cnt, stp->stlin_cnt);
+ __single_step = FALSE;
+ /* if more stepping, continue using istep itp matching if needed */
+ if (__step_rep_cnt <= 1) __step_match_itp = NULL; 
+ __verbose_step = FALSE;
+ suspend_curthd(stp);
+ /* even if interrupt (^c) received, doing again does not hurt */
+ signal(SIGINT, SIG_IGN);
+ /* when execing interactive command, never single stepped */
+ __pending_enter_iact = TRUE;
+ __iact_reason = IAER_STEP;  
+}
+
+/*
+ * return T if stepped to new scope or new file
+ */
+static int32 stepped_to_new_loc(struct st_t *stp)
+{
+ if (__last_stepitp != __inst_ptr
+  || __last_steptskp != __cur_thd->assoc_tsk
+  || __last_stepifi != (int32) stp->stfnam_ind
+  || __last_brktime != __simtime) return(TRUE); 
+ return(FALSE);
+}
+
+/*
+ * break point and tracing version of execute one statement
+ * also for executing non delay interactive statements
+ */
+extern struct st_t *__brktr_exec_1stmt(struct st_t *stp)
+{
+ register word32 val;
+ int32 tmp, wlen;
+ struct st_t *stp2;
+ struct xstk_t *xsp;
+ struct for_t *forp;
+ struct if_t *ifinfo;
+ struct expr_t *cntx;
+
+again:
+ /* notice must set location here - few cases where more than 1 stmt here */
+ __slin_cnt = stp->stlin_cnt;
+ __sfnam_ind = stp->stfnam_ind;
+ __num_execstmts++;
+ switch ((byte) stp->stmttyp) {
+  case S_NULL: case S_STNONE: break;
+  case S_FORASSGN:
+   xsp = __eval_assign_rhsexpr(stp->st.spra.rhsx, stp->st.spra.lhsx);
+   __exec2_proc_assign(stp->st.spra.lhsx, xsp->ap, xsp->bp);
+   if (__st_tracing) tr_proc_assign(stp, xsp);
+   __pop_xstk();
+   stp = stp->stnxt;
+   __num_addedexec++; 
+   __num_execstmts++;
+   goto again;
+  case S_PROCA:
+   xsp = __eval_assign_rhsexpr(stp->st.spra.rhsx, stp->st.spra.lhsx);
+   __exec2_proc_assign(stp->st.spra.lhsx, xsp->ap, xsp->bp);
+   if (__st_tracing) tr_proc_assign(stp, xsp);
+   __pop_xstk();
+   break;
+  case S_NBPROCA:
+   /* only non delay form non blocking assign exec here - implied #0 */
+   xsp = __eval_assign_rhsexpr(stp->st.spra.rhsx, stp->st.spra.lhsx);
+   if (__st_tracing) tr_nbproc_assign(stp, xsp);
+   sched_nbproc_delay((struct delctrl_t *) NULL, xsp, stp);
+   __pop_xstk();
+   break;
+  case S_RHSDEPROCA:
+   /* this is continuation point for rhs form after block */
+   wlen = wlen_(stp->st.spra.lhsx->szu.xclen);
+   __exec2_proc_assign(stp->st.spra.lhsx, __cur_thd->th_rhswp,
+    &(__cur_thd->th_rhswp[wlen]));
+   if (__st_tracing)
+    {
+     /* here delay statement already displayed */
+     __tr_msg("trace: %-7d %s = [%s] (saved rhs assign)\n", __slin_cnt,
+      __msgexpr_tostr(__xs, stp->st.spra.lhsx),
+      __xregab_tostr(__xs2, __cur_thd->th_rhswp, &(__cur_thd->th_rhswp[wlen]),
+      stp->st.spra.lhsx->szu.xclen, stp->st.spra.rhsx));
+    }
+   /* must reset and free pending saved rhs over schedule */
+   __my_free((char *) __cur_thd->th_rhswp, 2*wlen*WRDBYTES);
+   __cur_thd->th_rhswp = NULL;
+   __cur_thd->th_rhswlen = -1;
+   __cur_thd->th_rhsform = FALSE;
+   break;
+  case S_IF:
+   ifinfo = &(stp->st.sif);
+   xsp = __eval_xpr(ifinfo->condx);
+   /* condition T (1) only if at least 1, 1 */
+   if (xsp->xslen <= WBITS)
+    {
+     /* SJM 07/20/00 - must convert to real if real */
+     if (ifinfo->condx->is_real)
+      {
+       double d1;
+
+       memcpy(&d1, xsp->ap, sizeof(double));
+       tmp = (d1 != 0.0);
+      }
+     else tmp = ((xsp->ap[0] & ~xsp->bp[0]) != 0L);
+    }
+   else tmp = (__cvt_lngbool(xsp->ap, xsp->bp, wlen_(xsp->xslen)) == 1);
+   __pop_xstk();
+   if (__st_tracing)
+    __tr_msg("trace: %-7d if (%s) [cond %d]\n", __slin_cnt,
+     __msgexpr_tostr(__xs, ifinfo->condx), tmp);
+   if (tmp) stp = ifinfo->thenst;
+   else if (ifinfo->elsest != NULL) stp = ifinfo->elsest;
+   else stp = stp->stnxt;
+   return(stp);
+  case S_CASE:
+   /* notice Verilog cases cannot fall thru */
+   if ((stp2 = exec_case(stp)) == NULL) break;
+   return(stp2);
+  case S_FOREVER:
+   if (__st_tracing) __tr_msg("trace: %-7d forever\n", __slin_cnt);
+   return(stp->st.swh.lpst);
+  case S_REPSETUP:
+   /* know repeat stmt follows rep setup */
+   __num_addedexec++; 
+   cntx = stp->stnxt->st.srpt.repx;
+   xsp = __eval_xpr(cntx);
+   /* SJM 04/02/02 - real count must be converted to word/int32 */
+   if (cntx->is_real) __cnv_stk_fromreal_toreg32(xsp);
+   if (xsp->xslen > WBITS) __narrow_to1wrd(xsp);
+
+   if (xsp->ap[1] != 0L)
+    {
+     __last_stepitp = __cur_thd->th_itp;
+     __last_steptskp = __cur_thd->assoc_tsk;
+     __sgfwarn(645,
+      "repeat loop in %s count has x/z expression value - loop skipped",
+      __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+     val = 0;
+    }
+   else
+    {
+     /* SJM 04/02/02 - if repeat count signed and negative, never exec */ 
+     if (cntx->has_sign && ((int32) xsp->ap[0]) <= 0) val = 0;
+     else val = xsp->ap[0];
+    }
+   __pop_xstk();
+   /* notice count must be converted to word32 with neg set to 0 */
+   stp->stnxt->st.srpt.reptemp[__inum] = ++val;
+   break;
+  case S_REPEAT:
+   val = --(stp->st.srpt.reptemp[__inum]); 
+   if (__st_tracing)
+    {
+     __tr_msg("trace: %-7d repeat (%s) [count %u]\n", __slin_cnt,
+      __msgexpr_tostr(__xs, stp->st.srpt.repx), val);
+    }
+   if (val == 0L) break;
+   return(stp->st.srpt.repst);
+  case S_WHILE:
+   xsp = __eval_xpr(stp->st.swh.lpx);
+   if (xsp->xslen <= WBITS)
+    {
+     if (stp->st.swh.lpx->is_real)
+      { 
+       double d1;
+
+       memcpy(&d1, xsp->ap, sizeof(double));
+       if (d1 != 0.0) tmp = 1; else tmp = 0;
+       goto while_end;
+      }
+     val = xsp->bp[0];
+     if ((xsp->ap[0] & ~val) != 0L)
+      {
+       if (val != 0) 
+        {
+         __sgfinform(403, "while in %s condition true but some bits x/z",
+          __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+        }
+       tmp = 1;
+       goto while_end;
+      }
+     /* notice any 1 implies true so will not get here */
+     if (val != 0)
+      {
+        __sgfinform(402,
+        "while loop in %s terminating false condition value has x/z bits",
+        __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+      } 
+     tmp = 0;
+     goto while_end;
+    } 
+   if ((tmp = __cvt_lngbool(xsp->ap, xsp->bp, wlen_(xsp->xslen))) == 1)
+    {
+     if (!vval_is0_(xsp->bp, xsp->xslen))
+      {
+       __sgfinform(403, "while in %s condition true but some bits x/z",
+        __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+      }
+     goto while_end;
+    }
+   /* notice any 1 implies true so will not get here */
+   if (tmp == 3)
+    {
+     __sgfinform(402,
+      "while loop in %s terminating false condition value has x/z bits",
+      __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+    }
+   
+while_end:
+   __pop_xstk();
+   if (__st_tracing)
+    __tr_msg("trace: %-7d while (%s) [cond: %d]\n", __slin_cnt,
+     __msgexpr_tostr(__xs, stp->st.swh.lpx), tmp);
+   if (tmp == 1) return(stp->st.swh.lpst);
+   return(stp->stnxt);
+  case S_WAIT:
+   /* on true expression, returns true */
+   if (exec_wait(stp)) return(stp->st.swait.lpst);
+   /* is this unnecessary since action stmt points back to wait */
+   __cur_thd->thnxtstp = stp;
+   __stmt_suspend = TRUE;
+   return(NULL);
+  case S_FOR:
+   /* when loop done for returns NULL as next statement else 1st body st. */
+   forp = stp->st.sfor;
+   if (!for_not_done(forp))
+    break;
+   return(forp->forbody);
+  case S_REPDCSETUP:
+   /* 10/27/00 SJM - added repeat form rhs ectl and nb proca ectl setup */
+   /* next statment is s delctrl or one after if repeat cnt x/z or <= 0 */ 
+   return(exec_rep_ectl_setup(stp));
+  case S_DELCTRL:
+   /* this returns F, for suspend, non blocking returns T */
+   /* 10/27/00 SJM - for repeat rhs ectrl count x/z <= 0 assign */
+   /* immediate so also return T */
+   if (exec_dctrl(stp)) return(__cur_thd->thnxtstp);
+   __stmt_suspend = TRUE;
+   return(NULL);
+  case S_NAMBLK:
+   /* for function only, just continue in named block */
+   if (__fcspi >= 0)
+    {
+     if (__st_tracing)
+      {
+       __tr_msg("trace: %-7d begin : %s\n", __slin_cnt,
+        stp->st.snbtsk->tsksyp->synam);
+      }
+     return(stp->st.snbtsk->tskst);
+    }
+   /* know this is new down thread - know at least 1 statement */
+   exec_namblk(stp);
+   return(__cur_thd->thnxtstp);
+  case S_UNBLK:
+   if (__st_tracing) __tr_msg("trace: %-7d begin\n", __slin_cnt);
+   return(stp->st.sbsts);
+  case S_UNFJ:
+   /* this is unnamed fork-join only */ 
+   if (__st_tracing) __tr_msg("trace: %-7d fork\n", __slin_cnt);
+   __sched_fork(stp);
+   __cur_thd->thnxtstp = stp->stnxt;
+   __stmt_suspend = TRUE;
+   return(NULL);
+  case S_TSKCALL:
+   /* if system task, NULL will suspend, else continue in down thread */
+   if ((stp2 = __exec_tskcall(stp)) == NULL) return(NULL);
+   return(stp2);
+  case S_QCONTA:
+   if (stp->st.sqca->qcatyp == ASSIGN) __exec_qc_assign(stp, FALSE);
+   else
+    {
+     /* force of reg, is like assign except overrides assign */
+     if (stp->st.sqca->regform) __exec_qc_assign(stp, TRUE);
+     else __exec_qc_wireforce(stp);
+    }
+   if (__st_tracing)
+    {
+     char s1[RECLEN], s2[RECLEN];
+
+     strcpy(s2, "");  
+     if (stp->st.sqca->qcatyp == ASSIGN)
+      {
+       strcpy(s1, "assign");
+       if (__force_active) strcpy(s2, " [active force effect hidden]"); 
+      }
+     else
+      {
+       strcpy(s1, "force");
+       if (__assign_active) strcpy(s2, " [assign value saved]");
+      }
+     __tr_msg("trace: %-7d %s %s = %s%s\n", __slin_cnt, s1, 
+      __msgexpr_tostr(__xs, stp->st.sqca->qclhsx),
+      __msgexpr_tostr(__xs2, stp->st.sqca->qcrhsx), s2);
+    }
+   /* --- DBG remove 
+   __dmpmod_nplst(__inst_mod, TRUE); 
+   --- */
+   __force_active = FALSE;
+   __assign_active = FALSE;
+   break;
+  case S_QCONTDEA:
+   if (stp->st.sqcdea.qcdatyp == DEASSIGN) __exec_qc_deassign(stp, FALSE);
+   else
+    {
+     if (stp->st.sqcdea.regform) __exec_qc_deassign(stp, TRUE);
+     else __exec_qc_wirerelease(stp);
+    } 
+
+   if (__st_tracing)
+    {
+     char s1[RECLEN], s2[RECLEN];
+
+     strcpy(s2, "");  
+     if (stp->st.sqcdea.qcdatyp == DEASSIGN)
+      {
+       strcpy(s1, "deassign");
+       if (__force_active) strcpy(s2, " [active force effect hidden]"); 
+      }
+     else
+      {
+       strcpy(s1, "release");
+       if (__assign_active) strcpy(s2, " [assign value restored]");
+      }
+     __tr_msg("trace: %-7d %s %s%s\n", __slin_cnt, s1, 
+      __msgexpr_tostr(__xs, stp->st.sqcdea.qcdalhs), s2);
+    }
+   __force_active = FALSE;
+   __assign_active = FALSE;
+   break;
+  case S_CAUSE:
+   exec_cause(stp);
+   break;
+  case S_DSABLE:
+   if (__st_tracing)
+    {
+     __tr_msg("trace: %-7d disable %s;\n", __slin_cnt,
+      __msgexpr_tostr(__xs, stp->st.sdsable.dsablx));
+    }
+   /* if function, disable means continue with statement after block */ 
+   if (__fcspi >= 0) return(stp->st.sdsable.func_nxtstp);
+
+   /* here - done - suspend off so nil will end thread */
+   /* xmr disable will mark some thread and return F */ 
+   if (__exec_disable(stp->st.sdsable.dsablx)) return(NULL);
+   break;
+  case S_GOTO:
+   stp = stp->st.sgoto;
+   /* debug to nil ok, just end of list */
+   __num_addedexec++; 
+   if (__st_tracing)
+    __tr_msg("trace: %-7d --continue %s\n", __slin_cnt, 
+     __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt));
+   __num_execstmts++;
+   return(stp);
+  /* do not trace break during break - may trace when execed */ 
+  case S_BRKPT:
+   /* returns T on need to break */
+   if (__process_brkpt(stp)) return(stp); 
+
+   /* not a break for some reason - restore stmt type and exec 1 stmt */
+   /* if bp halt off 2nd time through after break, this execs */
+   stp->stmttyp = stp->rl_stmttyp;
+   stp2 = __brktr_exec_1stmt(stp);
+   stp->stmttyp = S_BRKPT;
+   return(stp2);
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(stp->stnxt);
+}
+
+/*
+ * evaluate an procedural assign rhs expression and convert to form
+ * needed for assignment
+ * handles real conversion and size changes - never z widening
+ * know returned stack width always exactly matches lhs width
+ */
+extern struct xstk_t *__eval_assign_rhsexpr(register struct expr_t *xrhs,
+ register struct expr_t *xlhs)
+{
+ register struct xstk_t *xsp;
+
+ xsp = __eval_xpr(xrhs);
+ if (xlhs->is_real)
+  { 
+   /* needed: think passing packed bit does not work on all compilers ? */ 
+   if (!xrhs->is_real) __cnv_stk_fromreg_toreal(xsp, (xrhs->has_sign == 1));
+  }
+ else
+  { 
+   /* handle rhs preparation of reals - then assign is just copy for reals */
+   if (xrhs->is_real) __cnv_stk_fromreal_toreg32(xsp);
+
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp->xslen > xlhs->szu.xclen) __narrow_sizchg(xsp, xlhs->szu.xclen);
+   else if (xsp->xslen < xlhs->szu.xclen)
+    {
+     if (xrhs->has_sign) __sgn_xtnd_widen(xsp, xlhs->szu.xclen);
+     else __sizchg_widen(xsp, xlhs->szu.xclen);
+    }
+  }
+ return(xsp);
+}
+
+/*
+ * evaulate task assign - only different if form of various flags 
+ */
+static void eval_tskassign_rhsexpr(register struct xstk_t *xsp,
+ register int32 lhsreal, register int32 lhswid, register int32 rhsreal,
+ register int32 rhssign)
+{
+ if (lhsreal)
+  { 
+   /* think passing packed bit does not work on all compilers ? */ 
+   if (!rhsreal) __cnv_stk_fromreg_toreal(xsp, rhssign);
+  }
+ else
+  { 
+   /* handle rhs preparation of reals - then assign is just copy for reals */
+   if (rhsreal) __cnv_stk_fromreal_toreg32(xsp);
+
+   if (xsp->xslen > lhswid) __narrow_sizchg(xsp, lhswid);
+   else if (xsp->xslen < lhswid)
+    {
+     if (rhssign) __sgn_xtnd_widen(xsp, lhswid);
+     else __sizchg_widen(xsp, lhswid);
+    }
+  }
+}
+
+/*
+ * trace an assignment statement
+ * notice this expects rhs value to be on top of stack (caller pops)
+ *
+ * ok to use rgab_tostr here since know __exprline can not be in use before
+ * statement execution begins
+ */
+static void tr_proc_assign(struct st_t *stp, struct xstk_t *xsp)
+{
+ struct expr_t *xrhs;
+
+ __cur_sofs = 0;
+ __dmp_proc_assgn((FILE *) NULL, stp, (struct delctrl_t *) NULL, FALSE);
+ __exprline[__cur_sofs] = 0; 
+ __trunc_exprline(TRTRUNCLEN, FALSE);
+ __tr_msg("trace: %-7d %s", __slin_cnt, __exprline);
+ xrhs = stp->st.spra.rhsx;
+ /* if rhs is number value is obvious, else print value that was assigned */
+ /* any conversion to lhs already made so expr. info from lhs */ 
+ if (xrhs->optyp != NUMBER && xrhs->optyp != REALNUM)
+  {
+   __tr_msg(" [%s]\n", __xregab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen,
+    stp->st.spra.lhsx));
+  }
+ else __tr_msg("\n");
+ __cur_sofs = 0;
+}
+
+/*
+ * trace an non blocking assignment statement
+ * notice this expects rhs value to be on top of stack (caller pops)
+ *
+ * ok to use rgab_tostr here since know __exprline can not be in use before
+ * statement execution begins
+ */
+static void tr_nbproc_assign(struct st_t *stp, struct xstk_t *xsp)
+{
+ struct expr_t *xrhs;
+
+ __cur_sofs = 0;
+ __dmp_nbproc_assgn((FILE *) NULL, stp, (struct delctrl_t *) NULL);
+ __exprline[__cur_sofs] = 0; 
+ __trunc_exprline(TRTRUNCLEN, FALSE);
+ __tr_msg("trace: %-7d %s", __slin_cnt, __exprline);
+ xrhs = stp->st.spra.rhsx;
+ if (xrhs->optyp != NUMBER && xrhs->optyp != REALNUM)
+  {
+   __tr_msg(" [%s]\n", __xregab_tostr(__xs, xsp->ap, xsp->bp,
+    xsp->xslen, xrhs));
+  }
+ else __tr_msg("\n");
+ __cur_sofs = 0;
+}
+
+/*
+ * execute repeat event setup (rhs nb ectl proca or rhs ectl delay  
+ * know rhs DEL CTRL stmt with repeat form rhs ev control follows
+ * only can be rhs ev control or rhs non blocking assign ev ctrl
+ */
+static struct st_t *exec_rep_ectl_setup(struct st_t *stp)
+{
+ register struct xstk_t *xsp;
+ register struct st_t *nxtstp, *astp;
+ struct delctrl_t *rdctp;
+ word32 val;
+
+ __num_addedexec++; 
+ nxtstp = stp->stnxt;
+ /* DBG RELEASE remove --- */
+ if (nxtstp->stmttyp != S_DELCTRL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ rdctp = nxtstp->st.sdc;
+ xsp = __eval_xpr(rdctp->repcntx);
+ /* SJM 04/02/02 - real count must be converted to word/int32 */
+ if (rdctp->repcntx->is_real) __cnv_stk_fromreal_toreg32(xsp);
+
+ /* FIXME ??? - although know WBITS wide, should use bp here */
+ if (xsp->ap[1] != 0L)
+  {
+   __sgfwarn(645,
+    "repeat event control in %s count has x/z value - no wait for event",
+    __msg_blditree(__xs, __cur_thd->th_itp, __cur_thd->assoc_tsk));
+   __pop_xstk();
+
+immed_ectl_exec:     
+   astp = nxtstp->st.sdc->actionst;
+   xsp = __eval_assign_rhsexpr(astp->st.spra.rhsx, astp->st.spra.lhsx);
+   if (astp->stmttyp == S_NBPROCA)
+    {
+     /* case 1: NB assign - becomes no delay NB assign form */ 
+     sched_nbproc_delay(NULL, xsp, astp);
+    }
+   else
+    {
+     /* case 2: rhs repeat event control - treat as simple proca */ 
+     __exec2_proc_assign(astp->st.spra.lhsx, xsp->ap, xsp->bp);
+    }
+   __pop_xstk();
+   /* continuation statment is one after S DELCTRL since no ev ctrl */
+   /* in this case */
+   return(nxtstp->stnxt);
+  }
+ /* if signed and <= 0, or word32 equal to 0, becomes immediate assign */
+ /* SJM 04/02/02 - need to use word32 counter and convert neg to 0 */
+ if (rdctp->repcntx->has_sign && (int32) xsp->ap[0] <= 0) val = 0;
+ else val = xsp->ap[0];
+ __pop_xstk();
+ if (val == 0) goto immed_ectl_exec;
+
+ /* val now number of edges (if 1 same as normal rhs ectrl */
+ /* notice, here never exec unless at least one so do not need inc */
+ rdctp->dce_repcnts[__inum] = val;
+ return(nxtstp);
+}
+
+/*
+ * execute a delay control indicator
+ * notice this arms or schedules something - caller suspends thread
+ * this return T if non blocking assign needs to not schedule
+ */
+static int32 exec_dctrl(struct st_t *stp)
+{
+ int32 bytes, wlen;
+ word32 *wp;
+ struct delctrl_t *dctp;
+ struct xstk_t *xsp;
+ struct st_t *astp;
+
+ dctp = stp->st.sdc;
+ if (__st_tracing)
+  {
+   __evtr_resume_msg();
+   __cur_sofs = 0;
+   if (dctp->actionst == NULL || dctp->dctyp == DC_RHSEVENT
+    || dctp->dctyp == DC_RHSDELAY) __dmp_dctrl((FILE *) NULL, dctp);
+   else
+    {
+     if (dctp->dctyp == DC_EVENT) addch_('@'); else addch_('#');
+     __dmp_dcxpr((FILE *) NULL, dctp->dc_du, dctp->dc_delrep);
+    }
+   __trunc_exprline(TRTRUNCLEN, FALSE);
+   __tr_msg("trace: %-7d %s\n", __slin_cnt, __exprline);
+   __cur_sofs = 0;
+  }
+ /* for all but non blocking assign block - continue with action statement */
+ if (dctp->actionst == NULL) __cur_thd->thnxtstp = stp->stnxt;
+ else __cur_thd->thnxtstp = dctp->actionst;
+
+ switch ((byte) dctp->dctyp) {
+  case DC_DELAY:
+   sched_proc_delay(dctp, (word32 *) NULL, -1);
+   break;
+  case DC_EVENT:
+   arm_event_dctrl(dctp, (word32 *) NULL, -1);
+   break; 
+  case DC_RHSDELAY: case DC_RHSEVENT:
+   /* 10/28/00 SJM - only rhs event either blocking or non blocking */
+   /* can have repeat form */
+   astp = dctp->actionst;
+   /* rhs # delay or event ctrl */
+   /* -- DBG remove
+   if (astp == NULL || (astp->stmttyp != S_RHSDEPROCA
+    && astp->stmttyp != S_NBPROCA)) __arg_terr(__FILE__, __LINE__);
+   --- */ 
+
+   /* evaluate rhs and schedule as usual */
+   /* notice this depends on contiguous xsp a and b parts */
+   xsp = __eval_assign_rhsexpr(astp->st.spra.rhsx, astp->st.spra.lhsx);
+
+   if (astp->stmttyp == S_NBPROCA)
+    {
+     /* for non blocking assign - must not exec assign - event processing */
+     /* routine does that, must continue after actionst if can else nxt */
+     if (dctp->actionst != NULL && dctp->actionst->stnxt != NULL)
+      __cur_thd->thnxtstp = dctp->actionst->stnxt;
+     else __cur_thd->thnxtstp = stp->stnxt;
+     
+     if (dctp->dctyp == DC_RHSDELAY) sched_nbproc_delay(dctp, xsp, astp);
+     else arm_nbevent_dctrl(dctp, xsp, astp);
+     __pop_xstk();
+     return(TRUE);
+    }
+   /* continuation point for rhs delay form is action statement if exists */
+   /* that is same as normal delay control */
+
+   /* if blocking allocate and store - no inertial problems for blocking */
+   /* SJM - 01/12/00 - wlen_ omitted so here was large memory leak */
+   /*                  was only freeing 4/32 percent of bytes */
+   wlen = wlen_(astp->st.spra.lhsx->szu.xclen);
+   bytes = 2*WRDBYTES*wlen;
+   
+   wp = (word32 *) __my_malloc(bytes);
+   memcpy(wp, xsp->ap, bytes); 
+
+   if (dctp->dctyp == DC_RHSDELAY) sched_proc_delay(dctp, wp, wlen);
+   else arm_event_dctrl(dctp, wp, wlen);
+   __pop_xstk();
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(FALSE);
+}
+
+/*
+ * schedule procedural delay thread simple prefix timing delay
+ *
+ * must continue after wake up with same thread (contents?)
+ * before call statement set to statement to exec after wake up
+ * also handles rhs delay form
+ *
+ * notice on disable event canceled and any rhs value free but that is
+ * all that is needed
+ */
+static void sched_proc_delay(struct delctrl_t *dctp, word32 *wp, int32 wlen)
+{
+ register i_tev_ndx tevpi;
+ register struct tev_t *tevp;
+ word64 t, schtim;
+ struct st_t *stp;
+
+ /* this can not be edge delay or syntax error before here */
+ __get_del(&t, dctp->dc_du, dctp->dc_delrep);  
+ schtim = __simtime + t;
+ alloc_tev_(tevpi, TE_THRD, __inst_ptr, schtim);
+ /* set the associate event - after return, __cur_thd will be new */
+ __cur_thd->thdtevi = tevpi;
+ /* restart current - will block after here and change threads */
+ tevp = &(__tevtab[tevpi]);
+ tevp->tu.tethrd = __cur_thd;
+ /* if rhs delay form, set values */ 
+ if (wp != NULL)
+  {
+   __cur_thd->th_rhsform = TRUE;
+   __cur_thd->th_rhswp = wp;
+   __cur_thd->th_rhswlen = wlen;  
+  }
+
+ if (__ev_tracing)
+  {
+   char s1[RECLEN], vs2[10];
+
+   __evtr_resume_msg();
+   if (wp == NULL) strcpy(vs2, ""); else strcpy(vs2, "(rhs)");
+   stp = tevp->tu.tethrd->thnxtstp;
+   __tr_msg("-- scheduling delay resume%s at %s for time %s\n",
+    vs2, __bld_lineloc(s1, stp->stfnam_ind, stp->stlin_cnt),
+    __to_timstr(__xs, &(tevp->etime)));
+  }
+ /* notice that procedural #0 (does not need to be rhs assign form) */
+ /* done after all normal events */
+ if (t == 0ULL)
+  {
+   if (__debug_flg && __ev_tracing)
+    {
+     __tr_msg("sched: adding #0 %s event to list end\n",
+      __to_tetyp(__xs, tevp->tetyp));
+    }
+   /* notice pound 0 only added from current time events */
+   if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+   else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+  }
+ /* if non blocking procedural assign, insert in normal moved to #0 later */
+ else __insert_event(tevpi);
+}
+
+/*
+ * schedule non blocking procedural assign simple prefix timing delay
+ *
+ * this is simple because of strange non hardware related semantics
+ * every time a non blocking delay assigned is executed, just compute
+ * delay and schedule - can have >1 events per unit or per statement
+ * but just schedule and forget
+ */
+static void sched_nbproc_delay(struct delctrl_t *dctp, struct xstk_t *xsp,
+ struct st_t *stp)
+{
+ i_tev_ndx tevpi;
+ word64 t, schtim;
+
+ /* if no delay form, schedule at end of currnt time #0s */
+ if (dctp == NULL) t = 0ULL;
+ /* error before here if edge dependent delay */
+ else __get_del(&t, dctp->dc_du, dctp->dc_delrep);  
+ schtim = __simtime + t;
+
+ if (__ev_tracing)
+  {
+   char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+   __evtr_resume_msg();
+   __tr_msg(
+    "-- scheduling delay form non blocking assign line %s now %s in %s:\n",
+    __bld_lineloc(s1, stp->stfnam_ind, stp->stlin_cnt),
+    __to_timstr(s2, &__simtime), __msg2_blditree(s3, __inst_ptr));
+   __tr_msg(" NB SCHEDULE TO NEW VALUE %s AT TIME %s\n",
+    __xregab_tostr(s1, xsp->ap, xsp->bp, stp->st.spra.rhsx->szu.xclen,
+     stp->st.spra.rhsx), __to_timstr(s2, &schtim));
+  }
+
+ /* build the disable remove list for possibly multiple active nb forms */
+ tevpi = __bld_nb_tev(stp, xsp, schtim); 
+ /* final step is inserting event in list */
+ /* no dleay form becomes #0 schedule for assign event here */
+ if (t == 0ULL)
+  {
+   if (__debug_flg && __ev_tracing)
+    {
+     __tr_msg("sched: adding #0 %s event to list end\n",
+      __to_tetyp(__xs, __tevtab[tevpi].tetyp));
+    }
+   /* notice pound 0 only added for current time events */
+   /* AIV 06/28/05 - if option not set add to the end of the nb #0 list */
+   if (!__nb_sep_queue)
+    {
+     if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+     else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+    }
+   else
+    {
+     /* AIV 07/05/05 - to match XL need nb te list that only processed */
+     /* when all pnd 0s done */  
+     /* effectively adds another section to current time event queue */
+     if (__nb_te_hdri == -1) __nb_te_hdri = __nb_te_endi = tevpi;
+     else { __tevtab[__nb_te_endi].tenxti = tevpi; __nb_te_endi = tevpi; }
+    }
+  }
+ /* if non blocking procedural assign, insert in normal moved to #0 later */
+ else __insert_event(tevpi);
+}
+
+/*
+ * build and emit trace message for non blocking schedule or trigger
+ * notice these are not inertial - just keep scheduling
+ * never cancel or re-schedule
+ *
+ * SJM 08/08/99 - change so if lhs expr (maybe concat) has non constant
+ * bit selects copy and then evaluate variable indices to numbers
+ * and change copied expr.
+ *
+ * BEWARE - code here and in many places assumes numeric expressions
+ * folded to number or IS number by here
+ */
+extern i_tev_ndx __bld_nb_tev(struct st_t *stp, struct xstk_t *xsp,
+ word64 schtim)
+{
+ register struct tenbpa_t *nbpap;
+ register word32 *wp;
+ i_tev_ndx tevpi;
+ int32 wlen; 
+ struct expr_t *lhsxp;
+
+ alloc_tev_(tevpi, TE_NBPA, __inst_ptr, schtim);
+ nbpap = (struct tenbpa_t *) __my_malloc(sizeof(struct tenbpa_t)); 
+ __tevtab[tevpi].tu.tenbpa = nbpap;
+ wlen = wlen_(stp->st.spra.lhsx->szu.xclen);
+ wp = (word32 *) __my_malloc(2*wlen*WRDBYTES);
+
+ memcpy(wp, xsp->ap, 2*wlen*WRDBYTES);
+
+ nbpap->nbawp = wp; 
+ nbpap->nbastp = stp;
+
+ /* copy expr. if needed */
+ /* BEWARE - code in many places assumes numeric expressions folded to */ 
+ /* number or IS number by here */
+ if (!__lhsexpr_var_ndx(stp->st.spra.lhsx)) nbpap->nblhsxp = NULL;
+ else
+  {
+   /* notice - know will have same width as stp lhsx */
+   lhsxp = __sim_copy_expr(stp->st.spra.lhsx);
+   __eval_lhsexpr_var_ndxes(lhsxp);
+   nbpap->nblhsxp = lhsxp; 
+  }
+ /* caller sets dctp if needed */
+ nbpap->nbdctp = NULL;
+ return(tevpi);
+}
+
+/*
+ * return T if expression contains non constant bit select index
+ *
+ * this assume only one level concats but maybe should
+ */
+extern int32 __lhsexpr_var_ndx(register struct expr_t *xp)
+{
+ switch ((byte) xp->optyp) {
+  case GLBREF: case ID:
+   break;
+  case PARTSEL:
+   /* part select always constant */
+   break;
+  case LSB:
+   if (xp->ru.x->optyp == NUMBER || xp->ru.x->optyp == ISNUMBER) break;
+   return(TRUE);
+  case LCB:
+   {
+    register struct expr_t *catxp;
+
+    for (catxp = xp->ru.x; catxp != NULL; catxp = catxp->ru.x)
+     {
+      /* if var index must copy entire expr. */
+      if (__lhsexpr_var_ndx(catxp->lu.x)) return(TRUE);
+     }
+   } 
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(FALSE);
+}
+
+/*
+ * evaluate any variable indices to constants
+ *
+ * this is guts of LRM non-blocking assign algorithm - for any variable
+ * bit index eval and convert to constant
+ *
+ * this mangles expr but since copied and free when non blocking assign
+ * done still works
+ *
+ * assumes only one level concats but maybe should
+ */
+extern void __eval_lhsexpr_var_ndxes(register struct expr_t *xp)
+{
+ int32 biti;
+ struct expr_t *idndp;
+ struct net_t *np;
+ struct expr_t *ndx;
+
+ switch ((byte) xp->optyp) {
+  case GLBREF: case ID: break;
+  case PARTSEL:
+   /* part select always constant */
+   break;
+  case LSB:
+   if (xp->ru.x->optyp != NUMBER && xp->ru.x->optyp != ISNUMBER)
+    {
+     idndp = xp->lu.x;
+     np = idndp->lu.sy->el.enp;
+     /* can be either constant or expr. - both handled in comp. */
+     biti = __comp_ndx(np, xp->ru.x);
+     /* out of range is x as index */
+     if (biti == -1) ndx = __bld_rng_numxpr(ALL1W, ALL1W, WBITS);
+     else ndx = __bld_rng_numxpr((word32) biti, 0, WBITS);
+     __free_xtree(xp->ru.x);
+     xp->ru.x = ndx;
+    }
+   /* if constant (even IS) index, nothing to do */ 
+   break;
+  case LCB:
+   {
+    register struct expr_t *catxp;
+
+    for (catxp = xp->ru.x; catxp != NULL; catxp = catxp->ru.x)
+     {
+      /* if var index must copy entire expr. */
+      __eval_lhsexpr_var_ndxes(catxp->lu.x);
+     }
+   } 
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * arm an event delay control - know already set up
+ * know current thread set to continuation point here
+ * know current thread will be blocked waiting for this 1 event
+ *
+ * notice may be triggered from other thread (init/always) in same inst.
+ * but continuation is here
+ * here arming ref. instance even though only change of target wire will
+ * trigger for xmr or col. case
+ */
+static void arm_event_dctrl(struct delctrl_t *dctp, register word32 *wp,
+ int32 wlen)
+{
+ register i_tev_ndx tevpi;
+ struct tev_t *tevp;
+ struct st_t *stp;
+
+ /* build after trigger fires, startup event */
+ /* notice this event record is not linked onto any event list for now */
+ alloc_tev_(tevpi, TE_THRD, __inst_ptr, __simtime);
+ /* link event back to thread */
+ __cur_thd->thdtevi = tevpi;
+ tevp = &(__tevtab[tevpi]);
+ tevp->tu.tethrd = __cur_thd;
+
+ /* if rhs delay form, set values */ 
+ if (wp != NULL)
+  {
+   __cur_thd->th_rhsform = TRUE;
+   __cur_thd->th_rhswp = wp;
+   __cur_thd->th_rhswlen = wlen;
+  }
+
+ if (__debug_flg && __st_tracing)
+  {
+   stp = tevp->tu.tethrd->thnxtstp;
+   __tr_msg("-- arming event thread %s itree loc. %s statement at %s\n",
+    __cur_thd->th_itp->itip->isym->synam, __inst_ptr->itip->isym->synam,
+    __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt));
+  }
+ /* RELEASE remove --
+ if (__debug_flg)
+  __dmp_dcemsg(dctp, "setting dce to event");
+ --- */
+
+ /* if rexecuting task, algorithm is to cancel previous pending */
+ /* delay control and emit warning */
+ if (dctp->dceschd_tevs[__inum] != -1)
+  {
+   if (__cur_thd->assoc_tsk == NULL)
+    {
+     stp = tevp->tu.tethrd->thnxtstp;
+     __sgfwarn(635, 
+      "INTERNAL BUG? - in %s cancel and rearm of event control to resume at %s",
+      __msg2_blditree(__xs, __inst_ptr), __bld_lineloc(__xs2, stp->stfnam_ind,
+      stp->stlin_cnt));
+    }
+   else
+    {
+     stp = tevp->tu.tethrd->thnxtstp;
+     __sgfwarn(635, 
+      "when reexecuting task %s cancel and rearm of event control to resume at %s",
+      __msg_blditree(__xs, __inst_ptr, __cur_thd->assoc_tsk),
+      __bld_lineloc(__xs2, stp->stfnam_ind, stp->stlin_cnt));
+    }
+  }
+
+ /* DBG remove -- */
+ if (__cur_thd->th_dctp != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* notice simply linking event on the scheduled list enables the ev ctrl */
+ dctp->dceschd_tevs[__inum] = tevpi;
+ __cur_thd->th_dctp = dctp;
+ /* handle any tracing */
+ if (__ev_tracing)
+  {
+   char vs2[10];
+
+   stp = tevp->tu.tethrd->thnxtstp;
+   if (wp == NULL) strcpy(vs2, ""); else strcpy(vs2, "(rhs)");
+   __tr_msg("-- event control suspend%s to resume line %s\n", 
+    vs2, __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt));
+  }
+}
+
+/*
+ * print a dctp message for debugging
+ */
+extern void __dmp_dcemsg(struct delctrl_t *dctp, char *dcemsg)
+{
+ char s1[RECLEN];
+
+ if (dctp->actionst != NULL)
+  __bld_lineloc(s1, dctp->actionst->stfnam_ind, dctp->actionst->stlin_cnt);
+ else strcpy(s1, "<none>");
+ __dbg_msg("%s: at %p of type %s instance %d(%s) iact=%d stmt. %s\n", dcemsg, 
+  dctp, __to_dcenam(__xs, dctp->dctyp), __inum,
+  __msg2_blditree(__xs2, __inst_ptr), dctp->dc_iact, s1);
+}
+
+/*
+ * arm a non blocking assign delay control
+ * 
+ * multiple allowed just add each new tev to end
+ * LOOKATME - notice current scheme requires linear traversal to list end.
+ */
+static void arm_nbevent_dctrl(struct delctrl_t *dctp, struct xstk_t *xsp,
+ struct st_t *stp)
+{
+ register i_tev_ndx tevp2i;
+ i_tev_ndx tevpi;
+ struct tev_t *tevp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN]; 
+
+ /* DBG remove -- */
+ if (__ev_tracing)
+  {
+   __evtr_resume_msg();
+    __tr_msg(
+     "-- arming event control non blocking assign line %s now %s in %s:\n",
+     __bld_lineloc(s1, stp->stfnam_ind, stp->stlin_cnt),
+     __to_timstr(s3, &__simtime), __msg2_blditree(s2, __inst_ptr));
+
+   __tr_msg("   EVENT TRIGGER ARM NEW VALUE %s\n",
+    __xregab_tostr(s1, xsp->ap, xsp->bp, stp->st.spra.lhsx->szu.xclen,
+    stp->st.spra.rhsx));
+  }
+ /* --- */
+ tevpi = __bld_nb_tev(stp, xsp, __simtime); 
+ tevp = &(__tevtab[tevpi]);
+ tevp->nb_evctrl = TRUE;
+ /* for event control form need to set dctp field */
+ tevp->tu.tenbpa->nbdctp = dctp;
+ if ((tevp2i = dctp->dceschd_tevs[__inum]) != -1)
+  {
+   /* could save end pointer if too slow ? */
+   for (; __tevtab[tevp2i].tenxti != -1; tevp2i = __tevtab[tevp2i].tenxti) ;
+   __tevtab[tevp2i].tenxti = tevpi;
+   /* ??? LOOKATME is this needed */
+   __tevtab[tevpi].tenxti = -1;
+  }
+ else dctp->dceschd_tevs[__inum] = tevpi;
+}
+
+/*
+ * execute a simple (not casex and casez) case statement
+ */
+static struct st_t *exec_case(struct st_t *stp)
+{
+ register word32 aw, bw;
+ register struct xstk_t *itemxsp;
+ register struct exprlst_t *xplp;
+ register struct csitem_t *csip;
+ int32 selxlen, selwlen, i; 
+ struct xstk_t *selxsp;
+ struct csitem_t *dflt_csip;
+
+ /* SJM 12/12/03 - must treat all 3 case types as special case if any */
+ /* of select or case item exprs real */
+ if (stp->st.scs.csx->is_real || stp->st.scs.csx->cnvt_to_real)
+  {
+   return(exec_real_case(stp));
+  }
+
+ if (stp->st.scs.castyp == CASEX) return(exec_casex(stp));
+ else if (stp->st.scs.castyp == CASEZ) return(exec_casez(stp));
+
+ /* compute the case type - determines operator to use */
+ selxsp = __eval_xpr(stp->st.scs.csx);
+
+ /* if expression real, convert to 32 bit reg */
+ if (stp->st.scs.csx->is_real) __cnv_stk_fromreal_toreg32(selxsp);
+
+ /* if result of selector is not as wide as needed widen */
+ /* case needs w bits width but selector is wire < w */
+ selxlen = stp->st.scs.maxselwid;
+ /* DBG remove -- */
+ if (selxsp->xslen > selxlen) __misc_terr(__FILE__, __LINE__);
+ /* --- */ 
+ /* SJM 09/29/03 - change for new sized but widen only */
+ if (selxsp->xslen < selxlen)
+  {
+   /* SJM 05/10/04 - LOOKATME - algorithm is that if any of the case match */
+   /* exprs are word32 - case becomes word32 */
+   if (stp->st.scs.csx->has_sign && !stp->st.scs.csx->unsgn_widen)
+    __sgn_xtnd_widen(selxsp, selxlen);
+   else __sizchg_widen(selxsp, selxlen);
+  }
+
+ selxlen = selxsp->xslen; 
+ if (__st_tracing) tr_case_st(selxsp, (stp->st.scs.csx->has_sign == 1));
+ dflt_csip = stp->st.scs.csitems;
+ csip = dflt_csip->csinxt;
+
+ /* case case 1: fits in one word32 */
+ if (selxlen <= WBITS)
+  {
+   aw = selxsp->ap[0];
+   bw = selxsp->bp[0];
+   for (; csip != NULL; csip = csip->csinxt)
+    {
+     for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+      {
+       itemxsp = __eval2_xpr(xplp->xp);
+
+       /* SJM 12/12/03 - never can be real here using new all if any code */
+
+       /* no conversion needed becaause know item may be too narrow only */
+       if (((aw ^ itemxsp->ap[0]) | (bw ^ itemxsp->bp[0])) == 0)
+        { __pop_xstk(); __pop_xstk(); return(csip->csist); }
+       __pop_xstk();
+      }
+    }
+   __pop_xstk();
+   if (dflt_csip->csist != NULL) return(dflt_csip->csist);
+   return(NULL);
+  }
+ /* case case 2: wider than 1 word32 */
+ selwlen = wlen_(selxlen);
+ for (; csip != NULL; csip = csip->csinxt)
+  {
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     itemxsp = __eval2_xpr(xplp->xp);
+
+     /* SJM 12/12/03 - never can be real here using new all if any code */
+
+     /* SJM 09/29/03 handle sign extension and separate cases */
+     if (itemxsp->xslen > selxlen) __narrow_sizchg(itemxsp, selxlen);
+     else if (itemxsp->xslen < selxlen)
+      {
+       if (xplp->xp->has_sign && !xplp->xp->unsgn_widen)
+        __sgn_xtnd_widen(itemxsp, selxlen);
+       else __sizchg_widen(itemxsp, selxlen);
+      }
+
+     for (i = 0; i < selwlen; i++)
+      {
+       if (((selxsp->ap[i] ^ itemxsp->ap[i])
+        | (selxsp->bp[i] ^ itemxsp->bp[i])) != 0) goto nxt_x;
+      }
+     __pop_xstk();
+     __pop_xstk();
+     return(csip->csist);
+
+nxt_x:
+     __pop_xstk();
+    }
+  }  
+ __pop_xstk();
+ if (dflt_csip->csist != NULL) return(dflt_csip->csist);
+ return(NULL);
+}
+
+/*
+ * special case routine to exec a case where any expr real
+ *
+ * SJM 12/12/03 - was converting real to word32 for cases with real but
+ * think that is wrong (although 2001 LRM does not say exactly) so now
+ * if any of case select or case item real, all compares real
+ * (following same rule, if any of select or match expr word32 all)
+ * (widening word32 - compares are for equal so only widening changes)
+ */
+static struct st_t *exec_real_case(struct st_t *stp)
+{
+ register struct xstk_t *itemxsp;
+ register struct exprlst_t *xplp;
+ register struct csitem_t *csip;
+ double d1, d2;
+ struct xstk_t *selxsp;
+ struct csitem_t *dflt_csip;
+
+ /* warning if casex or casez with real since no effect */
+ if (stp->st.scs.castyp == CASEX || stp->st.scs.castyp == CASEZ)
+  {
+   __sgfwarn(3113,
+    "select or case item expression real - casex/casez no effect");
+  }
+
+ /* compute the case type - determines operator to use */
+ selxsp = __eval_xpr(stp->st.scs.csx);
+
+ /* if select expr not real convert it */
+ if (stp->st.scs.csx->cnvt_to_real)
+  __cnv_stk_fromreg_toreal(selxsp, stp->st.scs.csx->has_sign);
+
+ if (__st_tracing) tr_case_st(selxsp, (stp->st.scs.csx->has_sign == 1));
+
+ dflt_csip = stp->st.scs.csitems;
+ csip = dflt_csip->csinxt;
+ memcpy(&d1, selxsp->ap, sizeof(double));
+
+ for (; csip != NULL; csip = csip->csinxt)
+  {
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     itemxsp = __eval2_xpr(xplp->xp);
+
+     /* if case item expr not real convert it */
+     if (xplp->xp->cnvt_to_real)
+      {
+       __cnv_stk_fromreg_toreal(itemxsp, xplp->xp->has_sign);
+      } 
+     memcpy(&d2, itemxsp->ap, sizeof(double));
+
+     /* real == (near 0.0) */
+     if ((d2 - d1) > -EPSILON && (d2 - d1) < EPSILON)
+      { __pop_xstk(); __pop_xstk(); return(csip->csist); }
+     __pop_xstk();
+    }
+  }
+ __pop_xstk();
+ if (dflt_csip->csist != NULL) return(dflt_csip->csist);
+ return(NULL);
+}
+
+/*
+ * trace a case (for any of case/casex/casez) 
+ */
+static void tr_case_st(struct xstk_t *selxsp, int32 cas_sign)
+{
+ __tr_msg("trace: %-7d -- [selector: %d'h%s]\n",
+  __slin_cnt, selxsp->xslen, __regab_tostr(__xs, selxsp->ap, selxsp->bp,
+  selxsp->xslen, BHEX, cas_sign));
+}
+
+/*
+ * execute a casex case statement
+ */
+static struct st_t *exec_casex(struct st_t *stp)
+{
+ register word32 aw, bw;
+ register struct xstk_t *itemxsp;
+ register struct csitem_t *csip;
+ register struct exprlst_t *xplp;
+ int32 selxlen, selwlen, i;
+ struct xstk_t *selxsp;
+ struct csitem_t *dflt_csip;
+
+ /* compute the case type - determines operator to use */
+ selxsp = __eval_xpr(stp->st.scs.csx);
+
+ /* if expression real, convert to 32 bit reg */
+ if (stp->st.scs.csx->is_real) __cnv_stk_fromreal_toreg32(selxsp);
+
+ /* if result of selector is not as wide as needed widen */
+ /* case needs w bits width but selector is wire < w */
+
+ selxlen = stp->st.scs.maxselwid;
+ /* DBG remove -- */
+ if (selxsp->xslen > selxlen) __misc_terr(__FILE__, __LINE__);
+ /* --- */ 
+ /* SJM 09/29/03 - change for new sized but widen only */
+ if (selxsp->xslen < selxlen)
+  {
+   if (stp->st.scs.csx->has_sign && !stp->st.scs.csx->unsgn_widen)
+    __sgn_xtnd_widen(selxsp, selxlen);
+   else __sizchg_widen(selxsp, selxlen);
+  }
+ if (__st_tracing) tr_case_st(selxsp, (stp->st.scs.csx->has_sign == 1));
+
+ dflt_csip = stp->st.scs.csitems;
+ csip = dflt_csip->csinxt;
+
+ /* case case 1: fits in one word32 */
+ if (selxlen <= WBITS)
+  {
+   aw = selxsp->ap[0];
+   bw = selxsp->bp[0];
+   for (; csip != NULL; csip = csip->csinxt)
+    {
+     for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+      {
+       itemxsp = __eval2_xpr(xplp->xp);
+
+       /* SJM 12/12/03 - never can be real here using new all if any code */
+
+       /* no conversion needed becaause know item may be too narrow only */
+       /* must 0 any don't care bits with either x/z bit 0 mask */
+       if ((((aw ^ itemxsp->ap[0]) | (bw ^ itemxsp->bp[0]))
+        & ~(bw | itemxsp->bp[0])) == 0)
+        { __pop_xstk(); __pop_xstk(); return(csip->csist); }
+       __pop_xstk();
+      }
+    }
+   __pop_xstk();
+   if (dflt_csip->csist != NULL) return(dflt_csip->csist);
+   return(NULL);
+  }
+ /* case case 2: wider than 1 word32 */
+ selwlen = wlen_(selxlen);
+ for (; csip != NULL; csip = csip->csinxt)
+  {
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     itemxsp = __eval2_xpr(xplp->xp);
+
+     /* SJM 12/12/03 - never can be real here using new all if any code */
+ 
+     /* SJM 09/29/03 handle sign extension and separate cases */
+     if (itemxsp->xslen > selxlen) __narrow_sizchg(itemxsp, selxlen);
+     else if (itemxsp->xslen < selxlen)
+      {
+       if (xplp->xp->has_sign && !xplp->xp->unsgn_widen)
+        __sgn_xtnd_widen(itemxsp, selxlen);
+       else __sizchg_widen(itemxsp, selxlen);
+      }
+
+     for (i = 0; i < selwlen; i++)
+      {
+       /* SJM 01/08/99 - WAS WRONG - for wide if == 0 always matches first */
+       if ((((selxsp->ap[i] ^ itemxsp->ap[i])
+        | (selxsp->bp[i] ^ itemxsp->bp[i]))
+        & ~(selxsp->bp[i] | itemxsp->bp[i])) != 0) goto nxt_x;
+      }
+     __pop_xstk();
+     __pop_xstk();
+     return(csip->csist);
+
+nxt_x:
+     __pop_xstk();
+    }
+  }
+ __pop_xstk();
+ if (dflt_csip->csist != NULL) return(dflt_csip->csist);
+ return(NULL);
+}
+
+/*
+ * execute a casez case statement
+ */
+static struct st_t *exec_casez(struct st_t *stp)
+{
+ register word32 aw, bw;
+ register struct xstk_t *itemxsp;
+ register struct csitem_t *csip;
+ register struct exprlst_t *xplp;
+ register word32 mask;
+ int32 selxlen, selwlen, i;
+ struct xstk_t *selxsp;
+ struct csitem_t *dflt_csip;
+
+ /* compute the case type - determines operator to use */
+ selxsp = __eval_xpr(stp->st.scs.csx);
+
+ /* if expression real, convert to 32 bit reg */
+ if (stp->st.scs.csx->is_real) __cnv_stk_fromreal_toreg32(selxsp);
+
+ /* if result of selector is not as wide as needed widen */
+ /* case needs w bits width but selector is wire < w */
+ selxlen = stp->st.scs.maxselwid;
+ /* DBG remove -- */
+ if (selxsp->xslen > selxlen) __misc_terr(__FILE__, __LINE__);
+ /* --- */ 
+ /* SJM 09/29/03 - change for new sized but widen only */
+ if (selxsp->xslen < selxlen)
+  {
+   if (stp->st.scs.csx->has_sign && !stp->st.scs.csx->unsgn_widen)
+    __sgn_xtnd_widen(selxsp, selxlen);
+   else __sizchg_widen(selxsp, selxlen);
+  }
+ if (__st_tracing) tr_case_st(selxsp, (stp->st.scs.csx->has_sign == 1));
+
+ dflt_csip = stp->st.scs.csitems;
+ csip = dflt_csip->csinxt;
+
+ /* case case 1: fits in one word32 */
+ if (selxlen <= WBITS)
+  {
+   aw = selxsp->ap[0];
+   bw = selxsp->bp[0];
+   for (; csip != NULL; csip = csip->csinxt)
+    {
+     for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+      {
+       itemxsp = __eval_xpr(xplp->xp);
+
+       /* SJM 12/12/03 - never can be real here using new all if any code */
+
+       /* no conversion needed becaause know item may be too narrow only */
+       /* must 0 any don't care bits z bits in either */
+       mask = (aw | ~bw) & (itemxsp->ap[0] | ~itemxsp->bp[0]);
+       if ((((aw ^ itemxsp->ap[0]) | (bw ^ itemxsp->bp[0])) & mask) == 0)
+        { __pop_xstk(); __pop_xstk(); return(csip->csist); }
+       __pop_xstk();
+      }
+    }
+   __pop_xstk();
+   if (dflt_csip->csist != NULL) return(dflt_csip->csist);
+   return(NULL);
+  }
+ /* case case 2: wider than 1 word32 */
+ selwlen = wlen_(selxlen);
+ for (; csip != NULL; csip = csip->csinxt)
+  {
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     itemxsp = __eval_xpr(xplp->xp);
+
+     /* SJM 12/12/03 - never can be real here using new all if any code */
+
+     /* SJM 09/29/03 handle sign extension and separate cases */
+     if (itemxsp->xslen > selxlen) __narrow_sizchg(itemxsp, selxlen);
+     else if (itemxsp->xslen < selxlen)
+      {
+       if (xplp->xp->has_sign && !xplp->xp->unsgn_widen)
+        __sgn_xtnd_widen(itemxsp, selxlen);
+       else __sizchg_widen(itemxsp, selxlen);
+      }
+
+     for (i = 0; i < selwlen; i++)
+      {
+       mask = (selxsp->ap[i] | ~selxsp->bp[i]) & (itemxsp->ap[i]
+        | ~itemxsp->bp[i]);
+/* SJM 01/08/99 - WRONG - for wide if == 0 always matches first */
+       if ((((selxsp->ap[i] ^ itemxsp->ap[i])
+        | (selxsp->bp[i] ^ itemxsp->bp[i])) & mask) != 0) goto nxt_x;
+      }
+     __pop_xstk();
+     __pop_xstk();
+     return(csip->csist);
+
+nxt_x:
+     __pop_xstk();
+    }
+  }
+ __pop_xstk();
+ if (dflt_csip->csist != NULL) return(dflt_csip->csist);
+ return(NULL);
+}
+
+/*
+ * execute the wait statement (not really a loop)
+ *
+ * if expression T, execute immediately
+ * else block until change of variable in expr.
+ * set up special net pin list elements (like events) until change
+ * evaluate and remove if T
+ *
+ */
+static int32 exec_wait(register struct st_t *stp)
+{
+ int32 tmp, rv;
+ i_tev_ndx tevpi;
+ struct xstk_t *xsp;
+ struct delctrl_t *dctp;
+ 
+ xsp = __eval_xpr(stp->st.swait.lpx);
+ dctp = stp->st.swait.wait_dctp;
+ if (xsp->xslen <= WBITS) tmp = ((xsp->ap[0] & ~xsp->bp[0]) != 0L);
+
+ if (xsp->xslen <= WBITS)
+  {
+   if (stp->st.swait.lpx->is_real)
+    {
+     double d1;
+ 
+     memcpy(&d1, xsp->ap, sizeof(double));
+     tmp = (d1 != 0.0);
+     /* must not emit z bit warning for real */
+     /* LOOKATME - changing part of stack since really done with it */
+     xsp->bp[0] = 0; 
+    }
+   else tmp = ((xsp->ap[0] & ~xsp->bp[0]) != 0L);
+  }
+ else tmp = (__cvt_lngbool(xsp->ap, xsp->bp, wlen_(xsp->xslen)) == 1);
+
+ if (tmp == 1)
+  {
+   if (!vval_is0_(xsp->bp, xsp->xslen))
+    __sgfinform(404, "TRUE wait expression contains some x/z bits");
+   __pop_xstk();
+
+   /* RELEASE remove
+   if (__debug_flg)
+    __dmp_dcemsg(dctp, "setting wait dce to nil");
+   --- */
+
+   /* disarm for this instance - wait now past */
+   /* first time thru will be nils but faster to just assign */
+   dctp->dceschd_tevs[__inum] = -1;
+   __cur_thd->th_dctp = NULL;
+
+   if (__st_tracing)
+    { strcpy(__xs2, "--continuing"); rv = TRUE; goto tr_done; }  
+   return(TRUE);
+  }
+
+ __pop_xstk();
+ /* because of fast tev reclaim scheme - allocate and assign new */
+ /* tev each time through here */
+ /* notice this does not link on list */
+ alloc_tev_(tevpi, TE_THRD, __inst_ptr, __simtime);
+ __cur_thd->thdtevi = tevpi;
+ __tevtab[tevpi].tu.tethrd = __cur_thd;
+ /* if rexecuting task, algorithm is to cancel previous pending */
+ /* delay control and emit warning */
+ if (dctp->dceschd_tevs[__inum] != -1)
+  {
+   if (__cur_thd->assoc_tsk == NULL)
+    {
+     __sgfwarn(635,
+      "INTERNAL BUG? - when reexecuting in %s cancel and rearm of wait",
+      __msg2_blditree(__xs, __inst_ptr));
+    }  
+   else
+    {
+     __sgfwarn(635, "when reexecuting task %s cancel and rearm of wait",
+     __msg_blditree(__xs, __inst_ptr, __cur_thd->assoc_tsk));
+    }
+  }
+ /* RELEASE remove ---
+ if (__debug_flg)
+  __dmp_dcemsg(dctp, "setting wait dce to event");
+ --- */
+ dctp->dceschd_tevs[__inum] = tevpi;
+ __cur_thd->th_dctp = dctp;
+ if (__st_tracing) { strcpy(__xs2, "--suspend"); rv = FALSE; goto tr_done; }
+ /* this arms this instances delay control in case expr. changes */
+ return(FALSE);
+
+tr_done:
+ if (__st_tracing)
+  {
+   __tr_msg("trace: %-7d wait (%s) [cond: %d] %s\n",
+    __slin_cnt, __msgexpr_tostr(__xs, stp->st.swait.lpx), tmp, __xs2);
+  }
+ return(rv);
+}
+
+/*
+ * execute a for statement header
+ * for is [init. assign; while (cond. exp) { <stmt>; <inc. assign stmt>; }
+ * notice unlike C both initial statement and inc. statement must be assigns
+ *
+ * know inc. executed before here and never seen
+ */
+static int32 for_not_done(struct for_t *frs)
+{
+ int32 tmp, has_xzs;
+ word32 val;
+ double d1;
+ struct xstk_t *xsp;
+
+ /* must move and execute for inc. at end not beginning of loop */
+ has_xzs = FALSE;
+ xsp = __eval_xpr(frs->fortermx);
+ if (xsp->xslen <= WBITS)
+  {
+   /* SJM 07/20/00 - must convert to real if real */
+   if (frs->fortermx->is_real)
+    { memcpy(&d1, xsp->ap, sizeof(double)); tmp = (d1 != 0.0); }
+   else
+    {
+     val = xsp->bp[0];
+     tmp = ((xsp->ap[0] & ~val) != 0L);
+     if (val != 0) { if (tmp == 0) tmp = 3; else has_xzs = TRUE; }
+    }
+  }
+ else
+  {
+   tmp = __cvt_lngbool(xsp->ap, xsp->bp, wlen_(xsp->xslen));
+   if (tmp == 1) { if (!vval_is0_(xsp->bp, xsp->xslen)) has_xzs = TRUE; }
+  }
+
+ if (__st_tracing)
+  {
+   __cur_sofs = 0; 
+   __dmp_forhdr((FILE *) NULL, frs);
+   __trunc_exprline(TRTRUNCLEN, FALSE);
+   __tr_msg("trace: %-7d %s) [cond: %d]\n", 
+    __slin_cnt, __exprline, tmp);
+   __cur_sofs = 0;
+  }
+ __pop_xstk();
+ if (tmp == 1)
+  {
+   if (has_xzs)
+    {
+     __sgfinform(405, "for condition true but has some x/z bits");
+    }
+   return(TRUE);
+  }
+ /* notice any 1 implies true so will not get here */
+ if (tmp == 3)
+  {
+   __sgfinform(406,
+    "for loop terminated by FALSE expressions containing x/z bits");
+  }
+ /* done with loop */
+ return(FALSE);
+}
+
+/* notice non label begin block optimized away by here */
+
+/*
+ * USER TASK/FUNCTION EXECUTION ROUTINES
+ */
+
+/*
+ * build named block thread structure and then execute the block
+ */
+static void exec_namblk(struct st_t *stp)
+{
+ struct task_t *tskp;
+ struct thread_t *thp;
+
+ tskp = stp->st.snbtsk;
+ /* indent block and statements within */
+ if (__st_tracing)
+  {
+   if (tskp->tsktyp == FORK) strcpy(__xs, "fork");
+   else strcpy(__xs, "begin");  
+   __tr_msg("trace: %-7d %s : %s\n", __slin_cnt, __xs,
+    tskp->tsksyp->synam);
+  }
+ /* use sub thread scheduling routine but just build and exec immediately */
+ __cur_thd->thofscnt = 1;
+ __cur_thd->thnxtstp = stp->stnxt;
+
+ /* create normal thread structure but exec immediately - no schedule */
+ thp = __setup_tsk_thread(tskp);
+
+ thp->thpar = __cur_thd;
+ __cur_thd->thofs = thp;
+ /* move down but notice never an xmr instance loc. change */
+ __cur_thd = thp;
+ __cur_thd->th_itp = __inst_ptr; 
+ /* DBG remove -- */
+ if (__cur_thd->thnxtstp == NULL) __misc_terr(__FILE__, __LINE__);
+ /* __dmp_tskthd(tskp, __inst_mod); */
+ /* --- */
+ /* always continue with down 1 thread - need thread only for possible */
+ /* disable of named block */ 
+}
+
+/*
+ * exec a task or named block as subthread of __cur_thd
+ * stp is place to begin after completion
+ * returns pointer to new sub thread 
+ *
+ * not used for fork-join because all fork join sub threads must be scheduled
+ * caller must set current thread fields
+ * will never see simple unnamed begin-end blocks here
+ */
+extern struct thread_t *__setup_tsk_thread(struct task_t *tskp)
+{
+ register struct thread_t *thp;
+ register struct tskthrd_t *ttp;
+
+ /* allocate a new thread */
+ thp = __alloc_thrd();
+ thp->thenbl_sfnam_ind = __sfnam_ind;
+ thp->thenbl_slin_cnt = __slin_cnt;
+
+ /* DBG remove -- */
+ if (tskp == NULL) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* if task, set next stmt to first of task and link thread on tasks list */
+ /* for disable, task list of all threads and thread to task link  */  
+ /* schedule of task conflicts with thread task */
+ /* DBG remove --- */
+ if (thp->assoc_tsk != NULL && thp->assoc_tsk != tskp)
+  __misc_sgfterr(__FILE__, __LINE__);
+ /* --- */
+
+ thp->thnxtstp = tskp->tskst;
+
+ /* put on front of task thread lists */
+ ttp = (struct tskthrd_t *) __my_malloc(sizeof(struct tskthrd_t)); 
+ ttp->tthd_l = NULL;
+ ttp->tthd_r = tskp->tthrds[__inum];
+ tskp->tthrds[__inum] = ttp;
+ if (ttp->tthd_r != NULL) ttp->tthd_r->tthd_l = ttp;
+ ttp->tthrd = thp;
+ thp->assoc_tsk = tskp;
+ /* set the one list element that this thread connects to */
+ thp->tthlst = ttp;
+ return(thp);
+}
+
+/*
+ * allocate threads and schedule execution of a fork-join 
+ * know __cur_thd will be named block thread for label fork join - else
+ * current thread
+ *
+ * no assoc. task since disabling fork-join label block disable 1 up normal
+ * label block not fork join
+ */
+extern void __sched_fork(register struct st_t *stp)
+{
+ register int32 fji;
+ register struct thread_t *thp;
+ int32 sav_slin_cnt, sav_sfnam_ind;
+ struct thread_t *last_thp;
+ struct st_t *fjstp;
+
+ /* DBG remove */
+ if (__cur_thd->thofscnt != 0) __misc_terr(__FILE__, __LINE__); 
+ /* --- */ 
+ /* convert current thread (one-up) to fork joint32 header */
+ /* and build (link in) list of per statement threads */  
+ last_thp = NULL;
+ for (fji = 0;; fji++)
+  {
+   if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+   
+   /* SJM 03/07/02 - for optimizer must always schedule 1st stmt of unblk */
+   /* instead of unnamed blk as now */
+   if (fjstp->stmttyp == S_UNBLK) fjstp = fjstp->st.sbsts;
+   
+   /* using location of fork-join statement as enable loc. not fork loc. */
+   sav_sfnam_ind = __sfnam_ind;
+   sav_slin_cnt = __slin_cnt;
+   __sfnam_ind = fjstp->stfnam_ind;
+   __slin_cnt = fjstp->stlin_cnt;
+   /* schedule each subthread after building it */
+   thp = sched_fj_subthread(fjstp);
+
+   __sfnam_ind = sav_sfnam_ind;
+   __slin_cnt = sav_slin_cnt;
+
+   __cur_thd->thofscnt += 1;
+   if (last_thp == NULL) __cur_thd->thofs = thp;
+   else { thp->thleft = last_thp; last_thp->thright = thp; }
+   thp->thpar = __cur_thd;
+   thp->th_itp = __inst_ptr;
+   /* flag on fork-join component to indicate must look for assoc tsk up */
+   thp->th_fj = TRUE;
+   last_thp = thp;
+  }
+}
+
+/*
+ * setup and schedule execution of one fork-join subthread of __cur_thd
+ *
+ * stp is place to begin when event processed
+ * returns pointer to thread value in scheduled event
+ * caller must set current thread fields
+ */
+static struct thread_t *sched_fj_subthread(struct st_t *stp)
+{
+ register struct thread_t *thp;
+ i_tev_ndx tevpi;
+
+ /* allocate a new thread */
+ thp = __alloc_thrd();
+ thp->thenbl_sfnam_ind = __sfnam_ind;
+ thp->thenbl_slin_cnt = __slin_cnt;
+
+ /* set the one fj statement (or list) as next stmt of subthread */
+ thp->thnxtstp = stp;
+ 
+ /* allocate an event for this fork-join component statement */
+ /* at end of current time slot */
+ alloc_tev_(tevpi, TE_THRD, __inst_ptr, __simtime);
+
+ /* link thread back to event */
+ thp->thdtevi = tevpi;
+ __tevtab[tevpi].tu.tethrd = thp;
+
+ if (__debug_flg && __st_tracing)
+  {
+   __tr_msg("trace: %-7d -- schedule new subthread at %s continue at %s\n",
+    __slin_cnt, __bld_lineloc(__xs, thp->thenbl_sfnam_ind,
+    thp->thenbl_slin_cnt), __bld_lineloc(__xs2, stp->stfnam_ind,
+    stp->stlin_cnt));
+  }
+
+ /* this must go on front because interactive statement must complete */
+ __add_ev_to_front(tevpi);
+ return(thp);
+}
+
+/*
+ * add an event to front of current queue
+ * for various procedural control - must go front so interactive completes
+ * before any other events processed
+ *
+ * scheme is to always execute procedural as soon as possible
+ * but declarative as late as possible
+ */
+extern void __add_ev_to_front(register i_tev_ndx tevpi)
+{
+ if (!__processing_pnd0s)
+  {
+   /* adding to front is just after current since now processing current */
+   if (__cur_tevpi == -1)
+    {
+     if (__cur_te_hdri == -1) __cur_te_hdri = __cur_te_endi = tevpi; 
+     else { __tevtab[tevpi].tenxti = __cur_te_hdri; __cur_te_hdri = tevpi; }
+    }
+   else
+    {
+     if (__cur_tevpi != __cur_te_endi)
+      __tevtab[tevpi].tenxti = __tevtab[__cur_tevpi].tenxti;
+     else __cur_te_endi = tevpi;
+     __tevtab[__cur_tevpi].tenxti = tevpi;
+    }
+   __num_twhevents++;
+   /* need to make sure number of timing wheel events matches cur number */
+   __twheel[__cur_twi]->num_events += 1;
+  }
+ else
+  {
+   /* also in pnd 0's front is just after current if set */
+   if (__cur_tevpi == -1)
+    {
+     /* notice during add net chg elements cur tevp nil, so common to add */
+     /* to end */ 
+     if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi; 
+     else { __tevtab[tevpi].tenxti = __p0_te_hdri; __p0_te_hdri = tevpi; }
+    }
+   else
+    {
+     if (__cur_tevpi != __p0_te_endi)
+      __tevtab[tevpi].tenxti = __tevtab[__cur_tevpi].tenxti;
+     else __p0_te_endi = tevpi;
+     __tevtab[__cur_tevpi].tenxti = tevpi;
+    }
+   /* this does not go on timing wheel or get counted */
+  }
+}
+
+/*
+ * allocate a new thread
+ */
+extern struct thread_t *__alloc_thrd(void)
+{
+ register struct thread_t *thp;
+
+ thp = (struct thread_t *) __my_malloc(sizeof(struct thread_t));
+ init_thrd(thp);
+ return(thp);
+}
+
+/*
+ * initialize a new thread
+ */
+static void init_thrd(register struct thread_t *thp)
+{
+ thp->tsk_stouts = FALSE;
+ thp->th_dsable = FALSE;
+ thp->th_rhsform = FALSE;
+ thp->th_fj = FALSE;
+ thp->th_ialw = FALSE;
+ thp->th_postamble = FALSE;
+ /* off-spring count is 0 unless incremented when sub thread created */  
+ thp->thofscnt = 0;
+ thp->thnxtstp = NULL;
+ thp->thpar = thp->thright = thp->thleft = thp->thofs = NULL;
+ thp->tthlst = NULL;
+ thp->assoc_tsk = NULL;
+ thp->th_dctp = NULL;
+ thp->thdtevi = -1;
+ thp->thenbl_sfnam_ind = 0;
+ thp->thenbl_slin_cnt = 0;
+ thp->th_rhswp = NULL;
+ thp->th_rhswlen = -1;
+ thp->th_itp = NULL;
+ thp->th_hctrl = NULL;
+}
+
+/*
+ * execute a task call
+ *
+ * thread suspend mechanism set up but works by continuing with first
+ * stmt in tsk body (can be execed as iop) - thread mechanism fixed 
+ * up so suspend works right including handling of disable and tsk outs
+ *
+ * know for user tasks, argument list exactly matches definition list 
+ * can improve this by preprocessing call/return evaluation
+ */
+extern struct st_t *__exec_tskcall(struct st_t *stp)
+{
+ register struct expr_t *xp;
+ register struct task_pin_t *tpp;
+ int32 argi;
+ struct tskcall_t *tkcp;
+ struct expr_t *tkxp, *rhsxp;
+ struct sy_t *syp;
+ struct task_t *tskp;
+ struct xstk_t *xsp;
+ struct net_t *np;
+ struct thread_t *thp;
+ struct itree_t *tsk_itp;
+ struct st_t *stp2;
+
+ tkcp = &(stp->st.stkc);
+ tkxp = tkcp->tsksyx;
+ syp = tkxp->lu.sy;
+
+ if (syp->sytyp == SYM_STSK)
+  {
+   /* no time movement in system tasks */
+   /* return NULL, to suspend thread - non null to continue as to next st */
+   /* this does own tracing */
+   if (__st_tracing)
+    {
+     __cur_sofs = 0;
+     __dmp_tskcall((FILE *) NULL, stp);
+     __trunc_exprline(TRTRUNCLEN, FALSE);
+     __tr_msg("trace: %-7d %s\n", __slin_cnt,
+       __exprline);
+     __cur_sofs = 0;
+    }
+   return(__exec_stsk(stp, syp, tkcp));
+  }
+ tskp = syp->el.etskp;
+ tpp = tskp->tskpins;
+
+ if (tkxp->optyp == GLBREF)
+  {
+   /* must get tsk exec itree location but cannot change to yet */
+   __xmrpush_refgrp_to_targ(tkxp->ru.grp);
+   tsk_itp = __inst_ptr;
+   /* notice need to print new location for xmr task */
+   if (__st_tracing) tr_resume_msg();
+   __pop_itstk();
+  }
+ else tsk_itp = NULL;
+ if (__st_tracing)
+  {
+   __cur_sofs = 0;
+   __adds("<** enabling task ");
+   __adds(__to_idnam(tkxp));
+   addch_('(');
+  }
+
+ /* must assign to task variables since values persist */
+ /* user tasks are value-result */
+ argi = 0;
+ for (xp = tkcp->targs; xp != NULL; xp = xp->ru.x, tpp = tpp->tpnxt, argi++)
+  {
+   if (tpp->trtyp != IO_OUT)
+    {
+     /* assign rhs in or inout arg. expr. to task local variable */
+     np = tpp->tpsy->el.enp;
+     rhsxp = xp->lu.x;
+     xsp = __eval_xpr(rhsxp);
+     eval_tskassign_rhsexpr(xsp, (np->ntyp == N_REAL), np->nwid,
+      (rhsxp->is_real == 1), (rhsxp->has_sign == 1));
+     if (__st_tracing) tradd_tf_argval(argi, np, xsp);
+     /* if xmr call, afer eval in cur. itree loc. must store in xmr dest */
+     if (tsk_itp != NULL)
+      {
+       __push_itstk(tsk_itp);
+       __chg_st_val(np, xsp->ap, xsp->bp);
+       __pop_itstk();
+      }
+     else __chg_st_val(np, xsp->ap, xsp->bp);
+     __pop_xstk();
+    }
+   else if (__st_tracing)
+    {
+     /* for tracing output value on entry, need caller's itree loc. */
+     np = tpp->tpsy->el.enp;
+     push_xstk_(xsp, np->nwid);
+     __ld_wire_val(xsp->ap, xsp->bp, np);
+     tradd_tf_argval(argi, np, xsp);
+     __pop_xstk();
+    }
+  }
+ if (__st_tracing)
+  {
+   __adds(")"); 
+   __trunc_exprline(TRTRUNCLEN, FALSE);
+   __tr_msg("trace: %-7d %s\n", __slin_cnt, __exprline);
+   __cur_sofs = 0;
+  }
+
+ /* use sub thread scheduling routine but just build and exec immediately */
+ __cur_thd->thofscnt = 1;
+
+ /* if xmr task call replace top of instance stack here - cur_thd has up 1 */
+ if (tsk_itp != NULL) { __pop_itstk(); __push_itstk(tsk_itp); }
+
+ /* trick here is that must not advance statement since need to store */
+ thp = __setup_tsk_thread(tskp);
+
+ if (tskp->thas_outs || __st_tracing)
+  {
+   thp->tsk_stouts = TRUE;
+   /* must set thrd nxt stmt to the task call so can find task after */ 
+   /* task completed suspend so can find tsk to set out params in */
+   /* fixup to skip of non loop end gotos after tsk outs stored */
+   __cur_thd->thnxtstp = stp;
+   __cur_thd->th_postamble = TRUE;
+  }
+ /* SJM 04/05/02 - skip over all non loop end gotos so can exec actual stmt */
+ else
+  {
+   stp2 = stp->stnxt;
+   if (stp2 == NULL) __cur_thd->thnxtstp = NULL;
+   else if (stp2->stmttyp != S_GOTO) __cur_thd->thnxtstp = stp2;
+   else if (stp2->lpend_goto) __cur_thd->thnxtstp = stp2;
+   else
+    {
+     for (;;)
+      {
+       /* know on entry stp2 goto */
+       stp2 = stp2->st.sgoto;
+       if (stp2 == NULL || stp2->stmttyp != S_GOTO)
+        { __cur_thd->thnxtstp = stp2; break; }
+       if (stp2->lpend_goto) { __cur_thd->thnxtstp = stp2; break; }
+      }
+    }
+  }
+
+ thp->thpar = __cur_thd;
+ __cur_thd->thofs = thp;
+ /* make task thread current */
+ __cur_thd = thp;
+ __cur_thd->th_itp = __inst_ptr;
+ /* DBG remove ---
+ __dmp_tskthd(tskp, __inst_mod);
+ --- */
+ return(thp->thnxtstp);
+}
+
+/*
+ * print a task or function argument value    
+ */
+static void tradd_tf_argval(int32 argi, struct net_t *np, struct xstk_t *xsp)
+{
+ char s1[RECLEN];
+ int32 signv, base;
+
+ if (argi != 0) __adds(", "); 
+ if (!vval_is0_(xsp->bp, xsp->xslen) && np->ntyp != N_REAL)
+  {
+   sprintf(s1, "%d'h", xsp->xslen); 
+   __adds(s1);
+   __regab_tostr(s1, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE);
+  }
+ else
+  {
+   signv = FALSE; base = BHEX;
+   if (np->ntyp == N_REAL) base = BDBLE; 
+   else if (np->n_signed) { base = BDEC; signv = TRUE; } 
+   __regab_tostr(s1, xsp->ap, xsp->bp, xsp->xslen, base, signv);
+  }
+ __adds(s1);
+}
+
+/*
+ * store task return output parameters
+ *
+ * if disabled never get here
+ * tricky because must eval using tos itree loc. but assign to 1 under
+ * also get here even if no out args but statement tracing on
+ *
+ * this is called from task thread and itree loc. but assigns to one up
+ * thread and itree location
+ */
+static void store_tskcall_outs(struct st_t *tskcall_stp) 
+{
+ register struct expr_t *xp;
+ register struct task_pin_t *tpp;
+ int32 first_time, base, signv;
+ struct tskcall_t *tkcp;
+ struct expr_t *tkxp, *lhsxp;
+ struct task_t *tskp;
+ struct xstk_t *xsp;
+ struct net_t *np;
+ char s1[RECLEN];
+
+ tkcp = &(tskcall_stp->st.stkc);
+ tkxp = tkcp->tsksyx;
+
+ tskp = tkxp->lu.sy->el.etskp;
+ if (__st_tracing)
+  {
+   __cur_sofs = 0;
+   __adds("**> returning from task ");
+   __adds(__to_idnam(tkxp));
+   addch_('(');
+  }
+ tpp = tskp->tskpins;
+ first_time = TRUE;
+ for (xp = tkcp->targs; xp != NULL; xp = xp->ru.x, tpp = tpp->tpnxt)
+  {
+   if (tpp->trtyp == IO_IN) continue;
+
+   /* assign task local param var. value to lhs call argument */
+   /* xp->lu.x is rhs src., np is lhs dest. var. */
+   np = tpp->tpsy->el.enp;
+   push_xstk_(xsp, np->nwid);
+   /* need load value here because, need to decode storage rep */
+   __ld_wire_val(xsp->ap, xsp->bp, np);
+   lhsxp = xp->lu.x;
+   eval_tskassign_rhsexpr(xsp, (lhsxp->is_real == 1), lhsxp->szu.xclen,
+    (np->ntyp == N_REAL), (np->n_signed == 1));
+   /* np here is rhs */
+   if (__st_tracing) 
+    {
+     if (first_time) first_time = FALSE; else __adds(", "); 
+     if (np->ntyp != N_REAL && !vval_is0_(xsp->bp, xsp->xslen))
+      {
+       sprintf(s1, "%d'h", xsp->xslen); 
+       __adds(s1);
+       __regab_tostr(s1, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE);
+      }
+     else
+      {
+       signv = FALSE; base = BHEX;
+       if (np->ntyp == N_REAL) base = BDBLE; 
+       else if (np->n_signed) { base = BDEC; signv = TRUE; } 
+       __regab_tostr(s1, xsp->ap, xsp->bp, xsp->xslen, base, signv); 
+      }
+     __adds(s1);
+    } 
+   /* notice for xmr task enable, must eval in task itree place */
+   /* but store top of expr. stack in calling itree place */
+   if (tkxp->optyp == GLBREF)
+    {
+     __push_itstk(__cur_thd->thpar->th_itp);
+     __exec2_proc_assign(lhsxp, xsp->ap, xsp->bp);
+     __pop_itstk();
+    }
+   else __exec2_proc_assign(lhsxp, xsp->ap, xsp->bp);
+   __pop_xstk();
+  }
+ if (__st_tracing)
+  {
+   __adds(")"); 
+   __trunc_exprline(TRTRUNCLEN, FALSE);
+   __tr_msg("trace: %-7d %s\n", __slin_cnt, __exprline);
+   __cur_sofs = 0;
+  }
+}
+
+/*
+ * execute a user function call operator in an expression
+ * ndp is FCALL expression node - ru is operand list
+ * user functions only take input args 
+ * notice local variables presist and puts return value on top of expr stk 
+ */
+extern void __exec_func(register struct expr_t *ndp) 
+{
+ register struct expr_t *argxp;
+ register struct task_pin_t *tpp;
+ int32 savslin_cnt, savsfnam_ind, nd_thdfree;
+ struct sy_t *fsyp;
+ struct itree_t *func_itp, *xmr_savitp;
+ struct st_t *stp;
+ struct task_t *tskp;
+ struct tev_t *tevp;
+ int32 argi;
+ struct gref_t *grp;
+ struct xstk_t *xsp;
+ struct net_t *np;
+ struct expr_t *rhsxp;
+ 
+ /* SJM 05/22/05 - no reason to pass func symbol - just get from expr node */  
+ fsyp = ndp->lu.x->lu.sy; 
+
+ /* for decl. rhs, maybe no thrd - bld for 1st call else take over cur. */ 
+ nd_thdfree = FALSE;
+ if (__cur_thd == NULL)
+  {
+   __cur_thd = __alloc_thrd();
+   __cur_thd->th_itp = __inst_ptr;
+   nd_thdfree = TRUE;
+  }
+ /* DBG remove --- */
+ else if (__cur_thd->th_itp != __inst_ptr) __misc_terr(__FILE__, __LINE__);
+ /* --- */ 
+
+ /* function source will be dump later */ 
+ if (__st_tracing)
+  {
+   __cur_sofs = 0;
+   __adds("<** calling function ");
+   __adds(__to_idnam(ndp->lu.x));
+   addch_('(');
+  }
+
+ xmr_savitp = __inst_ptr;
+ /* function call prep. block */
+
+ argi = 0;
+ tskp = fsyp->el.etskp;
+ tpp = tskp->tskpins->tpnxt;
+ /* if global, local variables accessed from target (defining mod) inst */
+ if (ndp->lu.x->optyp == GLBREF)
+  {
+   grp = ndp->lu.x->ru.grp;
+   __xmrpush_refgrp_to_targ(grp);
+   if (__st_tracing) tr_resume_msg();
+   func_itp = __inst_ptr;
+   /* cannot change to func xmr place yet */
+   __pop_itstk();
+  }
+ else func_itp = NULL;
+
+ /* evaluate and store input params */
+ /* 1st tpp is by convention is return value but 1st arg is real arg */
+ /* know number matches exactly (no ,,) or will not get here */ 
+ argi = 0;
+ for (argxp = ndp->ru.x; argxp != NULL; argxp = argxp->ru.x,
+  tpp = tpp->tpnxt, argi++)
+  {
+   /* if xmr call, must eval. these in current not func. */
+   /* assign rhs in or inout arg. expr. to task local variable */
+   np = tpp->tpsy->el.enp;
+   rhsxp = argxp->lu.x;
+   xsp = __eval2_xpr(rhsxp);
+   eval_tskassign_rhsexpr(xsp, (np->ntyp == N_REAL), np->nwid,
+    (rhsxp->is_real == 1), (rhsxp->has_sign == 1));
+
+   if (__st_tracing) tradd_tf_argval(argi, np, xsp);
+
+   /* notice can cause propagate reg xmr on rhs that is function arg */
+   /* if xmr need to store in down itree location */
+   if (func_itp != NULL)
+    {
+     __push_itstk(func_itp);
+     __chg_st_val(np, xsp->ap, xsp->bp);
+     __pop_itstk();
+    }
+   else __chg_st_val(np, xsp->ap, xsp->bp);
+   __pop_xstk();
+  }
+
+ if (__st_tracing)
+  {
+   __adds(")"); 
+   __trunc_exprline(TRTRUNCLEN, FALSE);
+   __tr_msg("trace: %-7d %s\n", __slin_cnt, __exprline);
+   __cur_sofs = 0;
+  }
+ /* this is dynamic call list */
+ if (++__fcspi >= __maxfcnest) grow_fcstk();
+ __fcstk[__fcspi] = tskp;
+ savslin_cnt = __slin_cnt;
+ savsfnam_ind = __sfnam_ind;
+ /* if xmr function call replace top - relative xmr's not though itstk */ 
+ if (func_itp != NULL)
+  { __pop_itstk(); __push_itstk(func_itp); __cur_thd->th_itp = __inst_ptr; }
+
+ /* cannot schedule and resume inside func. so suspend and schedule */
+ /* then unsuspend and cancel event */
+ stp = tskp->tskst;
+ __cur_thd->thnxtstp = stp;
+ /* if stepping, make sure first execed */
+ if (__single_step) __step_from_thread = FALSE;
+
+again:
+ __stmt_suspend = FALSE;
+ /* step returns after 1 statement (to new line) or end of func */
+ if (__single_step && __cur_thd->th_hctrl == NULL) step_exec_stmt(stp);
+ else if (__st_tracing || __single_step)
+  {
+    brktr_exec_stmts(stp);
+  }
+ else exec_stmts(stp);
+
+ /* happens if hit break or step or ^c hit - suspend routine just execed */
+ if (__stmt_suspend)
+  {
+   __do_interactive_loop();
+   /* tricky code for func - restart and cancel scheduled resume event */
+   /* DBG remove --- */  
+   if (__fsusp_tevpi == -1) __misc_terr(__FILE__, __LINE__);
+
+   tevp = &(__tevtab[__fsusp_tevpi]);
+   if (__inst_ptr != tevp->teitp || __inst_ptr != __suspended_itp) 
+    __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* restore from func. suspended event and cancel event */
+   __cur_thd = tevp->tu.tethrd;
+   tevp->te_cancel = TRUE;
+   __fsusp_tevpi = -1L;
+
+   /* undo suspend */
+   __cur_thd->thdtevi = -1;
+   __suspended_thd = NULL;
+   __suspended_itp = NULL;
+   stp = __cur_thd->thnxtstp;
+   goto again;
+  }
+ 
+ __slin_cnt = savslin_cnt;
+ __sfnam_ind = savsfnam_ind;
+ __fcspi--;
+
+ /* SJM 05/12/03 - do not need block here */
+ /* return block */
+ /* put assign func return variable (func. name) value on tos */
+ /* key here is task name local variable has declaration from func hdr */
+ /* notice ok if not assigned, to will just return x */
+ np = tskp->tskpins->tpsy->el.enp;
+ push_xstk_(xsp, np->nwid);
+ /* caller must intepret type of value on tos */
+ /* for itp this must be loaded from dest. */
+ __ld_wire_val(xsp->ap, xsp->bp, np);
+ /* if xmr replace top with original and put back thread itp */ 
+ if (func_itp != NULL)
+ { __pop_itstk(); __push_itstk(xmr_savitp); __cur_thd->th_itp = __inst_ptr; }
+
+ if (__st_tracing)
+  {
+   int32 signv, base;
+
+   if (np->ntyp != N_REAL && !vval_is0_(xsp->bp, xsp->xslen))
+    {
+     sprintf(__xs2, "%d'h%s", xsp->xslen, __regab_tostr(__xs, xsp->ap,
+      xsp->bp, xsp->xslen, BHEX, FALSE));
+    }
+   else 
+    {
+     signv = FALSE; base = BHEX;
+     if (np->ntyp == N_REAL) base = BDBLE; 
+     else if (np->n_signed) { base = BDEC; signv = TRUE; } 
+     __regab_tostr(__xs2, xsp->ap, xsp->bp, xsp->xslen, base, signv);
+    }
+   __tr_msg("trace: %-7d **> [%s] returned by function %s\n",
+    __slin_cnt, __xs2, __to_idnam(ndp->lu.x));
+  }
+
+ if (nd_thdfree)
+  {
+   __my_free((char *) __cur_thd, sizeof(struct thread_t));
+   __cur_thd = NULL;
+  } 
+ return;
+}
+
+
+/*
+ * routine to grow fcstk (function call no display local variables)
+ */
+static void grow_fcstk(void)
+{
+ register int32 i;
+ int32 old_maxnest;
+ int32 osize, nsize;
+
+ old_maxnest = __maxfcnest;
+ osize = old_maxnest*sizeof(struct task_t *);
+ /* grow by 50% after certain point */
+ if (__maxfcnest >= 2000) __maxfcnest += __maxfcnest/2;
+ else __maxfcnest *= 2;
+ nsize = __maxfcnest*sizeof(struct task_t *);
+ __fcstk = (struct task_t **) __my_realloc((char *) __fcstk, osize, nsize);
+ for (i = old_maxnest; i < __maxfcnest; i++) __fcstk[i] = NULL;
+ if (__debug_flg)
+  __dbg_msg("+++ fcall stack grew from %d bytes to %d\n", osize, nsize); 
+}
+
+/*
+ * execute a system function call operator
+ * ndp is actual FCALL node
+ * leaves return value on top of expr. stack but does not return it
+ */
+extern void __exec_sysfunc(register struct expr_t *ndp) 
+{
+ register struct xstk_t *xsp, *xsp2;
+ register struct expr_t *fax;
+ int32 ival, fd, c;
+ word32 uval;
+ word64 timval;
+ double d1;
+ struct sy_t *fsyp;
+ struct sysfunc_t *sfbp;
+
+ /* SJM 05/22/05 - no reason to pass func symbol - just get from expr node */  
+ fsyp = ndp->lu.x->lu.sy; 
+
+ sfbp = fsyp->el.esyftbp;
+ switch (sfbp->syfnum) {
+  /* functions that take exactly one argument */
+  case STN_FOPEN:
+   /* AIV 09/08/03 - changed now can take one or 2 args for OS FILE * */
+   /* fd = $fopen([filen name]) or fd = $fopen([file name], [I/O mode]) */
+   fax = ndp->ru.x->lu.x;
+   /* 2nd arg empty also must be interpreted as MCD open */
+   if (ndp->ru.x->ru.x != NULL && ndp->ru.x->lu.x->optyp != OPEMPTY)
+    {
+     uval = fio_do_fopen(fax, ndp->ru.x->ru.x->lu.x);
+    }
+   else uval = mc_do_fopen(fax);
+
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = (word32) uval;  
+   xsp->bp[0] = 0L;
+   break; 
+  /* AIV 09/08/03 - new fileio system functions */
+  case STN_FGETC:
+   /* c = $fgetc([fd expr]) */
+   /* on error, this sets errno OS state var */
+   if ((fd = chk_get_ver_fd(ndp->ru.x->lu.x)) == -1) c = -1;
+   else
+    {
+     /* on error, this return EOF (-1) and sets OS err number state var */
+     c = fgetc(__fio_fdtab[fd]->fd_s);
+    }
+   push_xstk_(xsp, WBITS);
+   /* -1 becomes correct all word32 all 1's until new signed added */
+   xsp->ap[0] = (word32) c;  
+   xsp->bp[0] = 0L;
+   break;
+  case STN_UNGETC:
+   /* c = $ungetc([put back ch], [fd expr]) */
+   /* know exactly 2 args or won't get here */
+   ival = fio_ungetc(ndp->ru.x->lu.x, ndp->ru.x->ru.x->lu.x);
+   push_xstk_(xsp, WBITS);
+   /* -1 becomes correct all word32 all 1's until new signed added */
+   xsp->ap[0] = (word32) ival;  
+   xsp->bp[0] = 0L;
+   break;
+  case STN_FGETS:
+   /* format: cnt = $fgets([lhs proc str expr], [fd expr]) */
+   /* know exactly 2 args or won't get here - returns 0 or num chs read */
+   ival= fio_fgets(ndp->ru.x->lu.x, ndp->ru.x->ru.x->lu.x);
+   push_xstk_(xsp, WBITS);
+   /* 0 on error esle number of chars read */
+   xsp->ap[0] = (word32) ival;  
+   xsp->bp[0] = 0L;
+   break;
+  case STN_FTELL:
+   /* format: fpos = $ftell([fd expr]) */
+   /* on error, this sets errno OS state var */
+   if ((fd = chk_get_ver_fd(ndp->ru.x->lu.x)) == -1) ival = -1;
+   else
+    {
+     /* on error, this return EOF (-1) and sets OS err number state var */
+     ival = ftell(__fio_fdtab[fd]->fd_s);
+    }
+   push_xstk_(xsp, WBITS);
+   /* -1 becomes correct all word32 all 1's until new signed added */
+   xsp->ap[0] = (word32) ival;
+   xsp->bp[0] = 0L;
+   break;
+  case STN_REWIND:
+   /* format: fpos = $rewind([fd expr]) */
+   ival = fio_rewind(ndp->ru.x->lu.x);
+   push_xstk_(xsp, WBITS);
+   /* -1 becomes correct all word32 all 1's until new signed added */
+   xsp->ap[0] = (word32) ival;
+   xsp->bp[0] = 0L;
+   break;
+  case STN_FSEEK:
+   /* format: fpos = $fseek([fd expr], [ofs expr], [whence expr]) */
+   /* syntax error does not have 3 args caught during check (in v_fx3.c) */
+   ival = fio_fseek(ndp->ru.x->lu.x, ndp->ru.x->ru.x->lu.x,
+    ndp->ru.x->ru.x->ru.x->lu.x);
+   push_xstk_(xsp, WBITS);
+   /* -1 becomes correct all word32 all 1's until new signed added */
+   xsp->ap[0] = (word32) ival;
+   xsp->bp[0] = 0L;
+   break;
+  case STN_FERROR:
+   /* format: errnum = $ferror([fd expr], [lhs proc string]) */
+   ival = fio_ferror(ndp->ru.x->lu.x, ndp->ru.x->ru.x->lu.x);
+   push_xstk_(xsp, WBITS);
+   /* -1 becomes correct all word32 all 1's until new signed added */
+   xsp->ap[0] = (word32) ival;
+   xsp->bp[0] = 0L;
+   break;
+  case STN_FREAD:
+   /* [num chars read] = $fread([lhs proc reg expr], [fd expr]) */
+   /* [num chars read] = $fread([mem name], [fd expr], [{starg}, {count}]) */
+   ival = fio_fread(ndp->ru.x);
+   push_xstk_(xsp, WBITS);
+   /* -1 becomes correct all word32 all 1's until new signed added */
+   xsp->ap[0] = (word32) ival;
+   xsp->bp[0] = 0L;
+   break;
+  case STN_FSCANF:
+   /* [num matched flds] = $fscanf([fd], [format], ...) */
+   ival = fio_fscanf(ndp->ru.x);
+   push_xstk_(xsp, WBITS);
+   /* -1 becomes correct all word32 all 1's until new signed added */
+   xsp->ap[0] = (word32) ival;
+   xsp->bp[0] = 0L;
+   break;
+ case STN_SSCANF:
+   /* [num matched flds] = $sscanf([string expr], [format], ...) */
+   ival = fio_sscanf(ndp->ru.x);
+   push_xstk_(xsp, WBITS);
+   /* -1 becomes correct all word32 all 1's until new signed added */
+   xsp->ap[0] = (word32) ival;
+   xsp->bp[0] = 0;
+   break;
+  case STN_STIME: 
+  case STN_TIME:
+   /* convert ticks to user time (maybe smaller) and return WBIT form */
+   /* with warn if does not fit */
+   /* this can be 0 - know conversion to user time always succeeds */
+   if (!__inst_mod->mno_unitcnv)
+    __cnv_ticks_tonum64(&timval, __simtime, __inst_mod);
+   else timval = __simtime;
+   if (sfbp->syfnum == STN_STIME)
+    { 
+     push_xstk_(xsp, WBITS);
+     if (timval > WORDMASK_ULL)
+      {
+       __sgfinform(411, "system function %s result does not fit in %d bits",
+        fsyp->synam, WBITS);
+      }
+     xsp->ap[0] = (word32) (timval & WORDMASK_ULL);
+     xsp->bp[0] = 0L;
+    }
+   else
+    {
+     push_xstk_(xsp, TIMEBITS);
+     xsp->ap[0] = (word32) (timval & WORDMASK_ULL);
+     xsp->ap[1] = (word32) ((timval >> 32) & WORDMASK_ULL);
+     xsp->bp[0] = xsp->bp[1] = 0L;
+    }
+   break;
+  case STN_REALTIME:
+   /* for time as user world (unscaled) time, must convert to real first */
+   d1 =__unscale_realticks(&__simtime, __inst_mod);
+   push_xstk_(xsp, WBITS);
+   /* copy from 1st to 2nd */
+   memcpy(xsp->ap, &d1, sizeof(double));
+   break;
+  case STN_STICKSTIME:
+   push_xstk_(xsp, WBITS);
+   if (__simtime > WORDMASK_ULL)
+    {
+     __sgfinform(411, "system function %s result does not fit in %d bits",
+      fsyp->synam, WBITS);
+    }
+   xsp->ap[0] = (word32) (__simtime & WORDMASK_ULL);
+   xsp->bp[0] = 0L;
+   break;
+  case STN_TICKSTIME:
+   push_xstk_(xsp, TIMEBITS);
+   xsp->ap[0] = (word32) (__simtime & WORDMASK_ULL);
+   xsp->ap[1] = (word32) ((__simtime >> 32) & WORDMASK_ULL);
+   xsp->bp[0] = xsp->bp[1] = 0L;
+   break;
+  case STN_BITSTOREAL:
+   /* this converts the a parts of a 64 bit reg to a wbit real */ 
+   /* know this will be 64 bit or previous error */
+   fax = ndp->ru.x->lu.x;
+   xsp = __eval_xpr(fax);
+   if (xsp->xslen != 64)
+    {
+     __sgfwarn(636, "$bitstoreal of %s value not 64 bits - set to 0",
+      __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+conv_0:
+     d1 = 0.0;
+     memcpy(xsp->ap, &d1, sizeof(double));
+     /* SJM 07/05/03 - need to also adjust b part for real */
+     xsp->xslen = WBITS;
+     xsp->bp = &(xsp->ap[1]);
+     break;
+    } 
+
+   /* notice must silently convert x to 0.0, since port will start at x */
+   if (!vval_is0_(xsp->bp, xsp->xslen)) goto conv_0;
+   /* finally, convert to real - assuming bits good - should convert to */
+   /* something and see what error code is set ? */
+   /* this is stupid but allow looking at the number in debugger */  
+   memcpy(&d1, xsp->ap, sizeof(double)); 
+   /* DBG - LOOKATME - why here 
+   if (finite(d1) == 0) __arg_terr(__FILE__, __LINE__);
+   -- */
+   memcpy(xsp->ap, &d1, sizeof(double)); 
+
+   xsp->bp = &(xsp->ap[1]);
+   xsp->xslen = WBITS;
+   break;
+  case STN_REALTOBITS:
+   push_xstk_(xsp, 64);
+   fax = ndp->ru.x->lu.x;
+   xsp2 = __eval_xpr(fax);
+   /* notice double stored with b (x/z) part as WBITS really 64 */
+   xsp->ap[0] = xsp2->ap[0];
+   xsp->ap[1] = xsp2->bp[0];
+   xsp->bp[0] = xsp->bp[1] = 0L;
+   __pop_xstk();
+   break;
+  case STN_ITOR:
+   /* know arg must be 32 or narrower */
+   fax = ndp->ru.x->lu.x;
+   xsp = __eval_xpr(fax);
+   if (xsp->bp[0] != 0L)
+    {
+     __sgfwarn(631,
+      "system function %s argument %s x/z value converted to 0.0", 
+       fsyp->synam, __msgexpr_tostr(__xs, fax));
+     d1 = 0.0;
+    }
+   else
+    {
+     if (fax->has_sign) { ival = (int32) xsp->ap[0]; d1 = (double) ival; } 
+     else d1 = (double) xsp->ap[0];
+    }
+   /* notice reusing xsp since know size of both is WBITS */
+   memcpy(xsp->ap, &d1, sizeof(double));
+   break;
+  case STN_RTOI:
+   /* think semantics is to convert keeping sign - number maybe 2's compl */
+   fax = ndp->ru.x->lu.x;
+   xsp = __eval_xpr(fax);
+   memcpy(&d1, xsp->ap, sizeof(double));
+   /* DBG - LOOKATME - why here 
+   if (finite(d1) == 0) __arg_terr(__FILE__, __LINE__);
+   -- */
+   ival = (int32) d1;
+   /* reuse expr. that know is WBITS */ 
+   xsp->bp[0] = 0L;
+   xsp->ap[0] = (word32) ival;
+   break;
+  case STN_SIGNED:
+   /* this must eval its argument and then return its value */
+   /* signed is just marking expr - no bit pattern change */
+   fax = ndp->ru.x->lu.x;
+   xsp = __eval_xpr(fax);
+   /* 05/26/04 - may need size change here to mach fcall node size */
+   if (xsp->xslen != ndp->szu.xclen)
+    {
+     if (xsp->xslen < ndp->szu.xclen) __sgn_xtnd_wrd(xsp, ndp->szu.xclen);
+     else __narrow_sizchg(xsp, ndp->szu.xclen);
+    }
+   break;
+  case STN_UNSIGNED:
+   /* this must eval its argument and then return its value */
+   /* word32 is just marking expr - no bit pattern change */
+   fax = ndp->ru.x->lu.x;
+   xsp = __eval_xpr(fax);
+
+   /* 05/26/04 - may need size change here to mach fcall node size */
+   /* but know result always word32 */ 
+   if (xsp->xslen != ndp->szu.xclen) __sizchgxs(xsp, ndp->szu.xclen);
+   
+   /* because function return value has exactly same width as arg - never */
+   /* need conversion */
+   /* DBG remove -- */
+   if (fax->szu.xclen != xsp->xslen) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   break;
+  case STN_RANDOM:
+   __exec_sfrand(ndp);
+   break; 
+  case STN_COUNT_DRIVERS:
+   exec_count_drivers(ndp);
+   break;
+  case STN_DIST_UNIFORM:
+   __exec_dist_uniform(ndp);
+   break;
+  case STN_DIST_EXPONENTIAL:
+   __exec_dist_exp(ndp);
+   break;
+  case STN_DIST_NORMAL:
+   __exec_dist_stdnorm(ndp);
+   break;
+  case STN_DIST_CHI_SQUARE:
+   __exec_chi_square(ndp);
+   break;
+  case STN_DIST_POISSON:
+   __exec_dist_poisson(ndp);
+   break;
+  case STN_DIST_T:
+   __exec_dist_t(ndp);
+   break;
+
+  case STN_DIST_ERLANG:
+   /* not yet implemented make 32 bit x */
+   __sgfwarn(550, "system function %s not implemented - returning 32'bx",
+    fsyp->synam);
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = ALL1W;
+   xsp->bp[0] = ALL1W;
+   break;
+  case STN_Q_FULL:
+   exec_qfull(ndp);  
+   break;
+  case STN_SCALE:
+   fax = ndp->ru.x->lu.x;
+   /* DBG remove */
+   if (fax->optyp != GLBREF) __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   /* this puts scale value on top of stack */
+   __exec_scale(fax);
+   break;
+  case STN_TESTPLUSARGS:
+   exec_testplusargs(ndp);      
+   break;
+  case STN_SCANPLUSARGS:
+   exec_scanplusargs(ndp);      
+   break;
+  case STN_RESET_COUNT:
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = (word32) __reset_count;
+   xsp->bp[0] = 0L;
+   break;
+  case STN_RESET_VALUE:
+   push_xstk_(xsp, WBITS);
+   /* value may be int32 (signed) - caller will interpret */
+   xsp->ap[0] = (word32) __reset_value;
+   xsp->bp[0] = 0L;
+   break;
+  case STN_GETPATTERN:
+   /* should never see get pattern here */
+   __arg_terr(__FILE__, __LINE__);
+   break;
+  case STN_COS: case STN_SIN: case STN_TAN:
+  case STN_ACOS: case STN_ASIN: case STN_ATAN:
+  case STN_COSH: case STN_SINH: case STN_TANH:
+  case STN_ACOSH: case STN_ASINH: case STN_ATANH:
+  case STN_LN: case STN_LOG10: case STN_ABS: case STN_SQRT: case STN_EXP:
+  case STN_HSQRT: case STN_HLOG: case STN_HLOG10: case STN_HDB: 
+   fax = ndp->ru.x->lu.x;
+   exec_1arg_transcendental(sfbp->syfnum, fax);
+   break;
+  case STN_INT:
+   exec_transcendental_int(ndp);
+   break;
+  case STN_SGN:
+   exec_transcendental_sign(ndp);
+   break;
+  case STN_POW: case STN_HPOW: case STN_HPWR: case STN_HSIGN:
+   exec_transcendental_powsign(sfbp->syfnum, ndp);
+   break;
+  case STN_MIN: case STN_MAX:
+   exec_transcendental_minmax(sfbp->syfnum, ndp);
+   break;
+  case STN_ATAN2:
+   exec_transcendental_atan2(ndp);
+   break;
+  case STN_HYPOT:
+   exec_transcendental_hypot(ndp);
+   break;
+  default:
+   /* DBG remove --- */
+   if (sfbp->syfnum < BASE_VERIUSERTFS || (int32) sfbp->syfnum > __last_systf)
+    __case_terr(__FILE__, __LINE__);
+   /* --- */
+   /* call pli system function calltf here - leave ret. value on stk */ 
+   if (sfbp->syfnum <= __last_veriusertf) __pli_func_calltf(ndp);
+   /* vpi_ systf after veriusertfs up to last systf */
+   else __vpi_sysf_calltf(ndp);
+ } 
+}
+
+/*
+ * execute the count driver system function
+ * notice these leave return (count) on expr. stack
+ * change so count forced when force implemented
+ */
+static void exec_count_drivers(struct expr_t *ndp)
+{
+ register struct net_pin_t *npp;
+ register struct expr_t *axp;
+ register int32 i;
+ int32 ri1, ri2, nd_itpop, biti, indi, is_forced, numdrvs, drvcnt[4];
+ word32 val;
+ byte *sbp;
+ struct net_t *np;
+ struct xstk_t *xsp;
+ struct expr_t *idndp;
+ struct gref_t *grp;
+
+ nd_itpop = FALSE;
+ for (i = 0; i < 4; i++) drvcnt[i] = 0; 
+ is_forced = 0;
+ numdrvs = 0;
+ biti = -1;
+ /* first get 1st argument value */
+ axp = ndp->ru.x->lu.x; 
+ /* know if bit select will be non x or earlier error to stop execution */
+ if (axp->optyp == LSB) 
+  {
+   /* must eval. index expr. in ref. not target in case xmr */ 
+   xsp = __eval_xpr(axp->ru.x);
+   biti = xsp->ap[0];
+   __pop_xstk(); 
+   idndp = axp->lu.x;   
+  }
+ else idndp = axp;
+
+ if (idndp->optyp == GLBREF)
+  {
+   grp = idndp->ru.grp;
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+  }
+ np = idndp->lu.sy->el.enp;
+
+ if (biti == -1) indi = 0; else indi = biti;
+ if (np->frc_assgn_allocated)
+  {
+   if (np->ntyp >= NONWIRE_ST)
+    {
+     if (np->nu2.qcval[2*__inum].qc_active ||
+      np->nu2.qcval[2*__inum + 1].qc_active) is_forced = TRUE;
+     }
+   else
+    {
+     if (np->nu2.qcval[np->nwid*__inum + indi].qc_active)
+      is_forced = TRUE;
+    }
+  }
+
+ /* since just evaluating read only must evaluate all drivers in here */
+ /* inout itp and inout mpp NULL which is needed */ 
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->npproctyp == NP_PROC_FILT
+    && npp->npaux->npu.filtitp != __inst_ptr) continue;
+
+   /* need to handle -2 IS specific bit select */ 
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   if (npp->npaux == NULL || ri1 == -1 || biti == -1) goto got_match;
+   if (biti > ri1 || biti < ri2) continue;
+
+got_match:
+   /* need to make sure driver is loaded - no concept of changing here */
+   switch (npp->npntyp) {
+    case NP_VPIPUTV:
+     /* for added vpi driver - this inst. or bit may not be added */
+     /* if not added (used), do not count */
+     if (!__has_vpi_driver(np, npp)) continue; 
+     goto load_driver;
+
+    case NP_GATE: case NP_CONTA: case NP_MDPRT: case NP_PB_MDPRT:
+    case NP_ICONN: case NP_TFRWARG:
+load_driver:
+     /* load driver leaves value on expr. stack */
+     if (np->n_stren)
+      { 
+       if ((xsp = __ld_stwire_driver(npp)) == NULL) break;
+       sbp = (byte *) xsp->ap;
+       val = sbp[indi] & 3;
+       __pop_xstk();
+      }
+     else
+      {
+       xsp = __ld_wire_driver(npp);
+       if (biti == -1) val = (xsp->ap[0] & 1L) | ((xsp->bp[0] & 1L) << 1); 
+       else val = (rhsbsel_(xsp->ap, biti)) | (rhsbsel_(xsp->bp, biti) << 1);
+       __pop_xstk();
+      }
+     (drvcnt[val])++;
+     break;
+    case NP_PULL: break; 
+    default: __case_terr(__FILE__, __LINE__);
+   } 
+   /* other drivers such as pull just ingored in determing drivers */
+  }
+ if (nd_itpop) __pop_itstk();
+
+ /* finally do the storing */
+ numdrvs = drvcnt[0] + drvcnt[1] + drvcnt[3];
+ /* know at least one argument */
+ push_xstk_(xsp, WBITS);
+ xsp->ap[0] = 0;
+ xsp->bp[0] = 0;
+ if ((axp = ndp->ru.x->ru.x) == NULL) goto just_ret; 
+ for (i = 1; axp != NULL; axp = axp->ru.x, i++)
+  {
+   if (axp->lu.x->optyp == OPEMPTY) continue;
+   switch ((byte) i) {
+    case 1: xsp->ap[0] = (word32) is_forced; break;
+    case 2: xsp->ap[0] = (word32) numdrvs; break;
+    /* next 3 are 0, 1, and x drivers */
+    case 3: xsp->ap[0] = (word32) drvcnt[0]; break;
+    case 4: xsp->ap[0] = (word32) drvcnt[1]; break;
+    case 5: xsp->ap[0] = (word32) drvcnt[3]; break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   __exec2_proc_assign(axp->lu.x, xsp->ap, xsp->bp);
+  }
+just_ret:
+ xsp->ap[0] = (numdrvs > 1) ? 1 : 0;
+}
+
+
+/*
+ * execute the test plus args system function
+ * argument does not include the plus
+ */
+static void exec_testplusargs(struct expr_t *ndp)
+{
+ int32 slen;
+ register struct optlst_t *olp;
+ register char *chp, *argchp;
+ int32 rv;
+ struct xstk_t *xsp;
+
+ argchp = __get_eval_cstr(ndp->ru.x->lu.x, &slen);
+ for (rv = 0, olp = __opt_hdr; olp != NULL; olp = olp->optlnxt)
+  {
+   /* ignore markers added for building vpi argc/argv */
+   if (olp->is_bmark || olp->is_emark) continue;
+
+   chp = olp->opt;
+   if (*chp != '+') continue;
+   if (strcmp(&(chp[1]), argchp) == 0) { rv = 1; break; }
+  }
+ push_xstk_(xsp, WBITS);
+ xsp->bp[0] = 0L;
+ xsp->ap[0] = (word32) rv;
+ __my_free(argchp, slen + 1);
+}
+
+/*
+ * execute the scan plus args added system function 
+ * same function as mc_scan_plusargs but assigns to 2nd parameter
+ * almost same code as mc scan plus args pli system task
+ * argument does not include the '+'
+ */
+static void exec_scanplusargs(struct expr_t *ndp)
+{
+ register struct optlst_t *olp;
+ register char *chp;
+ int32 arglen, rv;
+ struct expr_t *fax;
+ struct xstk_t *xsp;
+ char *plusarg;
+ 
+ fax = ndp->ru.x;
+ /* this is the passed argment prefix */
+ plusarg = __get_eval_cstr(fax->lu.x, &arglen);
+
+ /* all options expanded and saved so this is easy */
+ for (rv = 0, olp = __opt_hdr; olp != NULL; olp = olp->optlnxt)
+  {
+   /* ignore markers added for building vpi argc/argv */
+   if (olp->is_bmark || olp->is_emark) continue;
+
+   chp = olp->opt;
+   if (*chp != '+') continue;
+
+   /* option length if the length of the command line plus option string */
+   /* option must be at least as long as passed arg or cannot match */
+   if (strlen(chp) < arglen) continue; 
+   /* match prefix - arg. is same or narrow that plus command line option */
+   if (strncmp(&(chp[1]), plusarg, arglen) == 0)
+    {
+     rv = 1;
+     xsp = __cstr_to_vval(&(chp[arglen + 1]));
+     /* move to next - assign to arg */
+     fax = fax->ru.x;
+
+     /* SJM 05/10/04 - think this can be signed */
+     if (xsp->xslen != fax->lu.x->szu.xclen)
+      {
+       if (xsp->xslen < fax->lu.x->szu.xclen && fax->lu.x->has_sign)
+        __sgn_xtnd_wrd(xsp, fax->lu.x->szu.xclen);
+       else __sizchgxs(xsp, fax->lu.x->szu.xclen);
+      }
+
+     __exec2_proc_assign(fax->lu.x, xsp->ap, xsp->bp);
+     __pop_xstk();
+     break;
+    }
+  }
+ push_xstk_(xsp, WBITS);
+ xsp->bp[0] = 0L;
+ xsp->ap[0] = (word32) rv;
+ __my_free(plusarg, arglen + 1);
+}
+
+/*
+ * execute 1 real in returns real transcendental
+ * places computed real on to expr stack
+ */
+static void exec_1arg_transcendental(int32 syfnum, struct expr_t *fax)
+{
+ double d1, d2;
+ struct xstk_t *xsp;
+
+ /* this pushes avaluated expressions onto stack - always real and replaced */
+ xsp = __eval_xpr(fax);
+ if (!fax->is_real) d1 = __cnvt_stk_to_real(xsp, (fax->has_sign == 1));
+ else memcpy(&d1, xsp->ap, sizeof(double));
+
+ /* DBG - LOOKATME - why here 
+ if (finite(d1) == 0) __arg_terr(__FILE__, __LINE__);
+ -- */
+ switch (syfnum) {
+  case STN_COS: d2 = cos(d1); break;
+  case STN_SIN: d2 = sin(d1); break;
+  case STN_TAN: d2 = tan(d1); break;
+  case STN_ACOS:
+   if (d1 < -1.0 || d1 > 1.0)
+    {
+     __sgfwarn(631,
+      "$acos system function argument %s outside -1 to 1 legal range - returning 0.0", 
+       __msgexpr_tostr(__xs, fax));
+     d2 = 0.0;
+    }
+   else d2 = acos(d1);
+   break;
+  case STN_ACOSH:
+   if (d1 < 1.0)
+    {
+     __sgfwarn(631,
+      "$acosh system function argument %s outside 1 to inf legal range - returning 0.0", 
+       __msgexpr_tostr(__xs, fax));
+     d2 = 0.0;
+    }
+   else d2 = acosh(d1);
+   break;
+  case STN_ASIN:
+   if (d1 < -1.0 || d1 > 1.0)
+    {
+     __sgfwarn(631,
+      "$asin system function argument %s outside -1 to 1 legal range - returning 0.0", 
+       __msgexpr_tostr(__xs, fax));
+     d2 = 0.0;
+    }
+   else d2 = asin(d1);
+   break;
+  case STN_ASINH: d2 = asinh(d1); break;
+  case STN_ATAN: d2 = atan(d1); break;
+  case STN_COSH: d2 = cosh(d1); break;
+  case STN_SINH: d2 = sinh(d1); break;
+  case STN_TANH: d2 = tanh(d1); break;
+  case STN_ATANH:
+   if (d1 < -1.0 || d1 > 1.0)
+    {
+     __sgfwarn(631,
+      "$atanh system function argument %s outside -1 to 1 legal range - returning 0.0", 
+       __msgexpr_tostr(__xs, fax));
+     d2 = 0.0;
+    }
+   else d2 = atanh(d1);
+   break;
+  case STN_LN:
+   if (d1 <= 0.0)
+    {
+     __sgfwarn(631,
+      "$ln system function argument %s illegal non positive - returning 0.0", 
+       __msgexpr_tostr(__xs, fax));
+     d2 = 0.0;
+    }
+   else d2 = log(d1);
+   break;
+  case STN_LOG10:
+   if (d1 <= 0.0)
+    {
+     __sgfwarn(631,
+      "$log10 system function argument %s illegal non positive - returning 0.0", 
+       __msgexpr_tostr(__xs, fax));
+     d2 = 0.0;
+    }
+   else d2 = log10(d1);
+   break;
+  case STN_ABS: d2 = fabs(d1); break;
+  case STN_SQRT:
+   if (d1 < 0.0)
+    {
+     __sgfwarn(631,
+      "$sqrt system function argument %s illegal negative - returning 0.0", 
+       __msgexpr_tostr(__xs, fax));
+     d2 = 0.0;
+    }
+   else d2 = sqrt(d1);
+   break;
+  case STN_EXP: d2 = exp(d1); break;
+  case STN_HSQRT:
+   if (d1 >= 0.0) d2 = sqrt(d1); else d2 = -sqrt(-d1);
+   break;
+  case STN_HLOG:
+   if (d1 > 0.0) d2 = log(d1);
+   else if (d1 == 0.0) d2 = 0.0;
+   else d2 = -log(-d1);
+   break;
+  case STN_HLOG10:
+   if (d1 > 0.0) d2 = log10(d1);
+   else if (d1 == 0.0) d2 = 0.0;
+   else d2 = -log10(-d1);
+   break;
+  case STN_HDB: 
+   if (d1 > 0.0) d2 = log(d1);
+   else if (d1 == 0.0) d2 = 0.0;
+   else d2 = -20.0*log(-d1);
+   break;
+  default: d2 = 0.0; __case_terr(__FILE__, __LINE__);
+ }
+ memcpy(xsp->ap, &d2, sizeof(double));
+ xsp->bp = &(xsp->ap[1]);
+ xsp->xslen = WBITS;
+}
+
+/*
+ * execute transcendental int32 (convert to int32) routine
+ */
+static void exec_transcendental_int(struct expr_t *ndp)
+{
+ int32 ival;
+ double d1;
+ struct expr_t *fax;
+ struct xstk_t *xsp;
+
+ /* this returns 32 bit signed reg aka integer not real */
+ fax = ndp->ru.x->lu.x;
+ xsp = __eval_xpr(fax);
+ if (!fax->is_real)
+  {
+   if (xsp->xslen > WBITS) __narrow_to1wrd(xsp);
+   else
+    {
+     /* SJM 05/10/04 - old style convert to int32 - needs sign extension */
+     if (xsp->xslen < WBITS) __sgn_xtnd_wrd(xsp, fax->szu.xclen);
+    }
+
+   if (xsp->bp[0] != 0) { xsp->ap[0] = ALL1W; xsp->bp[0] = ALL1W; }
+   else 
+    {
+     /* LOOKATME - does this do anything? */ 
+     ival = (int32) xsp->ap[0];
+     xsp->ap[0] = (word32) ival;
+    }
+  }
+ else
+  {
+   memcpy(&d1, xsp->ap, sizeof(double));
+   ival = (int32) d1;
+   xsp->bp[0] = 0L;
+   xsp->ap[0] = (word32) ival;
+  }
+ /* reuse xstk that know is now WBITS */ 
+}
+
+/*
+ * execute transcendental sign routine
+ */
+static void exec_transcendental_sign(struct expr_t *ndp)
+{
+ int32 ival;
+ double d1;
+ struct expr_t *fax;
+ struct xstk_t *xsp;
+
+ /* this returns 32 bit signed reg aka integer not real */
+ fax = ndp->ru.x->lu.x;
+
+ xsp = __eval_xpr(fax);
+ if (!fax->is_real) d1 = __cnvt_stk_to_real(xsp, (fax->has_sign == 1));
+ else memcpy(&d1, xsp->ap, sizeof(double));
+ if (d1 < 0) ival = -1; else if (d1 > 0) ival = 1; else ival = 0;
+ /* reuse xstk that know is WBITS */ 
+ xsp->bp[0] = 0L;
+ xsp->ap[0] = (word32) ival;
+}
+
+/*
+ * exec transcendental pow - takes 2 args
+ * also hspice sign with 2 args here 
+ */
+static void exec_transcendental_powsign(int32 sysfnum, struct expr_t *ndp)
+{
+ int32 ival;
+ double d1, d2, d3;
+ struct expr_t *fax, *fax2;
+ struct xstk_t *xsp;
+
+ ndp = ndp->ru.x;
+ fax = ndp->lu.x;
+ xsp = __eval_xpr(fax);
+ if (!fax->is_real) d1 = __cnvt_stk_to_real(xsp, (fax->has_sign == 1));
+ else memcpy(&d1, xsp->ap, sizeof(double));
+ __pop_xstk();
+
+ ndp = ndp->ru.x;
+ fax2 = ndp->lu.x;
+ xsp = __eval_xpr(fax2);
+ if (!fax2->is_real) d2 = __cnvt_stk_to_real(xsp, (fax2->has_sign == 1));
+ else memcpy(&d2, xsp->ap, sizeof(double));
+
+ d3 = 0.0;
+ if (sysfnum == STN_POW)
+  {
+   if (d1 < 0.0)
+    {
+     double d4;
+
+     /* notice this uses hspice not Verilog conversion to int32 - matters not */
+     ival = (int32) d2;
+     d4 = ival;
+     /* != real */
+     if ((d4 - d2) <= -EPSILON && (d4 - d2) >= EPSILON)
+      {
+       __sgfwarn(631,
+        "$pow system function argument first argument %s negative and second argument %s non integral - returning 0.0", 
+       __msgexpr_tostr(__xs, fax), __msgexpr_tostr(__xs2, fax2));
+       d2 = 0.0;
+      }
+     else d3 = pow(d1, d2);
+    }
+   else d3 = pow(d1, d2);
+  }
+ else if (sysfnum == STN_HPOW)
+  {
+   /* LOOKATME - notice this uses Hspice not Verilog conversion to int32 */
+   ival = (int32) d2;
+   d2 = ival;
+   d3 = pow(d1, d2);
+  }
+ else if (sysfnum == STN_HPWR)
+  {
+   if (d1 > 0.0) d3 = pow(d1, d2);
+   else if (d1 == 0.0) d3 = 0.0;
+   else d3 = -pow(-d1, d2);
+  }
+ else if (sysfnum == STN_HSIGN)
+  {
+   /* notice $hsign returns double but $sign returns int32 */
+   if (d2 > 0.0) d3 = fabs(d1);
+   else if (d2 == 0.0) d3 = 0.0;
+   else d3 = -fabs(d1);
+  }
+ else { d3 = 0.0; __case_terr(__FILE__, __LINE__); }
+
+ memcpy(xsp->ap, &d3, sizeof(double));
+ xsp->bp = &(xsp->ap[1]);
+ xsp->xslen = WBITS;
+}
+
+/*
+ * exec transcendental min/max - takes 2 args
+ * LOOKATME - since can do with arg macro maybe unneeded
+ */
+static void exec_transcendental_minmax(int32 syfnum, struct expr_t *ndp)
+{
+ double d1, d2, d3;
+ struct expr_t *fax;
+ struct xstk_t *xsp;
+
+ ndp = ndp->ru.x;
+ fax = ndp->lu.x;
+ xsp = __eval_xpr(fax);
+ if (!fax->is_real) d1 = __cnvt_stk_to_real(xsp, (fax->has_sign == 1));
+ else memcpy(&d1, xsp->ap, sizeof(double));
+ __pop_xstk();
+
+ ndp = ndp->ru.x;
+ fax = ndp->lu.x;
+ xsp = __eval_xpr(fax);
+ if (!fax->is_real) d2 = __cnvt_stk_to_real(xsp, (fax->has_sign == 1));
+ else memcpy(&d2, xsp->ap, sizeof(double));
+
+ if (syfnum == STN_MIN) d3 = (d1 < d2) ? d1 : d2;
+ else d3 = (d1 > d2) ? d1 : d2;
+
+ memcpy(xsp->ap, &d3, sizeof(double));
+
+ xsp->bp = &(xsp->ap[1]);
+ xsp->xslen = WBITS;
+}
+
+/*
+ * exec transcendental atan2 - takes 2 args
+ */
+static void exec_transcendental_atan2(struct expr_t *ndp)
+{
+ double d1, d2, d3;
+ struct expr_t *fax;
+ struct xstk_t *xsp;
+
+ ndp = ndp->ru.x;
+ fax = ndp->lu.x;
+ xsp = __eval_xpr(fax);
+ if (!fax->is_real) d1 = __cnvt_stk_to_real(xsp, (fax->has_sign == 1));
+ else memcpy(&d1, xsp->ap, sizeof(double));
+ __pop_xstk();
+
+ ndp = ndp->ru.x;
+ fax = ndp->lu.x;
+ xsp = __eval_xpr(fax);
+ if (!fax->is_real) d2 = __cnvt_stk_to_real(xsp, (fax->has_sign == 1));
+ else memcpy(&d2, xsp->ap, sizeof(double));
+
+ d3 = atan2(d1, d2);
+ memcpy(xsp->ap, &d3, sizeof(double));
+
+ xsp->bp = &(xsp->ap[1]);
+ xsp->xslen = WBITS;
+}
+
+/*
+ * exec transcendental hypot (dist func) - takes 2 args
+ */
+static void exec_transcendental_hypot(struct expr_t *ndp)
+{
+ double d1, d2, d3;
+ struct expr_t *fax;
+ struct xstk_t *xsp;
+
+ ndp = ndp->ru.x;
+ fax = ndp->lu.x;
+ xsp = __eval_xpr(fax);
+ if (!fax->is_real) d1 = __cnvt_stk_to_real(xsp, (fax->has_sign == 1));
+ else memcpy(&d1, xsp->ap, sizeof(double));
+ __pop_xstk();
+
+ ndp = ndp->ru.x;
+ fax = ndp->lu.x;
+ xsp = __eval_xpr(fax);
+ if (!fax->is_real) d2 = __cnvt_stk_to_real(xsp, (fax->has_sign == 1));
+ else memcpy(&d2, xsp->ap, sizeof(double));
+
+ d3 = hypot(d1, d2);
+ memcpy(xsp->ap, &d3, sizeof(double));
+
+ xsp->bp = &(xsp->ap[1]);
+ xsp->xslen = WBITS;
+}
+
+
+/*
+ * ROUTINES TO EXEC CAUSE
+ */
+
+/*
+ * execute a cause statement
+ * this is simply an assign to the event variable - gets added to net chg
+ * as normal var change and during prep has normal dce npp's built
+ */
+static void exec_cause(struct st_t *stp)
+{
+ int32 nd_itpop;
+ struct expr_t *xp;
+ struct net_t *np;
+ struct gref_t *grp;
+
+ if (__st_tracing)
+  __tr_msg("trace: %-7d -> %s\n", __slin_cnt,
+   __to_idnam(stp->st.scausx));
+ xp = stp->st.scausx;
+ nd_itpop = FALSE;
+ if (xp->optyp == GLBREF)
+  {
+   /* idea for xmr cause is to cause an event in some other part of the */
+   /* itree - by changine current itree place will match waits only in */
+   /* target of cause instance */ 
+   grp = xp->ru.grp;    
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+  }
+ else if (xp->optyp != ID) __case_terr(__FILE__, __LINE__);
+
+ /* notice even if global ref. can still get net from symbol */ 
+ np = xp->lu.sy->el.enp;
+ /* notice cause does nothing - just schedules trigger for each waiting */
+ /* armed ectrl - so any waiting event control blocks will be activated */
+
+ /* record cause event var change as usual, if no pending do not record */
+ /* must not record or will be worse event ordering dependency */
+ /* know change see if need to record - also maybe dmpvars */
+ record_nchg_(np);
+
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * DISABLE ROUTINES
+ */
+
+/*
+ * ROUTINES TO IMPLEMENT TASK AND THREAD DISABLING
+ */
+
+/*
+ * execute a disable statement - disable tskp
+ * return T to cause disable of current thread (above on chain)
+ * and F if this thread continues as usual
+ * 
+ * this code is not for functions there all disables converted to added gotos
+ * disable argument is task name not ?? 
+ */
+extern int32 __exec_disable(struct expr_t *dsxndp)
+{
+ register struct tskthrd_t *ttp, *ttp_real_r;
+ int32 thread_finished, nd_itpop; 
+ struct sy_t *syp;
+ struct task_t *tskp; 
+ struct thread_t *dsathp, *thp, *thd_1up, *sav_thd;
+ struct gref_t *grp;
+ struct st_t *stp;
+
+ /* this pointer to target symbol in some other module */
+ nd_itpop = FALSE;
+ syp = dsxndp->lu.sy;  
+ if (dsxndp->optyp == GLBREF)
+  { grp = dsxndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+
+ /* disabling every thread associated with task of given instance required */
+ /* first disable and free all underneath */ 
+ tskp = syp->el.etskp;
+ /* assume current thread not disabled */
+ thread_finished = FALSE;
+ /* task can be enabled from >1 place in inst. but share vars */
+ ttp = tskp->tthrds[__inum];
+
+ if (ttp == NULL)
+  { 
+   __sgfinform(469, "disable of %s %s no effect - not active",
+    __to_tsktyp(__xs2, tskp->tsktyp), __msg_blditree(__xs, __inst_ptr, tskp));
+   goto done;
+  }
+ for (; ttp != NULL;)
+  {
+   /* the task thread list that ttp points to will probably be freed */
+   /* changing the right ptr so must get the next before freeing */
+   ttp_real_r = ttp->tthd_r;
+   dsathp = ttp->tthrd;
+
+   /* better point back to self */
+   /* -- DBG remove */
+   if (dsathp->assoc_tsk != NULL && dsathp->assoc_tsk != tskp)
+    __misc_sgfterr(__FILE__, __LINE__);
+   /* --- */
+
+   /* first if recurive task enables, disable top most */
+   if ((thp = find_hgh_sametskthrd(dsathp)) != NULL) dsathp = thp;
+
+   /* case 1: disabling current thread */ 
+   if (dsathp == __cur_thd)
+    {
+     /* cannot unlink here since will be unlinked because thread done */
+     __cur_thd->th_dsable = TRUE;
+     thread_finished = TRUE;
+    }
+   /* case 2: disabling highest thread above currently active */
+   /* this is case where above spawns subthread for task/blk/fj */
+   /* case 1: and 2: mutually exclusive */
+   else if (thread_above_cur(dsathp))
+    {
+     /* free under threads including current */
+     free_thd_subtree(dsathp);
+     /* ok to just set current thread since finished and all under gone */
+     __cur_thd = dsathp;
+     __cur_thd->th_dsable = TRUE;
+     thread_finished = TRUE;
+    }
+   /* disabling thread with scheduled event elsewhere in thread tree */
+   else
+    {
+     thd_1up = dsathp->thpar;
+     /* anything (task-named block than can be disabled here parent */
+     /* DBG remove --- */
+     if (thd_1up == NULL) __misc_terr(__FILE__, __LINE__);
+     if (thd_1up->thofscnt > 1 && !dsathp->th_fj)
+      __misc_terr(__FILE__, __LINE__);  
+     /* --- */
+     /* disable a thread means remove and unlink from parent */
+     thd_1up->thofscnt -= 1;
+     if (dsathp->thleft != NULL) dsathp->thleft->thright = dsathp->thright;
+     /* if first thread finished, make up thofs list point to its right */
+     else thd_1up->thofs = dsathp->thright;
+     if (dsathp->thright != NULL) dsathp->thright->thleft = dsathp->thleft;
+
+     /* free all under and thread itself - mark schd. events canceled */ 
+     free_thd_subtree(dsathp);
+     __free_1thd(dsathp);
+     dsathp = NULL;
+     /* if more subthreads, nothing to do since will eval thread events */
+     /* for other fj subthreads */
+     if (thd_1up->thofscnt == 0)
+      {
+       /* know have parent or cannot get here */
+       /* previously disable thread scheduled, after remove schedule 1 up */
+       /* eliminating any waiting delay/event controls */
+       sav_thd = __cur_thd;
+       __cur_thd = thd_1up;
+       /* if this was task with output parameters - do not store and */
+       /* make sure up thread not in task returning state */
+       if (thd_1up->th_postamble)
+        { stp = thd_1up->thnxtstp->stnxt; thd_1up->th_postamble = FALSE; }
+       else stp = thd_1up->thnxtstp;
+       /* this will incorrectly turn on stmt suspend */ 
+       /* DBG remove --- */
+       if (__stmt_suspend) __misc_terr(__FILE__, __LINE__);
+       /* --- */ 
+       suspend_curthd(stp);
+       __stmt_suspend = FALSE;
+       __cur_thd = sav_thd;
+      }
+    }
+   /* move to next - saved since previous probably freed */
+   ttp = ttp_real_r;
+  }
+
+done:
+ /* DBG remove ---
+ __dmp_tskthd(tskp, __inst_mod);
+ --- */
+ if (nd_itpop) __pop_itstk();
+ return(thread_finished);
+}
+
+/*
+ * find highest thread associated with same task above
+ * return NULL if thread to disable not above this one 
+ */
+static struct thread_t *find_hgh_sametskthrd(struct thread_t *dsthp)
+{
+ register struct thread_t *thp;
+ struct thread_t *highthd;
+
+ for (highthd = NULL, thp = __cur_thd; thp != NULL; thp = thp->thpar)
+  {
+   if (thp->assoc_tsk != NULL && thp->assoc_tsk == dsthp->assoc_tsk)
+    highthd = thp;
+  }
+ return(highthd);
+}
+
+/*
+ * return T if thread is above current thread
+ */
+static int32 thread_above_cur(struct thread_t *dsthp)
+{
+ register struct thread_t *thp;
+
+ for (thp = __cur_thd; thp != NULL; thp = thp->thpar)
+  {
+   if (thp == dsthp) return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * free a thread subtree below thp (but not including thp)
+ */
+static void free_thd_subtree(struct thread_t *thp)
+{
+ if (thp->thofs != NULL) __free_thd_list(thp->thofs);
+ thp->thofscnt = 0;
+ thp->thofs = NULL;
+ thp->th_fj = FALSE;
+}
+
+/*
+ * free a thread list (passed head that is probably thofs)
+ */
+extern void __free_thd_list(struct thread_t *thp)
+{
+ register struct thread_t *thp2, *thp3;
+
+ for (thp2 = thp; thp2 != NULL;)
+  {
+   thp3 = thp2->thright;
+   if (thp2->thofs != NULL) __free_thd_list(thp2->thofs);
+   __free_1thd(thp2);
+   thp2 = thp3;
+  }
+}
+
+/*
+ * free one thread
+ * called after any subthreads freed
+ */
+extern void __free_1thd(struct thread_t *thp)
+{
+ /* every thread with an associated task - unlabeled fork-join will not */
+ /* DBG remove --- */
+ if (thp->th_itp == NULL || thp->th_ialw)
+   __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ __push_itstk(thp->th_itp);
+ free_thd_stuff(thp);
+ __pop_itstk();
+ __my_free((char *) thp, sizeof(struct thread_t)); 
+}
+
+/*
+ * routine used by disable to force finish (free all but thread itself)
+ */
+static void free_thd_stuff(struct thread_t *thp)
+{
+ /* every thread with an associated task - unlabeled fork-join will not */
+ if (thp->tthlst != NULL) unlink_tskthd(thp);
+ if (thp->thdtevi != -1) __tevtab[thp->thdtevi].te_cancel = TRUE;
+ /* notice if free statements (from iact) this will be set to nil */
+ /* since when freeing dctrl and wait freeing the dctp */
+ /* events freed later */
+ if (thp->th_dctp != NULL)
+  {
+   if (thp->th_dctp->dceschd_tevs != NULL)
+    thp->th_dctp->dceschd_tevs[thp->th_itp->itinum] = -1;
+   thp->th_dctp = NULL;
+  }
+ if (thp->th_rhsform) 
+  {
+   __my_free((char *) thp->th_rhswp, 2*WRDBYTES*thp->th_rhswlen);
+   thp->th_rhswp = NULL;
+  }  
+}
+
+/*
+ * unlink and free one task thead - remove from tasks list
+ *
+ * every thread that has assoc task has pointer to 1 tskthrd_t element
+ * that is its entry on task's thread list for given instance 
+ */
+static void unlink_tskthd(struct thread_t *thp)
+{
+ struct tskthrd_t *ttp;
+ struct task_t *tskp;
+
+ ttp = thp->tthlst;
+ /* DBG remove --- */
+ if (__debug_flg && __st_tracing)
+  {
+   /* unlink of disabled thread to with no assoc. task */
+   /* should emit the itree loc. here */
+   if (thp->assoc_tsk == NULL) __misc_sgfterr(__FILE__, __LINE__);
+   __tr_msg("++ unlink task %s for instance %s number %d\n",
+    thp->assoc_tsk->tsksyp->synam, __inst_ptr->itip->isym->synam, __inum);
+  }
+ /* --- */
+
+ /* lifo recursive enable freeing case */
+ if (ttp->tthd_l == NULL)
+  {
+   tskp = thp->assoc_tsk;
+   tskp->tthrds[__inum] = ttp->tthd_r;
+   if (ttp->tthd_r != NULL) ttp->tthd_r->tthd_l = NULL;
+  }
+ else
+  {
+   /* any other order */
+   ttp->tthd_l->tthd_r = ttp->tthd_r;
+   if (ttp->tthd_r != NULL) ttp->tthd_r->tthd_l = ttp->tthd_l;
+  }
+ /* ttp has already been linked out */
+ __my_free((char *) ttp, sizeof(struct tskthrd_t));
+ thp->tthlst = NULL;   
+ /* DBG remove ---
+ __dmp_tskthd(tskp, __inst_ptr->itip->imsym->el.emdp);
+ --- */
+}
+
+/*
+ * SYSTEM TASK/FUNCTION EXECUTION ROUTINES
+ */
+
+/* 
+ * execute the system tasks
+ *
+ * for monitor and strobe effect is to set up later action
+ */
+extern struct st_t *__exec_stsk(struct st_t *stp, struct sy_t *tsyp,
+ struct tskcall_t *tkcp)
+{
+ int32 base, stav, oslen, slen;
+ word32 wval;
+ struct systsk_t *stbp;
+ struct strblst_t *strblp;
+ struct expr_t *argvx;
+ char *chp;
+
+ stbp = tsyp->el.esytbp;
+ switch (stbp->stsknum) {
+  /* file manipulation - most functions */
+  case STN_FCLOSE:
+   /* AIV 09/08/03 - for P1364 2001 must handle both MCD and FILE closes */
+   fio_do_fclose(tkcp->targs);
+   break;
+  case STN_FFLUSH:
+   /* AIV 09/08/03 - for P1364 2001 new sys task - not in 1995 std */
+   /* SJM 09/09/03 - there is POSIX flush all that also flushes PLI */
+   /* and other(?) open files - PORTABILITY? - works on Linux */
+   if (tkcp->targs == NULL) fflush(NULL);
+   else fio_fflush(tkcp->targs->lu.x);
+   break;
+  /* display write to terminal */
+  case STN_DISPLAY: base = BDEC; goto nonf_disp;
+  case STN_DISPLAYB: base = BBIN; goto nonf_disp;
+  case STN_DISPLAYH: base = BHEX; goto nonf_disp;
+  case STN_DISPLAYO:
+   base = BOCT;
+nonf_disp:
+   __do_disp(tkcp->targs, base);
+   __cvsim_msg("\n");
+   break;
+
+  /* write to terminal with no ending nl */
+  case STN_WRITE: base = BDEC; goto nonf_write;
+  case STN_WRITEH: base = BHEX; goto nonf_write;
+  case STN_WRITEB: base = BBIN; goto nonf_write;
+  case STN_WRITEO: base = BOCT;
+nonf_write:
+   __do_disp(tkcp->targs, base);
+   /* if tracing to stdout need the new line just to stdout */
+   /* LOOKATME - could change to separate verilog.trace file ?? */
+   /* NOTICE - this is not __tr_msg */
+   if (__st_tracing && __tr_s == stdout) __cv_msg("\n");
+   break;
+
+  /* multi-channel descriptor display to file */
+  case STN_FDISPLAY: base = BDEC; goto f_disp;
+  case STN_FDISPLAYB: base = BBIN; goto f_disp;
+  case STN_FDISPLAYH: base = BHEX; goto f_disp;
+  case STN_FDISPLAYO:
+   base = BOCT;
+f_disp:
+   __fio_do_disp(tkcp->targs, base, TRUE, tsyp->synam);
+   break;
+
+  /* multi-channel descriptor write to file */
+  case STN_FWRITE: base = BDEC; goto f_write;
+  case STN_FWRITEH: base = BHEX; goto f_write;
+  case STN_FWRITEB: base = BBIN; goto f_write;
+  case STN_FWRITEO: base = BOCT;
+f_write:
+   /* if tracing need the new line */
+   __fio_do_disp(tkcp->targs, base, __st_tracing, tsyp->synam);
+   break;
+  case STN_SWRITE: base = BDEC; goto s_write;
+  case STN_SWRITEH: base = BHEX; goto s_write;
+  case STN_SWRITEB: base = BBIN; goto s_write;
+  case STN_SWRITEO: base = BOCT;
+   /* $swrite([output reg], ...) */
+s_write:
+   fio_swrite(tkcp->targs, base);
+   break;
+  case STN_SFORMAT: 
+   /* SJM 05/14/04 - LOOKATME - LRM is unclear and suggests that $sformat */
+   /* returns a val but it is called a system task in LRM */
+   fio_sformat(tkcp->targs);
+   break; 
+  /* like display except write at end of current time */
+  case STN_FSTROBE: case STN_FSTROBEH: case STN_FSTROBEB: case STN_FSTROBEO:
+  case STN_STROBE: case STN_STROBEH: case STN_STROBEB: case STN_STROBEO:
+   /* if same strobe statement repeated in one time slot - warn/inform */
+   if (stp->strb_seen_now)
+    { 
+     /* if dup. of same inst. and statement, do not re-add */
+     if (!chk_strobe_infloop(stp, tsyp)) break;
+    }
+   if (__strb_freelst != NULL) 
+    {
+     strblp = __strb_freelst;
+     __strb_freelst = __strb_freelst->strbnxt;
+    }
+   else strblp = (struct strblst_t *) __my_malloc(sizeof(struct strblst_t));
+   strblp->strbstp = stp;
+   stp->strb_seen_now = TRUE;
+   strblp->strb_itp = __inst_ptr;
+   strblp->strbnxt = NULL;
+   __iact_can_free = FALSE;
+   if (__strobe_hdr == NULL)
+    {
+     __strobe_hdr = __strobe_end = strblp; 
+     __slotend_action |= SE_STROBE;
+    }
+   else { __strobe_end->strbnxt = strblp; __strobe_end = strblp; }
+   break;
+  /* monitor control sys tasks */ 
+  case STN_MONITOROFF: __monit_active = FALSE; break;
+  case STN_MONITORON:
+   __monit_active = TRUE;
+   __iact_can_free = FALSE;
+   /* when monitor turned on (even if on), trigger even if no changes */
+   /* and update save dce values to current */
+   __slotend_action |= SE_MONIT_CHG;
+   break;
+  case STN_FMONITOR: case STN_FMONITORH: case STN_FMONITORB:
+  case STN_FMONITORO:
+   __start_fmonitor(stp); 
+   __iact_can_free = FALSE;
+   /* DBG remove ---
+   if (__debug_flg)
+    __dmpmod_nplst(__inst_mod, TRUE); 
+   -- */
+   break;
+  /* change monitor write to terminal system tasks */
+  case STN_MONITOR: case STN_MONITORH: case STN_MONITORB: case STN_MONITORO:
+   __start_monitor(stp);
+   __iact_can_free = FALSE;
+   break;
+  /* time releated system tasks */
+  case STN_PRINTTIMESCALE:
+   exec_prttimscale(tkcp->targs);
+   break;
+  case STN_TIMEFORMAT:
+   /* if no `timescale in design, $timeformat is a noop */
+   if (__des_has_timescales) exec_timefmt(tkcp->targs);
+   break;
+  case STN_READMEMB:
+   __exec_readmem(tkcp->targs, BBIN);
+   break;
+  case STN_READMEMH:
+   __exec_readmem(tkcp->targs, BHEX);
+   break;
+  case STN_SREADMEMB:
+   __exec_sreadmem(tkcp->targs, BBIN);
+   break;
+  case STN_SREADMEMH:
+   __exec_sreadmem(tkcp->targs, BHEX);
+   break;
+
+  /* dump variables tasks */
+  case STN_DUMPVARS:
+   __exec_dumpvars(tkcp->targs);
+   break;
+  case STN_DUMPALL:
+   if (__dv_state == DVST_NOTSETUP)
+    {
+     __sgferr(703, "$dumpall ignored because: $dumpvars not set up");
+     break;
+    }
+   /* dumpall is independent of other dumpvars except past file size limit */
+   /* but still must dump at end of time slot */
+   if ((__slotend_action & SE_DUMPALL) != 0)
+    __sgfinform(445,
+     "$dumpall ignored beause: $dumpall already executed at this time");
+   /* turn on need dumpall plus need some dump vars action */
+   __slotend_action |= (SE_DUMPALL | SE_DUMPVARS);
+   break;
+  case STN_DUMPFILE: 
+   /* SJM 10/26/00 - fix to match XL */
+   /* can set dumpvars file name before time of dumpvars setup */
+   /* but not after dumpvars started */
+   if (__dv_seen)
+    {
+     __sgferr(1066,
+      "$dumpfile name set at time after $dmmpvars started - name not changed");
+     break;
+    }
+   /* if no argument just leaves default - cannot be called more than once */
+   if (tkcp->targs == NULL) break;
+
+   /* set the file to dump too */
+   argvx = tkcp->targs->lu.x;
+   chp = __get_eval_cstr(argvx, &slen);
+   /* cannot open yet but must save */
+   oslen = strlen(__dv_fnam);
+   if (__dv_fnam != NULL) __my_free((char *) __dv_fnam, oslen + 1);
+   __dv_fnam = chp;
+   break;
+  case STN_DUMPFLUSH:
+   /* flush the file now since need to flush before adding this times */
+   /* dumpvars */
+   if (__dv_state == DVST_NOTSETUP)
+    {
+     __sgferr(703,
+      "$dumpflush ignored because: dumping of variables not begun");
+     break;
+    }
+   if (__dv_fd == -1) __arg_terr(__FILE__, __LINE__);
+   /* flush when called - i.e. flush is before this time's dumping */
+   /* this call OS functions that may set errno */
+   __my_dv_flush();
+   break;
+  case STN_DUMPLIMIT:
+   /* notice can call even if not set up and can change if not over limit */
+   argvx = tkcp->targs->lu.x;
+   if (!__get_eval_word(argvx, &wval) || ((wval & (1 << (WBITS - 1))) != 0))
+    {
+     __sgferr(1036, "$dumplimit value %s illegal positive integer - not set",
+      __msgexpr_tostr(__xs, tkcp->targs));
+     break;
+    }
+    
+   /* if already over limit cannot change */
+   if (__dv_state == DVST_OVERLIMIT)
+    {
+     __sgferr(1069,
+      "$dumplimit not set to %d - dump file already over previous limit %d",
+      (int32) wval, __dv_dumplimit_size);
+     break;
+    }
+   /* else inform if already set */
+   if (__dv_dumplimit_size != 0)
+    {
+     __sgfinform(449, "$dumplimit changed from %d to %d",
+      __dv_dumplimit_size, (int32) wval);
+    }
+   __dv_dumplimit_size = (int32) wval; 
+   break;
+  case STN_DUMPON: 
+   switch ((byte) __dv_state) {
+    case DVST_NOTSETUP:
+     __sgferr(703, "$dumpon ignored because: $dumpvars not set up");
+     break;
+    /* if over limit silently ignore */
+    case DVST_OVERLIMIT: break;
+    case DVST_DUMPING:
+     if ((__slotend_action & SE_DUMPOFF) != 0)
+      {
+       __sgfinform(453, "$dumpon overrides $dumpoff executed at this time");
+       __slotend_action &= ~SE_DUMPOFF;
+      }
+     __sgfinform(446, "$dumpon ignored because: dumping already on");
+     break;
+    case DVST_NOTDUMPING:
+     if ((__slotend_action & SE_DUMPON) != 0)
+      __sgfinform(445,
+       "$dumpon ignored because: $dumpon already executed at this time");
+     /* also indicate need some dumpvars action */
+     __slotend_action |= (SE_DUMPON | SE_DUMPVARS);
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   break;
+  case STN_DUMPOFF: 
+   switch ((byte) __dv_state) {
+    case DVST_NOTSETUP:
+     __sgferr(703, "$dumpoff ignored because: $dumpvars not set up");
+     break;
+    case DVST_OVERLIMIT: break;
+    case DVST_NOTDUMPING:
+     if ((__slotend_action & SE_DUMPON) != 0)
+      {
+       __sgfinform(453, "$dumpoff overrides $dumpon executed at this time");
+       __slotend_action &= ~SE_DUMPON;
+      }
+     __sgfinform(446, "$dumpoff ignored because: dumping already off");
+     break;
+    case DVST_DUMPING:
+     if ((__slotend_action & SE_DUMPON) != 0)
+      __sgfinform(445,
+       "$dumpoff ignored because: $dumpoff already executed at this time");
+     /* also indicate need some dumpvars action even if no changes */
+     __slotend_action |= (SE_DUMPOFF | SE_DUMPVARS);
+     break;
+    default: __case_terr(__FILE__, __LINE__); 
+   }
+   break;
+  case STN_INPUT:
+   __exec_input_fnamchg(tkcp->targs);
+   break;
+  case STN_HISTORY:
+   /* LRM strictly requires all element here */
+   __exec_history_list(__hist_cur_listnum);
+   break;
+  case STN_NOKEY:
+no_key:
+   __sgfwarn(560, "%s no effect - obsolete key file not supported",
+    tsyp->synam);
+   /* DBGER ---
+   __save_key_s = __key_s;
+   __nokey_seen = TRUE;
+   __key_s = NULL;
+   break;
+   -- */
+  case STN_KEY:
+   goto no_key;
+  case STN_KEEPCMDS: 
+   if (__history_on)
+    __sgfinform(458, "%s ignored - command history saving already on", 
+     tsyp->synam);
+   __history_on = TRUE; 
+   break;
+  case STN_NOKEEPCMDS: 
+   if (!__history_on)
+    __sgfinform(458, "%s ignored - command history saving already off", 
+     tsyp->synam);
+   __history_on = FALSE; 
+   break;
+  case STN_NOLOG:
+   if (__log_s != NULL) fflush(__log_s);
+   __save_log_s = __log_s;   
+   
+   /* notice cannot close log file */
+   /* SJM 03/26/00 - 2 in Verilog 2000 not used for log file lumped with */
+   /*  stdout (bit 0 value 1) */
+   /* ---
+   if (__mulchan_tab[2].mc_s != NULL) 
+    {
+     __mulchan_tab[2].mc_s = NULL;
+     chp = __mulchan_tab[2].mc_fnam;
+     __my_free(chp, strlen(chp) + 1);
+     __mulchan_tab[2].mc_fnam = NULL;
+    }
+   --- */
+   __log_s = NULL;
+   break;
+  case STN_LOG:
+   exec_log_fnamchg(tkcp->targs); 
+   break;
+  case STN_TRACEFILE:
+   argvx = tkcp->targs->lu.x;
+   exec_trace_fnamchg(argvx); 
+   break;
+  case STN_SCOPE:
+   exec_expr_schg(tkcp->targs->lu.x);
+   break;
+  /* listing off because no interactive environment */
+  case STN_LIST:
+   /* list current scope - */
+   if (tkcp->targs != NULL)
+    {
+     struct itree_t *sav_scope_ptr = __scope_ptr;
+     struct task_t *sav_tskp = __scope_tskp;
+
+     exec_expr_schg(tkcp->targs->lu.x);
+     __do_scope_list();
+     __scope_ptr = sav_scope_ptr; 
+     __scope_tskp = sav_tskp;
+    }
+   else __do_scope_list();
+   break;
+
+  /* unimplemented - need complicated state write file mechanism */
+  case STN_SAVE: case STN_INCSAVE: case STN_RESTART:
+   goto un_impl;
+
+  case STN_FINISH:
+   if (__tfrec_hdr != NULL) __call_misctfs_finish();
+   if (__have_vpi_actions) __vpi_endsim_trycall();
+   stav = get_opt_starg(tkcp->targs, 1); 
+   if (stav >= 1 || __verbose)
+    {
+     /* LOOKATME - why needed - if (!__quiet_msgs) __cv msg("\n"); */
+     __cv_msg("Halted at location %s time %s from call to $finish.\n",   
+      __bld_lineloc(__xs2, (word32) __sfnam_ind, __slin_cnt),
+      __to_timstr(__xs, &__simtime));
+    }
+   if (stav >= 2 || __verbose) __emit_stsk_endmsg();
+   /* notice must always print error counts if any */
+   if (__pv_err_cnt != 0 || __pv_warn_cnt != 0 || __inform_cnt != 0)
+    __cv_msg("  There were %d error(s), %d warning(s), and %d inform(s).\n",
+     __pv_err_cnt, __pv_warn_cnt, __inform_cnt);
+   __my_exit(0, TRUE);
+  case STN_STOP:
+   if (__no_iact)
+    {
+     __sgfwarn(560, "%s no effect - interactive environment disabled",
+      stbp->stsknam);
+     break;
+    }
+   if (__iact_state)
+    {
+     __sgfwarn(587, "%s no effect - enabled from interactive debugger",
+      stbp->stsknam);
+     break;
+    }
+   stav = get_opt_starg(tkcp->targs, 1); 
+   if (stav >= 1)
+    {
+     if (!__quiet_msgs) __cv_msg("\n");
+     __cv_msg(
+      "$stop executed at time %s from source location %s.\n",
+      __to_timstr(__xs, &__simtime), __bld_lineloc(__xs2,
+      (word32) __sfnam_ind, __slin_cnt));
+    }
+   if (stav >= 2) __emit_stsk_endmsg();
+   __pending_enter_iact = TRUE;
+   __iact_reason = IAER_STOP;
+   signal(SIGINT, SIG_IGN);
+   __stmt_suspend = TRUE;
+   suspend_curthd(stp->stnxt);
+   return(NULL);
+  case STN_SETTRACE:
+   /* statement tracing change requires suspend of thread */
+   __st_tracing = TRUE;
+   /* if enabled from interactive state, suspend will cause core dump */
+   if (!__iact_state) suspend_curthd(stp->stnxt);
+   /* if trace file name set from command option open now if not open */  
+   __maybe_open_trfile();
+   return(NULL);
+  case STN_CLEARTRACE: 
+   __st_tracing = FALSE;
+   break;
+  case STN_SETEVTRACE:
+   __ev_tracing = TRUE;
+   /* if trace file name set from command option open now if not open */  
+   __maybe_open_trfile();
+   break;
+  case STN_CLEAREVTRACE:
+   /* notice leave file open */
+   __ev_tracing = FALSE;
+   break;
+  case STN_SETDEBUG:
+   __debug_flg = TRUE;
+   break;
+  case STN_CLEARDEBUG:
+   __debug_flg = FALSE;
+   break;
+  case STN_SHOWVARS:
+   do_showvars_stask(tkcp->targs);
+   break;
+  case STN_SHOWVARIABLES:
+   /* for now same as showvars - i.e. skip 1st control arg. */
+   do_showvars_stask(tkcp->targs->ru.x);
+   break;
+  case STN_SYSTEM:
+   /* $system with no args, means run interactive shell */ 
+   if (tkcp->targs == NULL) chp = __pv_stralloc(" ");
+   else
+    {
+     argvx = tkcp->targs->lu.x;
+     if (argvx->optyp == OPEMPTY) { chp = __pv_stralloc(" "); slen = 1; }
+     else chp = __get_eval_cstr(argvx, &slen);
+    }
+   __escape_to_shell(chp);
+   slen = strlen(chp);
+   __my_free(chp, slen + 1);
+   break;
+  case STN_SUPWARNS:
+   do_warn_supp_chg(stbp->stsknam, tkcp->targs, TRUE);
+   break;   
+  case STN_ALLOWWARNS:
+   do_warn_supp_chg(stbp->stsknam, tkcp->targs, FALSE);
+   break;
+  case STN_MEMUSE:
+   /* this will force output */
+   __cvsim_msg("Approximately %ld bytes allocated dynamic storage.\n",
+     __mem_use);
+   __cvsim_msg("Verilog arrays (memories) require %ld bytes.\n", __arrvmem_use);
+   break;
+  case STN_FLUSHLOG:
+   /* LOOKATME - maybe should check for rare but possible error */
+   if (__log_s != NULL) fflush(__log_s);
+   if (__tr_s != NULL) fflush(__tr_s);
+   break;
+  case STN_RESET:
+   /* do reset processing - final step is long jmp to top level */
+   do_reset(tkcp->targs);
+   break;
+  case STN_SNAPSHOT:
+   stav = get_opt_starg(tkcp->targs, DFLT_SNAP_EVS); 
+   __write_snapshot(stav);
+   break;
+  case STN_SHOWALLINSTANCES:
+   __prt2_mod_typetab(FALSE);
+   break;
+  case STN_SHOWSCOPES:
+   do_showscopes(tkcp->targs);
+   break;
+  /* graphical output tasks - ignore with warn */
+  case STN_GRREMOTE:
+  case STN_PSWAVES:
+  case STN_GRSYNCHON:
+  case STN_GRREGS:
+  case STN_GRWAVES:
+  case STN_FREEZEWAVES:
+  case STN_DEFINEGROUPWAVES:
+   /* earlier warning - just ignore */
+   break;
+   
+  /* internal simulation state printng tasks */
+  case STN_SHOWEXPANDEDNETS: goto un_impl;
+
+  /* q manipulation tasks - also q_full function */
+  case STN_Q_INITIALIZE:
+   do_q_init(tkcp->targs);
+   break;
+  case STN_Q_ADD:
+   do_q_add(tkcp->targs);
+   break;
+  case STN_Q_REMOVE:
+   do_q_remove(tkcp->targs);
+   break;
+  case STN_Q_EXAM:
+   do_q_examine(tkcp->targs);
+   break;
+  case STN_SDF_ANNOTATE:
+   __exec_sdf_annotate_systsk(tkcp->targs);
+   break;
+  default:
+   /* DBG remove --- */
+   if (stbp->stsknum < BASE_VERIUSERTFS || (int32) stbp->stsknum > __last_systf)
+     __case_terr(__FILE__, __LINE__);
+   /* --- */
+   /* exec (call) pli user tf system function here */ 
+   if (stbp->stsknum <= __last_veriusertf) __pli_task_calltf(stp);
+   else __vpi_syst_calltf(stp);
+ }
+ return(stp->stnxt);
+
+un_impl:
+ __sgfwarn(550, "system task %s not implemented - ignored", stbp->stsknam);
+ return(stp->stnxt);
+}
+
+/*
+ * MISCELLANEOUS SYSTEM TASK EXEC ROUTINES
+ */
+
+/*
+ * check strobe statement repeated in same strobe system task call
+ *
+ * notice this only called if know strobe task enable statement repeated
+ * checking for strobe repeated but in different instance 
+ */
+static int32 chk_strobe_infloop(struct st_t *stp, struct sy_t *tsksyp)
+{
+ register struct strblst_t *strbp;
+ int32 match;
+ 
+ match = FALSE;
+ for (strbp = __strobe_hdr; strbp != NULL; strbp = strbp->strbnxt)
+  {
+   if (strbp->strbstp == stp)
+    {
+     match = TRUE; 
+     if (strbp->strb_itp == __inst_ptr)
+      {
+       __sgfwarn(527, "%s enable for instance %s repeated at this time",
+        tsksyp->synam, __msg2_blditree(__xs, __inst_ptr));
+       return(FALSE);
+      }
+     /* maybe should only inform one inform per call ? */
+     __sgfinform(434, "%s enable in instance %s repeated in %s at this time", 
+      tsksyp->synam, __msg2_blditree(__xs, __inst_ptr),
+      __msg2_blditree(__xs2, strbp->strb_itp));
+    }
+  }
+ if (!match) __case_terr(__FILE__, __LINE__);
+ return(TRUE);
+}
+
+/*
+ * setup event from suspend (^c or $stop or stmt. break) of cur. thread
+ * stp is place to begin after wake up
+ * links new event on front of current event list
+ */
+static void suspend_curthd(struct st_t *stp)
+{
+ i_tev_ndx tevpi;
+
+ alloc_tev_(tevpi, TE_THRD, __inst_ptr, __simtime);
+ __cur_thd->thdtevi = tevpi;
+ __tevtab[tevpi].tu.tethrd = __cur_thd;
+ __cur_thd->thnxtstp = stp;
+ __stmt_suspend = TRUE;
+ __suspended_thd = __cur_thd;
+ __suspended_itp = __inst_ptr;
+ /* must save suspended, but popping done in event processing loop */
+ __cur_thd = NULL;
+
+ /* if hit break or step in func. save event, must unde (extr. and cancel) */
+ /* to continue in function without going through event processing loop */
+ if (__fcspi >= 0) __fsusp_tevpi = tevpi; else __fsusp_tevpi = -1;
+
+ /* since just suspending and want to continue from here, put on front */
+ __add_ev_to_front(tevpi);
+ /* maybe remove this since - will print interactive msg anyway ? */
+ if (__debug_flg && __st_tracing)
+  {
+   if (stp != NULL)
+    sprintf(__xs2,  "at %s", __bld_lineloc(__xs, stp->stfnam_ind,
+     stp->stlin_cnt));
+   else strcpy(__xs2, "**past end");
+   __tr_msg("-- suspend of current thread, was enabled at %s, continue %s\n",
+    __bld_lineloc(__xs, __suspended_thd->thenbl_sfnam_ind,
+      __suspended_thd->thenbl_slin_cnt), __xs2);
+  }
+}
+
+/*
+ * routine to open trace output file when needed
+ */
+extern void __maybe_open_trfile(void)
+{
+ if (strcmp(__tr_fnam, "stdout") == 0 || __tr_s != NULL) return;
+ if ((__tr_s = __tilde_fopen(__tr_fnam, "w")) == NULL)
+  {
+   __sgferr(1247, "cannot open trace output file %s - stdout used",
+    __tr_fnam);
+   __tr_s = stdout;
+   __my_free(__tr_fnam, strlen(__tr_fnam) + 1);
+   __tr_fnam = __my_malloc(7);
+   strcpy(__tr_fnam, "stdout");
+  }
+}
+
+/*
+ * execute the multi-channel descriptor file close 
+ * this is a system task not function  
+ *
+ * SJM 08/09/03 - FIXME ??? - need to disable pending f monit or strobe 
+ */
+static void mcd_do_fclose(struct expr_t *axp)
+{
+ word32 mcd;
+ struct xstk_t *xsp;
+
+ xsp = __eval_xpr(axp->lu.x);
+ if (xsp->bp[0] != 0L) 
+  {
+   __sgfwarn(611, 
+    "$fclose multi-channel descriptor %s contains x or z bits - no action",
+    __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+   __pop_xstk();
+   return;
+  }
+ /* system task does not return anything but vpi_ call does */
+ mcd = xsp->ap[0]; 
+ __pop_xstk();
+ __close_mcd((word32) mcd, FALSE);
+}
+
+/*
+ * close mcd
+ */
+extern word32 __close_mcd(word32 mcd, int32 from_vpi)
+{
+ register int32 i;
+ int32 err;
+
+ err = FALSE;
+ if (mcd == 0L)
+  {
+   if (!from_vpi)
+    {
+     __sgfinform(431,
+      "$fclose passed empty (no bits on) multi-channel descriptor");
+    }
+   return(bld_open_mcd());
+  }
+ if ((mcd & 1L) != 0)  
+  {
+   if (!from_vpi)
+    {
+     __sgfinform(432,
+      "$fclose bit 1 (stdout) multi-channel descriptor cannot be closed");
+    }
+   err = TRUE;
+  }
+ if ((mcd & 2L) != 0)  
+  {
+   if (!from_vpi)
+    {
+     __sgfinform(432,
+      "$fclose bit 2 (stderr) multi-channel descriptor cannot be closed");
+    }
+   err = TRUE;
+  }
+ for (i = 2; i < 31; i++)
+  {
+   if (((mcd >> i) & 1L) == 0L) continue;
+
+   if (__mulchan_tab[i].mc_s == NULL)
+    {
+     if (!from_vpi)
+      {
+       __sgfwarn(611,
+        "$fclose multi-channel descriptor bit %d on, but file already closed",
+        i + 1);  
+      }
+     err = TRUE;
+     continue;
+    }  
+   __my_fclose(__mulchan_tab[i].mc_s);
+   __mulchan_tab[i].mc_s = NULL;
+   __my_free(__mulchan_tab[i].mc_fnam, strlen(__mulchan_tab[i].mc_fnam) + 1); 
+   __mulchan_tab[i].mc_fnam = NULL;
+  }
+ if (!from_vpi)
+  {
+   if (((mcd >> 31) & 1L) != 0L)
+    {
+     __sgfwarn(611,
+      "$fclose multi-channel descriptor bit 31 on, but no open file - unusable because reserved for new Verilog 2000 file I/O");
+     err = TRUE;
+    }
+  }  
+
+ if (err) return(bld_open_mcd());
+ return(0);
+}
+
+/*
+ * build a mc descriptor for open channels 
+ */
+static word32 bld_open_mcd(void)
+{ 
+ word32 mcd; 
+ register int32 i;
+
+ /* SJM 03/26/00 - high bit 32 reserved for new Verilog 2000 file I/O */
+ for (i = 0, mcd = 0; i < 31; i++)
+  {
+   if (__mulchan_tab[i].mc_s == NULL) continue;
+   mcd |= (1 << i);   
+  }
+ return(mcd);
+}
+
+/*
+ * execute the multi-channel descriptor file open
+ * assigns to next free descriptor slot if one available
+ *
+ * this is system function that returns 0 on fail 
+ * 1 (index 0) is stdout and log file, 2 (index 1) is stder
+ */
+static word32 mc_do_fopen(struct expr_t *axp)
+{
+ int32 slen;
+ char *chp;
+
+ chp = __get_eval_cstr(axp, &slen);
+ return(__mc1_fopen(chp, strlen(chp), FALSE));
+}
+
+/*
+ * do the mcd fopen if possible
+ */
+extern word32 __mc1_fopen(char *chp, int32 slen, int32 from_vpi)
+{
+ register int32 i; 
+ FILE *tmp_s;
+
+ /* SJM 03/26/00 - changed to match Verilog 2000 LRM */
+ /* if name matches exactly return open - this is only heuristic */
+ /* notice 2 is bit 3 (or value 4) that is first to use */
+ /* bit 31 is rserved for new c style file open enhancement */
+ for (i = 2; i < 31; i++) 
+  {
+   if (__mulchan_tab[i].mc_s == NULL) continue; 
+
+   /* LOOKATME - not storing in tilde expanded form - same name can */
+   /* mismatch but will just get open error from OS */
+   if (strcmp(__mulchan_tab[i].mc_fnam, chp) == 0)
+    {
+     if (!from_vpi)
+      {
+       __sgfinform(433,
+        "$fopen of %s failed: file already open and assigned to channel %d",
+          chp, i + 1);
+        __my_free(chp, slen + 1);
+      }
+     return((word32) (1L << i));
+    }
+  }
+
+ for (i = 2; i < 31; i++) 
+  { if (__mulchan_tab[i].mc_s == NULL) goto found_free; }
+ if (!from_vpi)
+  {
+   __sgfinform(433,
+    "$fopen of %s failed: no available multi-channel descriptor", chp);
+  }
+err_done:
+ __my_free(chp, slen + 1);
+ return(0);
+
+found_free:
+ if ((tmp_s = __tilde_fopen(chp, "w")) == NULL)
+  {
+   if (!from_vpi) 
+    {
+     __sgfinform(433, "$fopen of %s multi-channel bit %d failed: %s",
+      chp, i, strerror(errno));
+    }
+   goto err_done;
+  }
+ __mulchan_tab[i].mc_s = tmp_s;
+ /* know this is closed so no previous name to free */
+ __mulchan_tab[i].mc_fnam = chp;
+ /* notice first unused is 3 which is bit 4 on (if low bit is 1) */
+ return((word32) (1L << i));
+}
+
+
+/*
+ * execute showvars system task
+ * this is called with fcall comma arg. list header not value 
+ */
+static void do_showvars_stask(struct expr_t *argxp)
+{
+ register int32 ni;
+ register struct expr_t *xp;
+ register struct net_t *np;
+ int32 nd_itpop;
+ struct gref_t *grp;
+ struct task_t *tskp;
+ struct expr_t *ndp;
+
+ if (__iact_state) tskp = __scope_tskp;
+ else tskp = __getcur_scope_tsk();
+
+ /* notice here, calling itree location correct */
+ if (argxp == NULL)
+  {
+   /* if no arguments - all variables in current scope */
+   __cvsim_msg(">>> $showvars all local variables - scope %s type %s.\n",
+    __msg_blditree(__xs, __inst_ptr, tskp), __inst_ptr->itip->imsym->synam);
+   if (tskp != NULL)
+    {
+     if (tskp->trnum != 0)
+      {
+       np = &(tskp->tsk_regs[0]);
+       for (ni = 0; ni < tskp->trnum; ni++, np++) __emit_1showvar(np, NULL);
+      }
+    }
+   else
+    {
+     if (__inst_mod->mnnum != 0)
+      {
+       for (ni = 0, np = &(__inst_mod->mnets[0]); ni < __inst_mod->mnnum;
+        ni++, np++)
+        __emit_1showvar(np, NULL);
+      }
+    }
+  }
+ else
+  {
+   /* go through list of variables - may be xmr's */ 
+   /* these can be only var, bit select or part select */
+   __cvsim_msg(
+    ">>> $showvars list of variables form - current scope %s type %s.\n",
+    __msg_blditree(__xs, __inst_ptr, tskp), __inst_ptr->itip->imsym->synam);
+   for (xp = argxp; xp != NULL; xp = xp->ru.x)
+    {
+     nd_itpop = FALSE;
+     grp = NULL;
+     ndp = xp->lu.x;
+     if (ndp->optyp == LSB || ndp->optyp == PARTSEL)
+      {
+       np = ndp->lu.x->lu.sy->el.enp;
+       if (ndp->lu.x->optyp == GLBREF)
+        {
+         grp = ndp->lu.x->ru.grp;
+         __xmrpush_refgrp_to_targ(grp);
+         nd_itpop = TRUE;
+        }
+      }
+     else
+      {
+       if (ndp->optyp == GLBREF)
+        { grp = ndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+       np = ndp->lu.sy->el.enp;
+      }
+     __emit_1showvar(np, grp);
+     if (nd_itpop) __pop_itstk();
+    }
+  }
+}
+
+/*
+ * set new suppressed warnings during simulation
+ */
+static void do_warn_supp_chg(char *stnam, struct expr_t *argxp, int32 supp)
+{
+ int32 argi;
+ word32 ernum;
+ struct expr_t *ndp;
+
+ for (argi = 1; argxp != NULL; argxp = argxp->ru.x, argi++)
+  {
+   ndp = argxp->lu.x;
+   if (!__get_eval_word(ndp, &ernum))
+    {
+bad_num:
+     __sgferr(714,
+      "%s argument %d value %s illegal or outside of inform/warning number range",
+      stnam, argi, __msgexpr_tostr(__xs, ndp));
+     continue;
+    }
+   if (!__enum_is_suppressable(ernum)) goto bad_num;
+
+   if (supp) __wsupptab[ernum/WBITS] |= (1 << (ernum % WBITS));
+   else __wsupptab[ernum/WBITS] &= ~(1 << (ernum % WBITS));
+  }
+}
+
+/*
+ * execute reset system task
+ */
+static void do_reset(struct expr_t *axp)
+{
+ int32 enter_iact, reset_val, diag_val;
+
+ /* assume interactive entry in case reset value (2nd) arg missing */
+ enter_iact = TRUE;
+ reset_val = 0;
+ diag_val = 0; 
+ if (axp == NULL) goto do_it;
+ if (get_opt_starg(axp, 0) != 0) enter_iact = FALSE;
+ if ((axp = axp->ru.x) == NULL) goto do_it; 
+ reset_val = get_opt_starg(axp, 0);
+ if ((axp = axp->ru.x) == NULL) goto do_it; 
+ diag_val = get_opt_starg(axp, 0);
+
+do_it:
+ if (diag_val >= 1)
+  {
+   if (!__quiet_msgs) __cv_msg("\n");
+   __cv_msg("$reset to time 0 called from location %s at time %s.\n",
+    __bld_lineloc(__xs2, (word32) __sfnam_ind, __slin_cnt),
+    __to_timstr(__xs, &__simtime));
+  }
+ if (diag_val >= 2) __emit_stsk_endmsg();
+ /* enter interactive unless reset value given and non zero */
+ if (reset_val != 0) enter_iact = FALSE;
+
+ if (enter_iact) __stop_before_sim = TRUE;
+ else __stop_before_sim = FALSE;
+ /* record state changes caused by arguments */
+ __reset_value = reset_val;
+
+ /* reenable the normal ^c signal handler - when variables reset */
+ /* sim will replace with sim handler for entering interactive */
+#if defined(INTSIGS)
+ signal(SIGINT, __comp_sigint_handler);
+#else
+ signal(SIGINT, (void (*)()) __comp_sigint_handler);
+#endif
+
+ /* this does not return - uses lng jmp */
+ longjmp(__reset_jmpbuf, 1);
+}
+
+/*
+ * write the scope information
+ * uses current scope not interactive - except $scope also changes current 
+ * if in interactive mode
+ */
+static void do_showscopes(struct expr_t *axp)
+{
+ word32 flag;
+ struct task_t *tskp;
+ struct mod_t *imdp;
+ struct sy_t *syp;
+
+ if (axp == NULL) flag = 0;
+ else if (!__get_eval_word(axp->lu.x, &flag))
+  {
+   __sgfwarn(646, "$showscopes argument value %s has x/z bits - made 0",
+    __msgexpr_tostr(__xs, axp->lu.x));
+   flag = 0;
+  }
+ /* use current thread to determine if in task */
+ /* if no thread (sim. not started) cannot be active task */
+ if (__cur_thd == NULL) tskp = NULL; else tskp = __getcur_scope_tsk();
+
+ /* 0 means current level, other value all underneath */
+ if (flag == 0)
+  {
+   if (tskp == NULL) prt_1m_scopelist(__inst_ptr);
+   else prt_1tsk_scopelist(tskp, TRUE);
+  }
+ else
+  { 
+   __cvsim_msg("Nested scopes:\n");
+   __outlinpos = 0;
+   __pv_stlevel = 0;
+
+   if (tskp == NULL) prt_1m_nestscopes(__inst_ptr);
+   /* if current scope is task, must print out named blocks inside */
+   else prt_1tsk_nestscopes(tskp->tsksymtab->sytofs);
+
+   __pv_stlevel = 0;
+   __outlinpos = 0;
+  }
+
+ /* final step is printing current scope and list of top level modules */
+ imdp = __inst_mod;
+ 
+ if (tskp == NULL) syp = imdp->msym; else syp = tskp->tsksyp;
+ __cvsim_msg("Current scope: %s (file %s line %d)\n",
+  __msg_blditree(__xs, __inst_ptr, tskp), __schop(__xs2,
+  __in_fils[syp->syfnam_ind]), syp->sylin_cnt); 
+ __prt_top_mods();
+}
+
+/*
+ * show one module scope level given itree location 
+ *
+ * notice this is sort of static since once at itree location under same
+ * 4 catagories of scopes: instances, tasks, functions, named blocks
+ * everything here but named blockes in tasks/functions or named blocks
+ */
+static void prt_1m_scopelist(struct itree_t *itp)
+{
+ register int32 i;
+ register struct task_t *tskp;
+ int32 none, first_time;
+ struct mod_t *imdp;
+ struct inst_t *ip;
+
+ if (__outlinpos != 0) __misc_terr(__FILE__, __LINE__);
+ /* first instances */
+ __pv_stlevel = 0;
+ imdp = itp->itip->imsym->el.emdp;
+ if (imdp->minum != 0) __wrap_puts("  Instances:", stdout);
+ __pv_stlevel = 3;
+ for (i = 0; i < imdp->minum; i++)
+  {
+   ip = &(imdp->minsts[i]);
+   __wrap_putc(' ', stdout);
+   __wrap_puts(ip->isym->synam, stdout);
+   __wrap_putc('(', stdout);
+   __wrap_puts(ip->imsym->synam, stdout);
+   if (i < imdp->minum - 1) __wrap_puts("),", stdout);
+   else __wrap_putc(')', stdout);
+  }
+ if (__outlinpos != 0) { __wrap_putc('\n', stdout); __outlinpos = 0; }
+ __pv_stlevel = 0;
+
+ /* next tasks */
+ for (none = TRUE, tskp = imdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  { if (tskp->tsktyp == TASK) { none = FALSE; break; } } 
+ if (!none) 
+  {
+   __wrap_puts("  Tasks:", stdout);
+   __pv_stlevel = 3;
+   first_time = TRUE;
+   for (tskp = imdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if (tskp->tsktyp != TASK) continue;
+     if (first_time) { __wrap_putc(' ', stdout); first_time = FALSE; }
+     else __wrap_puts(", ", stdout);
+     __wrap_puts(tskp->tsksyp->synam, stdout);
+    }
+   if (__outlinpos != 0) { __wrap_putc('\n', stdout); __outlinpos = 0; }
+   __pv_stlevel = 0;
+  }
+ /* next functons */
+ for (none = TRUE, tskp = imdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  { if (tskp->tsktyp == FUNCTION) { none = FALSE; break; } } 
+ if (!none) 
+  {
+   __wrap_puts("  Functions:", stdout);
+   __pv_stlevel = 3;
+   first_time = TRUE;
+   for (tskp = imdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if (tskp->tsktyp != FUNCTION) continue;
+     if (first_time) { __wrap_putc(' ', stdout); first_time = FALSE; }
+     else __wrap_puts(", ", stdout);
+     __wrap_puts(tskp->tsksyp->synam, stdout);
+    }
+   if (__outlinpos != 0) { __wrap_putc('\n', stdout); __outlinpos = 0; }
+   __pv_stlevel = 0;
+  }
+ /* finally named blocks */
+ for (none = TRUE, tskp = imdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+
+   if (tskp->tsktyp == FORK || tskp->tsktyp == Begin)
+    { none = FALSE; break; }
+  } 
+ if (!none) 
+  {
+   __wrap_puts("  Named blocked:", stdout);
+   __pv_stlevel = 3;
+   first_time = TRUE;
+   for (tskp = imdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+
+     if (tskp->tsktyp == TASK || tskp->tsktyp == FUNCTION) continue;
+     if (first_time) { __wrap_putc(' ', stdout); first_time = FALSE; }
+     else __wrap_puts(", ", stdout);
+     __wrap_puts(tskp->tsksyp->synam, stdout);
+    }
+   if (__outlinpos != 0) { __wrap_putc('\n', stdout); __outlinpos = 0; }
+   __pv_stlevel = 0;
+  }
+}
+
+/*
+ * print the scopes in a task scope
+ * here can only be named blocks located from symbol table
+ * separate routine for recursive named block listing
+ */
+static void prt_1tsk_scopelist(struct task_t *tskp, int32 nd_msg)
+{
+ register struct symtab_t *sytp2;
+ struct symtab_t *sytp;
+ int32 first_time;
+ 
+ sytp = tskp->tsksymtab;
+ if (sytp->sytofs == NULL && nd_msg) return;
+ __wrap_puts("  Named blocks:", stdout);
+ __pv_stlevel = 3;
+ first_time = FALSE;
+ for (sytp2 = sytp->sytofs; sytp2 != NULL; sytp2 = sytp2->sytsib)
+  {
+   if (first_time) { first_time = FALSE; __wrap_putc(' ', stdout); }
+   else __wrap_puts(", ", stdout);
+   __wrap_puts(sytp2->sypofsyt->synam, stdout);
+  }
+ if (__outlinpos != 0) { __wrap_putc('\n', stdout); __outlinpos = 0; }
+ __pv_stlevel = 0;
+ if (__outlinpos != 0) __misc_terr(__FILE__, __LINE__);
+ /* first instances */
+ __pv_stlevel = 0;
+}
+
+/*
+ * for module print nested scopes with indent - to show the scope structure
+ */
+static void prt_1m_nestscopes(struct itree_t *itp)
+{
+ register int32 i;
+ register struct task_t *tskp;
+ struct mod_t *mdp;
+ struct itree_t *down_itp;
+ struct inst_t *ip;
+
+ __pv_stlevel++;
+ mdp = itp->itip->imsym->el.emdp;
+ for (i = 0; i < mdp->minum; i++)
+  {
+   down_itp = &(itp->in_its[i]);
+   ip = down_itp->itip;
+   __wrap_putc(' ', stdout);
+   __wrap_puts(ip->isym->synam, stdout);
+   __wrap_putc('(', stdout);
+   __wrap_puts(ip->imsym->synam, stdout);
+   __wrap_putc(')', stdout);
+   if (__outlinpos != 0) { __wrap_putc('\n', stdout); __outlinpos = 0; }
+   prt_1m_nestscopes(down_itp);
+  }
+ /* next tasks */
+ __pv_stlevel++;
+ for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+
+   sprintf(__xs, "%s: ", __to_tsktyp(__xs2, tskp->tsktyp));
+   __wrap_puts(__xs, stdout);
+   __wrap_puts(tskp->tsksyp->synam, stdout);
+   if (__outlinpos != 0) { __wrap_putc('\n', stdout); __outlinpos = 0; }
+   if (tskp->tsksymtab->sytofs != NULL)
+    {
+     __pv_stlevel++;
+     prt_1tsk_nestscopes(tskp->tsksymtab->sytofs);
+     __pv_stlevel--;
+    }
+  }
+ __pv_stlevel -= 2;
+}
+
+static void prt_1tsk_nestscopes(struct symtab_t *up_sytp)
+{
+ struct symtab_t *sytp; 
+ struct task_t *tskp;
+
+ for (sytp = up_sytp->sytofs; sytp != NULL; sytp = sytp->sytsib) 
+  {
+   tskp = sytp->sypofsyt->el.etskp;
+   sprintf(__xs, "%s: ", __to_tsktyp(__xs2, tskp->tsktyp));
+   __wrap_puts(__xs, stdout);
+   __wrap_puts(tskp->tsksyp->synam, stdout);
+   if (__outlinpos != 0) { __wrap_putc('\n', stdout); __outlinpos = 0; }
+   if (tskp->tsksymtab->sytofs != NULL)
+    {
+     __pv_stlevel++;
+     prt_1tsk_nestscopes(tskp->tsksymtab->sytofs);
+     __pv_stlevel--;
+    }
+  }
+}
+
+/*
+ * BUILT INTO VERILOG STOCHASTIC QUEUE SYSTEM TASKS
+ */
+
+/*
+ * execute the qfull function - must push 1 (room), 0 no room onto xstk
+ *
+ * LOOKATME - is this a 1 bit 0/1?
+ */
+static void exec_qfull(struct expr_t *argxp)
+{
+ int32 q_id, rv;
+ word32 val;
+ struct q_hdr_t *q_p;
+ struct expr_t *xp, *a1xp, *a2xp;
+ struct xstk_t *xsp;
+
+ rv = 0;
+ /* access the required 4 arguments */
+ if ((xp = argxp) == NULL) __arg_terr(__FILE__, __LINE__);
+ /* first element in function arg. list is return variable */
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = xp->lu.x;
+
+ if (!__get_eval_word(a1xp, &val))
+  {
+   __sgfwarn(596, "$q_full argument 1, q_id value %s x/z or out of range",
+    __msgexpr_tostr(__xs, a1xp));
+ret_x:
+   push_xstk_(xsp, 1);
+   xsp->ap[0] = 1;
+   xsp->bp[0] = 1;
+   rv = 2;
+   goto done;
+  }
+ q_id = (int32) val;
+
+ /* find q that matches passed q id */
+ if ((q_p = find_q_from_id(q_id)) == NULL) goto ret_x;
+
+ push_xstk_(xsp, 1);
+ xsp->bp[0] = 0;
+ if (q_p->q_size >= q_p->q_maxlen) xsp->ap[0] = 1;
+ else xsp->ap[0] = 0;
+
+done:
+ if (a2xp->optyp == OPEMPTY) return;
+
+ push_xstk_(xsp, WBITS);
+ xsp->ap[0] = (word32) rv; 
+ xsp->bp[0] = 0L;
+
+ /* SJM 09/29/03 - change to handle sign extension and separate types */
+ /* know xsp WBITS but can widen or narow */
+ if (xsp->xslen > a2xp->szu.xclen) __narrow_sizchg(xsp, a2xp->szu.xclen);
+ else if (xsp->xslen < a2xp->szu.xclen)
+  {
+   if (a2xp->has_sign) __sgn_xtnd_widen(xsp, a2xp->szu.xclen);
+   else __sizchg_widen(xsp, a2xp->szu.xclen);
+  }
+
+ __exec2_proc_assign(a2xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+}
+
+/*
+ * initialize a queue
+ *
+ * know exactly 4 args (possibly ,,) or will not get here
+ */
+static void do_q_init(struct expr_t *argxp)
+{
+ int32 q_id, q_type, q_maxlen, rv;
+ word32 val;
+ struct q_hdr_t *q_p;
+ struct expr_t *xp, *a1xp, *a2xp, *a3xp, *a4xp;
+ struct xstk_t *xsp;
+
+ rv = 0;
+ /* access the required 4 arguments */
+ if ((xp = argxp) == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a3xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a4xp = xp->lu.x;
+ if (xp->ru.x != NULL) __arg_terr(__FILE__, __LINE__);
+
+ /* access the rhs arguments */
+ if (!__get_eval_word(a1xp, &val))
+  {
+   __sgfwarn(596, "$q_initialize argument 1, q_id value %s x/z or out of range",
+    __msgexpr_tostr(__xs, a1xp));
+   rv = 2;
+   q_id = 0;
+  }
+ else q_id = (int32) val;
+ if (!__get_eval_word(a2xp, &val) || val < 1 || val > 2)
+  {
+   __sgfwarn(596,
+    "$q_initialize argument 2, q_type value %s x/z or out of range",
+    __msgexpr_tostr(__xs, a2xp));
+   if (rv == 0) rv = 4;
+   q_type = 0;
+  }
+ else q_type = (int32) val;
+ if (!__get_eval_word(a3xp, &val)) 
+  {
+bad_qlen:
+   __sgfwarn(596,
+    "$q_initialize argument 3, max_length value %s x/z or negative",
+    __msgexpr_tostr(__xs, a3xp));
+   if (rv == 0) rv = 5;
+   q_maxlen = 0;
+  }
+ else
+  {
+   q_maxlen = (int32) val;
+   if (q_maxlen <= 0) goto bad_qlen;
+  }
+ if (rv != 0) goto done;
+
+ /* make sure id is unqiue */
+ if (find_q_from_id(q_id) != NULL) { rv = 6; goto done; }
+
+ /* allocate the new q header and link into q list */
+ q_p = (struct q_hdr_t *) __my_malloc(sizeof(struct q_hdr_t));
+ init_q(q_p);
+ if (__qlist_hdr == NULL) __qlist_hdr = q_p; 
+ else { q_p->qhdrnxt = __qlist_hdr; __qlist_hdr = q_p; }
+ if (q_type == 1) q_p->q_fifo = TRUE; else q_p->q_fifo = FALSE;
+ q_p->qarr = (struct q_val_t *) __my_malloc(q_maxlen*sizeof(struct q_val_t)); 
+ memset(q_p->qarr, 0, q_maxlen*sizeof(struct q_val_t));
+ q_p->q_id = q_id;
+ q_p->q_maxlen = q_maxlen;
+
+done:
+ if (a4xp->optyp == OPEMPTY) return;
+
+ push_xstk_(xsp, WBITS);
+ xsp->ap[0] = (word32) rv; 
+ xsp->bp[0] = 0L;
+
+ /* SJM 09/29/03 - change to handle sign extension and separate types */
+ /* know xsp WBITS but can widen or narow */
+ if (xsp->xslen > a4xp->szu.xclen) __narrow_sizchg(xsp, a4xp->szu.xclen);
+ else if (xsp->xslen < a4xp->szu.xclen)
+  {
+   if (a2xp->has_sign) __sgn_xtnd_widen(xsp, a4xp->szu.xclen);
+   else __sizchg_widen(xsp, a4xp->szu.xclen);
+  }
+
+ __exec2_proc_assign(a4xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+}
+
+/*
+ * initialize a q
+ */
+static void init_q(struct q_hdr_t *q_p)
+{
+ q_p->q_fifo = FALSE;
+ q_p->q_id = 0;
+ q_p->q_hdr = -1;
+ q_p->q_tail = -1;
+ q_p->q_maxlen = 0;
+ q_p->q_size = 0;
+ q_p->q_minwait = 0xffffffffffffffffULL;
+ q_p->qhdrnxt = NULL;
+}
+
+/*
+ * find q header record from identifying q id number
+ *
+ * LOOKATME - could use binary search but think will not be many queues
+ */
+static struct q_hdr_t *find_q_from_id(int32 id)
+{
+ register struct q_hdr_t *qp;
+
+ for (qp = __qlist_hdr; qp != NULL; qp = qp->qhdrnxt)
+  {
+   if (qp->q_id == id) return(qp);
+  }
+ return(NULL);
+}
+
+/*
+ * add an element to a queue
+ *
+ * know exactly 4 args (possibly ,,) or will not get here
+ */
+static void do_q_add(struct expr_t *argxp)
+{
+ int32 q_id, qjob_id, qinform_id, rv;
+ word32 val;
+ struct q_hdr_t *q_p;
+ struct q_val_t *qvp;
+ struct expr_t *xp, *a1xp, *a2xp, *a3xp, *a4xp;
+ struct xstk_t *xsp;
+
+ rv = 0;
+ /* access the required 4 arguments */
+ if ((xp = argxp) == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a3xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a4xp = xp->lu.x;
+ if (xp->ru.x != NULL) __arg_terr(__FILE__, __LINE__);
+
+ /* access the rhs arguments */
+ if (!__get_eval_word(a1xp, &val))
+  {
+   __sgfwarn(596, "$q_add argument 1, q_id value %s x/z or out of range",
+    __msgexpr_tostr(__xs, a1xp));
+   rv = 2;
+   q_id = 0;
+  }
+ else q_id = (int32) val;
+ if (a2xp->optyp == OPEMPTY) qjob_id = 0;
+ else
+  {
+   if (!__get_eval_word(a2xp, &val))
+    {
+     __sgfwarn(596,
+      "$q_add argument 2, job_id value %s x/z or too wide (0 used)",
+      __msgexpr_tostr(__xs, a2xp));
+     val = 0;
+    }
+   qjob_id = (int32) val;
+  }
+ if (a3xp->optyp == OPEMPTY) qinform_id = 0;
+ else
+  {
+   if (!__get_eval_word(a3xp, &val)) 
+    {
+     __sgfwarn(596,
+      "$q_add argument 3, inform_id value %s x/z or too wide (0 used)",
+      __msgexpr_tostr(__xs, a3xp));
+     val = 0;
+    }
+   qinform_id = (int32) val;
+  }
+ if (rv != 0) goto done;
+
+ /* find q that matches passed q id */
+ if ((q_p = find_q_from_id(q_id)) == NULL) { rv = 2; goto done; }
+
+ /* add the element */
+ if (q_p->q_fifo)
+  {
+   if (q_p->q_hdr == -1) q_p->q_hdr = q_p->q_tail = 0;
+   else
+    {
+     if (q_p->q_size >= q_p->q_maxlen) { rv = 1; goto done; }
+     (q_p->q_hdr)++;
+     /* wrap queue around - since size not too big know empty */ 
+     if (q_p->q_hdr >= q_p->q_maxlen) q_p->q_hdr = 0;
+    }
+  }
+ else
+  {
+   /* easy stack lifo case - q tail not used */
+   if (q_p->q_hdr == -1) q_p->q_hdr = 0;
+   else
+    {
+     if (q_p->q_size >= q_p->q_maxlen) { rv = 1; goto done; }
+     (q_p->q_hdr)++;
+    }
+  }
+ qvp = &(q_p->qarr[q_p->q_hdr]);
+ (q_p->q_size)++;
+ if (q_p->q_size > q_p->q_maxsize) q_p->q_maxsize = q_p->q_size;
+ qvp->job_id = qjob_id;
+ qvp->inform_id = qinform_id;
+ qvp->enter_tim = __simtime;
+
+done:
+ if (a4xp->optyp == OPEMPTY) return;
+
+ push_xstk_(xsp, WBITS);
+ xsp->ap[0] = (word32) rv; 
+ xsp->bp[0] = 0L;
+
+ /* SJM 09/29/03 - change to handle sign extension and separate types */
+ /* know xsp WBITS but can widen or narow */
+ if (xsp->xslen > a4xp->szu.xclen) __narrow_sizchg(xsp, a4xp->szu.xclen);
+ else if (xsp->xslen < a4xp->szu.xclen)
+  {
+   if (a2xp->has_sign) __sgn_xtnd_widen(xsp, a4xp->szu.xclen);
+   else __sizchg_widen(xsp, a4xp->szu.xclen);
+  }
+
+ __exec2_proc_assign(a4xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+}
+
+/*
+ * delete an element from a queue
+ *
+ * know exactly 4 args (possibly ,,) or will not get here
+ */
+static void do_q_remove(struct expr_t *argxp)
+{
+ int32 q_id, qjob_id, qinform_id, rv;
+ word32 val;
+ word64 timval;
+ struct q_hdr_t *q_p;
+ struct q_val_t *qvp;
+ struct expr_t *xp, *a1xp, *a2xp, *a3xp, *a4xp;
+ struct xstk_t *xsp;
+
+ rv = 0;
+ /* access the required 4 arguments - last 3 outputs can be empty */
+ if ((xp = argxp) == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a3xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a4xp = xp->lu.x;
+ if (xp->ru.x != NULL) __arg_terr(__FILE__, __LINE__);
+
+ /* access the rhs arguments */
+ if (!__get_eval_word(a1xp, &val))
+  {
+   __sgfwarn(596, "$q_remove argument 1, q_id value %s x/z or out of range",
+    __msgexpr_tostr(__xs, a1xp));
+   rv = 2;
+   goto done;
+  }
+ else q_id = (int32) val;
+
+ /* find q that matches passed q id */
+ if ((q_p = find_q_from_id(q_id)) == NULL) { rv = 2; goto done; }
+
+ /* here no assignment to output values */
+ if (q_p->q_size == 0) { rv = 3; goto done; }
+
+ qvp = &(q_p->qarr[q_p->q_tail]); 
+ /* delete the element - take off from tail */
+ if (q_p->q_fifo)
+  {
+   if (q_p->q_size == 1) q_p->q_hdr = q_p->q_tail = -1;
+   else
+    {
+     (q_p->q_tail)++;
+     /* wrap queue around - since size not too big know empty */ 
+     if (q_p->q_tail >= q_p->q_maxlen) q_p->q_tail = 0;
+    }
+  }
+ /* easy stack lifo case - q tail not used */
+ else (q_p->q_hdr)--;
+
+ /* save minimum time in q (wait time) */
+ timval = __simtime - qvp->enter_tim;
+ if (timval < q_p->q_minwait) q_p->q_minwait = timval;
+
+ (q_p->q_size)--;
+ qjob_id = qvp->job_id;
+ qinform_id = qvp->inform_id;
+
+ if (a2xp->optyp != OPEMPTY)
+  {
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = (word32) qjob_id; 
+   xsp->bp[0] = 0L;
+
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   /* know xsp WBITS but can widen or narow */
+   if (xsp->xslen > a2xp->szu.xclen) __narrow_sizchg(xsp, a2xp->szu.xclen);
+   else if (xsp->xslen < a2xp->szu.xclen)
+    {
+     if (a2xp->has_sign) __sgn_xtnd_widen(xsp, a2xp->szu.xclen);
+     else __sizchg_widen(xsp, a2xp->szu.xclen);
+    }
+
+   __exec2_proc_assign(a2xp, xsp->ap, xsp->bp);
+   __pop_xstk();
+  }
+
+ if (a3xp->optyp != OPEMPTY)
+  {
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = (word32) qinform_id; 
+   xsp->bp[0] = 0L;
+
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   /* know xsp WBITS but can widen or narow */
+   if (xsp->xslen > a3xp->szu.xclen) __narrow_sizchg(xsp, a3xp->szu.xclen);
+   else if (xsp->xslen < a3xp->szu.xclen)
+    {
+     if (a3xp->has_sign) __sgn_xtnd_widen(xsp, a3xp->szu.xclen);
+     else __sizchg_widen(xsp, a3xp->szu.xclen);
+    }
+
+   __exec2_proc_assign(a3xp, xsp->ap, xsp->bp);
+   __pop_xstk();
+  }
+
+done:
+ if (a4xp->optyp == OPEMPTY) return;
+
+ push_xstk_(xsp, WBITS);
+ xsp->ap[0] = (word32) rv; 
+ xsp->bp[0] = 0L;
+
+ /* SJM 09/29/03 - change to handle sign extension and separate types */
+ /* know xsp WBITS but can widen or narow */
+ if (xsp->xslen > a4xp->szu.xclen) __narrow_sizchg(xsp, a4xp->szu.xclen);
+ else if (xsp->xslen < a4xp->szu.xclen)
+  {
+   if (a4xp->has_sign) __sgn_xtnd_widen(xsp, a4xp->szu.xclen);
+   else __sizchg_widen(xsp, a4xp->szu.xclen);
+  }
+
+ __exec2_proc_assign(a4xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+}
+
+/*
+ * examine a queue
+ *
+ * know exactly 4 args (possibly ,,) or will not get here
+ */
+static void do_q_examine(struct expr_t *argxp)
+{
+ int32 q_id, q_stat_code, rv;
+ word32 val;
+ word64 timval;
+ struct q_hdr_t *q_p;
+ struct expr_t *xp, *a1xp, *a2xp, *a3xp, *a4xp;
+ struct xstk_t *xsp;
+
+ rv = 0;
+ /* access the required 4 arguments - last 3 outputs can be empty */
+ if ((xp = argxp) == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a3xp = xp->lu.x;
+ if ((xp = xp->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a4xp = xp->lu.x;
+ if (xp->ru.x != NULL) __arg_terr(__FILE__, __LINE__);
+
+ /* access the rhs arguments */
+ if (!__get_eval_word(a1xp, &val))
+  {
+   __sgfwarn(596, "$q_examine argument 1, q_id value %s x/z or out of range",
+    __msgexpr_tostr(__xs, a1xp));
+   rv = 2;
+   goto done;
+  }
+ q_id = (int32) val;
+
+ if (!__get_eval_word(a2xp, &val) || val < 1 || val > 6)
+  {
+   __sgfwarn(596,
+    "$q_examine argument 2, q_stat_code value %s x/z or out of range",
+    __msgexpr_tostr(__xs, a2xp));
+   /* LOOKATME - really no good value for this error */
+   q_stat_code = 0;
+   rv = 4;
+  }
+ else q_stat_code = (int32) val;
+
+ if (rv != 0) goto done;
+
+ /* find q that matches passed q id */
+ if ((q_p = find_q_from_id(q_id)) == NULL) { rv = 2; goto done; }
+
+ switch (q_stat_code) {
+  case 1:
+   /* current size of q */
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = (word32) q_p->q_size;
+   xsp->bp[0] = 0L;
+   break;
+  case 2:
+   /* mean inter arrival time for elements currently in the q */
+   cmp_mean_interarriv_tim(&timval, q_p);
+push_cmp_tim:
+   push_xstk_(xsp, 64);
+   xsp->ap[0] = (word32) (timval & WORDMASK_ULL);
+   xsp->ap[1] = (word32) ((timval >> 32) & WORDMASK_ULL); 
+   xsp->bp[0] = xsp->bp[1] = 0L;
+   break;
+  case 3:
+   /* maximum size queue ever attained */
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = (word32) q_p->q_maxsize;
+   xsp->bp[0] = 0L;
+   break;
+  case 4:
+   push_xstk_(xsp, 64);
+   xsp->ap[0] = (word32) (q_p->q_minwait & WORDMASK_ULL);
+   xsp->ap[1] = (word32) ((q_p->q_minwait >> 32) & WORDMASK_ULL);
+   xsp->bp[0] = xsp->bp[1] = 0L;
+   break;
+  case 5:
+   cmp_max_wait(&timval, q_p);
+   goto push_cmp_tim;
+  case 6:
+   cmp_mean_wait_tim(&timval, q_p);
+   goto push_cmp_tim;
+  default: __case_terr(__FILE__, __LINE__); return;
+ }
+
+ /* only assign result, lhs arg. passed */
+ if (a3xp->optyp != OPEMPTY)
+  {
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   /* know xsp WBITS but can widen or narow */
+   if (xsp->xslen > a3xp->szu.xclen) __narrow_sizchg(xsp, a3xp->szu.xclen);
+   else if (xsp->xslen < a3xp->szu.xclen)
+    {
+     if (a3xp->has_sign) __sgn_xtnd_widen(xsp, a3xp->szu.xclen);
+     else __sizchg_widen(xsp, a3xp->szu.xclen);
+    }
+
+   __exec2_proc_assign(a3xp, xsp->ap, xsp->bp);
+  }
+ __pop_xstk();
+
+done:
+ if (a4xp->optyp == OPEMPTY) return;
+
+ push_xstk_(xsp, WBITS);
+ xsp->ap[0] = (word32) rv; 
+ xsp->bp[0] = 0L;
+
+ /* SJM 09/29/03 - change to handle sign extension and separate types */
+ /* know xsp WBITS but can widen or narow */
+ if (xsp->xslen > a4xp->szu.xclen) __narrow_sizchg(xsp, a4xp->szu.xclen);
+ else if (xsp->xslen < a4xp->szu.xclen)
+  {
+   if (a4xp->has_sign) __sgn_xtnd_widen(xsp, a4xp->szu.xclen);
+   else __sizchg_widen(xsp, a4xp->szu.xclen);
+  }
+
+ __exec2_proc_assign(a4xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+}
+
+/*
+ * compute average inter (between 2) arrival time for qs currently in queue
+ */
+static void cmp_mean_interarriv_tim(word64 *timvalp, struct q_hdr_t *q_p)
+{
+ register int32 qi, i;
+ word64 avgtim, arrdif, quot, rem;
+
+ /* for one or less size q mean always 0 */
+ if (q_p->q_size <= 1) { *timvalp = 0ULL; return; }
+ avgtim = 0ULL;
+ if (q_p->q_fifo)
+  {
+   for (qi = q_p->q_hdr, i = 0; i < q_p->q_size; i++)
+    {
+     if ((++qi) >= q_p->q_size) qi = 0;
+     if (i == 0) continue;
+
+     arrdif = q_p->qarr[qi].enter_tim - q_p->qarr[qi - 1].enter_tim;
+     avgtim += arrdif;
+    }
+  }
+ else
+  {
+   /* easy lifo stack case */
+   for (qi = 0; qi < q_p->q_size; qi++)
+    {
+     if (qi == 0) continue;
+     arrdif = q_p->qarr[qi].enter_tim - q_p->qarr[qi - 1].enter_tim;
+     avgtim += arrdif;
+    }
+  }
+ /* divide - round - know q at least 2 elements to get here */
+ /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
+ quot = avgtim/((word64) (((word32) q_p->q_size) - 1)); 
+ rem = avgtim % ((word64) (((word32) q_p->q_size) - 1));
+ avgtim = quot;
+ if (rem >= ((word64) (((word32) q_p->q_size)/2))) avgtim++;
+ *timvalp = avgtim;
+}
+
+/*
+ * compute longest wait (in queue) time for elements in queue
+ */
+static void cmp_max_wait(word64 *timvalp, struct q_hdr_t *q_p)
+{
+ register int32 qi, i;
+ word64 inqtim;
+
+ if (q_p->q_size <= 1) { *timvalp = 0ULL; return; }
+ if (q_p->q_fifo)
+  {
+   for (qi = q_p->q_hdr, i = 0; i < q_p->q_size; i++)
+    {
+     if ((++qi) >= q_p->q_size) qi = 0;
+     if (i == 0)
+      {
+       *timvalp = q_p->qarr[qi].enter_tim;
+       continue;
+      }
+     inqtim = __simtime - q_p->qarr[qi].enter_tim;
+     if (inqtim < *timvalp) *timvalp = inqtim;
+    }
+  }
+ else
+  {
+   /* easy lifo stack case */
+   for (qi = 0; qi < q_p->q_size; qi++)
+    {
+     if (qi == 0)
+      {
+       *timvalp = q_p->qarr[qi].enter_tim;
+       continue;
+      }
+     inqtim = __simtime - q_p->qarr[qi].enter_tim;
+     if (inqtim < *timvalp) *timvalp = inqtim;
+    }
+  }
+}
+
+/*
+ * compute average (mean) time each element has spent in queue
+ */
+static void cmp_mean_wait_tim(word64 *timvalp, struct q_hdr_t *q_p)
+{
+ register int32 qi, i;
+ word64 avgtim, waitdif, quot, rem;
+
+ if (q_p->q_size <= 0) { *timvalp = 0ULL; return; }
+ avgtim = 0ULL;
+ if (q_p->q_fifo)
+  {
+   for (qi = q_p->q_hdr, i = 0; i < q_p->q_size; i++)
+    {
+     if ((++qi) >= q_p->q_size) qi = 0;
+     waitdif = __simtime - q_p->qarr[qi].enter_tim; 
+     avgtim += waitdif;
+    }
+  }
+ else
+  {
+   /* easy lifo stack case */
+   for (qi = 0; qi < q_p->q_size; qi++)
+    {
+     waitdif = __simtime - q_p->qarr[qi].enter_tim;
+     avgtim += waitdif;
+    }
+  }
+ /* divide - round - know q at least 1 element to get here */
+ quot = avgtim/((word64) ((word32) q_p->q_size)); 
+ rem = avgtim % ((word64) ((word32) q_p->q_size));
+ avgtim = quot;
+ if (rem >= ((word64) (((word32) q_p->q_size)/2))) avgtim++;
+ *timvalp = avgtim;
+}
+
+/*
+ * TIMESCALE TASK ROUTINES 
+ */
+
+/*
+ * execute the print time scale
+ * know the 1 arg. is xmr or no arg means current scope
+ *
+ * know arg. is xmr even if only has one component
+ * axp is nil (for none) or function call comma operator (head of list)
+ */
+static void exec_prttimscale(struct expr_t *axp)
+{
+ struct mod_t *mdp;
+ struct expr_t *ndp; 
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ __cur_sofs = 0;
+ __adds("Time scale of (");
+ if (axp == NULL)
+  {
+   mdp = __scope_ptr->itip->imsym->el.emdp;
+   __disp_itree_path(__inst_ptr, (struct task_t *) NULL);
+  }
+ else 
+  {
+   ndp = axp->lu.x;
+   if (ndp->optyp == GLBREF)
+    { mdp = ndp->ru.grp->targmdp; __adds(ndp->ru.grp->gnam); }
+   else if (ndp->lu.sy->sytyp == SYM_M)
+    { mdp = ndp->lu.sy->el.emdp; __adds(mdp->msym->synam); }
+   else { __case_terr(__FILE__, __LINE__);  return; }
+  }
+ sprintf(s1, ") is %s / %s\n",
+  __to_timunitnam(s2, mdp->mtime_units),
+  __to_timunitnam(s3, mdp->mtime_units + mdp->mtime_prec));
+ __adds(s1);
+ /* notice cannot truncate here */
+ my_puts_(__exprline, stdout);
+ __cur_sofs = 0;
+}
+
+/*
+ * execute the time format system task - just sets some internal values 
+ * know exactly four arguments or will not get here
+ *
+ * this allows ,, and missing arguments that mean use 0 - error
+ */
+static void exec_timefmt(struct expr_t *argxp) 
+{
+ int32 argi, i1, slen;
+ word32 val, val1, val2, val3;
+ struct expr_t *xp, *ndp;
+ char *chp;
+
+ /* set values for missing arguments */
+ val1 = val2 = val3 = 0; 
+
+ argi = 1;
+ /* empty arg. list already checked for */
+ if ((xp = argxp) == NULL) __arg_terr(__FILE__, __LINE__);
+ ndp = xp->lu.x;
+ if (ndp->optyp != OPEMPTY)
+  {
+   /* eval. here is just word32 stored in 2 complement */
+   if (!__get_eval_word(ndp, &val)) goto bad_arg; 
+   i1 = (int32) val;
+   if (i1 > 0 || i1 < -15) goto bad_arg;
+   i1 = -i1;
+   val1 = (word32) i1;
+   if (val1 > __des_timeprec)
+    { 
+     __sgferr(1240,
+      "$timeformat units %s (%d) impossible - must be larger than %s (%d) tick",
+       __to_timunitnam(__xs, (word32) val1), -((int32) val1),
+       __to_timunitnam(__xs2, (word32) __des_timeprec),
+       -((int32) __des_timeprec));
+     /* change nothing if this does not change */
+     return;
+    }
+  }
+ if ((xp = xp->ru.x) == NULL)
+  { chp = __my_malloc(1); *chp = '\0'; slen = 1; goto do_chg; }
+
+ ndp = xp->lu.x; 
+ argi++;
+ if (ndp->optyp != OPEMPTY)
+  {
+   if (!__get_eval_word(ndp, &val)) goto bad_arg;
+   i1 = (int32) val;
+   if (i1 < 0 || i1 >= RECLEN) goto bad_arg;
+   val2 = val;
+  }
+
+ if ((xp = xp->ru.x) == NULL)
+  { chp = __my_malloc(1); *chp = '\0'; slen = 1; goto do_chg; }
+ ndp = xp->lu.x;
+ argi++;
+ if (ndp->optyp != OPEMPTY)
+  {
+   chp = __get_eval_cstr(ndp, &slen);
+   /* must fit in RECLEN style string - but maybe should be narrower */ 
+   if (slen >= RECLEN) { __my_free(chp, slen + 1); goto bad_arg; }
+  }
+ else { chp = __my_malloc(1); *chp = '\0'; slen = 1; }
+ 
+ if ((xp = xp->ru.x) == NULL) goto do_chg;
+ ndp = xp->lu.x;
+ argi++;
+ /* must allow ,) form */
+ if (ndp->optyp != OPEMPTY)
+  {
+   if (!__get_eval_word(ndp, &val) || val > 40)
+    {
+     __sgferr(1047,
+      "$timeformat minimum field width must be between 0 and 40 - not changed");
+     __my_free(chp, slen + 1);
+     return;
+    }
+   val3 = val;
+  }
+ 
+do_chg:
+ if (slen > (int32) (val3 + 1))  
+  {
+   __sgferr(1047,
+    "$timeformat suffix length %d wider than minimum field width (%d) - not changed",
+    slen, val3);
+   __my_free(chp, slen + 1);
+   return;
+  }
+ __tfmt_units = val1;
+ __tfmt_precunits = val2;
+ __my_free((char *) __tfmt_suf, strlen(__tfmt_suf) + 1);
+ __tfmt_suf = chp;
+ __tfmt_minfwid = val3;
+ return;
+
+bad_arg:
+ __sgferr(713, "$timeformat argument %d value %s x/z or out of range",
+  argi, __msgexpr_tostr(__xs, ndp));
+}
+
+/*
+ * get an optional system task control argument
+ * gets converted to machine int
+ * this must be called with xp head of fcall list (comma operator)
+ */
+static int32 get_opt_starg(struct expr_t *xp, int32 dflt_val)
+{
+ int32 val;
+ word32 rval;
+ struct expr_t *axp;
+
+ if (xp == NULL) return(dflt_val);
+ axp = xp->lu.x;
+ if (axp->optyp == OPEMPTY) return(dflt_val);
+
+ if (!__get_eval_word(axp, &rval))
+  {
+   __sgfwarn(519,
+    "optional system task numeric argument has x/z bits - default used");
+   return(dflt_val);
+  }
+ val = (int32) rval;
+ return(val); 
+}
+
+/*
+ * evaluate a value to an int32 (return F if not a non x/z WBIT int32)
+ * this must be called with actual argument expr. not fcall comma expr.
+ */
+extern int32 __get_eval_word(struct expr_t *xp, word32 *wval)
+{
+ int32 rval;
+ struct xstk_t *xsp;
+
+ *wval = 0;
+ xsp = __eval_xpr(xp); 
+ /* semantics says there is an implied conversion from real to int32 */
+ /* but not across system task/func. arguments */
+ /* however this routine is only called when int32 needed */
+ if (xp->optyp == REALNUM || xp->optyp == ISREALNUM)
+  {
+   double d1;
+
+   /* truncating since for getting 32 bit value */
+   memcpy(&d1, xsp->ap, sizeof(double));
+   *wval = (word32) d1; 
+   rval = TRUE; 
+   goto done;
+  }
+ if (xsp->xslen > WBITS)
+  {
+   if (!vval_is0_(&(xsp->ap[1]), xsp->xslen - WBITS)
+    || !vval_is0_(&(xsp->bp[1]), xsp->xslen - WBITS))
+    { rval = FALSE; goto done; }
+  }
+ if (xsp->bp[0] != 0L) { rval = FALSE; goto done; }
+ *wval = xsp->ap[0];
+ rval = TRUE;
+
+done:
+ __pop_xstk();
+ return(rval);
+}
+
+/*
+ * exec the $log file system task
+ * this is called with fcall comma operator header
+ */
+static void exec_log_fnamchg(struct expr_t *axp)
+{ 
+ int32 slen;
+ FILE *tmp_s;
+ char *chp;
+
+ if (axp == NULL) { __log_s = __save_log_s; return; }
+ chp = __get_eval_cstr(axp->lu.x, &slen);
+ if ((tmp_s = __tilde_fopen(chp, "w")) == NULL)
+  {
+   __sgferr(1243, 
+    "cannot open new $log output transcript file %s - not changed",
+    __exprline); 
+   __my_free(chp, slen + 1);
+   return;
+  }
+ if (__log_s != NULL && __log_s != stdout && __log_s != stderr)
+  {
+   __my_fclose(__log_s);
+   __my_free(__log_fnam, strlen(__log_fnam) + 1);
+   __log_fnam = NULL;
+  }
+ __log_fnam = chp; 
+ __log_s = tmp_s;
+ __save_log_s = NULL;
+ /* SJM 03/26/00 - log file now not an mcd - lumped with 0 (stdout) */
+ /* ---
+ __mulchan_tab[2].mc_fnam = __pv_stralloc(__log_fnam);
+ __mulchan_tab[2].mc_fnam = __pv_stralloc(__log_fnam);
+ --- */ 
+ if (__verbose)
+  __cv_msg("  Now writing output log to file \"%s\".\n", __log_fnam);
+}
+
+/*
+ * exec the $tracefile system task
+ * always open - if no writing into then just empty file
+ *
+ * will not get here if name argument missing 
+ * this is called with actual file name argument not fcall list header op
+ * 
+ */
+static void exec_trace_fnamchg(struct expr_t *argvx)
+{ 
+ int32 slen;
+ FILE *tmp_s;
+ char *chp;
+
+ chp = __get_eval_cstr(argvx, &slen);
+ if (strcmp(chp, "STDOUT") == 0) strcpy(chp, "stdout");
+ if (strcmp(__tr_fnam, chp) == 0) 
+  {
+   __sgfwarn(625, "$tracefile file name %s same as previous - task ignored",
+    __tr_fnam);
+   goto done;
+  }
+ /* if changing to stdout set it, but cannot open */
+ if (strcmp(chp, "stdout") == 0)
+  {
+   if (__tr_s != NULL && __tr_s != stdout && __tr_s != stderr)
+    __my_fclose(__tr_s);
+
+   if (__tr_fnam != NULL) __my_free(__tr_fnam, strlen(__tr_fnam) + 1);
+   __tr_fnam = chp;
+   __tr_s = stdout;
+   goto new_tr;
+  }
+ /* know new file not stdout - always open system task new trace file */
+ if ((tmp_s = __tilde_fopen(chp, "w")) == NULL)
+  {
+   __sgferr(1247, "cannot open new trace output file %s - not changed",
+    chp); 
+   goto done;
+  }
+ if (__tr_s != NULL && __tr_s != stdout && __tr_s != stderr)
+  __my_fclose(__tr_s);
+
+ if (__tr_fnam != NULL) __my_free(__tr_fnam, strlen(__tr_fnam) + 1);
+ __tr_fnam = chp;
+ __tr_s = tmp_s;
+
+new_tr:
+ if (__verbose) 
+  {
+   __cv_msg(
+   "  Now writing statement and/or event trace output to file \"%s\".\n",
+   __tr_fnam);
+  }
+ return;
+
+done:
+ __my_free(chp, slen + 1);
+}
+
+/*
+ * execute a $scope change
+ * this can be used for scope changes into local task from instance
+ */
+static void exec_expr_schg(struct expr_t *xp)
+{
+ struct itree_t *itp;
+ struct task_t *tskp; 
+ struct sy_t *syp;
+
+ /* will not get here if no argument */
+
+ /* need to handle scope change into local task - inst. does not change */
+ /* scope changes of local [lb].[lb].[lb] simple task target by here */
+ if (xp->optyp == ID)
+  { 
+   syp = xp->lu.sy;
+   /* DBG remove */
+   if (syp->sytyp != SYM_TSK && syp->sytyp != SYM_F && syp->sytyp != SYM_LB)
+    __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   __scope_tskp = xp->lu.sy->el.etskp;
+   if (__iact_state) __set_scopchg_listline();
+   return;
+  } 
+
+ /* DBG remove --- */
+ if (xp->optyp != GLBREF) __arg_terr(__FILE__, __LINE__);
+ /* --- */ 
+
+ /* this converts from gref to itree location */
+ __xmrpush_refgrp_to_targ(xp->ru.grp);
+ itp = __inst_ptr;
+ __pop_itstk();
+ if (xp->lu.sy->sytyp != SYM_I && xp->lu.sy->sytyp != SYM_M)
+  tskp = xp->lu.sy->el.etskp;
+ else tskp = NULL;
+ __scope_ptr = itp; 
+ __scope_tskp = tskp;
+ /* if called from interactive must update list line to scope */
+ if (__iact_state)
+  {
+   /* in iact, need top of inst. stack to be same as scope ptr */
+   __pop_itstk();
+   __push_itstk(__scope_ptr);
+   __set_scopchg_listline();
+
+   if (__tfrec_hdr != NULL) __call_misctfs_scope();
+   if (__have_vpi_actions) __vpi_iactscopechg_trycall();
+  }
+}
+
+/*
+ * emit various systask time end message - task passed >= 2 arg 
+ */
+extern void __emit_stsk_endmsg(void)
+{
+ /* notice must know current end time */
+ __my_ftime(&__end_time, &__end_mstime);
+ __prt_end_msg();
+}
+
+/*
+ * ROUTINES TO MAKE VARIABLE DECLARATION INITIALIZE ASSIGNMENTS
+ */
+
+/*
+ * after init sim and any -i interactive running, set all var decl initials
+ *
+ * semantics is same as: reg [r1:r2] x; initial x = [expr]; 
+ */
+extern void __exec_var_decl_init_assigns(void)
+{
+ register struct varinitlst_t *initp;
+ register struct net_t *np;
+ register struct expr_t *xp; 
+ struct xstk_t *xsp;
+ struct mod_t *mdp;
+ int32 ii;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mvarinits == NULL) continue; 
+
+   for (ii = 0; ii < mdp->flatinum; ii++)
+    {
+     __push_itstk(mdp->moditps[ii]);
+     
+     for (initp = mdp->mvarinits; initp != NULL; initp = initp->varinitnxt)
+      { 
+       xp = initp->init_xp;
+       np = initp->init_syp->el.enp;
+       /* notice this code is almost same as eval assign rhsexpr except */ 
+       /* do not have lhs expr but instead have net */
+       xsp = __eval_xpr(initp->init_xp);
+       if (np->ntyp == N_REAL)
+        { 
+         if (!xp->is_real) __cnv_stk_fromreg_toreal(xsp, (xp->has_sign == 1));
+        }
+       else
+        { 
+         if (xp->is_real) __cnv_stk_fromreal_toreg32(xsp);
+
+         if (xsp->xslen > np->nwid) __narrow_sizchg(xsp, np->nwid);
+         else if (xsp->xslen < np->nwid)
+          {
+           if (xp->has_sign) __sgn_xtnd_widen(xsp, np->nwid);
+           else __sizchg_widen(xsp, np->nwid);
+          }
+        }
+
+       /* notice may need change store here - works because netchg list hd */
+       /* initialized in init stim so at end of first time 0 queue segment */
+       /* the changes will be processed */
+       if (np->nchg_nd_chgstore) __chg_st_val(np, xsp->ap, xsp->bp);
+       else __st_val(np, xsp->ap, xsp->bp);
+       __pop_xstk();
+      }
+     __pop_itstk();
+    }
+  }
+}
+
+/* 
+ * ROUTINES TO IMPLEMENT FILE IO SYS TASKS AND FUNCS (INTERMIXED)
+ */
+
+/*
+ * open a OS file system and return the 32 bit file descriptor
+ * fd is OS file descriptor although using buffered read/write I/O
+ */
+static word32 fio_do_fopen(struct expr_t *axp, struct expr_t *mode_xp)
+{
+ int32 slen, slen2;
+ word32 rv;
+ char *chp, *chp2;
+
+ /* these always return something as a string - can never fail */ 
+ chp = __get_eval_cstr(axp, &slen);
+ chp2 = __get_eval_cstr(mode_xp, &slen2);
+ rv = fio_fopen(chp, chp2);
+
+ /* get eval cstr puts string into malloc memory, must free */
+ __my_free(chp, slen + 1);
+ __my_free(chp2, slen2 + 1);
+ return(rv);
+}
+
+/*
+ * file descriptor fopen and update fio used file table 
+ * returns 0 on error else file Verilog fd number (with high bit on)
+ *
+ * notice the verilog file I/O number may not match the OS one
+ */
+static word32 fio_fopen(char *chp, char *fmode)
+{
+ int32 fd;
+ FILE *fd_s;
+ struct fiofd_t *fdtp;
+ char os_mode[RECLEN];
+
+ /* check the fmode string */
+ if (!chk_cnvt_fd_modes(os_mode, fmode)) { errno = EINVAL; return(0); }
+
+ /* notice if too many open files (use PLI plus Verilog fd open) this fails */
+ if ((fd_s = __tilde_fopen(chp, os_mode)) == NULL)
+  {
+   /* notice errno set by OS file open call */
+   return(0);
+  }
+ fd = fileno(fd_s);
+ /* SJM 09/08/03 - ??? can file name be "stdin" here - think not */
+ if (fd == -1 || fd < FIO_STREAM_ST) { errno = EBADF; return(0); }
+
+ /* SJM 08/09/03 - change so always uses OS file number as index */
+ /* internal error if same returned twice for open file */
+ if (__fio_fdtab[fd] != NULL)
+  {
+   /* not quite right since error really fd number in use */
+   errno = EEXIST;
+   __misc_terr(__FILE__, __LINE__);
+   return(0);
+  }
+
+ /* notice index with high bit on is the Verilog side file descriptor no. */
+ fdtp = (struct fiofd_t *) __my_malloc(sizeof(struct fiofd_t));
+ fdtp->fd_error = FALSE;
+ fdtp->fd_name = __pv_stralloc(chp);
+ /* notice can always get fd from stream using fileno C lib func */
+ fdtp->fd_s = fd_s;
+ __fio_fdtab[fd] = fdtp; 
+ 
+ return(fd | FIO_MSB);
+}
+
+/*
+ * check and convert the file modes (types for file descriptions) strings
+ * returns F on fail else T
+ *
+ * ending 'b' allowed but never used for unix  
+ * SJM 09/08/03 - must fix for other OSes
+ */
+static int32 chk_cnvt_fd_modes(char *os_mode, char *ver_mode)
+{
+ /* assume ver mode string and OS mode string same */ 
+ strcpy(os_mode, ver_mode); 
+
+ if (strcmp(ver_mode, "r") == 0) return(TRUE);
+ if (strcmp(ver_mode, "rb") == 0) { strcpy(os_mode, "r"); return(TRUE); }
+ if (strcmp(ver_mode, "w") == 0) return(TRUE);
+ if (strcmp(ver_mode, "wb") == 0) { strcpy(os_mode, "w"); return(TRUE); }
+ if (strcmp(ver_mode, "a") == 0) return(TRUE);
+ if (strcmp(ver_mode, "ab") == 0) { strcpy(os_mode, "a"); return(TRUE); }
+ if (strcmp(ver_mode, "r+") == 0) return(TRUE);
+ if (strcmp(ver_mode, "r+b") == 0) { strcpy(os_mode, "r+"); return(TRUE); }
+ if (strcmp(ver_mode, "rb+") == 0) { strcpy(os_mode, "r+"); return(TRUE); }
+ if (strcmp(ver_mode, "w+") == 0) return(TRUE);
+ if (strcmp(ver_mode, "w+b") == 0) { strcpy(os_mode, "w+"); return(TRUE); }
+ if (strcmp(ver_mode, "wb+") == 0) { strcpy(os_mode, "w+"); return(TRUE); }
+ if (strcmp(ver_mode, "a+") == 0) return(TRUE);
+ if (strcmp(ver_mode, "a+b") == 0) { strcpy(os_mode, "a+"); return(TRUE); }
+ if (strcmp(ver_mode, "ab+") == 0) { strcpy(os_mode, "a+"); return(TRUE); }
+ return(FALSE);
+}
+
+/*
+ * close either an mcd (all files - bits) or one file if fd passed
+ * this is sys task so just sets errno on error - no error return
+ *
+ * SJM 09/08/03 - FIXME ??? need to cancel pending f monits and strobes
+ */
+static void fio_do_fclose(struct expr_t *axp)
+{
+ int32 fd, is_mcd;
+
+ /* this sets error nunber */
+ if ((fd = chk_get_mcd_or_fd(axp->lu.x, &is_mcd)) == -1) return;
+
+ /* case close mcd */
+ if (is_mcd)
+  {
+   /* just have this re-eval mcd */
+   mcd_do_fclose(axp);
+   return;
+  }
+ 
+ /* notice $fclose does not return anything but vpi mcd fclose with fd does */
+ __fd_do_fclose(fd);
+}
+
+/*
+ * close a file descriptor and return 0 on success and 1 on error 
+ */
+extern int32 __fd_do_fclose(int32 fd)
+{
+ int32 slen;
+ FILE *f;
+
+ /* know fd in range but if not open error */ 
+ if (__fio_fdtab[fd] == NULL)
+  {
+   errno = EBADF;
+   /* SJM 09/23/03 - STRANGE but LRM says return open mcd numbers even here */
+   return(bld_open_mcd());
+  }
+ 
+ /* must save fd stream before freeing */
+ f = __fio_fdtab[fd]->fd_s;
+ slen = strlen(__fio_fdtab[fd]->fd_name);
+ __my_free(__fio_fdtab[fd]->fd_name, slen + 1); 
+ __my_free((char *) __fio_fdtab[fd], sizeof(struct fiofd_t)); 
+ __fio_fdtab[fd] = NULL;
+ __my_fclose(f);
+
+ return(0);
+}
+ 
+/*
+ * check and then convert mcd or fd expressions to int
+ * returns -1 on error else mcd or fd number (with high bit off)
+ * sets is_mcd arg to 1 if mcd to 0 for Unix fd 
+ *
+ * there is implied truncation to 32 bits so if wider with x's ok
+ */
+static int32 chk_get_mcd_or_fd(struct expr_t *fdxp, int32 *is_mcd)
+{
+ word32 fd;
+ struct xstk_t *xsp;
+
+ /* assume new file descriptor passed */
+ *is_mcd = FALSE;
+ xsp = __eval_xpr(fdxp);
+ if (xsp->bp[0] != 0L) { errno = EBADF; __pop_xstk(); return(-1); }
+
+ fd = xsp->ap[0];
+ __pop_xstk();
+
+ /* if high bit 0, then know mcd */
+ if ((fd & FIO_FD) == 0)
+  {
+   *is_mcd = TRUE;
+   return(fd);
+  } 
+ /* turn off high bit for file descriptor */
+ fd &= ~(FIO_FD);
+ if (fd >= FOPEN_MAX) { errno = EBADF; return(-1); }
+ if (__fio_fdtab[fd] == NULL) { errno = EBADF; return(-1); } 
+ return(fd);
+}
+
+/*
+ * flush either an mcd (all bits on) or one fd file
+ */
+static void fio_fflush(struct expr_t *axp)
+{
+ register int32 i;
+ int32 fd, is_mcd;
+ word32 mcd;
+
+ /* this sets error nunber */
+ if ((fd = chk_get_mcd_or_fd(axp, &is_mcd)) == -1) return;
+
+ /* case close mcd */
+ if (is_mcd)
+  {
+   mcd = (word32) fd;
+   /* SJM 09/09/03 - bit 31 now not used for mcds */   
+   for (i = 1; i < 30; i++)
+    {
+     if (((mcd >> i) & 1L) != 0L)
+      {
+       if (__mulchan_tab[i].mc_s == NULL)
+        {
+         __sgfinform(583,
+          "multi-channel descriptor bit %d on, but file not open",  i);
+        }
+       else fflush(__mulchan_tab[i].mc_s);
+      }
+    }
+   return;
+  }
+
+ /* know fd in range but if not open error */ 
+ if (__fio_fdtab[fd] == NULL) { errno = EBADF; return; }
+ fflush(__fio_fdtab[fd]->fd_s);
+}
+
+/* 
+ * get a character from stream with verilog file descripter expr fdxp
+ *
+ * SJM 08/09/03 - using literal -1 but maybe should be using EOF define?
+ * SJM 08/09/03 - LOOKATME - assuming OS will catch seeking on std[in,out,err]
+ * files
+ */
+static int32 fio_ungetc(struct expr_t *chxp, struct expr_t *fdxp)
+{
+ int32 c, fd, ival;
+ struct xstk_t *xsp;
+
+ /* implied assign to 8 bits - if b part non zero implied assign to 32 bits */
+ xsp = __eval_xpr(chxp); 
+ if (xsp->bp[0] != 0) { errno = EINVAL; __pop_xstk(); return(-1); }
+ /* this insures good char */ 
+ c = (int32) (xsp->ap[0] & 0xff);
+ __pop_xstk();
+ 
+ /* fd is OS file number with high bit anded off */
+ if ((fd = chk_get_ver_fd(fdxp)) == -1) return(-1);
+
+ /* returns c if success else -1 */
+ ival = ungetc(c, __fio_fdtab[fd]->fd_s);
+ return(ival);
+}
+
+/*
+ * check and then convert fd expressions to int
+ * return -1 on error else fd number with high bit off (know positive or 0)
+ *
+ * there is implied truncation to 32 bits so if wider with x's ok
+ */
+static int32 chk_get_ver_fd(struct expr_t *fdxp)
+{
+ int32 fd;
+ struct xstk_t *xsp;
+
+ xsp = __eval_xpr(fdxp);
+ if (xsp->bp[0] != 0L) { errno = EBADF; __pop_xstk(); return(-1); }
+
+ fd = xsp->ap[0] & FIO_FD;
+ __pop_xstk();
+ if (fd >= FOPEN_MAX) { errno = EBADF; return(-1); }
+ /* AIV 06/27/05 - fd cannot be greater than max file size */
+ if (fd >= MY_FOPEN_MAX || __fio_fdtab[fd] == NULL) 
+  { errno = EBADF; return(-1); } 
+ return(fd);
+}
+
+/* 
+ * get a string from stream with verilog file descripter expr fdxp
+ *
+ * SJM 09/08/03 - assuming following C lib fgets new line included in string
+ */
+static int32 fio_fgets(struct expr_t *str_xp, struct expr_t *fdxp)
+{
+ int32 fd, slen, chlen;
+ struct xstk_t *xsp;
+ char *lp;
+ 
+ /* result string can't be empty "(, fd)" */
+ if (str_xp->optyp == OPEMPTY) { errno = EINVAL; return(0); }
+
+ /* fd is OS file number with high bit anded off - on error OS err num set */
+ if ((fd = chk_get_ver_fd(fdxp)) == -1) return(0);
+ 
+ /* len rounds down if not div by 8 following LRM */
+ slen = str_xp->szu.xclen/8;
+ lp = __my_malloc(slen + 1);
+ /* fgets returns ptr to lp or nil not number of read chars */
+ if (fgets(lp, slen, __fio_fdtab[fd]->fd_s) == NULL)
+  {
+   __my_free(lp, slen + 1);
+   return(0);
+  }
+
+ /* SJM 10/20/03 - think fgets should return nil if at eof but check */ 
+ /* DBG remove -- */
+ if (*lp == '\0') __misc_terr(__FILE__, __LINE__);
+ /* --- */ 
+
+ chlen = strlen(lp);
+
+ xsp = __cstr_to_vval(lp);
+ /* now done with read c string must free */
+ __my_free(lp, slen + 1);
+
+ /* following verilog convention if not enough chars (EOF) zero fill */ 
+
+ /* 05/16/04 - Verilog strings can't be signed */
+ if (xsp->xslen != str_xp->szu.xclen) __sizchgxs(xsp, str_xp->szu.xclen);
+
+ __exec2_proc_assign(str_xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+ /* notice num chars read my be differ than len of lhs assign to reg */
+ return(chlen);
+}
+
+/* 
+ * rewind within an OS stream - returns -1 on error 0 on success
+ *
+ * equivalent to C lib fseek(FILE *, 0, SEEK_SET) 
+ */
+static int32 fio_rewind(struct expr_t *fdxp)
+{
+ int32 fd;
+
+ /* fd is OS file number with high bit anded off - on error OS err num set */
+ if ((fd = chk_get_ver_fd(fdxp)) == -1) return(-1);
+
+ fseek(__fio_fdtab[fd]->fd_s, 0L, SEEK_SET);
+ /* returns 0 on success */
+ return(0);
+}
+
+/* 
+ * seek within an OS stream - returns -1 on error and 0 on success
+ */
+static int32 fio_fseek(struct expr_t *fdxp, struct expr_t *ofs_xp,
+ struct expr_t *whence_xp)
+{
+ int32 fd, offset, whence, seek_typ;
+ struct xstk_t *xsp;
+
+ /* fd is OS file number with high bit anded off - on error OS err num set */
+ if ((fd = chk_get_ver_fd(fdxp)) == -1) return(-1);
+
+ /* there is an implied convert to 32 bits here */
+ xsp = __eval_xpr(ofs_xp);
+ if (xsp->bp[0] != 0) { errno = EINVAL; __pop_xstk(); return(-1); }
+ /* offset can be negative */
+ offset = (int32) xsp->ap[0];
+ __pop_xstk();
+
+ /* there is an implied convert to 32 bits here */
+ xsp = __eval_xpr(whence_xp);
+ if (xsp->bp[0] != 0) { errno = EINVAL; __pop_xstk(); return(-1); }
+ /* only 3 possibilities */
+ whence = (int32) xsp->ap[0];
+ __pop_xstk();
+ /* check for legal whence seek type */ 
+ if (whence == 0) seek_typ = SEEK_SET;
+ else if (whence == 1) seek_typ = SEEK_CUR;
+ else if (whence == 2) seek_typ = SEEK_END;
+ else { errno = EINVAL; return(-1); }
+  
+ if (__fio_fdtab[fd] == NULL) { errno = EBADF; return(-1); } 
+ fseek(__fio_fdtab[fd]->fd_s, (long) offset, seek_typ);
+ /* returns 0 on success */
+ return(0);
+}
+
+/*
+ * get error status - verilog equivalent of strerror function
+ * return 0 on no error else set error number and copies err str to str xp
+ * 
+ * if user passes string narrower than 80 chars, silently truncates err str
+ * notice if this has error it overwrites the pending errno error
+ *
+ * SJM 08/09/03 - although LRM does not say it, returns -1 on error here
+ */
+static int32 fio_ferror(struct expr_t *fdxp, struct expr_t *str_xp)
+{
+ int32 fd, rv, stream_err;
+ char *cp;
+ struct xstk_t *xsp;
+  
+ /* result string can't be empty "(, fd)" */
+ if (str_xp->optyp == OPEMPTY) { errno = EINVAL; return(-1); }
+  
+ /* fd is OS file number with high bit anded off - on error OS err num set */
+ /* notice if fails can change error number */
+ if ((fd = chk_get_ver_fd(fdxp)) == -1) return(-1);
+ 
+ if ((stream_err = ferror(__fio_fdtab[fd]->fd_s)) == 0)
+  {
+   rv = 0; 
+err_ret:
+   push_xstk_(xsp, str_xp->szu.xclen);
+   zero_allbits_(xsp->ap, xsp->xslen);
+   zero_allbits_(xsp->bp, xsp->xslen);	
+   __exec2_proc_assign(str_xp, xsp->ap, xsp->bp);
+   __pop_xstk();
+   return(rv);
+  }
+
+ /* use the reentrant posix form of str error function */
+ /* SJM 01/26/05 - no reason for reentrant version strerr here */
+ if ((cp = strerror(stream_err)) == NULL) { rv = -1; goto err_ret; }
+
+ /* know buf ends with '\0' */
+ xsp = __cstr_to_vval(cp);
+ /* 05/16/04 - Verilog strings can't be signed */
+ if (xsp->xslen != str_xp->szu.xclen) __sizchgxs(xsp, str_xp->szu.xclen);
+
+ __exec2_proc_assign(str_xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+ return(errno);
+}
+
+/* 
+ * fread data into reg or memory - only 0 or 1 can be read
+ * on error 0 else number of 8 bit chars read
+ *
+ * SJM 09/20/03 - LRM wrong for memories fread can't read addresses
+ */
+static int32 fio_fread(struct expr_t *ndp)
+{
+ int32 fd, vlen, nbytes, bufi;
+ byte *buf;
+ struct expr_t *lhsx, *fdxp, *startxp, *cntxp;
+ struct net_t *np;
+ struct xstk_t *xsp;
+
+ lhsx = ndp->lu.x;
+ /* result string can't be empty "(, fd)" */
+ if (lhsx->optyp == OPEMPTY) { errno = EINVAL; return(-1); }
+
+ fdxp = ndp->ru.x->lu.x;
+ /* fd is OS file number with high bit anded off - on error OS err num set */
+ if ((fd = chk_get_ver_fd(fdxp)) == -1) return(0);
+
+ startxp = cntxp = NULL; 
+ if (lhsx->optyp == ID || lhsx->optyp == GLBREF)
+  {
+   /* for array element, won't be ID */
+   np = lhsx->lu.sy->el.enp;
+   if (np->n_isarr)
+    {
+     if ((ndp = ndp->ru.x->ru.x) != NULL)
+      {
+       startxp = ndp->lu.x;
+       if ((ndp = ndp->ru.x) != NULL) cntxp = ndp->lu.x;
+      }
+     return(fio_arr_fread(lhsx, fd, startxp, cntxp));
+    }
+  }
+
+ /* case 1: read into reg - start and end args ignored if present */
+ /* len rounds down if not div by 8 following LRM */
+ /* SJM 09/20/03 LRM says round down but that doesn't make sense */ 
+ /* so round up following PLI implementation */
+ vlen = (lhsx->szu.xclen + 7)/8;
+
+ /* must store into stack value and then assign */ 
+ buf = (byte *) __my_malloc(vlen);
+
+ nbytes = fread(buf, 1, vlen, __fio_fdtab[fd]->fd_s);
+ /* if unable to read entire reg, return error and do not assign */
+ /* if part read and EOF, correct for reg to not be changed */
+ if (nbytes != vlen)
+  {
+   __my_free((char *) buf, vlen);
+   /* for short last section, reg not assigned and bytes in stream read */
+   /* returned - user must call ferror or feof system task to find error */
+   /* to mimic stdio lib beheavior - if error will probably be 0 */
+   return(nbytes);
+  }
+
+ push_xstk_(xsp, lhsx->szu.xclen);
+ /* 0 value so only need to turn 1 bits on */
+ zero_allbits_(xsp->ap, lhsx->szu.xclen);
+ zero_allbits_(xsp->bp, lhsx->szu.xclen);
+ bufi = vlen - 1;
+
+ fread_onto_stk(xsp, buf, bufi);
+
+ __my_free((char *) buf, vlen);
+ /* know xsp width exactly match lhs expr width */  
+ __exec2_proc_assign(lhsx, xsp->ap, xsp->bp);
+ __pop_xstk();
+ return(0);
+}
+
+/*
+ * read one reg (also used for cell of array)
+ * can't fail
+ *
+ * know correct width location pushed onto x stack that is filled 
+ * also know that f read buf value big enough and bufi starts at high end byte
+ */
+static void fread_onto_stk(struct xstk_t *xsp, byte *buf, int32 bufi)
+{
+ register int32 bi;
+ int32 hbused, hbi, wi, bi2;  
+ word32 bitval, bval;
+
+ /* know have char 0/1 value for every bit */
+ /* handle partially filled high byte as special case */
+ hbused = xsp->xslen % 8;
+ bi = xsp->xslen - 1;
+ if (hbused != 0)
+  {
+   bval = (word32) buf[0];
+   for (hbi = hbused - 1; hbi >= 0; hbi--, bi--)
+    {
+     wi = get_wofs_(bi);
+     bi2 = get_bofs_(bi);
+     bitval = ((bval >> hbi) & 1) << bi2;
+     if (bitval != 0) xsp->ap[wi] |= bitval;  
+    }
+   bufi--;
+  }
+ /* handle simple all bits in all fread bytes used */
+ /* bi correct next high bit to set from read byte */ 
+ for (; bufi >= 0; bufi--)
+  {
+   bval = (word32) buf[bufi];
+   for (hbi = 7; hbi >= 0; hbi--, bi--) 
+    {
+     /* DBG remove -- */
+     if (bi < 0) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     wi = get_wofs_(bi);
+     bi2 = get_bofs_(bi);
+     bitval = ((buf[bufi] >> hbi) & 1) << bi2;
+     if (bitval != 0) xsp->ap[wi] |= bitval;  
+    }
+  }
+}
+
+/*
+ * fread into array (memory)
+ *
+ * fread of memory differs from read mem because no addresses in file   
+ * and can only read non x/z values
+ */
+static int32 fio_arr_fread(struct expr_t *lhsx, int32 fd,
+ struct expr_t *startxp, struct expr_t *cntxp)
+{
+ register int32 i, arri;
+ int32 ri1, ri2, arrwid, starti, cnt, nbytes, tot_bytes, nd_itpop, vlen;
+ byte *buf;
+ struct net_t *np;
+ struct xstk_t *xsp;
+ struct gref_t *grp;
+
+ np = lhsx->lu.sy->el.enp;
+ __getarr_range(np, &ri1, &ri2, &arrwid);
+
+ /* array elements stored h:0 normalized so index h to high */
+ /* but loading is from low to high array words */
+ starti = 0;
+ cnt = arrwid - 1;
+
+ /* ,,) form possible for start and count expressions */
+ if (startxp != NULL) 
+  {
+   if (startxp->optyp != OPEMPTY) 
+    {
+     /* can't use comp ndx here because value is just normal expr */
+     xsp = __eval_xpr(cntxp);
+     if (!vval_is0_(xsp->bp, xsp->xslen) ||
+      (xsp->xslen > WBITS && !vval_is0_(&(xsp->ap[1]), xsp->xslen - WBITS)))
+      {
+       __sgfwarn(588,
+        "array $fread of %s start value has x/z bits or wide - low a part used",
+        np->nsym->synam);
+      }
+     arri = (int32) xsp->ap[0];
+     /* stsk arg. in Verilog source is actual index - must convert to h:0 */
+     starti = normalize_ndx_(arri, ri1, ri2); 
+     __pop_xstk();
+     if (starti < 0 || starti >= arrwid) 
+      {
+       errno = EINVAL;
+       return(0);
+      }
+    }
+  }
+ if (cntxp != NULL)
+  {
+   if (cntxp->optyp != OPEMPTY)
+    {
+     /* if count present but not start then use first addr in mem */
+     xsp = __eval_xpr(cntxp);
+     if (!vval_is0_(xsp->bp, xsp->xslen) ||
+      (xsp->xslen > WBITS && !vval_is0_(&(xsp->ap[1]), xsp->xslen - WBITS)))
+      {
+       __sgfwarn(588,
+        "array $fread of %s count value has x/z bits or wide - low a part used",
+        np->nsym->synam);
+      }
+     cnt = (int32) xsp->ap[0];
+     if (cnt < 0 || starti + cnt >= arrwid) 
+      {
+       errno = EINVAL;
+       return(0);
+      }
+    }
+  }
+
+ nd_itpop = FALSE;
+ if (lhsx->optyp == GLBREF)
+  { grp = lhsx->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ push_xstk_(xsp, np->nwid);
+
+ /* round up so 1 bit memory still requires 1 byte per cell */
+ vlen = (arrwid + 7)/8;
+ buf = (byte *) __my_malloc(vlen);
+ tot_bytes = 0;
+ for (arri = starti, i = 0; i < cnt; i++, arri++)  
+  {
+   nbytes = fread(buf, 1, vlen, __fio_fdtab[fd]->fd_s);
+   tot_bytes += nbytes;
+   /* if unable to read entire reg, return error and do not assign */
+   /* if part read and EOF, correct for reg to not be changed */
+   if (nbytes != vlen) goto done;
+
+   /* 0 value so only need to turn 1 bits on */
+   zero_allbits_(xsp->ap, lhsx->szu.xclen);
+   zero_allbits_(xsp->bp, lhsx->szu.xclen);
+
+   fread_onto_stk(xsp, buf, vlen - 1);
+
+   /* SJM 03/15/01 - change to fields in net record */
+   if (np->nchg_nd_chgstore)
+    {
+     __chg_st_arr_val(np->nva, arrwid, np->nwid, arri, xsp->ap, xsp->bp);
+
+     /* SJM - 06/25/00 - lhs changed possible from change store */
+     /* and must only trigger change for right array index */
+     if (__lhs_changed) record_sel_nchg_(np, arri, arri);
+    }
+   else __st_arr_val(np->nva, arrwid, np->nwid, arri, xsp->ap, xsp->bp);
+  }
+done:
+ __my_free((char *) buf, vlen);
+ __pop_xstk();
+ if (nd_itpop) __pop_itstk();
+ return(tot_bytes);
+}
+ 
+/*
+ * implement the swrite to string (instead of file) Verilog formatted 
+ * print sys tasks
+ *
+ * easy since because of mcds formatting always goes into c string
+ * using the _expr line and cur sofs mechanism
+ */
+static void fio_swrite(struct expr_t *axp, int32 dflt_fmt)
+{
+ struct expr_t *str_xp; 
+ struct xstk_t *xsp;
+
+ str_xp = axp->lu.x;
+ axp = axp->ru.x;
+ __str_do_disp(axp, dflt_fmt);
+ xsp = __cstr_to_vval(__exprline);
+
+ /* now done with expr line */
+ __cur_sofs = 0;
+
+ /* do the assign to string after formatting into __expr line */
+ /* following verilog convention if not enough chars (EOF) zero fill */ 
+
+ /* 05/16/04 - Verilog strings can't be signed */
+ if (xsp->xslen != str_xp->szu.xclen) __sizchgxs(xsp, str_xp->szu.xclen);
+
+ __exec2_proc_assign(str_xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+}
+
+/*
+ * implement $sformat version of $swrite that has only 1 format but can
+ * be variable unlike $swrite
+ *
+ * first arg is string to write into, 2nd arg is format that can be
+ * var so needs to be evaled - rest are the format args - error if
+ * too few format args and ignores extra (unlike $swrite that prints
+ * them with format)
+ */
+static void fio_sformat(struct expr_t *axp)
+{
+ int32 blen, flen;
+ struct expr_t *str_xp, *fmt_xp; 
+ struct xstk_t *xsp;
+ char *fmtstr;
+
+ /* lhs expr to store formatted string into */
+ str_xp = axp->lu.x;
+
+ /* evaluate the format into a Verilog string */
+ axp = axp->ru.x;
+ fmt_xp = axp->lu.x;
+
+ xsp = __eval_xpr(fmt_xp);
+ if (!vval_is0_(xsp->bp, xsp->xslen))
+  {
+   errno = EINVAL;
+   return;
+  }
+
+ /* trim high 0's of a part only */
+ blen = __trim1_0val(xsp->ap, xsp->xslen); 
+ if (blen == 0)
+  {
+   errno = EINVAL;
+   return;
+  }
+
+ /* this mallocs the input string to scan from */
+ fmtstr = __vval_to_vstr(xsp->ap, blen, &flen);
+ __pop_xstk();
+
+ /* assuming 8 bit bytes */
+ axp = __disp_1fmt_to_exprline(fmtstr, axp);
+ if (axp != NULL)
+  {
+   __sgfwarn(3133,
+    "$sformat extra unused arguments after format exhausted");
+  }
+
+ __my_free(fmtstr, flen);
+
+ xsp = __cstr_to_vval(__exprline);
+ /* now done with expr line */
+ __cur_sofs = 0;
+
+ /* do the assign to string after formatting into __expr line */
+ /* following verilog convention if not enough chars (EOF) zero fill */ 
+
+ /* 05/16/04 - Verilog strings can't be signed */
+ if (xsp->xslen != str_xp->szu.xclen) __sizchgxs(xsp, str_xp->szu.xclen);
+
+ __exec2_proc_assign(str_xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+}
+
+/*
+ * implement $fscanf for now using old scin_s scanf code
+ */
+static int32 fio_fscanf(struct expr_t *ndp)
+{
+ int32 fd, blen, flen, rv;
+ char *fmtstr;
+ struct expr_t *fmt_xp;
+ struct xstk_t *xsp;
+
+ /* fd is OS file number with high bit anded off - on error OS err num set */
+ /* notice if fails can change error number */
+ if ((fd = chk_get_ver_fd(ndp->lu.x)) == -1) return(-1);
+
+ /* know fd in range but if not open error */ 
+ if (__fio_fdtab[fd] == NULL) { errno = EBADF; return(-1); }
+
+ ndp = ndp->ru.x;
+ fmt_xp = ndp->lu.x;
+ xsp = __eval_xpr(fmt_xp);
+ if (!vval_is0_(xsp->bp, xsp->xslen))
+  {
+   errno = EINVAL;
+   return(-1);
+  }
+ /* trim high 0's of a part only */
+ blen = __trim1_0val(xsp->ap, xsp->xslen); 
+ if (blen == 0)
+  {
+   errno = EINVAL;
+   return(-1);
+  }
+ fmtstr = __vval_to_vstr(xsp->ap, blen, &flen);
+ __fiofp = fmtstr; 
+
+ /* ndp now ptr to comma operator of first arg past fmt */
+ ndp = ndp->ru.x;
+ rv = fio_exec_scanf(__fio_fdtab[fd]->fd_s, ndp);
+ __my_free(fmtstr, flen);
+ __pop_xstk();
+ return(rv);
+}
+
+/*
+ * implement $sscanf for now using old scin_s scanf code
+ */
+static int32 fio_sscanf(struct expr_t *ndp)
+{
+ int32 blen, slen, flen, rv;
+ char *instr, *fmtstr;
+ struct expr_t *str_xp, *fmt_xp;
+ struct xstk_t *xsp;
+
+ /* first arg is string to read from */
+ str_xp = ndp->lu.x;
+ xsp = __eval_xpr(str_xp);
+ if (!vval_is0_(xsp->bp, xsp->xslen))
+  {
+   errno = EINVAL;
+   return(-1);
+  }
+ /* trim high 0's of a part only */
+ blen = __trim1_0val(xsp->ap, xsp->xslen); 
+ if (blen == 0)
+  {
+   errno = EINVAL;
+   return(-1);
+  }
+
+ /* this mallocs the input string to scan from */
+ instr = __vval_to_vstr(xsp->ap, blen, &slen);
+ /* implied global used for reading input char by char */ 
+ __fiolp = instr; 
+ __pop_xstk();
+
+ ndp = ndp->ru.x;
+ fmt_xp = ndp->lu.x;
+ xsp = __eval_xpr(fmt_xp);
+ if (!vval_is0_(xsp->bp, xsp->xslen))
+  {
+   errno = EINVAL;
+   return(-1);
+  }
+ /* trim high 0's of a part only */
+ blen = __trim1_0val(xsp->ap, xsp->xslen); 
+ if (blen == 0)
+  {
+   errno = EINVAL;
+   return(-1);
+  }
+
+ /* this mallocs the fmt string to scan from */
+ /* notice for new routines (especially input), only one format string */
+ fmtstr = __vval_to_vstr(xsp->ap, blen, &flen);
+ __fiofp = fmtstr; 
+ __pop_xstk();
+
+ /* AIV 09/29/03 - forgot to assign ndp to first arg past format */
+ ndp = ndp->ru.x;
+
+ rv = fio_exec_scanf(NULL, ndp);
+ /* free the version in malloced storage */
+ __my_free(instr, slen);
+ __my_free(fmtstr, flen);
+ return(rv);
+}
+
+/* SJM 09/24/03 - why need defines here? */
+/* SJM 09/24/03 - eliminated EOL since no significance of new line now */
+#define infmt() ((*__fiofp == '\0') ? EOF : *__fiofp++)
+
+/*
+ * execute the scan input system task 
+ * returns number of successfully read items 
+ *
+ * on entry axp points to arg list comma operator of first scan into arg
+ * if f nil, gets char from global file io work char ptr else read char
+ *
+ * know globals __fiolp points to string (for sscanf) and __fiofp always
+ * points to first char in format string on entry
+ *
+ * SJM 09/24/03 - seems that unlike c lib no \ escaping of % allowed - true?
+ * now must check format syntax correctness here because format can be var 
+ */
+static int32 fio_exec_scanf(FILE *f, struct expr_t *axp)
+{
+ register char *wchp;
+ register int32 c, fch, width;
+ int32 len, num_matched, base, signc, ival;
+ int32 retval, assgn_sup, stval, sav_sofs, lmatch; 
+ double d1;
+ struct expr_t *lhsx; 
+ struct xstk_t *xsp;
+ struct task_t *tskp;
+
+ /* if F, illegal format so return EOF */ 
+ if (!chk_scanf_fmt(__fiofp))
+  {
+   errno = EINVAL;
+   return(-1);
+  }
+
+ /* start by readin first input char - may push back */
+ /* axp always points to comma operator of next arg (maybe nil) */
+ retval = -1;
+
+ /* if EOF on input file before any matches return EOF */
+ if ((c = scanf_getc(f)) == EOF) return(-1);
+ for (lmatch = num_matched = 0;;)
+  {
+   if (f != NULL && lmatch != num_matched)
+    {
+     if ((__scanf_pos = ftell(f)) == -1) return(-1);
+    }
+   lmatch = num_matched;
+
+   /* at beginning of loop c is next input line char to process */
+   /* but fch is last processed format char */
+   if ((fch = infmt()) == EOF) break; 
+   if (fch != '%')
+    {
+     /* fmt white space matches optional any width input line white space */
+     if (isspace(fch))
+      {
+       while(isspace(c))
+        {
+         if ((c = scanf_getc(f)) == EOF) break;
+        }
+       if (c == EOF) break;
+       continue;
+      }
+     else if (c == fch)
+      {
+       c = scanf_getc(f);
+       continue;
+      }
+     /* mismatched input char - finished ret count of assigned */
+     retval = 0;  
+     break;
+    }
+   if ((fch = infmt()) == EOF) break;
+   /* check for format suppress char */
+   if (fch == '*') 
+    {
+     assgn_sup = TRUE;
+     if ((fch = infmt()) == EOF) break; 
+    }
+   else assgn_sup = FALSE;
+
+   /* find maximum field width */
+   width = 0;
+   while (isdigit(fch))
+    {
+     width *= 10;
+     width += fch - '0';
+     if ((fch = infmt()) == EOF) goto done;
+    }
+   if (width == 0) width = -1;
+
+   /* LOOKATME - possible portability problem since isspace of */ 
+   /* special -2 may or may be space - checking both */
+   /* consume input line white space unless special c format */
+   if (fch != 'c')
+    {
+     while (isspace(c)) { if ((c = scanf_getc(f)) == EOF) break; }
+    }
+
+   retval = 0;
+   switch (fch) {
+    case '%':
+     /* %% matches % - i.e. it is % escaping mechanism */
+     if (c != '%') goto done; 
+     break;
+    case 'd': base = BDEC; goto do_num;
+    case 'b': base = BBIN; goto do_num;
+    case 'o': base = BOCT; goto do_num;
+    case 'x': case 'h': base = BHEX;
+do_num: 
+     /* return F if no characters collected */
+     if (!collect_scanf_num(&signc, f, c, base, width)) goto done;
+     if (!assgn_sup)
+      {
+       num_matched++; 
+       if (axp == NULL) goto done;
+       lhsx = axp->lu.x;
+
+       /* also convert into ac/bc wrk globals */
+       /* conversion requires knowing arg expr width - can only do here */
+       __itoklen = lhsx->szu.xclen;
+       /* converted number converted to exactly lhs expr size */ 
+       /* use expr. width as imputed [num]' form - always succeeds */
+       __to_dhboval(base, FALSE);
+
+       /* try to correct value for minus sign */
+       if (signc == '-')
+        {
+         /* SJM 05/14/04 - must handle any width signed */
+         if (vval_is0_(__bcwrk, __itoklen))
+          {
+           if (__itoklen == WBITS)
+            { ival = (int32) __acwrk[0]; __acwrk[0] = (word32) -ival; }
+           else __inplace_lnegate(__acwrk, __itoklen);
+          }
+        }
+
+       /* know __acwrk and _bcwrk have right width number */
+       if (lhsx->optyp != OPEMPTY)
+        {
+         __exec2_proc_assign(lhsx, __acwrk, __bcwrk);
+        }
+       /* know c has 1 char after number */
+       axp = axp->ru.x;
+      }
+     break;
+    case 'f': case 'e': case 'g': case 't':
+     if (!collect_scanf_realnum(&(d1), f, c, width, fch)) goto done;
+     if (!assgn_sup)
+      {
+       if (axp == NULL) goto done;
+       lhsx = axp->lu.x;
+       axp = axp->ru.x;
+       num_matched++; 
+       if (lhsx->optyp != OPEMPTY)
+        {
+         push_xstk_(xsp, WBITS);
+         memcpy(xsp->ap, &d1, sizeof(double));
+         if (!lhsx->is_real)
+          {
+           __cnv_stk_fromreal_toreg32(xsp);
+
+           /* SJM 09/29/03 - chg to handle sign extend and separate types */
+           if (xsp->xslen > lhsx->szu.xclen)
+            __narrow_sizchg(xsp, lhsx->szu.xclen);
+           else if (xsp->xslen < lhsx->szu.xclen)
+            {
+             /* know always signed */
+             __sgn_xtnd_widen(xsp, lhsx->szu.xclen);
+            }
+          }
+
+         __exec2_proc_assign(lhsx, xsp->ap, xsp->bp);
+         __pop_xstk();
+        }
+      }
+     /* know c has 1 char after number */
+     break;
+    case 'v':
+     wchp = __numtoken; 
+     /* know there is always look ahead char */ 
+     wchp[0] = c;
+     if ((c = scanf_getc(f)) == EOF) goto done;
+     wchp[1] = c;
+     if ((c = scanf_getc(f)) == EOF) goto done;
+     wchp[2] = c;
+     wchp[3] = '\0';
+     if ((stval = cnvt_scanf_stnam_to_val(wchp)) == 0) goto done;
+     if (!assgn_sup)
+      {
+       lhsx = axp->lu.x;
+       if (lhsx->optyp != OPEMPTY)
+        {
+         push_xstk_(xsp, 1);
+         /* SJM 09/25/03 - since can only assign to reg remove stren */ 
+         xsp->ap[0] = stval & 1;
+         xsp->bp[0] = (stval >> 1) & 1;
+
+         /* SJM 09/29/03 - since 1 bit rhs never signed - can only widen */
+         if (xsp->xslen != lhsx->szu.xclen)
+          __sizchg_widen(xsp, lhsx->szu.xclen);
+
+         __exec2_proc_assign(lhsx, xsp->ap, xsp->bp);
+         __pop_xstk();
+        }
+      }
+     break;
+    case 'c':
+     /* SJM 09/24/03 - old sscanf multiple chars removed - now 1 char only */
+     /* SJM 03/20/00 - know never need to grow num token - f get used */
+     /* notice unlike clib, width can't be used for "string" of chars */
+     /* SJM 05/14/04 - know the char already read and in c */
+     /* must be one char left on input stream */
+     if (c == EOF) goto done;
+     wchp = __numtoken;
+     wchp[0] = (byte) c;
+     wchp[1] = '\0';
+     len = 1;
+     /* if past end of formats, no more assignments to do */
+     /* convert to pascal style string as Verilog value on stack */
+do_str_assign:
+     /* DBG remove ---
+     if (__debug_flg)
+      { __dbg_msg("read string [%s]\n", __numtoken); }
+     --- */
+     if (!assgn_sup)
+      {
+       num_matched++; 
+       if (axp == NULL) goto done;
+       lhsx = axp->lu.x;
+       axp = axp->ru.x;
+       push_xstk_(xsp, 8*len);
+       zero_allbits_(xsp->bp, xsp->xslen);
+       __vstr_to_vval(xsp->ap, __numtoken, 8*len);
+       if (lhsx->optyp != OPEMPTY)
+        {
+         /* size chg never needs sign extend - can narrow or widen */ 
+         if (xsp->xslen != lhsx->szu.xclen) __sizchgxs(xsp, lhsx->szu.xclen);
+
+         __exec2_proc_assign(lhsx, xsp->ap, xsp->bp);
+        }
+       __pop_xstk();
+       /* c has next char to process */ 
+      }
+     break;
+    case 's': 
+     /* s is for white space delimited strings */
+     wchp = __numtoken;
+     /* notice works since added \0 to end of input line */
+     /* i.e. empty string ok */ 
+     for (len = 0;;)
+      {
+       *wchp++ = c;
+       len++;
+       c = scanf_getc(f);
+       if (width > 0 && --width == 0) break;
+       if (c == EOF || isspace(c)) break;
+      }
+     *wchp = '\0'; 
+     goto do_str_assign;
+    case 'u':
+     /* no way to detemine num words to read */
+     if (assgn_sup)
+      {
+       __sgferr(3417,
+        "scanf assignment suppression character illegal with %%u binary data format");
+       errno = EINVAL;
+       return(-1);
+      }
+     if (width != -1)
+      {
+       __sgfinform(3008,
+        "scanf field width meaningless with %%u binary data format - width ignored");
+      }      
+     if (axp == NULL) goto done;
+     lhsx = axp->lu.x;
+     xsp = collect_ufmt_binval(f, lhsx, c);
+     if (xsp == NULL) goto done;
+     axp = axp->ru.x;
+     /* since use scanf assign to reg arg for size - never need size chg */
+     __exec2_proc_assign(lhsx, xsp->ap, xsp->bp);
+     __pop_xstk();
+     break;
+    case 'z':
+     /* no way to detemine num words to read */
+     if (assgn_sup)
+      {
+       __sgferr(3417,
+        "scanf assignment suppression character illegal with %%z binary data format");
+       errno = EINVAL;
+       return(-1);
+      }
+     if (width != -1)
+      {
+       __sgfinform(3008,
+        "scanf field width meaningless with %%z binary data format - width ignored");
+      }      
+     if (axp == NULL) goto done;
+     lhsx = axp->lu.x;
+     axp = axp->ru.x;
+     xsp = collect_zfmt_binval(f, lhsx, c);
+     if (xsp == NULL) goto done;
+
+     /* since use scanf assign to reg arg for size - never need size chg */
+     __exec2_proc_assign(lhsx, xsp->ap, xsp->bp);
+     __pop_xstk();
+     break;
+    case 'm':
+     sav_sofs = __cur_sofs;
+     if (__cur_thd == NULL) tskp = __scope_tskp; 
+     else tskp = __getcur_scope_tsk();
+     __disp_itree_path(__inst_ptr, tskp);
+     /* use optional width field to truncate */
+     if (width > 1 && (__cur_sofs - sav_sofs) > width)
+      {
+       __cur_sofs = sav_sofs + width;
+       __exprline[__cur_sofs] = '\0';
+      }
+     len = __cur_sofs - sav_sofs;
+     if (!assgn_sup)
+      {
+       num_matched++; 
+       if (axp == NULL) { __cur_sofs = sav_sofs; goto done; }
+
+       lhsx = axp->lu.x;
+       axp = axp->ru.x;
+       push_xstk_(xsp, 8*len);
+       zero_allbits_(xsp->bp, xsp->xslen);
+       __vstr_to_vval(xsp->ap, __exprline, 8*len);
+       if (lhsx->optyp != OPEMPTY)
+        {
+         /* widening adds high 0 bits */
+         /* again can narrow or widen and neve need sign extend */
+         if (xsp->xslen != lhsx->szu.xclen) __sizchgxs(xsp, lhsx->szu.xclen);
+
+         __exec2_proc_assign(lhsx, xsp->ap, xsp->bp);
+        }
+       __pop_xstk();
+      }
+     /* c has next char to process */ 
+     continue;
+    default:
+     /* invalid format char after % */
+     errno = EINVAL;
+     goto done; 
+   }
+   /* SJM 05/14/04 - top of loop expects one ahead */
+   c = scanf_getc(f);
+  }
+ /* good exit from scan processing of fmt - but still read one too far */  
+ scanf_ungetc(c, f);
+
+ /* this is nothing read case */
+ if (retval == -1) return(-1);
+ return(num_matched);
+
+done:
+ if (f != NULL && __scanf_pos > 0)
+  {
+   if (fseek(f, __scanf_pos - 1, SEEK_SET) == -1) return(-1);
+  }
+ /* this is nothing read case */
+ if (retval == -1) return(-1);
+ return(num_matched);
+}
+
+/*
+ * version of getc that read from passed scanf input file or buf for sscanf
+ */
+static int32 scanf_getc(FILE *f)
+{
+ int32 c;
+
+ if (f == NULL)
+  {
+   if (*__fiolp == '\0') return(EOF);
+   return(*__fiolp++);
+  }
+ c = fgetc(f); 
+ return(c); 
+}
+
+/*
+ * version of ungetc that backup up buffer for string file io operations 
+ * BEWARE - can't call ungetc unless something read
+ */
+static void scanf_ungetc(int32 c, FILE *f)
+{
+ if (f == NULL) __fiolp--; else ungetc(c, f);
+}
+
+/*
+ * check new fileio $fscanf or $sscanf format string
+ *
+ * SJM 09/24/03 - now must check at run time each time called because
+ * format can be variable - also only check fmt not arg matching
+ *
+ * LOOKATME - could check only once for constant fmt string
+ */
+static int32 chk_scanf_fmt(char *fmt)
+{
+ register char *fp;
+ int32 fmt_pos, rv, has_width;
+
+ rv = TRUE;
+ fp = fmt;
+ fmt_pos = 0;
+ while (*fp != '\0')
+  {
+   /* just char in fmt to match */
+   if (*fp++ != '%') continue;
+  
+   /* %% is way to match % in input */ 
+   /* SJM 09/24/03 - assuming %[* and/or width digs]% illegal */
+   if (*fp == '%') { fp++; continue; }
+
+   /* assign suppress char legal */
+   if (*fp == '*') fp++;
+
+   /* possible %ddd[fmt letter] */
+   has_width = FALSE;
+   while (isdigit(*fp))
+    {
+     fp++;
+     if (*fp == '\0')
+      {
+       __sgferr(1186,
+         "end of format while reading maximum field width (pos. %d)",
+        fmt_pos);
+       rv = FALSE;
+       goto done;
+      }
+     has_width = TRUE;
+    }
+   fmt_pos++;
+   /* string formats must be multiple of 8 bits */
+   switch (*fp) {
+    case 'b': case 'o': case 'h': case 'x': case 'd':
+     break;
+    case 'f': case 'e': case 'g':
+     break;
+    case 'v':
+     break;
+    case 't':
+     break;
+    case 'c':
+     if (has_width)
+      {
+       __sgfwarn(3104,
+        "maximum field width used with %%c format (pos. %d) - width ignored",
+        fmt_pos);
+      }
+     break;
+    case 's':
+     break;
+    case 'u':
+     break;
+    case 'z':
+     break;
+    case 'm':
+     break;
+    default:
+     __sgferr(1274,
+      "$scanf %%%c (pos. %d) is not legal FILE IO format letter",
+      *fp, fmt_pos); 
+     rv = FALSE;
+   }
+   fp++;
+  }
+done:
+ return(rv);
+}
+
+/*
+ * collect a dhbo number from input into num token global 
+ * returns F on error - if so num token invalid 
+ */
+static int32 collect_scanf_num(int32 *signc, FILE *f, int32 c, int32 base, int32 width)
+{
+ register char *wchp;
+
+ wchp = __numtoken; 
+ /* collect number */
+ if (c == '-' || c == '+')
+  {
+   /* minus only legal for %d (and real) format(s) */
+   if (base != BDEC)
+    {
+     __sgfinform(3008,
+      "numeric non decimal (%%d) scanf format illegally begins with sign");
+     return(FALSE);
+    } 
+   *signc = c;
+   if (width > 0) --width;
+   c = scanf_getc(f);
+  }
+ else *signc = ' ';
+
+ for (;;)
+  {
+   if (isspace(c) || c == EOF) break;
+   /* skip _ space holder */
+   if (c != '_')
+    {
+     /* non number char ends number if not ended with white space */
+     if ((c = __is_vdigit(c, base)) < 0) break;
+
+     if (base == BDEC)
+      {
+       /* SJM 05/14/04 - decimal format ended by non beginning xz, i.e. */ 
+       /* it is assumed to be start of a string */
+       if ((c == 'x' || c == 'z') && wchp != __numtoken) break;  
+      }
+     *wchp++ = c;
+    }
+   c = scanf_getc(f);
+   if (width > 0 && --width == 0) break;
+  }
+ *wchp = '\0';
+ if (wchp == __numtoken) return(FALSE);
+ /* SJM 05/14/04 - if ends with non white space, need to start reading with */ 
+ /* ending char */
+ if (!isspace(c) && c != EOF) scanf_ungetc(c, f);
+
+ return(TRUE);
+}
+
+/*
+ * collect a ral (f,g, e, and t) real number from input into num token global 
+ * returns F on error - if so dret not changed
+ */
+static int32 collect_scanf_realnum(double *dret, FILE *f, int32 c, int32 width,
+ int32 fch)
+{
+ register char *wchp;
+ double d1;
+ int32 got_dot, got_e, signc, unit, errnum;
+ char *endp;
+
+ /* collect the string */
+ wchp = __numtoken; 
+ if (c == '-' || c == '+')
+  { signc = c; if (width > 0) --width; c = scanf_getc(f); }
+ else signc = ' ';
+ got_dot = got_e = 0;
+ for (;;)
+  {
+   if (isdigit(c)) *wchp++ = c;
+   else if (got_e && wchp[-1] == 'e' && (c == '-' || c == '+'))
+    *wchp++ = c;
+   else if (!got_e && (c == 'e' || c == 'E'))
+    { *wchp++ = 'e'; got_e = got_dot = 1; }
+   else if (c == '.' && !got_dot) { *wchp++ = c; got_dot = 1; }
+   else break;
+
+   if ((c = scanf_getc(f)) == EOF) break;
+   if (width > 0 && --width == 0) break;
+  }
+ *wchp = '\0';
+ /* terminate if no characters collected */
+ if (wchp == __numtoken) return(FALSE);
+
+ /* SJM 05/14/04 - if ends with non white space, need to start reading with */ 
+ /* ending char */
+ if (!isspace(c) && c != EOF) scanf_ungetc(c, f);
+
+ d1 = __my_strtod(__numtoken, &endp, &errnum);   
+ if (errnum != 0 || *endp != '\0') return(FALSE);
+ if (signc == '-') d1 = -d1;
+
+ /* SJM 09/24/03 - LOOKATME - maybe should only do if not suppresed */
+ if (fch == 't')
+  {
+   /* t format same as real except need to scale time format */ 
+   if (__inst_mod->mtime_units != __tfmt_units)
+    {
+     if (__inst_mod->mtime_units > __tfmt_units)
+      {
+       /* here d1 module ticks higher exp (more precision) - divide */  
+       unit = __inst_mod->mtime_units - __tfmt_units;
+       d1 /= __dbl_toticks_tab[unit];
+      }   
+     else
+      {
+       /* here d1 module ticks lower (less precision) - multiply */
+       unit = __tfmt_units - __inst_mod->mtime_units;
+       d1 *= __dbl_toticks_tab[unit];
+      }
+    }
+  }
+ *dret = d1;
+ return(TRUE);
+}
+
+/*
+ * collect 'u' format binary 0/1 one word32 values onto top of pushed xstk
+ */
+static struct xstk_t *collect_ufmt_binval(FILE *f, struct expr_t *lhsx, int32 c)
+{
+ register int32 wi;
+ register word32 wrd;
+ int32 b1, b2, b3, b4;
+ struct xstk_t *xsp;
+
+ push_xstk_(xsp, lhsx->szu.xclen);
+ /* b part always 0 */
+ zero_allbits_(xsp->bp, xsp->xslen);
+ for (wi = 0; wi < wlen_(lhsx->szu.xclen); wi++)
+  {
+   b1 = (word32) c;
+   if ((c = scanf_getc(f)) == EOF) return(NULL);
+   b2 = (word32) c;
+   if ((c = scanf_getc(f)) == EOF) return(NULL);
+   b3 = (word32) c;
+   if ((c = scanf_getc(f)) == EOF) return(NULL);
+   b4 = (word32) c;
+#if (BYTE_ORDER == BIG_ENDIAN)
+   wrd = (b1 & 0xff) | ((b2 & 0xff) << 8) | ((b3 & 0xff) << 16)
+    | ((b4 & 0xff) << 24);
+#else
+   wrd = (b4 & 0xff) | ((b3 & 0xff) << 8) | ((b2 & 0xff) << 16)
+    | ((b1 & 0xff) << 24);
+#endif
+   xsp->ap[wi] = wrd;
+  }
+ return(xsp);
+}
+
+/*
+ * collect 'z' format binary 4 value 2 word32 values onto top of pushed xstk
+ */
+static struct xstk_t *collect_zfmt_binval(FILE *f, struct expr_t *lhsx,
+ int32 c2)
+{
+ register int32 wi;
+ register word32 wrd, wrd2;
+ int32 c, b1, b2, b3, b4;
+ struct xstk_t *xsp;
+
+ push_xstk_(xsp, lhsx->szu.xclen);
+ for (wi = 0; wi < wlen_(lhsx->szu.xclen); wi++)
+  {
+   /* binary format by convention is a/b pairs following PLI t_vecval */
+   b1 = (word32) c2;
+   if ((c = scanf_getc(f)) == EOF) return(NULL);
+   b2 = (word32) c;
+   if ((c = scanf_getc(f)) == EOF) return(NULL);
+   b3 = (word32) c;
+   if ((c = scanf_getc(f)) == EOF) return(NULL);
+   b4 = (word32) c;
+#if (BYTE_ORDER == BIG_ENDIAN)
+   wrd = (b1 & 0xff) | ((b2 & 0xff) << 8) | ((b3 & 0xff) << 16)
+    | ((b4 & 0xff) << 24);
+#else
+   wrd = (b4 & 0xff) | ((b3 & 0xff) << 8) | ((b2 & 0xff) << 16)
+    | ((b1 & 0xff) << 24);
+#endif
+   xsp->ap[wi] = wrd;
+
+   if ((c = scanf_getc(f)) == EOF) return(NULL);
+   b1 = (word32) c;
+   if ((c = scanf_getc(f)) == EOF) return(NULL);
+   b2 = (word32) c;
+   if ((c = scanf_getc(f)) == EOF) return(NULL);
+   b3 = (word32) c;
+   if ((c = scanf_getc(f)) == EOF) return(NULL);
+   b4 = (word32) c;
+#if (BYTE_ORDER == BIG_ENDIAN)
+   wrd2 = (b1 & 0xff) | ((b2 & 0xff) << 8) | ((b3 & 0xff) << 16)
+    | ((b4 & 0xff) << 24);
+#else
+   wrd2 = (b4 & 0xff) | ((b3 & 0xff) << 8) | ((b2 & 0xff) << 16)
+    | ((b1 & 0xff) << 24);
+#endif
+   xsp->bp[wi] = wrd2;
+  }
+ return(xsp);
+}
+
+/*
+ * convert scanf stren name to one byte stren value
+ * return byte value or 0 (impossible stren) on error
+ *
+ * since scanf can only assign to regs, stren has stren removed
+ * but must check for legal and then remove stren
+ */
+static int32 cnvt_scanf_stnam_to_val(char *s) 
+{
+ int32 stval, st0, st1;
+ char val;
+ char stren[RECLEN];
+
+ if (strcmp(s, "HiZ") == 0) return(2);
+
+ val = s[2];
+ strncpy(stren, s, 2);  
+ stren[2] = '\0';
+ if (strcmp(stren, "Su") == 0) st0 = st1 = ST_SUPPLY;
+ else if (strcmp(stren, "St") == 0) st0 = st1 = ST_STRONG;
+ else if (strcmp(stren, "Pu") == 0) st0 = st1 = ST_PULL;
+ else if (strcmp(stren, "La") == 0) st0 = st1 = ST_LARGE;
+ else if (strcmp(stren, "We") == 0) st0 = st1 = ST_WEAK;
+ else if (strcmp(stren, "Me") == 0) st0 = st1 = ST_MEDIUM;
+ else if (strcmp(stren, "Sm") == 0) st0 = st1 = ST_SMALL;
+ else return(-1);
+
+ /* only use of Z aready eliminated */
+ /* notice st1 and st0 must be same here */
+ switch(val) {
+  case '0':
+   stval = 0 | (st1 << 2) | (st0 << 5);
+   break; 
+  case '1':
+   stval = 1 | (st1 << 2) | (st0 << 5);
+   break;
+  case 'X':
+   stval = 3 | (st1 << 2) | (st0 << 5);
+   break;
+  case 'L':
+   stval = 3 | (st0 << 5); 
+   break;
+  case 'H':
+   stval = 3 | (st1 << 2); 
+   break;
+  default: return(0);
+ } 
+ return(stval);
+}
+
diff --git a/src/v_ex2.c b/src/v_ex2.c
new file mode 100644
index 0000000..8f7f274
--- /dev/null
+++ b/src/v_ex2.c
@@ -0,0 +1,6974 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * run time execution routines - rhs evaluation and readmem
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include <ctype.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+/* REMOVEME - no longer supporting SunOS - maybe needed for hpux? */
+#if defined(__sparc) && !defined(__SVR4)  
+extern int32 tolower(int32);
+extern ungetc(int32 c, FILE *);
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void prep_bld_monit_dces(struct expr_t *, int32);
+static void linkon_monit_dce(struct net_t *, int32, int32, int32,
+ struct itree_t *);
+static int32 chk_monits_chged(register struct dceauxlst_t *);
+static int32 chk_rm_rng_legal(int32, int32, int32, char *);
+static void push_bsel(struct expr_t *);
+static void push_psel(register struct expr_t *);
+static int32 mdata_gettok(FILE *, int32);
+static int32 rmrd_comment(FILE *);
+static int32 mdata_rdhex(FILE *, int32);
+static int32 is_mdataxdigit(int32);
+static int32 mdata_rdbin(FILE *, int32);
+static int32 rm_getc(FILE *);
+static void rm_ungetc(int32, FILE *);
+static int32 is_mdatabit(int32);
+static void do_srm_xtrct(struct expr_t *, int32, struct net_t *, int32, int32,
+ int32, int32, int32);
+static double stdnorm_dev(int32 *);
+static double gamma_dev(double, int32 *);
+static int32 poisson_dev(int32, int32 *);
+static double log_gamma(double);
+static void lxqcol(register struct xstk_t *, register struct xstk_t *,
+ register struct xstk_t *, int32, int32, int32);
+static void eval_unary(struct expr_t *);
+static void eval_wide_unary(register struct expr_t *,
+ register struct xstk_t *);
+static void eval_binary(struct expr_t *);
+static void eval_wide_binary(struct expr_t *, register struct xstk_t *,
+ register struct xstk_t *);
+static void bitmwrshift(register word32 *, register int32, register int32);
+static void bitmwlshift(register word32 *, register int32, register int32);
+static void wrdmwrshift(register word32 *, register int32, register int32);
+static void wrdmwlshift(register word32 *, register int32, register int32);
+static int32 sgn_linc(register word32 *, int32);
+static int32 accmuladd32(word32 *, word32 *, word32, word32 *, int32);
+static void mpexpr_zdiv(word32 *, word32 *, word32 *, int32, word32 *, int32);
+static int32 ztrim(word32 *, int32);
+static void dadd(word32 *, word32 *, int32, int32);
+static int32 dsub(word32 *, int32, word32 *, int32, int32, int32);
+static void dmul(word32 *, int32, word32 *, int32, word64);
+static int32 ldiv_cmp(register word32 *, register word32 *, int32);
+static void xchg_stk(int32, int32);
+static double uniform(int32 *, sword32, sword32);
+static sword32 rtl_dist_uniform(int32 *, sword32, sword32);
+
+/* extern prototypes (maybe defined in this module) */
+extern char *__my_realloc(char *, int32, int32);
+extern char *__my_malloc(int32);
+extern void __my_free(char *, int32);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern struct xstk_t *__eval2_xpr(struct expr_t *);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern void __ld_stval(register word32 *, register word32 *, register byte *, int32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char __to_baselet(int32);
+extern struct dcevnt_t *__alloc_dcevnt(struct net_t *);
+extern FILE *__tilde_fopen(char *, char *);
+extern word32 __wrd_redxor(word32);
+extern double __cnvt_stk_to_real(struct xstk_t *, int32);
+extern char *__bld_lineloc(char *, word32, int32);
+extern char *__to_timstr(char *, word64 *);
+extern char *__vval_to_vstr(word32 *, int32, int32 *);
+extern char * __get_eval_cstr(struct expr_t *, int32 *);
+extern word32 __lsub(register word32 *, register word32 *, register word32 *,
+ int32);
+extern void __st_perinst_val(union pck_u pckv, int32, register word32 *,
+ register word32 *);
+
+extern void __start_monitor(struct st_t *);
+extern void __start_fmonitor(struct st_t *);
+extern void __alloc_1instdce_prevval(struct dcevnt_t *);
+extern void __init_1instdce_prevval(struct dcevnt_t *);
+extern int32 __get_dcewid(struct dcevnt_t *, struct net_t *);
+extern int32 __get_pcku_chars(int32, int32);
+extern void __exec_strobes(void);
+extern void __exec_fmonits(void);
+extern void __exec_monit(struct dceauxlst_t *, int32);
+extern void __ld_wire_sect(word32 *, word32 *, struct net_t *, register int32,
+ register int32);
+extern void __grow_tevtab(void);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __alloc_xsval(struct xstk_t *, int32);
+extern void __ld_wire_val(register word32 *, register word32 *,
+ struct net_t *);
+extern void __ld_perinst_val(register word32 *, register word32 *,
+ union pck_u, int32);
+extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
+extern void __ld_bit(register word32 *, register word32 *,
+ register struct net_t *, int32);
+extern void __ld_arr_val(register word32 *, register word32 *, union pck_u,
+ int32, int32, int32);
+extern void __ld_psel(register word32 *, register word32 *,
+ register struct net_t *, int32, int32);
+extern void __rhspsel(register word32 *, register word32 *, register int32,
+ register int32);
+extern void __exec_readmem(struct expr_t *, int32);
+extern void __exec_sreadmem(struct expr_t *, int32);
+extern void __exec_sfrand(struct expr_t *);
+extern void __ld_addr(word32 **, word32 **, register struct net_t *);
+extern void __luminus(word32 *, word32 *, int32);
+extern int32 __is_lnegative(word32 *, int32); 
+extern word32 __cp_lnegate(word32 *, register word32 *, int32);
+extern word32 __inplace_lnegate(register word32 *, int32);
+extern void __lunredand(int32 *, int32 *, word32 *, word32 *, int32);
+extern void __lunredor(int32 *, int32 *, word32 *, word32 *, int32);
+extern void __lunredxor(int32 *, int32 *, word32 *, word32 *, int32);
+extern void __mwrshift(word32 *, word32, int32);
+extern void __arith_mwrshift(word32 *, word32, int32);
+extern void __mwlshift(word32 *, word32, int32);
+extern int32 __cvt_lngbool(word32 *, word32 *, int32); 
+extern int32 __do_widecmp(int32 *, register word32 *, register word32 *,
+ register word32 *, register word32 *, int32);
+extern int32 __do_sign_widecmp(int32 *, register word32 *, register word32 *,
+ register word32 *, register word32 *, int32);
+extern int32 __do_xzwidecmp(register word32 *, register word32 *,
+ register word32 *, register word32 *, int32);
+extern void __ladd(word32 *, word32 *, word32 *, int32);
+extern void __lmult(register word32 *, register word32 *, register word32 *,
+ int32);
+extern void __sgn_lmult(register word32 *, register word32 *,
+ register word32 *, int32);
+extern void __ldivmod(word32 *, word32 *, word32 *, int32, int32);
+extern void __sgn_ldivmod(register word32 *, register word32 *,
+ register word32 *, int32, int32);
+extern void __ldivmod2(word32 *, word32 *, word32 *, word32 *, int32);
+extern void __by16_ldivmod(word32 *, word32 *, word32 *, word32, int32);
+
+extern void __fio_do_disp(register struct expr_t *, int32, int32, char *);
+extern void __do_disp(register struct expr_t *, int32);
+extern void __get_cor_range(register int32, union intptr_u, register int32 *,
+ register int32 *);
+extern int32 __get_arrwide(struct net_t *);
+extern void __exec_sysfunc(register struct expr_t *);
+extern void __exec_func(register struct expr_t *);
+extern void __lhsbsel(register word32 *, register int32, word32);
+extern void __cp_sofs_wval(register word32 *, register word32 *,
+ register int32, register int32);
+extern void __getarr_range(struct net_t *, int32 *, int32 *, int32 *);
+extern void __my_fclose(FILE *);
+extern void __to_dhboval(int32, int32);
+extern void __sizchgxs(register struct xstk_t *, int32);
+extern void __sgn_xtnd_widen(struct xstk_t *, int32);
+extern void __sgn_xtnd_wrd(struct xstk_t *, int32);
+extern void __sizchg_widen(register struct xstk_t *, int32);
+extern void __narrow_sizchg(register struct xstk_t *, int32);
+extern void __narrow_to1bit(register struct xstk_t *);
+
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern int32 __trim1_0val(word32 *, int32);
+extern void __lhspsel(register word32 *, register int32, register word32 *,
+ register int32);
+extern int32 __vval_is1(register word32 *, int32);
+extern int32 __get_eval_word(struct expr_t *, word32 *);
+extern void __exec2_proc_assign(struct expr_t *, register word32 *,
+ register word32 *);
+extern void __rhs_concat(struct expr_t *);
+extern void __eval_qcol(register struct expr_t *);
+extern void __eval_realrealqcol(register struct expr_t *);
+extern void __eval_realregqcol(register struct expr_t *);
+extern void __eval_regrealqcol(register struct expr_t *);
+extern void __lunbitnot(word32 *, word32 *, int32);
+extern int32 __set_binxresult(word32 *, word32 *, word32 *, word32 *, int32);
+extern void __lbitand(word32 *, word32 *, word32 *, word32 *, int32);
+extern void __lbitor(word32 *, word32 *, word32 *, word32 *, int32);
+extern void __lbitxor(word32 *, word32 *, word32 *, word32 *, int32);
+extern void __lbitxnor(word32 *, word32 *, word32 *, word32 *, int32);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern int32 __omitxz_widenoteq(register word32 *, register word32 *,
+ register word32 *, register word32 *, int32);
+extern void __dcelst_on(struct dceauxlst_t *);
+extern void __dcelst_off(struct dceauxlst_t *);
+extern void init_dcelst(struct dceauxlst_t *); 
+extern void __dce_turn_chg_store_on(struct mod_t *, struct dcevnt_t *, int32);  
+extern void __do_rm_reading(FILE *, int32, struct net_t *, int32, int32,
+ int32, int32, int32);
+extern void __wakeup_delay_ctrls(register struct net_t *, register int32,
+ register int32);
+extern void __add_select_nchglst_el(register struct net_t *, register int32,
+ register int32);
+extern void __add_dmpv_chglst_el(struct net_t *);
+extern void __st_arr_val(union pck_u, int32, int32, int32, register word32 *,
+ register word32 *);
+extern void __chg_st_arr_val(union pck_u, int32, int32, int32,
+ register word32 *, register word32 *);
+
+extern void __cvsim_msg(char *, ...);
+/* SJM - not used -extern void __pv_err(int32, char *, ...); */
+extern void __pv_warn(int32, char *,...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __pv_fwarn(int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __inform(int32, char *, ...);
+
+extern word32 __masktab[];
+extern char __pv_ctab[];
+
+/*
+ * MONITOR/STROBE SETUP AND EXECUTION ROUTINES
+ */
+
+/*
+ * set up a new monitor argument list
+ * every expression in $monitor has event trigger added
+ *
+ * SJM 06/20/02 - change so this exec routine assumes dce's built if in
+ * source - only builds if from interactive
+ * this runs with itree context set
+ */
+extern void __start_monitor(struct st_t *stp)
+{
+ register struct expr_t *alxp;
+ int32 argi;
+ byte *argisvtab;
+ struct tskcall_t *tkcp;
+ struct mod_t *imdp;
+ struct monaux_t *mauxp;
+
+ tkcp = &(stp->st.stkc);
+
+ /* turn off all monitor events associated with previous monitor (1 inst.) */
+ /* LOOKATME - possible minor memory leak here */
+ if (__monit_dcehdr != NULL)
+  {
+   __dcelst_off(__monit_dcehdr);
+   __monit_dcehdr = NULL;
+  }
+
+ /* turn off monitor by $monitor() - empty arg list */ 
+ if (tkcp->targs == NULL)
+  { __monit_stp = NULL; __monit_itp = NULL; return; }
+
+ /* DBG remove -- */
+ if (tkcp->tkcaux.mauxp == NULL || tkcp->tkcaux.mauxp->argisvtab == NULL)
+  __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ mauxp = tkcp->tkcaux.mauxp;
+ argisvtab = (byte *) mauxp->argisvtab;
+
+ __monit_stp = stp;
+ /* if $monitor in multiply instantiated module, last one executed is */
+ /* current instance */
+ __monit_itp = __inst_ptr;
+ __cur_fmon = NULL;
+ 
+ if (!mauxp->dces_blt)
+  {
+   register int32 ii;
+
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    {
+     __push_itstk(__inst_mod->moditps[ii]);
+
+     __monit_dcehdr = NULL;
+     alxp = tkcp->targs;
+     for (argi = 0; alxp != NULL; alxp = alxp->ru.x, argi++)
+      {
+       prep_bld_monit_dces(alxp->lu.x, (int32) argisvtab[argi]);
+      }
+     mauxp->mon_dcehdr[ii] = __monit_dcehdr; 
+
+     __pop_itstk();
+    }
+   mauxp->dces_blt = TRUE;
+  }
+ __monit_dcehdr = mauxp->mon_dcehdr[__inum];
+ /* turn on (enable) all dces in list built during prep - off when built */ 
+ __dcelst_on(__monit_dcehdr);
+
+ /* SJM 01/02/03 - must re-initialize monit dces previous value if present */
+ init_dcelst(__monit_dcehdr);
+
+ /* changing $monitor (including 1st) always trigger 1 output */
+ /* no warning since normal to turn off monitoring with $monitor() */
+ __slotend_action |= SE_MONIT_CHG;
+ imdp = __inst_mod;
+ if (imdp->flatinum > 1)
+  __sgfinform(441,
+   "$monitor invoked in module %s that is instantiated multiple times",
+   imdp->msym->synam);
+}
+
+/*
+ * initialize dce list for monitor form that is always one inst
+ */
+extern void init_dcelst(struct dceauxlst_t *dcehdr) 
+{
+ register struct dceauxlst_t *dclp;
+
+ for (dclp = dcehdr; dclp != NULL; dclp = dclp->dclnxt)
+  {
+   /* notice if no previous value, this detects it and does nothing */ 
+   if (dclp->ldcep->prevval.bp != NULL) __init_1instdce_prevval(dclp->ldcep);
+  }
+}
+
+/* 
+ * enable all dces in dceaux list
+ */
+extern void __dcelst_on(struct dceauxlst_t *dcehdr)
+{
+ register struct dceauxlst_t *dclp;
+ register struct net_t *np;
+
+ for (dclp = dcehdr; dclp != NULL; dclp = dclp->dclnxt)
+  {
+   dclp->ldcep->dce_off = FALSE; 
+   np = dclp->ldcep->dce_np;
+   /* SJM 07/19/02 - turn on so now records chges - if nld nil won't record */
+   /* until first time here */
+   if (np->ntyp >= NONWIRE_ST) np->nchg_has_dces = TRUE;
+
+   /* SJM 11/25/02 - never turn in src dces on/off */
+   /* DBG remove -- */
+   if (dclp->ldcep->dce_typ == DCE_INST
+    || dclp->ldcep->dce_typ == DCE_RNG_INST) __misc_terr(__FILE__, __LINE__); 
+   /* --- */
+   /* DBG remove -- */
+   if (!dclp->ldcep->dce_1inst) __misc_terr(__FILE__, __LINE__);
+   /* --- */ 
+   
+   /* since adding dce, if wire and no lds, must turn off all chged */ 
+   /* that prevents recording since now must record for wire dce wakeup */
+   /* SJM 11/25/02 - since only 1 inst match forms can be turned on/off */
+   /* just turn on the match itp here */
+   if (np->nlds == NULL && np->ntyp < NONWIRE_ST) 
+    {
+     np->nchgaction[dclp->ldcep->dce_matchitp->itinum] &= ~(NCHG_ALL_CHGED);
+    }
+  }
+}
+
+/* 
+ * disable all dces in dceaux list
+ *
+ * notice not stopping recording of changes since expect to be activated again
+ */
+extern void __dcelst_off(struct dceauxlst_t *dcehdr)
+{
+ register struct dceauxlst_t *dclp;
+
+ for (dclp = dcehdr; dclp != NULL; dclp = dclp->dclnxt)
+  {
+   dclp->ldcep->dce_off = TRUE; 
+  }
+}
+
+/*
+ * set up a new fmonitor argument list
+ *
+ * every expression in $fmonitor has event trigger added
+ * this runs with itree context set
+ */
+extern void __start_fmonitor(struct st_t *stp)
+{
+ register struct expr_t *alxp;
+ register struct dceauxlst_t *dclp;
+ int32 argi;
+ byte *argisvtab;
+ struct tskcall_t *tkcp;
+ struct fmonlst_t *fmonp;
+ struct fmselst_t *fmsep;
+ struct dceauxlst_t *sav_dclp;
+ struct dcevnt_t *dcep;
+ struct monaux_t *mauxp;
+
+ tkcp = &(stp->st.stkc);
+ /* ignore first mc channel descripter since not involved in monitoring */
+ if (tkcp->targs != NULL) alxp = tkcp->targs->ru.x; else alxp = NULL;
+
+ /* $fmonitor with no argument list does nothing - ignore with warn */
+ if (alxp == NULL)
+  {
+   __sgfwarn(639,
+    "execution of $fmonitor with one argument has no effect - ignored"); 
+   return;
+  } 
+
+ /* DBG remove -- */
+ if (tkcp->tkcaux.mauxp == NULL || tkcp->tkcaux.mauxp->argisvtab == NULL)
+  __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ mauxp = tkcp->tkcaux.mauxp;
+ argisvtab = (byte *) mauxp->argisvtab;
+ 
+ /* allocate and link on fmonitor record for this fmonitor */
+ fmonp = (struct fmonlst_t *) __my_malloc(sizeof(struct fmonlst_t));
+ fmonp->fmon_stp = stp;
+ fmonp->fmon_itp = __inst_ptr;
+ fmonp->fmonnxt = NULL;
+ if (__fmon_hdr == NULL) __fmon_hdr = fmonp; else __fmon_end->fmonnxt = fmonp; 
+ __fmon_end = fmonp; 
+ __cur_fmon = fmonp;
+
+ /* SJM 06/20/02 - new algorithm only build if call from interactive mode */
+ /* works because if any vm insn gen, no interactive */
+ if (!mauxp->dces_blt)
+  {
+   register int32 ii;
+
+   /* save $monit dce list */
+   sav_dclp = __monit_dcehdr; 
+   __monit_dcehdr = NULL; 
+
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    {
+     /* build the dces - notice build now starts each monit dce off*/
+     __monit_dcehdr = NULL;
+     for (argi = 1; alxp != NULL; alxp = alxp->ru.x, argi++)
+       prep_bld_monit_dces(alxp->lu.x, (int32) argisvtab[argi]);
+
+     /* SJM 08/26/02 - need to indicate monit is fmonit */ 
+     for (dclp = __monit_dcehdr; dclp != NULL; dclp = dclp->dclnxt)
+      {
+       dcep = dclp->ldcep;
+       dcep->is_fmon = TRUE;
+
+      }
+
+     mauxp->mon_dcehdr[ii] = __monit_dcehdr; 
+    }
+   mauxp->dces_blt = TRUE;
+   __monit_dcehdr = sav_dclp;
+  }
+ fmonp->fmon_dcehdr = mauxp->mon_dcehdr[__inum];
+
+ /* turn on - for fmonitor nothing to turn off */
+ __dcelst_on(mauxp->mon_dcehdr[__inum]);
+
+ /* SJM 01/02/03 - must re-initialize fmonit dces previous value if presetn */
+ init_dcelst(mauxp->mon_dcehdr[__inum]); 
+
+ dclp = mauxp->mon_dcehdr[__inum];
+ for (; dclp != NULL; dclp = dclp->dclnxt)
+  {
+   dclp->ldcep->dceu2.dce_fmon = __cur_fmon;
+  }
+
+ /* add to triggered this time list since always write first time seen */ 
+ if (__fmse_freelst == NULL) 
+  fmsep = (struct fmselst_t *) __my_malloc(sizeof(struct fmselst_t)); 
+ else { fmsep = __fmse_freelst; __fmse_freelst = __fmse_freelst->fmsenxt; } 
+ fmsep->fmsenxt = NULL;
+
+ fmsep->fmon = fmonp; 
+ fmonp->fmse_trig = fmsep; 
+ fmonp->fmon_forcewrite = TRUE;
+ if (__fmonse_hdr == NULL) __fmonse_hdr = fmsep;
+ else __fmonse_end->fmsenxt = fmsep; 
+ __fmonse_end = fmsep;
+ /* changing $fmonitor (including 1st) always trigger 1 output */
+ __slotend_action |= SE_FMONIT_TRIGGER;
+}
+
+/*
+ * build the dces for each monit/fmonit in source once 
+ * then assign list when enable and turn off list when replaced
+ *
+ * SJM 06/21/02 - new algorithm build dce list for all in src (f)monit
+ * during prep and activate/deactive from execution
+ */
+extern void __prep_insrc_monit(struct st_t *stp, int32 fmon_type)
+{
+ register int32 ii;
+ register struct expr_t *alxp;
+ register struct dceauxlst_t *dclp;
+ int32 argi;
+ byte *argisvtab;
+ struct tskcall_t *tkcp;
+ struct monaux_t *mauxp;
+ char s1[RECLEN];
+
+ tkcp = &(stp->st.stkc);
+ /* ignore first mc channel descripter since not involved in monitoring */
+ /* ignore first mc channel descripter since not involved in monitoring */
+ /* AIV 06/25/05 - must check if fmonit if not first arg is not decriptor */
+ /* was skipping first arg to $monitor */ 
+ if (fmon_type) 
+  {
+   if (tkcp->targs != NULL) alxp = tkcp->targs->ru.x; else alxp = NULL;
+  }
+ else
+  {
+   if (tkcp->targs != NULL) alxp = tkcp->targs->lu.x; else alxp = NULL;
+  }
+ 
+ if (fmon_type) strcpy(s1, "$fmonitor"); else strcpy(s1, "$monitor");
+
+ /* $monitor/$fmonitor with no args - does nothing - ignore with warn */
+ if (alxp == NULL)
+  {
+   /* SJM - 05/14/04 - monitor with no args turns off monitor - no warn */
+   return;
+  } 
+ /* DBG remove -- */
+ if (tkcp->tkcaux.mauxp == NULL || tkcp->tkcaux.mauxp->argisvtab == NULL)
+  __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ mauxp = tkcp->tkcaux.mauxp;
+ argisvtab = (byte *) mauxp->argisvtab;
+
+ for (ii = 0; ii < __inst_mod->flatinum; ii++)
+  {
+   __push_itstk(__inst_mod->moditps[ii]);
+
+   __monit_dcehdr = NULL;
+   argi = 0;
+   for (alxp = tkcp->targs; alxp != NULL; alxp = alxp->ru.x, argi++)
+    {
+     prep_bld_monit_dces(alxp->lu.x, (int32) argisvtab[argi]);
+    }
+   if (fmon_type)
+    {
+     /* SJM 08/26/02 - need to indicate monit is fmonit */ 
+     for (dclp = __monit_dcehdr; dclp != NULL; dclp = dclp->dclnxt)
+      {
+       dclp->ldcep->is_fmon = TRUE;
+      }
+    }
+   mauxp->mon_dcehdr[ii] = __monit_dcehdr; 
+
+   __pop_itstk(); 
+  } 
+ mauxp->dces_blt = TRUE;
+ __monit_dcehdr = NULL;
+}
+
+/*
+ * during design preparation build monitor dces for every possible
+ * instance (also non prep version for when monit added from iact mode)
+ */
+static void prep_bld_monit_dces(struct expr_t *xp, int32 argisvfmt)  
+{
+ struct net_t *np;
+ int32 biti, bitj;
+ word32 *wp;
+ struct expr_t *idndp, *ndx;
+ struct expr_t *fax;
+ struct itree_t *ref_itp;
+ 
+ ref_itp = __inst_ptr;
+ switch ((byte) xp->optyp) {
+  case GLBREF:
+   idndp = xp; 
+   /* for global - do not need ref. point - just link on 1 (because only 1 */
+   /* monit call from 1 inst.) target wire */
+   biti = bitj = -1;
+glb_dce:
+   __xmrpush_refgrp_to_targ(idndp->ru.grp);
+   np = idndp->lu.sy->el.enp;
+   linkon_monit_dce(np, biti, bitj, argisvfmt, ref_itp);
+   __pop_itstk();
+   break;
+  case ID:
+   idndp = xp; 
+   np = xp->lu.sy->el.enp;
+   linkon_monit_dce(np, -1, -1, argisvfmt, ref_itp);
+   break;
+  /* SJM 05/18/00 - must do nothing for reals */ 
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   return;
+  case LSB:
+   idndp = xp->lu.x; 
+   np = idndp->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   /* for monits, any reg or non scalared wire must trigger on any chg */
+   if (ndx->optyp == NUMBER)
+    {
+     wp = &(__contab[ndx->ru.xvi]);
+     if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
+    }
+   else if (ndx->optyp == ISNUMBER)
+    {
+     wp = &(__contab[ndx->ru.xvi]);
+     wp = &(wp[2*__inum]);
+     /* need length for IS number because can be wider - but get low */
+     if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
+    }
+   else
+    {
+     /* notice for monitor and dctrl event change, variable here is legal */
+     /* and implies change for index and trigger on all bits of variable */
+     prep_bld_monit_dces(ndx, argisvfmt);
+     biti = -1;
+    }
+   bitj = biti;
+   if (biti != -1 && !np->vec_scalared) biti = bitj = -1;
+   if (idndp->optyp == GLBREF) goto glb_dce;
+   linkon_monit_dce(np, biti, biti, argisvfmt, ref_itp);
+   break;
+  case PARTSEL:
+   idndp = xp->lu.x; 
+   np = idndp->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   /* know part select never IS */
+   wp = &(__contab[ndx->lu.x->ru.xvi]);
+   biti = (int32) wp[0];
+   wp = &(__contab[ndx->ru.x->ru.xvi]);
+   bitj = (int32) wp[0];
+
+   if (!np->vec_scalared) biti = bitj = -1;
+   if (idndp->optyp == GLBREF) goto glb_dce;
+   linkon_monit_dce(np, biti, bitj, argisvfmt, ref_itp);
+   break;
+  case FCALL:
+   /* if any arguments of system or user functions change, monitor triggers */
+   /* notice $time function do not have arguments */
+   for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+    {
+     prep_bld_monit_dces(fax->lu.x, argisvfmt);
+    }
+   break;
+  case LCB:
+   for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+    {
+     prep_bld_monit_dces(fax->lu.x, argisvfmt);
+    }
+   break;
+  default:
+   if (xp->lu.x != NULL) prep_bld_monit_dces(xp->lu.x, argisvfmt);
+   if (xp->ru.x != NULL) prep_bld_monit_dces(xp->ru.x, argisvfmt);
+   break;
+ } 
+}
+
+/*
+ * link on a special (simplified) monitor dce
+ * IS form never possible here and always local, have moved to dest.
+ *
+ * if xmr know np is already dest. and itree place is dest.
+ *
+ * monitor dce must go on dest. since when value changed that wire
+ * is traced, final eval. is separate unrelated code
+ * this is never dce_itp since just put on one right xmr targ.
+ * and moved to xmr target above
+ * goes on front but after andy dmpvar dces
+ * also for fmonitor - different end of slot list
+ *
+ * SJM 01/06/03 - only callable during prep since all monit dces in src
+ * build here or from interactive mode
+ */
+static void linkon_monit_dce(struct net_t *np, int32 biti, int32 bitj,
+ int32 argisvfmt, struct itree_t *ref_itp)
+{
+ struct dcevnt_t *dcep;
+ struct dceauxlst_t *dclp;
+
+ /* allocate, init, and fill the fields */
+ dcep = __alloc_dcevnt(np);
+ if (biti == -1) dcep->dce_typ = DCE_MONIT;
+ else
+  {
+   dcep->dce_typ = DCE_RNG_MONIT;
+   dcep->dci1 = biti;
+   dcep->dci2.i = bitj;
+  }
+ /* dce's assume on but here only turned on when activated by exec */
+ dcep->dce_off = TRUE;
+
+ /* non v format strengths for monitor only output if value part changes */ 
+ if (np->n_stren && argisvfmt) dcep->dce_nomonstren = FALSE;
+
+ /* this is instance where dce trigger must occur for xmr different from */
+ /* itree location in which (f)monitor execed */
+ dcep->dce_matchitp = __inst_ptr;
+ dcep->dce_refitp = ref_itp;
+ dcep->dce_1inst = TRUE;
+ dcep->dceu2.dce_fmon = __cur_fmon;
+ 
+ /* link this on front */
+ dcep->dcenxt = np->dcelst;
+ np->dcelst = dcep;
+ 
+ /* allocate the prev val fields and set to cur. value of wire for inst. */
+ /* for monits always need prev. val. field because set flag if any */
+ /* change and change may get filtered out later */
+ /* except for entire reg, do not need */
+ __alloc_1instdce_prevval(dcep);
+ /* SJM 05/04/05 - can initialize since for cver-cc, not linked to .bss yet */
+
+ /* then link on undo/chg list - fmon's never undone except for :reset */
+ dclp = (struct dceauxlst_t *) __my_malloc(sizeof(struct dceauxlst_t));
+ dclp->ldcep = dcep; 
+ dclp->dclnxt = __monit_dcehdr;
+ __monit_dcehdr = dclp;
+
+ if (__iact_state)
+  {
+   /* since no dce, no loads, and no dmpvars must always turn chg store on */
+   if (!dcep->dce_np->nchg_nd_chgstore)
+    {
+     /* this also causes regen of all mod entire procedural iops since net */
+     /* need to be compiled with change form on everywhere */
+     __dce_turn_chg_store_on(__inst_mod, dcep, TRUE);  
+    }
+   /* SJM 02/06/03 - may have npps but not dces so must turn this on */
+   /* since nchg nd chgstore on, know nchg action right */
+   if (np->ntyp >= NONWIRE_ST) np->nchg_has_dces = TRUE;
+  } 
+
+ /* -- DBG REMOVE
+ {
+  struct dceauxlst_t *dclp2, *dclp3; 
+
+  for (dclp2 = __monit_dcehdr; dclp2 != NULL; dclp2 = dclp2->dclnxt)
+   {
+    for (dclp3 = dclp2->dclnxt; dclp3 != NULL; dclp3 = dclp3->dclnxt)
+     if (dclp2 == dclp3)
+      {
+       __dbg_msg("^^^ monitor dclp duplicate addr %lx\n", dclp2);
+       __misc_terr(__FILE__, __LINE__);
+      }
+   }
+ }
+ --- */
+}
+
+/*
+ * get width in bits of a dcep range or wire
+ */
+extern int32 __get_dcewid(struct dcevnt_t *dcep, struct net_t *np)
+{
+ if (dcep->dci1 == -2) return(1);
+ if (dcep->dci1 == -1) return(np->nwid);
+ return(dcep->dci1 - dcep->dci2.i + 1);  
+}
+
+/*
+ * get number of packed bytes for ld peri and st peri access 
+ */
+extern int32 __get_pcku_chars(int32 blen, int32 insts)
+{
+ /* SJM 10/14/99 - now storing all scalars as one byte */
+ if (blen == 1) return(insts);
+ /* SJM 07/15/00 - no longer packing 2 to 16 bits */
+ return(2*insts*wlen_(blen)*WRDBYTES);
+}
+
+/*
+ * execute the strobe statements at end of time slot
+ * only called if at least one and by end of time slot functionality
+ * of $display
+ *
+ * need fstrobes here too
+ */
+extern void __exec_strobes(void)
+{
+ register struct strblst_t *strblp;
+ int32 base, sav_slin_cnt, sav_sfnam_ind;
+ struct st_t *stp;
+ struct tskcall_t *tkcp;
+ struct expr_t *tkxp;
+ struct systsk_t *stbp;
+
+ sav_slin_cnt = __slin_cnt;
+ sav_sfnam_ind = __sfnam_ind;
+ for (strblp = __strobe_hdr; strblp != NULL; strblp = strblp->strbnxt)
+  {
+   stp = strblp->strbstp;
+   __slin_cnt = stp->stlin_cnt;
+   __sfnam_ind = stp->stfnam_ind;
+
+   /* notice here cur. itp does not need to be preserved */
+   __push_itstk(strblp->strb_itp);
+   tkcp = &(stp->st.stkc);
+   tkxp = tkcp->tsksyx;
+   stbp = tkxp->lu.sy->el.esytbp;
+
+   switch (stbp->stsknum) {
+    case STN_STROBE: base = BDEC; goto nonf_write;
+    case STN_STROBEH: base = BHEX; goto nonf_write;
+    case STN_STROBEB: base = BBIN; goto nonf_write;
+    case STN_STROBEO: base = BOCT;
+nonf_write:
+     __do_disp(tkcp->targs, base);
+     __cvsim_msg("\n");
+     break;
+    case STN_FSTROBE: base = BDEC; goto f_disp;
+    case STN_FSTROBEB: base = BBIN; goto f_disp;
+    case STN_FSTROBEH: base = BHEX; goto f_disp;
+    case STN_FSTROBEO:
+     base = BOCT;
+f_disp:
+     __fio_do_disp(tkcp->targs, base, TRUE, tkxp->lu.sy->synam);
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   stp->strb_seen_now = FALSE;
+   __pop_itstk();
+  }
+ /* free strobes all at once */
+ if (__strobe_hdr != NULL)
+  { __strobe_end->strbnxt = __strb_freelst; __strb_freelst = __strobe_hdr; }
+ __strobe_hdr = __strobe_end = NULL; 
+ __slin_cnt = sav_slin_cnt;
+ __sfnam_ind = sav_sfnam_ind;
+}
+
+/*
+ * execute all triggered during this time slot fmonitors
+ * LOOKATME - for now $monitoroff (on) does not effect fmonitor and iact -[num]
+ * also impossible
+ */
+extern void __exec_fmonits(void)
+{
+ register struct fmselst_t *fmsep;
+ struct fmonlst_t *fmonp;
+ struct st_t *sav_monit_stp;
+ struct itree_t *sav_monit_itp;
+
+ if (__fmonse_hdr == NULL) __arg_terr(__FILE__, __LINE__);
+ sav_monit_stp = __monit_stp;
+ sav_monit_itp = __monit_itp;
+ for (fmsep = __fmonse_hdr; fmsep != NULL; fmsep = fmsep->fmsenxt)
+  {
+   fmonp = fmsep->fmon;
+   __monit_stp = fmonp->fmon_stp; 
+   __monit_itp = fmonp->fmon_itp; 
+   __exec_monit(fmonp->fmon_dcehdr, (int32) (fmonp->fmon_forcewrite == 1));
+   /* turn off triggered since this time slot end change processed */
+   fmonp->fmse_trig = NULL;
+   fmonp->fmon_forcewrite = FALSE;
+   /* DBG remove --
+   if (__debug_flg)
+    {
+     __dbg_msg("+++ time %s: executing fmonitor at %s\n", __to_timstr(__xs,
+      &__simtime), __bld_lineloc(__xs2, __monit_stp->stfnam_ind,
+      __monit_stp->stlin_cnt));
+    }
+   --- */
+  } 
+ __monit_stp = sav_monit_stp;
+ __monit_itp = sav_monit_itp;
+ /* add entire list to se free list */
+ __fmonse_end->fmsenxt = __fmse_freelst;
+ __fmse_freelst = __fmonse_hdr; 
+ __fmonse_hdr = __fmonse_end = NULL;
+}
+
+/*
+ * execute the monitor statements at end of time slot
+ * only called if at least one and like dispay not write
+ * fmonp nil implies it is $monitor
+ */
+extern void __exec_monit(struct dceauxlst_t *monit_hd, int32 force_write)
+{
+ int32 base, sav_slin_cnt, sav_sfnam_ind;
+ struct tskcall_t *tkcp;
+ struct expr_t *tkxp;
+ struct systsk_t *stbp;
+
+ /* if execed "$monitor;" no monitoring but force write will be on */
+ if (__monit_stp == NULL) return;
+
+ /* first make sure at least one changed (or just starting so must write) */
+ /* and update all dce values (not per inst.) to current value if chged */ 
+ if (!chk_monits_chged(monit_hd) && !force_write) return;
+
+ sav_slin_cnt = __slin_cnt;
+ sav_sfnam_ind = __sfnam_ind;
+ __slin_cnt = __monit_stp->stlin_cnt;
+ __sfnam_ind = __monit_stp->stfnam_ind;
+
+ tkcp = &(__monit_stp->st.stkc);
+ tkxp = tkcp->tsksyx;
+ stbp = tkxp->lu.sy->el.esytbp;
+ /* current instance does not need to be preserved here */
+ __push_itstk(__monit_itp);
+
+ switch (stbp->stsknum) {
+  case STN_MONITOR: base = BDEC; goto nonf_write;
+  case STN_MONITORH: base = BHEX; goto nonf_write;
+  case STN_MONITORB: base = BBIN; goto nonf_write;
+  case STN_MONITORO: base = BOCT;
+nonf_write:
+   __do_disp(tkcp->targs, base);
+   __cvsim_msg("\n");
+   break;
+  case STN_FMONITOR: base = BDEC; goto f_disp;
+  case STN_FMONITORB: base = BBIN; goto f_disp;
+  case STN_FMONITORH: base = BHEX; goto f_disp;
+  case STN_FMONITORO: base = BOCT;
+f_disp:
+   __fio_do_disp(tkcp->targs, base, TRUE, tkxp->lu.sy->synam);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ __pop_itstk();
+ __slin_cnt = sav_slin_cnt;
+ __sfnam_ind = sav_sfnam_ind;
+}
+
+/*
+ * routine to go through entire monit dce list and see if any really changed
+ * if really changed, store new value 
+ *
+ * know itree loc set
+ */
+static int32 chk_monits_chged(register struct dceauxlst_t *dclp)
+{
+ register struct xstk_t *xsp, *xsp2; 
+ byte *sbp, *sbp2;
+ int32 i1, i2, i, chged, dcewid;
+ struct dcevnt_t *dcep;
+ struct net_t *np; 
+
+ chged = FALSE;
+ for (; dclp != NULL; dclp = dclp->dclnxt)
+  {
+   dcep = dclp->ldcep;
+
+   /* for array index or entire non wire (not constant range), no change */
+   /* previous value needed, if in list changed */ 
+   /* but notice must go thru entire list to update changed values */
+   if (dcep->prevval.wp == NULL) { chged = TRUE; continue; }
+
+   np = dcep->dce_np;
+   dcewid = __get_dcewid(dcep, np);
+   __push_itstk(dcep->dce_matchitp);
+   __get_cor_range(dcep->dci1, dcep->dci2, &i1, &i2);
+   if (np->n_stren)
+    {
+     /* for monit know exactly one prevval */
+     sbp = dcep->prevval.bp;
+     /* this uses "real" iti num */
+     get_stwire_addr_(sbp2, np);
+     if (i1 != -1) sbp2 = &(sbp2[i2]);
+
+     if (dcep->dce_nomonstren)
+      {
+       for (i = 0; i < dcewid; i++, sbp++, sbp2++) 
+        {
+         if (*sbp != *sbp2)
+          {
+           /* here only changed if value (low 2 bits) differ */
+           if ((*sbp & 3) != (*sbp2 & 3)) chged = TRUE; 
+           /* always copy even if values the same */
+           *sbp = *sbp2;
+          }
+        }
+      }
+     else
+      {
+       if (memcmp(sbp, sbp2, dcewid) != 0)
+        { chged = TRUE; memcpy(sbp, sbp2, dcewid); }
+      }
+    }
+   else
+    {
+     push_xstk_(xsp, dcewid);
+
+     /* this need to access 0th instance since one inst form */
+     __push_wrkitstk(__inst_mod, 0);
+     __ld_perinst_val(xsp->ap, xsp->bp, dcep->prevval, dcewid);
+     __pop_wrkitstk();
+
+     /* now must load from correct inst and store into one inst. */
+     push_xstk_(xsp2, dcewid);
+     __ld_wire_sect(xsp2->ap, xsp2->bp, np, i1, i2);
+     if (cmp_vval_(xsp->ap, xsp2->ap, dcewid) != 0 || 
+      cmp_vval_(xsp->bp, xsp2->bp, dcewid) != 0)
+      {
+       chged = TRUE;
+   
+       /* know tmpitp unchanged since load */
+       __push_wrkitstk(__inst_mod, 0);
+       __st_perinst_val(dcep->prevval, dcewid, xsp2->ap, xsp2->bp);
+       __pop_wrkitstk();
+      }
+     __pop_xstk();
+     __pop_xstk();
+    }
+   __pop_itstk();
+  }
+ return(chged);
+}
+
+/*
+ * load section of wirereg for monitor and dce change determination
+ * know itree location correct and i1 and i2 set (-2 IS form fixed by here)
+ * if bit select of array load array cell
+ * this is for non strength wire case
+ */ 
+extern void __ld_wire_sect(word32 *ap, word32 *bp, struct net_t *np,
+ register int32 i1, register int32 i2)
+{
+ int32 arrwid;
+
+ if (i1 == -1) { __ld_wire_val(ap, bp, np); return; }
+ if (i1 == i2)
+  {
+   if (!np->n_isarr) __ld_bit(ap, bp, np, i1);
+   else
+    {
+     arrwid = __get_arrwide(np);
+     __ld_arr_val(ap, bp, np->nva, arrwid, np->nwid, i1);
+    }
+   return;
+  }
+ __ld_psel(ap, bp, np, i1, i2);
+}
+
+/*
+ * ROUTINES TO EVALUATE RHS EXPRESSIONS
+ */
+
+/*
+ * wrapper for eval_xpr that sets correct exec source location
+ */
+extern struct xstk_t *__src_rd_eval_xpr(struct expr_t *ndp)
+{
+ struct xstk_t *xsp;
+ int32 sav_slin_cnt, sav_sfnam_ind;
+
+ /* can assign specparam value immediately */
+ /* SJM 06/17/99 - needs to run in run/fixup mode - statement loc set */
+ sav_slin_cnt = __slin_cnt;
+ sav_sfnam_ind = __sfnam_ind;
+ __sfnam_ind = __cur_fnam_ind;
+ __slin_cnt = __lin_cnt;
+
+ xsp = __eval_xpr(ndp);
+
+ /* must put back in case reading iact source */
+ __slin_cnt = sav_slin_cnt;
+ __sfnam_ind = sav_sfnam_ind;
+ return(xsp);
+}
+
+/*
+ * for debugging special interface to evaluate expression 
+ * so stack depth can be checked
+ * -- notice where strength needed (even if non stren) use ndst eval xpr
+ * this is normally macro see pvmacros.h
+ */
+/* --- DBG add ---
+extern struct xstk_t *__eval_xpr(struct expr_t *ndp)
+{
+ struct xstk_t *xsp;
+  
+ xsp = __eval2_xpr(ndp);
+
+ -* ---
+ if (__debug_flg)
+  {
+   if (__xspi != 0 && __fcspi == -1)
+    {
+     __sgfwarn(526, 
+     "INTERNAL - %d extra values on stack after expression evaluation", __xspi);
+    }   
+  }
+ --- *-
+ return(xsp);
+}
+---- */
+
+/*
+ * evaluate a rhs expressions
+ * pushes and pops temps and leaves result on top of reg stack
+ * requires all expr. node widths to be set
+ * both for constant folding and execution
+ * caller must pop value from stack
+ * know a and p parts always contiguous
+ *
+ * this is used for constant evaluation where already check for only values
+ * parameters are converted to numbers by here and spec params are never in
+ * expressions
+ *
+ * LOOKATME - since now have real cont table and real storage table
+ *            could get rid of double copying even for interpreter
+ */
+extern struct xstk_t *__eval2_xpr(register struct expr_t *ndp)
+{
+ register struct xstk_t *xsp;
+ int32 wlen;
+ register word32 *wp;
+ struct net_t *np;
+ struct gref_t *grp;
+ struct sy_t *syp;
+
+ /* DBG remove --- 
+ if (ndp == NULL) __arg_terr(__FILE__, __LINE__);
+ --- */
+
+ /* in this case, must put value on tos */
+ switch ((byte) ndp->optyp) {
+  case NUMBER:
+   push_xstk_(xsp, ndp->szu.xclen);
+   if (ndp->szu.xclen <= WBITS)
+    {
+     xsp->ap[0] = __contab[ndp->ru.xvi];
+     xsp->bp[0] = __contab[ndp->ru.xvi + 1];
+    }
+   else memcpy(xsp->ap, &(__contab[ndp->ru.xvi]),
+    2*WRDBYTES*wlen_(ndp->szu.xclen));
+
+   return(xsp); 
+  case REALNUM:
+   push_xstk_(xsp, ndp->szu.xclen);
+   /* know high bits of num value already zeroed */
+   memcpy(xsp->ap, &(__contab[ndp->ru.xvi]),
+    2*WRDBYTES*wlen_(ndp->szu.xclen));
+   return(xsp);
+  case OPEMPTY:
+   /* this evaluates to one space - for procedural (stask) ,, connections */
+   push_xstk_(xsp, 8);
+   xsp->bp[0] = 0L;
+   xsp->ap[0] = ' ';
+   return(xsp);
+  case UNCONNPULL:
+   /* only for inst. input where down must be marked strength */
+   __case_terr(__FILE__, __LINE__);
+   break;
+  case ISNUMBER:
+   push_xstk_(xsp, ndp->szu.xclen);
+   wlen = wlen_(ndp->szu.xclen);
+   wp = (word32 *) &(__contab[ndp->ru.xvi]);
+   memcpy(xsp->ap, &(wp[2*wlen*__inum]), 2*WRDBYTES*wlen);
+   return(xsp);
+  case ISREALNUM:
+   push_xstk_(xsp, ndp->szu.xclen);
+   wlen = wlen_(ndp->szu.xclen);
+   wp = &(__contab[ndp->ru.xvi + 2*__inum]);
+   memcpy(xsp->ap, wp, 2*WRDBYTES*wlen);
+   return(xsp);
+  case GLBREF:
+   /* if local fall through - symbol and cur. itp right */
+   grp = ndp->ru.grp;
+   __xmrpush_refgrp_to_targ(grp);
+   push_xstk_(xsp, ndp->szu.xclen);
+   /* know this is global wire or will not get here */
+   /* cannot use short circuit xva for globals */
+   np = grp->targsyp->el.enp;
+   __ld_wire_val(xsp->ap, xsp->bp, np);
+   __pop_itstk();
+   goto done;
+  case ID:
+   push_xstk_(xsp, ndp->szu.xclen);
+   np = ndp->lu.sy->el.enp;
+   __ld_wire_val(xsp->ap, xsp->bp, np);
+   goto done;
+  case LSB:
+   push_bsel(ndp);
+   goto done;
+  case PARTSEL:
+   push_psel(ndp);
+   goto done;
+  case LCB:
+   __rhs_concat(ndp);
+   goto done;
+  case FCALL:
+   syp = ndp->lu.x->lu.sy;
+   /* notice these routines in v_ex - result left on top of stack */
+   /* as usual caller must free */
+   if (syp->sytyp == SYM_SF) __exec_sysfunc(ndp); else __exec_func(ndp);
+   /* function return value now on top of stack */
+   goto done; 
+  case QUEST:
+   /* notice that because of side effects, must evaluate in order */
+   __eval_qcol(ndp);
+   goto done;
+  case REALREALQUEST:
+   __eval_realrealqcol(ndp);
+   goto done;
+  case REALREGQUEST:
+   __eval_realregqcol(ndp);
+   goto done;
+  case REGREALQCOL:
+   __eval_regrealqcol(ndp);
+   /* 1 value now on tos */
+   goto done;
+  }
+ if (ndp->ru.x == NULL) eval_unary(ndp); else eval_binary(ndp);
+done:
+ return(__xstk[__xspi]);
+}
+
+/*
+ * routine to grow xstk
+ */
+extern void __grow_xstk(void)
+{
+ register int32 i;
+ int32 old_maxxnest;
+ int32 osize, nsize;
+
+ old_maxxnest = __maxxnest;
+ osize = old_maxxnest*sizeof(struct xstk_t *);
+ if (__maxxnest >= XNESTFIXINC) __maxxnest += XNESTFIXINC;
+ else __maxxnest *= 2;
+ nsize = __maxxnest*sizeof(struct xstk_t *);
+ __xstk = (struct xstk_t **) __my_realloc((char *) __xstk, osize, nsize);
+ /* assume stack hold 1 work case at initialization */
+ for (i = old_maxxnest; i < __maxxnest; i++)
+  {
+   __xstk[i] = (struct xstk_t *) __my_malloc(sizeof(struct xstk_t));
+   __alloc_xsval(__xstk[i], 1);
+  }
+ if (__debug_flg)
+  __dbg_msg("+++ expr. stack grew from %d bytes to %d\n", osize, nsize); 
+}
+
+/* 
+ * routine to widen xstk element if wider than default words - rare 
+ */
+extern void __chg_xstk_width(struct xstk_t *xsp, int32 wlen)
+{
+ /* freeing in case of need for very wide expr. */
+ __my_free((char *) xsp->ap, 2*WRDBYTES*xsp->xsawlen);
+ __alloc_xsval(xsp, wlen);
+}
+
+/*
+ * allocate stack entry value word32 array
+ * only called after need to widen determined 
+ * this allocates wide enough stack value - caller must set width and value
+ * this always makes a and b parts contiguous
+ *
+ * only allocate and free here 
+ * FIXME - why not use re-alloc?
+ */
+extern void __alloc_xsval(struct xstk_t *xsp, int32 xstkwlen)
+{
+ word32 *ap;
+ int32 awlen;
+
+ awlen = (xstkwlen < DFLTIOWORDS) ? DFLTIOWORDS : xstkwlen;
+ /* notice a and b parts must be allocated once contiguously */
+ /* 4 words means 128 bits at 32 bits dependent per word32 */
+ ap = (word32 *) __my_malloc(2*WRDBYTES*awlen);
+ xsp->ap = ap;
+ /* this makes 2 part contiguous */
+ xsp->bp = &(ap[xstkwlen]);
+ xsp->xsawlen = awlen;
+}
+
+/*
+ * load (copy) an entire value into possibly separated rgap and rgbp from wp
+ * of length blen instance cur. itp loaded with representation srep
+ *
+ * assumes cur. itp starts at 0
+ * cannot be used to access array and removes any strengths (value only)
+ * rgap and rgbp assumed to have enough room
+ * also for params and specparams
+ */
+extern void __ld_wire_val(register word32 *rgap, register word32 *rgbp,
+ struct net_t *np)
+{
+ register word32 uwrd, *rap, *wp;
+ register int32 wlen;
+ struct expr_t *xp;
+ struct expr_t **pxparr;
+ struct xstk_t *xsp;
+
+ switch ((byte) np->srep) {
+  case SR_VEC:
+   /* rap is 2*wlen word32 section of vec array that stores cur. inst vec. */
+   wlen = wlen_(np->nwid);
+   /* DBG remove ---
+   if (__inst_ptr == NULL) __arg_terr(__FILE__, __LINE__);
+   --- */
+   rap = &(np->nva.wp[2*wlen*__inum]);
+   memcpy(rgap, rap, WRDBYTES*wlen);
+   memcpy(rgbp, &(rap[wlen]), WRDBYTES*wlen);
+   return;
+  case SR_SVEC:
+   __ld_stval(rgap, rgbp, &(np->nva.bp[np->nwid*__inum]), np->nwid);
+   return;
+  case SR_SCAL:
+   ld_scalval_(rgap, rgbp, np->nva.bp);
+   return;
+  case SR_SSCAL:
+   /* notice accessing byte value and assign so endian ok */
+   uwrd = (word32) np->nva.bp[__inum];
+   rgap[0] = uwrd & 1L;
+   rgbp[0] = (uwrd >> 1) & 1L;
+   return;
+
+  /* PX representations are left for getting param value at run time */
+  /* also for parameter forms never selects */
+  case SR_PXPR:
+   wlen = wlen_(np->nwid);
+   /* this assumes for parameters expr. points to nva expr. field */
+   xp = (struct expr_t *) np->nva.wp;
+   xsp = __eval2_xpr(xp);
+   memcpy(rgap, xsp->ap, WRDBYTES*wlen);
+   memcpy(rgbp, xsp->bp, WRDBYTES*wlen);
+   __pop_xstk();
+   return;
+  case SR_PISXPR:
+   wlen = wlen_(np->nwid);
+   /* this assumes for parameters expr. points to nva expr. field */
+   /* caller sets iti num */
+   pxparr = (struct expr_t **) np->nva.wp;  
+   xsp = __eval2_xpr(pxparr[__inum]);
+   /* if real just copy */
+   memcpy(rgap, xsp->ap, WRDBYTES*wlen);
+   memcpy(rgbp, xsp->bp, WRDBYTES*wlen);
+   __pop_xstk();
+   return;
+  case SR_PNUM:
+   wlen = wlen_(np->nwid);
+   wp = np->nva.wp;
+   memcpy(rgap, wp, WRDBYTES*wlen);
+   memcpy(rgbp, &(wp[wlen]), WRDBYTES*wlen);
+   return;
+  case SR_PISNUM:
+   wlen = wlen_(np->nwid);
+   wp = &(np->nva.wp[2*wlen*__inum]);
+   memcpy(rgap, wp, WRDBYTES*wlen);
+   memcpy(rgbp, &(wp[wlen]), WRDBYTES*wlen);
+   return;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * load per inst. value - allows packing etc.
+ * mostly for continuous assign driver 
+ * not for strengths and needs __inst_ptr to be set
+ * caller needs to push big enough area pointed to by rgap/rgbp
+ *
+ * know size change never needed here 
+ */
+extern void __ld_perinst_val(register word32 *rgap, register word32 *rgbp,
+ union pck_u pckv, int32 vblen)
+{
+ word32 *rap;
+ int32 wlen;
+
+ if (vblen == 1) { ld_scalval_(rgap, rgbp, pckv.bp); return; }
+ /* SJM - 07/15/00 - all per-inst vecs in at least 2 words */
+ wlen = wlen_(vblen);
+ rap = &(pckv.wp[2*wlen*__inum]);
+ memcpy(rgap, rap, WRDBYTES*wlen);
+ memcpy(rgbp, &(rap[wlen]), WRDBYTES*wlen);
+}
+
+/*
+ * load value part of a strength scalar bytes array into an a/b vector
+ * strength bytes (bits) stored low to high just like normal words
+ *
+ * notice this uses lhs selects into rgap/rgbp so must 0 to start
+ * and cannot assume contiguous
+ */
+extern void __ld_stval(register word32 *rgap, register word32 *rgbp,
+ register byte *sbp, int32 blen)
+{
+ register int32 bi;
+ int32 wlen;
+ word32 tmpw;
+ 
+ /* zero unused high bits in high word32 only - rest will be selected into */
+ wlen = wlen_(blen);
+ rgap[wlen - 1] = 0L;
+ rgbp[wlen - 1] = 0L;
+ for (bi = 0; bi < blen; bi++)
+  {
+   tmpw = (word32) sbp[bi];
+   __lhsbsel(rgap, bi, tmpw & 1L);
+   __lhsbsel(rgbp, bi, (tmpw >> 1) & 1L);
+  }
+}
+
+/*
+ * push (access) a selected bit or array locaton on top of reg. stack
+ * know width will be 1 if bit or array vector width if array
+ *
+ * this can be improved by assigning free reg not just pushing
+ * for now not separating at compile time (stupid) so separate is done here
+ */
+static void push_bsel(struct expr_t *ndp)
+{
+ register struct xstk_t *xsp;
+ register struct net_t *np;
+ register word32 *rap;
+ int32 biti, arrwid, wlen;
+ struct expr_t *idndp;
+ 
+ idndp = ndp->lu.x;
+ np = idndp->lu.sy->el.enp;
+
+ /* can be either constant or expr. - both handled in comp. */
+ biti = __comp_ndx(np, ndp->ru.x);
+ push_xstk_(xsp, ndp->szu.xclen);
+ if (biti == -1)
+  {
+   /* notice too many places where cannot emit warning - just change to x/z */
+   set_regtox_(xsp->ap, xsp->bp, xsp->xslen);
+   return;
+  }
+
+ /* notice load routines unwound into both paths */
+ if (idndp->optyp != GLBREF)
+  {
+   /* if (!np->n_isarr) __ld_bit(xsp->ap, xsp->bp, np, biti); */
+   if (!np->n_isarr)
+    {
+     if (np->srep == SR_VEC)
+      {
+       /* BEWARE - this is vectored rep. short circuit */
+       wlen = wlen_(np->nwid);  
+       rap = &(np->nva.wp[2*wlen*__inum]);
+       xsp->ap[0] = rhsbsel_(rap, biti);
+       xsp->bp[0] = rhsbsel_(&(rap[wlen]), biti);
+      }
+     else __ld_bit(xsp->ap, xsp->bp, np, biti);
+    }
+   else
+    {
+     arrwid = __get_arrwide(np);
+     __ld_arr_val(xsp->ap, xsp->bp, np->nva, arrwid, np->nwid, biti);
+    }
+   return;
+  }
+
+ __xmrpush_refgrp_to_targ(idndp->ru.grp);
+ /* if (!np->n_isarr) __ld_bit(xsp->ap, xsp->bp, np, biti); */
+ if (!np->n_isarr)
+  {
+   if (np->srep == SR_VEC)
+    {
+     /* BEWARE - this is vectored rep. short circuit */
+     wlen = wlen_(np->nwid);  
+     rap = &(np->nva.wp[2*wlen*__inum]);
+     xsp->ap[0] = rhsbsel_(rap, biti);
+     xsp->bp[0] = rhsbsel_(&(rap[wlen]), biti);
+    }
+   else __ld_bit(xsp->ap, xsp->bp, np, biti);
+  }
+ else
+  {
+   arrwid = __get_arrwide(np);
+   __ld_arr_val(xsp->ap, xsp->bp, np->nva, arrwid, np->nwid, biti);
+  }
+ __pop_itstk();
+}
+
+/*
+ * compute a vector or array var or constant index value
+ * returns -1 on x - caller must handle
+ * if returns -1, globals __badind_a and __badind_b contain value
+ *
+ * if net is a array, array index else vector index 
+ *
+ * just like C implied truncating index to 32 bit value
+ * constants are already normalized during compilation
+ * reals illegal and caught before here
+ */
+extern int32 __comp_ndx(register struct net_t *np,
+ register struct expr_t *ndx)
+{
+ register word32 *rap;
+ register word32 *wp;
+ int32 biti, ri1, ri2, biti2, obwid;
+ struct net_t *xnp;
+ struct xstk_t *xsp2;
+
+ /* special case 0 - simple unpacked variable */
+ /* SJM 05/21/04 - can only short circuit if fits in one word32 */
+ if (ndx->optyp == ID && ndx->szu.xclen <= WBITS)
+  {
+   xnp = ndx->lu.sy->el.enp;
+   if (xnp->srep != SR_VEC) goto nd_eval;
+
+   /* BEWARE - this short circuit assumes particular SR_VEC d.s. */
+   rap = &(xnp->nva.wp[2*__inum]);
+   biti2 = rap[0];
+   if (rap[1] == 0L) goto normalize; 
+    
+   __badind_a = rap[0];
+   __badind_b = rap[1];
+   __badind_wid = xnp->nwid;
+   return(-1);
+  }
+
+ /* case 1: constant */
+ if (ndx->optyp == NUMBER)  
+  {
+   wp = &(__contab[ndx->ru.xvi]); 
+   if (wp[1] != 0L)
+    {
+     __badind_a = wp[0];
+     __badind_b = wp[1];
+     __badind_wid = ndx->szu.xclen;
+     return(-1);
+    }
+   return((int32) wp[0]);
+  }
+ /* case 2 IS constant */
+ /* notice IS NUMBER form must be normalized at compile time */
+ if (ndx->optyp == ISNUMBER)
+  {
+   wp = &(__contab[ndx->ru.xvi]); 
+   wp = &(wp[2*__inum]);
+   if (wp[1] != 0L)
+    {
+     __badind_a = wp[0];
+     __badind_b = wp[1];
+     __badind_wid = ndx->szu.xclen;
+     return(-1);
+    }
+   return((int32) wp[0]);
+  }
+ /* case 3 expression */
+ /* case 3b - other expr. */
+nd_eval:
+ xsp2 = __eval2_xpr(ndx);
+
+ if (xsp2->bp[0] != 0L)
+  {
+   __badind_a = xsp2->ap[0];
+   __badind_b = xsp2->bp[0];
+   __badind_wid = ndx->szu.xclen;
+   __pop_xstk();
+   return(-1);
+  }
+ biti2 = (int32) xsp2->ap[0];
+ __pop_xstk();
+
+normalize:
+ /* convert index to h:0 normalized value */
+ /* === SJM 11/16/03 - using inline code this is slower 
+ if (np->n_isarr) __getarr_range(np, &ri1, &ri2, &obwid);
+ else { __getwir_range(np, &ri1, &ri2); obwid = np->nwid; }
+ === */ 
+
+ /* SJM 11/14/03 - use original code - MAYBE PUTMEBACK */ 
+ if (np->n_isarr)
+  {
+   ri1 = np->nu.rngarr->ai1;
+   ri2 = np->nu.rngarr->ai2;
+   obwid = (ri1 >= ri2) ? (ri1 - ri2 + 1) : (ri2 - ri1 + 1);
+  }
+ else
+  {
+   if (np->nrngrep == NX_CT)
+    {
+     ri1 = (int32) __contab[np->nu.ct->nx1->ru.xvi];
+     ri2 = (int32) __contab[np->nu.ct->nx2->ru.xvi];
+    }
+   else
+    {
+     ri1 = np->nu.rngdwir->ni1;
+     ri2 = np->nu.rngdwir->ni2;
+    }
+   obwid = np->nwid;
+  }
+
+ biti = normalize_ndx_(biti2, ri1, ri2);
+ /* SJM 05/21/04 - for 0:h - if above - value will be negative */
+ if (biti >= obwid || biti < 0)
+  { __badind_a = biti2; __badind_b = 0L; __badind_wid = WBITS; return(-1); }
+ return(biti);
+}
+
+/*
+ * pop the expression stack
+ * DBG macro: #define __pop_xstk() xsp = __xstk[__xspi--]
+ */
+/* -- ??? DBG ADD --
+extern void __pop_xstk(void)
+{
+ struct xstk_t *xsp;
+
+ if (__xspi < 0) __arg_terr(__FILE__, __LINE__);
+ xsp = __xstk[__xspi];
+ if (xsp->xsawlen > MUSTFREEWORDS) __chg_xstk_width(xsp, 1);
+ __xspi--;
+ -* ---
+ if (__debug_flg)
+  __dbg_msg("+++ popping stack to height %d, old bit length %d\n", __xspi + 1,
+   xsp->xslen);
+ ---*-
+}
+--- */
+
+/* BEWARE - a and b parts must be contiguous because often refed as only a */ 
+/* -- ??? DBG ADD --
+extern struct xstk_t *__push_xstk(int32 blen)
+{ 
+ register struct xstk_t *xsp;
+
+ if (++__xspi >= __maxxnest) __grow_xstk();
+ xsp = __xstk[__xspi];
+ if (wlen_(blen) > xsp->xsawlen) __chg_xstk_width(xsp, wlen_(blen));
+ xsp->bp = &(xsp->ap[wlen_(blen)]);
+ xsp->xslen = blen;
+
+ -* --- *-
+ if (__debug_flg)
+  __dbg_msg("+++ pushing stack to height %d, bit length %d\n", __xspi + 1,
+   xsp->xslen);
+ -* ---*-
+
+ return(xsp);
+}
+--- */
+
+/*
+ * load one bit into low bit position of registers rgpa and rgpb from
+ * coded wp of length blen from biti current instance stored using
+ * representation srep;
+ * biti must be corrected to normalized h:0 value before here 
+ * and biti of x also handled before here
+ * know result will be isolated in low bit value (no need to mask)
+ *
+ * this differs from rhs bit select in accessing value for current inst and
+ * adjusting place to select from according to storage representation
+ * if value out of range sets result to x
+ *
+ * cannot be used to access array and ignores strength parts of stren values
+ * at least for now this load makes a copy in normal ab vector form
+ *
+ * only run time SR forms possible here
+ * BEWARE - this is sometimes used to load scalar so much leave scalar sreps 
+ */
+extern void __ld_bit(register word32 *rgap, register word32 *rgbp,
+ register struct net_t *np, int32 biti)
+{
+ register word32 uwrd, *rap;
+ register int32 wlen;
+
+ /* out of range is x */
+ if (biti > np->nwid) { rgap[0] = rgbp[0] = 1L; return; }
+ /* this is number of words needed to hold a or b part not region */ 
+ switch ((byte) np->srep) {
+  case SR_VEC:
+   wlen = wlen_(np->nwid);
+   /* rap is start of instance coded vector a/b groups */
+   rap = &(np->nva.wp[2*wlen*__inum]);
+   rgap[0] = rhsbsel_(rap, biti);
+   rgbp[0] = rhsbsel_(&(rap[wlen]), biti);
+   break;
+  case SR_SVEC:
+   /* strength vectors normalized to h:0 which means v[0] is index 0 */
+   /* since h:0 means low bit to left in radix style notation */
+   uwrd = (word32) np->nva.bp[__inum*np->nwid + biti];
+do_slb:
+   rgap[0] = uwrd & 1L;
+   rgbp[0] = (uwrd >> 1) & 1L;
+   break;
+  case SR_SCAL:
+   /* LOOKATME - maybe load bit of scalar should be fatat err */
+   /* this is same as full value load for 1 bit thing */
+   /* notice biti will be 0 or will not get here */
+   ld_scalval_(rgap, rgbp, np->nva.bp);
+   break;
+  case SR_SSCAL:
+   uwrd = (word32) np->nva.bp[__inum];
+   goto do_slb;
+  case SR_PISNUM:
+   wlen = wlen_(np->nwid);
+   /* rap is start of instance coded vector a/b groups */
+   rap = &(np->nva.wp[2*wlen*__inum]);
+   rgap[0] = rhsbsel_(rap, biti);
+   rgbp[0] = rhsbsel_(&(rap[wlen]), biti);
+   break;
+  /* SJM 08/22/00 - also allowing part and bit selects from parameters */
+  case SR_PNUM:
+   wlen = wlen_(np->nwid);
+   /* rap is start of instance coded vector a/b groups */
+   rap = np->nva.wp;
+   rgap[0] = rhsbsel_(rap, biti);
+   rgbp[0] = rhsbsel_(&(rap[wlen]), biti);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * load one indexed element of a array map, size mlen with each element
+ * blen wide from index arri from current instance into rgap and rgbp
+ *
+ * arrays stored and normalized h:0 just like vectors
+ *
+ * vector (or scalar) are packed into 1 linear array of partial bit
+ * elements - 4,8,16,32 with both a and b together - both array index
+ * and instance index used to decode linear array
+ *
+ * arri here must be normalized to h:0 form
+ * map is base of array area (np nva)
+ */
+extern void __ld_arr_val(register word32 *rgap, register word32 *rgbp,
+ union pck_u map, int32 mlen, int32 blen, int32 arri)
+{
+ register int32 wlen;
+ register word32 *rap;
+ word32 tmpw;
+ int32 indi;
+
+ /* compute number of words used to store 1 array element */
+ /* 17 or more bits cannot be packed with multiple elements per word32 */
+ if (blen > WBITS/2)
+  {
+   /* case 1: each vector element of array needs multiple words */
+   wlen = wlen_(blen);
+   /* find array for inst i with each vector wlen words wide */
+   rap = &(map.wp[2*wlen*mlen*__inum]);
+   /* find element arri that may be a vector */
+   rap = &(rap[arri*2*wlen]);
+   cp_walign_(rgap, rap, blen);
+   cp_walign_(rgbp, &(rap[wlen]), blen);
+   return;
+  }
+ /* case 2: array of scalars */
+ if (blen == 1)
+  {
+   /* here arri is real twice real index to get bit index */
+   indi = 2*(mlen*__inum + arri);
+   tmpw = map.wp[get_wofs_(indi)] >> (get_bofs_(indi));
+   rgap[0] = tmpw & 1L;
+   rgbp[0] = (tmpw >> 1) & 1L;
+   return;
+  }
+ /* case 3: multiple elements packed per word32, half word32, or byte */
+ indi = __inum*mlen + arri;
+ /* SJM 12/16/99 - still need to really pack memories to bytes and hwords */
+ tmpw = get_packintowrd_(map, indi, blen);
+ rgap[0] = tmpw & __masktab[blen];
+ /* know high unused bits of byte, hword, or word 0 */
+ rgbp[0] = (tmpw >> blen);
+}
+
+/*
+ * push (access) a selected part select range on top of reg. stack
+ * know index values must be <= WBITS constants
+ * notice for now only one representation for vector that can be part selected
+ * from - one bit ok but cannot part select from scalar
+ */
+static void push_psel(register struct expr_t *ndp)
+{
+ register struct expr_t *ndx1, *ndx2;
+ int32 bi1, bi2;
+ struct expr_t *idndp;
+ struct xstk_t *xsp;
+ struct net_t *np;
+ struct gref_t *grp;
+
+ idndp = ndp->lu.x;
+ /* know these are both constant nodes */
+ ndx1 = ndp->ru.x->lu.x;
+ ndx2 = ndp->ru.x->ru.x;
+ push_xstk_(xsp, ndp->szu.xclen);
+
+ /* here never need to execute a part select with x range - what is meaning */
+ bi1 = __contab[ndx1->ru.xvi];
+ bi2 = __contab[ndx2->ru.xvi];
+ /* notice calling of ld psel unwound to 2 paths */
+ if (idndp->optyp == GLBREF)
+  {
+   grp = idndp->ru.grp;    
+   __xmrpush_refgrp_to_targ(grp);
+   np = grp->targsyp->el.enp;
+   __ld_psel(xsp->ap, xsp->bp, np, bi1, bi2);
+   __pop_itstk();
+   return;
+  }
+ /* part selects bit numbered from h:0 (i.e. 31..0) */
+ np = idndp->lu.sy->el.enp;
+ __ld_psel(xsp->ap, xsp->bp, np, bi1, bi2);
+}
+
+/*
+ * load part select into low bit positions of registers rgap and rgbp from
+ * coded wp of length blen from bit1 to bit2 current instance
+ *
+ * representation must be a vector 
+ * bit1 > bit2 according to normalized h:0 form
+ * low bit is 0 and high bit is 31 in word
+ * part select in range or will not get here
+ *
+ * notice perfectly legal to declare wire [1:1] x and psel the 1 bit
+ */
+extern void __ld_psel(register word32 *rgap, register word32 *rgbp,
+ register struct net_t *np, int32 bith, int32 bitl)
+{
+ register word32 *rap;
+ byte *netsbp;
+ int32 wlen, numbits;
+ 
+ numbits = bith - bitl + 1;
+
+ switch ((byte) np->srep) {
+  case SR_VEC:
+   /* rap is start of current instance coded vector a b groups */
+   wlen = wlen_(np->nwid);
+   rap = &(np->nva.wp[2*wlen*__inum]);
+   /* this routine expects select to start from bit in 1st word32 */
+   __rhspsel(rgap, rap, bitl, numbits);
+   rap = &(rap[wlen]);
+   __rhspsel(rgbp, rap, bitl, numbits);
+   break;
+  case SR_SVEC:
+   netsbp = &(np->nva.bp[__inum*np->nwid + bitl]);
+   /* copy from low to high in array according to radix notation */
+   __ld_stval(rgap, rgbp, netsbp, numbits);
+   break;
+  /* SJM 08/22/00 - also allowing part and bit selects from parameters */
+  case SR_PNUM:
+   /* rap is start of current instance coded vector a b groups */
+   wlen = wlen_(np->nwid);
+   rap = np->nva.wp;
+   /* this routine expects select to start from bit in 1st word32 */
+   __rhspsel(rgap, rap, bitl, numbits);
+   rap = &(rap[wlen]);
+   __rhspsel(rgbp, rap, bitl, numbits);
+   break;
+  case SR_PISNUM:
+   /* rap is start of current instance coded vector a b groups */
+   wlen = wlen_(np->nwid);
+   rap = &(np->nva.wp[2*wlen*__inum]);
+   /* this routine expects select to start from bit in 1st word32 */
+   __rhspsel(rgap, rap, bitl, numbits);
+   rap = &(rap[wlen]);
+   __rhspsel(rgbp, rap, bitl, numbits);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * right hand side part select from swp of len sblen at sbit1 into dwp
+ *
+ * selecting numbits long section
+ * sbits must be in range 0 to [high bit]
+ * notice for part select, range correction done at compile time
+ * also notice that 1 bits things can go through here but not lhs psel
+ */
+extern void __rhspsel(register word32 *dwp, register word32 *swp,
+ register int32 sbit1, register int32 numbits)
+{
+ register int32 wi, corsbit1;
+
+ /* case 1 - select within 1st word32 */
+ if (sbit1 + numbits <= WBITS)
+  {
+   corsbit1 = sbit1;
+do_inword:
+   if (corsbit1 == 0) *dwp = *swp & __masktab[numbits];
+   else *dwp = (*swp >> corsbit1) & __masktab[numbits];
+   return;
+  }
+
+ /* normalize so swp and corsbit1 start of src with corsbit1 in 1st word32 */
+ wi = get_wofs_(sbit1);
+ swp = &(swp[wi]);
+ corsbit1 = ubits_(sbit1);
+
+ /* case 2 - selection does not cross word32 boundary */
+ if (corsbit1 + numbits <= WBITS) goto do_inword;
+
+ /* case 3a - selection crosses word32 boundary but start on word32 boundary */
+ if (corsbit1 == 0) { cp_walign_(dwp, swp, numbits); return; }
+
+ /* case 3a - crosses 1 word32 boundary and <= WBITS long */
+ if (numbits <= WBITS)
+  {
+   *dwp = (swp[0] >> corsbit1);
+   *dwp |= swp[1] << (WBITS - corsbit1);
+   *dwp &= __masktab[numbits];
+   return;
+  }
+ __cp_sofs_wval(dwp, swp, corsbit1, numbits);
+}
+
+/*
+ * ROUTINES TO IMPLEMENT READMEM
+ */
+
+/*
+ * execute the readmem[bh] system task
+ * know 2nd argument array and from 2 to 4 args or will not get here
+ * LOOKATME maybe a memory leak with __cur_fnam?
+ */
+extern void __exec_readmem(struct expr_t *argxp, int32 base)
+{
+ int32 slen, ri1, ri2, arrwid, arr1, arr2;
+ int32 tmpi, sav_lincnt, nd_itpop;
+ FILE *f;
+ struct expr_t *axp;
+ struct net_t *np;
+ char *chp, *savfnam;
+ char s1[RECLEN];
+
+ axp = argxp->lu.x;
+ /* if contains non printable ok, since will just not be able to open file */
+ chp = __get_eval_cstr(axp, &slen);
+ savfnam = __cur_fnam;
+ sav_lincnt = __lin_cnt;
+ /* notice must copy out of __exprline since reused below */
+ __cur_fnam = chp;
+ if ((f = __tilde_fopen(__cur_fnam, "r")) == NULL)
+  {
+   __sgferr(716, "unable to open $readmem%c input file %s",
+    __to_baselet(base), __cur_fnam);
+   goto no_fil_done;
+  }
+
+ /* 2nd arg. is array destination */
+ argxp = argxp->ru.x;
+ axp = argxp->lu.x; 
+
+ /* know will be array name ID or array name global reference */
+ if (axp->optyp == GLBREF)
+  {
+   __xmrpush_refgrp_to_targ(axp->ru.grp);
+   nd_itpop = TRUE;
+  }
+ else nd_itpop = FALSE;
+
+ if (axp->is_real)
+  {
+   __sgferr(717, "$readmem%c of %s illegal no readmem of array of reals",
+    __to_baselet(base), __msgexpr_tostr(__xs, axp));
+   goto fil_done;
+  }
+ np = axp->lu.sy->el.enp;
+
+ argxp = argxp->ru.x;
+ /* know this is array so range is array range */
+ __getarr_range(np, &ri1, &ri2, &arrwid);
+ /* set up addresses */
+ /* if no range - use array declaration range */ 
+ arr1 = arr2 = -1;
+ if (argxp != NULL) 
+  {
+   axp = argxp->lu.x;
+   if (axp->optyp != OPEMPTY) 
+    {
+     if ((tmpi = __comp_ndx(np, axp)) == -1)
+      {
+       __sgferr(717,
+        "$readmem%c start address expression %s unknown or out of range",
+        __to_baselet(base), __msgexpr_tostr(__xs, axp));
+       goto fil_done;
+      }
+     sprintf(s1, "$readmem%c start", __to_baselet(base));
+     if (!chk_rm_rng_legal(tmpi, ri1, ri2, s1)) goto fil_done;
+     arr1 = tmpi;
+    }
+   argxp = argxp->ru.x;
+   /* if no 2nd ending range (4th arg), use array decl. 2nd range */
+   if (argxp != NULL)
+    {
+     axp = argxp->lu.x;
+     if (axp->optyp != OPEMPTY) 
+      {
+       if ((tmpi = __comp_ndx(np, axp)) == -1)
+        {
+         __sgferr(718, 
+          "$readmem%c end address expression %s unknown or out of range",
+          __to_baselet(base), __msgexpr_tostr(__xs, axp));
+         goto fil_done;
+        }
+       sprintf(s1, "$readmem%c end", __to_baselet(base));
+       if (!chk_rm_rng_legal(tmpi, ri1, ri2, s1)) goto fil_done;
+       arr2 = tmpi;
+       if (arr1 == -1)
+        {
+         __sgferr(718, 
+          "$readmem%c end address value %d illegal - no start address",
+          __to_baselet(base), arr2);
+         goto fil_done;
+        }
+      }
+    }
+  }
+ __do_rm_reading(f, base, np, arr1, arr2, ri1, ri2, arrwid);
+ /* DBG remove ---
+ if (__debug_flg) __dmp_arr_all(np, __inum, __inum);
+ --- */ 
+
+fil_done:
+ if (nd_itpop) __pop_itstk();
+ __my_fclose(f);
+no_fil_done:
+ __lin_cnt = sav_lincnt;
+ __cur_fnam = savfnam;
+}
+
+/*
+ * check a readmem range value to make sure in range
+ * return F on error
+ */
+static int32 chk_rm_rng_legal(int32 tmpi, int32 ri1, int32 ri2, char *msg)
+{
+ if (ri1 <= ri2) { if (tmpi >= ri1 && tmpi <= ri2) return(TRUE); } 
+ else { if (tmpi <= ri1 && tmpi >= ri2) return(TRUE); }
+ __sgferr(712, "%s address value %d outside memory range [%d:%d]",
+  msg, tmpi, ri1, ri2);
+ return(FALSE);
+}
+
+/*
+ * do the readmem reading and filling 
+ *
+ * SJM - 06/19/00 - LRM wrong fills from 0 to high unless
+ * ranges arr1 and arr2 both given
+ * -1 for arr1 and/or arr2 if not given if only arr1 given direction up
+ * arr2 can only be set if arr1 is
+ * only way array down (-1 direction) if arr1 > arr2
+ *
+ * this corrects each time for non h:0 form if needed
+ * if readmem array is XMR itree loc changed before this call
+ */
+extern void __do_rm_reading(FILE *f, int32 base, struct net_t *np,
+ int32 arr1, int32 arr2, int32 ri1, int32 ri2, int32 arrwid)
+{
+ register int32 arri, rmfr, rmto; 
+ int32 dir, nbytes, ttyp, h0_arri, no_rngwarn;
+ struct xstk_t *xsp;
+
+ /* fill the array */
+ no_rngwarn = FALSE;
+ __lin_cnt = 1;
+ /* if only one starting range, direction toward high */
+ /* only way for downward range is arr2 not -1 and arr2 > arr1 */
+ if (arr2 != -1) { if (arr1 <= arr2) dir = 1; else dir = -1; }
+ else dir = 1;
+
+ if (arr1 == -1)
+  {
+   if (ri1 <= ri2) { rmfr = ri1; rmto = ri2; }
+   else { rmfr = ri2; rmto = ri1; }
+  }
+ else if (arr2 == -1)
+  {
+   rmfr = arr1;
+   if (ri1 <= ri2) rmto = ri2; else rmto = ri1;
+  }
+ else { rmfr = arr1; rmto = arr2; }
+
+ for (arri = rmfr;;)
+  {
+   /* separate get tok that does not malloc value */
+   ttyp = mdata_gettok(f, base);
+   if (ttyp == TEOF)
+    {
+     /* only range not filled warning if range passed */
+     if (!no_rngwarn && arr2 != -1 && arri != rmto)
+      __sgfwarn(529,
+       "$readmem%c fewer data elements than range size at **%s(%d)",
+       __to_baselet(base), __cur_fnam, __lin_cnt);
+     return;
+    }
+   if (ttyp == BADOBJ)
+    {
+     __sgferr(720,
+      "illegal $readmem%c file value at **%s(%d) - loading terminated",
+      __to_baselet(base), __cur_fnam, __lin_cnt); 
+     break;
+    }
+   if (ttyp == RMADDR) 
+    {
+     /* convert to hex number - in __acwrk value - check number */
+     /* no error possible in here for hex since digits checked during */
+     /* token input */
+     /* notice this puts in [a/b]cwrk but does not allocate */
+     __to_dhboval(BHEX, TRUE);
+     if (__bcwrk[0] != 0L)
+      {
+       __sgferr(721,
+       "illegal $readmem%c address value %s at **%s(%d) - loading terminated",
+        __to_baselet(base), __regab_tostr(__xs, __acwrk, __bcwrk, __itoklen,
+        BHEX, FALSE), __cur_fnam, __lin_cnt); 
+       return;
+      }
+     /* check for within specified range */
+     arri = (int32) __acwrk[0];
+     if ((dir == 1 && (arri < rmfr || arri > rmto))
+      || (dir == -1 && (arri > rmfr || arri < rmto)))
+      {
+       __sgferr(722,
+       "$readmem%c address value %lu out of range at **%s(%d) - loading terminated",
+        __to_baselet(base), __acwrk[0], __cur_fnam, __lin_cnt); 
+       return;
+      }
+     no_rngwarn = TRUE;
+     continue;
+    }
+   if ((dir == 1 && arri > rmto) || (dir == -1 && arri < rmto))
+    {
+     __sgfwarn(521, "$readmem%c extra data words at **%s(%d) ignored",
+      __to_baselet(base), __cur_fnam, __lin_cnt);
+     return;
+    }
+   __to_dhboval(base, TRUE);
+   h0_arri = normalize_ndx_(arri, ri1, ri2); 
+   /* SJM 09/22/03 - modern P1364 algorithm requires chg stores for each */ 
+   /* index if memory elements appear on any assign rhs */
+   /* correct size if needed */
+   if (np->nwid != __itoklen)
+    {
+     push_xstk_(xsp, __itoklen);
+     nbytes = WRDBYTES*wlen_(__itoklen); 
+     memcpy(xsp->ap, __acwrk, nbytes);
+     memcpy(xsp->bp, __bcwrk, nbytes);
+
+     /* SJM 09/29/03 - change to handle sign extension and separate types */
+     if (xsp->xslen > np->nwid) __narrow_sizchg(xsp, np->nwid);
+     else if (xsp->xslen < np->nwid)
+      {
+       if (np->n_signed) __sgn_xtnd_widen(xsp, np->nwid);
+       else __sizchg_widen(xsp, np->nwid);
+      }
+
+     if (np->nchg_nd_chgstore)
+      {
+       __chg_st_arr_val(np->nva, arrwid, np->nwid, h0_arri,
+        xsp->ap, xsp->bp);
+
+       /* must only trigger change for right array index */
+       if (__lhs_changed) record_sel_nchg_(np, h0_arri, h0_arri);
+      }
+     else __st_arr_val(np->nva, arrwid, np->nwid, h0_arri, xsp->ap, xsp->bp);
+     __pop_xstk();
+    }
+   else
+    {
+     if (np->nchg_nd_chgstore)
+      {
+       __chg_st_arr_val(np->nva, arrwid, np->nwid, h0_arri,
+        __acwrk, __bcwrk);
+
+       /* must only trigger change for right array index */
+       if (__lhs_changed) record_sel_nchg_(np, h0_arri, h0_arri);
+      }
+     else __st_arr_val(np->nva, arrwid, np->nwid, h0_arri, __acwrk, __bcwrk);
+    }
+
+   /* finally increment index */
+   if (dir > 0) { arri++; if (arri > rmto) break; }
+   else { arri--; if (arri < rmto) break; }
+  }
+}
+
+/*
+ * read a readmem file style token
+ * (modified from yylex in "The Unix Programming Environment" p. 337)
+ * value in token of __itoklen bits
+ * array width here limited to 1023 chars 
+ */
+static int32 mdata_gettok(FILE *f, int32 base)
+{
+ register int32 c;
+
+again:
+ while ((c = rm_getc(f)) == ' ' || c == '\t' || c == '\f' || c == '\r') ;
+ if (c == '\n') { __lin_cnt++; goto again; }
+ if (c == EOF) return(TEOF);
+
+ if (c == '/')
+  { if (rmrd_comment(f) == UNDEF) goto again; else return(BADOBJ); }
+ if (c == '@') 
+  {
+   c = rm_getc(f);
+   if (mdata_rdhex(f, c) == BADOBJ) return(BADOBJ);
+   return(RMADDR);
+  }
+ if (base == BBIN)
+  {
+   if (mdata_rdbin(f, c) == BADOBJ) return(BADOBJ);
+   return(NUMBER);
+  }
+ if (mdata_rdhex(f, c) == BADOBJ) return(BADOBJ);
+ return(NUMBER);
+}
+
+/*
+ * readmem form of get a comment
+ */
+static int32 rmrd_comment(FILE *f)
+{
+ register int32 c;
+ int32 c2;
+
+ /* // to EOL comment */
+ if ((c2 = rm_getc(f)) == '/')
+  {
+   while ((c = rm_getc(f)) != '\n') if (c == EOF) return(TEOF);
+   __lin_cnt++;
+   return(UNDEF);
+  }
+ /* slash-star comments don't nest */
+ if (c2 == '*')
+  {
+more_comment:
+   while ((c = rm_getc(f)) != '*')
+    {
+     /* error if / * comments nested */
+     if (c == '/')
+      {
+       if ((c2 = rm_getc(f)) == '*')
+        { __inform(407, "/* style comment nested in readmem"); continue; }
+       c = c2;
+      }
+     if (c == EOF) return(TEOF);
+     if (c == '\n') __lin_cnt++;
+    }
+got_star:
+   if ((c = rm_getc(f)) == '/') return(UNDEF);
+   if (c == '*') goto got_star;
+   if (c == '\n') __lin_cnt++;
+   goto more_comment;
+  }
+ /* not a comment so treat as name token */
+ rm_ungetc(c2, f);
+ return(BADOBJ);
+}
+
+/*
+ * routine to read readmem style hex number
+ */
+static int32 mdata_rdhex(FILE *f, int32 c)
+{
+ register char *chp;
+ int32 len, nsize;
+ int32 has_digit = FALSE;
+ int32 toolong = FALSE;
+ 
+ for (chp = __numtoken, len = 0;;)
+  {
+   if (c ==  '_') { c = rm_getc(f); continue; } 
+   if (!is_mdataxdigit(c))
+    {
+     *chp = '\0';
+     if (!has_digit) return(BADOBJ);
+     /* if white space good end */
+     if (vis_white_(c))
+      {
+       /* if new line must push back for correct line counts */
+       if (c == '\n') rm_ungetc(c, f);
+       break;
+      }
+     /* end of string only good is reading smem */ 
+     if (f == NULL && (c == '\0' || c == -1)) break;
+     return(BADOBJ);
+
+     /* end of string only good is reading smem */ 
+     /* LOOKATME - think this can never happen */
+     if (f == NULL && c == '\0') break;
+     /* SJM 09/13/99 - EOF char returned for both files and strings */
+     if (f != NULL && c == EOF) { rm_ungetc(c, f); break; }
+    }
+   if (c == '?') c = 'X';
+   else if (isalpha(c) && isupper(c)) c = tolower(c);
+
+   if (++len >= __numtok_wid)
+    {
+     /* since hex each digit takes 4 bits */
+     if (len >= (MAXNUMBITS + 1)/4) 
+      {
+       if (!toolong)
+        {
+         __pv_fwarn(522, "readmem value or address too wide (%d) - truncated",
+          MAXNUMBITS);
+         toolong = TRUE;
+        }
+       len--;
+      }
+     else
+      {
+       /* increase size and continue */
+       /* LOOKATME - SJM 03/20/00 - doubling may be too fast growth */
+       nsize = 2*__numtok_wid;
+       __numtoken = __my_realloc(__numtoken, __numtok_wid, nsize);
+       __numtok_wid = nsize;
+       *chp++ = c;
+      }
+    }
+   else *chp++ = c;
+
+   c = rm_getc(f);
+   has_digit = TRUE;
+  }
+ __itoklen = 4*len;
+ return(NUMBER);
+}
+
+/*
+ * return T if readmem style hex digit 
+ */
+static int32 is_mdataxdigit(int32 c)
+{
+ switch ((byte) c) {
+  case 'z': case 'Z': case 'x': case 'X': case '?': break;
+  default: if (isxdigit(c)) return(TRUE); else return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * routine to read readmem style binary number
+ */
+static int32 mdata_rdbin(FILE *f, int32 c)
+{
+ register char *chp;
+ register int32 len;
+ int32 nsize;
+ int32 has_bit = FALSE;
+ int32 toolong = FALSE;
+
+ for (len = 0, chp = __numtoken;;)
+  {
+   if (c ==  '_') { c = rm_getc(f); continue; } 
+   if (!is_mdatabit(c))
+    {
+     *chp = '\0';
+     if (!has_bit) return(BADOBJ);
+     /* if white space good end */
+     if (vis_white_(c))
+      {
+       /* if new line must push back for correct line counts */
+       /* impossible in string case */
+       if (c == '\n') rm_ungetc(c, f);
+       break;
+      }
+     /* SJM 09/13/99 - EOF char return for both files and strings */
+     if (c == EOF) { rm_ungetc(c, f); break; }
+     return(BADOBJ);
+    }
+   if (c == '?') c = 'X';
+   else if (isalpha(c) && isupper(c)) c = tolower(c);
+
+   if (++len >= __numtok_wid)
+    {
+     if (len >= MAXNUMBITS) 
+      {
+       if (!toolong)
+        {
+         __pv_fwarn(523, "readmemb value too wide (%d) - truncated",
+          MAXNUMBITS);
+         toolong = TRUE;
+        }
+       len--;
+      }
+     else
+      {
+       /* increase size and continue */
+       /* LOOKATME - SJM 03/20/00 - doubling may be too fast growth */
+       nsize = 2*__numtok_wid;
+       __numtoken = __my_realloc(__numtoken, __numtok_wid, nsize);
+       __numtok_wid = nsize;
+       *chp++ = c;
+      }
+    }
+   else *chp++ = c;
+
+   c = rm_getc(f);
+   has_bit = TRUE;
+  }
+ __itoklen = len;
+ return(NUMBER);
+}
+
+/*
+ * special get that allow reading from sreadmem c style string argument
+ */
+static int32 rm_getc(FILE *f)
+{
+ register int32 c;
+ int32 blen;
+
+ if (f == NULL)
+  {
+   c = *__srm_strp;
+   /* end of string means white space */
+   if (c == '\0')
+    {
+     struct xstk_t *xsp;
+
+     if (__srm_strp_len != 0)
+      __my_free(__srm_strp_beg, __srm_strp_len);
+     __srm_strp_len = 0;
+
+     /* need 2 cases for eof since, normally would push eof back first */
+     /* but when reading strings cannot do that */
+     if (__srm_xp == NULL) return(EOF);
+     if ((__srm_xp = __srm_xp->ru.x) == NULL) return(EOF);
+
+     /* eval to allow params and expressions */
+     xsp = __eval_xpr(__srm_xp->lu.x);
+     if (!vval_is0_(xsp->bp, xsp->xslen))
+      {
+       __pv_fwarn(579,
+        "sreadmem required string is x/z number (pos. %d) - x/z's ignored",
+        __srm_stargi);
+      }         
+     /* must trim away high 0's since will cause leading \0 at start */
+     blen = __trim1_0val(xsp->ap, xsp->xslen);
+     blen = ((blen + 7)/8)*8;
+
+     /* SJM 09/29/03 - change to handle sign extension and separate types */
+     if (xsp->xslen > blen) __narrow_sizchg(xsp, blen);
+     else if (xsp->xslen < blen)
+      {
+       if (__srm_xp->has_sign) __sgn_xtnd_widen(xsp, blen);
+       else __sizchg_widen(xsp, blen);
+      }
+
+     /* notice this is actual Pascal style string len, no ending \0 */
+     __srm_strp_beg = __vval_to_vstr(xsp->ap, xsp->xslen, &__srm_strp_len);
+     __srm_strp = __srm_strp_beg;
+     __pop_xstk();
+     if (__debug_flg) __dbg_msg("new sreadmem string: %s\n", __srm_strp);
+     __srm_stargi++;
+     return(' ');
+    }
+   __srm_strp++;
+   return(c);
+  }
+ return(getc(f));
+}
+
+/*
+ * special get that allow reading from sreadmem c style string argument
+ * caller's responsible to not back over front 
+ */
+static void rm_ungetc(int32 c, FILE *f)
+{
+ if (f != NULL) ungetc(c, f); else __srm_strp--;
+}
+
+/*
+ * return T if readmem style bin digit 
+ */
+static int32 is_mdatabit(int32 c)
+{
+ switch ((byte) c) {
+  case 'z': case 'Z': case 'x': case 'X': case '?': case '0': case '1':
+   break;
+  default:
+  return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * execute the sreadmem[bh] system task
+ * know 1st argument array, 2nd and 3nd range, rest strings
+ */
+extern void __exec_sreadmem(struct expr_t *argxp, int32 base)
+{
+ int32 ri1, ri2, arrwid, arr1, arr2, tmpi, nd_itpop;
+ struct expr_t *axp;
+ struct net_t *np;
+ char s1[RECLEN];
+
+ /* 1st arg. is array destination to read into */
+ axp = argxp->lu.x;
+ /* know will be array name ID or array name global reference */
+ if (axp->optyp == GLBREF)
+  {
+   __xmrpush_refgrp_to_targ(axp->ru.grp);
+   nd_itpop = TRUE;
+  }
+ else nd_itpop = FALSE;
+
+ np = axp->lu.sy->el.enp;
+ if (axp->is_real)
+  {
+   __sgferr(717, "$sreadmem%c of %s illegal - no readmem of array of reals",
+    __to_baselet(base), __msgexpr_tostr(__xs, axp));
+   goto done;
+  }
+ /* know this is array so range is array range */
+ __getarr_range(np, &ri1, &ri2, &arrwid);
+
+ arr1 = arr2 = -1;
+ argxp = argxp->ru.x;
+ /* set up addresses - start and end range must be present or fixup error */
+ axp = argxp->lu.x;
+ /* for system task arguments optyp empty not used - know arg present */
+ if (axp->optyp != OPEMPTY)
+  {
+   if ((tmpi = __comp_ndx(np, axp)) == -1)
+    {
+     __sgferr(723,
+      "$sreadmem%c start address expression %s unknown or out of range",
+      __to_baselet(base), __msgexpr_tostr(__xs, axp));
+     goto done;
+    }
+   sprintf(s1, "$sreadmem%c start", __to_baselet(base));
+   if (!chk_rm_rng_legal(tmpi, ri1, ri2, s1)) goto done;
+   arr1 = tmpi;
+  }
+ argxp = argxp->ru.x;
+ axp = argxp->lu.x;
+ if (axp->optyp != OPEMPTY)
+  {
+   if ((tmpi = __comp_ndx(np, axp)) == -1)
+    {
+     __sgferr(724,
+     "$sreadmem%c end address expression %s unknown or out of range",
+      __to_baselet(base), __msgexpr_tostr(__xs, axp));
+     goto done;
+    }
+   sprintf(s1, "$sreadmem%c end", __to_baselet(base));
+   if (!chk_rm_rng_legal(tmpi, ri1, ri2, s1)) goto done;
+   arr2 = tmpi;
+   if (arr1 == -1)
+    {
+     __sgferr(724, 
+      "$sreadmem%c end address value %d illegal - no start address",
+      __to_baselet(base), arr2);
+     goto done;
+    }
+  }
+ do_srm_xtrct(argxp->ru.x, base, np, arr1, arr2, ri1, ri2, arrwid);
+ if (__srm_strp_len != 0) __my_free(__srm_strp_beg, __srm_strp_len);
+ __srm_strp_beg = NULL;
+ __srm_strp_len = 0;
+done:
+ if (nd_itpop) __pop_itstk();
+ /* DBG remove ---
+ if (__debug_flg) __dmp_arr_all(np, __inum, __inum);
+ --- */
+}
+
+/*
+ * do the sreadmem string extraction and array filling
+ *
+ * this keeps arr1, arr2, and arri in original ranges and corrects each
+ * time for non h:0 form - could use correct range and uncorrect for msgs
+ *
+ * string can be any expr. that evaluates to string
+ */
+static void do_srm_xtrct(struct expr_t *xp, int32 base, struct net_t *np,
+ int32 arr1, int32 arr2, int32 ri1, int32 ri2, int32 arrwid)
+{
+ register int32 arri; 
+ FILE *f;
+ int32 dir, ttyp, h0_arri, nbytes, no_rngwarn, blen;
+ int32 rmfr, rmto;
+ struct xstk_t *xsp;
+
+ no_rngwarn = FALSE;
+
+ /* SJM - 06/19/00 - if only one starting range, direction toward high */
+ /* only way for downward range is arr2 not -1 and arr2 > arr1 */
+ if (arr2 != -1) { if (arr1 <= arr2) dir = 1; else dir = -1; }
+ else dir = 1;
+
+ if (arr1 == -1)
+  {
+   if (ri1 <= ri2) { rmfr = ri1; rmto = ri2; }
+   else { rmfr = ri2; rmto = ri1; }
+  }
+ else if (arr2 == -1)
+  {
+   rmfr = arr1;
+   if (ri1 <= ri2) rmto = ri2; else rmto = ri1;
+  }
+ else { rmfr = arr1; rmto = arr2; }
+
+ __srm_stargi = 1;
+ __srm_xp = xp;
+ __srm_strp_len = 0;
+ __srm_strp_beg = NULL;
+
+ /* notice must leave non printing as is and add \0 - know there is room */
+ xsp = __eval_xpr(__srm_xp->lu.x);
+ /* check for x/z (not really string) */
+ if (!vval_is0_(xsp->bp, xsp->xslen))
+  {
+   __pv_fwarn(579,
+    "sreadmem required string value is x/z number (pos. 1) - x/z's ignored");
+  }         
+ /* must trim away high 0's since will cause leading \0 at start */
+ blen = __trim1_0val(xsp->ap, xsp->xslen);
+ blen = ((blen + 7)/8)*8;
+
+ /* SJM 09/29/03 - change to handle sign extension and separate types */
+ if (xsp->xslen > blen) __narrow_sizchg(xsp, blen);
+ else if (xsp->xslen < blen)
+  {
+   if (__srm_xp->has_sign) __sgn_xtnd_widen(xsp, blen);
+   else __sizchg_widen(xsp, blen);
+  }
+
+ __srm_strp_beg = __vval_to_vstr(xsp->ap, xsp->xslen, &__srm_strp_len);
+ __srm_strp = __srm_strp_beg;
+ __pop_xstk();
+ if (__debug_flg) __dbg_msg("first sreadmem string: %s\n", __srm_strp);
+ f = NULL;
+
+ for (arri = rmfr;;)
+  {
+   /* also for sreadmem, rm_getc will have freed string ptr needed */
+   if (__srm_xp == NULL) ttyp = TEOF;
+   else ttyp = mdata_gettok(f, base);
+   if (ttyp == TEOF)
+    {
+     if (!no_rngwarn && arr2 != -1 && arri != rmto)
+      __sgfwarn(524,
+       "$sreadmem%c number of data words fewer than range size (pos. %d)",
+        __to_baselet(base), __srm_stargi);
+     return;
+    }
+   if (ttyp == BADOBJ)
+    {
+     __sgferr(725,
+      "illegal $sreadmem%c string value (pos. %d) - loading terminated",
+      __to_baselet(base), __srm_stargi);
+     break;
+    }
+   if (ttyp == RMADDR) 
+    {
+     /* convert to hex number - in __acwrk value - check number */
+     /* no error possible in here for hex since digits checked during */
+     /* token input */
+     __to_dhboval(BHEX, TRUE);
+     if (__bcwrk[0] != 0L)
+      {
+       __sgferr(726,
+       "illegal $readmem%c address value %s (pos. %d) - loading terminated",
+        __to_baselet(base), __regab_tostr(__xs, __acwrk, __bcwrk, __itoklen,
+        BHEX, FALSE), __srm_stargi);
+       return;
+      }
+     /* check for within specified range */
+     arri = (int32) __acwrk[0];
+     if ((dir == 1 && (arri < rmfr || arri > rmto))
+      || (dir == -1 && (arri > rmfr || arri < rmto)))
+      {
+       __sgferr(727,
+       "$sreadmem%c address value %lu out of range (pos. %d) - loading terminated",
+        __to_baselet(base), __acwrk[0], __srm_stargi);
+       return;
+      }
+     no_rngwarn = TRUE;
+     continue;
+    }
+   if ((dir == 1 && arri > rmto) || (dir == -1 && arri < rmto))
+    {
+     __sgfwarn(525, "$sreadmem%c extra data words ignored (pos. %d)",
+      __to_baselet(base), __srm_stargi);
+     return;
+    }
+   __to_dhboval(base, TRUE);
+
+   h0_arri = normalize_ndx_(arri, ri1, ri2); 
+
+   /* SJM 09/22/03 - modern P1364 algorithm requires chg stores for each */ 
+   /* index if memory elements appear on any assign rhs */
+   /* correct size if needed */
+   if (np->nwid != __itoklen)
+    {
+     push_xstk_(xsp, __itoklen);
+     nbytes = WRDBYTES*wlen_(__itoklen); 
+     memcpy(xsp->ap, __acwrk, nbytes);
+     memcpy(xsp->bp, __bcwrk, nbytes);
+
+     /* SJM 09/29/03 - change to handle sign extension and separate types */
+     /* SJM 05/19/04 - notice read into memory can be signed - need net wid */ 
+     if (xsp->xslen > np->nwid) __narrow_sizchg(xsp, np->nwid);
+     else if (xsp->xslen < np->nwid)
+      {
+       if (np->n_signed) __sgn_xtnd_widen(xsp, np->nwid);
+       else __sizchg_widen(xsp, np->nwid);
+      }
+
+     if (np->nchg_nd_chgstore)
+      {
+       __chg_st_arr_val(np->nva, arrwid, np->nwid, h0_arri,
+        xsp->ap, xsp->bp);
+
+       /* must only trigger change for right array index */
+       if (__lhs_changed) record_sel_nchg_(np, h0_arri, h0_arri);
+      }
+     else __st_arr_val(np->nva, arrwid, np->nwid, h0_arri, xsp->ap, xsp->bp);
+     __pop_xstk();
+    }
+   else
+    {
+     if (np->nchg_nd_chgstore)
+      {
+       __chg_st_arr_val(np->nva, arrwid, np->nwid, h0_arri,
+        __acwrk, __bcwrk);
+
+       /* must only trigger change for right array index */
+       if (__lhs_changed) record_sel_nchg_(np, h0_arri, h0_arri);
+      }
+     else __st_arr_val(np->nva, arrwid, np->nwid, h0_arri, __acwrk, __bcwrk);
+    }
+
+   /* finally increment index */
+   if (dir > 0) arri++; else arri--;
+  }
+}
+
+/*
+ * RANDOM NUMBER GENERATION ROUTINES 
+ */
+
+#define MY_LONG_MAX2 0xffffffff
+/* SJM 11/19/03 - must use 32 bit range even for 64 bit systems */ 
+/* because Verilog WBITS (for now?) must be set to 32 */
+#define MY_LONG_MAX 2147483647L
+#define MY_LONG_MIN (-MY_LONG_MAX - 1L)
+
+/*
+ * execute the random system function 
+ * this leaves new value on tos and uses a copy of the good Berkeley
+ * unix style random number generator
+ *
+ * notice pli code no longer shares random number generator
+ * this is 32 bit long int dependent
+ *
+ * SJM 11/18/03 - rewritten to make seed arg inout instead of input if used
+ * SJM 01/27/04 - seed must be C global and initialized to 0 (guess) in
+ *                case user never passes the seed argument
+ */
+extern void __exec_sfrand(struct expr_t *ndp)
+{
+ int32 ranv;
+ struct xstk_t *xsp;
+ struct expr_t *fax;
+
+ /* case 1 random with seed set - arg is inout */
+ if (ndp->ru.x != NULL && ndp->ru.x->optyp != OPEMPTY)
+  {
+   fax = ndp->ru.x->lu.x;
+   /* even though evaling, previous error if seed is not simple WBIT reg */
+   xsp = __eval_xpr(fax);
+   /* know here the argument must be a reg. that is updated */
+   /* by setting reg., user can change seed */
+   if (xsp->bp[0] != 0)
+    {
+     __sgfwarn(588,
+      "$random seed register value %s has x/z bits - a part used",
+      __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+     xsp->bp[0] = 0L;
+    }
+   __seed = (int32) xsp->ap[0]; 
+   __pop_xstk();
+
+   /* this sets the seed (acutally a state) - 1 to reset to defl. sequence */
+   /* generator returns only 31 (signed +) bits so high bit always 0 */  
+   ranv = rtl_dist_uniform(&__seed, MY_LONG_MIN, MY_LONG_MAX);
+
+   push_xstk_(xsp, WBITS);
+   xsp->bp[0] = 0L;
+   xsp->ap[0] = ranv;
+
+   /* SJM 11/19/03 - I misread LRM - if seed arg passed it is inout not in */ 
+   /* temp use of top of stack - removed before return that needs tos */
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = (word32) __seed;
+   xsp->bp[0] = 0L;
+
+   __exec2_proc_assign(fax, xsp->ap, xsp->bp);
+   __pop_xstk();
+   return; 
+  }
+
+ /* case 2: no seed passed */
+ /* SJM 01/27/04 - now if no seed passed uses last one */
+ push_xstk_(xsp, WBITS);
+ xsp->bp[0] = 0L;
+ /* generator returns only 31 (signed +) bits so high bit always 0 */  
+ ranv = rtl_dist_uniform(&__seed, LONG_MIN, LONG_MAX);
+ xsp->ap[0] = (word32) ranv;
+}
+
+/*
+ * SJM 11/19/03 - replacing $random with LRM 2001 random as suggested
+ * by standard - although BSD algorithm better (longer period), it
+ * requires 8 words of state which can't be returned in seed
+ */
+
+/*
+ * uniform distribution low level routine from 2001 LRM
+ *
+ * this is wrapper handling edge cases and returns 32 bit signed not double
+ * notice since uses double and maps back to word32 has good period 
+ */
+static sword32 rtl_dist_uniform(int32 *seed, sword32 start, sword32 end)
+{
+ double r;
+ sword32 i;
+
+ if (start >= end) return(start);
+ if (end != LONG_MAX)
+  {
+   end++;
+   r = uniform(seed, start, end);
+   if (r >= 0)
+    {
+     i = (sword32) r;
+    }
+   else
+    {
+     i = (sword32) (r - 1);
+    }
+   if (i < start) i = start;
+   if (i >= end) i = end-1;
+  }
+ else if (start != LONG_MIN)
+  {
+   start--;
+   r = uniform(seed, start, end) + 1.0;
+   if (r >= 0)
+    {
+     i = (sword32) r;
+    }
+   else
+    {
+     i = (sword32) (r - 1);
+    }
+   if (i <= start) i = start+1;
+   if (i > end) i = end;
+  }
+ else
+  {
+   r = (uniform(seed,start,end) + 2147483648.0)/4294967295.0;
+   r = r*4294967296.0 - 2147483648.0;
+   if (r >= 0)
+    {
+     i = (sword32) r;
+    }
+   else
+    {
+     i = (sword32) (r-1);
+    }
+  }
+ return(i);
+}
+
+/*
+ * uniform distribution low level routine from 2001 LRM
+ * this returns double random number
+ *
+ * BEWARE - IEEE floating point format dependent
+ */
+static double uniform(int32 *seed, sword32 start, sword32 end)
+{
+ union u_s
+  {
+   float s;
+   word32 stemp;
+  } u;
+ double d = 0.00000011920928955078125;
+ double a,b,c;
+
+ if ((*seed) == 0) *seed = 259341593;
+ if (start >= end)
+  {
+   a = 0.0;
+   b = 2147483647.0;
+  }
+ else
+  {
+   a = (double) start;
+   b = (double) end;
+  }
+ *seed = 69069 * (*seed) + 1;
+ u.stemp = *seed;
+
+ /* This relies on IEEE floating point format */
+ u.stemp = (u.stemp >> 9) | 0x3f800000;
+ c = (double) u.s;
+ c = c + (c*d);
+ c = ((b - a) * (c - 1.0)) + a;
+ return(c);
+}
+
+/*
+ * IMPLEMENT SPECIAL DISTRIBUTION ROUTINES
+ */
+
+/*
+ * return a randomly distributed integer between start and end
+ *
+ * notice requiring all 3 arguments - ,, illegal
+ *
+ * idea for left hand side seed is that normal random is returned
+ * so can be used to repeat next normal dist.
+ *
+ * algorithm maps uniformly distributed random real in 0 to 1 range to int
+ * in start to end range (integers where start or end can be negative)
+ */
+extern void __exec_dist_uniform(struct expr_t *ndp)
+{
+ int32 start, end, u2;
+ word32 val;
+ double rng, x;
+ struct expr_t *fax, *a1xp, *a2xp, *a3xp;
+ struct xstk_t *xsp, *xsp2;
+
+ /* for func passed func node not first arg */
+ fax = ndp->ru.x;
+ /* access the required 3 arguments */
+ if (fax == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = fax->lu.x;
+ if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = fax->lu.x;
+ if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a3xp = fax->lu.x;
+ if (fax->ru.x != NULL) __arg_terr(__FILE__, __LINE__);
+
+ /* all 3 arguments required */
+ if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY
+  || a3xp->optyp == OPEMPTY)
+  {
+   __sgfwarn(588,
+   "$dist_uniform arguments must not be missing (,, form) - returning 32'bx");
+   goto ret_x;
+  }
+
+ /* even though evaling, previous error if seed is not simple WBIT reg */
+ xsp = __eval_xpr(a1xp);
+ if (xsp->bp[0] != 0)
+  {
+   __sgfwarn(588,
+    "$dist_uniform seed value %s has x/z bits - returning 32'bx",
+    __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+   xsp->bp[0] = 0L;
+   __pop_xstk(); 
+ret_x:
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = ALL1W;
+   xsp->bp[0] = ALL1W;
+   return;
+  }
+ __seed = (int32) xsp->ap[0]; 
+ __pop_xstk();
+
+ if (!__get_eval_word(a2xp, &val))
+  {
+   __sgfwarn(588,
+    "$dist_uniform argument 2, start value %s x/z - returning 32'bx",
+    __msgexpr_tostr(__xs, a2xp));
+   goto ret_x;
+  }
+ start = (int32) val;
+ if (!__get_eval_word(a3xp, &val))
+  {
+   __sgfwarn(588,
+    "$dist_uniform argument 3, end value %s x/z - returning 32'bx",
+    __msgexpr_tostr(__xs, a2xp));
+   goto ret_x;
+  }
+ end = (int32) val;
+ x = uniform(&__seed, 0, 1); 
+
+ /* LOOKATME - maybe: rng = (double) (end - start); */
+ rng = (double) (end - start + 1);
+ /* FIXME - does this round right? */
+ u2 = start + ((int32) (rng*x));
+
+ push_xstk_(xsp, WBITS);
+ xsp->bp[0] = 0L;
+ /* notice generator returns only 31 (signed +) bits so high bit always 0 */  
+ xsp->ap[0] = (word32) u2;
+
+ push_xstk_(xsp2, WBITS);
+ xsp2->ap[0] = (word32) __seed;
+ xsp2->bp[0] = 0L;
+ __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
+ __pop_xstk();
+}
+
+/*
+ * return randomly distributed int std. normal dist - std. dev. 'standard_dev'
+ * and mean 'mean'
+ *
+ * notice requiring all 3 arguments - ,, illegal
+ *
+ * algorithm uses ratio method to map uniform random real in 0 to 1 range
+ * into standard normal with mean 0.0 and standard deviation 1.0
+ * then convert to integer with translated standard_Dev and mean mean
+ *
+ * i.e. if mean is same 0 and standard_dev is same 1.0 only will return ints
+ * -4 to 4 nearly all the time (>4 standard devs rare)
+ */
+extern void __exec_dist_stdnorm(struct expr_t *ndp)
+{
+ int32 mean, std_dev, u2;
+ word32 val;
+ double x, u;
+ struct expr_t *fax, *a1xp, *a2xp, *a3xp;
+ struct xstk_t *xsp, *xsp2;
+
+ /* for func passed func node not first arg */
+ fax = ndp->ru.x;
+ /* access the required 3 arguments */
+ if (fax == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = fax->lu.x;
+ if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = fax->lu.x;
+ if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a3xp = fax->lu.x;
+ if (fax->ru.x != NULL) __arg_terr(__FILE__, __LINE__);
+
+ /* all 3 arguments required */
+ if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY
+  || a3xp->optyp == OPEMPTY)
+  {
+   __sgfwarn(588,
+   "$dist_normal arguments must not be missing (,, form) - returning 32'bx");
+   goto ret_x;
+  }
+
+ /* even though evaling, previous error if seed is not simple WBIT reg */
+ xsp = __eval_xpr(a1xp);
+ if (xsp->bp[0] != 0)
+  {
+   __sgfwarn(588,
+    "$dist_normal seed value %s has x/z bits - returning 32'bx",
+    __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+   xsp->bp[0] = 0L;
+   __pop_xstk(); 
+ret_x:
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = ALL1W;
+   xsp->bp[0] = ALL1W;
+   return;
+  }
+ __seed = (int32) xsp->ap[0]; 
+ __pop_xstk();
+
+ if (!__get_eval_word(a2xp, &val))
+  {
+   __sgfwarn(588,
+    "$dist_normal argument 2, mean value %s x/z - returning 32'bx",
+    __msgexpr_tostr(__xs, a2xp));
+   goto ret_x;
+  }
+ mean = (int32) val;
+ if (!__get_eval_word(a3xp, &val))
+  {
+   __sgfwarn(588,
+    "$dist_normal argument 3, standard_dev value %s x/z - returning 32'bx",
+    __msgexpr_tostr(__xs, a2xp));
+   goto ret_x;
+  }
+ std_dev = (int32) val;
+
+ /* get the standard normal deviate (stddev=1.0, mean = 0.0) */
+ x = stdnorm_dev(&__seed);
+
+ /* map to real with passed std_dev and mean */
+ u = (double) mean + x*((double) std_dev);
+ /* then to int32 using Verilog round rules */
+ u2 = ver_rint_(u);
+
+ push_xstk_(xsp, WBITS);
+ xsp->bp[0] = 0L;
+ /* notice generator returns only 31 (signed +) bits so high bit always 0 */  
+ xsp->ap[0] = (word32) u2;
+
+ push_xstk_(xsp2, WBITS);
+ xsp2->ap[0] = (word32) __seed;
+ xsp2->bp[0] = 0L;
+ __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
+ __pop_xstk();
+}
+
+/*
+ * generate standard norm with median 0 and standard deviation 1
+ *
+ * from Knuth - Seminumerical algorithms - uses ratio method
+ */
+static double stdnorm_dev(int32 *seed)
+{
+ double u, v, x;
+
+ /* generate two uniform deviates in 0.0 to 1.0 (u non 0) */
+ for (;;)
+  {
+   do { u = uniform(seed, 0, 1); } while (u == 0.0); 
+   v = uniform(seed, 0, 1); 
+
+   x = (sqrt(8.0/M_E)*(v - 0.5))/u; 
+   if (x*x <= -4.0/log(u)) return(x); 
+  }
+}
+
+/*
+ * return randomly distributed exponential with mean 'mean'
+ * returns values with average mean 
+ *
+ * notice requiring both arguments - ,, illegal
+ *
+ * algorithm uses a=1 case of gamma deviate with mean 1.0
+ *
+ * i.e. if mean is same 1 - values from 0 to inf with mean 1
+ */
+extern void __exec_dist_exp(struct expr_t *ndp)
+{
+ int32 mean, u2;
+ word32 val;
+ double x, u;
+ struct expr_t *fax, *a1xp, *a2xp;
+ struct xstk_t *xsp, *xsp2;
+
+ /* for func passed func node not first arg */
+ fax = ndp->ru.x;
+ /* access the required 2 arguments */
+ if (fax == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = fax->lu.x;
+ if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = fax->lu.x;
+
+ /* both arguments required */
+ if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY)
+  {
+   __sgfwarn(588,
+   "$dist_exponential arguments must not be missing (,, form) - returning 32'bx");
+   goto ret_x;
+  }
+
+ /* even though evaling, previous error if seed is not simple WBIT reg */
+ xsp = __eval_xpr(a1xp);
+ if (xsp->bp[0] != 0)
+  {
+   __sgfwarn(588,
+    "$dist_exponential seed value %s has x/z bits - returning 32'bx",
+    __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+   xsp->bp[0] = 0L;
+   __pop_xstk(); 
+ret_x:
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = ALL1W;
+   xsp->bp[0] = ALL1W;
+   return;
+  }
+ __seed = (int32) xsp->ap[0]; 
+ __pop_xstk();
+
+ if (!__get_eval_word(a2xp, &val))
+  {
+   __sgfwarn(588,
+    "$dist_exponential argument 2, mean value %s x/z - returning 32'bx",
+    __msgexpr_tostr(__xs, a2xp));
+   goto ret_x;
+  }
+ mean = (int32) val;
+
+ /* get the gamma deviate (mean = 1.0, ) */
+ x = gamma_dev((double) 1, &__seed);
+
+ /* map to real mean mean (expand by multiplying here */
+ u = x*((double) mean);
+ /* then to int32 (but will always be positive) using Verilog round rules */
+ u2 = ver_rint_(u);
+
+ push_xstk_(xsp, WBITS);
+ xsp->bp[0] = 0L;
+ /* notice generator returns only 31 (signed +) bits so high bit always 0 */  
+ xsp->ap[0] = (word32) u2;
+
+ push_xstk_(xsp2, WBITS);
+ xsp2->ap[0] = (word32) __seed;
+ xsp2->bp[0] = 0L;
+ __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
+ __pop_xstk();
+}
+
+/*
+ * gamma deviate from normal deviate of order xia
+ * returns real with mean around 1.0
+ * 
+ * using seed random seed and setting seed to last generated
+ * again from Numerical Recipes
+ * caller must have checked arguments
+ */
+static double gamma_dev(double xa, int32 *seed)
+{
+ double am, e, s, v1, v2, x, y;
+
+ if (xa < 1.0) __arg_terr(__FILE__, __LINE__); 
+ /* direct method for order 1 - exponential */
+ if (xa == 1.0) { x = uniform(seed, 0, 1); x = -log(x); return(x); }
+
+ /* rejection method for any higher order - works for non integal */
+ do {
+  do {  
+   do {
+    v1 = uniform(seed, 0, 1);
+    v2 = 2.0*uniform(seed, 0, 1) - 1.0;
+   } while (v1*v1 + v2*v2 > 1.0);
+   y = v2/v1;
+   am = xa - 1.0;
+   s = sqrt(2.0*am + 1.0);
+   x = s*y + am;   
+  } while (x <= 0.0);
+  e = (1.0 + y*y)*exp(am*log(x/am) - s*y);
+ } while (uniform(seed, 0, 1) > e);
+ return(x);
+}
+
+/*
+ * return randomly distributed poisson distribution integer value
+ *with mean 'mean'
+ *
+ * notice requiring both arguments - ,, illegal
+ * almost same as gamm dist. but integral so computation different
+ *
+ * algorithm uses rejection method poisson routine from Numerical
+ * Recipes this is integral distribution related to binomial
+ */
+extern void __exec_dist_poisson(struct expr_t *ndp)
+{
+ int32 mean, u2;
+ word32 val;
+ struct expr_t *fax, *a1xp, *a2xp;
+ struct xstk_t *xsp, *xsp2;
+
+ /* for func passed func node not first arg */
+ fax = ndp->ru.x;
+ /* access the required 2 arguments */
+ if (fax == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = fax->lu.x;
+ if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = fax->lu.x;
+
+ /* both arguments required */
+ if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY)
+  {
+   __sgfwarn(588,
+   "$dist_poisson arguments must not be missing (,, form) - returning 32'bx");
+   goto ret_x;
+  }
+
+ /* even though evaling, previous error if seed is not simple WBIT reg */
+ xsp = __eval_xpr(a1xp);
+ if (xsp->bp[0] != 0)
+  {
+   __sgfwarn(588,
+    "$dist_poisson seed value %s has x/z bits - returning 32'bx",
+    __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+   xsp->bp[0] = 0L;
+   __pop_xstk(); 
+ret_x:
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = ALL1W;
+   xsp->bp[0] = ALL1W;
+   return;
+  }
+ __seed = (int32) xsp->ap[0]; 
+ __pop_xstk();
+
+ if (!__get_eval_word(a2xp, &val))
+  {
+   __sgfwarn(588,
+    "$dist_poisson argument 2, mean value %s x/z - returning 32'bx",
+    __msgexpr_tostr(__xs, a2xp));
+   goto ret_x;
+  }
+ mean = (int32) val;
+
+ /* get the gamma deviate (mean = 1.0, ) */
+ u2 = poisson_dev(mean, &__seed);
+
+ push_xstk_(xsp, WBITS);
+ xsp->bp[0] = 0L;
+ xsp->ap[0] = (word32) u2;
+
+ push_xstk_(xsp2, WBITS);
+ xsp2->ap[0] = (word32) __seed;
+ xsp2->bp[0] = 0L;
+ __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
+ __pop_xstk();
+}
+
+/*
+ * poission deviate using rejection method (exp for small)
+ * 
+ * using seed random seed and setting seed to last generated
+ * random number
+ *
+ * again from Numerical Recipes
+ */
+static int32 poisson_dev(int32 ixm, int32 *seed)
+{
+ int32 iem;
+ double em, g, t, xm, sq, alxm, y; 
+
+ /* direct method for small order */
+ if (ixm < 12) 
+  {
+   g = exp((double) ixm);
+   t = 1.0;
+   iem = -1;
+   do {
+    ++iem;
+    /* "multiplying uniform deviates same as adding exp"? */
+    t *= uniform(seed, 0, 1);
+   } while (t > g);
+   return(iem);
+  }
+
+ /* otherwise use bounded region rejection method */
+ xm = (double) ixm;
+ sq = sqrt(2.0*ixm);  
+ alxm = log (xm);
+ g = xm*alxm - log_gamma(xm + 1.0);
+ do {
+  do {
+   y = tan(M_PI*uniform(seed, 0, 1));
+   em = sq*y + xm;
+   /* reject if in region of 0 probability */
+  } while (em < 0.0); 
+  /* maybe follow Verilog convention should be rounded? */
+  iem = (int32) floor(em);
+  t = 0.9 + (1.0*y*y)*exp(em*alxm - log_gamma(em + 1.0) - g);
+ /* rejection by probability preserving ratio step */
+ } while (uniform(seed, 0, 1) > t);
+ return(iem);
+}
+
+static double gamma_powser_coeff[6] = { 76.18009172947146,
+ -86.50532032941677, 24.01409824083091, -1.231739572450155,
+ 0.1208650973866179E-2, -0.5395239384953E-5 };
+
+/*
+ * log gamma (gamma large so better to calculate with log)
+ *
+ * This follows method in Numerical Recipes in C
+ */
+static double log_gamma(double d1)
+{
+ register int32 j;
+ double y, x, tmp, ser;
+ 
+ y = x = d1;
+ tmp = x + 5.5;
+ tmp -= (x + 0.5)*log(tmp);
+ ser = 1.000000000190015;
+ for (j = 0; j <= 5; j++) ser += gamma_powser_coeff[j]/++y;
+ return(-tmp + log(2.5066282746310005*ser/x));
+}
+
+/*
+ * return randomly distributed chi-square with freedeg degrees
+ * of freedom
+ *
+ * notice requiring both arguments - ,, illegal
+ *
+ * algorithm uses gamma dist. of order v/2 and mean 1
+ */
+extern void __exec_chi_square(struct expr_t *ndp)
+{
+ int32 u2;
+ word32 val;
+ double x, u;
+ struct expr_t *fax, *a1xp, *a2xp;
+ struct xstk_t *xsp, *xsp2;
+
+ /* for func passed func node not first arg */
+ fax = ndp->ru.x;
+ /* access the required 2 arguments */
+ if (fax == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = fax->lu.x;
+ if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = fax->lu.x;
+
+ /* both arguments required */
+ if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY)
+  {
+   __sgfwarn(588,
+   "$chi_square arguments must not be missing (,, form) - returning 32'bx");
+   goto ret_x;
+  }
+
+ /* although evaling, previous error if seed is not simple WBIT reg */
+ xsp = __eval_xpr(a1xp);
+ if (xsp->bp[0] != 0)
+  {
+   __sgfwarn(588,
+    "$dist_chi_square seed value %s has x/z bits - returning 32'bx",
+    __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+   xsp->bp[0] = 0L;
+   __pop_xstk(); 
+ret_x:
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = ALL1W;
+   xsp->bp[0] = ALL1W;
+   return;
+  }
+ __seed = (int32) xsp->ap[0]; 
+ __pop_xstk();
+
+ if (!__get_eval_word(a2xp, &val))
+  {
+   __sgfwarn(588,
+    "$dist_chi_square argument 2, degree_of_freedom value %s x/z - returning 32'bx",
+    __msgexpr_tostr(__xs, a2xp));
+   goto ret_x;
+  }
+ /* look at me - are odd case right?, i.e. does rounding work? */
+ /* for <= 2 degress of freedom same as exponential */
+ u = val;
+ if (u <= 2.0) u = 1.0; else u = u/2.0;
+
+ /* chi-square is 2 times gamma deviate of degree_of_freedom/2 */
+ x = gamma_dev(u, &__seed);
+
+ /* map to real mean for chi-square always 1 */
+ /* then to int32 (will always be positive) using Verilog round rules */
+ u2 = ver_rint_(x);
+
+ push_xstk_(xsp, WBITS);
+ xsp->bp[0] = 0L;
+ /* notice generator returns only 31 (signed +) bits so high bit always 0 */  
+ xsp->ap[0] = (word32) u2;
+
+ push_xstk_(xsp2, WBITS);
+ xsp2->ap[0] = (word32) __seed;
+ xsp2->bp[0] = 0L;
+ __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
+ __pop_xstk();
+}
+
+/*
+ * return randomly distributed t-distribution with freedeg degrees
+ * of freedom
+ *
+ * notice requiring both arguments - ,, illegal
+ *
+ * t distribution is std normal (real) Y1 with mean 1 and var. 0
+ * and chi-square Y2 with v degress of freed and mean 1 (see above)
+ * t is then y1/sqrt(y2/v)
+ */
+extern void __exec_dist_t(struct expr_t *ndp)
+{
+ int32 u2;
+ word32 val;
+ double y1, y2, x, u, v;
+ struct expr_t *fax, *a1xp, *a2xp;
+ struct xstk_t *xsp, *xsp2;
+
+ /* for func passed func node not first arg */
+ fax = ndp->ru.x;
+ /* access the required 2 arguments */
+ if (fax == NULL) __arg_terr(__FILE__, __LINE__);
+ a1xp = fax->lu.x;
+ if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
+ a2xp = fax->lu.x;
+
+ /* both arguments required */
+ if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY)
+  {
+   __sgfwarn(588,
+   "$dist_t arguments must not be missing (,, form) - returning 32'bx");
+   goto ret_x;
+  }
+
+ /* although evaling, previous error if seed is not simple WBIT reg */
+ xsp = __eval_xpr(a1xp);
+ if (xsp->bp[0] != 0)
+  {
+   __sgfwarn(588,
+    "$dist_t seed value %s has x/z bits - returning 32'bx",
+    __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+   xsp->bp[0] = 0L;
+   __pop_xstk(); 
+ret_x:
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = ALL1W;
+   xsp->bp[0] = ALL1W;
+   return;
+  }
+ __seed = (int32) xsp->ap[0]; 
+ __pop_xstk();
+
+ if (!__get_eval_word(a2xp, &val))
+  {
+   __sgfwarn(588,
+    "$dist_t argument 2, degree_of_freedom value %s x/z - returning 32'bx",
+    __msgexpr_tostr(__xs, a2xp));
+   goto ret_x;
+  }
+ /* look at me - are odd case right?, i.e. does rounding work? */
+ /* for <= 2 degress of freedom same as exponential */
+ v = (double) val;
+ if (v <= 2.0) u = 1.0; else u = v/2.0;
+
+
+ /* Y1 is stdnorm with 0 mean and 1.0 variance */
+ y1 = stdnorm_dev(&__seed);
+
+ /* Y2 real chi-square is 2*gamma deviate of degree_of_freedom/2 */
+ y2 = gamma_dev(u, &__seed);
+ x = y1/sqrt(y2/v); 
+
+ /* map to real mean for chi-square always 1 */
+ /* then to int32 (will always be positive) using Verilog round rules */
+ u2 = ver_rint_(x);
+
+ push_xstk_(xsp, WBITS);
+ xsp->bp[0] = 0L;
+ /* generator returns only 31 (signed +) bits so high bit always 0 */  
+ xsp->ap[0] = (word32) u2;
+
+ push_xstk_(xsp2, WBITS);
+ xsp2->ap[0] = (word32) __seed;
+ xsp2->bp[0] = 0L;
+ __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
+ __pop_xstk();
+}
+
+/*
+ * SPECIAL OPERATOR EVALUATION ROUTINES
+ */
+
+/*
+ * evaluate a rhs concatenate on to top of reg stack
+ * key is that { op. node width is same as starting high bit of value
+ *
+ * this requires inst ptr set
+ */
+extern void __rhs_concat(struct expr_t *lcbndp)
+{
+ register int32 catxlen;
+ register struct expr_t *catndp, *catrhsx; 
+ register word32 *ap, *bp;
+ word32 *wp, *sawp, *sbwp, tmpa, tmpb;
+ int32 wlen, bi1;
+ struct xstk_t *catreg, *xsp;
+ struct net_t *np;
+
+ /* build concatenate from high (right) to low since faster */
+ push_xstk_(catreg, lcbndp->szu.xclen);
+ ap = catreg->ap;
+ bp = catreg->bp;
+ /* never z extend for rhs concat eval. - only assigns */
+ zero_allbits_(ap, catreg->xslen);
+ zero_allbits_(bp, catreg->xslen);
+
+ /* now evaluate components and assign to section of ap/bp */
+ /* first concat component is highest bit(s) so work from high bits to low */ 
+ for (catndp = lcbndp->ru.x; catndp != NULL; catndp = catndp->ru.x)
+  {
+   /* catrhsx actual rhs concat component expr. with width catxlen */
+   catrhsx = catndp->lu.x;
+   catxlen = catrhsx->szu.xclen;
+   /* catndp comma node is dist. to low bit, bi1 is low bit of rhs psel */
+   bi1 = catndp->szu.xclen - catxlen;
+
+   /* DBG remove ---
+   if (__debug_flg)
+    __dbg_msg(
+     "+++rhs: total concat wid=%u, low index=%d, wid=%u, remaining wid=%u\n",
+      lcbndp->szu.xclen, bi1, catxlen, catndp->szu.xclen);
+   --- */ 
+   switch ((byte) catrhsx->optyp) {
+    /* notice IS number just falls through to expr load case */ 
+    case NUMBER:
+     wlen = wlen_(catxlen);
+     sawp = &(__contab[catrhsx->ru.xvi]);
+     sbwp = &(sawp[wlen]);
+do_lhssel:
+     /* notice lhs bsel takes value not ptr to value */
+     if (catxlen == 1)
+      { __lhsbsel(ap, bi1, sawp[0]); __lhsbsel(bp, bi1, sbwp[0]); }
+     else
+      {
+       __lhspsel(ap, bi1, sawp, catxlen);
+       __lhspsel(bp, bi1, sbwp, catxlen);
+      }
+     break;
+    case ISNUMBER:
+     wlen = wlen_(catxlen);
+     wp = &(__contab[catrhsx->ru.xvi]);
+     sawp = &(wp[2*wlen*__inum]);
+     sbwp = &(sawp[wlen]);
+     goto do_lhssel;
+    case ID:
+     /* optimize if fits in word32 case - else just use eval mechanism */
+     if (catxlen <= WBITS)
+      {
+       np = catrhsx->lu.sy->el.enp;
+       /* cannot optimize more because can be scalar or strength rep */ 
+       __ld_wire_val(&tmpa, &tmpb, np);
+       if (catxlen == 1)
+	{
+	 __lhsbsel(ap, bi1, tmpa & 1L);
+	 __lhsbsel(bp, bi1, tmpb & 1L);
+	}
+       else
+	{
+         __lhspsel(ap, bi1, &tmpa, catxlen);
+         __lhspsel(bp, bi1, &tmpb, catxlen);
+	}
+       break;
+      }
+     /* > WBITS so fall thru */
+     /* cases PARTSEL, LSB, GLBREF, ... fall thru */
+     /* just evaluate normally */
+     /* and then assigned like a normal expression */
+     /* so far do not have a way of doing these special cases faster */
+    default:
+     xsp = __eval2_xpr(catrhsx);
+     /* get rid of this stuff when debugged */
+     /* expression in concatenate has wrong width */
+     if (xsp->xslen != catxlen) __misc_terr(__FILE__, __LINE__);
+     if (catxlen == 1)
+      { __lhsbsel(ap, bi1, xsp->ap[0]); __lhsbsel(bp, bi1, xsp->bp[0]); }
+     else
+      {
+       __lhspsel(ap, bi1, xsp->ap, catxlen);
+       __lhspsel(bp, bi1, xsp->bp, catxlen);
+      }
+     __pop_xstk();
+   }
+  }
+}
+
+/*
+ * load rhs only address of a part of contiguous coded variable
+ * returned value is read only - must use st_ routines to store
+ *
+ * this must not be used for strength values
+ * for scalars and packed moves to tmp so not really load address
+ * i.e. address returned cannot be indirectly stored into
+ * 
+ * notice xmr must be converted to net before here 
+ */
+extern void __ld_addr(word32 **aap, word32 **abp, register struct net_t *np)
+{
+ register word32 *ap, *bp;
+ register int32 wlen;
+
+ switch ((byte) np->srep) {
+  case SR_VEC:
+   wlen = wlen_(np->nwid);
+   ap = &(np->nva.wp[2*wlen*__inum]);
+   bp = &(ap[wlen]);
+   break;
+  case SR_SCAL:
+   ap = __addrtmp;
+   bp = &(__addrtmp[1]);
+   ld_scalval_(ap, bp, np->nva.bp);
+   break;
+  default: __case_terr(__FILE__, __LINE__); return;
+ }
+ *aap = ap;
+ *abp = bp;
+}
+
+/*
+ * evaluate a question ?: expression
+ *
+ * SJM 01/14/99 - fixed bug - previously always evaluatged expr 1 and 2
+ * that was wrong since only need to do that if selector has x/z bits
+ */
+extern void __eval_qcol(register struct expr_t *ndp)
+{
+ struct xstk_t *xspq, *xsp1, *xsp2;
+
+ xspq = __eval_xpr(ndp->lu.x);
+ /* case 1: some x bits in selector, need both to be result (widest) wide */
+ if (!vval_is0_(xspq->bp, xspq->xslen))
+  {
+   xsp1 = __eval_xpr(ndp->ru.x->lu.x);
+   xsp2 = __eval_xpr(ndp->ru.x->ru.x);
+   /* xspq overwritten with x case (i.e. 2 down from top) */
+   /* SJM 09/30/03 - select self determined so may or may not be signed */
+   /* : operands either both signed or neither signed */
+   lxqcol(xspq, xsp1, xsp2, ndp->szu.xclen, ndp->lu.x->has_sign,
+    ndp->ru.x->lu.x->has_sign);
+   /* pop top 2 arguments leaving result that is always down 2 */
+   __pop_xstk();
+   __pop_xstk();
+   return;
+  }
+ /* case 2: non x/z selector */
+ /* case 2a: non 0 is true - only evaluate first for non x/z selector */
+ if (!vval_is0_(xspq->ap, xspq->xslen))
+  {
+   /* pop selector */
+   __pop_xstk();
+   /* evaluate expression 1 */ 
+   xsp1 = __eval_xpr(ndp->ru.x->lu.x);
+
+   /* need to change width to widest if 1 and 2 differ */
+   /* SJM 09/30/03 - widen only but can be sign extend */
+   if (xsp1->xslen != ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
+     else __sizchg_widen(xsp1, ndp->szu.xclen);
+    }
+   return;
+  }
+ /* case 2b: 0 is FALSE - only evaluate first for non x/z selector */
+ /* pop selector */
+ __pop_xstk();
+ /* evaluate expression 2 */ 
+ xsp1 = __eval_xpr(ndp->ru.x->ru.x);
+ /* need to change width to widest if 1 and 2 differ */
+
+ /* need to change width to widest if 1 and 2 differ */
+ /* SJM 09/30/03 - widen only but can be sign extend */
+ if (xsp1->xslen < ndp->szu.xclen)
+  {
+   if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
+   else __sizchg_widen(xsp1, ndp->szu.xclen);
+  }
+}
+
+/*
+ * eval real ?: both condition and : operands reals
+ *
+ * SJM 01/14/99 - fixed bug - previously always evaluated expr 1 and 2
+ * that was always wrong for reals 
+ */
+extern void __eval_realrealqcol(register struct expr_t *ndp)
+{
+ double d1;
+ register struct xstk_t *xspq, *xsp;
+ register struct expr_t *xp;
+
+ /* know this is real to get here */
+ xspq = __eval2_xpr(ndp->lu.x);
+ memcpy(&d1, xspq->ap, sizeof(double));
+
+ /* T case - evaluate first */
+ if (d1 != 0.0)
+  {
+   __pop_xstk();
+   xp = ndp->ru.x->lu.x;
+   xsp = __eval_xpr(xp);
+   if (xp->cnvt_to_real)
+    {
+     d1 = __cnvt_stk_to_real(xsp, (xp->has_sign == 1));
+     /* this works because minimum stack every allocated is 8 bytes */
+     /* PORTABILITY - stack must always be at least 8 bytes */
+     memcpy(xsp->ap, &d1, sizeof(double));
+    }
+   return;
+  }
+ /* F case - evaluate 2nd */
+ __pop_xstk();
+ xp = ndp->ru.x->ru.x;
+ xsp = __eval_xpr(xp);
+ if (xp->cnvt_to_real)
+  {
+   d1 = __cnvt_stk_to_real(xsp, (xp->has_sign == 1));
+   /* this works because minimum stack every allocated is 8 bytes */
+
+   /* PORTABILITY - stack must always be at least 8 bytes */
+   memcpy(xsp->ap, &d1, sizeof(double));
+  }
+}
+
+/*
+ * eval realreg ?: condition real but : operands regs
+ *
+ * SJM 01/14/99 - fixed bug - previously always evaluated expr 1 and 2
+ * now since selector real only evaluate right one
+ */
+extern void __eval_realregqcol(struct expr_t *ndp)
+{
+ struct xstk_t *xspq, *xsp;
+ double d1;
+
+ xspq = __eval_xpr(ndp->lu.x);
+ memcpy(&d1, xspq->ap, sizeof(double));
+ /* case 2a: non 0 is true - only evaluate first for non x/z selector */
+ if (d1 != 0.0)
+  {
+   /* pop selector */
+   __pop_xstk();
+   /* evaluate expression 1 */ 
+   xsp = __eval_xpr(ndp->ru.x->lu.x);
+   /* need to change width to widest if 1 and 2 differ */
+
+   /* need to change width to widest if 1 and 2 differ */
+   /* SJM 09/30/03 - widen only but can be sign extend */
+   if (xsp->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp, ndp->szu.xclen);
+     else __sizchg_widen(xsp, ndp->szu.xclen);
+    }
+   return;
+  }
+ /* case 2b: 0 is FALSE - only evaluate first for non x/z selector */
+ /* pop selector */
+ __pop_xstk();
+ /* evaluate expression 2 */ 
+ xsp = __eval_xpr(ndp->ru.x->ru.x);
+ /* need to change width to widest if 1 and 2 differ */
+ /* SJM 09/30/03 - widen only but can be sign extend */
+ if (xsp->xslen < ndp->szu.xclen)
+  {
+   if (ndp->has_sign) __sgn_xtnd_widen(xsp, ndp->szu.xclen);
+   else __sizchg_widen(xsp, ndp->szu.xclen);
+  }
+}
+
+/*
+ * eval regreal ?: condition reg but : operands real
+ *
+ * SJM 01/14/99 - fixed bug - previously always evaluated expr 1 and 2
+ * now only evaluate if selector has x/z bits 
+ */
+extern void __eval_regrealqcol(register struct expr_t *ndp)
+{
+ register struct xstk_t *xspq, *xsp;
+ register struct expr_t *xp;
+ double d1;
+
+ xspq = __eval_xpr(ndp->lu.x);
+ /* case 1: selector has x/z bits */
+ if (!vval_is0_(xspq->bp, xspq->xslen))
+  {
+   __sgferr(730,
+     "?: operator select condition x/z but values are real - 0.0 returned");
+   d1 = 0.0;
+   memcpy(xspq->ap, &d1, sizeof(double));
+   return;
+  }
+
+ /* T (non zero) case */
+ if (!vval_is0_(xspq->ap, xspq->xslen))
+  {
+   __pop_xstk();
+   xp = ndp->ru.x->lu.x;
+   xsp = __eval_xpr(xp);
+   if (xp->cnvt_to_real)
+    {
+     d1 = __cnvt_stk_to_real(xsp, (xp->has_sign == 1));
+     /* this works because minimum stack every allocated is 8 bytes */
+
+     /* PORTABILITY - stack must always be at least 8 bytes */
+     memcpy(xsp->ap, &d1, sizeof(double));
+    }
+   return;
+  }
+ /* F case */
+ __pop_xstk();
+ xp = ndp->ru.x->ru.x;
+ xsp = __eval_xpr(xp);
+ if (xp->cnvt_to_real)
+  {
+   d1 = __cnvt_stk_to_real(xsp, (xp->has_sign == 1));
+   /* this works because minimum stack every allocated is 8 bytes */
+   /* PORTABILITY - stack must always be at least 8 bytes */
+   memcpy(xsp->ap, &d1, sizeof(double));
+  }
+}
+
+/*
+ * evaluate a qcol x form (at least one x bit) truth table
+ *
+ * notice this overwrites conditional but works because once know any x's
+ * in conditional, then value obtained purely from combination of args.
+ * LOOKATME - one word32 form could be more efficient but used for all
+ *
+ * SJM 09/30/03 - need different widen if signed - : operand either both
+ * signed or both no signed
+ */
+static void lxqcol(register struct xstk_t *xspq, register struct xstk_t *xsp1,
+ register struct xstk_t *xsp2, int32 opbits, int32 sel_sign, int32 col_sign)
+{
+ register int32 wi;
+ word32 *resap, *resbp;
+ struct xstk_t *tmpq;
+ int32 wlen, ubits;
+
+ /* LOOKATME - LRM 2.0 is wrong to match OVIsim any 1 in value is T */ 
+ /* any one implies use T */
+ /* notice must use qcol word32 width here */
+ wlen = wlen_(xspq->xslen);
+ for (wi = 0; wi < wlen; wi++)
+  { if ((xspq->ap[wi] & ~xspq->bp[wi]) != 0) goto true_has_1bit; }
+
+ wlen = wlen_(opbits);
+ 
+ /* SJM 09/30/03 - widen only but can be sign extend - know : opands same */
+ if (xsp1->xslen < opbits)
+  {
+   if (col_sign) __sgn_xtnd_widen(xsp1, opbits);
+   else __sizchg_widen(xsp1, opbits);
+  }
+ if (xsp2->xslen < opbits)
+  {
+   if (col_sign) __sgn_xtnd_widen(xsp2, opbits);
+   else __sizchg_widen(xsp2, opbits);
+  }
+
+ /* SJM 05/21/04 - if select is wider need to narrow it - the : arms */ 
+ /* can only be widened because max width set in return val node */
+ if (xspq->xslen > opbits) __narrow_sizchg(xspq, opbits);
+ else if (xspq->xslen < opbits)
+  {
+   if (sel_sign) __sgn_xtnd_widen(xspq, opbits);
+   else __sizchg_widen(xspq, opbits);
+  }
+
+ resap = xspq->ap; resbp = xspq->bp;
+ for (wi = 0; wi < wlen; wi++)
+  {
+   /* widened already with 0's before using table */
+   /* truth table is 0-0 = 0, 1-1 = 1, else x */
+   resbp[wi] = xsp2->bp[wi] | xsp1->bp[wi] | (xsp2->ap[wi] ^ xsp1->ap[wi]);
+   /* if resbp bit zero, know either both 1 or both 0 */
+   resap[wi] = resbp[wi] | xsp1->ap[wi];
+  }
+ ubits = ubits_(opbits);
+ resap[wlen - 1] &= __masktab[ubits];
+ resbp[wlen - 1] &= __masktab[ubits];
+ return;
+
+true_has_1bit:
+ /* T case because at least one bit 1 */
+ /* just shuffle pointers to stack regs here */
+ tmpq = __xstk[__xspi - 2];
+ __xstk[__xspi - 2] = __xstk[__xspi - 1];
+ __xstk[__xspi - 1] = tmpq; 
+}
+
+/*
+ * ROUTINES TO EVALUATE NORMAL UNARY OPERATORS
+ */
+
+/*
+ * evaluate a unary operator
+ * replaces tos expr. value with result
+ * for now routine always uses long form, need too routines
+ *
+ * never need stack conversion here to real because will not be real op
+ * if operand not real
+ */
+static void eval_unary(struct expr_t *ndp)
+{
+ register word32 op1a, op1b;
+ register struct xstk_t *xsp;
+ word32 mask;
+ int32 ida;
+ double d1;
+
+ xsp = __eval2_xpr(ndp->lu.x);
+ /* notice double must not be > WBITS (i.e 64 bits no b part - width WBITS) */ 
+ if (ndp->szu.xclen > WBITS || xsp->xslen > WBITS)
+  {
+   eval_wide_unary(ndp, xsp); 
+   return;
+  }
+ op1a = xsp->ap[0];
+ op1b = xsp->bp[0]; 
+
+ /* SJM 03/11/02 - beware - this uses fact that op1b same as xsp b part */
+ /* operand so if op1b 0, know xsp, bp part also 0 */
+ switch ((byte) ndp->optyp) {
+  /* both unary and binary but used as unary here */
+  case /* + */ PLUS:
+   /* plus removed (no op) before here */
+   __misc_terr(__FILE__, __LINE__);
+   return;
+  case /* - */ MINUS:
+   /* only if operand value too wide, need mask to narrow */
+   if (op1b == 0L)
+    {
+     if (ndp->has_sign && ndp->lu.x->szu.xclen != WBITS)
+      {
+       /* SJM 06/01/04 - may need to sign extend operand */
+       if ((op1a & (1 << (ndp->lu.x->szu.xclen - 1))) != 0) 
+        op1a |= ~(__masktab[ndp->lu.x->szu.xclen]);
+      } 
+     /* convert to signed 32 bit then copy back to word32 */
+     /* works because narrower than 32 signed extended already */
+     ida = (int32) op1a;
+     xsp->ap[0] = ((word32) -ida) & __masktab[ndp->szu.xclen];
+    }
+   else xsp->ap[0] = xsp->bp[0] = __masktab[ndp->szu.xclen];
+   return;
+  case /* real - */ REALMINUS:
+   /* notice double may be on only 4 byte boundary so need to copy and op */
+   /* also width of xsp is WBITS - 8 bytes for double - known real */ 
+   /* FIXME ??? - this is stupid - should use endianness */
+   memcpy(&d1, xsp->ap, sizeof(double));   
+   d1 = -d1;
+   memcpy(xsp->ap, &d1, sizeof(double));
+   return;
+  case /* ~ */ BITNOT:
+   mask = __masktab[ndp->szu.xclen];
+   xsp->ap[0] = (~op1a | op1b) & mask;
+   xsp->bp[0] = op1b & mask; 
+   return;
+  /* notice for reduction and logicals - must set xsp stack width to 1 */ 
+  case /* logical ! */ NOT:
+   /* know a val unused bits will be 0 */
+   if (op1b == 0L) xsp->ap[0] = (xsp->ap[0] == 0L) ? 1L : 0L;
+   else xsp->ap[0] = xsp->bp[0] = 1L;
+   break;
+  case /* logical real ! */ REALNOT:
+   /* real only uses x stack a part */
+   /* width of xsp is WBITS - 8 bytes for double - known real */ 
+   memcpy(&d1, xsp->ap, sizeof(double));
+   /* notice overwriting place dp points */
+   /* SJM 01/04/99 - had logic backward */
+   if (d1 > -EPSILON && d1 < EPSILON) xsp->ap[0] = 1L; else xsp->ap[0] = 0L;
+   xsp->bp[0] = 0L;
+   break;
+  case /* & */ BITREDAND:
+   /* width here is just unary operand width since unary self determined */  
+   /* must use operand width since result node width will be 1 probably */
+   mask = __masktab[xsp->xslen];
+   /* if even 1 0 value in any used bit, result is 0 */
+   if (op1b == 0L) xsp->ap[0] = (op1a != mask) ? 0L : 1L;
+   else if ((op1a | op1b) != mask) xsp->ap[0] = xsp->bp[0] = 0L; 
+   else xsp->ap[0] = xsp->bp[0] = 1L;
+   break;
+  case /* | */ BITREDOR:
+   /* here wide will be zero's so no need for width change */
+   if (op1b == 0L) xsp->ap[0] = (op1a != 0L) ? 1L : 0L;
+   else if ((op1a & ~op1b) != 0L) { xsp->ap[0] = 1L; xsp->bp[0] = 0L; }
+   else xsp->ap[0] = xsp->bp[0] = 1L;
+   break;
+  case /* ^ */ BITREDXOR:
+   if (op1b != 0L) { xsp->ap[0] = xsp->bp[0] = 1L; break; } 
+   /* notice here any high unused 0's will not effect result */
+   xsp->bp[0] = 0L;
+   xsp->ap[0] = __wrd_redxor(op1a);
+   break;
+  case /* ^~ */ REDXNOR:
+   /* exec as first the ^ then take opposite of 1 bit */
+   /* truth table is: 00 = 1, 01 = 0,  10 = 0, 11 = 1 */   
+   /* odd numer of 1 bits value 1, else value 0 */
+   if (op1b != 0L) { xsp->ap[0] = xsp->bp[0] = 1L; break; } 
+   /* use mask as tmp */
+   xsp->ap[0] = !__wrd_redxor(op1a);
+   xsp->bp[0] = 0L; 
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ xsp->xslen = 1;
+}
+
+/*
+ * evaluate a wide unary 
+ * notice xsp widened to same width as ndp above here for - and ~
+ * but not for reduction and logical
+ */
+static void eval_wide_unary(register struct expr_t *ndp,
+ register struct xstk_t *xsp)
+{
+ int32 rta, rtb;
+
+ switch ((byte) ndp->optyp) {
+  /* both unary and binary but used as unary here */
+  case /* + */ PLUS:
+   /* unary plus eliminated before here */
+   __misc_terr(__FILE__, __LINE__);
+   return;
+  case /* - */ MINUS:
+   /* SJM 05/10/04 FIXME - since sign extended, do not need signed l uminus */
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp->xslen > ndp->szu.xclen) __narrow_sizchg(xsp, ndp->szu.xclen);
+   else if (xsp->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp, ndp->szu.xclen);
+     else __sizchg_widen(xsp, ndp->szu.xclen);
+    }
+
+   __luminus(xsp->ap, xsp->bp, ndp->szu.xclen);
+   /* must fix since stack exchanged */
+   xsp->xslen = ndp->szu.xclen;
+   return;
+  case /* ~ */ BITNOT:
+   /* SJM 05/10/04 FIXME - since sign extended, do not need signed l bitnot */
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp->xslen > ndp->szu.xclen) __narrow_sizchg(xsp, ndp->szu.xclen);
+   else if (xsp->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp, ndp->szu.xclen);
+     else __sizchg_widen(xsp, ndp->szu.xclen);
+    }
+
+   __lunbitnot(xsp->ap, xsp->bp, ndp->szu.xclen);
+   /* know bit not in place and size changed already */
+   return;
+  /* notice for logicals and reductions must set width to 1 */
+  case /* logical ! */ NOT:
+   if (vval_is0_(xsp->bp, xsp->xslen))
+    {
+     rtb = 0L;
+     if (vval_is0_(xsp->ap, xsp->xslen)) rta = 1L; else rta = 0L;
+    }
+   else rta = rtb = 1L;
+   /* SJM 09/30/03 - can use simpler narrow to 1 bit */
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = rta;
+   xsp->bp[0] = rtb;
+   break;
+  case /* & */ BITREDAND:
+   /* this changes tos to 1 bit value */
+   __lunredand(&rta, &rtb, xsp->ap, xsp->bp, xsp->xslen);
+   /* SJM 09/30/03 - can use simpler narrow to 1 bit */
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = (word32) rta; 
+   xsp->bp[0] = (word32) rtb;
+   break;
+  case /* | */ BITREDOR:
+   __lunredor(&rta, &rtb, xsp->ap, xsp->bp, xsp->xslen);
+   /* SJM 09/30/03 - can use simpler narrow to 1 bit */
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = (word32) rta; 
+   xsp->bp[0] = (word32) rtb;
+   break;
+  case /* ^ */ BITREDXOR:
+   __lunredxor(&rta, &rtb, xsp->ap, xsp->bp, xsp->xslen);
+   /* SJM 09/30/03 - can use simpler narrow to 1 bit */
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = (word32) rta; 
+   xsp->bp[0] = (word32) rtb;
+   break;
+  case /* ^~ */ REDXNOR:
+   /* truth table is logical not of bit wire reducing */ 
+   /* odd numer of 1 bits value 1, else value 0 */
+   __lunredxor(&rta, &rtb, xsp->ap, xsp->bp, xsp->xslen);
+   /* SJM 09/30/03 - can use simpler narrow to 1 bit */
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = (word32) rta; 
+   xsp->bp[0] = (word32) rtb;
+   if (rtb == 0L) xsp->ap[0] = (word32) !rta;
+   /* this produces the 1 bit result */
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ xsp->xslen = 1;
+}
+
+/*
+ * unary bit not - notice this is bit for bit
+ */
+extern void __lunbitnot(word32 *op1ap, word32 *op1bp, int32 opwid)
+{
+ register int32 wi;
+ int32 wlen;
+
+ wlen = wlen_(opwid);
+ for (wi = 0; wi < wlen; wi++)
+  {
+   op1ap[wi] = (~op1ap[wi] | op1bp[wi]);
+   /* b value remains unchanged */
+  }
+ op1ap[wlen - 1] &= __masktab[ubits_(opwid)];
+}
+
+/*
+ * unary minus (0 - value)
+ * know op1ap and op1bp are just pointers to tos values
+ *
+ * SJM 09/30/03 - signed just works because 2's complement
+ */
+extern void __luminus(word32 *op1ap, word32 *op1bp, int32 opbits)
+{
+ struct xstk_t *xsp0, *xspr;
+
+ if (!vval_is0_(op1bp, opbits))
+  { one_allbits_(op1ap, opbits); one_allbits_(op1bp, opbits); }
+ else
+  {
+   /* need real multi-bit subtract */
+   push_xstk_(xsp0, opbits);
+   zero_allbits_(xsp0->ap, opbits);
+   zero_allbits_(xsp0->bp, opbits);
+
+   push_xstk_(xspr, opbits);
+   /* result on tos above 2 operands */
+   __lsub(xspr->ap, xsp0->ap, op1ap, opbits);
+   zero_allbits_(xspr->bp, opbits);
+   /* now must adjust tos stack */
+   xchg_stk(__xspi - 2, __xspi);
+   __pop_xstk();
+   __pop_xstk();
+  }
+}
+
+/*
+ * exchange 2 eval. stack locations
+ */
+static void xchg_stk(int32 xspi1, int32 xspi2)
+{
+ struct xstk_t *xstmp;
+
+ xstmp = __xstk[xspi1]; __xstk[xspi1] = __xstk[xspi2]; __xstk[xspi2] = xstmp;
+}
+
+/*
+ * compute reduction xor for 32 bit word32 (or part)
+ * this returns 1 bit
+ * notice this is 32 bit word32 dependent
+ * 
+ * FIXME - if processor has instruction for word32 reducing xor should use
+ */
+extern word32 __wrd_redxor(word32 opa)
+{
+ register word32 t, rta;
+
+ t = opa;
+ t = t ^ (t >> 16);
+ t = t ^ (t >> 8);
+ t = t ^ (t >> 4);
+ t = t ^ (t >> 2);
+ rta = (t ^ (t >> 1)) & 1L;
+ return(rta);
+}
+
+/*
+ * compute reduction xor for 64 bit lword (or word64) (or part of lword)
+ * this returns 1 bit
+ * notice this is 64 bit word32 dependent
+ * 
+ * FIXME - if processor has instruction for word32 reducing xor should use
+ */
+extern word64 __lwrd_redxor(word64 opa)
+{
+ register word64 t, rta;
+
+ t = opa;
+ t = t ^ (t >> 32);
+ t = t ^ (t >> 16);
+ t = t ^ (t >> 8);
+ t = t ^ (t >> 4);
+ t = t ^ (t >> 2);
+ rta = (t ^ (t >> 1)) & 1ULL;
+ return(rta);
+}
+
+/*
+ * ROUTINES FOR WIDE UNARY OPERATORS
+ */
+
+/*
+ * wide bit reducing and - set tos to 1 bit result
+ * if not all 1's, reduction and will turn to 0
+ */
+extern void __lunredand(int32 *rta, int32 *rtb, word32 *op1ap, word32 *op1bp,
+ int32 opwid)
+{
+ register int32 wi;
+ int32 wlen, ubits;
+
+ /* handle non x/z case */
+ if (vval_is0_(op1bp, opwid))
+  {
+   *rtb = 0;
+   if (!__vval_is1(op1ap, opwid)) *rta = 0; else *rta = 1;
+   return;
+  }
+
+ /* if even one 0 => 0, else x, know high op1a and op1b bit 0 */
+ wlen = wlen_(opwid);
+ ubits = ubits_(opwid);
+ if (ubits != 0) wlen--;
+
+ for (wi = 0; wi < wlen; wi++)
+  {
+   /* if any 0 value bits in either, reducing and will be 0 */
+   if ((op1ap[wi] | op1bp[wi]) != ALL1W) { *rtb = *rta = 0; return; }
+  }
+ if (ubits != 0)
+  {
+   if ((op1ap[wlen] | op1bp[wlen]) != __masktab[ubits])
+    { *rtb = *rta = 0; return; }
+  }
+ /* did not find 0, must be x */
+ *rtb = *rta = 1;
+} 
+
+/*
+ * wide bit reducing or - set tos to 1 bit result
+ * if not all 0's, reduction and will turn to 1
+ */
+extern void __lunredor(int32 *rta, int32 *rtb, word32 *op1ap, word32 *op1bp,
+ int32 opwid)
+{
+ register int32 wi;
+ register word32 rta2, rtb2;
+
+ /* if even 1 1 and no x/z bits, reduction and will turn to 1 */
+ if (vval_is0_(op1bp, opwid))
+  {
+   rtb2 = 0;
+   if (!vval_is0_(op1ap, opwid)) rta2 = 1; else rta2 = 0;
+   goto done;
+  }
+ /* if even one 1 => 1, else x, know high op1a and op1b bit 0 */
+ /* since know high bits will be 0, no need to handle separately */
+ for (wi = 0; wi < wlen_(opwid); wi++)
+  {
+   /* if a bit is 1 and b bit is 0, have the one needed 1 */
+   if ((op1ap[wi] & ~op1bp[wi]) != 0L)
+    { rtb2 = 0; rta2 = 1; goto done; }
+  }
+ /* did not find a 1, must be x */
+ rtb2 = rta2 = 1;
+done:
+ *rta = rta2;
+ *rtb = rtb2;
+ return;
+}
+
+/*
+ * wide bit reducing xor - set tos to 1 bit result
+ * counts number of 1 bits
+ */
+extern void __lunredxor(int32 *rta, int32 *rtb, word32 *op1ap, word32 *op1bp,
+ int32 opwid)
+{
+ register int32 wi;
+ register word32 rtmp, rtmp2;
+
+ /* if any x/zs, return is x */
+ if (!vval_is0_(op1bp, opwid)) { *rta = *rtb = 1; return; }
+
+ /* any unused 0's can be ignored - just produce 0 */
+ for (rtmp = 0, wi = 0; wi < wlen_(opwid); wi++)
+  {
+   /* this returns 1 bit result */ 
+   rtmp2 = __wrd_redxor(op1ap[wi]);
+   rtmp ^= rtmp2;
+  }
+ *rta = rtmp; 
+ *rtb = 0L;
+ return;
+}
+
+/*
+ * ROUTINES TO EVALUATE NORMAL BINARY OPERATORS
+ */
+
+/*
+ * evaluate a binary operator
+ * know all high (unused) bits set to zero - and left as zero
+ * evaluates 2 operands and places result on tos (i.e. stack shrinks by 1)
+ *
+ * SJM 10/22/03 - the signed narrower than 32 bits consistently wrong
+ * because sign bit not in bit 32 as was case when only 32 bit ints
+ * could be signed - now either sign extend or use signed magnitude operation
+ *
+ * notice are tmps that can be changed during evaluation
+ */
+static void eval_binary(struct expr_t *ndp)
+{
+ register word32 rta, rtb;
+ register word32 op1a, op1b, op2a, op2b, mask;
+ int32 tmp1, tmp2, nd_signop, opwid, has_sign;
+ double d1, d2;
+ struct xstk_t *xsp1, *xsp2;
+ struct expr_t *lx, *rx;
+
+ xsp1 = __eval2_xpr(ndp->lu.x);
+ xsp2 = __eval2_xpr(ndp->ru.x);
+
+ /* need to separate off wide case */
+ /* notice this code depends on real width == W BITS */
+ if (ndp->szu.xclen > WBITS || xsp1->xslen > WBITS || xsp2->xslen > WBITS)
+  {
+   /* this replaces tos 2 values with 1 value */
+   /* wide always word32 */
+   eval_wide_binary(ndp, xsp1, xsp2);
+   return;
+  }
+ opwid = ndp->szu.xclen;
+ /* set during checking - result has sign if < WBITS and not 1 bit */
+ /* and one or both operaads have sign */
+ if (ndp->has_sign || ndp->rel_ndssign) nd_signop = TRUE;
+ else nd_signop = FALSE;
+
+ op1a = xsp1->ap[0]; op1b = xsp1->bp[0];
+ op2a = xsp2->ap[0]; op2b = xsp2->bp[0];
+ mask = __masktab[ubits_(opwid)];
+
+ /* this is result operator not operands width */
+ rta = rtb = 0L;
+ switch ((byte) ndp->optyp) {
+  case /* + */ PLUS:
+   if (op1b == 0L && op2b == 0L)
+    {
+     rtb = 0;
+     /* SJM 09/30/03 - need signed for c signed add (hardware sign xtnd) */
+     if (!nd_signop) rta = (op1a + op2a) & mask;
+     else
+      {
+       /* SJM 09/29/04 - but do need to mask if either operand not 32 bits */ 
+       if (ndp->lu.x->szu.xclen != WBITS)
+        {
+         /* complex narrower than 32 bit signed case - sign extend to c int */ 
+         if ((op1a & (1 << (xsp1->xslen - 1))) != 0) 
+          op1a |= ~(__masktab[xsp1->xslen]);
+        } 
+       if (ndp->ru.x->szu.xclen != WBITS)
+        {
+         if ((op2a & (1 << (xsp2->xslen - 1))) != 0) 
+          op2a |= ~(__masktab[xsp2->xslen]);
+        }
+       /* mask even if 32 bits */
+       rta = (word32) ((((sword32) op1a) + ((sword32) op2a)) & mask);    
+      }
+    }
+   else rta = rtb = mask;
+   break;
+  case /* + real */ REALPLUS:
+   /* is it portable to pass 1 bit bit field? */
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+
+   /* notice never a size change since both must be real */
+   d1 += d2;
+   /* this works because minimum stack every allocated is 8 bytes */
+   /* PORTABILITY - stack must always be at least 8 bytes */
+   memcpy(xsp1->ap, &d1, sizeof(double));
+   __pop_xstk();
+   return;
+  case  /* - */ MINUS:
+   if (op1b == 0L && op2b == 0L)
+    {
+     rtb = 0L;
+     /* SJM 09/30/03 - need signed for c signed - (hardware sign xtnd) */
+     if (!nd_signop)
+      {
+       rta = op1a + op2a;
+       rta = (op1a - op2a) & mask;
+      }
+     /* since know 32 bits, no need to mask */
+     else
+      {
+       /* SJM 09/29/04 - but do need to mask if either operand not 32 bits */ 
+       if (ndp->lu.x->szu.xclen != WBITS)
+        {
+         /* complex narrower than 32 bit signed case - sign extend to c int */ 
+         if ((op1a & (1 << (xsp1->xslen - 1))) != 0) 
+          op1a |= ~(__masktab[xsp1->xslen]);
+        }
+       if (ndp->ru.x->szu.xclen != WBITS)
+        {
+         if ((op2a & (1 << (xsp2->xslen - 1))) != 0) 
+          op2a |= ~(__masktab[xsp2->xslen]);
+        }
+       rta = (word32) ((((sword32) op1a) - ((sword32) op2a)) & mask);    
+      }
+    }
+   else rta = rtb = mask;
+   break;
+  case /* - real */ REALMINUS:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   d1 -= d2;
+   /* notice never a size change since both must be real */
+   memcpy(xsp1->ap, &d1, sizeof(double));
+   __pop_xstk();
+   return;
+  case /* * */ TIMES:
+   if (op1b != 0L || op2b != 0L) rta = rtb = mask;
+   else
+    {
+     /* SJM 09/30/03 - need ints for c signed op to work */
+     if (!nd_signop) rta = (op1a * op2a) & mask;
+     /* never need to mask for 32 bits */
+     /* SJM 09/29/04 - but do need to mask if either operand not 32 bits */ 
+     else if (ndp->lu.x->szu.xclen == WBITS && ndp->ru.x->szu.xclen == WBITS)
+      rta = (word32) (((sword32) op1a) * ((sword32) op2a));  
+     else
+      {
+       /* SJM 10/22/03 - LOOKATME - think this must use sign/magnitude */
+       /* complex narrower than 32 bit signed case */ 
+       has_sign = FALSE; 
+       /* 2's complement makes positive if needed */
+       if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+        {
+         /* since c - of cast to int can only handle 32 bit ints, sign xtnd */
+         op1a |= ~(__masktab[xsp1->xslen]);
+         op1a = (word32) (-((sword32) op1a)); 
+         has_sign = TRUE;
+        }
+       if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+        {
+         /* since c - of cast to int can only handle 32 bit ints, sign xtnd */
+         op2a |= ~(__masktab[xsp2->xslen]);
+         op2a = (word32) (-((sword32) op2a));
+         has_sign = !has_sign;
+        }
+
+       /* know op1a and op2a positive */
+       rta = op1a * op2a;
+       if (has_sign) rta = (word32) (-((sword32) rta));
+       /* must mask so product fits in widest operand size */  
+       rta &= mask;
+      }
+     rtb = 0;
+    } 
+   break;
+  case /* * real */ REALTIMES:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+
+   /* notice never a size change since both must be real */
+   d1 *= d2;
+   memcpy(xsp1->ap, &d1, sizeof(double));
+   __pop_xstk();
+   return;
+  case /* / */ DIV:
+   if (op1b != 0L || op2b != 0L || op2a == 0L) rta = rtb = mask;
+   /* case 1: unsigned */
+   else if (!nd_signop) rta = op1a / op2a;
+   /* SJM 09/29/04 - but do need to mask if either operand not 32 bits */ 
+   else if (ndp->lu.x->szu.xclen == WBITS && ndp->ru.x->szu.xclen == WBITS)
+    {
+     /* case 2 signed but int32 so can use c casts */
+     rta = (word32) ((sword32) op1a / (sword32) op2a);
+     rtb = 0L;
+     /* SJM 05/13/04 - no need to mask since know WBITS */
+    }
+   else 
+    {
+     /* SJM 10/22/03 - must extract signs (sign of result from 1st) */
+     /* and do operation word32 and then put back sign */
+     if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+      {
+       /* SJM 05/13/04 - must sign extend to WBITS int32 size */
+       op1a = op1a | ~(__masktab[xsp1->xslen]);
+       op1a = (word32) (-((sword32) op1a)); 
+       has_sign = TRUE;
+      }
+     else has_sign = FALSE; 
+
+     /* for mod, first operand determines sign of result */
+     if ((op2a & (1 <<( xsp2->xslen - 1))) != 0)
+      {
+       /* SJM 05/13/04 - must sign extend to WBITS int32 size */
+       op2a = op2a | ~(__masktab[xsp2->xslen]);
+       op2a = (word32) (-((sword32) op2a)); 
+       /* sign combination rules for div same as mult */
+       has_sign = !has_sign;
+      }
+
+     /* know op1a and op2a positive */
+     rta = op1a / op2a;
+     /* if result signed, first comp WBITS signed - */
+     if (has_sign) rta = (word32) (-((sword32) rta));
+     rta &= mask;
+     rtb = 0L;
+    }
+   break;
+  case /* * real */ REALDIV:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+
+   /* notice never a size change since both must be real */
+   d1 /= d2;
+   memcpy(xsp1->ap, &d1, sizeof(double));
+   __pop_xstk();
+   return;
+  case /* % */ MOD:
+   if (op1b != 0L || op2b != 0L || op2a == 0L) rta = rtb = mask;
+   /* case 1: unsigned */
+   else if (!nd_signop) rta = op1a % op2a;
+   /* SJM 09/29/04 - but do need to mask if either operand not 32 bits */ 
+   else if (ndp->lu.x->szu.xclen == WBITS && ndp->ru.x->szu.xclen == WBITS)
+    {
+     /* case 2 signed but int32 so can use c casts */
+     /* case 2 signed but int32 so can use c casts */
+     rta = (word32) ((sword32) op1a % (sword32) op2a);
+     rtb = 0L;
+     /* think value narrower but needed for signed */
+     rta &= mask;
+    }
+   else 
+    {
+     /* SJM 10/22/03 - must extract signs (sign of result from 1st) */
+     /* and do operation word32 and then put back sign */
+     if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+      {
+       /* SJM 05/13/04 - must sign extend to WBITS int32 size */
+       op1a = op1a | ~(__masktab[xsp1->xslen]);
+       has_sign = TRUE;
+      }
+     else has_sign = FALSE; 
+
+     /* for mod, first operand determines sign of result */
+     if ((op2a & (1 <<( xsp2->xslen - 1))) != 0)
+      {
+       /* SJM 05/13/04 - must sign extend to WBITS int32 size */
+       op2a = op2a | ~(__masktab[xsp2->xslen]);
+      }
+
+     /* know op1a and op2a positive */
+     rta = op1a % op2a;
+     if (has_sign) rta = (word32) (-((sword32) rta));
+     rta &= mask;
+     rtb = 0L;
+    }
+   break;
+  case /* & */ BITREDAND:
+   /* idea is if both op1b and op2b 1 (x), need rta to be 1 for x result */
+   if ((op1b | op2b) == 0L) { rtb = 0L; rta = (op1a & op2a); }
+   else
+    {
+     rta = (op1a | op1b) & (op2a | op2b);
+     rtb = rta & (op2b | op1b);
+    }
+   break;
+  case /* | */ BITREDOR:
+   if ((op1b | op2b) == 0L) { rtb = 0L; rta = (op1a | op2a); }
+   else
+    {
+     rtb = op2b ^ op1b ^ ((op1a | op1b) & (op2b | (op2a & op1b)));
+     rta = rtb | op2a | op1a;
+    }
+   break;
+  case /* ^ */ BITREDXOR:
+   /* know same width so high non 0 never possible */
+   if ((op1b | op2b) == 0L) { rtb = 0L; rta = (op1a ^ op2a); }
+   else { rtb = op1b | op2b; rta = rtb | (op1a ^ op2a);  }
+   break;
+  case /* not ^ */ REDXNOR:
+   /* since same length, xor 0 0 is 1, not of 1 is 0 so works */
+   if ((op1b | op2b) == 0L) 
+    { rtb = 0L; rta = ~(op1a ^ op2a) & mask; }
+   else
+    /* must mask here because 0 xnor 0 is 1 for high unused bits */
+    { rtb = op1b | op2b; rta = (rtb | ~(op1a ^ op2a)) & mask; }
+   break;
+  case /* >= */ RELGE:
+   if ((op1b | op2b) == 0L)
+    {
+     rtb = 0L;
+     /* C result for true is always 1 */
+     if (nd_signop)
+      {
+       /* SJM 10/22/03 - easiest here to just sign extend - does it work? */
+       /* SJM 05/13/04 - width is opand not result width */
+       if (xsp1->xslen < WBITS)
+        {
+         if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+          op1a |= ~(__masktab[xsp1->xslen]);
+        }
+       if (xsp2->xslen < WBITS)
+        {
+         if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+          op2a |= ~(__masktab[xsp2->xslen]);
+        }
+       rta = (word32) (((sword32) op1a) >= ((sword32) op2a));
+      }
+     else rta = op1a >= op2a;
+    }
+   else rta = rtb = 1L;
+   break;
+  case /* >= real */ REALRELGE:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+
+   rta = (d1 >= d2) ? 1L : 0L;
+   rtb = 0L; 
+   break;
+  case /* > */ RELGT:
+   if ((op1b | op2b)== 0L)
+    {
+     rtb = 0L;
+     if (nd_signop)
+      {
+       /* SJM 10/22/03 - easiest here to just sign extend - does it work? */
+       /* SJM 05/13/04 - width is opand not result width */
+       if (xsp1->xslen < WBITS)
+        {
+         if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+          op1a |= ~(__masktab[xsp1->xslen]);
+        }
+       if (xsp2->xslen < WBITS)
+        {
+         if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+          op2a |= ~(__masktab[xsp2->xslen]);
+        }
+       rta = (word32) (((sword32) op1a) > ((sword32) op2a));
+      }
+     else rta = op1a > op2a;
+    }
+   else rta = rtb = 1L;
+   break;
+  case /* > real */ REALRELGT:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   rta = (d1 > d2) ? 1L : 0L;
+   rtb = 0L; 
+   break;
+  case /* <= */ RELLE:
+   if ((op1b | op2b) == 0L)
+    {
+     rtb = 0L;
+     if (nd_signop)
+      { 
+       /* SJM 10/22/03 - easiest here to just sign extend - does it work? */
+       /* SJM 05/13/04 - width is opand not result width */
+       if (xsp1->xslen < WBITS)
+        {
+         if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+          op1a |= ~(__masktab[xsp1->xslen]);
+        }
+       if (xsp2->xslen < WBITS)
+        {
+         if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+          op2a |= ~(__masktab[xsp2->xslen]);
+        }
+       rta = (word32) (((sword32) op1a) <= ((sword32) op2a));
+      }
+     else rta = op1a <= op2a;
+    }
+   else rta = rtb = 1L;
+   break;
+  case /* <= real */ REALRELLE:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   rta = (d1 <= d2) ? 1L : 0L;
+   rtb = 0L; 
+   break;
+  case /* < */ RELLT:
+   if ((op1b | op2b) == 0L)
+    {
+     rtb = 0L;
+     if (nd_signop)
+      {
+       /* SJM 10/22/03 - easiest here to just sign extend - does it work? */
+       /* SJM 05/13/04 - width is opand not result width */
+       if (xsp1->xslen < WBITS)
+        {
+         if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+          op1a |= ~(__masktab[xsp1->xslen]);
+        }
+       if (xsp2->xslen < WBITS)
+        {
+         if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+          op2a |= ~(__masktab[xsp2->xslen]);
+        }
+       rta = (word32) (((sword32) op1a) < ((sword32) op2a));
+      } 
+     else rta = op1a < op2a;
+    }
+   else rta = rtb = 1L;
+   break;
+  case /* < real */ REALRELLT:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   /* notice never a size change since both must be real */
+   rta = (d1 < d2) ? 1L : 0L;
+   rtb = 0L; 
+   break;
+  case /* != */ RELNEQ:
+
+   if ((op1b | op2b) == 0L)
+    {
+     if (nd_signop)
+      {
+       /* SJM 05/13/04 - width is opand not result width */
+       if (xsp1->xslen < WBITS)
+        {
+         if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+          op1a |= ~(__masktab[xsp1->xslen]);
+        }
+       if (xsp2->xslen < WBITS)
+        {
+         if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+          op2a |= ~(__masktab[xsp2->xslen]);
+        }
+      }
+     rtb = 0L;
+     rta = (op1a != op2a);
+     break;
+    }
+
+   /* SJM 06/16/00 - was wrong for x cases because if non equal where both */
+   /* operands non x/z, should be 0 not unknown */
+   /* new algorithm - if compare with a parts all x/z bits set to 1 */
+   /* not equal then x/z bits can not effect not equal result */
+   /* know at least one bit x/z to get here */
+
+   if (nd_signop)
+    {
+     /* SJM 05/13/04 - width is opand not result width */
+     if (xsp1->xslen < WBITS)
+      {
+       if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+        op1a |= ~(__masktab[xsp1->xslen]);
+       /* if any x/z bits must x/z extned if signed */
+       if ((op1b & (1 << (xsp1->xslen - 1))) != 0)
+        op1b |= ~(__masktab[xsp1->xslen]);
+      }
+     if (xsp2->xslen < WBITS)
+      {
+       if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+        op2a |= ~(__masktab[xsp2->xslen]);
+       if ((op2b & (1 << (xsp2->xslen - 1))) != 0)
+        op2b |= ~(__masktab[xsp2->xslen]);
+      }
+    }
+   if ((op1a | (op1b | op2b)) != (op2a | (op1b | op2b)))
+    { rtb = 0L; rta = 1L; }
+   else rta = rtb = 1L;
+   break;
+  case /* != real */ REALRELNEQ:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+
+   /* notice never a size change since both must be real */
+   /* this is ieee float point dependent */
+   rta = (fabs(d1 - d2) >= EPSILON) ? 1L : 0L;
+   rtb = 0L; 
+   break;
+  case /* == */ RELEQ:
+   /* relation true in C is always 1 */
+   if ((op1b | op2b) == 0L)
+    {
+     if (nd_signop)
+      {
+       /* SJM 05/13/04 - width is opand not result width */
+       if (xsp1->xslen < WBITS)
+        {
+         if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+          op1a |= ~(__masktab[xsp1->xslen]);
+        }
+       if (xsp2->xslen < WBITS)
+        {
+         if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+          op2a |= ~(__masktab[xsp2->xslen]);
+        }
+      }
+     rtb = 0L;
+     rta = (op1a == op2a);
+     break;
+    }
+
+   /* SJM 06/16/00 - wrong for x cases because if non equal where both */
+   /* operands non x/z, should be 0 not unknown */
+   /* new algorithm - if compare with a parts all x/z bits set to 1 */
+   /* not equal then x/z bits can not effect not equal result */
+   /* know at least one bit x/z to get here */
+
+   if (nd_signop)
+    {
+     /* SJM 05/13/04 - width is opand not result width */
+     if (xsp1->xslen < WBITS)
+      {
+       if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+        op1a |= ~(__masktab[xsp1->xslen]);
+       /* if any x/z bits must x/z extned if signed */
+       if ((op1b & (1 << (xsp1->xslen - 1))) != 0)
+        op1b |= ~(__masktab[xsp1->xslen]);
+      }
+     if (xsp2->xslen < WBITS)
+      {
+       if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+        op2a |= ~(__masktab[xsp2->xslen]);
+       if ((op2b & (1 << (xsp2->xslen - 1))) != 0)
+        op2b |= ~(__masktab[xsp2->xslen]);
+      }
+    }
+
+   if ((op1a | (op1b | op2b)) != (op2a | (op1b | op2b)))
+    { rtb = 0L; rta = 0L; }
+   else rta = rtb = 1L;
+   break;
+  case /* == real */ REALRELEQ:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   /* notice never a size change since both must be real */
+   /* this is ieee float point dependent */
+   rta = (fabs(d1 - d2) >= EPSILON) ? 0L : 1L;
+   rtb = 0L; 
+   break;
+  case /* === */ RELCEQ:
+
+   if (nd_signop)
+    {
+     /* SJM 05/13/04 - width is opand not result width */
+     if (xsp1->xslen < WBITS)
+      {
+       if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+        op1a |= ~(__masktab[xsp1->xslen]);
+       /* if any x/z bits must x/z extned if signed */
+       if ((op1b & (1 << (xsp1->xslen - 1))) != 0)
+        op1b |= ~(__masktab[xsp1->xslen]);
+      }
+     if (xsp2->xslen < WBITS)
+      {
+       if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+        op2a |= ~(__masktab[xsp2->xslen]);
+       if ((op2b & (1 << (xsp2->xslen - 1))) != 0)
+        op2b |= ~(__masktab[xsp2->xslen]);
+      }
+    }
+   rtb = 0L;
+   /* works without masking since semantics requires 0 extending */
+   rta = (0L == ((op1a ^ op2a) | (op1b ^ op2b)));
+   break;
+  case /* !== */ RELCNEQ:
+
+   if (nd_signop) 
+    {
+     /* SJM 05/13/04 - width is opand not result width */
+     if (xsp1->xslen < WBITS)
+      {
+       if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
+        op1a |= ~(__masktab[xsp1->xslen]);
+       /* if any x/z bits must x/z extned if signed */
+       if ((op1b & (1 << (xsp1->xslen - 1))) != 0)
+        op1b |= ~(__masktab[xsp1->xslen]);
+      }
+     if (xsp2->xslen < WBITS)
+      {
+       if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
+        op2a |= ~(__masktab[xsp2->xslen]);
+       if ((op2b & (1 << (xsp2->xslen - 1))) != 0)
+        op2b |= ~(__masktab[xsp2->xslen]);
+      }
+    }
+   rtb = 0L;
+   /* works without masking since semantics requires 0 extending */
+   rta = (0L != ((op1a ^ op2a) | (op1b ^ op2b)));
+   break;
+  case /* && */ BOOLAND:
+   /* notice this complicated algorithm is needed because if a bit */
+   /* is some position is 0 other bit does not matter - i.e. this is */
+   /* really 32 bool ands */
+   rtb = 0L;
+   tmp1 = cvt_wrdbool_(op1a, op1b);
+   if (tmp1 == 0) { rta = 0L; break; }
+   tmp2 = cvt_wrdbool_(op2a, op2b);
+   if (tmp2 == 0) { rta = 0L; break; }
+   if (tmp1 == 1 && tmp2 == 1) rta = 1L; else rta = rtb = 1L;
+   break;
+  case /* && real */ REALBOOLAND:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   /* notice never a size change since both must be real */
+   rta = (d1 != 0.0 && d2 != 0.0) ? 1L : 0L;   
+   rtb = 0L; 
+   break;
+  case /* || */ BOOLOR:
+   rtb = 0L;
+   tmp1 = cvt_wrdbool_(op1a, op1b);
+   if (tmp1 == 1) { rta = 1L; break; }
+   tmp2 = cvt_wrdbool_(op2a, op2b);
+   if (tmp2 == 1) { rta = 1L; break; }
+   /* if not both 0, some bit x&x or x&1 */
+   if (tmp1 == 0 && tmp2 == 0) rta = 0L; else rta = rtb = 1L;
+   break;
+  case /* && real */ REALBOOLOR:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+
+   /* notice never a size change since both must be real */
+   rta = (d1 != 0.0 || d2 != 0.0) ? 1L : 0L;   
+   rtb = 0L; 
+   break;
+  case /* << */ SHIFTL:
+  case /* <<< */ ASHIFTL:
+   /* if shift amt x/z, result is 0 */ 
+   if (op2b != 0L) rtb = rta = mask;
+   /* if shift length wider than op1, result is 0 */
+   /* 2nd shift width operand is interpreted as range index (word32) */
+   else if (op2a > (word32) opwid) rtb = rta = 0L;
+   else
+    {
+     if (nd_signop && xsp1->xslen < ndp->szu.xclen)
+      {
+       __sgn_xtnd_wrd(xsp1, ndp->szu.xclen);
+       op1a = xsp1->ap[0]; 
+       op1b = xsp1->bp[0]; 
+      }
+     rtb = (op1b << op2a) & mask;
+     rta = (op1a << op2a) & mask;
+    }
+   break;
+  case /* >> */ SHIFTR:
+   /* SJM 09/30/03 - logical shift right stays same even if sign bit 1 */
+   /* if shift amt x/z, result is 0 */ 
+   if (op2b != 0L) rtb = rta = mask;
+   else if (op2a > (word32) ndp->szu.xclen)
+    {
+     /* if shift length wider than op1, result is 0 */
+     /* 2nd shift width operand is interpreted as range index (word32) */
+     rtb = rta = 0L;
+    }
+   else
+    {
+     /* notice no need to mask since 0's injected into high bits */
+     rtb = op1b >> op2a;
+     rta = op1a >> op2a;
+     }
+   break;
+  case /* >>> */ ASHIFTR:
+   /* SJM 09/30/03 - arithmetic shift right inserts sign bit if on not 0 */
+   /* if shift amt x/z, result is x */ 
+   if (op2b != 0L)
+    {
+     rtb = rta = mask;
+    }
+   else if (op2a > (word32) ndp->szu.xclen)
+    { 
+     /* 2nd shift width operand is interpreted as range index (word32) */
+     /* notice if word32, no sign bit */
+     if (nd_signop)
+      {
+       if ((op1a & (1 << (ndp->szu.xclen - 1))) != 0)
+        {
+         /* since shift amount wider than var, if sign bit on */ 
+         /* 1's shifted into each bit position, else 0 */
+         rta = mask;
+         rtb = 0;
+        }
+       else rta = rtb = 0;
+      }
+     else rtb = rta = 0L;
+    }
+   else
+    {
+     /* notice no need to mask since 0's injected into high bits */
+     if (nd_signop)
+      {
+       /* SJM 05/10/04 - could use c signed arithmetic shift for WBITS wide */
+       /* SJM for word32 arithmetic right shift use c arithmetic shift */
+       /* AIV 06/02/05 - if shift amt is wrong for 0 - don't mask */
+       if (op2a != 0 && (op1a & (1 << (ndp->szu.xclen - 1))) != 0)
+        {
+         /* first shift as if 0 bits then or in the bits shifted in from */
+         /* injected sign bits */
+         rta = (word32) (op1a >> op2a);
+         rtb = (word32) (op1b >> op2a);
+         rta |= (__masktab[op2a] << (ndp->szu.xclen - op2a));
+        }
+       else
+        {
+         /* if sign bit off - same as logical right shift */
+         rta = (word32) (op1a >> op2a);
+         rtb = (word32) (op1b >> op2a);
+        }
+      }
+     else
+      {
+       rtb = op1b >> op2a;
+       rta = op1a >> op2a;
+      }
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ /* DB remove after debugged ---
+ if ((rta & ~mask) != 0L || (rtb & ~mask) != 0L)
+  {
+   __pv_warn(528,
+    "INTERNAL - binary op truncation wrong - width %d, av=%lx,bv=%lx",
+    ndp->szu.xclen, rta, rtb);
+  }
+ --- */
+ xsp1->ap[0] = rta;
+ xsp1->bp[0] = rtb;
+ xsp1->xslen = ndp->szu.xclen;
+ __pop_xstk();
+}
+
+/*
+ * ROUTINES FOR WIDE BINARY OPERATORS
+ */
+
+/*
+ * evaluate binary operators where at least 1 operand wider than 32
+ * what about 1 extension here and in <32 case
+ * notice operation must be done in wider of operands and then copied
+ * if needed
+ *
+ * this expects 2 operands on tos and leaves 1 result on tos
+ * xsp2 is above xsp1 and arith routines called from here need 3 on stack
+ * wider than 32 never signed - no checking
+ */
+static void eval_wide_binary(struct expr_t *ndp, register struct xstk_t *xsp1,
+ register struct xstk_t *xsp2)
+{
+ register word32 rta, rtb;
+ int32 isxz, cmpval, tmp1, tmp2, nd_signop;
+ word32 shiftamt;
+ struct xstk_t *xspr;
+ struct expr_t *lx, *rx;
+ double d1, d2;
+
+ if (ndp->has_sign || ndp->rel_ndssign) nd_signop = TRUE;
+ else nd_signop = FALSE;
+
+ /* impossible for both operands <32 but result > 32 */
+ switch ((byte) ndp->optyp) {
+  case /* + */ PLUS:
+  case /* - */ MINUS:
+  case /* * */ TIMES:
+  case /* / */ DIV:
+  case /* % */ MOD:
+   /* SJM 09/30/03 - change to handle sign extension and separate types */
+   if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
+   else if (xsp1->xslen < ndp->szu.xclen)
+    {
+     /* if any signed all will be */
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
+     else __sizchg_widen(xsp1, ndp->szu.xclen);
+    }
+   if (xsp2->xslen > ndp->szu.xclen) __narrow_sizchg(xsp2, ndp->szu.xclen);
+   else if (xsp2->xslen < ndp->szu.xclen)
+    {
+     /* if any signed all will be */
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp2, ndp->szu.xclen);
+     else __sizchg_widen(xsp2, ndp->szu.xclen);
+    }
+
+   if (__set_binxresult(xsp1->ap, xsp1->bp, xsp1->bp, xsp2->bp,
+     ndp->szu.xclen))
+    {
+     __pop_xstk();
+     return;
+    }
+
+   /* for 0 divisor, result is x */
+   if ((ndp->optyp == DIV || ndp->optyp == MOD)
+    && vval_is0_(xsp2->ap, xsp2->xslen))
+    {
+     one_allbits_(xsp1->ap, xsp1->xslen);
+     one_allbits_(xsp1->bp, xsp1->xslen);
+     __pop_xstk();
+     return;
+    }
+   /* in routine will fill all of xspr with value - no need to init */
+   push_xstk_(xspr, ndp->szu.xclen);
+   /* add/sub to accumulator */
+   /* SJM 09/30/03 - since using sign mult and div others 2 complement work */
+   switch ((byte) ndp->optyp) {
+    case /* + */ PLUS:
+     __ladd(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen);
+     break;
+    case /* - */ MINUS:
+     __lsub(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen);
+     break;
+    case /* * */ TIMES:
+     /* SJM 09/30/03 - need wapper for signed since wide needs positive */
+     if (ndp->has_sign)
+      __sgn_lmult(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen);
+     else __lmult(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen);
+     break;
+    case /* / */ DIV:
+     /* SJM 09/30/03 - need wapper for signed since wide needs positive */
+     if (ndp->has_sign)
+      __sgn_ldivmod(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen, TRUE);
+     else __ldivmod(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen, TRUE);
+     break;
+    case /* % */ MOD:
+     /* SJM 09/30/03 - need wapper for signed since wide needs positive */
+     if (ndp->has_sign)
+      __sgn_ldivmod(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen, FALSE);
+      else __ldivmod(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen, FALSE);
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   /* zero result b value */
+   zero_allbits_(xspr->bp, xspr->xslen);
+   /* move result down 2 and then pop top 2 (old tmp result and op2) */
+   xchg_stk(__xspi - 2, __xspi);
+   __pop_xstk();
+   __pop_xstk();
+   break;
+  case /* << */ SHIFTL:
+  case /* >>> */ ASHIFTL:
+  case /* >> */ SHIFTR:
+   /* this replaces top 2 args with shifted result replacing 2nd down */
+   /* if shift width has any x/z's, even if will be truncated, result x */
+   /* need to widen from context before shift - need overflow bits */
+
+   /* SJM 09/29/03 - change to handle sign extension but left arithmetic */
+   /* shift same as left logical shift (only change is signed widening) */
+   if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
+   else if (xsp1->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
+     else __sizchg_widen(xsp1, ndp->szu.xclen);
+    }
+
+   if (!vval_is0_(xsp2->bp, xsp2->xslen))
+    {
+     one_allbits_(xsp1->ap, xsp1->xslen);
+     one_allbits_(xsp1->bp, xsp1->xslen);
+    }
+   else
+    {
+     /* if op value is 0 or shift amount wider than op */
+     /* SJM 12/28/98 - this was wrongly checking first word32 of long */  
+     /* SJM 03/28/03 - for shift of case with only z's in op1 was wrong */
+     /* because if a part 0 but b part 1 (z in val) wrongly setting to 0 */ 
+     if ((vval_is0_(xsp1->ap, xsp1->xslen)
+      && vval_is0_(xsp1->bp, xsp1->xslen)) 
+      || (xsp2->xslen > WBITS && !vval_is0_(&(xsp2->ap[1]),
+       xsp2->xslen - WBITS)) || xsp2->ap[0] >= (word32) xsp1->xslen) 
+       memset(xsp1->ap, 0, 2*WRDBYTES*wlen_(xsp1->xslen)); 
+     else
+      {
+       if ((shiftamt = xsp2->ap[0]) != 0) 
+        { 
+         if (vval_is0_(xsp1->bp, xsp1->xslen)) isxz = FALSE;
+         else isxz = TRUE;
+         if (ndp->optyp != SHIFTR)
+          {
+           __mwlshift(xsp1->ap, shiftamt, xsp1->xslen);
+           if (isxz) __mwlshift(xsp1->bp, shiftamt, xsp1->xslen);
+          }
+         else
+          {
+           __mwrshift(xsp1->ap, shiftamt, xsp1->xslen);
+           if (isxz) __mwrshift(xsp1->bp, shiftamt, xsp1->xslen);
+          }
+        }   
+      }
+    }
+   __pop_xstk();
+   break;
+  case /* >>> */ ASHIFTR:
+   /* SJM 05/11/04 - split arithmetic right shift off */ 
+   /* main different is that if sign bit on, need to shift in 1's for both */
+   /* a and b parts */
+   /* SJM 05/11/04 - notice that shift amount always treated as word32, */
+   /* i.e. no minus opposite direction shifts */
+   if (!vval_is0_(xsp2->bp, xsp2->xslen))
+    {
+     one_allbits_(xsp1->ap, xsp1->xslen);
+     one_allbits_(xsp1->bp, xsp1->xslen);
+     goto ashift_pop; 
+    }
+   if (vval_is0_(xsp1->ap, xsp1->xslen) && vval_is0_(xsp1->bp, xsp1->xslen)) 
+    {
+     /* opand 1 value 0 - shift can't change */
+     memset(xsp1->ap, 0, 2*WRDBYTES*wlen_(xsp1->xslen)); 
+     goto ashift_pop; 
+    }
+   if ((xsp2->xslen > WBITS && !vval_is0_(&(xsp2->ap[1]),
+    xsp2->xslen - WBITS)) || xsp2->ap[0] >= (word32) xsp1->xslen) 
+    {
+     int32 bi, wlen;
+
+     /* shift amount wider than value */
+     bi = get_bofs_(xsp1->xslen);
+     wlen = wlen_(xsp1->xslen);
+       
+     /* SJM 06/20/04 - if right ashift opand word32 - no sign extend */
+     if (ndp->has_sign && (xsp1->ap[wlen - 1] & (1 << bi)) != 0)
+      {
+       /* since shift amount wider than var, if sign bit on */ 
+       /* 1's shifted into each bit position, i.e. set all bits to 1 */
+       one_allbits_(xsp1->ap, xsp1->xslen);
+      }
+     else memset(xsp1->ap, 0, 2*WRDBYTES*wlen); 
+
+     /* if b part high bit on, all bits become x/z */
+     if (ndp->has_sign && (xsp1->bp[wlen - 1] & (1 << bi)) != 0)
+      {
+       one_allbits_(xsp1->bp, xsp1->xslen);
+      }
+     else memset(xsp1->ap, 0, 2*WRDBYTES*wlen); 
+     goto ashift_pop; 
+    }
+   if ((shiftamt = xsp2->ap[0]) != 0) 
+    { 
+     if (vval_is0_(xsp1->bp, xsp1->xslen)) isxz = FALSE;
+     else isxz = TRUE;
+
+     if (nd_signop)
+      {
+       __arith_mwrshift(xsp1->ap, shiftamt, xsp1->xslen);
+       if (isxz) __arith_mwrshift(xsp1->bp, shiftamt, xsp1->xslen);
+      }
+     else
+      {
+       /* arithmetic right shift for word32 same as logical */
+       __mwrshift(xsp1->ap, shiftamt, xsp1->xslen);
+       if (isxz) __mwrshift(xsp1->bp, shiftamt, xsp1->xslen);
+      }
+    }
+ashift_pop:
+   __pop_xstk();
+   break;
+  /* binary of these is bit by bit not reducing and ndp width is needed */
+  case /* & */ BITREDAND:
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
+   else if (xsp1->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
+     else __sizchg_widen(xsp1, ndp->szu.xclen);
+    }
+   if (xsp2->xslen > ndp->szu.xclen) __narrow_sizchg(xsp2, ndp->szu.xclen);
+   else if (xsp2->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp2, ndp->szu.xclen);
+     else __sizchg_widen(xsp2, ndp->szu.xclen);
+    }
+
+   __lbitand(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp, xsp1->xslen);
+   __pop_xstk();
+   break;
+  case /* | */ BITREDOR:
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
+   else if (xsp1->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
+     else __sizchg_widen(xsp1, ndp->szu.xclen);
+    }
+   if (xsp2->xslen > ndp->szu.xclen) __narrow_sizchg(xsp2, ndp->szu.xclen);
+   else if (xsp2->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp2, ndp->szu.xclen);
+     else __sizchg_widen(xsp2, ndp->szu.xclen);
+    }
+
+   __lbitor(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp, xsp1->xslen);
+   __pop_xstk();
+   break;
+  case /* ^ */ BITREDXOR:
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
+   else if (xsp1->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
+     else __sizchg_widen(xsp1, ndp->szu.xclen);
+    }
+   if (xsp2->xslen > ndp->szu.xclen) __narrow_sizchg(xsp2, ndp->szu.xclen);
+   else if (xsp2->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp2, ndp->szu.xclen);
+     else __sizchg_widen(xsp2, ndp->szu.xclen);
+    }
+
+   __lbitxor(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp, xsp1->xslen);
+   __pop_xstk();
+   break;
+  case /* ^~ */ REDXNOR:
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
+   else if (xsp1->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
+     else __sizchg_widen(xsp1, ndp->szu.xclen);
+    }
+   if (xsp2->xslen > ndp->szu.xclen) __narrow_sizchg(xsp2, ndp->szu.xclen);
+   else if (xsp2->xslen < ndp->szu.xclen)
+    {
+     if (ndp->has_sign) __sgn_xtnd_widen(xsp2, ndp->szu.xclen);
+     else __sizchg_widen(xsp2, ndp->szu.xclen);
+    }
+
+   __lbitxnor(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp, xsp1->xslen);
+   __pop_xstk();
+   break;
+  case /* != */ RELNEQ:
+  case /* == */ RELEQ:
+   /* SJM 10/16/00 - for non equal when x/z in either not counted must be */
+   /* less pessimistic not equal */
+   /* LOOKATME - this is complex - can it be simplified? */
+
+   /* widen narrower to be same as wider - may need sign xtnd */
+   /* SJM 05/13/04 - was wrongly using the 1 bit result not other opand */
+   if (xsp1->xslen > xsp2->xslen)
+    {
+     /* SJM 05/13/04 - since result 1 bit word32 but operand cmp signed */
+     if (ndp->rel_ndssign) __sgn_xtnd_widen(xsp2, xsp1->xslen);
+     else __sizchg_widen(xsp2, xsp1->xslen);
+    }
+   else if (xsp2->xslen > xsp1->xslen)
+    {
+     if (ndp->rel_ndssign) __sgn_xtnd_widen(xsp1, xsp2->xslen);
+     else __sizchg_widen(xsp1, xsp2->xslen);
+    }
+
+   /* result goes into 1 bit tos and know ndp xclen is 1 here */
+   /* SJM 05/13/04 - compare can't be signed since eq */
+   cmpval = __do_widecmp(&isxz, xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp,
+     xsp1->xslen);
+
+   rtb = 0;
+   if (isxz)
+    {
+     if (!__omitxz_widenoteq(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp,
+      xsp1->xslen)) rtb = rta = 1L;
+     else { if (ndp->optyp == RELEQ) rta = 0; else rta = 1; }
+    }
+   else
+    {
+     if (ndp->optyp == RELEQ) rta = (cmpval == 0); else rta = (cmpval != 0);
+    }
+   goto make_1bit;
+  case /* >= */ RELGE:
+  case /* > */ RELGT:
+  case /* <= */ RELLE:
+  case /* < */ RELLT:
+   /* widen narrower to be same as wider - may need sign xtnd */
+   /* SJM 05/13/04 - was wrongly using the 1 bit result not other opand */
+   if (xsp1->xslen > xsp2->xslen)
+    {
+     /* SJM 05/13/04 - since result 1 bit word32 but operand cmp signed */
+     if (ndp->rel_ndssign) __sgn_xtnd_widen(xsp2, xsp1->xslen);
+     else __sizchg_widen(xsp2, xsp1->xslen);
+    }
+   else if (xsp2->xslen > xsp1->xslen)
+    {
+     if (ndp->rel_ndssign) __sgn_xtnd_widen(xsp1, xsp2->xslen);
+     else __sizchg_widen(xsp1, xsp2->xslen);
+    }
+
+   /* result goes into 1 bit tos and know ndp xclen is 1 here */
+   /* AIV 05/27/04 - must be nd sign not res node has sign since res 1 bit */ 
+   if (ndp->rel_ndssign)
+    {
+     /* SJM 05/10/04 - wide sign compare casts to int32 on not == */
+     cmpval = __do_sign_widecmp(&isxz, xsp1->ap, xsp1->bp, xsp2->ap,
+      xsp2->bp, xsp1->xslen);
+    }
+   else
+    {
+     cmpval = __do_widecmp(&isxz, xsp1->ap, xsp1->bp, xsp2->ap,
+      xsp2->bp, xsp1->xslen);
+    }
+   if (isxz) { rtb = rta = 1L; goto make_1bit; }
+   rta = rtb = 0L;
+
+   switch ((byte) ndp->optyp) {
+    case RELGE: rta = (cmpval >= 0); break;
+    case RELGT: rta = (cmpval > 0); break;
+    case RELLE: rta = (cmpval <= 0); break;
+    case RELLT: rta = (cmpval < 0); break;
+   }
+make_1bit:
+   /* this is need because a and b parts must be kept contiguous */
+   /* SJM 09/30/03 - can use simpler narrow to 1 bit */
+   __narrow_to1bit(xsp1);
+   xsp1->ap[0] = rta;
+   xsp1->bp[0] = rtb;
+   xsp1->xslen = 1;
+   __pop_xstk();
+   break;
+  case /* === */ RELCEQ:
+  case /* !== */ RELCNEQ:
+   /* SJM 09/29/03 - only widen - can be signed */
+   if (xsp1->xslen > xsp2->xslen)
+    { 
+     /* only signed if both signed */
+     if (ndp->rel_ndssign) __sgn_xtnd_widen(xsp2, xsp1->xslen);
+     else __sizchg_widen(xsp2, xsp1->xslen);
+    }
+   else if (xsp2->xslen > xsp1->xslen)
+    {
+     if (ndp->lu.x->has_sign) __sgn_xtnd_widen(xsp1, xsp2->xslen);
+     else __sizchg_widen(xsp1, xsp2->xslen);
+    }
+
+   /* returns 1 if not equal, 0 if equal */
+   cmpval = __do_xzwidecmp(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp,
+    xsp1->xslen);
+   rtb = 0L;
+   if (ndp->optyp == RELCEQ) rta = (cmpval == 0); else rta = (cmpval != 0);
+   goto make_1bit;
+  case /* && */ BOOLAND:
+   rtb = 0L;
+   tmp1 = __cvt_lngbool(xsp1->ap, xsp1->bp, wlen_(xsp1->xslen));
+   if (tmp1 == 0) { rta = 0L; goto make_1bit; }
+   tmp2 = __cvt_lngbool(xsp2->ap, xsp2->bp, wlen_(xsp2->xslen));
+   if (tmp2 == 0) { rta = 0L; goto make_1bit; }
+   if (tmp1 == 1 && tmp2 == 1) rta = 1L; else rta = rtb = 1L;
+   goto make_1bit;
+  case /* || */ BOOLOR:
+   rtb = 0L;
+   tmp1 = __cvt_lngbool(xsp1->ap, xsp1->bp, wlen_(xsp1->xslen));
+   if (tmp1 == 1) { rta = 1L; goto make_1bit; }
+   tmp2 = __cvt_lngbool(xsp2->ap, xsp2->bp, wlen_(xsp2->xslen));
+   if (tmp2 == 1) { rta = 1L; goto make_1bit; }
+   if (tmp1 == 0 && tmp2 == 0) rta = 0L; else rta = rtb = 1L;
+   goto make_1bit;
+
+  /* SJM 03/01/00 - all real binaries can be wide if one wide operand and */
+  /* other real (usually 64 bit time) - need to be converted to real and */
+  /* evaled as real - same as non wide case be duplicated here so no */
+  /* need for extra test in eval inner loop - the non real arg converted */
+  /* to real */
+  case /* + real */ REALPLUS:
+   /* is it portable to pass 1 bit bit field? */
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+
+   /* notice never a size change since both must be real */
+   d1 += d2;
+   /* this works because minimum stack every allocated is 8 bytes */
+   /* PORTABILITY - stack must always be at least 8 bytes */
+   memcpy(xsp1->ap, &d1, sizeof(double));
+   __pop_xstk();
+   return;
+  case /* - real */ REALMINUS:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   d1 -= d2;
+   /* notice never a size change since both must be real */
+   memcpy(xsp1->ap, &d1, sizeof(double));
+   __pop_xstk();
+   return;
+  case /* * real */ REALTIMES:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   /* notice never a size change since both must be real */
+   d1 *= d2;
+   memcpy(xsp1->ap, &d1, sizeof(double));
+   __pop_xstk();
+   return;
+  case /* * real */ REALDIV:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   /* notice never a size change since both must be real */
+   d1 /= d2;
+   memcpy(xsp1->ap, &d1, sizeof(double));
+   __pop_xstk();
+   return;
+  case /* >= real */ REALRELGE:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   rta = (d1 >= d2) ? 1L : 0L;
+   rtb = 0L; 
+   goto make_1bit;
+  case /* > real */ REALRELGT:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   rta = (d1 > d2) ? 1L : 0L;
+   rtb = 0L; 
+   goto make_1bit;
+  case /* <= real */ REALRELLE:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   rta = (d1 <= d2) ? 1L : 0L;
+   rtb = 0L; 
+   goto make_1bit;
+  case /* < real */ REALRELLT:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+
+   /* notice never a size change since both must be real */
+   rta = (d1 < d2) ? 1L : 0L;
+   rtb = 0L; 
+   goto make_1bit;
+  case /* != real */ REALRELNEQ:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+
+   /* notice never a size change since both must be real */
+   /* this is ieee float point dependent */
+   rta = (fabs(d1 - d2) >= EPSILON) ? 1L : 0L;
+   rtb = 0L; 
+   goto make_1bit;
+  case /* == real */ REALRELEQ:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   /* notice never a size change since both must be real */
+   /* this is ieee float point dependent */
+   rta = (fabs(d1 - d2) >= EPSILON) ? 0L : 1L;
+   rtb = 0L; 
+   goto make_1bit;
+  case /* && real */ REALBOOLAND:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   /* notice never a size change since both must be real */
+   rta = (d1 != 0.0 && d2 != 0.0) ? 1L : 0L;   
+   rtb = 0L; 
+   goto make_1bit;
+  case /* && real */ REALBOOLOR:
+   lx = ndp->lu.x;
+   rx = ndp->ru.x;
+   if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
+   else memcpy(&d1, xsp1->ap, sizeof(double));
+
+   if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
+   else memcpy(&d2, xsp2->ap, sizeof(double));
+   /* notice never a size change since both must be real */
+   rta = (d1 != 0.0 || d2 != 0.0) ? 1L : 0L;   
+   rtb = 0L; 
+   goto make_1bit;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * if any x in bin. operand nodes set accumulator to all x's and return T
+ */
+extern int32 __set_binxresult(word32 *resap, word32 *resbp, word32 *op1bp,
+ word32 *op2bp, int32 opbits)
+{
+ if (!vval_is0_(op1bp, opbits)) goto not_zero;
+ if (!vval_is0_(op2bp, opbits)) goto not_zero;
+ return(FALSE);
+
+not_zero:
+ one_allbits_(resap, opbits);
+ one_allbits_(resbp, opbits);
+ return(TRUE);
+}
+
+/*
+ * right shift multiword value into new valune - shift value <1m (1 word32)
+ * know shiftval <= lwlen
+ *
+ * notice no need to mask off high bits here;
+ */
+extern void __mwrshift(word32 *valwp, word32 shiftval, int32 blen)
+{
+ int32 shwords, shbits, lwlen;
+
+ lwlen = wlen_(blen);
+ shwords = get_wofs_(shiftval);
+ /* notice value here is 0-31 */
+ shbits = ubits_(shiftval);
+
+ /* DBG remove ---
+ if (__debug_flg)
+  __dbg_msg("---> mw right shift of %d was %lx", shiftval, valwp[0]);
+ --- */
+ if (shwords != 0) wrdmwrshift(valwp, shwords, lwlen);
+ if (shbits != 0) bitmwrshift(valwp, shbits, lwlen);
+ /* DBG remove --
+ if (__debug_flg) __dbg_msg("after %lx\n", valwp[0]);
+ */
+}
+
+/*
+ * arithmetic right shift multiword value into new value
+ * 
+ * arithmetic (signed) version of multi-word right shift - if sign 1,
+ * then set area to 1's not 0
+ *
+ * SJM 10/08/04 - this shifts both a and b part
+ */
+extern void __arith_mwrshift(word32 *valwp, word32 shiftval, int32 blen)
+{
+ register int32 wlen, wi;
+ int32 sign_bi, bi, shwords, shbits, nblen, is_signed;
+
+ wlen = wlen_(blen);
+ sign_bi = get_bofs_(blen - 1);
+  
+ if ((valwp[wlen - 1] & (1 << sign_bi)) != 0) is_signed = TRUE;
+ else is_signed = FALSE;
+
+ shwords = get_wofs_(shiftval);
+ /* notice ubits and get_bofs macros are the same */
+ shbits = get_bofs_(shiftval);
+ /* do normal shift */
+ if (shwords != 0) wrdmwrshift(valwp, shwords, wlen);
+ if (shbits != 0) bitmwrshift(valwp, shbits, wlen);
+
+ if (!is_signed) return;
+
+ /* tricky part is making sure sign/x/z bit gets shifted in (duplicated) */
+ /* new sign bit is one less than new bit len */
+ nblen = blen - shiftval;
+ /* set 1 bits for wi+1 to end and high bits in wi word32 */
+ bi = get_bofs_(nblen);
+ wi = get_wofs_(nblen); 
+ if (bi != 0)
+  {
+   valwp[wi] |= (__masktab[WBITS - bi] << bi);
+   one_allbits_(&(valwp[wi + 1]), shiftval - (WBITS - bi));
+  }
+ else one_allbits_(&(valwp[wi]), shiftval);
+}
+
+/*
+ * wide left shift - know value will not be wider than WBITS
+ * for left shift must mask off high bits
+ *
+ * SJM 10/01/03 - for wide left shift arithmetic is same
+ */
+extern void __mwlshift(word32 *valwp, word32 shiftval, int32 blen)
+{
+ int32 shwords, shbits, lwlen, ubits;
+
+ lwlen = wlen_(blen);
+ /* this and 1f for 32 mask on number of bits */
+ shwords = get_wofs_(shiftval);
+ /* notice value here is 0-31 */
+ shbits = ubits_(shiftval);
+
+ /* DBG remove --
+ if (__debug_flg)
+  __dbg_msg("---> mw left shift of %d was %lx", shiftval, valwp[0]);
+ -- */
+ if (shwords != 0) wrdmwlshift(valwp, shwords, lwlen);
+ if (shbits != 0) bitmwlshift(valwp, shbits, lwlen);
+ ubits = ubits_(blen);
+ valwp[lwlen - 1] &= __masktab[ubits];
+ /* DBG remove ---
+ if (__debug_flg) __dbg_msg("after %lx\n", valwp[0]);
+ --- */
+}
+
+/*
+ * partial word32 shift within multiword value
+ * k < WBITS bits mw right shift (high bits toward low bits - divide)
+ * this handles bit shifting - other part does word32 shifting
+ */
+static void bitmwrshift(register word32 *wp, register int32 k, register int32 lwlen)
+{
+ register int32 i;
+ register word32 cy;
+
+ wp[0] >>= k;
+ for (i = 1; i < lwlen; i++)
+  {
+   cy = (wp[i] & __masktab[k]) << (WBITS - k);
+   wp[i - 1] |= cy;
+   /* C language right shift of word32 defined to shift in 0's */
+   wp[i] >>= k;
+  }
+ /* since know wp right width with high zero's - know anwswer is right */
+}
+
+/*
+ * partial word32 shift within multiword value
+ * k < WBITS bits mw left shift (low bits toward high - mult.)
+ * this handles bit shifting - other part does word32 shifting
+ */
+static void bitmwlshift(register word32 *wp, register int32 k, register int32 lwlen)
+{
+ register int32 i;
+ register word32 cy;
+
+ wp[lwlen - 1] <<= k;
+ for (i = lwlen - 2; i >= 0; i--)
+  {
+   cy = ((wp[i] >> (WBITS - k)) & __masktab[k]);
+   wp[i + 1] |= cy;
+   /* C language left logical shift of word32 defined to shift in 0's */
+   wp[i] <<= k;
+  }
+}
+
+/*
+ * whole word32 right shift within multiword value
+ * kwrds is number of words
+ * high words toward low - divide by 2**32 units
+ * this handles word32 shifting - other part does bit shifting
+ * know kwrds never 0
+ */
+static void wrdmwrshift(register word32 *wp, register int32 kwrds,
+ register int32 lwlen)
+{
+ register int32 wi;
+
+ for (wi = kwrds; wi < lwlen; wi++)  wp[wi - kwrds] = wp[wi];
+ for (wi = lwlen - kwrds; wi < lwlen; wi++) wp[wi] = 0L;
+}
+
+/*
+ * whole word32 left shift within multiword value
+ * kwrds is number of words
+ * low words toward high- multiply by 2**32 units
+ * this handles word32 shifting - other part does bit shifting
+ * know kwrds never 0
+ */
+static void wrdmwlshift(register word32 *wp, register int32 kwrds,
+ register int32 lwlen)
+{
+ register int32 swi, wi;
+
+ for (swi = lwlen - 1; swi >= kwrds; swi--) wp[swi] = wp[swi - kwrds];
+ for (wi = 0; wi < kwrds; wi++) wp[wi] = 0L;
+}
+
+/*
+ * long binary bit and - in place from top to 1 down
+ * know both operands correct final width
+ */
+extern void __lbitand(word32 *op1ap, word32 *op1bp, word32 *op2ap, word32 *op2bp,
+ int32 opbits)
+{
+ register int32 wi;
+
+ for (wi = 0; wi < wlen_(opbits); wi++)
+  {
+   if ((op1bp[wi] | op2bp[wi]) == 0L)
+    { op1bp[wi] = 0L; op1ap[wi] = op1ap[wi] & op2ap[wi]; }
+   else
+    {
+     op1ap[wi] = (op1ap[wi] | op1bp[wi]) & (op2ap[wi] | op2bp[wi]);
+     op1bp[wi] = op1ap[wi] & (op2bp[wi] | op1bp[wi]);
+    }
+  }
+}
+
+/*
+ * long binary bit or - both operands on stack already widened to same size
+ * no reason to mask off high since both xor and or of 0 and 0 are 0
+ */
+extern void __lbitor(word32 *op1ap, word32 *op1bp, word32 *op2ap, word32 *op2bp,
+ int32 opbits)
+{
+ register int32 wi;
+
+ for (wi = 0; wi < wlen_(opbits); wi++)
+  {
+   if ((op1bp[wi] | op2bp[wi]) == 0L)
+    { op1bp[wi] = 0L; op1ap[wi] = op1ap[wi] | op2ap[wi]; }
+   else
+    {
+     op1bp[wi] = op2bp[wi] ^ op1bp[wi] ^ ((op1ap[wi] | op1bp[wi])
+      & (op2bp[wi] | (op2ap[wi] & op1bp[wi])));
+     op1ap[wi] = op1bp[wi] | op2ap[wi] | op1ap[wi];
+    }
+  }
+}
+
+/*
+ * long binary bit xor - both operands on stack already widened
+ * to exactly same width 
+ */
+extern void __lbitxor(word32 *op1ap, word32 *op1bp, word32 *op2ap, word32 *op2bp,
+ int32 opbits)
+{
+ register int32 wi;
+ int32 wlen;
+
+ wlen = wlen_(opbits);
+ for (wi = 0; wi < wlen; wi++)
+  {
+   if ((op1bp[wi] | op2bp[wi]) == 0L)
+    { op1bp[wi] = 0L; op1ap[wi] = op1ap[wi] ^ op2ap[wi]; }
+   else
+    {
+     op1bp[wi] = op1bp[wi] | op2bp[wi];
+     op1ap[wi] = op1bp[wi] | (op1ap[wi] ^ op2ap[wi]);
+    }
+  }
+ /* know high bits are 0, since both op's high bits 0 */
+}
+
+/*
+ * long binary bit xnor - both operands on stack already widened
+ */
+extern void __lbitxnor(word32 *op1ap, word32 *op1bp, word32 *op2ap, word32 *op2bp,
+ int32 opbits)
+{
+ register int32 wi;
+ int32 wlen;
+
+ wlen = wlen_(opbits);
+ for (wi = 0; wi < wlen; wi++)
+  {
+   if ((op1bp[wi] | op2bp[wi]) == 0L)
+    { op1bp[wi] = 0L; op1ap[wi] = ~(op1ap[wi] ^ op2ap[wi]); }
+   else
+    {
+     op1bp[wi] = op1bp[wi] | op2bp[wi];
+     op1ap[wi] = op1bp[wi] | ~(op1ap[wi] ^ op2ap[wi]);
+    }
+  }
+ op1ap[wlen - 1] &= __masktab[ubits_(opbits)];
+ /* know high bits in b part are 0, since both op's high bits 0 */
+}
+
+/*
+ * convert wide value on top of reg stack to boolean - any 1=1,0,x(3)
+ * must be extern since invoked by macro
+ */
+extern int32 __cvt_lngbool(word32 *ap, word32 *bp, int32 wlen)
+{
+ register int32 wi;
+ int32 hasxs;
+
+ for (hasxs = FALSE, wi = 0; wi < wlen; wi++)
+  {
+   if ((ap[wi] & ~bp[wi]) != 0L) return(1);
+   if (bp[wi] != 0L) hasxs = TRUE;
+  }
+ if (hasxs) return(3);
+ return(0);
+}
+
+/*
+ * compare word32 first with second - know widths the same
+ *
+ * set isx if either has x or z, else -1 <, 0 = , 1 >
+ * know all wider than WBITS values in Verilog are unsigned
+ * not for === or !== sincd non x even if x's or z's
+ *
+ * know size change made so both same no. words and high bits of narrow now 0 
+ */
+extern int32 __do_widecmp(int32 *isx, register word32 *op1ap, register word32 *op1bp,
+ register word32 *op2ap, register word32 *op2bp, int32 opwid)
+{
+ register int32 i;
+
+ *isx = TRUE;
+ if (!vval_is0_(op1bp, opwid)) return(0);
+ if (!vval_is0_(op2bp, opwid)) return(0);
+
+ *isx = FALSE;
+ /* know unused parts of high words will both be zero */
+ for (i = wlen_(opwid) - 1; i >= 0; i--)
+  {
+   if (op1ap[i] != op2ap[i])
+    { if (op1ap[i] < op2ap[i]) return(-1); else return(1); }
+  }
+ return(0);
+}
+
+/*
+ * compare signed wide first with second - know widths the same
+ *
+ * set isx if either has x or z, else -1 <, 0 = , 1 >
+ * not for === or !== sincd non x even if x's or z's
+ *
+ * know size change made so both same no. words and high bits of narrow now 0 
+ */
+extern int32 __do_sign_widecmp(int32 *isx, register word32 *op1ap,
+ register word32 *op1bp, register word32 *op2ap, register word32 *op2bp, int32 opwid)
+{
+ register int32 i, i1, i2;
+ int32 wlen;
+
+ *isx = TRUE;
+ if (!vval_is0_(op1bp, opwid)) return(0);
+ if (!vval_is0_(op2bp, opwid)) return(0);
+
+ *isx = FALSE;
+ /* wi is index of high word32 */
+ wlen = wlen_(opwid);
+ 
+ /* if op1 is negative */
+ if ((op1ap[wlen - 1] & (1 << ubits_(opwid - 1))) != 0)
+  {
+   /* if op1 is negative and op2 is positive */
+   if (!(op2ap[wlen - 1] & (1 << ubits_(opwid - 1))) != 0) return(-1);
+  }
+ /* op1 is positive and op2 is negative */
+ else if ((op2ap[wlen - 1] & (1 << ubits_(opwid - 1))) != 0) return(1);
+
+ /* here both will have the same sign (especially high word32) */
+ /* know unused parts of high words will both be zero */
+ for (i = wlen_(opwid) - 1; i >= 0; i--)
+  {
+   if (op1ap[i] != op2ap[i])
+    {
+     i1 = (sword32) op1ap[i];    
+     i2 = (sword32) op2ap[i];
+     if (i1 < i2) return(-1);
+     else return(1);
+    }
+  }
+ return(0);
+}
+
+/*
+ * compare known x/z wide values and return T if not equal when x/z bits
+ * ignored
+ *
+ * SJM 10/16/00 - routine for wide == or != return T if non x/z 
+ * comparision is not equal (i.e. if for every word32 any x/z bits in either
+ * 1st or 2nd operand are set to same 1 for comparison, then if value not
+ * equal x/z bits do not effect outcome so result must be not equal)
+ *
+ * no need for high bit masking because high unused set to 0 and size
+ * change made to make bits same width
+ * know size change made before calling this so both same words with narrower's
+ * high bits 0 (if one was narrower)
+ */
+extern int32 __omitxz_widenoteq(register word32 *op1ap, register word32 *op1bp,
+ register word32 *op2ap, register word32 *op2bp, int32 opwid)
+{
+ register word32 xzmask;
+ int32 i;
+ 
+ /* know unused parts of high words will both be zero */
+ /* when find first bit that makes not equal after masking all x/z in both */
+ /* to same, done */
+ for (i = wlen_(opwid) - 1; i >= 0; i--)
+  {
+   xzmask = op1bp[i] | op2bp[i];
+   if ((op1ap[i] | xzmask) != (op2ap[i] | xzmask)) return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * compare word32 first with second - know widths the same
+ * returns 1 if non equal 0 if equal
+ * for === and !== compare cannot be used for greater or less 
+ *
+ * do not need to worry about high bits since sematics requires 0 extend
+ * and 0 and 0 will match as 0 (never effect result)
+ */
+extern int32 __do_xzwidecmp(register word32 *op1ap, register word32 *op1bp,
+ register word32 *op2ap, register word32 *op2bp, int32 opbits)
+{
+ int32 bytlen;
+
+ bytlen = WRDBYTES*wlen_(opbits);
+ if (memcmp(op1ap, op2ap, bytlen) != 0 || memcmp(op1bp, op2bp, bytlen) != 0)
+  return(1);
+ return(0);
+}
+
+/*
+ * MULTIWORD ARITHMETIC ROUTINES
+ */
+
+/*
+ * routines taken from BSD style license mpexpr package and modified
+ * to match Verilog internal storage requirements and operation semantics
+ * routines mostly stright forward implementations from Knuht Vol. 2
+ *  
+ * here is copyright notice in mpexpr package zmath.c file: 
+ *
+ * Copyright (c) 1994 David I. Bell
+ * Permission is granted to use, distribute, or modify this source,
+ * provided that this copyright notice remains intact.
+ *
+ * Extended precision integral arithmetic primitives
+ *
+ * I have re-written these routines to use Cver endian code and to use
+ * result wrap around trick for determining add/sub carry from 32 bit
+ * words without using 64 bit arithemtic - also not using packages n**1.6
+ * multiply routine since more then 300 (or so) bit multiples rare in
+ * verilog
+ */
+
+/*
+ * wide word32 add
+ * know u and v same width and resp wide enough and high zeroed
+ * >WBITS always unsigned
+ *
+ * result and operands can't be same
+ * LOOKATME - think not worth converting to word32 64 array
+ *
+ * SJM 09/30/03 - for signed just works because of 2's complement  
+ */
+extern void __ladd(word32 *res, word32 *u, word32 *v, int32 blen)
+{
+ register word32 a2;
+ register word32 *u_end, cy;
+ int32 ublen, vblen, trimblen, wlen, hzwlen, verwlen;
+ extern void __my_fprintf(FILE *, char *, ...);
+ 
+ ublen = __trim1_0val(u, blen);
+ vblen = __trim1_0val(v, blen);
+ trimblen = (ublen >= vblen) ? ublen : vblen;
+ /* if trimmed max fits, need 1 more word32 for carry that is needed */ 
+ if ((wlen = wlen_(trimblen)) < (verwlen = wlen_(blen))) wlen++;
+ if ((hzwlen = verwlen - wlen) > 0)
+  memset(&(res[wlen]), 0, WRDBYTES*hzwlen);
+
+ u_end = &(u[wlen]);
+ cy = 0;
+ do {
+   /* DBG remove --
+   __dbg_msg("at top of loop: cy=%0x\n", cy); 
+   -- */ 
+   a2 = *v++;
+   *res = *u++ + a2 + cy;
+   /* use wrap around 32 bit test and auto incr instead of mpexpr cast */
+   /* to word32 64 although current gcc does not handle auto inc/dec well */
+ 
+   /* notice if cy on if res and v equal, must not turn off */
+   /* also if cy off if res and v equal, do not turn on */
+   if (cy == 0) { if (*res < a2) cy = 1; }
+   else { if (*res > a2) cy = 0; }
+   res++;
+
+   /* DBG remove ---
+   __dbg_msg("*u=%0x, *v=%0x, a2=%0x, *res=%0x, cy=%0x\n", u[-1], v[-1],
+     a2, res[-1], cy);
+   --- */
+  } while (u < u_end);
+
+ /* usually do not need this but faster to mask than test and then mask */
+ res--;
+ *res &= __masktab[ubits_(blen)];
+}
+
+/*
+ * wide subtract
+ * know u and v same width and resp wide enough and zeroed
+ * also res can be same as u or v (needed for ldiv2)
+ * can get by with 32 bit arithmetic here
+ * since mask any unused high bits - can borrow from unused
+ *
+ * LOOKATME - think not worth converting to word32 64 array
+ * SJM 09/28/03 - 2's complement means signed just interpretation
+ * i.e. if sign bit on then negative
+ */
+extern word32 __lsub(word32 *res, word32 *u, word32 *v, int32 blen)
+{
+ register word32 *u_end, borrow, tmpres;
+ int32 wlen;
+
+ wlen = wlen_(blen);
+ borrow = 0; 
+ u_end = &(u[wlen]);
+ do {
+   /* modified to use only 32 bit arithmetic and ptr inc */
+   if ((tmpres = *u++ - borrow) > (ALL1W - borrow)) tmpres = ALL1W - *v; 
+   else if ((tmpres -= *v) > (ALL1W - *v)) borrow = 1;
+   else borrow = 0;
+   *res++ = tmpres; 
+   v++;
+ } while (u < u_end);
+ /* notice in Verilog borrow always taken - even though nothing higher */
+ res--; 
+ *res &= __masktab[ubits_(blen)];
+ return(borrow);
+} 
+
+/*
+ * multiple 2 multi-word32 signed numbers
+ *
+ * wrapper that use normal word32 lmult on absolute values
+ * since no x/z part (already handled) no x/z extension
+ * BEWARE - this depends on fact that xstk ap/bp parts contiguous
+ */
+extern void __sgn_lmult(register word32 *res, register word32 *u,
+ register word32 *v, int32 blen)
+{
+ int32 wlen, usign, vsign;
+ word32 *wrku, *wrkv;
+ struct xstk_t *uxsp, *vxsp;
+
+ wlen = wlen_(blen);
+ usign = vsign = 1;
+ uxsp = vxsp = NULL;
+ if (__is_lnegative(u, blen))
+  {
+   /* SJM 09/15/04 - lnegate need both a and b parts */
+   push_xstk_(uxsp, blen);
+   usign = -1;
+   /* ignoring carry */
+   __cp_lnegate(uxsp->ap, u, blen);
+   wrku = uxsp->ap;
+  }
+ else wrku = u;
+ if (__is_lnegative(v, blen))
+  {
+   /* SJM 09/15/04 - lnegate need both a and b parts */
+   push_xstk_(vxsp, blen);
+   vsign = -1;
+   /* ignoring carry */
+   __cp_lnegate(vxsp->ap, v, blen);
+   wrkv = vxsp->ap;
+  }
+ else wrkv = v;
+
+ __lmult(res, wrku, wrkv, blen);
+ if ((usign*vsign) == -1)
+  {
+   __inplace_lnegate(res, blen);
+  }
+ if (uxsp != NULL) __pop_xstk();
+ if (vxsp != NULL) __pop_xstk();
+}
+
+/*
+ * routine to determine if signed val negative by checking sign bit
+ * 
+ * FIXME - this should be macro
+ */
+extern int32 __is_lnegative(word32 *u, int32 blen) 
+{
+ register int32 wi, bi;
+
+ blen--;
+ wi = get_wofs_(blen);
+ bi = get_bofs_(blen);
+ if ((u[wi] & (1 << bi)) != 0) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * in place routine to compute 2's complement negation of signed wide number
+ * formula is ~(value) + 1
+ * return carry if any but not used for now
+ * in place
+ *
+ * LOOKATME - copy version - maybe in place better
+ */
+extern word32 __inplace_lnegate(register word32 *u, int32 blen)
+{
+ register int32 wi, ubits;
+ int32 wlen;
+ word32 cy;
+ 
+ wlen = wlen_(blen);
+ for (wi = 0; wi < wlen; wi++) u[wi] = ~(u[wi]);
+ ubits = ubits_(blen); 
+ u[wlen - 1] &= __masktab[ubits]; 
+ /* SJM 09/15/04 - was wrongly passes ubits so was not incing high words */ 
+ cy = sgn_linc(u, blen);
+ return(cy);
+}
+
+/*
+ * copy routine to compute 2's complement negation of signed wide number
+ * formula is ~(value) + 1
+ * return carry if any but not used for now
+ * in place
+ *
+ * LOOKATME - copy version - maybe in place better
+ */
+extern word32 __cp_lnegate(word32 *u, register word32 *v, int32 blen)
+{
+ register int32 wi, ubits;
+ word32 cy;
+ int32 wlen;
+ 
+ wlen = wlen_(blen);
+ for (wi = 0; wi < wlen; wi++, v++) u[wi] = ~(*v);
+ ubits = ubits_(blen); 
+ u[wlen - 1] &= __masktab[ubits]; 
+
+ cy = sgn_linc(u, blen);
+ return(cy);
+}
+
+/*
+ * inc (add 1) in place to wide signed value
+ */
+static int32 sgn_linc(register word32 *u, int32 blen)
+{
+ register int32 wi, ubits;
+ register int32 wlen;
+
+ wlen = wlen_(blen);
+ /* done when no carry - special case speed up attmpt */ 
+ if (++(u[0]) != 0) return(0); 
+
+ /* enter loop with cy */
+ for (wi = 1; wi < wlen; wi++)
+  {
+   /* add the carry from last one */
+   if (++(u[wi]) != 0)
+    {
+     if (wi != wlen - 1) return(0);
+     ubits = ubits_(blen);
+     u[wi] &= __masktab[ubits];
+     return(1);
+    }
+  }
+ /* value was all 1's and fills high word32, no mask but return cy */
+ /* 2's complement of 0 is 0 plus carry */
+ return(1);
+}
+
+/*
+ * multiply two multi-word32 numbers to obtain the double len product
+ *
+ * notice res must not be same addr as u or v
+ * original idea for this routine came from Dr. Dobbs article
+ *
+ * this does not use mpexpr recursive 1.6 power multiply since Verilog
+ * numbers rarely wider than 300 bits - algorithm is simple distributed
+ * accumulate
+ *
+ * SJM 09/28/03 - must multply with absolute values so there is sign  
+ * handling wrapper for signed wide multiply
+ */
+extern void __lmult(register word32 *res, register word32 *u, register word32 *v,
+ int32 blen)
+{
+ register int32 i;
+ int32 wlen, ublen, vblen, uwlen, vwlen, prodwlen;
+ word32 *wp;
+ w64_u w64res;
+ struct xstk_t *xsp;
+ 
+ /* set result to zero for special case - not using b part - left as 0 */
+ wlen = wlen_(blen);
+ memset(res, 0, wlen*WRDBYTES);
+
+ /* normalize - by finding bit widths for u and v */
+ ublen = __trim1_0val(u, blen);
+ vblen = __trim1_0val(v, blen);
+ if (ublen == 0 || vblen == 0) return;
+ /* if trim so that both multipliers fit in 32 bits use 64 prod routine */
+ /* know blen > WBITS or will not be called */
+ if (ublen <= WBITS && vblen <= WBITS) 
+  {
+   /* notice if blen wider then 64 - values already 0ed and left 0ed */
+   w64res.w64v = ((word64) *u)*((word64) *v);
+   res[0] = w64res.w_u.low;
+   /* SJM 12/07/01 - and out any bits wider than blen if blen < 64 */
+   /* very wide blen can trim to here, if so no mask needed */
+   res[1] = w64res.w_u.high;
+   if (blen < 64) res[1] &= __masktab[ubits_(blen)];
+   return;
+  }
+ /* at least one trim wider than 32 but no carry to high since blen <= 64 */
+ if (blen <= 64) 
+  {
+   w64_u w64op1, w64op2;
+   
+   /* LOOKATME - could just use pointer for little endia X86 */
+   w64op1.w_u.low = u[0];
+   w64op1.w_u.high = u[1]; 
+   w64op2.w_u.low = v[0];
+   w64op2.w_u.high = v[1]; 
+   w64res.w64v = w64op1.w64v * w64op2.w64v;
+   res[0] = w64res.w_u.low;
+   /* SJM 12/07/01 - and out any bits wider than blen - fastest always mask */
+   res[1] = w64res.w_u.high & __masktab[ubits_(blen)];
+   return;
+  }
+ uwlen = wlen_(ublen); 
+ vwlen = wlen_(vblen);
+ prodwlen = uwlen + vwlen;
+ /* multiply into double trimmed width product - but use all no b part */
+ push_xstk_(xsp, prodwlen*WBITS/2);
+ wp = xsp->ap;
+ memset(wp, 0, WRDBYTES*prodwlen);
+ for (i = 0; i < uwlen; i++) 
+  {
+   wp[i + vwlen] += accmuladd32(&(wp[i]), &(wp[i]), u[i], v, vwlen);
+  }
+ /* SJM 04/07/03 - need to mask high bits in high word32 here */
+ wp[wlen - 1] &= __masktab[ubits_(blen)];
+ 
+ memcpy(res, wp, ((wlen < prodwlen) ? wlen : prodwlen)*WRDBYTES); 
+ __pop_xstk();
+}
+
+/*
+ * a[] = b[] + c*d[] - compute array per word32, word32 product sum
+ * returns carry
+ */
+static int32 accmuladd32(word32 *a, word32 *b, word32 c, word32 *d, int32 wlen)
+{
+ register int32 i;
+ register word32 t0, t1, cy;
+ w64_u res;
+ word64 c64;
+
+ c64 = (word64) c;
+ for (cy = 0, i = 0; i < wlen; i++)
+  {
+   /* know product of 2 32 bit values fits in 64 bits */
+   res.w64v = c64*((word64) d[i]);
+   t0 = res.w_u.low;
+   t1 = res.w_u.high;
+
+   if ((a[i] = b[i] + cy) < cy) cy = 1; else cy = 0;
+   if ((a[i] += t0) < t0) cy++;
+   cy += t1;
+  }
+ return(cy);
+}
+
+/*
+ * interfact to signed long div and mod (keep rem) that select needed result
+ *
+ * wrapper that use normal word32 on absolute values then adjusts signs
+ * since no x/z part (already handled) no x/z extension
+ * BEWARE - this depends on fact that xstk ap/bp parts contiguous
+ */
+extern void __sgn_ldivmod(register word32 *res, register word32 *u,
+ register word32 *v, int32 blen, int32 nd_quot)
+{
+ int32 wlen, usign, vsign;
+ word32 *wrku, *wrkv;
+ struct xstk_t *uxsp, *vxsp, *tmpxsp; 
+
+ /* always need unused tmp area for unused of mod/div results */
+ wlen = wlen_(blen);
+ push_xstk_(tmpxsp, wlen*WBITS/2);
+
+ wlen = wlen_(blen);
+ usign = vsign = 1;
+ uxsp = vxsp = NULL;
+ /* div/mod routine assumes both operands positive */
+ if (__is_lnegative(u, blen))
+  {
+   /* SJM 09/15/04 - lnegate need both a and b parts */
+   push_xstk_(uxsp, blen);
+   usign = -1;
+   /* ignoring carry */
+   __cp_lnegate(uxsp->ap, u, blen);
+   wrku = uxsp->ap;
+  }
+ else wrku = u;
+ if (__is_lnegative(v, blen))
+  {
+   /* SJM 09/15/04 - lnegate need both a and b parts */
+   push_xstk_(vxsp, blen);
+   vsign = -1;
+   /* ignoring carry */
+   __cp_lnegate(vxsp->ap, v, blen);
+   wrkv = vxsp->ap;
+  }
+ else wrkv = v;
+
+ /* separate into div/mod and adjust sign according to different rules */
+ if (nd_quot)
+  {
+   __ldivmod2(res, tmpxsp->ap, wrku, wrkv, blen);
+   /* for div sign negative if one but not both negative */
+   if ((usign*vsign) == -1) __inplace_lnegate(res, blen);
+  }
+ else
+  {
+   __ldivmod2(tmpxsp->ap, res, wrku, wrkv, blen);
+   /* for mod sign same as sign of first but must do word32 wide div/mod */
+   if (usign == -1) __inplace_lnegate(res, blen);
+  }
+ if (uxsp != NULL) __pop_xstk();
+ if (vxsp != NULL) __pop_xstk();
+ __pop_xstk();
+}
+
+/*
+ * interfact to long div and mod (keep rem) that select needed result
+ */
+extern void __ldivmod(word32 *res, word32 *u, word32 *v, int32 blen, int32 nd_quot)
+{
+ int32 wlen; 
+ struct xstk_t *tmpxsp; 
+
+ wlen = wlen_(blen);
+ push_xstk_(tmpxsp, wlen*WBITS/2);
+
+ if (nd_quot) __ldivmod2(res, tmpxsp->ap, u, v, blen);
+ else __ldivmod2(tmpxsp->ap, res, u, v, blen);
+ __pop_xstk();
+}
+
+/*
+ * Divide two numbers to obtain a quotient and remainder.
+ *
+ * dividing u by v - know if v 0 already returned x value
+ * res, quot, u and v must all be different addresses
+ * u and v are preserved and no b parts are assumed to exist 
+ *
+ * blen is width of both u and z (one widened if needed from Ver semantics)
+ * fills blen wide result
+ *
+ * SJM 09/30/03 - wrapper insures operands here are positive  
+ */
+extern void __ldivmod2(word32 *quot, word32 *rem, word32 *u, word32 *v, int32 blen)
+{
+ register word32 *uwp, *vwp;
+ word32 r0;
+ int32 ublen, vblen, uwlen, vwlen, wlen, normdist, ubits;
+ struct xstk_t *xsp;
+
+ /* set rem and quotient to zero */
+ wlen = wlen_(blen);
+
+ memset(quot, 0, wlen*WRDBYTES);
+ memset(rem, 0, wlen*WRDBYTES);
+
+ /* normalize - by finding bit widths for u and v */
+ ublen = __trim1_0val(u, blen);
+ vblen = __trim1_0val(v, blen);
+ /* 0 over anything is quotient and remainder of 0 */
+ if (ublen == 0) return;
+
+ /* can use c division - know not signed */
+ if (ublen <= WBITS && vblen <= WBITS) 
+  { quot[0] = u[0] / v[0]; rem[0] = u[0] % v[0]; return; }
+
+ /* if divisor fits in half word32, use fast linear algorithm */
+ if (vblen <= WBITS/2)
+  {
+   /* special divide by 1 - rem is 0 (already initialized and quot is u) */
+   if (v[0] == 1)
+    {
+     cp_walign_(quot, u, ublen);
+     return;
+    }
+   __by16_ldivmod(quot, &r0, u, v[0], ublen);
+   rem[0] = r0;
+   return;
+  }
+ /* if u smaller in abs. value then v, answer immediate */
+ uwlen = wlen_(ublen);
+ vwlen = wlen_(vblen);
+ /* if u smaller than v, then rem is u and quotient is 0 */
+ /* think this is wrong - what about extra high part of 1 ? */
+ if (ldiv_cmp(u, v, ((uwlen < vwlen) ? vwlen : uwlen)) < 0)
+  { cp_walign_(rem, u, blen); return; }
+
+ /* need long division */
+ /* normalizing divisor (bottom)(v) first */ 
+ /* high bit of divisor (v) must be 1 - compute number of leading 0s */
+ /* AIV 06/25/04 - only nomalize if not multiple of WBITS */
+ ubits = ubits_(vblen);
+ normdist = (ubits == 0) ? 0 : WBITS - ubits;
+
+ /* since must shift, need copy of if stacked v (divisor) can be changed */
+ /* could just shift */
+ push_xstk_(xsp, vwlen*WBITS/2);
+ vwp = xsp->ap;
+ memcpy(vwp, v, vwlen*WRDBYTES);
+
+ if (normdist != 0) bitmwlshift(vwp, normdist, vwlen);
+
+ /* normalize dividend next */
+ /* need 1 extra 0 digit in work numerator (u) so shift fits */
+ push_xstk_(xsp, (uwlen + 1)*WBITS/2);
+ uwp = xsp->ap;
+ memcpy(uwp, u, uwlen*WRDBYTES); 
+
+ uwp[uwlen] = 0;
+ if (normdist != 0) bitmwlshift(uwp, normdist, uwlen + 1);
+
+ /* use basic algorithm of mpexpr long div routine */
+ /* notice length of dividend (u) is plus 1 because divisor (v) gets */
+ /* normalized probably causing shift of part of u into 1 higher word32 */
+ mpexpr_zdiv(quot, rem, uwp, uwlen + 1, vwp, vwlen);
+ if (normdist != 0) bitmwrshift(rem, normdist, vwlen);
+ __pop_xstk();
+ __pop_xstk();
+}
+
+
+/*
+ * EXTENDED PRECISION DIVISION ROUTINE 
+ */
+
+#define BASE 0x100000000ULL
+#define BASE1 BASE - 1ULL
+
+/*
+ * Divide ztmp1/ztmp2 and set quotient in quot and remainder in rem
+ *
+ * user must allocate large enough area for quot and rem and they must
+ * be zeroed before call 
+ * 
+ * know ztmp1 and zmp2 normalized copies of u and v (u/v) so this can
+ * overright values
+ *
+ * routine is taken exactly from mpexpr except changed to verilog number
+ * representation and special cases handled by ldiv/lmod removed
+ *
+ * "digit" here is word32 32 bit word32, lengths are no. of words 
+ * uwp is top and vwp is bottom
+ *
+ * changed endian word64/word32 access to follow Cver conventions and set
+ * 64 long long 32 long that is only supported by modern c compilers
+ * know both zu and v normalized and dividend > 0 when called
+ * 
+ * uwp and vwp are copies of u and v and both normalized before calling zdiv
+ * 
+ * Comments in mpexpr:
+ *   This algorithm is taken from
+ *   Knuth, The Art of Computer Programming, vol 2: Seminumerical Algorithms.
+ *   Slight modifications were made to speed this mess up.
+ *
+ */
+static void mpexpr_zdiv(word32 *quot, word32 *rem, word32 *ztmp1, int32 ztmp1_len,
+ word32 *ztmp2, int32 ztmp2_len)  
+{
+ register word32 *q, *pp;
+ int32 quot_len, y, ztmp3_len, k;
+ word64 x;
+ word32 *ztmp3, h2, v2;
+ /* pair of word32 values to make word64 value - uses endianess */
+ w64_u pair;
+ struct xstk_t *ztmp3_xsp;
+
+ /* know u/v both normalized and remainder only case remove before here */
+ quot_len = ztmp1_len - ztmp2_len;
+ q = &(quot[quot_len]);
+ y = ztmp1_len - 1;
+ h2 = ztmp2[ztmp2_len - 1];
+ v2 = 0;
+ k = ztmp1_len - ztmp2_len;
+
+ /* need ztmp3 of width v_len (denominator size) + 1 & b part for dbg print */
+ /* LOOKATME - except for debugging this does not need b part */
+ push_xstk_(ztmp3_xsp, (ztmp2_len + 1)*WBITS);
+ ztmp3 = ztmp3_xsp->ap;
+ ztmp3_len = ztmp2_len + 1;
+ /* zero b part for debugging */
+ memset(&(ztmp3[ztmp3_len]), 0, ztmp3_len*WRDBYTES);
+ if (ztmp2_len >= 2) v2 = ztmp2[ztmp2_len - 2];
+
+ /* y starts at trimmed len of u - 1 in words and is deced each time thru */
+ /* k is how many "digits" more in numerator than denominator */
+ for (; k--; --y)
+  {
+   pp = &(ztmp1[y - 1]);
+   pair.w_u.low = pp[0];
+   pair.w_u.high = pp[1];
+
+   if (ztmp1[y] == h2) x = BASE1; else x = pair.w64v/(word64) h2;
+   if (x != 0ULL)
+    {
+     /* this computes one word32 ("digit") x */
+     while ((pair.w64v - x*h2 < BASE) && (y > 1)
+      && (v2*x > (pair.w64v - x*h2) * BASE + ztmp1[y-2]))
+      {
+       x--;
+      }
+     /* multiply high digit by numerator in preparation for subtract */
+     /* carry may go into one digit wider than denominator w2tmp size */
+     /* notice reversed order from mpexpr zdiv so result in 1st arg */
+     dmul(ztmp3, ztmp3_len, ztmp2, ztmp2_len, x);
+
+     /* DBG remove ---
+     if (__debug_flg)
+      {
+       __dbg_msg("** zdiv: x = %ld\n", x);
+       __dbg_msg("         ztmp1 = %s\n", __regab_tostr(__xs, ztmp1,
+        &(ztmp1[ztmp1_len]), ztmp1_len*WBITS, BHEX, FALSE));
+       __dbg_msg("         ztmp2 = %s\n", __regab_tostr(__xs, ztmp2,
+        &(ztmp2[ztmp2_len]), ztmp2_len*WBITS, BHEX, FALSE));
+       memset(&ztmp3[ztmp3_len], 0, ztmp3_len*WRDBYTES);
+       __dbg_msg("         ztmp3 = %s\n", __regab_tostr(__xs, ztmp3,
+        &(ztmp3[ztmp3_len]), ztmp3_len*WBITS, BHEX, FALSE));
+      }
+     --- */
+
+     /* subtract new "high" digit ("word") from numerator */
+     if (dsub(ztmp1, ztmp1_len, ztmp3, ztmp3_len, y, ztmp2_len))
+      {
+       --x;
+       /* DBG remove --
+       if (__debug_flg) __dbg_msg("** zdiv: adding back\n");
+       -- */  
+       dadd(ztmp1, ztmp2, y, ztmp2_len);
+      }
+    }
+   ztmp1_len = ztrim(ztmp1, ztmp1_len);
+   /* each time thru set one current high digit of quotient to value */
+   *--q = (word32) x;
+  }
+
+ /* remainder is value now in ztmp1, caller unnormalizes rem */
+ memcpy(rem, ztmp1, ztmp1_len*WRDBYTES);
+
+ /* quot has right value - no need to unnormalize */
+ __pop_xstk();
+}
+
+/*
+ * 32 bit "digit" trim - unlike mpexpr ztrim returns trimmed width 
+ */
+static int32 ztrim(word32 *zp, int32 z_len)
+{
+ register word32 *h;
+ register int32 len;
+ 
+ h = &(zp[z_len - 1]);
+ len = z_len;
+ while (*h == 0 && len > 1) { --h; --len; }
+ return (len);
+}
+
+/*
+ * internal add in place z1 += z2
+ *
+ * what are y and n
+ * need len to save extra work for high 0s
+ */
+static void dadd(word32 *z1p, word32 *z2p, int32 y, int32 n)
+{
+ word32 *s1p, *s2p;
+ word32 carry;
+ word64 sum;
+
+ s1p = &(z1p[y - n]);
+ s2p = z2p;
+ carry = 0;
+ while (n--)
+  {
+   sum = ((word64) *s1p) + ((word64) *s2p) + ((word64) carry);
+   carry = 0;
+   if (sum >= BASE) { sum -= BASE; carry = 1; }
+   *s1p = (word32) sum;
+   ++s1p;
+   ++s2p;
+  }
+ sum = ((word64) *s1p) + ((word64) carry);
+ *s1p = (word32) sum;
+}
+
+/*
+ * subtract z2p from z1p with result in place into z1p for divide
+ * returns T result goes negative.
+ *
+ * LOOKATME - what are y and n?
+ * "digits" unsigned
+ */
+static int32 dsub(word32 *z1p, int32 z1_len, word32 *z2p, int32 z2_len, int32 y, int32 n)
+{
+ word32 *s1p, *s2p, *s3p;
+ word64 i1;
+ int32 neg;
+
+ neg = FALSE;
+ s1p = &(z1p[y - n]);
+ s2p = z2p;
+ if (++n > z2_len) n = z2_len;
+
+ while (n--)
+  {
+   i1 = (word64) *s1p;
+   if (i1 < (word64) *s2p)
+    {
+     s3p = &(s1p[1]);
+     while (s3p < &(z1p[z1_len]) && !(*s3p))
+      { *s3p = (word32) BASE1; ++s3p; }
+
+     if (s3p >= &(z1p[z1_len])) neg = TRUE; else --(s3p[0]);
+     i1 += BASE;
+    }
+  *s1p = (word32) (i1 - (word64) *s2p);
+  ++s1p;
+  ++s2p;
+ }
+ return neg;
+}
+
+/*
+ * multiply into tmp dest zp times one word32 ("digit") in mul  
+ *
+ * mpexpr comments:
+ * Multiply a number by a single 'digit'.
+ * This is meant to be used only by the divide routine, and so the
+ * destination area must already be allocated and be large enough.
+ */
+static void dmul(word32 *destp, int32 dest_len, word32 *z1p, int32 z1_len, word64 mul)
+{
+ register word32 *zp, *dp;
+ w64_u pair;
+ word64 carry;
+ long len;
+
+ memset(destp, 0, dest_len*WRDBYTES);
+ /* multiple by 0 result is 0 */
+ if (mul == 0ULL) return;
+
+ len = z1_len;
+ zp = &(z1p[len - 1]);
+ dp = destp;
+ /* trim each time to save work */
+ while ((*zp == 0) && (len > 1)) { len--; zp--; }
+ zp = z1p;
+
+ carry = 0;
+ /* compute 4 word("digits") sections with unrolled loop */ 
+ while (len >= 4) {
+  len -= 4;
+  pair.w64v = (mul * ((word64) *zp++)) + carry;
+  *dp++ = pair.w_u.low;
+  pair.w64v = (mul * ((word64) *zp++)) + ((word64) pair.w_u.high);
+  *dp++ = pair.w_u.low;
+  pair.w64v = (mul * ((word64) *zp++)) + ((word64) pair.w_u.high);
+  *dp++ = pair.w_u.low;
+  pair.w64v = (mul * ((word64) *zp++)) + ((word64) pair.w_u.high);
+  *dp++ = pair.w_u.low;
+  carry = pair.w_u.high;
+ }
+ /* copmute final ending left over digits ("words") */ 
+ while (--len >= 0) {
+  pair.w64v = (mul * ((word64) *zp++)) + carry;
+  *dp++ = pair.w_u.low;
+  carry = pair.w_u.high;
+ }
+ /* LOOKATME - how make sure enough room in dest if there is a carry? */
+ if (carry != 0) *dp = (word32) carry;
+}
+
+/*
+ * compare only a parts - know wider than WBITS bits
+ */
+static int32 ldiv_cmp(register word32 *u, register word32 *v, int32 wlen) 
+{
+ register int32 i;
+
+ /* know unused parts of high words will both be zero */
+ for (i = wlen - 1; i >= 0; i--)
+  {
+   if (u[i] < v[i]) return(-1);
+   else if (u[i] > v[i]) return(1);
+  }
+ return(0);
+}
+
+/*
+ * divide a number by 1 half word32 (digit based 16 bits)
+ * notice all values must be separate addresses
+ *
+ * also quot and rem assumed to be initialized to 0 before passing to here
+ * also this works on words not half words
+ */
+extern void __by16_ldivmod(word32 *quot, word32 *r0, word32 *u, word32 v0, int32 ublen)
+{
+ register int32 i;
+ int32 uwlen;
+ word32 r, newn;
+
+ uwlen = wlen_(ublen); 
+ r = 0L;
+ for (i = uwlen - 1; i >= 0; i--)
+  {
+   newn = r*SHORTBASE + (u[i] >> (WBITS/2));
+   quot[i] = (newn / v0) << (WBITS/2);
+   r = newn % v0;
+   /* notice since r < d0, newn / v0 will aways fit in half word32 */
+   newn = r*SHORTBASE + (u[i] & ALL1HW); 
+   quot[i] |= (newn / v0);
+   r = newn % v0;
+  }
+ *r0 = r;
+}
diff --git a/src/v_ex3.c b/src/v_ex3.c
new file mode 100644
index 0000000..2f1271a
--- /dev/null
+++ b/src/v_ex3.c
@@ -0,0 +1,6670 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * run time execution routines - lhs stores and gate evalution routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void do_qc_assign(struct st_t *, struct expr_t *, int32,
+ struct dceauxlstlst_t *);
+static void do_qc_deassign(struct expr_t *);
+static void do_qc_regforce(struct st_t *, struct expr_t *, int32,
+ struct dceauxlstlst_t *);
+static void do_qc_regrelease(struct expr_t *);
+static void do_qc_wireforce(struct st_t *, struct expr_t *, int32,
+ struct dceauxlstlst_t *);
+static void do_1bit_wireforce(struct st_t *, struct net_t *, int32, int32,
+ int32, struct itree_t *itp, struct dceauxlst_t *);
+static void do_qc_wirerelease(struct expr_t *);
+static void assign_alllhs_bits(struct expr_t *, struct xstk_t *);
+static void do_qc2_regstore(struct net_t *, struct qcval_t *,
+ struct xstk_t *);
+static void do_qc2_wirestore(struct net_t *, struct qcval_t *,
+ struct xstk_t *);
+static void trace_conta_assign(struct expr_t *, word32 *, word32 *);
+static void sched_conta_assign(struct expr_t *, register word32 *,
+ register word32 *);
+static void evtr_wdel_schd_1wirebit(register struct net_t *, register int32,
+ register word32, register word32, int32);
+static void schd_1pthwirebit(register struct net_t *, register int32,
+ register word32, register word32);
+static void evtr_schd_1pthwirebit(register struct net_t *, register int32,
+ register word32, register word32);
+static void prt_dbgpthtrmsg(struct spcpth_t *, word64);
+static void get_impth_del(word64 *, struct net_t *, int32, struct mipd_t *);
+static void prt_dbgimpthtrmsg(struct net_t *, int32, word64, word64);
+static void evtr_sched_mipd_nchg(struct net_t *, int32, struct mipd_t *);
+static void cancel_1mipdev(struct tev_t *);
+static i_tev_ndx reschedule_1mipd(struct net_t *, int32, i_tev_ndx,
+ word64, word64);
+static void st_vecval(word32 *, int32, register word32 *, register word32 *);
+static void chg_st_vecval(register word32 *, int32, register word32 *,
+ register word32 *);
+static void schedassign_to_bit(struct net_t *, struct expr_t *,
+ struct expr_t *, register word32 *, register word32 *);
+static void get_unknown_biti_val(struct net_t *, word32 *, word32 *, word32 *,
+ word32 *, word32);
+static void setx_ifnotval(word32 *, word32 *, word32);
+static void chg_lhsbsel(register word32 *, int32, word32);
+static int32 forced_assign_to_psel(struct expr_t *, int32, int32,
+ struct net_t *, register word32 *, register word32 *);
+static void schedassign_to_psel(struct expr_t *, register word32 *,
+ register word32 *);
+static void ins_walign(register word32 *, register word32 *, register int32);
+static void cp_dofs_wval(register word32 *, register word32 *, int32, int32);
+static void chg_st_unpckpsel(word32 *, int32, int32, int32, register word32 *,
+ register word32 *);
+static void chg_ins_wval(register word32 *, register int32, register word32 *,
+ register int32);
+static int32 chg_ofs_cmp(register word32 *, register word32 *, int32, int32);
+static void eval_wide_gate(struct gate_t *, struct xstk_t *);
+static void chg_st_psel(struct net_t *, int32, int32, register word32 *,
+ register word32 *);
+
+/* extern prototypes (maybe defined in this module) */
+extern void __exec2_proc_assign(struct expr_t *, register word32 *,
+ register word32 *);
+extern void __exec2_proc_concat_assign(struct expr_t *, word32 *, word32 *);
+extern void __exec_qc_assign(struct st_t *, int32);
+extern void __exec_qc_deassign(struct st_t *, int32);
+extern void __exec_qc_wireforce(struct st_t *);
+extern void __exec_qc_wirerelease(struct st_t *);
+extern void __assign_qcaf(struct dcevnt_t *);
+extern void __do_qc_store(struct net_t *, struct qcval_t *, int32);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern struct itree_t *__find_unrt_targitp(struct gref_t *,
+ register struct itree_t *, int32);
+extern struct inst_t *__get_gref_giarr_ip(struct gref_t *, int32,
+ struct itree_t *); 
+extern int32 __match_push_targ_to_ref(word32, struct gref_t *);
+extern void __exec_ca_concat(struct expr_t *, register word32 *,
+ register word32 *, int32);
+extern void __stren_exec_ca_concat(struct expr_t *, byte *, int32);
+extern void __exec_conta_assign(struct expr_t *, register word32 *,
+ register word32 *, int32);
+extern int32 __correct_forced_newwireval(struct net_t *, word32 *, word32 *);
+extern void __bld_forcedbits_mask(word32 *, struct net_t *);
+extern void __pth_schd_allofwire(struct net_t *, register word32 *,
+ register word32 *, int32);
+extern void __wdel_schd_allofwire(struct net_t *, register word32 *,
+ register word32 *, int32);
+extern void __pth_stren_schd_allofwire(struct net_t *, register byte *, int32);
+extern void __wdel_schd_1wirebit(register struct net_t *, register int32,
+ register word32, register word32, int32);
+extern void __wdel_stren_schd_allofwire(struct net_t *, register byte *,
+ int32);
+extern void __emit_path_distinform(struct net_t *, struct pthdst_t *,
+ word64 *);
+extern void __emit_path_samewarn(struct net_t *, int32, struct tev_t *,
+ word64 *, char *, word32);
+extern void __emit_path_pulsewarn(struct pthdst_t *, struct tev_t *,
+ word64 *, word64 *, char *, word32);
+extern struct pthdst_t *__get_path_del(struct rngdwir_t *, int32, word64 *);
+extern void __schedule_1wev(struct net_t *, int32, int32, word64, word64,
+ word32, i_tev_ndx *, int32);
+extern void __reschedule_1wev(i_tev_ndx, word32, word64, word64, i_tev_ndx *);
+extern void __cancel_1wev(struct tev_t *);
+extern void __st_val(struct net_t *, register word32 *, register word32 *);
+extern void __st_perinst_val(union pck_u, int32, register word32 *,
+ register word32 *);
+extern void __chg_st_val(register struct net_t *, word32 *, word32 *);
+extern void __assign_to_bit(struct net_t *, struct expr_t *, struct expr_t *,
+ register word32 *, register word32 *);
+extern void __assign_to_arr(struct net_t *, struct expr_t *, struct expr_t *,
+ register word32 *, register word32 *);
+extern int32 __forced_inhibit_bitassign(struct net_t *, struct expr_t *,
+ struct expr_t *);
+extern void __stren_schedorassign_unknown_bit(struct net_t *, word32, int32);
+extern void __schedorassign_unknown_bit(struct net_t *np, word32 av,
+ word32 bv, int32 schd_wire);
+extern void __lhsbsel(register word32 *, register int32, word32);
+extern void __chg_st_bit(struct net_t *, int32, register word32,
+ register word32);
+extern void __st_bit(struct net_t *, int32, register word32, register word32);
+extern void __st_arr_val(union pck_u, int32, int32, int32, register word32 *,
+ register word32 *);
+extern void __chg_st_arr_val(union pck_u, int32, int32, int32,
+ register word32 *, register word32 *);
+extern void __assign_to_psel(struct expr_t *, int32, int32, struct net_t *,
+ register word32 *, register word32 *);
+extern void __lhspsel(register word32 *, register int32, register word32 *,
+ register int32);
+extern void __cp_sofs_wval(register word32 *, register word32 *,
+ register int32, register int32);
+extern void __chg_lhspsel(register word32 *, register int32,
+ register word32 *, register int32);
+extern void __sizchgxs(register struct xstk_t *, int32);
+extern void __narrow_to1bit(register struct xstk_t *);
+extern void __narrow_to1wrd(register struct xstk_t *);
+extern void __fix_widened_tozs(struct xstk_t *, int32);
+extern void __fix_widened_toxs(register struct xstk_t *, int32);
+extern void __strenwiden_sizchg(struct xstk_t *, int32);
+extern int32 __eval_logic_gate(struct gate_t *, word32, int32 *);
+extern void __ld_gate_wide_val(word32 *, word32 *, word32 *, int32);
+extern int32 __eval_bufif_gate(register struct gate_t *, word32, int32 *);
+extern void __eval_nmos_gate(register word32);
+extern void __eval_rnmos_gate(register word32);
+extern void __eval_pmos_gate(register word32);
+extern void __eval_rpmos_gate(register word32);
+extern void __eval_cmos_gate(struct gate_t *);
+extern char *__to_gassign_str(char *, struct expr_t *);
+extern int32 __eval_udp(register struct gate_t *, word32, int32 *, int32);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __rhspsel(register word32 *, register word32 *, register int32,
+ register int32);
+extern char *__to_idnam(struct expr_t *);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern char *__to_timstr(char *, word64 *);
+extern char *__my_malloc(int32);
+extern void __my_free(char *, int32);
+extern void __find_call_force_cbs(struct net_t *, int32);
+extern void __cb_all_rfs(struct net_t *, int32, int32);
+extern void __find_call_rel_cbs(struct net_t *, int32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern int32 __get_const_bselndx(register struct expr_t *);
+extern void __assign_1mdrwire(register struct net_t *);
+extern struct xstk_t *__eval_assign_rhsexpr(register struct expr_t *,
+ register struct expr_t *);
+extern char *__xregab_tostr(char *, word32 *, word32 *, int32,
+ struct expr_t *);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern void __st_standval(register byte *, register struct xstk_t *, byte);
+extern char *__st_regab_tostr(char *, byte *, int32);
+extern int32 __vval_is1(register word32 *, int32);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern void __ld_wire_val(register word32 *, register word32 *,
+ struct net_t *);
+extern void __ld_bit(register word32 *, register word32 *,
+ register struct net_t *, int32);
+extern void __add_nchglst_el(register struct net_t *);
+extern void __add_select_nchglst_el(register struct net_t *, register int32,
+ register int32);
+extern void __wakeup_delay_ctrls(register struct net_t *, register int32,
+ register int32);
+extern void __get_del(register word64 *, register union del_u, word32);
+extern char *__to_evtrwnam(char *, struct net_t *, int32, int32,
+ struct itree_t *);
+extern char *__to_vnam(char *, word32, word32);
+extern int32 __em_suppr(int32);
+extern void __insert_event(register i_tev_ndx);
+extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
+extern int32 __get_arrwide(struct net_t *);
+extern void __ld_psel(register word32 *, register word32 *,
+ register struct net_t *, int32, int32);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern word32 __wrd_redxor(word32);
+extern void __lunredand(int32 *, int32 *, word32 *, word32 *, int32);
+extern void __lunredor(int32 *, int32 *, word32 *, word32 *, int32);
+extern void __lunredxor(int32 *, int32 *, word32 *, word32 *, int32);
+extern char *__gstate_tostr(char *, struct gate_t *, int32);
+extern word32 __comb_1bitsts(word32, register word32, register word32);
+extern struct xstk_t *__ndst_eval_xpr(struct expr_t *);
+extern void __add_dmpv_chglst_el(struct net_t *);
+extern void __qc_tran_wireforce(struct net_t *, int32, int32, int32,
+ struct itree_t *, struct st_t *);
+extern void __qc_tran_wirerelease(struct net_t *, int32, int32,
+ struct itree_t *, struct expr_t *lhsx);
+extern void __eval_tran_1bit(register struct net_t *, register int32);
+extern char *__to_ptnam(char *, word32);
+extern int32 __eval_1wide_gate(struct gate_t *, int32);
+extern void __ins_wval(register word32 *, register int32, register word32 *,
+ int32);
+extern void __rem_stren(word32 *ap, word32 *bp, byte *, int32);
+extern void __get_qc_wirrng(struct expr_t *, struct net_t **, int32 *,
+ int32 *, struct itree_t **);
+extern void __dcelst_on(struct dceauxlst_t *);
+extern void __dcelst_off(struct dceauxlst_t *);
+
+extern void __tr_msg(char *, ...);
+extern void __gfwarn(int32, word32, int32, char *, ...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __pv_warn(int32, char *,...);
+extern void __gfinform(int32, word32, int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+
+extern word32 __masktab[];
+
+/*
+ * LHS ASSIGN ROUTINES
+ */
+
+/*
+ * PROCEDURAL ASSIGNMENT ROUTINES
+ */
+
+/*
+ * immediate procedural assign from stacked value to lhs expr. xlhs
+ * if assign changes, sets lhs change to T
+ * know rhs side width same as lhs destination
+ *
+ * notice every path through here must add the net change element - called
+ * this routine must be only possible way lhs procedural reg can be changed
+ */
+extern void __exec2_proc_assign(struct expr_t *xlhs, register word32 *ap,
+ register word32 *bp)
+{
+ register struct net_t *np;
+ int32 nd_itpop, ri1, ri2;
+ struct expr_t *idndp, *ndx1;
+ struct gref_t *grp;
+
+ nd_itpop = FALSE;
+ switch ((byte) xlhs->optyp) {
+  case GLBREF:
+   grp = xlhs->ru.grp;    
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+   /* FALLTHRU */
+  case ID:
+   np = xlhs->lu.sy->el.enp;
+   if (np->frc_assgn_allocated && reg_fr_inhibit_(np)) goto chk_itpop;
+
+   /* this add the changed wire to nchglst if needed */
+   /* SJM 03/15/01 - change to fields in net record */
+   if (np->nchg_nd_chgstore) __chg_st_val(np, ap, bp);
+   else __st_val(np, ap, bp);
+
+chk_itpop:
+   if (nd_itpop) __pop_itstk();
+   break;
+  case LSB:
+   /* for now first determine if array index */
+   idndp = xlhs->lu.x;
+   ndx1 = xlhs->ru.x;
+   np = idndp->lu.sy->el.enp;
+   /* notice can never assign or force arrays */
+   if (np->n_isarr) __assign_to_arr(np, idndp, ndx1, ap, bp);
+   else
+    {
+     if (np->frc_assgn_allocated)
+      {
+       if (idndp->optyp == GLBREF)
+        {
+         grp = idndp->ru.grp;
+         __xmrpush_refgrp_to_targ(grp);
+         nd_itpop = TRUE;
+        }
+       if (reg_fr_inhibit_(np)) goto chk_itpop;
+       /* assign to bit handles own grep itree stack pushing */ 
+       if (nd_itpop) __pop_itstk();
+      }
+     __assign_to_bit(np, idndp, ndx1, ap, bp);
+    }
+   break;
+  case PARTSEL:
+   idndp = xlhs->lu.x;
+   np = idndp->lu.sy->el.enp;
+   if (np->frc_assgn_allocated)
+    {
+     if (idndp->optyp == GLBREF)
+      { grp = idndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+     /* do not assign if assign or force pending on inst. of wire */
+     if (reg_fr_inhibit_(np)) goto chk_itpop;
+     /* assign to psel handles own grep itree stack pushing */ 
+     if (nd_itpop) __pop_itstk();
+    }
+   ri1 = (int32) __contab[xlhs->ru.x->lu.x->ru.xvi];
+   ri2 = (int32) __contab[xlhs->ru.x->ru.x->ru.xvi];
+   __assign_to_psel(idndp, ri1, ri2, np, ap, bp);
+   break;
+  case LCB:
+   /* know evaluated rhs (maybe concatenate) in top of stack reg. */
+   __exec2_proc_concat_assign(xlhs, ap, bp);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * execute an assignment or schedule to a concatentate (know non strength)
+ * rhs value on stack apportioned into parts of concatenate
+ * know xsp width same as lhs destination
+ * caller must pop stack on return
+ */
+extern void __exec2_proc_concat_assign(struct expr_t *xlhs, word32 *ap, word32 *bp)
+{
+ register struct expr_t *catndp, *catlhsx;
+ register int32 catxlen;
+ int32 bi1;
+ struct xstk_t *catxsp;
+
+ /* do lhs concatenate assigns from left to right */
+ for (catndp = xlhs->ru.x; catndp != NULL; catndp = catndp->ru.x)
+  {
+   catlhsx = catndp->lu.x;
+   catxlen = catlhsx->szu.xclen;
+   /* bi1 is low bit of rhs part select */
+   /* length for catndp is distance from high bit of section to right end */ 
+   bi1 = catndp->szu.xclen - catxlen;
+
+   /* --- DBG remove 
+   if (__debug_flg)
+    __dbg_msg(
+     "+++lhs proc: total cat wid=%u, low index=%d, wid=%u, remaining wid=%u\n",
+     xlhs->szu.xclen, bi1, catxlen, catndp->szu.xclen);
+  --- */
+
+   /* select current pos. right width piece from rhs and put on tos reg */
+   /* notice assignment always same width */
+   push_xstk_(catxsp, catxlen);
+   if (catxlen == 1)
+    { catxsp->ap[0] = rhsbsel_(ap, bi1); catxsp->bp[0] = rhsbsel_(bp, bi1); }
+   else
+    {
+     __rhspsel(catxsp->ap, ap, bi1, catxlen);
+     __rhspsel(catxsp->bp, bp, bi1, catxlen);
+    }
+
+   /* know reals illegal in concatenates (rhs/lhs components of) */
+   /* also nested lhs concatenates illegal - will never appear */
+   /* notice this is part of immediate assign must not inc assign counter */
+   /* and know no nested lhs concatenates */ 
+   __exec2_proc_assign(catlhsx, catxsp->ap, catxsp->bp);
+   __pop_xstk();
+  }
+}
+
+/*
+ * QUASI CONTINUOUS REG ASSIGN/DEASSIGN/FORCE/RELEASE ROUTINES 
+ */
+
+/*
+ * exec a quasi-continuous assign or force of register (same as qc assign)
+ * this is for both reg force and reg assign
+ */
+extern void __exec_qc_assign(struct st_t *stp, int32 is_force)
+{
+ register struct expr_t *catndp;
+ register struct dceauxlstlst_t *dcllp;
+ int32 catxlen, bi1; 
+ struct expr_t *lhsx, *catlhsx;
+
+ /* first evaluate rhs */
+ lhsx = stp->st.sqca->qclhsx;
+ /* only possibilities are concat and ID - list of ptrs to peri/bit lists */
+ dcllp = stp->st.sqca->rhs_qcdlstlst;
+ if (lhsx->optyp != LCB)
+  {
+   if (is_force) do_qc_regforce(stp, lhsx, -1, dcllp);
+   else do_qc_assign(stp, lhsx, -1, dcllp);
+  }
+ else
+  {
+   /* concatenate case know lhs full wire - tricky extractions of rhs */
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x,
+    dcllp = dcllp->dcelstlstnxt)
+    {
+     catlhsx = catndp->lu.x;
+     catxlen = catlhsx->szu.xclen;
+     bi1 = catndp->szu.xclen - catxlen;
+     if (is_force) do_qc_regforce(stp, catlhsx, bi1, dcllp);
+     else do_qc_assign(stp, catlhsx, bi1, dcllp);
+    }
+  }
+}
+
+/*
+ * execute a quasi-continuous deassign
+ * inverse of assign
+ */
+extern void __exec_qc_deassign(struct st_t *stp, int32 is_force)
+{
+ register struct expr_t *catndp;
+ struct expr_t *lhsx, *catlhsx;
+
+ /* SJM 07/19/02 - was wrongly accessing qconta not qcontdea record */
+ lhsx = stp->st.sqcdea.qcdalhs;
+ /* only possibilities are concat and ID */
+ if (lhsx->optyp != LCB)
+  {
+   if (is_force) do_qc_regrelease(lhsx);
+   else do_qc_deassign(lhsx);
+  }
+ else
+  {
+   /* concatenate case know lhs full wire - tricky extractions of rhs */
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    {
+     catlhsx = catndp->lu.x;
+     if (is_force) do_qc_regrelease(catlhsx);
+     else do_qc_deassign(catlhsx);
+    }
+  }
+}
+
+/*
+ * exec quasi continuous assign for one expr in one inst.
+ *
+ * know lhs always entire register - no assign for wires - lhs can be xmr 
+ *
+ * if active force do nothing but save assign rhs expr. so if force released
+ * assign expr. evaluated and activated
+ *
+ * SJM 06/23/02 - new qcaf algorithm build qcaf lists during prep and moves
+ * to and from stmt sqca fields and turns on/off when needed
+ */
+static void do_qc_assign(struct st_t *qcastp, struct expr_t *lhsx, int32 rhsbi,
+ struct dceauxlstlst_t *dcllp)
+{
+ int32 nd_itpop, stmt_inum;
+ struct net_t *np;
+ struct gref_t *grp;
+ struct qcval_t *frc_qcp, *assgn_qcp; 
+
+ /* assign to lhs itree loc. */
+ nd_itpop = FALSE;
+ /* SJM 05/23/03 - need to access stmt info from original inum if XMR */
+ stmt_inum = __inum;
+ if (lhsx->optyp == GLBREF)
+  { grp = lhsx->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ else if (lhsx->optyp != ID) __case_terr(__FILE__, __LINE__);
+ np = lhsx->lu.sy->el.enp;
+
+ /* for reg var 2 records always allocated, first is force and 2nd assign */
+ frc_qcp = &(np->nu2.qcval[2*__inum]);
+ assgn_qcp = &(np->nu2.qcval[2*__inum + 1]);
+ /* if active force of wire just fill assign qcval so when force removed */
+ /* assign becomes active - but do not make qc assign active */
+ if (frc_qcp->qc_active)
+  {
+   /* notice this can replace other over-ridden */
+   assgn_qcp->qc_overridden = TRUE;
+   assgn_qcp->qcstp = qcastp;
+   assgn_qcp->qcrhsbi = rhsbi; 
+   assgn_qcp->qclhsbi = -1; 
+   /* need lhs target inst. loc including non xmr same for change assign */
+   assgn_qcp->lhsitp = __inst_ptr;
+   /* assign group of dces (usually 1) - if lhs concat this lhs expr's one */
+   /* but don't turn on yet */
+   /* SJM 05/23/03 - dcllp is linked off stmt and has stmt instances */
+   assgn_qcp->qcdcep = dcllp->dcelsttab[stmt_inum];
+
+   if (nd_itpop) __pop_itstk();
+
+   if (__debug_flg && __ev_tracing)
+    {
+     char s1[RECLEN];
+
+     /* context for trace message is stmt not possible xmr */
+     __tr_msg(
+      ":: quasi-continuous assign to reg %s at %s in %s now %s - no effect active force\n",
+      __to_idnam(lhsx), __bld_lineloc(__xs, (word32) __sfnam_ind, __slin_cnt),
+      __msg2_blditree(__xs2, __inst_ptr), __to_timstr(s1, &__simtime));
+    }
+   return;
+  }
+ /* if active assign, deactivate before setting new - know fields replaced */
+ if (assgn_qcp->qc_active)
+  {
+   assgn_qcp->qc_active = FALSE;
+   /* turn on dces after doing store if rhs dces */
+   /* SJM 08/18/02 - bug - this was turning on but must turn off */
+   if (assgn_qcp->qcdcep != NULL) __dcelst_off(assgn_qcp->qcdcep);
+  }
+
+ /* SJM 07/19/02 - was not making assign active */
+ assgn_qcp->qc_active = TRUE;
+ /* DBG remove - can't be over-ridden by force if get here */
+ if (assgn_qcp->qc_overridden) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ /* but still save in case reg var force removed */
+ assgn_qcp->qcstp = qcastp;
+ assgn_qcp->qcrhsbi = rhsbi; 
+ assgn_qcp->qclhsbi = -1;
+ /* do store and build dces in ref. itree loc. */ 
+ assgn_qcp->lhsitp = __inst_ptr;
+ /* assign group of dces (usually 1) - if lhs concat this lhs expr's one */
+ assgn_qcp->qcdcep = dcllp->dcelsttab[stmt_inum];
+
+ if (nd_itpop) __pop_itstk();
+
+ if (__debug_flg && __ev_tracing)
+  {
+   char s1[RECLEN];
+
+   __tr_msg(":: quasi-continuous assign to reg %s at %s in %s now %s\n",
+    __to_idnam(lhsx), __bld_lineloc(__xs, (word32) __sfnam_ind, __slin_cnt),
+    __msg2_blditree(__xs2, __inst_ptr), __to_timstr(s1, &__simtime));
+  }
+
+ /* these routines need ref. itree loc - they set right context for xmr */
+ __do_qc_store(np, assgn_qcp, TRUE);
+
+ /* turn on dces after doing store if rhs dces */
+ if (assgn_qcp->qcdcep != NULL) __dcelst_on(assgn_qcp->qcdcep);
+
+ /* FIXME ??? - assign callbacks go here */
+}
+
+/*
+ * do the quasi continuous deassign for one lhs expr.
+ *
+ * know lhs always entire register and cannot be wire
+ * notice lhs here can be xmr
+ * sematics is deassign leaves val until next assgn which now happens execs
+ * value of wire not changed here  
+ * for xmr (reg only possible), must exec in target itree loc.
+ */
+static void do_qc_deassign(struct expr_t *lhsx)
+{
+ int32 nd_itpop;
+ struct net_t *np;
+ struct gref_t *grp;
+ struct qcval_t *frc_qcp, *assgn_qcp;
+ char s1[RECLEN];
+
+ strcpy(s1, "");
+ /* must work in itree loc. of lhs if xmr */
+ nd_itpop = FALSE;
+ if (lhsx->optyp == GLBREF)
+  { grp = lhsx->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ else if (lhsx->optyp != ID) __case_terr(__FILE__, __LINE__);
+ np = lhsx->lu.sy->el.enp;
+ 
+ /* for reg var 2 records always allocated, first is force and 2nd assign */
+ frc_qcp = &(np->nu2.qcval[2*__inum]);
+ assgn_qcp = &(np->nu2.qcval[2*__inum + 1]);
+ if (!assgn_qcp->qc_active && !assgn_qcp->qc_overridden)
+  {
+   __sgfinform(462,
+    "attempted deassign of reg %s in instance %s failed - not assigned",
+    __to_idnam(lhsx), __msg2_blditree(__xs, __inst_ptr));
+   goto done;
+  }
+ assgn_qcp->qc_active = FALSE; 
+ /* turn off dces but do not empty qcval rec - will get refilled if needed */
+ /* if over-ridden were not turned so do not need to turn off */
+ if (!assgn_qcp->qc_overridden)
+  {
+   if (assgn_qcp->qcdcep != NULL) __dcelst_off(assgn_qcp->qcdcep);
+  }
+ assgn_qcp->qcdcep = NULL; 
+ assgn_qcp->qc_overridden = FALSE;
+ __assign_active = FALSE; 
+ /* LOOKATME - extra work to set force flag only used for tracing */
+ if (frc_qcp->qc_active)
+  {
+   /* dce list can be empty if forced to constant */
+   __force_active = TRUE;
+   strcpy(s1, " force active");
+  }
+ if (__debug_flg && __ev_tracing)
+  {
+   char s2[RECLEN];
+
+   /* messages needs itree context of stmt */
+   if (nd_itpop) __pop_itstk();
+
+   __tr_msg(":: quasi-continuous deassign of reg %s%s at %s in %s now %s\n",
+    __to_idnam(lhsx), s1, __bld_lineloc(__xs, (word32) __sfnam_ind,
+    __slin_cnt), __msg2_blditree(__xs2, __inst_ptr),
+    __to_timstr(s2, &__simtime));
+
+   return;
+  }
+
+done:
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * do the quasi continuous force for reg variables
+ *
+ * know lhs always entire register
+ * lhs here can be xmr 
+ * force of entire reg only overrides possible active reg assign
+ *
+ * SJM 06/15/02 - new algorithm leaves dce list always linked on, turns on/off
+ * when active and keeps one different qc dce lists for each lhs concat el
+ * so can reg release each reg listed in lhs concats separately
+ */
+static void do_qc_regforce(struct st_t *qcastp, struct expr_t *lhsx,
+  int32 rhsbi, struct dceauxlstlst_t *dcllp)
+{
+ int32 nd_itpop, stmt_inum;
+ struct net_t *np;
+ struct gref_t *grp;
+ struct qcval_t *assgn_qcp, *frc_qcp; 
+ struct itree_t *itp;
+ char s1[RECLEN];
+
+ strcpy(s1, "");
+ /* if lhs xmr, change to target since forcing in target instance */
+ nd_itpop = FALSE;
+ /* for XMR need stmt context inum for getting dcellst linked on stmt */
+ stmt_inum = __inum;
+ itp = NULL;
+ if (lhsx->optyp == GLBREF)
+  {
+   grp = lhsx->ru.grp;
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+  }
+ else if (lhsx->optyp != ID) __case_terr(__FILE__, __LINE__);
+ np = lhsx->lu.sy->el.enp;
+
+ /* for reg var 2 records always allocated, first is force and 2nd assign */
+ frc_qcp = &(np->nu2.qcval[2*__inum]);
+ assgn_qcp = &(np->nu2.qcval[2*__inum + 1]);
+
+ /* case 1, force pending */
+ if (frc_qcp->qc_active) 
+  { 
+   strcat(s1, " replace force");
+   /* turn off current (if lhs concat many) list of rhs dces */
+   if (frc_qcp->qcdcep != NULL) __dcelst_off(frc_qcp->qcdcep);
+   frc_qcp->qcdcep = NULL;
+   frc_qcp->qc_active = FALSE;
+   goto setup_force;
+  }
+
+ /* if qc assign pending, inactivate but leave ptrs and set bit */
+ if (assgn_qcp->qc_active)
+  {
+   /* turn off the assign list - will be turned on if reg force released */
+   if (assgn_qcp->qcdcep != NULL) __dcelst_off(assgn_qcp->qcdcep);
+   assgn_qcp->qc_active = FALSE;
+   assgn_qcp->qc_overridden = TRUE;
+   strcat(s1, " override assign");
+  }
+setup_force:
+ /* setup the new force */
+ frc_qcp->qc_active = TRUE;
+ frc_qcp->qcstp = qcastp; 
+ frc_qcp->qcrhsbi = rhsbi; 
+ frc_qcp->qclhsbi = -1;
+ frc_qcp->lhsitp = __inst_ptr;
+ /* SJM 06/23/02 - add qc dcep list (right one if lhs cat) to qcval rec */
+ /* one needed for each lhs element because reg release can do separately */
+ frc_qcp->qcdcep = dcllp->dcelsttab[stmt_inum];
+
+ if (nd_itpop) { itp = __inst_ptr; __pop_itstk(); }
+ if (__debug_flg && __ev_tracing)
+  {
+   char s2[RECLEN];
+
+   /* message needs itree context of stmt not lhs if xmr */ 
+   __tr_msg(":: quasi-continuous force of reg %s%s at %s in %s now %s\n",
+    __to_idnam(lhsx), s1, __bld_lineloc(__xs, (word32) __sfnam_ind,
+    __slin_cnt), __msg2_blditree(__xs2, __inst_ptr),
+    __to_timstr(s2, &__simtime));
+  }
+
+ /* start force by storing rhs of force - dces will cause dce chges */
+ /* these routines need ref itree loc not lhs xmr */
+ __do_qc_store(np, frc_qcp, TRUE);
+
+ /* SJM 07/19/02 - must not turn on any rhs dces until store done */
+ /* turn on reg force for this set of dces if non constant rhs */ 
+ if (frc_qcp->qcdcep != NULL) __dcelst_on(frc_qcp->qcdcep);
+
+ /* but these need to run in itree context of lhs */
+ if (nd_itpop) __push_itstk(itp);
+
+ /* notice can have both many wire specific and many all cbs */
+ if (__num_vpi_force_cbs > 0) __find_call_force_cbs(np, -1);
+ if (__vpi_force_cb_always) __cb_all_rfs(np, -1, TRUE);
+
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * do a quasi continuous release for a reg lhs (lvalue)
+ *
+ * know lhs always entire register
+ * lhs here can be xmr
+ * releasing reg with pending active assign re-establishes assign
+ *
+ * SJM 06/23/02 - new qcaf algorithm build qcaf lists during prep and moves
+ * to and from stmt sqca fields and turns on/off when needed
+ */
+static void do_qc_regrelease(struct expr_t *lhsx)
+{
+ int32 nd_itpop;
+ struct net_t *np;
+ struct gref_t *grp;
+ struct qcval_t *assgn_qcp, *frc_qcp; 
+ struct itree_t *itp;
+ char s1[RECLEN];
+
+ strcpy(s1, "");
+ /* must release reg in itree loc. of lhs if xmr */
+ nd_itpop = FALSE;
+ itp = NULL;
+ if (lhsx->optyp == GLBREF)
+  { grp = lhsx->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ else if (lhsx->optyp != ID) __case_terr(__FILE__, __LINE__);
+ np = lhsx->lu.sy->el.enp;
+
+ /* for reg var 2 records always allocated, first is force and 2nd assign */
+ frc_qcp = &(np->nu2.qcval[2*__inum]);
+ assgn_qcp = &(np->nu2.qcval[2*__inum + 1]);
+
+ /* if no force, nothing to do */
+ if (!frc_qcp->qc_active)
+  {
+   /* message here needs lhs xmr context */
+   __sgfinform(465,
+    "attempted release of reg %s in instance %s failed - never forced",
+    __to_idnam(lhsx), __msg2_blditree(__xs, __inst_ptr));
+   if (nd_itpop) __pop_itstk();
+   return;
+  }
+ frc_qcp->qc_active = FALSE;
+ /* turn off active force dces */
+ if (frc_qcp->qcdcep != NULL) __dcelst_off(frc_qcp->qcdcep);
+ frc_qcp->qcdcep = NULL;
+ __force_active = FALSE;
+
+ /* if pending but inactive assign - must reactivate it */
+ if (assgn_qcp->qc_overridden)
+  {
+   /* these need to run in itree context of stmt not lhs if xmr */
+   if (nd_itpop) { itp = __inst_ptr; __pop_itstk(); }
+
+   __do_qc_store(np, assgn_qcp, TRUE);
+   /* build the QCAF dcelst - this must be build in rhs ref. itree loc. */
+
+   assgn_qcp->qc_active = TRUE; 
+   assgn_qcp->qc_overridden = FALSE;
+   /* turn stored last dce list on */
+   /* FIXME - this is never first time */
+   if (assgn_qcp->qcdcep != NULL) __dcelst_on(assgn_qcp->qcdcep);
+   __assign_active = TRUE;
+   strcpy(s1, " reactivating assign");
+  }
+ else { if (nd_itpop) { itp = __inst_ptr; __pop_itstk(); } }
+
+ /* message need stmt itree context */
+ if (__debug_flg && __ev_tracing)
+  {
+   char s2[RECLEN];
+
+   __tr_msg(":: quasi-continuous release of reg %s%s at %s in %s now %s\n",
+    __to_idnam(lhsx), s1, __bld_lineloc(__xs, (word32) __sfnam_ind,
+    __slin_cnt), __msg2_blditree(__xs2, __inst_ptr),
+    __to_timstr(s2, &__simtime));
+  }
+
+ /* these must run in lhs itree context for xmr */ 
+ if (nd_itpop) __push_itstk(itp);
+
+ /* notice can have both many wire specific and many all cbs */
+ if (__num_vpi_rel_cbs > 0) __find_call_rel_cbs(np, -1);
+ if (__vpi_rel_cb_always) __cb_all_rfs(np, -1, FALSE);
+
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * QUASI CONTINUOUS WIRE FORCE/RELEASE ROUTINES 
+ */
+
+/*
+ * execute a quasi-continuous force on a wire
+ * possibilities here are wire, constant bit select, part select
+ * also concat of above
+ * wire must be scalared and everything decomposed to bits
+ */
+extern void __exec_qc_wireforce(struct st_t *stp)
+{
+ register struct expr_t *catndp;
+ register struct dceauxlstlst_t *dcllp;
+ int32 catxlen, bi1; 
+ struct expr_t *lhsx, *catlhsx;
+
+ /* DBG remove --
+ struct itree_t *sav_itp = __inst_ptr;
+ ---*/
+
+ lhsx = stp->st.sqca->qclhsx;
+ dcllp = stp->st.sqca->rhs_qcdlstlst;
+ /* only possibilities are concat and ID */
+ if (lhsx->optyp != LCB) do_qc_wireforce(stp, lhsx, -1, dcllp);
+ else
+  {
+   /* concatenate case know lhs full wire - tricky extractions of rhs */
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x,
+    dcllp = dcllp->dcelstlstnxt)
+    {
+     catlhsx = catndp->lu.x;
+     catxlen = catlhsx->szu.xclen;
+     bi1 = catndp->szu.xclen - catxlen;
+     do_qc_wireforce(stp, catlhsx, bi1, dcllp);
+    }
+  }
+ /* DBG remove --
+ if (sav_itp != __inst_ptr) __misc_terr(__FILE__, __LINE__); 
+ ---*/
+}
+
+/*
+ * execute a quasi-continuous release
+ * only scalared wires or selects or cats not regs
+ * wire force/release is one level only
+ * called in itree context of release stmt 
+ */
+extern void __exec_qc_wirerelease(struct st_t *stp)
+{
+ register struct expr_t *catndp;
+ struct expr_t *lhsx, *catlhsx;
+
+ /* DBG remove --
+ struct itree_t *sav_itp = __inst_ptr;
+ ---*/
+
+ lhsx = stp->st.sqcdea.qcdalhs; 
+ /* only possibilities are concat and ID */
+ if (lhsx->optyp != LCB) do_qc_wirerelease(lhsx);
+ else
+  {
+   /* concatenate case know lhs full wire - tricky extractions of rhs */
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    { catlhsx = catndp->lu.x; do_qc_wirerelease(catlhsx); }
+  }
+ /* DBG remove --
+ if (sav_itp != __inst_ptr) __misc_terr(__FILE__, __LINE__); 
+ ---*/
+}
+
+/*
+ * after possible concat unwinding, exec the wire force
+ *
+ * wire force is bit by bit unless vectored wire (when only entire wire)
+ *
+ * force which is for debugging overrides any wire delay assign
+ * when wire change happens (wire event process) if force active, no assign
+ * rhsbi is low bit of possible rhs section select (0 for not concat)
+ * this is called with stmt itree loc even if lhs xmr and handled push/pop
+ *
+ * SJM 11/14/00 - tran channel (inout port) force now is separate routine
+ * LOOKATME - think could simplify since for wire force always one bit
+ */
+static void do_qc_wireforce(struct st_t *qcfstp, struct expr_t *lhsx,
+ int32 rhsbi, struct dceauxlstlst_t *dcllp)
+{
+ register int32 bi, ibase;
+ int32 biti, bitj, rhsbi2, lhsbi2, ndx;
+ struct net_t *np;
+ struct itree_t *itp;
+ struct dceauxlst_t *qcdcep;
+ 
+ /* step 1: get the wire range */
+ /* for psel or vector, range is biti down to bitj - for scalar 0,0 */
+ /* this computes any xmr new itp but does not push it */
+ __get_qc_wirrng(lhsx, &np, &biti, &bitj, &itp); 
+
+ /* SJM 11/14/00 - if wire in tran chan, force all wires in it*/
+ if (np->ntraux != NULL)
+  {
+   /* this pushes and pops lhs xmr itree context itp if needed */ 
+   /* routine also handles any PLI force callbacks */
+   /* SJM 02/26/02 - no dces so new pre-build qcaf dces does not chg this */
+   __qc_tran_wireforce(np, biti, bitj, rhsbi, itp, qcfstp);
+
+   /* SJM - 04/15/01 - must eval tran chan in lhs xmr itree context */
+   if (itp != NULL) __push_itstk(itp);
+   /* SJM - 03/15/01 - must re-eval all bits if this is vector range */
+   /* new tran force algorithm - force wire in tran channel and then */ 
+   /* re-eval channel */ 
+   for (bi = biti; bi >= bitj; bi--) { __eval_tran_1bit(np, bi); }
+   if (itp != NULL) __pop_itstk();
+
+   /* but trace message must use stmt context */
+   if (__debug_flg && __ev_tracing)
+    {
+     char s1[RECLEN], s2[RECLEN];
+
+     __tr_msg(":: quasi-continuous force of wire %s at %s in %s now %s\n",
+      __msgexpr_tostr(__xs, lhsx), __bld_lineloc(__xs2,
+      (word32) __sfnam_ind, __slin_cnt), __msg2_blditree(s1, __inst_ptr),
+     __to_timstr(s2, &__simtime));
+    }
+   return;
+  }
+
+ /* SJM 07/22/02 - need to access dce list form stmt inum not lhs if xmr */
+ /* access dce list from stmt not lhs itree context */
+ qcdcep = dcllp->dcelsttab[__inum];
+ /* wire force must run in lhs itree context */ 
+ if (itp != NULL) __push_itstk(itp);
+ /* ibase is lhs xmr qcval base */ 
+ ibase = __inum*np->nwid;
+ if (!np->n_isavec)
+  {
+   /* DBG remove */
+   if (biti != 0 || bitj != 0) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   /* this pops itstk if needed */
+   do_1bit_wireforce(qcfstp, np, ibase, -1, rhsbi, itp, qcdcep);
+   ndx = -1;    
+   goto done;
+  }
+
+ /* force every bit in range using same rhs dce list for each */
+ for (bi = bitj; bi <= biti; bi++)
+  {
+   /* rhsbi is low bit of possible lhs concat caused rhs select */
+   if (rhsbi == -1) rhsbi2 = bi - bitj;
+   else rhsbi2 = rhsbi + (bi - bitj);
+   lhsbi2 = bi;
+
+   do_1bit_wireforce(qcfstp, np, ibase, lhsbi2, rhsbi2, itp, qcdcep);
+  }
+
+ if (biti != bitj) ndx = -1; else ndx = biti;
+
+done:
+ if (__debug_flg && __ev_tracing)
+  {
+   char s1[RECLEN], s2[RECLEN];
+
+   /* this must run in itree context of stmt not possible lhs xmr */
+   if (itp != NULL) __pop_itstk(); 
+   __tr_msg(":: quasi-continuous force of wire %s at %s in %s now %s\n",
+    __msgexpr_tostr(__xs, lhsx), __bld_lineloc(__xs2, (word32) __sfnam_ind,
+     __slin_cnt), __msg2_blditree(s1, __inst_ptr),
+    __to_timstr(s2, &__simtime));
+   if (itp != NULL) __push_itstk(itp); 
+  }
+
+ /* these need to run in itree context of possible lhs xmr */
+ /* notice can have both many wire specific and many all cbs */
+ if (__num_vpi_force_cbs > 0) __find_call_force_cbs(np, ndx);
+ if (__vpi_force_cb_always) __cb_all_rfs(np, ndx, TRUE);
+
+ /* on return, itree context of force stmt needed */ 
+ if (itp != NULL) __pop_itstk(); 
+}
+
+/*
+ * do 1 bit wire force 
+ *
+ * this is called with itree context of lhs that is passed in itp if lhs xmr
+ * it handles it own popping and pushing and leave itree same as called 
+ */
+static void do_1bit_wireforce(struct st_t *qcstp, struct net_t *np,
+ int32 ibase, int32 lhsbi, int32 rhsbi, struct itree_t *itp,
+ struct dceauxlst_t *qcdcep)
+{
+ int32 biti;
+ struct qcval_t *frc_qcp;
+
+ if (lhsbi == -1) biti = 0; else biti = lhsbi;
+
+ /* for reg var 2 records always allocated, first is force and 2nd assign */
+ frc_qcp = &(np->nu2.qcval[ibase + biti]);
+ /* forcing to different expr */
+ if (frc_qcp->qc_active)
+  {
+   if (frc_qcp->qcdcep != NULL) __dcelst_off(frc_qcp->qcdcep);
+   frc_qcp->qcdcep = NULL;
+  }
+
+ /* setup the new force */
+ frc_qcp->qcstp = qcstp; 
+ /* rhsbi is low bit of rhs range in case lhs concatenate */ 
+ frc_qcp->qcrhsbi = rhsbi;
+ frc_qcp->qclhsbi = lhsbi;
+ /* store and build dces in lhs ref. itree location */ 
+ frc_qcp->lhsitp = __inst_ptr;
+ frc_qcp->qcdcep = qcdcep;
+
+ /* store and setup dces needs to run in stmt itree context */ 
+ if (itp != NULL) __pop_itstk();
+
+ /* start force by storing rhs of force - dces will cause dce chges */
+ __do_qc_store(np, frc_qcp, FALSE);
+ frc_qcp->qc_active = TRUE;
+
+ /* turn on dces after doing store */
+ if (frc_qcp->qcdcep != NULL) __dcelst_on(frc_qcp->qcdcep);
+
+ if (itp != NULL) __push_itstk(itp);
+}
+
+/*
+ * get qc wire element (after lhs concat separation) 
+ * this sets needed itree loc. to itpp, also sets wire, and range 
+ */
+extern void __get_qc_wirrng(struct expr_t *lhsx, struct net_t **nnp,
+ int32 *biti, int32 *bitj, struct itree_t **itpp)
+{
+ int32 nd_itpop;
+ word32 *wp;
+ struct gref_t *grp;
+ struct net_t *np;
+ struct expr_t *idndp, *ndx;
+
+ *itpp = NULL; 
+ np = NULL;
+ nd_itpop = FALSE;
+ switch ((byte) lhsx->optyp) {
+  case GLBREF:
+   grp = lhsx->ru.grp;
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+   /* FALLTHRU */
+  case ID:
+   np = lhsx->lu.sy->el.enp;
+   *biti = np->nwid - 1;
+   *bitj = 0;
+   break;
+  case LSB: case PARTSEL:
+   idndp = lhsx->lu.x;
+   if (idndp->optyp == GLBREF)
+    {
+     grp = idndp->ru.grp;
+     __xmrpush_refgrp_to_targ(grp);
+     nd_itpop = TRUE;
+    }
+   np = idndp->lu.sy->el.enp;
+   /* know error before here if non in range constant value */ 
+   if (lhsx->optyp == LSB) *bitj = *biti = __get_const_bselndx(lhsx);
+   else
+    {
+     ndx = lhsx->ru.x->lu.x;
+     __inst_mod = __inst_mod;
+     wp = &(__contab[ndx->ru.xvi]);
+     *biti = wp[0];
+     ndx = lhsx->ru.x->ru.x;
+     wp = &(__contab[ndx->ru.xvi]);
+     *bitj = wp[0];
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ if (nd_itpop) { *itpp = __inst_ptr;  __pop_itstk(); }
+ *nnp = np;
+}
+
+/*
+ * after possible concat unwinding, exec the wire section release
+ *
+ * tricky part is need to force evaluation and store of all drivers
+ * LOOKATME - is there any reason cannot just call multi driver eval
+ * even for 1 or no driver case 
+ */
+static void do_qc_wirerelease(struct expr_t *lhsx)
+{
+ register int32 bi, ibase;
+ int32 biti, bitj, all_forced, ndx;
+ struct net_t *np;
+ struct itree_t *itp;
+ struct qcval_t *frc_qcp;
+ char s1[RECLEN];
+ 
+ /* step 1: get the wire range */
+ /* for psel or vector, range is biti down to bitj - for scalar 0,0 */
+ __get_qc_wirrng(lhsx, &np, &biti, &bitj, &itp); 
+
+ /* SJM 11/14/00 - if wire in tran chan, force all wires in it*/
+ if (np->ntraux != NULL)
+  {
+   __qc_tran_wirerelease(np, biti, bitj, itp, lhsx);
+
+   /* SJM 04/15/01 - need to eval tran in lhs itree context */
+   if (itp != NULL) __push_itstk(itp);
+
+   /* SJM - 03/15/01 - must re-eval all bits if this is vector range */
+   /* new tran force algorithm - force wire in tran channel and then */ 
+   /* re-eval channel */ 
+   for (bi = biti; bi >= bitj; bi--)
+    {
+     __eval_tran_1bit(np, bi);
+    }
+   if (itp != NULL) __pop_itstk();
+
+   /* but messages needs stmt itree context */
+   if (__debug_flg && __ev_tracing)
+    {
+     char s2[RECLEN];
+
+     __tr_msg(":: quasi-continuous force of wire %s at %s in %s now %s\n",
+      __msgexpr_tostr(__xs, lhsx), __bld_lineloc(__xs2,
+      (word32) __sfnam_ind, __slin_cnt), __msg2_blditree(s1, __inst_ptr),
+     __to_timstr(s2, &__simtime));
+    }
+   return;
+  }
+
+ /* SJM 07/23/02 - this needs lhs expr context */
+ if (itp != NULL) __push_itstk(itp);
+
+ ibase = __inum*np->nwid;
+ for (bi = 0; bi < np->nwid; bi++)
+  {
+   frc_qcp = &(np->nu2.qcval[ibase + bi]);
+   if (frc_qcp->qc_active) goto some_bit_forced;
+  }
+ strcpy(s1, " - no bits forced");
+ __sgfinform(465,
+  "attempted release of %s in instance %s failed%s",
+  __msgexpr_tostr(__xs2, lhsx), __msg2_blditree(__xs, __inst_ptr), s1);
+ /* SJM 04/15/01 - if no bits forced, do not try to exec call backs */
+ if (itp != NULL) __pop_itstk();
+ return;
+
+some_bit_forced:
+ if (__debug_flg && __ev_tracing)
+  {
+   char s2[RECLEN];
+
+   __tr_msg(":: quasi-continuous release of wire %s at %s in %s now %s\n",
+    __msgexpr_tostr(__xs, lhsx), __bld_lineloc(__xs2, (word32) __sfnam_ind,
+     __slin_cnt), __msg2_blditree(s1, __inst_ptr),
+    __to_timstr(s2, &__simtime));
+  }
+
+ /* know some forced or will not get here - release all in range */
+ /* notice wire force is per bit but no second qc assigns for wires */  
+ all_forced = TRUE;
+ for (bi = biti; bi >= bitj; bi--)
+  {
+   frc_qcp = &(np->nu2.qcval[ibase + bi]);
+   if (!frc_qcp->qc_active) { all_forced = FALSE; continue; }
+   frc_qcp->qc_active = FALSE;
+
+   /* turn off dces after doing store if rhs non constant */ 
+   if (frc_qcp->qcdcep != NULL) __dcelst_off(frc_qcp->qcdcep);
+   frc_qcp->qcdcep = NULL;
+  }
+
+ /* assign expected value now that force removed by evaling all drivers */
+ /* must re-eval entire wire since other drivers may overlap forced range */
+ /* notice this must be called from target of xmr and/or col. to */
+ /* it handles moving back to references */
+ __assign_1mdrwire(np);
+
+ if (!all_forced)
+  {
+   if (itp != NULL) __pop_itstk();
+   strcpy(s1, " - some bits forced");
+   __sgfinform(465, "attempted release of %s in instance %s failed%s",
+    __msgexpr_tostr(__xs2, lhsx), __msg2_blditree(__xs, __inst_ptr), s1);
+   if (itp != NULL) __push_itstk(itp);
+
+   /* here still need to try to exec PLI callbacks */
+  } 
+
+ /* must exec call backs in possible lhs xmr itree context */ 
+ /* FIXME - why not calling for every bit in range - only 1 bit possible? */
+ if (biti != bitj) ndx = -1; else ndx = biti;
+ /* notice can have both many wire specific and many all cbs */
+ if (__num_vpi_rel_cbs > 0) __find_call_rel_cbs(np, ndx);
+ if (__vpi_rel_cb_always) __cb_all_rfs(np, ndx, FALSE);
+
+ if (itp != NULL) __pop_itstk();
+}
+
+/*
+ * ROUTINES TO EXEC QUASI-CONTINOUS ASSIGN OPERATIONS
+ */
+
+/*
+ * exec the quasi-continuous assign or force under control of qcval 
+ * change may be in rhs xmr target, but must exec this is ref.
+ * rhs wire np changed
+ *
+ * SJM 06/16/02 - new algorithm that builds qcval and qc dces once
+ * works because dce points to corresponding qcval record
+ */
+extern void __assign_qcaf(struct dcevnt_t *dcep)
+{
+ register struct expr_t *catndp;
+ int32 nd_itpop, nd_itpop2;
+ struct qcval_t *qcvalp;
+ struct st_t *stp;
+ struct expr_t *lhsx, *lhsx2, *rhsx; 
+ struct xstk_t *xsp;
+ struct net_t *np;
+
+ nd_itpop = FALSE;
+ /* first must move itree loc. back to ref. (where lhs and rhs are) */ 
+ if (dcep->dce_1inst) { nd_itpop = TRUE; __push_itstk(dcep->dce_refitp); }  
+
+ /* know some bit in rhs changed, get one qcval */
+ /* here using fmon field really as union since unused in qca case */
+ qcvalp = dcep->dceu2.dce_qcvalp;
+
+ /* get the qc statement */
+ stp = qcvalp->qcstp; 
+ /* evaluate the rhs */
+ rhsx = stp->st.sqca->qcrhsx; 
+ lhsx = stp->st.sqca->qclhsx;
+ /* this converts rhs if needed and makes right lhs width */
+ xsp = __eval_assign_rhsexpr(rhsx, lhsx);
+
+ if (__debug_flg && __ev_tracing)
+  {
+   char s1[RECLEN], s2[RECLEN];
+
+   __tr_msg(
+    ":: quasi-continuous rhs at %s changed in %s now %s - assign/force to %s\n",
+    __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt),
+    __msg2_blditree(__xs2, __inst_ptr), __to_timstr(s1, &__simtime),
+    __msgexpr_tostr(s2, stp->st.sqca->qclhsx));
+  }
+ /* if reg form and not concatenate, easy just use changed qcval */
+ if (stp->st.sqca->regform)
+  {
+   if (lhsx->optyp != LCB)
+    {
+     np = lhsx->lu.sy->el.enp;
+     do_qc2_regstore(np, qcvalp, xsp);
+    }
+   else
+    {
+     /* concatenate required finding qcval for each */
+     for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+      {
+       lhsx2 = catndp->lu.x;
+       /* each lhs concatenate component may be xmr */
+       if (lhsx2->optyp == GLBREF)
+        { __xmrpush_refgrp_to_targ(lhsx2->ru.grp); nd_itpop2 = TRUE; }
+       else nd_itpop2 = FALSE;
+
+       np = lhsx2->lu.sy->el.enp;
+       if (stp->st.sqca->qcatyp == ASSIGN)
+        qcvalp = &(np->nu2.qcval[2*__inum + 1]);
+       else qcvalp = &(np->nu2.qcval[2*__inum]);
+       do_qc2_regstore(np, qcvalp, xsp);
+       if (nd_itpop2) __pop_itstk();
+      }
+    }
+  } 
+ else
+  {
+   /* for every lhs concat part and bit do the assign */
+   if (lhsx->optyp != LCB) assign_alllhs_bits(lhsx, xsp);
+   else
+    {
+     for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+      assign_alllhs_bits(catndp->lu.x, xsp);
+    }
+  }
+ __pop_xstk();
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * assign to all qcval bits of passed lhs expr (know not concat)
+ */
+static void assign_alllhs_bits(struct expr_t *lhsx, struct xstk_t *xsp)
+{
+ register int32 bi, ibase;
+ int32 biti, bitj, nd_itpop;
+ struct net_t *np;
+ struct itree_t *lhsitp;
+ struct qcval_t *frc_qcp;
+
+ nd_itpop = FALSE;
+ __get_qc_wirrng(lhsx, &np, &biti, &bitj, &lhsitp); 
+ if (lhsitp != NULL) { nd_itpop = TRUE; __push_itstk(lhsitp); }
+ /* must run this in lhs itree loc. */
+ ibase = np->nwid*__inum;
+ for (bi = biti; bi >= bitj; bi--, frc_qcp--)
+  {
+   frc_qcp = &(np->nu2.qcval[ibase + bi]);
+   do_qc2_wirestore(np, frc_qcp, xsp);
+  }
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * execute a qc assign under control of qc val record into net np
+ *
+ * this must be called from ref. stmt (not xmr lhs) itree location
+ * notice assign is either entire reg or bit of wire 
+ */
+extern void __do_qc_store(struct net_t *np, struct qcval_t *qcvalp, int32 is_reg)
+{ 
+ struct xstk_t *xsp;
+ struct expr_t *rhsx;
+
+ rhsx = qcvalp->qcstp->st.sqca->qcrhsx; 
+ /* this converts rhs if needed and makes lhs right width */
+ xsp = __eval_assign_rhsexpr(rhsx, qcvalp->qcstp->st.sqca->qclhsx);
+ if (is_reg) do_qc2_regstore(np, qcvalp, xsp);
+ else do_qc2_wirestore(np, qcvalp, xsp);
+ __pop_xstk();
+}
+
+/*
+ * store q qc value with rhs in xsp for reg entire wire only
+ * ths must run in assign/force stmt context since get rhs
+ */
+static void do_qc2_regstore(struct net_t *np, struct qcval_t *qcvalp,
+ struct xstk_t *xsp)
+{
+ int32 nd_itpop, nd_xpop;
+ struct xstk_t *xsp2;
+
+ /* know lhs always entire reg but rhs may need select out */ 
+ /* rhsbi field is low bit of section from lhs concatenate if needed */
+ if (qcvalp->qcrhsbi != -1)
+  {
+   push_xstk_(xsp2, np->nwid);
+   __rhspsel(xsp2->ap, xsp->ap, qcvalp->qcrhsbi, np->nwid);
+   __rhspsel(xsp2->bp, xsp->bp, qcvalp->qcrhsbi, np->nwid);
+   nd_xpop = TRUE;; 
+  }
+ else { xsp2 = xsp; nd_xpop = FALSE; }
+
+ if (qcvalp->lhsitp != NULL)
+  { nd_itpop = TRUE; __push_itstk(qcvalp->lhsitp); }
+ else nd_itpop = FALSE;
+
+ /* emit debug tracing message if needed */
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg("   QC immediate store of %s into reg %s\n",
+    __xregab_tostr(__xs2, xsp2->ap, xsp2->bp, xsp2->xslen,
+    qcvalp->qcstp->st.sqca->qcrhsx), np->nsym->synam);
+  }
+ __chg_st_val(np, xsp2->ap, xsp2->bp);
+
+ if (nd_xpop) __pop_xstk();
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * store qc value with rhs in xsp for wire either scalar or 1 bit select only
+ */
+static void do_qc2_wirestore(struct net_t *np, struct qcval_t *qcvalp,
+ struct xstk_t *xsp)
+{
+ int32 ind, nd_itpop, nd_xpop;
+ byte *sbp;
+ struct xstk_t *xsp2, *xsp3;
+
+ /* DBG remove ---
+ __dbg_msg("   +++ before QC cat rhs value %s rhsbi=%d, lhsbi=%d\n",
+  __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE),
+  qcvalp->qcrhsbi, qcvalp->qclhsbi);
+ --- */
+
+ /* 2 cases that require selecting a bit from evaled rhs xsp */
+ /* rhs bi or lhs bi not -1 because lhs concatenate */
+ if (qcvalp->qcrhsbi != -1 || qcvalp->qclhsbi != -1)
+  {
+   ind = ((qcvalp->qcrhsbi == -1) ? 0 : qcvalp->qcrhsbi);
+   push_xstk_(xsp2, 1);
+   xsp2->ap[0] = rhsbsel_(xsp->ap, ind);
+   xsp2->bp[0] = rhsbsel_(xsp->bp, ind);
+   nd_xpop = TRUE;
+  }
+ else { xsp2 = xsp; nd_xpop = FALSE; }
+
+ /* now know lot bit of xsp is value to assign */
+ /* DBG remove ---
+ if (__debug_flg)
+  {
+   __dbg_msg("   +++ after QC cat rhs value %s rhsbi=%d, lhsbi=%d\n",
+    __regab_tostr(__xs, xsp2->ap, xsp2->bp, xsp2->xslen, BHEX, FALSE),
+    qcvalp->qcrhsbi, qcvalp->qclhsbi);
+  } 
+ --- */ 
+
+ if (qcvalp->lhsitp != NULL)
+  { nd_itpop = TRUE; __push_itstk(qcvalp->lhsitp); }
+ else nd_itpop = FALSE;
+
+ /* emit debug tracing message if needed */
+ if (__debug_flg && __ev_tracing)
+  {
+   if (qcvalp->qclhsbi == -1) strcpy(__xs, "");
+   else sprintf(__xs, "[%d]", qcvalp->qclhsbi);
+   __tr_msg("   QC immediate store of %s into wire %s%s\n",
+    __xregab_tostr(__xs2, xsp2->ap, xsp2->bp, xsp->xslen,
+    qcvalp->qcstp->st.sqca->qcrhsx), np->nsym->synam, __xs);
+  }
+
+ /* quasi-continuous assign to strength wire always strong */
+ if (np->n_stren)
+  {
+   push_xstk_(xsp3, 4);
+   sbp = (byte *) xsp3->ap;
+   /* LOOKATME could simpify since know only 1 bit */
+   __st_standval(sbp, xsp2, ST_STRVAL);
+   /* notice if vector for wire know lhs bi always non zero */
+
+   /* SJM 11/14/00 slightly better to just pass a part as sbp */
+   /* notice if vector for wire know lhs bi always non zero */
+   if (np->n_isavec) __chg_st_bit(np, qcvalp->qclhsbi, (word32) sbp[0], 0L); 
+
+   /* AIV 07/09/04 - was calling macro but macro never checked record nchg */
+   /* notice for non stren case was calling chg st as needed */ 
+   else __chg_st_val(np, (word32 *) sbp, 0L); 
+   __pop_xstk();
+  }
+ else 
+  {
+   if (np->n_isavec)
+    __chg_st_bit(np, qcvalp->qclhsbi, xsp2->ap[0], xsp2->bp[0]); 
+   else __chg_st_val(np, xsp2->ap, xsp2->bp);
+  }
+ if (nd_xpop) __pop_xstk();
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * ROUTINES TO MOVE ITREE LOCATION (PUSH/POP ITREE STACK) 
+ */
+
+/*
+ * routine to push something onto itstk when there is no itree context
+ */
+extern void __push_wrkitstk(struct mod_t *mdp, int32 winum)
+{
+ struct itree_t *tmpitp;
+ struct inst_t *tmpip;
+
+ /* DBG REMOVE --- 
+ if (__inst_mod != NULL) 
+  __dbg_msg("### pushing inst mod (before) = %s\n", __inst_mod->msym->synam);
+ --- */
+
+ if (__tmpitp_freelst == NULL)
+  {
+   tmpitp = (struct itree_t *) __my_malloc(sizeof(struct itree_t)); 
+   tmpip = (struct inst_t *) __my_malloc(sizeof(struct inst_t));
+  }
+ else
+  {
+   tmpitp = __tmpitp_freelst;
+   tmpip = __tmpip_freelst;
+   __tmpitp_freelst = __tmpitp_freelst->up_it;
+   __tmpip_freelst = (struct inst_t *) __tmpip_freelst->imsym;
+  }
+
+ tmpitp->itinum = winum;
+ tmpitp->up_it = NULL;
+ tmpitp->in_its = NULL;
+ tmpitp->itip = tmpip;
+ tmpip->imsym = mdp->msym;
+ /* indicates dummy work itp */
+ tmpip->isym = NULL;
+ __push_itstk(tmpitp);
+ /* DBG REMOVE ---
+ __dbg_msg("### pushing inst mod (after) = %s\n", __inst_mod->msym->synam);
+ --- */
+}
+
+/*
+ * routine to pop something from itstk when there is no itree context
+ * must pair with push_wrkistk
+ */
+extern void __pop_wrkitstk(void)
+{
+ struct itree_t *tmpitp;
+ struct inst_t *tmpip;
+
+ tmpitp = __inst_ptr;
+ /* REMOVE ---
+ __dbg_msg("### popping inst mod (before) = %s\n", __inst_mod->msym->synam);
+ --- */
+ tmpip = tmpitp->itip;
+ __pop_itstk();
+ /* DBG REMOVE ---
+ if (__inst_mod != NULL)
+  __dbg_msg("### popping inst mod (after) = %s\n", __inst_mod->msym->synam);
+ -- */
+ tmpip = tmpitp->itip;
+ tmpitp->up_it = __tmpitp_freelst;
+ __tmpitp_freelst = tmpitp;
+ tmpip->imsym = (struct sy_t *) __tmpitp_freelst;
+ __tmpip_freelst = tmpip;
+}
+
+/*
+ * push new current itp and set current inst num
+ * LOOKATME - maybe these could be macros (see cvmacros.h)
+ * SJM 04/20/01 - this now used instead of macros since do not slow down much
+ */
+/* ---- */
+extern void __push_itstk(struct itree_t *itp)
+{
+ /* DBG remove --
+ if (itp == NULL) __misc_terr(__FILE__, __LINE__);
+ if (__itspi + 1 >= MAXITDPTH) __misc_terr(__FILE__, __LINE__);
+ --- */
+ __itstk[++__itspi] = __inst_ptr = itp;
+ /* DBG remove --
+ if (__inst_ptr == NULL) __misc_terr(__FILE__, __LINE__);
+ --- */
+ __inst_mod = __inst_ptr->itip->imsym->el.emdp;
+ __inum = __inst_ptr->itinum;
+ /* DBG REMOVE ---
+ if (__debug_flg)
+  {
+   if (__inst_ptr->itip == NULL) strcpy(__xs, "**no itip (dummy)**");
+   else if (__inst_ptr->itip->isym == NULL) strcpy(__xs, "*no ip (wrkitp?)");
+   else __msg2_blditree(__xs, __inst_ptr);
+   __dbg_msg(
+    "+++ pushing itree stack to height %d - inum %d, inst %s mod %s\n",
+    __itspi + 1, __inum, __xs, __inst_mod->msym->synam);
+  }
+ -- */
+ /* DBG remove - this can happen but need to study example */
+ /* if (__itspi > 6) __misc_terr(__FILE__, __LINE__); */
+}
+/* --- */
+
+/*
+ * pop cur. itp - module itree place
+ *
+ * this is for debugging normally use this macro
+ */
+/* --- */
+extern void __pop_itstk(void)
+{
+ /* DBG remove ---
+ if (__itspi < 0) __misc_terr(__FILE__, __LINE__);
+  -- */
+ if (--__itspi < 0)
+  {
+   __inst_ptr = NULL;
+   __inst_mod = NULL;
+   __inum = 0xffffffff;
+  }
+ else 
+  {
+   __inst_ptr = __itstk[__itspi];
+ 
+   /* DBG remove ---
+   if (__inst_ptr == NULL || __inum == 0xffffffff)
+    __misc_terr(__FILE__, __LINE__);
+   -- */
+   __inst_mod = __inst_ptr->itip->imsym->el.emdp;
+   __inum = __inst_ptr->itinum;
+  }
+
+ /* DBG remove ---
+ if (__debug_flg)
+  __dbg_msg("+++ popping itree stack to height %d\n", __itspi + 1);
+ --- */
+}
+/* --- */
+
+/*
+ * push an itree stack entry that is the global inst. place
+ * current itp place is place xmr appears - push target after tracing
+ *
+ * this pushes target given reference xmr location
+ * by here all selects of instance arrays have been resolved to right symbol
+ */
+extern void __xmrpush_refgrp_to_targ(struct gref_t *grp)
+{
+ struct itree_t *itp;
+
+ /* rooted case */
+ if (grp->is_rooted)
+  {
+   __push_itstk(grp->targu.targitp);
+   /* DBG remove ---
+   if (__debug_flg)
+    __dbg_msg("== pushing rooted global %s target (itree=%s)\n",
+     grp->gnam, __msg2_blditree(__xs, __inst_ptr));
+   --- */  
+   return;
+  }
+ /* upward relative case - requires linear list search */
+ if (grp->upwards_rel)
+  {
+   __push_itstk(grp->targu.uprel_itps[__inum]);
+   /* --- DBG remove */
+   if (__debug_flg)
+    __dbg_msg("== pushing upward relative global %s target (itree=%s)\n",
+     grp->gnam, __msg2_blditree(__xs, __inst_ptr));
+   /* -- */
+   return;
+  }
+ /* normal downward instance path case */
+ itp = __find_unrt_targitp(grp, __inst_ptr, 0);
+ __push_itstk(itp);
+
+ /* DBG remove --- 
+ if (__debug_flg)
+  __dbg_msg("== pushing downward global %s target (itree=%s) \n",
+    grp->gnam, __msg2_blditree(__xs, __inst_ptr));
+ --- */
+} 
+
+/*
+ * return target itp given current itp and downward xmr (gref)
+ *
+ * by here all selects of instance arrays resolved to right inst symbol
+ */
+extern struct itree_t *__find_unrt_targitp(struct gref_t *grp,
+ register struct itree_t *itp, int32 startii)
+{
+ register int32 gri;
+ int32 ii; 
+ byte *bp1, *bp2;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+
+ /* notice first is inst. in module gref appears in */
+ imdp = itp->itip->imsym->el.emdp;
+ for (gri = startii;;)
+  {
+   if (grp->grxcmps[gri] != NULL) ip = __get_gref_giarr_ip(grp, gri, itp); 
+   else ip = grp->grcmps[gri]->el.eip;
+
+   /* DBG remove RELEASE REMOVEME -- */
+   if (imdp->minsts == NULL) __misc_terr(__FILE__, __LINE__);
+   /* -- */
+
+   /* making use of c pointer subtraction correction object size here */
+   /* changing to byte ptr because not sure of c ptr size object rules */
+   bp1 = (byte *) ip;
+   bp2 = (byte *) imdp->minsts;
+   /* DBG remove ---
+   if (bp2 > bp1)
+    {
+     __dbg_msg("== global %s comp=%d mod=%s inst=%s itp=%s(%s).\n",
+      grp->gnam, gri, imdp->msym->synam, ip->isym->synam, 
+      itp->itip->isym->synam, itp->itip->imsym->synam);
+     __arg_terr(__FILE__, __LINE__);
+    }
+   --- */
+   ii = (bp1 - bp2)/sizeof(struct inst_t);
+   itp = &(itp->in_its[ii]);
+   /* DBG remove ---
+   if (__debug_flg)
+    {
+     __dbg_msg("== global %s comp=%d mod=%s inst=%s num=%d, itp=%s(%s).\n",
+      grp->gnam, gri, imdp->msym->synam, ip->isym->synam, ii, 
+      itp->itip->isym->synam, itp->itip->imsym->synam);
+    }
+   --- */
+   if (++gri > grp->last_gri) break;
+   imdp = itp->itip->imsym->el.emdp;
+  }
+ return(itp);
+}
+
+/*
+ * access a gref inst array index and return the right expanded instance
+ *
+ * assumes grxcmps folded to 32 bit non x/z constants (maybe IS)
+ * LOOKATME - this always checks ranges - maybe should have separate routine
+ */
+extern struct inst_t *__get_gref_giarr_ip(struct gref_t *grp, int32 gri,
+ struct itree_t *itp) 
+{
+ int32 indx, ii2, ii3;      
+ byte *bp1, *bp2;
+ struct sy_t *syp;
+ struct xstk_t *xsp;
+ struct giarr_t *giap;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+
+ syp = grp->grcmps[gri];
+ /* DBG remove --- */
+ if (!syp->sy_giabase) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ __push_itstk(itp);
+ /* evaluate - this just loads constant but may be IS form constant */
+ /* know checked so will be non x/z 32 bit value or will not get here */
+ xsp = __eval_xpr(grp->grxcmps[gri]);
+ indx = (int32) xsp->ap[0];
+ __pop_xstk();
+ __pop_itstk();
+ imdp = itp->itip->imsym->el.emdp;
+ /* syp points to first instance of expanded */
+ ip = syp->el.eip;
+ bp1 = (byte *) ip;
+ bp2 = (byte *) imdp->minsts;
+ ii2 = (bp1 - bp2)/sizeof(struct inst_t);
+ giap = imdp->miarr[ii2]; 
+ if (giap->gia1 > giap->gia2)
+  {
+   if (indx > giap->gia1 || indx < giap->gia2) goto bad_ref; 
+   else ii3 = giap->gia_bi + (giap->gia1 - indx);
+  }
+ else
+  {
+   if (indx < giap->gia1 || indx > giap->gia2) goto bad_ref; 
+   ii3 = giap->gia_bi + (indx - giap->gia1);
+  }
+done:
+ ip = &(imdp->minsts[ii3]);
+ return(ip);
+
+bad_ref:
+ __gferr(680, grp->grfnam_ind, grp->grflin_cnt,
+  "hierarchical reference %s of %s index %d (comp. %d) out of range [%d:%d]",
+  grp->gnam, syp->synam, indx, gri + 1, giap->gia1, giap->gia2); 
+ ii3 = giap->gia_bi;
+ goto done;
+}
+
+/*
+ * routine to push ref. itstk place onto inst. stack when at define place
+ * propagation caller will pop back to target place - only called if xmr 
+ * notice if this is called, caller will need to pop
+ */
+extern int32 __match_push_targ_to_ref(word32 xmrtyp, struct gref_t *grp)
+{
+ register int32 i, gri;
+ struct itree_t *itp;
+ struct inst_t *ip;
+
+ switch ((byte) xmrtyp) {
+  case XNP_DOWNXMR:
+   /* since current itp is target - back up to reference itp */
+   itp = __inst_ptr;
+   /* SJM 04/17/03 - must move up and check that each one on way up */
+   /* matches inst above since down can be multiply instanciated */
+   for (gri = grp->last_gri; gri >= 0; gri--)
+    {
+     /* need to use inst array select expr which is itree loc. specific */
+     if (grp->grxcmps[gri] != NULL) ip = __get_gref_giarr_ip(grp, gri, itp); 
+     else ip = grp->grcmps[gri]->el.eip;
+
+     if (ip != itp->itip)
+      {
+       /* DBG remove --- */ 
+       if (__debug_flg)
+        {
+         __dbg_msg(
+          "== down glb drive/load of %s (in %s) mismatch instance %s (comp %s != %s)\n",
+          grp->gnam, grp->gin_mdp->msym->synam, __msg2_blditree(__xs,
+          __inst_ptr), ip->isym->synam, itp->itip->isym->synam);
+        }
+       /* --- */
+       return(FALSE);
+      }
+     /* DBG remove --- */
+     if (itp->up_it == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     /* DBG remove --- */ 
+     if (__debug_flg)
+      {
+       __dbg_msg(
+        "== down glb %s drive/load move from decl in targ %s to ref in %s\n",
+        grp->gnam, __msg2_blditree(__xs, itp),
+        __msg2_blditree(__xs2, itp->up_it)); 
+      }
+     /* --- */
+     itp = itp->up_it;
+    }
+   break;
+  case XNP_RTXMR:
+   /* rooted not part of np union field - never called uses filter fld */ 
+   __case_terr(__FILE__, __LINE__);
+   return(FALSE);
+  case XNP_UPXMR:
+   /* SJM 09/14/00 - must search for current target place to move back */
+   /* to location referenced in */
+   /* SJM 07/01/03 - index was one too many */
+   for (i = 0; i < grp->gin_mdp->flatinum; i++)
+    {
+     if (__inst_ptr == grp->targu.uprel_itps[i])
+      {
+       /* DBG remove --- */ 
+       if (__debug_flg)
+        {
+         __dbg_msg(
+          "== up rel glb %s drive/load move from decl in targ %s to ref in %s\n",
+          grp->gnam, __msg2_blditree(__xs, __inst_ptr),
+          __msg2_blditree(__xs2, grp->gin_mdp->moditps[i]));
+        }
+       /* --- */
+       goto got_itp;
+      }
+    } 
+   /* SJM 05/23/03 - possible for down declared in upwards rel to all go */ 
+   /* to only some instances so this declared in may not exist */
+   if (__debug_flg)
+    {
+     __dbg_msg(
+      "== uprel glb %s drive/load of %s (in %s) no matching uprel inst\n",
+       grp->gnam, grp->gin_mdp->msym->synam, __msg2_blditree(__xs,
+       __inst_ptr));
+    }
+   return(FALSE);
+got_itp:
+   itp = grp->gin_mdp->moditps[i];
+   break;
+  default: __case_terr(__FILE__, __LINE__); return(TRUE);
+ } 
+ __push_itstk(itp);
+ return(TRUE);
+}
+
+/*
+ * CONTINUOUS ASSIGNMENT ROUTINES
+ */
+
+/*
+ * execute concat assign part of non strength lhs wire continuous assign
+ *
+ * know rhs non strength and no component of lhs needs strength
+ * i.e. continuous assign does not drive strength (strong0, strong1)
+ * caller must pop stack on return
+ */
+extern void __exec_ca_concat(struct expr_t *xlhs, register word32 *ap, 
+ register word32 *bp, int32 must_schedule)
+{
+ register struct expr_t *catndp;
+ register int32 catxlen;
+ register struct xstk_t *catxsp;
+ int32 bi1;
+ struct expr_t *catlhsx;
+
+ /* do lhs concatenate assigns from left to right */
+ for (catndp = xlhs->ru.x; catndp != NULL; catndp = catndp->ru.x)
+  {
+   catlhsx = catndp->lu.x;
+   catxlen = catlhsx->szu.xclen;
+   /* catndp comma node is dist. to low bit, bi1 is low bit of rhs psel */
+   bi1 = catndp->szu.xclen - catxlen;
+
+   /* DBG remove ---
+   if (__debug_flg)
+    __dbg_msg(
+     "+++lhs: total concat wid=%u, low index=%d, wid=%u, remaining wid=%u\n",
+     xlhs->szu.xclen, bi1, catxlen, catndp->szu.xclen);
+   --- */
+
+   /* select current pos. right width piece from rhs and put on tos reg */
+   /* notice assignment always same width */
+   push_xstk_(catxsp, catxlen);
+   if (catxlen == 1)
+    { catxsp->ap[0] = rhsbsel_(ap, bi1); catxsp->bp[0] = rhsbsel_(bp, bi1); } 
+   else
+    {
+     __rhspsel(catxsp->ap, ap, bi1, catxlen);
+     __rhspsel(catxsp->bp, bp, bi1, catxlen);
+    }
+   /* also nested lhs concatenates illegal - will never appear */
+   /* notice this is part of immediate assign must not inc assign counter */
+   /* here know every catlhsx wire must be strength */
+   __exec_conta_assign(catlhsx, catxsp->ap, catxsp->bp, must_schedule);
+   __pop_xstk();
+  }
+}
+
+/*
+ * execute assign part of strength lhs wire continuous assign concat
+ *
+ * know rhs has strength - maybe only (strong0, strong1) because at least
+ * one lhs wire needs strength - if any lhs concat component non stren
+ * that section converted back to value here
+ * caller must pop stack on return
+ */
+extern void __stren_exec_ca_concat(struct expr_t *xlhs, byte *sbp,
+ int32 must_schedule)
+{
+ register int32 catxlen;
+ register struct expr_t *catndp;
+ register int32 sbi, sbi2;
+ int32 bi1;
+ byte *sbp2;
+ struct expr_t *catlhsx;
+ struct xstk_t *catxsp, *xsp;
+
+ /* do lhs concatenate assigns from left to right */
+ for (catndp = xlhs->ru.x; catndp != NULL; catndp = catndp->ru.x)
+  {
+   catlhsx = catndp->lu.x;
+   catxlen = catlhsx->szu.xclen;
+   /* bi1 is low bit of rhs evaluted value part select */
+   bi1 = catndp->szu.xclen - catxlen; 
+
+   /* --- DBG remove
+   if (__debug_flg)
+    __dbg_msg(
+     "+++lhs proc: total cat wid=%u, low index=%d, wid=%u, remaining wid=%u\n",
+     xlhs->szu.xclen, bi1, catxlen, catndp->szu.xclen);
+   --- */
+
+   /* select current pos. right width piece from rhs and put on tos reg */
+   /* notice assignment always same width */
+   push_xstk_(catxsp, 4*catxlen);
+   sbp2 = (byte *) catxsp->ap;
+   if (catxlen == 1) sbp2[0] = sbp[bi1];
+   else
+    {
+     /* sbp2 and sbi2 is section selected from concatenate rhs */
+     for (sbi = bi1, sbi2 = 0; sbi2 < catxlen; sbi++, sbi2++)
+      sbp2[sbi2] = sbp[sbi];
+    }
+   if (!catlhsx->x_stren)
+    {
+     push_xstk_(xsp, catxlen);
+     __rem_stren(xsp->ap, xsp->bp, sbp2, catxlen); 
+     /* DBG remove */
+     if (__debug_flg && __ev_tracing)
+      __tr_msg("+++ strength concat assign - needed to remove strength?");
+     /* --- */
+     __exec_conta_assign(catlhsx, xsp->ap, xsp->bp, must_schedule);
+     __pop_xstk();
+    }
+   else
+    {
+     /* also nested lhs concatenates illegal - will never appear */
+     /* this is part of immediate assign must not inc assign counter */
+     __exec_conta_assign(catlhsx, catxsp->ap, catxsp->bp, must_schedule);
+    }
+   __pop_xstk();
+  }
+}
+
+/*
+ * actually execute the continuous assign store 
+ *
+ * concatenates removed before here
+ * the various store routines assume xsp stren consistent with wire type
+ * i.e. this routine handles both stren and non stren
+ * know xlhs is same width as ap/bp that is new rhs value
+ *
+ * key here is that mutiple driver or supply0/1 or tri0/1 or tran chan nets
+ * never just assigned here without fi>1 eval. all drivers evaluated 
+ *
+ * notice that if this is called from force mechanism caller must
+ * turn off any bits before or will not really change value
+ */
+extern void __exec_conta_assign(struct expr_t *xlhs, register word32 *ap,
+ register word32 *bp, int32 must_schedule)
+{
+ int32 nd_itpop, ri1, ri2;
+ struct expr_t *idndp, *ndx1;
+ struct net_t *np;
+ struct gref_t *grp;
+
+ /* notice if forced still must schedule since force maybe off later */
+ if (must_schedule) { sched_conta_assign(xlhs, ap, bp); return; }
+
+ nd_itpop = FALSE;
+ switch ((byte) xlhs->optyp) {
+  case GLBREF:
+   grp = xlhs->ru.grp;    
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+   /* FALLTHRU */
+  case ID:
+   np = xlhs->lu.sy->el.enp;
+   /* this add the changed wire to nchglst if needed */
+   if (np->frc_assgn_allocated)
+    {
+     /* return F if all of wire forced, nothing to do */ 
+     if (!__correct_forced_newwireval(np, ap, bp))
+      { if (nd_itpop) __pop_itstk(); return; }
+    }
+   /* SJM 03/15/01 - change to fields in net record */
+   if (np->nchg_nd_chgstore) __chg_st_val(np, ap, bp);
+   else __st_val(np, ap, bp);
+
+   if (nd_itpop) __pop_itstk();
+   break;
+  case LSB:
+   /* for now first determine if array index */
+   idndp = xlhs->lu.x;
+   ndx1 = xlhs->ru.x;
+   np = idndp->lu.sy->el.enp;
+   /* the 1 bit is forced nothing to do else normal assign */
+   if (np->frc_assgn_allocated
+    && __forced_inhibit_bitassign(np, idndp, ndx1)) return;
+   __assign_to_bit(np, idndp, ndx1, ap, bp);
+   break;
+  case PARTSEL:
+   idndp = xlhs->lu.x;
+   np = idndp->lu.sy->el.enp;
+   ri1 = (int32) __contab[xlhs->ru.x->lu.x->ru.xvi];
+   ri2 = (int32) __contab[xlhs->ru.x->ru.x->ru.xvi];
+
+   /* if all bits of lhs part select range forced, do not do assign */
+   /* this also update ap and bp to include forced values */
+   if (np->frc_assgn_allocated
+    && !forced_assign_to_psel(idndp, ri1, ri2, np, ap, bp)) return;
+
+   /* know part select here in range and converted to h:0 index form */ 
+   __assign_to_psel(idndp, ri1, ri2, np, ap, bp);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ /* DBG remove --- */
+ if (__debug_flg && __ev_tracing) trace_conta_assign(xlhs, ap, bp);
+ /* --- */
+}
+
+/*
+ * trace conta assign
+ */
+static void trace_conta_assign(struct expr_t *xlhs, word32 *ap, word32 *bp)
+{
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (xlhs->x_stren) __st_regab_tostr(s1, (byte *) ap, xlhs->szu.xclen);
+ else __regab_tostr(s1, ap, bp, xlhs->szu.xclen, BHEX, FALSE);
+ /* SJM 08/24/03 - printing chg state wrong since this is not chg */
+ __tr_msg("## declarative assign to %s (itree=%s) value %s\n",
+  __msgexpr_tostr(s2, xlhs), __msg2_blditree(s3, __inst_ptr), s1);
+}
+
+/*
+ * correct an entire wire about to be assigned value for forced bits
+ * if no assign needed return F else T
+ * must be called from correct itree location
+ * know has qcval or will not get here
+ * this does not leave anything on stack 
+ */
+extern int32 __correct_forced_newwireval(struct net_t *np, word32 *ap, word32 *bp) 
+{
+ register int32 bi, ibase, wi;
+ int32 nd_assign, wlen;
+ byte *sbp, *sbp2;
+ struct xstk_t *xsp, *xsp2;
+  
+ /* if scalar or 1 bit only, no correction but maybe skip assign */ 
+ if (!np->n_isavec)
+  {
+   if (np->nu2.qcval[__inum].qc_active) return(FALSE);
+   return(TRUE);
+  }
+ ibase = __inum*np->nwid;
+ if (np->n_stren)
+  {
+   sbp = (byte *) ap;
+   get_stwire_addr_(sbp2, np);
+   /* trick is to replace forced bits so new assign is same as forced val */
+   for (nd_assign = FALSE, bi = 0; bi < np->nwid; bi++)
+    {
+     /* some bits not forced - so need assign */
+     if (np->nu2.qcval[ibase + bi].qc_active) sbp[bi] = sbp2[bi];
+     else nd_assign = TRUE;
+    }
+   return(nd_assign);
+  }
+
+ push_xstk_(xsp, np->nwid);
+ __bld_forcedbits_mask(xsp->ap, np);
+ zero_allbits_(xsp->bp, np->nwid); 
+ 
+ /* if all bits forced nothing to do */
+ if (__vval_is1(xsp->ap, np->nwid)) { __pop_xstk(); return(FALSE); }
+ /* if no bits forced, just assign ap */
+ if (vval_is0_(xsp->ap, np->nwid)) { __pop_xstk(); return(TRUE); }
+
+ /* only load wire if some bits forced */
+ push_xstk_(xsp2, np->nwid);
+ __ld_wire_val(xsp2->ap, xsp2->bp, np);
+
+ /* take new value and merge in some forced bits */
+ wlen = wlen_(np->nwid);    
+ for (wi = 0; wi < wlen; wi++)
+  {
+   /* remove forced bits from new value */
+   ap[wi] &= ~(xsp->ap[wi]);
+   bp[wi] &= ~(xsp->ap[wi]);
+   /* remove non forced bits from new wire */
+   xsp2->ap[wi] &= (xsp->ap[wi]);
+   xsp2->bp[wi] &= (xsp->ap[wi]);
+   /* combine old maybe forced bits into new value - so will be same */  
+   ap[wi] |= (xsp2->ap[wi]);
+   bp[wi] |= (xsp2->ap[wi]);
+  }
+ __pop_xstk();
+ __pop_xstk();
+ return(TRUE);
+}
+
+/*
+ * convert the per bit forced table to a per bit forced vector 
+ */
+extern void __bld_forcedbits_mask(word32 *ap, struct net_t *np)
+{
+ register int32 bi;
+ int32 ibase;
+
+ zero_allbits_(ap, np->nwid); 
+ /* build mask in ap part with 1 for every forced bit */ 
+ ibase = __inum*np->nwid;
+ for (bi = 0; bi < np->nwid; bi++)
+  {
+   if (np->nu2.qcval[ibase + bi].qc_active) __lhsbsel(ap, bi, 1L);
+  }
+}
+
+/*
+ * schedule assignment of all bits from wire that is lhs of conta
+ * processing conta assign event - this delays wire value change
+ */
+static void sched_conta_assign(struct expr_t *xlhs, register word32 *ap, 
+ register word32 *bp)
+{
+ int32 nd_itpop;
+ byte *sbp;
+ struct gref_t *grp;
+ struct net_t *np;
+
+ nd_itpop = FALSE;
+ switch ((byte) xlhs->optyp) {
+  case GLBREF:
+   grp = xlhs->ru.grp;    
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+   /* FALLTHRU */
+  case ID:
+   np = xlhs->lu.sy->el.enp;
+   if (np->nu.rngdwir->n_delrep == DT_PTHDST)
+    {
+     if (np->n_stren)
+      {
+       sbp = (byte *) ap;
+       __pth_stren_schd_allofwire(np, sbp, xlhs->szu.xclen);
+      }
+     else __pth_schd_allofwire(np, ap, bp, xlhs->szu.xclen);
+    }
+   else
+    {
+     if (np->n_stren)
+      {
+       sbp = (byte *) ap;
+       __wdel_stren_schd_allofwire(np, sbp, xlhs->szu.xclen);
+      }
+     else __wdel_schd_allofwire(np, ap, bp, xlhs->szu.xclen);
+    }
+   if (nd_itpop) __pop_itstk();
+   break;
+  case LSB:
+   np = xlhs->lu.x->lu.sy->el.enp;
+   schedassign_to_bit(np, xlhs->lu.x, xlhs->ru.x, ap, bp);
+   break;
+  case PARTSEL:
+   schedassign_to_psel(xlhs, ap, bp);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * convert conta where lhs is strength wire to strength form
+ * trick here is that conta always eats strength and maybe generates its own
+ */
+extern void __rem_stren(word32 *ap, word32 *bp, byte *sbp, int32 blen)
+{
+ register int32 bi, bi2, wi;
+ int32 wlen, ubits;   
+ word32 aw, bw;
+
+ wlen = wlen_(blen);
+ if ((ubits = ubits_(blen)) == 0) ubits = WBITS;
+ for (bi2 = blen - 1, wi = wlen - 1; wi >= 0; wi--)
+  { 
+   aw = bw = 0L;
+   for (bi = ubits - 1; bi >= 0; bi--, bi2--)   
+    {
+     aw |= ((sbp[bi2] & 1L) << bi);
+     bw |= (((sbp[bi2] & 2L) >> 1) << bi);
+    }
+   ap[wi] = aw;
+   bp[wi] = bw;
+   ubits = WBITS;
+  }
+} 
+
+/*
+ * INTERMEDIATE WIRE SCHEDULING ROUTINES
+ */
+
+/*
+ * schedule an entire non strength wire with delay
+ * this always requires z extension
+ *
+ * blen here is real not 4x too big
+ */
+extern void __pth_schd_allofwire(struct net_t *np, register word32 *ap,
+ register word32 *bp, int32 blen)
+{
+ register int32 bi;
+ register word32 aval, bval;
+ word32 av, bv;
+
+ if (!np->n_isavec)
+  {
+   aval = ap[0] | (bp[0] << 1);
+   /* must load wire value here in case packed */
+   __ld_wire_val(&av, &bv, np);
+   av |= (bv << 1);
+   /* must pass index of 0, since only bit is 0th here */
+   schd_1pthwirebit(np, 0, aval, av);
+   return;
+  }
+ 
+ /* case 1: same or truncate */
+ if (blen >= np->nwid)
+  {
+   for (bi = 0; bi < blen; bi++)
+    {
+     aval = rhsbsel_(ap, bi);
+     bval = rhsbsel_(bp, bi);
+     aval |= (bval << 1);
+     __ld_bit(&av, &bv, np, bi); 
+     schd_1pthwirebit(np, bi, aval, (av | (bv << 1)));
+    }
+   return;
+  }
+ /* case 2: widen rhs */
+ for (bi = 0; bi < blen; bi++)
+  {
+   aval = rhsbsel_(ap, bi);
+   bval = rhsbsel_(bp, bi);
+   aval |= (bval << 1);
+   __ld_bit(&av, &bv, np, bi); 
+   schd_1pthwirebit(np, bi, aval, (av | (bv << 1)));
+  }
+ for (bi = blen; bi < np->nwid; bi++)
+  {
+   __ld_bit(&av, &bv, np, bi); 
+   schd_1pthwirebit(np, bi, (word32) 2, (av | (bv << 1)));
+  }
+}
+
+/*
+ * schedule an entire non strength delay with wire
+ * this always requires z extension
+ * ap/bp is new value to assign
+ *
+ * blen here is real not 4x too big
+ */
+extern void __wdel_schd_allofwire(struct net_t *np, register word32 *ap,
+ register word32 *bp, int32 blen)
+{
+ register int32 bi;
+ register word32 aval, bval;
+ word32 av, bv;
+
+ if (!np->n_isavec)
+  {
+   aval = ap[0] | (bp[0] << 1);
+   /* must load wire value here in case packed */
+   __ld_wire_val(&av, &bv, np);
+   av |= (bv << 1);
+   /* must pass index of 0, since only bit is 0th here */
+   __wdel_schd_1wirebit(np, 0, aval, av, FALSE);
+   return;
+  }
+ 
+ /* case 1: same or truncate */
+ if (blen >= np->nwid)
+  {
+   for (bi = 0; bi < blen; bi++)
+    {
+     aval = rhsbsel_(ap, bi);
+     bval = rhsbsel_(bp, bi);
+     aval |= (bval << 1);
+     __ld_bit(&av, &bv, np, bi); 
+     __wdel_schd_1wirebit(np, bi, aval, (av | (bv << 1)), FALSE);
+    }
+   return;
+  }
+ /* case 2: widen rhs */
+ for (bi = 0; bi < blen; bi++)
+  {
+   aval = rhsbsel_(ap, bi);
+   bval = rhsbsel_(bp, bi);
+   aval |= (bval << 1);
+   __ld_bit(&av, &bv, np, bi); 
+   __wdel_schd_1wirebit(np, bi, aval, (av | (bv << 1)), FALSE);
+  }
+ for (bi = blen; bi < np->nwid; bi++)
+  {
+   __ld_bit(&av, &bv, np, bi); 
+   __wdel_schd_1wirebit(np, bi, (word32) 2, (av | (bv << 1)), FALSE);
+  }
+}
+
+/* table (copied in other places) to convert from cap to 6 bit stren */
+/* 0 is impossible any error caught before here */
+word32 __cap_to_stren[] = { 0, 0x24, 0x48, 0x90 }; 
+
+/*
+ * schedule an entire strength path delay wire
+ * this always requires z extension
+ *
+ * blen here is real not 4x too big
+ * this handles change from z to previous value plus cap. size
+ * never see trireg here since cannot be path destination
+ */
+extern void __pth_stren_schd_allofwire(struct net_t *np, register byte *sbp,
+ int32 sblen)
+{
+ register int32 bi;
+ register byte *sbp2;
+
+ /* DBG remove --- */
+ if (np->ntyp == N_TRIREG) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* get strength wire address */
+ get_stwire_addr_(sbp2, np);
+ if (!np->n_isavec)
+  {
+   schd_1pthwirebit(np, 0, (word32) sbp[0], (word32) sbp2[0]);
+   return;
+  }
+
+ /* case 1: same or truncate */
+ if (sblen >= np->nwid)
+  {
+   for (bi = 0; bi < np->nwid; bi++)
+    schd_1pthwirebit(np, bi, (word32) sbp[bi], (word32) sbp2[bi]);
+   return;
+  }
+ /* case 2: widen rhs */
+ for (bi = 0; bi < sblen; bi++)
+  schd_1pthwirebit(np, bi, (word32) sbp[bi], (word32) sbp2[bi]);
+ for (bi = sblen; bi < np->nwid; bi++)
+  schd_1pthwirebit(np, bi, (word32) 2, (word32) sbp2[bi]); 
+}
+
+/*
+ * schedule an entire strength wire with delay
+ * this always requires z extension
+ *
+ * blen here is real not 4x too big
+ * this handles change from z to previous value plus cap. size
+ *
+ * this is only place need to schedule trireg decay since trireg always fi>1
+ * non fi>1 lhs select assigns only for non fi>1
+ */
+extern void __wdel_stren_schd_allofwire(struct net_t *np, register byte *sbp,
+ int32 sblen)
+{
+ register int32 bi;
+ register byte *sbp2;
+
+ /* get strength wire address */
+ get_stwire_addr_(sbp2, np);
+
+ if (np->ntyp == N_TRIREG) 
+  {
+   int32 tr_decay;
+   byte ntrival;
+   word64 ndel;
+
+   /* DBG remove ---
+   if (np->nwid != sblen) __misc_terr(__FILE__, __LINE__);
+   --- */
+   for (bi = 0; bi < np->nwid; bi++)
+    {
+     if (sbp[bi] == ST_HIZ)
+      {
+       /* immediately assign the cap. size strength (same old value) */ 
+       ntrival = (sbp2[bi] & 3) | __cap_to_stren[np->n_capsiz];
+       if (ntrival != sbp2[bi])
+        {
+         sbp2[bi] = ntrival;
+         /* since otherwise scheduling must indicate immed. net changed */
+         /* also schedule decay */
+         record_sel_nchg_(np, bi, bi);
+        }
+       /* schedule decay to cap. size x value change if z delay not 0 */
+       /* trireg charge decay time is third to-z delay - 0 means never */
+       /* decays to z */
+       __new_gateval = 2;
+       __old_gateval = sbp2[bi];
+       /* index in get_del removes any indexing */
+       __get_del(&ndel, np->nu.rngdwir->n_du, np->nu.rngdwir->n_delrep);
+       if (ndel == 0ULL) continue;
+       sbp[bi] = 3 | __cap_to_stren[np->n_capsiz];
+       tr_decay = TRUE;
+      }
+     /* use normal to 0, 1, or x delay if not all z drivers of bit */ 
+     else tr_decay = FALSE;
+     __wdel_schd_1wirebit(np, bi, (word32) sbp[bi], (word32) sbp2[bi], tr_decay);
+    }
+   return; 
+  }
+
+ if (!np->n_isavec)
+  {
+   __wdel_schd_1wirebit(np, 0, (word32) sbp[0], (word32) sbp2[0], FALSE);
+   return;
+  }
+
+ /* case 1: same or truncate */
+ if (sblen >= np->nwid)
+  {
+   for (bi = 0; bi < np->nwid; bi++)
+    __wdel_schd_1wirebit(np, bi, (word32) sbp[bi], (word32) sbp2[bi], FALSE);
+   return;
+  }
+ /* case 2: widen rhs */
+ for (bi = 0; bi < sblen; bi++)
+  __wdel_schd_1wirebit(np, bi, (word32) sbp[bi], (word32) sbp2[bi], FALSE);
+ for (bi = sblen; bi < np->nwid; bi++)
+  __wdel_schd_1wirebit(np, bi, (word32) 2, (word32) sbp2[bi], FALSE); 
+}
+
+/*
+ * ROUTINES TO SCHEDULE AND PROCESS WIRE EVENTS - ALWAYS BIT BY BIT
+ */
+
+/*
+ * schedule a 1 bit wire change - know wire has delay to get here 
+ *
+ * no spike analysis because even though inertial modeling here 
+ * wires do not switch
+ *
+ * this works for both strength 8 bit nval and oval and non strength
+ * if scalar biti must be 0 (i.e. biti can not be -1)
+ * nval is new value to schedule change to, old value is current wire value
+ *
+ * for trireg - if nval is weak previous, ndselval is 2 and nval for 
+ * all z drivers is built cap. stren plus current value
+ */
+extern void __wdel_schd_1wirebit(register struct net_t *np, register int32 biti,
+ register word32 nval, register word32 oval, int32 tr_decay)
+{
+ word64 ndel, schtim;
+ i_tev_ndx tevpi, *itevpi;
+ struct tev_t *tevp;
+ struct rngdwir_t *dwirp; 
+
+ if (__ev_tracing)
+  { evtr_wdel_schd_1wirebit(np, biti, nval, oval, tr_decay); return; }
+
+ dwirp = np->nu.rngdwir;
+ itevpi = &(dwirp->wschd_pbtevs[np->nwid*__inum]); 
+ tevpi = itevpi[biti];
+
+ /* since always use last changed value, if last same as current */
+ /* because gate style spike nothing to do since already right value */   
+ if (tevpi == -1 && nval == oval) return;
+
+ /* get delay and if path delay immediate (distributed longer) store */
+ /* globals must be set for get del routine */
+ __old_gateval = oval;
+ /* notice new gateval is not value set but to-z needed for get del */
+ __new_gateval = (tr_decay) ? 2 : nval;
+
+ /* normal wire delay */
+ /* notice old and new gate values always set before here */
+ __get_del(&ndel, dwirp->n_du, dwirp->n_delrep);
+ schtim = __simtime + ndel;
+
+ if (tevpi == -1)
+  {
+   /* if nothing pending can just schedule */
+   __schedule_1wev(np, biti, TE_WIRE, ndel, schtim, nval, itevpi, tr_decay);
+   return;
+  }
+ tevp = &(__tevtab[tevpi]);
+ /* DBG remove -- */
+ if (tevp->tetyp != TE_WIRE) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* there is a pending unmatured event */
+ /* case 1: real pulse (aka spike or glitch) just cancel */ 
+ if (nval == oval)
+  {
+   /* cancel */
+   __cancel_1wev(tevp);
+   itevpi[biti] = -1;
+  }
+ /* this handles cancel too */
+ else __reschedule_1wev(tevpi, nval, ndel, schtim, itevpi);
+} 
+
+/*
+ * trace version sched 1 bit wire change - know wire has delay to get here 
+ *
+ * no spike analysis but normal inertial rescheduling
+ * this works for both strength 8 bit nval and oval and non strength
+ *
+ * for trireg - if nval is weak previous, ndselval is 2 and nval for 
+ * all z drivers is built cap. stren plus current value
+ */
+static void evtr_wdel_schd_1wirebit(register struct net_t *np,
+ register int32 biti, register word32 nval, register word32 oval, int32 tr_decay)
+{
+ word32 is_stren;
+ i_tev_ndx tevpi, *itevpi;
+ word64 ndel, schtim;
+ struct tev_t *tevp;
+ struct rngdwir_t *dwirp; 
+ char s1[RECLEN], vs1[10], vs2[10], vs3[10];
+
+ dwirp = np->nu.rngdwir;
+ itevpi = &(dwirp->wschd_pbtevs[np->nwid*__inum]); 
+ tevpi = itevpi[biti];
+ is_stren = np->n_stren;
+
+ /* if no change and do not need schedule time for cancel, done */
+ __tr_msg("-- delayed wire %s changed:\n",
+  __to_evtrwnam(__xs, np, biti, biti, __inst_ptr));
+
+ /* since always use last changed value, if last same as current */
+ /* because gate style spike nothing to do since already right value */   
+ if (tevpi == -1 && nval == oval)
+  {
+   __tr_msg(" NOPEND, NOCHG <OV=%s>\n", __to_vnam(vs1, is_stren, nval));
+   return;
+  }
+
+ /* get delay and if path delay immediate (distributed longer) store */
+ /* these globals must be set for get del routine */
+ __new_gateval = (tr_decay) ? 2 : nval;
+ __old_gateval = oval;
+ /* normal wire delay */
+ /* notice old and new gate values always set before here */
+ __get_del(&ndel, dwirp->n_du, dwirp->n_delrep);
+ schtim = __simtime + ndel; 
+
+ if (tevpi == -1)
+  {
+   __tr_msg(" SCHD AT %s <OV=%s, NSV=%s>\n",
+    __to_timstr(s1, &schtim), __to_vnam(vs1, is_stren, oval),
+    __to_vnam(vs2, is_stren, nval));
+   /* if nothing pending can just schedule */
+   __schedule_1wev(np, biti, TE_WIRE, ndel, schtim, nval, itevpi,
+    tr_decay);
+   return;
+  }
+
+ tevp = &(__tevtab[tevpi]);
+ /* DBG remove -- */
+ if (tevp->tetyp != TE_WIRE) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* pending event - no spike analysis but inertial reschedule */
+ /* current driving and schedule same causes scheduled to be removed since */
+ /* output value correct */
+ if (nval == oval)
+  {
+   __tr_msg(" PENDING EVENT, SAME <OV=NSV=%s, OSV=%s AT %s CANCEL>\n",
+    __to_vnam(vs1, is_stren, nval), __to_vnam(vs2, is_stren, oval), 
+    __to_timstr(s1, &schtim));
+
+   /* cancel */
+   __cancel_1wev(tevp);
+   itevpi[biti] = -1;
+  }
+ else
+  {
+   __tr_msg(
+    " PENDING EVENT, RESCHD <OV=%s, OSV=%s AT %s, NSV=%s AT %s REPLACES>\n",
+    __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren,
+    (word32) tevp->outv), __to_timstr(s1, &(tevp->etime)), __to_vnam(vs3,
+    is_stren, nval), __to_timstr(__xs, &schtim));
+
+   __reschedule_1wev(tevpi, nval, ndel, schtim, itevpi);
+  }
+} 
+
+/*
+ * schedule a 1 bit path delay 
+ *
+ * implements show cancel e analysis including non path distributed delay
+ *
+ * this works for both strength 8 bit nval and oval and non strength
+ * if scalar biti must be 0 (i.e. biti can not be -1)
+ * nval is new value to schedule change to, old value is current wire value
+ */
+static void schd_1pthwirebit(register struct net_t *np, register int32 biti,
+ register word32 nval, register word32 oval) 
+{
+ word32 is_stren;
+ word64 schtim;
+ i_tev_ndx tevpi, *itevpi;
+ struct tev_t *tevp;
+ struct rngdwir_t *dwirp; 
+ struct pthdst_t *pdp;
+ 
+ if (__ev_tracing)
+  {
+   evtr_schd_1pthwirebit(np, biti, nval, oval);
+   return;
+  }
+ dwirp = np->nu.rngdwir;
+ itevpi = &(dwirp->wschd_pbtevs[np->nwid*__inum]); 
+ tevpi = itevpi[biti];
+
+ /* since always use last changed value, if last same as current */
+ /* because gate style glitch nothing to do since already right value */   
+ if (tevpi == -1 && nval == oval)
+  return;
+
+ /* DBG remove --
+ if (tevpi != -1 && __tevtab[tevpi].tetyp != TE_WIRE)
+  __misc_terr(__FILE__, __LINE__);
+ --- */
+
+ /* these globals must be set for get del routine */
+ is_stren = (word32) np->n_stren;
+ __new_gateval = nval;
+ __old_gateval = oval;
+ /* possible for some bits to not be path destinations - just immed assign */
+ /* SJM 11/24/00 - if values same won't find path or delay since need */
+ /* transition */
+ if (nval != oval) 
+  {
+   if ((pdp = __get_path_del(dwirp, biti, &schtim)) == NULL)   
+    {
+     if (is_stren) __chg_st_bit(np, biti, nval, 0L);
+     else __chg_st_bit(np, biti, nval & 1L, (nval >> 1) & 1L);
+     return;
+    }
+  }
+ else { pdp = NULL; schtim = 0ULL; }
+
+ /* special case 0 - distributed delay longer - immediate assign */
+ /* normal cause is path (probably from multiple input final driving gate) */
+ /* that has not path delay on it - this may be ok */
+ if (pdp != NULL && schtim <= __simtime)
+  {
+   /* problem with modeling - distributed delay longer than path */
+   if (!__no_informs) __emit_path_distinform(np, pdp, &__pdmindel);
+
+   /* modeling anomally style spike possible - know immed. assign earlier */ 
+   if (tevpi != -1)
+    {
+     tevp = &(__tevtab[tevpi]);
+
+     if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+      __emit_path_pulsewarn(pdp, tevp, &(tevp->etime), NULL,
+       "distributed longer or path destination driver unstable",
+       is_stren);
+     /* always cancel pending */
+     __cancel_1wev(tevp);
+     itevpi[biti] = -1;
+
+     /* this is same for on detect and on event */
+     if (__show_cancel_e)
+      {
+       /* this is special case where immediate assign must be to x */ 
+       /* and cancel future event that can be scheduled for now */
+set_on_detect_x:
+       if (is_stren) __chg_st_bit(np, biti, (word32) ST_STRONGX, 0L);
+       else __chg_st_bit(np, biti, 1L, 1L);
+       return;
+      }
+     /* if no show canceled e, just assign */  
+    }
+
+   if (is_stren) __chg_st_bit(np, biti, nval, 0L);
+   else __chg_st_bit(np, biti, nval & 1L, (nval >> 1) & 1L);
+   return;
+  }
+
+ /* no pending event - know nval not = oval or will not get here */
+ if (tevpi == -1)
+  {
+   /* because no pending event must be different */
+   __schedule_1wev(np, biti, TE_WIRE, __pdmindel, schtim, nval, itevpi,
+    FALSE);
+   return;
+  }    
+
+ /* pending event */
+ /* new and old same but know scheduled different - classic pulse/glitch */
+ tevp = &(__tevtab[tevpi]);
+ if (nval == oval)
+  {
+   /* spike analysis, know scheduled different - tell user */
+   /* this is classical spike analysis */
+   /* do not have delay to use to select pa0th */  
+   if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+    {
+     __emit_path_samewarn(np, biti, tevp, &(tevp->etime), "pulse", is_stren);
+    }
+
+   /* if spike, suppress future but schedule to x at currently scheduled */
+   if (__show_cancel_e)
+    {
+     if (__showe_onevent) { tevp->outv = (is_stren) ? ST_STRONGX : 3; return; }
+     __cancel_1wev(tevp);
+     itevpi[biti] = -1;
+     goto set_on_detect_x;
+    }
+   /* remove pulse */
+   __cancel_1wev(tevp);
+   itevpi[biti] = -1;
+   return;
+  }
+ /* SJM 11/24/00 - now know has pdp delay since old and new not same */
+
+ /* new schedule to same value case */
+ /* here delay can be different because different path selected */
+ /* and maybe other reasons */
+ /* done silently here - trace message only below */
+ if (tevp->outv == (byte) nval) return;
+
+ /* inertial reschedule */
+ if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+  __emit_path_pulsewarn(pdp, tevp, &(tevp->etime), &schtim, "unstable",
+   is_stren);   
+
+ /* easy show cancel (set to x case) - no new event may or may not switch */
+ if (__show_cancel_e)
+  {
+   /* LOOKATME - maybe need to check old tevp and new schd time and if 2nd */
+   /* input change results in earlier edge cancel and schedule earlier */
+   if (__showe_onevent)
+    { tevp->outv = (is_stren) ? ST_STRONGX : 3; return; }
+
+   /* remove pulse */
+   __cancel_1wev(tevp);
+   itevpi[biti] = -1;
+   goto set_on_detect_x;
+  }
+ /* inertial reschedule, this handles cancel if needed */
+ __reschedule_1wev(tevpi, nval, __pdmindel, schtim, itevpi);
+}
+
+/*
+ * trace version - schedule a 1 bit path delay 
+ *
+ * schedule a 1 bit path delay change 
+ *
+ * show cancel e analysis including non path distributed delay
+ *
+ * this works for both strength 8 bit nval and oval and non strength
+ * if scalar biti must be 0 (i.e. biti can not be -1)
+ * nval is new value to schedule change to, old value is current wire value
+ */
+static void evtr_schd_1pthwirebit(register struct net_t *np, register int32 biti,
+ register word32 nval, register word32 oval) 
+{
+ word32 is_stren;
+ word32 outval;
+ word64 schtim, distdel, tevptim;
+ i_tev_ndx tevpi, *itevpi;
+ struct tev_t *tevp;
+ struct rngdwir_t *dwirp; 
+ struct pthdst_t *pdp;
+ struct spcpth_t *pthp;
+ char s1[RECLEN], s2[RECLEN], vs1[10], vs2[10], vs3[10];
+
+ is_stren = np->n_stren;
+ dwirp = np->nu.rngdwir;
+ itevpi = &(dwirp->wschd_pbtevs[np->nwid*__inum]); 
+ tevpi = itevpi[biti];
+
+ if (tevpi != -1)
+  {
+   /* DBG remove -- */
+   if (__tevtab[tevpi].tetyp != TE_WIRE) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   strcpy(s1, " (pending event)");
+  }
+ else strcpy(s1, "");
+
+ /* if no change and do not need schedule time for cancel, done */
+ __tr_msg("-- path delay destination %s driver change%s now %s:\n",
+  __to_evtrwnam(__xs, np, biti, biti, __inst_ptr), s1,
+  __to_timstr(__xs2, &__simtime));
+
+ /* since always use last changed value, if last same as current */
+ /* because gate style glitch nothing to do since already right value */   
+ if (tevpi == -1 && nval == oval)
+  {
+   __tr_msg(" PATHDEL, NOCHG <OV=%s> now %s\n",
+    __to_vnam(vs1, is_stren, nval), __to_timstr(__xs, &__simtime));
+   return;
+  }
+
+ /* these globals must be set for get del routine */
+ __new_gateval = nval;
+ __old_gateval = oval;
+ 
+ if (nval != oval)
+  {
+   /* possible for some bits to not be path desitinations - just immed assign */
+   if ((pdp = __get_path_del(dwirp, biti, &schtim)) == NULL)   
+    {
+     __tr_msg(" BIT %d NOT PATH DEST: IMMED ASSIGN <OV=%s, NV=%s>\n",
+      biti, __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren, nval));
+
+     if (is_stren) __chg_st_bit(np, biti, nval, 0L);
+     else __chg_st_bit(np, biti, nval & 1L, (nval >> 1) & 1L);
+     return;
+    } 
+   pthp = pdp->pstchgp->chgu.chgpthp;
+   __tr_msg(" PATH (at line %s) SRC CHG TIME %s\n",
+    __bld_lineloc(s1, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt),
+    __to_timstr(__xs, &__pdlatechgtim));
+  }
+ else { pdp = NULL; schtim = 0ULL; }
+
+
+ /* special case 0 - distributed delay longer - immediate assign */
+ if (pdp != NULL && schtim <= __simtime)
+  {
+   /* problem with modeling - distributed delay longer than path */
+   /* or changed path has no path delay */
+   if (!__no_informs) __emit_path_distinform(np, pdp, &__pdmindel);
+
+   /* modeling anomally style spike possible - know immed. assign earlier */ 
+   if (tevpi != -1)
+    {
+     tevp = &(__tevtab[tevpi]);
+     if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+      __emit_path_pulsewarn(pdp, tevp, &(tevp->etime), NULL,
+       "distributed longer or path destination driver unstable",
+       is_stren);
+
+     outval = (word32) tevp->outv;
+     tevptim = tevp->etime;
+     /* always cancel pending */
+     __cancel_1wev(tevp);
+     itevpi[biti] = -1;
+
+     /* this is same for on detect and on event since immed. assign */
+     if (__show_cancel_e)
+      {
+       /* this is special case where immediate assign must be to x */ 
+       /* and cancel future event that can be scheduled for now */
+       __tr_msg(
+        " PATH, DIST DELAY PULSE <OV=%s, OSV=%s at %s NV=%s SHOWING X FROM NOW>\n",
+        __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren, outval),
+        __to_timstr(s1, &tevptim), __to_vnam(vs3, is_stren, nval));
+
+set_on_detect_x:
+       if (is_stren) __chg_st_bit(np, biti, (word32) ST_STRONGX, 0L);
+       else __chg_st_bit(np, biti, 1L, 1L);
+       return;
+      }
+     __tr_msg(
+      " PATH, DIST DELAY PULSE <OV=%s, OSV=%s at %s - NV=%s ASSIGN AND CANCEL>\n",
+      __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren, outval),
+      __to_timstr(s1, &tevptim), __to_vnam(vs3, is_stren, nval));
+     if (is_stren) __chg_st_bit(np, biti, nval, 0L);
+     else __chg_st_bit(np, biti, nval & 1L, (nval >> 1) & 1L);
+     return; 
+    }
+   /* no pending event store - know must be different */
+   distdel = __simtime - __pdlatechgtim;
+   __tr_msg(
+    " DIST DELAY %s LONGER THAN PATH %s: IMMED ASSIGN <OV=%s, NV=%s>\n",
+    __to_timstr(__xs2, &distdel), __to_timstr(s1, &__pdmindel), 
+    __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren, nval));
+   if (is_stren) __chg_st_bit(np, biti, nval, 0L);
+   else __chg_st_bit(np, biti, nval & 1L, (nval >> 1) & 1L);
+   return;
+  }
+
+ /* real path delay */
+ /* case 1: no pending event - know have different new value */
+ if (tevpi == -1)
+  {
+   /* because no pending event must be different */
+   __tr_msg(" PATH DEL, SCHD AT %s <OV=%s, NSV=%s>\n",
+    __to_timstr(s1, &schtim), __to_vnam(vs1, is_stren, oval),
+    __to_vnam(vs2, is_stren, nval));
+   __schedule_1wev(np, biti, TE_WIRE, __pdmindel, schtim, nval,
+    itevpi, FALSE);
+   return;
+  }    
+
+ /* pending event */
+ tevp = &(__tevtab[tevpi]);
+ /* new and old same but know scheduled different - classic pulse/glitch */
+ if (nval == oval)
+  {
+   /* show cancel e analysis, know scheduled different - tell user */
+   /* this is classical spike analysis */
+   if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+    {
+     __emit_path_samewarn(np, biti, tevp, &(tevp->etime), "pulse", is_stren);
+    }
+
+   /* if spike, suppress future but schedule to x at currently scheduled */
+   if (__show_cancel_e)
+    {
+     if (__showe_onevent) sprintf(s1, "%s (on event)", __to_timstr(__xs,
+      &(tevp->etime)));
+     else sprintf(s1, "%s (on detect)", __to_timstr(__xs, &__simtime));
+
+     /* LOOKATME - think on event pulse should use schedule if earlier? */
+     __tr_msg(
+      " PATH DEL, PEND AT %s, PULSE <OV=NSV=%s, OSV=%s SHOWING X FROM %s>\n",
+      __to_timstr(__xs, &(tevp->etime)), __to_vnam(vs1, is_stren, oval),
+      __to_vnam(vs2, is_stren, (word32) tevp->outv), s1);
+
+     if (__showe_onevent)
+      { tevp->outv = (is_stren) ? ST_STRONGX : 3; return; }
+
+     /* cancel pending */
+     __cancel_1wev(tevp);
+     itevpi[biti] = -1;
+     goto set_on_detect_x;
+    }
+   /* remove pulse */
+   __tr_msg(" PATH DEL, PEND, PULSE, INERTIAL CANCEL AT %s <OV=%s, OSV=%s>\n",
+    __to_timstr(s1, &(tevp->etime)), __to_vnam(vs1, is_stren, oval),
+    __to_vnam(vs2, is_stren, (word32) tevp->outv));
+   /* no spike, but newly scheduled to same so no event - cancel */
+   __cancel_1wev(tevp);
+   itevpi[biti] = -1;
+   return;
+  }
+
+ /* new schedule to same value case - know have pdp and delay */
+ /* know that delay same and later so just discard new event */
+ /* done silently here - trace message only */
+ if (tevp->outv == (byte) __new_gateval)
+  {
+   __tr_msg(
+    " PATH DEL, MODEL ANOMALLY IGNORE SCHED TO SAME <OSV=NSV=%s> OLD AT %s NEW %s\n",
+    __to_vnam(vs1, is_stren, nval), __to_timstr(s1, &(tevp->etime)),
+    __to_timstr(s2, &schtim));
+   return;
+  }
+
+ /* inertial reschedule */
+ if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+  __emit_path_pulsewarn(pdp, tevp, &(tevp->etime), &schtim, "unstable",
+   is_stren);
+
+ /* easy show cancel (set to x case) - no new event may or may not switch */
+ if (__show_cancel_e)
+  {
+   if (__showe_onevent) sprintf(s2, "%s (on event)", __to_timstr(__xs,
+    &(tevp->etime)));
+   else sprintf(s2, "%s (on detect)", __to_timstr(__xs, &__simtime));
+
+   __tr_msg(
+    " PATH DEL, PEND AT %s, UNSTABLE <OV=%s, OSV=%s, NSV=%s SHOWING X FROM %s>\n",
+     __to_timstr(s1, &(tevp->etime)), __to_vnam(vs1, is_stren, oval),
+     __to_vnam(vs2, is_stren, (word32) tevp->outv), __to_vnam(vs3, is_stren,
+     nval), s2);
+   if (__showe_onevent)
+    { tevp->outv = (is_stren) ? ST_STRONGX : 3; return; }
+
+   __cancel_1wev(tevp);
+   itevpi[biti] = -1;
+   goto set_on_detect_x;
+  }
+
+ /* inertial reschedule, this handles cancel if needed */ 
+ __tr_msg(
+  " PATH DEL, PEND, UNSTABLE, INERTIAL RESCHD <OV=%s, OSV=%s AT %s, NSV=%s AT %s>\n",
+  __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren, (word32) tevp->outv),
+  __to_timstr(s1, &(tevp->etime)), __to_vnam(vs3, is_stren, nval),
+  __to_timstr(s2, &schtim)); 
+
+ __reschedule_1wev(tevpi, nval, __pdmindel, schtim, itevpi);
+}
+
+/*
+ * print a distributed delay longer than path warning
+ * normally caused by path not having path delay which is maybe ok
+ *
+ * algorithm for path delays is: 1) record path source changes, 2) only when
+ * destination changes (attempt to assign value to wire) schedule wire delay
+ * at src change time plus path delay, 3) if dest. assign to wire after
+ * time when path would have changed immediate assign with warning
+ * 
+ * this is questionable inform because happens when source change
+ * does not propagate to output
+ */
+extern void __emit_path_distinform(struct net_t *np, struct pthdst_t *pdp,
+ word64 *pdmindel)
+{
+ word64 distdel;
+ struct spcpth_t *pthp;
+ char s1[RECLEN], s2[RECLEN];
+
+ distdel = __simtime - __pdlatechgtim;
+ pthp = pdp->pstchgp->chgu.chgpthp;
+
+ __gfinform(470, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+  "path (in %s) distributed delay %s longer than path %s (path without path delay? or destination driver unstable) - storing %s",
+  __msg2_blditree(s1, __inst_ptr), __to_timstr(__xs, &distdel),  
+  __to_timstr(__xs2, pdmindel), __to_vnam(s2,
+  (unsigned) ((np->n_stren) ? TRUE : FALSE), (word32) __new_gateval));
+}
+
+/*
+ * emit path pulse warning if not turned off
+ */
+extern void __emit_path_pulsewarn(struct pthdst_t *pdp, struct tev_t *tevp,
+ word64 *etim, word64 *newetim, char *sptnam, word32 is_stren)
+{
+ struct spcpth_t *pthp;
+ char s1[RECLEN], s2[RECLEN], s3[10], s4[10], s5[10], s6[RECLEN];
+
+ /* must turn on spike analysis */
+ if (__show_cancel_e)
+  {
+   if (__showe_onevent) strcpy(s1, " - edge event to x");
+   else strcpy(s1, " - now detect to x");
+  }
+ else strcpy(s1, "");
+
+ sprintf(s2, "old %s, scheduled %s, new %s%s",
+  __to_vnam(s3, is_stren, (word32) __old_gateval), __to_vnam(s4, is_stren,
+  (word32) tevp->outv), __to_vnam(s5, is_stren, (word32) __new_gateval), s1);   
+
+ if (newetim == NULL) 
+  { sprintf(s6, "(edge at %s removed)", __to_timstr(__xs2, etim)); }
+ else 
+  {
+   sprintf(s6, "(edge at %s replaced by new at %s)",
+    __to_timstr(__xs, etim), __to_timstr(__xs2, newetim));
+  }
+ pthp = pdp->pstchgp->chgu.chgpthp;
+ /* notice spike means new and old the same */
+ __gfwarn(592, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+  "path (in %s) %s %s - %s", __msg2_blditree(s1, tevp->teitp), sptnam,
+ s6, s2);
+}
+
+/*
+ * emit path pulse warning for same value unstable (no new path)
+ */
+extern void __emit_path_samewarn(struct net_t *np, int32 biti,
+ struct tev_t *tevp, word64 *etim, char *sptnam, word32 is_stren)
+{
+ char s1[RECLEN], s2[RECLEN], s3[10], s4[10], s5[10], s6[RECLEN];
+
+ /* must turn on spike analysis */
+ if (__show_cancel_e)
+  {
+   if (__showe_onevent) strcpy(s1, " - edge event to x");
+   else strcpy(s1, " - now detect to x");
+  }
+ else strcpy(s1, "");
+
+ sprintf(s2, "old %s, scheduled %s, new %s%s",
+  __to_vnam(s3, is_stren, (word32) __old_gateval), __to_vnam(s4, is_stren,
+  (word32) tevp->outv), __to_vnam(s5, is_stren, (word32) __new_gateval), s1);   
+
+ sprintf(s1, "(edge at %s removed)", __to_timstr(__xs2, etim));
+
+ if (np->n_isavec) sprintf(s6, "%s %s[%d]", __to_ptnam(__xs, np->iotyp),
+  np->nsym->synam, biti);
+ else sprintf(s6, "%s %s", __to_ptnam(__xs, np->iotyp), np->nsym->synam);
+
+ /* notice spike means new and old the same */
+ __pv_warn(592, "path destination %s: %s %s - %s", s6, sptnam, s1, s2);
+}
+
+/*
+ * compute path delay and imputed schedule time (sets delay in global)
+ *
+ * caller determines action if immediate assign needed
+ * return nil for bit not path dest. (other bits are), pschtim not set
+ *
+ * rules for multiple paths with this destination
+ *  1) select latest change (inertial pattern - schedule with latest)
+ *  2) if 2 sources changed at same time use shortest path - open path end
+ *     spigot as soon possible
+ *
+ * this assumes globals __new_gateval and __old_gateval have out transition 
+ * do not need delay because here know never pnd0
+ * notice transition that selects delay here is output change 
+ *
+ * this finds last change path even though maybe no input changed and
+ * this is just path dest. change from non path delay cause
+ *
+ * LOOKATME - contrary to P1364 LRM, ifnone paths just like other paths
+ * in selecting path delays to use.  filtering for sdps done on input
+ * and because input changes may not propagate to output, if ifnone selected
+ * because latest change (and shortest delay if tie) must use - ifnone only
+ * used to distinguish exact ties in last change and delay time
+ */
+extern struct pthdst_t *__get_path_del(struct rngdwir_t *dwirp, int32 biti,
+ word64 *pschtim) 
+{
+ register struct pthdst_t *pdp, *latepdp;
+ register struct spcpth_t *latepthp, *newpthp;
+ word64 chgtim, newdel;
+
+ if ((pdp = dwirp->n_du.pb_pthdst[biti]) == NULL) return(NULL);
+
+ /* list of paths terminating on wire np is same for all insts */
+ __pdlatechgtim = pdp->pstchgp->lastchg[__inum];
+ latepdp = pdp;
+ latepthp = latepdp->pstchgp->chgu.chgpthp;
+ if (__pth_tracing || (__debug_flg && __ev_tracing))
+  prt_dbgpthtrmsg(latepthp, __pdlatechgtim);
+ __get_del(&__pdmindel, latepthp->pth_du, latepthp->pth_delrep);
+ /* common only 1 path ends on net case */ 
+ if ((pdp = pdp->pdnxt) == NULL)
+  {
+   *pschtim = __pdlatechgtim + __pdmindel;
+   return(latepdp);
+  }
+
+ /* complicated case where more than one path end on this dest. wire np */
+ for (;pdp != NULL; pdp = pdp->pdnxt)
+  {
+   /* get source change time */
+   chgtim = pdp->pstchgp->lastchg[__inum];
+   if (__pth_tracing || (__debug_flg && __ev_tracing))
+    prt_dbgpthtrmsg(pdp->pstchgp->chgu.chgpthp, chgtim);
+
+   /* case 1: change time earlier, always select latest */
+   if (chgtim < __pdlatechgtim) continue;
+    
+   newpthp = pdp->pstchgp->chgu.chgpthp;
+   __get_del(&newdel, newpthp->pth_du, newpthp->pth_delrep);
+
+   /* if change times are the same, use the shortest path */
+   if (chgtim == __pdlatechgtim)
+    {
+     if (newpthp->pth_ifnone && newdel == __pdmindel) continue;
+
+     /* newdel larger implies not shorter path, do not change */
+     /* if same try to replace since for ties must replace ifnone */ 
+     if (newdel > __pdmindel) continue;
+    }
+   /* this path's change time later(< handled above), just use */
+   else __pdlatechgtim = chgtim;
+
+   __pdmindel = newdel;
+   latepdp = pdp;
+   latepthp = newpthp;
+  }
+ *pschtim = __pdlatechgtim + __pdmindel;
+ return(latepdp);
+}
+
+/*
+ * print a debugging or path trace message
+ */
+static void prt_dbgpthtrmsg(struct spcpth_t *newpthp, word64 chgtim)
+{
+ word64 newdel;
+ char s1[RECLEN];
+
+ __get_del(&newdel, newpthp->pth_du, newpthp->pth_delrep);
+ __tr_msg("## path (line %s) last change %s delay %s.\n",
+  __bld_lineloc(__xs, newpthp->pthsym->syfnam_ind, newpthp->pthsym->sylin_cnt),
+  __to_timstr(__xs2, &chgtim), __to_timstr(s1, &newdel)); 
+}
+
+/*
+ * compute intermodule path delay and imputed schedule time 
+ * only called if at least one inter module interconnect path
+ *
+ * this assumes new and old gate vals glbs set
+ * using same algorithm as used for normal specify path delays 
+ * each inst/bit for mipd src-dst delays different (outside inst struct)
+ * LOOKATME - is this algorithm right for intra-module paths
+ */
+static void get_impth_del(word64 *pschtim, struct net_t *np, int32 bi,
+ struct mipd_t *mipdp)
+{
+ register struct impth_t *impdp;
+ word64 chgtim, newdel;
+  
+ impdp = mipdp->impthtab[__inum];
+ __pdlatechgtim = impdp->lastchg;
+ /* know delay is non IS since src-dst delays outside inst tree */
+ __get_del(&__pdmindel, impdp->impth_du, impdp->impth_delrep);
+
+ if (__pth_tracing || (__debug_flg && __ev_tracing))
+  { prt_dbgimpthtrmsg(np, bi, __pdlatechgtim, __pdmindel); } 
+
+ /* common only 1 path ends on net/bit case */ 
+ if ((impdp = impdp->impthnxt) == NULL)
+  {
+   *pschtim = __pdlatechgtim + __pdmindel;
+   return;
+  }
+
+ /* complicated case where more than one path end on this dest. wire np */
+ for (;impdp != NULL; impdp = impdp->impthnxt)
+  {
+   /* get source change time */
+   chgtim = impdp->lastchg;
+
+   if (__pth_tracing || (__debug_flg && __ev_tracing))
+    { 
+     /* know this will be non IS delay */
+     __get_del(&newdel, impdp->impth_du, impdp->impth_delrep);
+     prt_dbgimpthtrmsg(np, bi, chgtim, newdel);
+    }
+
+   /* case 1: change time earlier, always select latest */
+   if (chgtim < __pdlatechgtim) continue;
+    
+   /* know this will be non IS delay */
+   __get_del(&newdel, impdp->impth_du, impdp->impth_delrep);
+
+   /* if change times are the same, use the shortest path */
+   if (chgtim == __pdlatechgtim)
+    {
+     /* newdel larger implies not shorter path, do not change */
+     /* if same try to replace */
+     if (newdel > __pdmindel) continue;
+    }
+   /* this path's change time later(< handled above), just use */
+   else __pdlatechgtim = chgtim;
+
+   __pdmindel = newdel;
+  }
+ *pschtim = __pdlatechgtim + __pdmindel;
+}
+
+/*
+ * print a debugging or path trace message
+ * passed bi as 0 for scalar and corrects in here
+ */
+static void prt_dbgimpthtrmsg(struct net_t *np, int32 bi, word64 chgtim,
+ word64 newdel)
+{
+ int32 bi2;
+ char s1[RECLEN];
+
+ bi2 = (!np->n_isavec) ? -1 : bi;
+ __tr_msg("## intermodule src-dest path end on %s last change %s delay %s.\n",
+  __to_evtrwnam(__xs, np, bi2, bi2, __inst_ptr), __to_timstr(__xs2, &chgtim),
+  __to_timstr(s1, &newdel)); 
+}
+
+/*
+ * schedule 1 wire event
+ *
+ * passed in np but may be mpp (no cast needed) user must access right union
+ */
+extern void __schedule_1wev(struct net_t *np, int32 bi, int32 etyp, word64 ndel,
+ word64 schtim, word32 newval, i_tev_ndx *itevpi, int32 tr_decay)
+{
+ register i_tev_ndx tevpi; 
+ register struct tev_t *tevp;
+ register struct tenp_t *tenp; 
+
+ alloc_tev_(tevpi, etyp, __inst_ptr, schtim);
+ if (ndel == 0ULL)
+  {
+   /* this is #0, but must still build tev */
+   if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+   else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+  }
+ else __insert_event(tevpi);
+ tevp = &(__tevtab[tevpi]);
+ tevp->outv = (byte) newval;
+ tevp->te_trdecay = tr_decay;
+ itevpi[bi] = tevpi;
+
+ tenp = (struct tenp_t *) __my_malloc(sizeof(struct tenp_t));
+ tevp->tu.tenp = tenp;
+ tenp->tenu.np = np;
+ tenp->nbi = bi;
+}
+
+/*
+ * take wire del event and new val and update if time same or cancel and
+ * create new event if later
+ */
+extern void __reschedule_1wev(i_tev_ndx tevpi, word32 newval, word64 ndel,
+ word64 newtim, i_tev_ndx *itevpi)
+{
+ struct tenp_t *tenp; 
+ struct tev_t *tevp;
+
+ tevp = &(__tevtab[tevpi]);
+ /* if del == 0 (pnd0), will always be same time reschedule */
+ if (ndel == 0ULL)
+  {
+   /* new scheduled value replaces old - itevp remains correct */
+   __newval_rescheds++;
+   tevp->outv = (byte) newval;
+   return;
+  }
+ tenp = tevp->tu.tenp;
+ /* notice this will replace pending event in itevp */
+ __schedule_1wev(tenp->tenu.np, tenp->nbi, (int32) tevp->tetyp, ndel,
+  newtim, newval, itevpi, (int32) tevp->te_trdecay);
+ __cancel_1wev(tevp);
+}
+
+/*
+ * cancel 1 wev - after process or really cancel to free storage
+ * know itevp new event already adjusted
+ *
+ * this must be event not index since need old here
+ */
+extern void __cancel_1wev(struct tev_t *tevp)
+{
+ tevp->te_cancel = TRUE;
+ __inertial_cancels++;
+ /* DBG remove --- */
+ if (tevp->tu.tenp == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ __my_free((char *) tevp->tu.tenp, sizeof(struct tenp_t)); 
+ tevp->tu.tenp = NULL;
+}
+
+/*
+ * ROUTINES TO PROCESS MIPD LOAD SCHEDULING AND EV PROCESSING
+ */
+
+/*
+ * schedule one simple MIPD delay nchg propagate event
+ * this runs with itree instance location pushed
+ *
+ * works by stopping normal net change load propagation and scheduling it
+ * after MIPD delay has elaspsed
+ */
+extern void __sched_mipd_nchg(struct net_t *np, int32 bi, struct mipd_t *mipdp)
+{
+ register i_tev_ndx tevpi;
+ register word32 nval, oval;
+ word32 nav, nbv;
+ word64 ndel, schtim;
+ struct tev_t *tevp;
+ struct tenp_t *tenp; 
+
+ if (__ev_tracing)
+  { evtr_sched_mipd_nchg(np, bi, mipdp); return; }
+
+ /* load new wire value - need this call in case packed */
+ if (!np->n_isavec)
+  {
+   /* BEWARE - this depends on all scalars stored as byte array */
+   /* need to preserve strens for change check */
+   nval = (word32) np->nva.bp[__inum];
+  }
+ else
+  {
+   if (np->srep == SR_SVEC)
+    {
+     /* BEWARE - this depends on stren vec stored as byte array */
+     nval = (word32) np->nva.bp[__inum*np->nwid + bi];
+    }
+   else
+    {
+     __ld_bit(&nav, &nbv, np, bi); 
+     nval = (nav & 1) | ((nbv & 1) << 1);
+    }
+  }
+
+ tevpi = mipdp->mipdschd_tevs[__inum];
+ oval = mipdp->oldvals[__inum];
+
+ /* if no pending event and this bit unchanged nothing to schedule */
+ /* know at least one bit chged or will not get here but maybe not this one */
+ if (tevpi == -1 && nval == oval) return;
+
+ mipdp->oldvals[__inum] = nval;
+ /* delay only uses logic not stren part of value */
+ __new_gateval = nval & 3;
+ __old_gateval = oval & 3;
+
+ /* notice old and new gate values must be set before here */
+ if (!mipdp->pth_mipd || mipdp->impthtab == NULL
+  || mipdp->impthtab[__inum] == NULL)
+  {
+   /* non src-dst path delay for this simple MIPD case */
+   __get_del(&ndel, mipdp->pb_mipd_du, mipdp->pb_mipd_delrep);
+   schtim = __simtime + ndel;
+  }
+ else
+  {
+   /* use same algorithm as specify path delay algorithm to get last chged */
+   get_impth_del(&schtim, np, bi, mipdp); 
+   ndel = schtim - __simtime;
+  }
+
+ if (tevpi == -1)
+  {
+   /* if nothing pending can just schedule */
+   alloc_tev_(tevpi, TE_MIPD_NCHG, __inst_ptr, schtim);
+   if (ndel == 0ULL)
+    {
+     /* this is #0, but must still build tev */
+     if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+     else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+    }
+   else __insert_event(tevpi);
+   mipdp->mipdschd_tevs[__inum] = tevpi;
+   tevp = &(__tevtab[tevpi]);
+   tenp = (struct tenp_t *) __my_malloc(sizeof(struct tenp_t));
+   tevp->tu.tenp = tenp;
+   tenp->tenu.np = np;
+   tenp->nbi = bi;
+   return;
+  }
+
+ tevp = &(__tevtab[tevpi]);
+ /* DBG remove --- */
+ if (tevp->tetyp != TE_MIPD_NCHG)
+  {
+   char s1[RECLEN], s2[RECLEN];
+   extern char *__to_tetyp(char *, word32);
+
+   __dbg_msg("^^%s event index %d in inst. %s at %s cancel=%d\n",
+    __to_tetyp(s1, tevp->tetyp), tevpi, __msg2_blditree(s2, tevp->teitp),
+    __to_timstr(__xs, &__simtime), tevp->te_cancel);
+   __misc_terr(__FILE__, __LINE__);
+  }
+    
+ /* --- */
+
+ /* pending event - no spike analysis but inertial reschedule */
+ /* case 1a: pending event earlier than newly scheduled */
+ if (tevp->etime <= schtim)
+  {
+   /* current driving and schedule same, new later inertial value just */
+   /* causes scheduled to be removed since output at right value */
+   if (nval == oval)
+    {
+     /* cancel */
+     cancel_1mipdev(tevp);
+     mipdp->mipdschd_tevs[__inum] = -1;
+    }
+   else
+    {
+     /* reschedule - cancel and sched new or replace if pound 0 */
+     mipdp->mipdschd_tevs[__inum] = reschedule_1mipd(np, bi, tevpi, ndel,
+      schtim);
+    }
+   /* fall through since next case does nothing */
+  }
+ /* case 1b: pending event later (rare modeling anomally?) */ 
+ /* since inertial just ignore new change */
+}
+
+/*
+ * cancel 1 mipd ev - after process or really cancel to free storage
+ * this must be event not index since need old here
+ *
+ * sinc wev also uses tenp malloced field this is same as cance 1 wev
+ */
+static void cancel_1mipdev(struct tev_t *tevp)
+{
+ tevp->te_cancel = TRUE;
+ __inertial_cancels++;
+ /* DBG remove --- */
+ if (tevp->tu.tenp == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ __my_free((char *) tevp->tu.tenp, sizeof(struct tenp_t)); 
+ tevp->tu.tenp = NULL;
+}
+
+/*
+ * take wire del event and new val and update if time same or cancel and
+ * create new event if later
+ */
+static i_tev_ndx reschedule_1mipd(struct net_t *np, int32 bi, i_tev_ndx tevpi,
+ word64 ndel, word64 newtim)
+{
+ register struct tev_t *tevp, *tevp2;
+ register struct tenp_t *tenp; 
+ i_tev_ndx tevpi2;
+
+ tevp = &(__tevtab[tevpi]);
+ /* if del == 0 (pnd0), will always be same time reschedule */
+ if (ndel == 0ULL)
+  {
+   /* new scheduled value replaces old - same pending event */
+   __newval_rescheds++;
+   return(tevpi);
+  }
+
+ /* if nothing pending can just schedule */
+ alloc_tev_(tevpi2, TE_MIPD_NCHG, __inst_ptr, newtim);
+ __insert_event(tevpi2);
+ tevp2 = &(__tevtab[tevpi2]);
+ tenp = (struct tenp_t *) __my_malloc(sizeof(struct tenp_t));
+ tevp2->tu.tenp = tenp;
+ tenp->tenu.np = np;
+ tenp->nbi = bi;
+
+ cancel_1mipdev(tevp);
+ return(tevpi2);
+}
+
+/*
+ * tracing version schedule one simple MIPD delay nchg propagate event
+ *
+ * no spike analysis but normal inertial rescheduling
+ * this works for both strength 8 bit nval and oval and non strength
+ */
+static void evtr_sched_mipd_nchg(struct net_t *np, int32 bi,
+ struct mipd_t *mipdp)
+{
+ register i_tev_ndx tevpi;
+ register word32 nval, oval;
+ word32 nav, nbv;
+ word64 ndel, schtim;
+ word32 is_stren;
+ struct tev_t *tevp;
+ struct tenp_t *tenp; 
+ char s1[RECLEN], vs1[10], vs2[10], vs3[10];
+
+ is_stren = np->n_stren;
+ tevpi = mipdp->mipdschd_tevs[__inum];
+
+ /* if no change and do not need schedule time for cancel, done */
+ __tr_msg("-- scheduling MIPD for %s:\n",
+  __to_evtrwnam(__xs, np, bi, bi, __inst_ptr));
+
+ /* load new wire value - need this call in case packed */
+ if (!np->n_isavec)
+  {
+   /* BEWARE - this depends on all scalars stored as byte array */
+   /* need to preserve strens for change check */
+   nval = (word32) np->nva.bp[__inum];
+  }
+ else
+  {
+   if (np->srep == SR_SVEC)
+    {
+     /* BEWARE - this depends on stren vec stored as byte array */
+     nval = (word32) np->nva.bp[__inum*np->nwid + bi];
+    }
+   else
+    {
+     __ld_bit(&nav, &nbv, np, bi); 
+     nval = (nav & 1) | ((nbv & 1) << 1);
+    }
+  }
+ oval = mipdp->oldvals[__inum];
+
+ /* since always use last changed value, if last same as current */
+ /* because gate style spike nothing to do since already right value */   
+ if (tevpi == -1 && nval == oval)
+  {
+   __tr_msg(" NOPEND, NOCHG <OV=%s>\n", __to_vnam(vs1, is_stren, nval));
+   return;
+  }
+
+ mipdp->oldvals[__inum] = nval;
+ /* delay only uses logic not stren part of value */
+ __new_gateval = nval & 3;
+ __old_gateval = oval & 3;
+ /* notice old and new gate values must be set before here */
+ if (!mipdp->pth_mipd || mipdp->impthtab == NULL
+  || mipdp->impthtab[__inum] == NULL)
+  {
+   /* non src-dst path delay for this simple MIPD case */
+   __get_del(&ndel, mipdp->pb_mipd_du, mipdp->pb_mipd_delrep);
+   schtim = __simtime + ndel;
+  }
+ else
+  {
+   /* use same algorithm as specify path delay algorithm to get last chged */
+   get_impth_del(&schtim, np, bi, mipdp); 
+   ndel = schtim - __simtime;
+  }
+
+ if (tevpi == -1)
+  {
+   __tr_msg(" SCHD AT %s <OV=%s, NSV=%s>\n", __to_timstr(s1, &schtim),
+    __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren, nval));
+
+   /* if nothing pending can just schedule */
+   alloc_tev_(tevpi, TE_MIPD_NCHG, __inst_ptr, schtim);
+   if (ndel == 0ULL)
+    {
+     /* this is #0, but must still build tev */
+     if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+     else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+    }
+   else __insert_event(tevpi);
+
+   mipdp->mipdschd_tevs[__inum] = tevpi;
+   tevp = &(__tevtab[tevpi]);
+   tenp = (struct tenp_t *) __my_malloc(sizeof(struct tenp_t));
+   tevp->tu.tenp = tenp;
+   tenp->tenu.np = np;
+   tenp->nbi = bi;
+   return;
+  }
+
+ tevp = &(__tevtab[tevpi]);
+ /* DBG remove --- */
+ if (tevp->tetyp != TE_MIPD_NCHG)
+  {
+   char s2[RECLEN];
+   extern char *__to_tetyp(char *, word32);
+
+   tevp = &(__tevtab[tevpi]);
+   __dbg_msg("^^%s event index %d in inst. %s at %s cancel=%d\n",
+    __to_tetyp(s1, tevp->tetyp), tevpi, __msg2_blditree(s2, tevp->teitp),
+    __to_timstr(__xs, &__simtime), tevp->te_cancel);
+   __misc_terr(__FILE__, __LINE__);
+  }
+ /* --- */
+
+ /* pending event - no spike analysis but inertial reschedule */
+ /* case 1a: pending event earlier than newly scheduled */
+ if (tevp->etime <= schtim)
+  {
+   /* current driving and schedule same, new later inertial value just */
+   /* causes scheduled to be removed since output at right value */
+   if (nval == oval)
+    {
+     __tr_msg(" PENDING NCHG EVENT, SAME <NV==%s, OV=%s AT %s CANCEL>\n",
+      __to_vnam(vs1, is_stren, nval), __to_vnam(vs2, is_stren, oval), 
+      __to_timstr(s1, &schtim));
+     /* cancel */
+     cancel_1mipdev(tevp);
+     mipdp->mipdschd_tevs[__inum] = -1;
+    }
+   else
+    {
+     __tr_msg(
+      " PENDING NCHG EVENT, RESCHD <OV=%s, AT %s, NV=%s AT %s REPLACES>\n",
+      __to_vnam(vs1, is_stren, oval), __to_timstr(s1, &(tevp->etime)),
+       __to_vnam(vs3, is_stren, nval), __to_timstr(__xs, &schtim));
+
+     /* reschedule - cancel and sched new or replace if pound 0 */
+     mipdp->mipdschd_tevs[__inum] = reschedule_1mipd(np, bi, tevpi, ndel,
+      schtim);
+    }
+   /* although next case does nothing, must not emit the message */
+   return;
+  }
+ /* case 1b: pending event later (rare modeling anomally?) */ 
+ /* since inertial just ignore new change */
+ __tr_msg(
+  " PENDING NCHG EVENT, NEW EARLY <OV=%s AT %s, INERTIAL IGNORE NV=%s AT %s>\n",
+  __to_vnam(vs1, is_stren, oval), __to_timstr(s1, &(tevp->etime)),
+  __to_vnam(vs3, is_stren, nval), __to_timstr(__xs, &schtim));
+} 
+
+/*
+ * VALUE STORE ROUTINES FOR ASSIGNS
+ */
+
+/*
+ * store (copy) an entire value from rgap and rgbp into wp of length blen
+ * from current instance 
+ * stored according to representation srep from from rgap and rgbp
+ * but cannot be used to store strength values
+ *
+ * stored using representation srep
+ * separate rgap and rgbp into code contigous wp since stack size changes
+ * cause non contigous storage form
+ * know rgap and rgbp exact np nwid width
+ */
+extern void __st_val(struct net_t *np, register word32 *rgap,
+ register word32 *rgbp)
+{
+ register word32 *dwp;
+ register int32 wlen;
+ byte *newsbp;
+
+ switch ((byte) np->srep) {
+  case SR_SCAL:
+   st_scalval_(np->nva.bp, rgap[0], rgbp[0]);
+   break;
+  case SR_VEC:
+   wlen = wlen_(np->nwid);
+   dwp = &(np->nva.wp[2*wlen*__inum]);
+   st_vecval(dwp, np->nwid, rgap, rgbp);
+   break;
+  case SR_SVEC:
+   /* this must be strong */
+   memcpy(&(np->nva.bp[np->nwid*__inum]), rgap, np->nwid);
+   break;
+  case SR_SSCAL:
+   newsbp = (byte *) rgap;
+   np->nva.bp[__inum] = *newsbp;
+   break;
+  default: __case_terr(__FILE__, __LINE__); return;
+ }
+}
+
+/*
+ * store a per instance value into a word32 location
+ * mostly for storing cont. assign driver values
+ * bit width determines form
+ *
+ * caller must make sure source blen and vblen same
+ */
+extern void __st_perinst_val(union pck_u pckv, int32 vblen, register word32 *rgap,
+ register word32 *rgbp)
+{
+ register word32 *dwp;
+ int32 wlen;
+
+ /* know rgab always scalar here if 1 bit case */
+ if (vblen == 1) { st_scalval_(pckv.bp, rgap[0], rgbp[0]); return; }
+ /* SJM - 07/15/00 - all vectors now not packed - min 2 words */
+ wlen = wlen_(vblen);
+ dwp = &(pckv.wp[2*wlen*__inum]);
+ st_vecval(dwp, vblen, rgap, rgbp);
+}
+
+/*
+ * store into value at dwp of length destination length from ap and bp of
+ * srcblen
+ *
+ * any high bits of destination must be zeroed - not for lhs selects
+ * know vectors always occupy number of words (no packing to less then word32)
+ * routine called after array or instance decoding completed to get dwp
+ */
+static void st_vecval(word32 *dwp, int32 blen, register word32 *ap,
+ register word32 *bp)
+{
+ int32 wlen;
+
+ /* truncating wide source into narrower dest. */
+ wlen = wlen_(blen);
+ /* know copy will 0 any high unused bits of high word32 */
+ cp_walign_(dwp, ap, blen);
+ cp_walign_(&(dwp[wlen]), bp, blen);
+}
+
+/*
+ * store if changed (and set flag) know rgap and rgbp are adjusted and
+ * z extended (if needed) to exact wire width
+ * also any 1 bit cases must already be adjusted to a part only form  
+ */
+extern void __chg_st_val(register struct net_t *np, word32 *rgap, word32 *rgbp)
+{
+ register word32 *dwp;
+ int32 wlen;
+ byte *netsbp, *newsbp;
+
+ switch ((byte) np->srep) {
+  case SR_SCAL:
+   chg_st_scalval_(np->nva.bp, rgap[0], rgbp[0]);
+   break;
+  case SR_VEC:
+   wlen = wlen_(np->nwid);
+   dwp = &(np->nva.wp[2*wlen*__inum]);
+   chg_st_vecval(dwp, np->nwid, rgap, rgbp);
+   break;
+  case SR_SVEC:
+   /* this must be strong */
+   netsbp = &(np->nva.bp[np->nwid*__inum]); 
+   newsbp = (byte *) rgap;
+   if (memcmp(netsbp, newsbp, np->nwid) != 0)
+    {
+     /* bcopy 2nd argument is destination */
+     memcpy(netsbp, newsbp, np->nwid);
+     __lhs_changed = TRUE;
+    }
+   break;
+  case SR_SSCAL:
+   netsbp = &(np->nva.bp[__inum]); 
+   newsbp = (byte *) rgap;
+   if (*netsbp != *newsbp) { *netsbp = *newsbp; __lhs_changed = TRUE; } 
+   break;
+  default: __case_terr(__FILE__, __LINE__); return;
+ }
+ if (__lhs_changed) record_nchg_(np);
+}
+
+/*
+ * routine to record net change - non macro for debugging
+ */
+/* DBG ??? add ---
+extern void __record_nchg(struct net_t *np)
+{
+ -* SJM 08/08/03 - can't assume caller turns off chged flag any more *-
+ -* but one record called, it must be off for dctrl processing - not needed *- 
+ __lhs_changed = FALSE;
+
+ -* --- DBG remove
+ if (__debug_flg)
+  {
+   strcpy(__xs2, "");
+   if (np->nlds == NULL) strcat(__xs2, "[no lds, ");
+   else strcat(__xs2, "[ld, ");
+   if (np->dcelst == NULL) strcat(__xs2, "no dces, ");
+   else strcat(__xs2, "dces, ");
+   if (np->ndrvs == NULL) strcat(__xs2, "no drvs]");
+   else strcat(__xs2, "drvs]");
+   
+   -* emit for inst 0 (all should be same) *-
+   __dbg_msg("record nchg for net %s type %s nchgaction=%x conn=%s\n",
+    np->nsym->synam, __to_wtnam(__xs, np), np->nchgaction[__inum], __xs2);
+  }
+ --- *-
+
+ -* SJM 07/24/00 - has dces only on for regs *-
+ -* SJM 03/15/01 - change to fields in net record *-
+ if (np->nchg_has_dces) __wakeup_delay_ctrls(np, -1, -1);
+
+ if ((np->nchgaction[__inum] & NCHG_ALL_CHGED) == 0)
+   __add_nchglst_el(np);
+
+ if ((np->nchgaction[__inum] & (NCHG_DMPVARNOW | NCHG_DMPVNOTCHGED)) 
+  == (NCHG_DMPVARNOW | NCHG_DMPVNOTCHGED))
+  {
+   np->nchgaction[__inum] &= ~(NCHG_DMPVNOTCHGED);
+   __add_dmpv_chglst_el(np);
+  }
+}
+--- */
+
+/*
+ * routine to record net select change - non macro for debugging
+ */
+/* DBG ??? add ---
+extern void __record_sel_nchg(struct net_t *np, int32 i1, int32 i2)
+{
+ -* SJM 08/08/03 - can't assume caller turns off chged flag any more *-
+ -* but one record called, it must be off for dctrl processing - not needed *- 
+ __lhs_changed = FALSE;
+
+ -* --- DBG remove *-
+ if (__debug_flg)
+  {
+   strcpy(__xs2, "");
+   if (np->nlds == NULL) strcat(__xs2, "[no lds, ");
+   else strcat(__xs2, "[ld, ");
+   if (np->dcelst == NULL) strcat(__xs2, "no dces, ");
+   else strcat(__xs2, "dces, ");
+   if (np->ndrvs == NULL) strcat(__xs2, "no drvs]");
+   else strcat(__xs2, "drvs]");
+   
+   __dbg_msg("record nchg for net %s[%d:%d] type %s nchgaction=%x conn=%s\n",
+    np->nsym->synam, i1, i2, __to_wtnam(__xs, np), np->nchgaction[__inum],
+    __xs2);
+  }
+ --- *-
+
+ -* --- *- 
+ -* SJM 07/24/00 - has dces only on for regs *-
+ if (np->nchg_has_dces) __wakeup_delay_ctrls(np, i1, i2); 
+
+ if ((np->nchgaction[__inum] & NCHG_ALL_CHGED) == 0)
+  __add_select_nchglst_el(np, i1, i2); 
+
+ if ((np->nchgaction[__inum] & (NCHG_DMPVARNOW | NCHG_DMPVNOTCHGED)) 
+  == (NCHG_DMPVARNOW | NCHG_DMPVNOTCHGED))
+  {
+   np->nchgaction[__inum] &= ~(NCHG_DMPVNOTCHGED);
+   __add_dmpv_chglst_el(np);
+  }
+}
+--- */
+
+/*
+ * change form of store vector value - know stacked ap and bp width
+ * same as destination
+ * know blen at least 16 bits or wider
+ *
+ * caller must adjust
+ * notice this does not add changed net to change list
+ */
+static void chg_st_vecval(register word32 *dwp, int32 blen, register word32 *ap,
+ register word32 *bp)
+{
+ int32 wlen;
+ word32 *dwp2;
+
+ if (blen <= WBITS)
+  { 
+   if (dwp[0] != ap[0])
+    {
+     dwp[0] = ap[0];
+     __lhs_changed = TRUE;
+    }
+   if (dwp[1] != ap[1])
+    {
+     dwp[1] = bp[0];
+     __lhs_changed = TRUE;
+    }
+   return;
+  }
+ wlen = wlen_(blen);
+ if (cmp_wvval_(dwp, ap, wlen) != 0)
+  { cp_walign_(dwp, ap, blen); __lhs_changed = TRUE; }
+ dwp2 = &(dwp[wlen]); 
+ if (cmp_wvval_(dwp2, bp, wlen) != 0)
+  { cp_walign_(dwp2, bp, blen); __lhs_changed = TRUE; }
+}
+
+/*
+ * assign to a bit
+ * if np is stren ap will point to array with one byte
+ * know ap/bp either strength 8 bits in ap part or exactly 1 bit
+ */
+extern void __assign_to_bit(struct net_t *np, struct expr_t *idndp,
+ struct expr_t *ndx1, register word32 *ap, register word32 *bp)
+{
+ int32 biti, nd_itpop;
+ byte *sbp;
+ struct gref_t *grp;
+
+ biti = __comp_ndx(np, ndx1);
+ nd_itpop = FALSE;
+ if (idndp->optyp == GLBREF)
+  { grp = idndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ if (biti == -1)
+  {
+   if (np->n_stren)
+    {
+     sbp = (byte *) ap;
+     __stren_schedorassign_unknown_bit(np, (word32) sbp[0], FALSE); 
+    }
+   else __schedorassign_unknown_bit(np, ap[0], bp[0], FALSE); 
+  }
+ else
+  {
+   /* notice best to use change form since it has fast macro checking */
+   /* need to record change - non change bit store not much better */
+   /* SJM 03/15/01 - change to fields in net record */
+   if (np->nchg_nd_chgstore)
+    {
+     if (np->n_stren)
+      {
+       sbp = (byte *) ap;
+       __chg_st_bit(np, biti, (word32) sbp[0], (word32) 0);
+      }
+     else __chg_st_bit(np, biti, ap[0], bp[0]);
+    }
+   else
+    {
+     if (np->n_stren)
+      {
+       sbp = (byte *) ap;
+       __st_bit(np, biti, (word32) sbp[0], (word32) 0);
+      }
+     else __st_bit(np, biti, ap[0], bp[0]);
+    }
+  }
+ if (nd_itpop) __pop_itstk();
+} 
+
+/*
+ * if 1 bit is forced return T (nothing to do) if need assign returns F
+ */
+extern int32 __forced_inhibit_bitassign(struct net_t *np, struct expr_t *idndp,
+ struct expr_t *ndx1)
+{
+ int32 biti, nd_itpop, rv;
+ struct gref_t *grp;
+
+ /* SJM 10/11/02 - should compute index in assign itree cntxt not xmr */
+ biti = __comp_ndx(np, ndx1);
+
+ nd_itpop = FALSE;
+ if (idndp->optyp == GLBREF)
+  { grp = idndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+
+ if (biti == -1) __arg_terr(__FILE__, __LINE__);
+ /* if the one bit is forced, no need to do assign */
+ if (np->nu2.qcval[np->nwid*__inum + biti].qc_active) rv = TRUE;
+ else rv = FALSE;
+ if (nd_itpop) __pop_itstk();
+ return(rv);
+} 
+
+/*
+ * schedule assignment to a bit
+ * ap and bp may be wider than 1 bit 
+ */
+static void schedassign_to_bit(struct net_t *np, struct expr_t *idndp,
+ struct expr_t *ndx1, register word32 *ap, register word32 *bp)
+{
+ int32 biti, nd_itpop;
+ byte *sbp, *sbp2;
+ word32 av, bv, nval;
+ struct gref_t *grp;
+
+ biti = __comp_ndx(np, ndx1);
+ nd_itpop = FALSE;
+ if (idndp->optyp == GLBREF)
+  { grp = idndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ if (biti == -1)
+  {
+   /* here same routine for both */
+   if (np->n_stren)
+    {
+     sbp = (byte *) ap;
+     __stren_schedorassign_unknown_bit(np, (word32) sbp[0], TRUE); 
+    }
+   else __schedorassign_unknown_bit(np, ap[0], bp[0], TRUE); 
+   if (nd_itpop) __pop_itstk();
+   return;
+  }
+
+ if (np->n_stren)
+  {
+   /* get strength wire address */
+   get_stwire_addr_(sbp, np);
+   sbp2 = (byte *) ap;
+   if (np->nu.rngdwir->n_delrep == DT_PTHDST)
+    schd_1pthwirebit(np, biti, (word32) sbp2[0], (word32) sbp[biti]);
+   else
+    __wdel_schd_1wirebit(np, biti, (word32) sbp2[0], (word32) sbp[biti], FALSE);
+  }
+ else
+  {
+   __ld_bit(&av, &bv, np, biti); 
+   nval = (ap[0] & 1L) | ((bp[0] << 1) & 2L);
+   if (np->nu.rngdwir->n_delrep == DT_PTHDST)
+    schd_1pthwirebit(np, biti, nval, (av | (bv << 1)));
+   else __wdel_schd_1wirebit(np, biti, nval, (av | (bv << 1)), FALSE);
+  }
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * assign or schedule to an unknown - bit - all x that differs from value
+ *
+ * strength version
+ */
+extern void __stren_schedorassign_unknown_bit(struct net_t *np, word32 bval,
+ int32 schd_wire)
+{
+ register int32 i;
+ byte *sbp;
+ word32 newval;
+
+ /* get strength wire address */
+ get_stwire_addr_(sbp, np);
+ /* even if value the same - strength here always strong */
+ if (schd_wire)
+  {
+   /* case 1a: schedule for delay wire - know not a path source */
+   for (i = 0; i < np->nwid; i++)
+    {
+     if (sbp[i] != (byte) bval) newval = (word32) ST_STRONGX;
+     else newval = bval;
+     if (newval != (word32) sbp[i])
+      {
+       if (np->nu.rngdwir->n_delrep == DT_PTHDST)
+        schd_1pthwirebit(np, i, newval, (word32) sbp[i]);
+       else __wdel_schd_1wirebit(np, i, newval, (word32) sbp[i], FALSE);
+      }
+    }
+   return;
+  }
+ /* case 1b : immediate assign */
+ for (i = 0; i < np->nwid; i++)
+  {
+   /* LOOKATME - think this can be simplified - but if chg to x and was x*/
+   /* still need to do nothing - also need cast to word32 */
+   /* SJM 01/18/01 - was always setting lhs changed even if same */
+   if (sbp[i] != (byte) bval) newval = (word32) ST_STRONGX;
+   else newval = bval;
+   if (newval != (word32) sbp[i])
+    { sbp[i] = (byte) newval; __lhs_changed = TRUE; }
+  }
+ /* this could be lots of 1 bit schedules */
+ if (__lhs_changed) record_nchg_(np);
+}
+
+/*
+ * assign or schedule to an unknown - bit - all x that differs from value
+ *
+ * non strength version
+ */
+extern void __schedorassign_unknown_bit(struct net_t *np, word32 av, word32 bv,
+ int32 schd_wire)
+{
+ register int32 i;
+ word32 bval, newval, oval, w1, w2;
+ struct xstk_t *oxsp, *nxsp;
+
+ bval = av | (bv << 1);
+ push_xstk_(oxsp, np->nwid);
+ /* know net width > 1 */
+ __ld_wire_val(oxsp->ap, oxsp->bp, np);
+ push_xstk_(nxsp, np->nwid);
+ get_unknown_biti_val(np, nxsp->ap, nxsp->bp, oxsp->ap, oxsp->bp, bval); 
+
+ /* bit by bit select comparison if needed for source else just store */
+ /* case 2a: schdule delay wire - know cannot be path source */
+ if (schd_wire)
+  {
+   for (i = 0; i < np->nwid; i++)
+    {
+     w1 = rhsbsel_(nxsp->ap, i);
+     w2 = rhsbsel_(nxsp->bp, i);
+     newval = w1 | (w2 << 1);
+     w1 = rhsbsel_(oxsp->ap, i);
+     w2 = rhsbsel_(oxsp->bp, i);
+     oval = w1 | (w2 << 1);
+     if (newval != oval)
+      {
+       if (np->nu.rngdwir->n_delrep == DT_PTHDST)
+        schd_1pthwirebit(np, i, newval, oval);
+       else __wdel_schd_1wirebit(np, i, newval, oval, FALSE);
+      }
+    }
+  }
+ /* normal store entire value - faster than bit by bit */
+ /* know store and both are wire width */
+ else __chg_st_val(np, nxsp->ap, nxsp->bp);
+ __pop_xstk();
+ __pop_xstk();
+}
+
+/*
+ * build the new unknown biti value on stack where new bit value is newval
+ * this is not needed for strength case where stored as bytes 
+ */
+static void get_unknown_biti_val(struct net_t *np, word32 *nap, word32 *nbp,
+ word32 *oap, word32 *obp, word32 newval)
+{
+ register int32 i;
+ int32 wlen, ubits;
+
+ /* if new value x, then all bits of var. changed to x */
+ if (newval == 3)
+  { one_allbits_(nap, np->nwid); one_allbits_(nbp, np->nwid); return; }
+ /* otherwide make all bits that differ from value x */
+ wlen = wlen_(np->nwid);
+ for (i = 0; i < wlen; i++)
+  {
+   nap[i] = oap[i];
+   nbp[i] = obp[i];
+   setx_ifnotval(&(nap[i]), &(nbp[i]), newval);
+  }
+ ubits = ubits_(np->nwid);
+ nap[wlen - 1] &= __masktab[ubits];
+ nbp[wlen - 1] &= __masktab[ubits];
+} 
+
+/*
+ * set new a word32 and b word32 so that if value leave as is else x
+ */
+static void setx_ifnotval(word32 *ap, word32 *bp, word32 val)
+{
+ word32 mask;
+
+ switch ((byte) val) {
+  case 0: mask = ap[0] | bp[0]; ap[0] = bp[0] = mask; break;
+  case 1: ap[0] = ALL1W; bp[0] = ~(ap[0] | bp[0]) | bp[0]; break;
+  case 2: ap[0] = ~(ap[0] | bp[0]) | ap[0]; bp[0] = ALL1W; break;
+  case 3: ap[0]= bp[0] = ALL1W; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * set bit dbit of dwp from low bit of word32 sw 
+ * know dbit in range 
+ * this does not assume dbit in 1st word32 of dwp
+ * also sw may have high bits beside low bit on
+ * dwp must be set to right place using current instance
+ *
+ * these should be macros in asm
+ */
+extern void __lhsbsel(register word32 *dwp, register int32 dbit, word32 sw)
+{
+ register int32 bi, wi;
+
+ /* dbit in word32 0 is 0-31, word32 1 is 32-63, etc */
+ wi = get_wofs_(dbit);
+ /* bi is index with 0 rightmost bit and 31 high bit in select word32 */
+ bi = get_bofs_(dbit);
+ dwp[wi] &= ~(1L << bi);
+ dwp[wi] |= ((sw & 1L) << bi);
+}
+
+/*
+ * change versions of store bit
+ * know biti in range
+ */
+extern void __chg_st_bit(struct net_t *np, int32 biti, register word32 av,
+ register word32 bv)
+{
+ register word32 *rap;
+ byte *netsbp;
+ int32 wlen;
+
+ switch ((byte) np->srep) {
+ /* this is same as full value store - biti 0 or will not get here */
+  case SR_SCAL:
+   /* DBG remove --
+   if (biti != 0) __arg_terr(__FILE__, __LINE__); 
+   --- */
+   chg_st_scalval_(np->nva.bp, av, bv);
+   break;
+  case SR_VEC:
+   /* rap is base of vector for current inst */
+   wlen = wlen_(np->nwid);
+   rap = &(np->nva.wp[2*wlen*__inum]);
+   chg_lhsbsel(rap, biti, av);
+   chg_lhsbsel(&(rap[wlen]), biti, bv);
+   break;
+  case SR_SVEC:
+   /* rap is base of vector for current inst */
+   netsbp =  &(np->nva.bp[np->nwid*__inum]);
+   if (netsbp[biti] != (byte) av)
+    { netsbp[biti] = (byte) av; __lhs_changed = TRUE; }
+   break;
+  case SR_SSCAL:
+   /* DBG remove ---
+   if (biti != 0) __arg_terr(__FILE__, __LINE__); 
+   -- */
+   netsbp = &(np->nva.bp[__inum]);
+   if (netsbp[0] != (byte) av)
+    { *netsbp = (byte) av; __lhs_changed = TRUE; }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ if (__lhs_changed) record_sel_nchg_(np, biti, biti);
+}
+
+/*
+ * immediate versions of store bit
+ * know biti in range
+ */
+extern void __st_bit(struct net_t *np, int32 biti, register word32 av,
+ register word32 bv)
+{
+ register word32 *rap;
+ int32 wlen;
+
+ switch ((byte) np->srep) {
+ /* this is same as full value store - biti 0 or will not get here */
+  case SR_SCAL:
+   /* DBG remove --
+   if (biti != 0) __arg_terr(__FILE__, __LINE__); 
+   --- */
+   st_scalval_(np->nva.bp, av, bv);
+   break;
+  case SR_VEC:
+   /* rap is base of vector for current inst */
+   wlen = wlen_(np->nwid);
+   rap = &(np->nva.wp[2*wlen*__inum]);
+   __lhsbsel(rap, biti, av);
+   __lhsbsel(&(rap[wlen]), biti, bv);
+   break;
+  case SR_SVEC:
+   /* rap is base of vector for current inst */
+   np->nva.bp[np->nwid*__inum + biti] = (byte) av;
+   break;
+  case SR_SSCAL:
+   /* DBG remove ---
+   if (biti != 0) __arg_terr(__FILE__, __LINE__); 
+   -- */
+   np->nva.bp[__inum] = (byte) av;
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * lhs bit select but do not store if same
+ * sets global lhs changed to F if the same
+ * LOOKATME - is it true that sw must be masked off - faster if not needed
+ */
+static void chg_lhsbsel(register word32 *dwp, int32 dbit, word32 sw)
+{
+ register word32 mask, sw2;
+ register int32 bi, wi;
+
+ /* dbit in word32 0: 0-31, word32 1: 32-63, etc (32 left high - 0 right low) */
+ wi = get_wofs_(dbit);
+ bi = get_bofs_(dbit);
+ mask = 1L << bi;
+ sw2 = (sw & 1L) << bi;
+ if (((dwp[wi] & mask) ^ sw2) != 0L)
+  { __lhs_changed = TRUE; dwp[wi] &= ~mask; dwp[wi] |= sw2; }
+}
+
+/*
+ * assign to an indexed array location (procedural only)
+ */
+extern void __assign_to_arr(struct net_t *np, struct expr_t *idndp,
+ struct expr_t *ndx1, register word32 *ap, register word32 *bp)
+{
+ int32 arri, nd_itpop, arrwid;
+ struct gref_t *grp;
+
+ /* arrwid is number of cells in array */
+ arri = __comp_ndx(np, ndx1);
+ /* for array - if index out of range - do not change array at all */ 
+ if (arri == -1)
+  {
+   __sgfwarn(530,
+   "left hand side array index %s of %s unknown or out of range - unchanged",
+    __regab_tostr(__xs, &__badind_a, &__badind_b, __badind_wid, BHEX, FALSE),
+    __to_idnam(idndp));
+   return;
+  }
+ /* SJM DBG REMOVEME --- */
+ if (arri == -2) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ arrwid = __get_arrwide(np);
+ nd_itpop = FALSE;
+ /* notice for xmr - symbol points to right wire - trick is to make */
+ /* sure target itree place right */
+ if (idndp->optyp == GLBREF)
+  { grp = idndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+
+ /* SJM 03/15/01 - change to fields in net record */
+ if (np->nchg_nd_chgstore)
+  {
+   __chg_st_arr_val(np->nva, arrwid, np->nwid, arri, ap, bp);
+
+   /* SJM - 06/25/00 - lhs changed possible from change store */
+   /* and must only trigger change for right array index */
+   if (__lhs_changed) record_sel_nchg_(np, arri, arri);
+  }
+ else __st_arr_val(np->nva, arrwid, np->nwid, arri, ap, bp);
+
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * store into array map of len mlen with element length blen using index
+ * arri value from current instance from rgap and rgbp
+ *
+ * notice arrays stored and normalized to h:0 just like vectors
+ * this handles source (to be stored) value of wrong size
+ */
+extern void __st_arr_val(union pck_u pckv, int32 mlen, int32 blen, int32 arri,
+ register word32 *rgap, register word32 *rgbp)
+{
+ register word32 uwrd;
+ int32 indi, wlen, wi, bi;
+ register word32 *vap, *rap;
+
+ /* compute number of words used to store 1 array element */
+ /* 17 or more bits cannot be packed with multiple elements per word32 */
+ /* new real arrays fit here */ 
+ if (blen > WBITS/2)
+  {
+   /* case 1: each vector element of array takes multiple words */
+
+   wlen = wlen_(blen);
+   /* find array for inst i with each vector wlen words wide */
+   vap = &(pckv.wp[2*wlen*mlen*__inum]);
+   /* find element arri that may be a vector */
+   rap = &(vap[arri*2*wlen]);
+
+   /* instance and array index used to decode into vector addr rap */
+   st_vecval(rap, blen, rgap, rgbp);
+   return;
+  }
+
+ /* case 2: array of 1 bit elements */
+ if (blen == 1)
+  {
+   indi = 2*(__inum*mlen + arri);
+   wi = get_wofs_(indi);
+   bi = get_bofs_(indi);
+   uwrd = pckv.wp[wi];
+   uwrd &= ~(3L << bi); 
+   uwrd |= (((rgap[0] & 1L) | ((rgbp[0] & 1L) << 1)) << bi);
+   pckv.wp[wi] = uwrd;
+   return;
+  } 
+ /* case 3: array cells packed */
+ uwrd = (rgap[0] & __masktab[blen]) | ((rgbp[0] & __masktab[blen]) << blen);
+ indi = __inum*mlen + arri;
+ st_packintowrd_(pckv, indi, uwrd, blen);
+}
+
+/*
+ * store a array value if changed only - reset lhs change if not changed
+ *
+ * notice this does not record change (caller must)
+ */
+extern void __chg_st_arr_val(union pck_u pckv, int32 mlen, int32 blen, int32 arri,
+ register word32 *ap, register word32 *bp)
+{
+ register word32 *rap, uwrd, ouwrd;
+ int32 wlen, wi, bi, indi;
+ word32 *vap;
+
+ /* compute number of words used to store 1 array element */
+ /* 17 or more bits cannot be packed with multiple elements per word32 */
+ if (blen > WBITS/2)
+  {
+   /* case 1: each vector element of array takes multiple words */
+   /* new real arrays fit here */ 
+
+   wlen = wlen_(blen);
+   /* find array for inst i with each vector wlen words wide */
+   vap = &(pckv.wp[2*wlen*mlen*__inum]);
+   /* find element arri that may be a vector */
+   rap = &(vap[arri*2*wlen]);
+   /* instance and array indexed used to decode into vector addr rap */
+   /* SJM 08/24/03 - caller check for lhs changed maybe set by this */
+   chg_st_vecval(rap, blen, ap, bp);
+   return;
+  }
+
+ /* case 2: array of 1 bit elements */
+ if (blen == 1)
+  {
+   indi = 2*(__inum*mlen + arri);
+   wi = get_wofs_(indi);
+   bi = get_bofs_(indi);
+   ouwrd = pckv.wp[wi];
+   uwrd = ouwrd & ~(3L << bi); 
+   uwrd |= (((ap[0] & 1L) | ((bp[0] & 1L) << 1)) << bi);
+   if (ouwrd != uwrd) { pckv.wp[wi] = uwrd; __lhs_changed = TRUE; }
+   return;
+  } 
+ /* case 3: array cells packed */
+ indi = __inum*mlen + arri;
+ /* SJM 02/08/00 - since memory still need to get pack into word32 */
+ ouwrd = get_packintowrd_(pckv, indi, blen);
+ uwrd = (ap[0] & __masktab[blen]) | ((bp[0] & __masktab[blen]) << blen);
+ if (uwrd != ouwrd)
+  {
+   st_packintowrd_(pckv, indi, uwrd, blen);
+   __lhs_changed = TRUE;
+  }
+}
+
+/*
+ * assign to a part select
+ * know xsp width exactly matches part select range
+ */
+extern void __assign_to_psel(struct expr_t *idndp, int32 ri1, int32 ri2,
+ struct net_t *np, register word32 *ap, register word32 *bp)
+{
+ struct gref_t *grp;
+ int32 nd_itpop;
+
+ nd_itpop = FALSE;
+ if (idndp->optyp == GLBREF)
+  { grp = idndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ /* if strength, know ap points to st bytes and array rhswid 4x to big */
+ chg_st_psel(np, ri1, ri2, ap, bp);
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * assign to a part select
+ * know ap/bp width exactly matches part select range
+ * if returns F, caller does not do lhs assign, if T must do it
+ */
+static int32 forced_assign_to_psel(struct expr_t *idndp, int32 ri1, int32 ri2,
+ struct net_t *np, register word32 *ap, register word32 *bp)
+{
+ register int32 bi, bi2;
+ int32 wi, pswid, nd_itpop, wlen, nd_assign, ibase;
+ byte *sbp, *sbp2;
+ struct gref_t *grp;
+ struct xstk_t *xsp, *xsp2;
+
+ pswid = ri1 - ri2 + 1; 
+ nd_itpop = FALSE;
+ if (idndp->optyp == GLBREF)
+  { grp = idndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+
+ if (np->n_stren)
+  {
+   sbp = (byte *) ap;
+   get_stwire_addr_(sbp2, np);
+
+   /* trick is to replace forced bits so new assign is same as forced val */
+   /* if all bits forced, do not need assign */
+   ibase = __inum*np->nwid;
+   for (nd_assign = FALSE, bi = ri2, bi2 = 0; bi2 < pswid; bi++, bi2++)
+    {
+     /* some bits not forced - so need assign */
+     if (np->nu2.qcval[ibase + bi].qc_active) sbp[bi] = sbp2[bi];
+     else nd_assign = TRUE;
+    }
+   if (nd_itpop) __pop_itstk();
+   return(nd_assign);
+  }
+
+ push_xstk_(xsp, pswid);
+ push_xstk_(xsp2, np->nwid);
+ __bld_forcedbits_mask(xsp2->ap, np);
+ 
+ /* xsp has part select range forced bits */
+ __rhspsel(xsp->ap, xsp2->ap, ri2, pswid);
+ __pop_xstk();
+
+ /* if all bits forced nothing to do */
+ if (__vval_is1(xsp->ap, pswid))
+  { __pop_xstk(); if (nd_itpop) __pop_itstk(); return(FALSE); }
+ /* if no bits in range forced, just do lhs part select */
+ if (vval_is0_(xsp->ap, pswid))
+  { __pop_xstk(); if (nd_itpop) __pop_itstk(); return(TRUE); }
+
+ push_xstk_(xsp2, pswid);
+ /* xsp2 has value of old wire part selected range */
+ __ld_psel(xsp2->ap, xsp2->bp, np, ri1, ri2); 
+ wlen = wlen_(pswid);
+
+ /* this changes new value so lhs part select will set right value */
+ for (wi = 0; wi < wlen; wi++) 
+  {
+   /* remove forced bits from new value */
+   ap[wi] &= ~(xsp->ap[wi]);   
+   bp[wi] &= ~(xsp->ap[wi]);
+   /* remove non forced bits from old (current value) */
+   xsp2->ap[wi] &= xsp->ap[wi];
+   xsp2->bp[wi] &= xsp->ap[wi];
+   /* or old value forced into new value */
+   ap[wi] |= xsp2->ap[wi]; 
+   bp[wi] |= xsp2->ap[wi]; 
+  }
+ __pop_xstk();
+ __pop_xstk();
+ if (nd_itpop) __pop_itstk();
+ return(TRUE);
+}
+
+/*
+ * schedule assignment to a part select
+ * know xsp width exactly matches part select range
+ */
+static void schedassign_to_psel(struct expr_t *xlhs, register word32 *ap,
+ register word32 *bp)
+{
+ register int32 bi, bi2;
+ int32 ri1, ri2, pslen, nd_itpop;
+ byte *sbp, *sbp2;
+ word32 oav, obv, aval, bval; 
+ struct net_t *np;
+ struct expr_t *idndp, *ndx1, *ndx2;
+ struct gref_t *grp;
+
+ idndp = xlhs->lu.x;
+ np = idndp->lu.sy->el.enp;
+
+ ndx1 = xlhs->ru.x->lu.x;
+ ri1 = (int32) __contab[ndx1->ru.xvi];
+ ndx2 = xlhs->ru.x->ru.x;
+ ri2 = (int32) __contab[ndx2->ru.xvi];
+
+ nd_itpop = FALSE;
+ if (idndp->optyp == GLBREF)
+  { grp = idndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ pslen = ri1 - ri2 + 1;
+ if (np->n_stren)
+  {
+   sbp = (byte *) ap;
+   /* get strength wire address */
+   get_stwire_addr_(sbp2, np);
+   for (bi = ri2, bi2 = 0; bi < ri2 + pslen; bi++, bi2++)
+    {
+     if (np->nu.rngdwir->n_delrep == DT_PTHDST)
+      schd_1pthwirebit(np, bi, (word32) sbp[bi], (word32) sbp2[bi2]);
+     else __wdel_schd_1wirebit(np, bi, (word32) sbp[bi], (word32) sbp2[bi2],
+      FALSE);
+    }
+  }
+ else
+  {
+   /* schedule for each bit */
+   for (bi = ri2; bi < ri2 + pslen; bi++)
+    {
+     /* isolate rhs bit */
+     aval = rhsbsel_(ap, bi);
+     bval = rhsbsel_(bp, bi);
+     aval |= (bval << 1);
+     /* load old bit from wire */
+     __ld_bit(&oav, &obv, np, bi); 
+     if (np->nu.rngdwir->n_delrep == DT_PTHDST)
+      schd_1pthwirebit(np, bi, aval, (oav | (obv << 1)));
+     else __wdel_schd_1wirebit(np, bi, aval, (oav | (obv << 1)), FALSE);
+    }
+  }
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * part select numbits from swp (starting at 0) into dwp starting at dbi
+ * assume swp part starts at bit 0
+ * preserves high unused bits of new high word32 of dwp
+ */
+extern void __lhspsel(register word32 *dwp, register int32 dbi,
+ register word32 *swp, register int32 numbits)
+{
+ register int32 wi;
+
+ /* correct so part select goes into 1st word32 */
+ if (dbi >= WBITS)
+  { wi = get_wofs_(dbi); dwp = &(dwp[wi]); dbi = get_bofs_(dbi); }
+ /* if swp too short must correct */
+ if (dbi == 0) ins_walign(dwp, swp, numbits);
+ else __ins_wval(dwp, dbi, swp, numbits);
+}
+
+/*
+ * insert aligned on word32 boudary dest. dwp numbits from swp 
+ * preserves any unused high bits of high destination word
+ * and ignored any used high bits of swp (wider than numbits)
+ * if swp too narror correction made before here
+ */
+static void ins_walign(register word32 *dwp, register word32 *swp,
+ register int32 numbits)
+{
+ register int32 ubits, wlen;
+ word32 save_val;
+
+ if (numbits <= WBITS)
+  {
+   /* preserve high bits and zero low */
+   *dwp &= ~__masktab[numbits];
+   /* or in new low bits - aligned to low (right) bits of word32 */
+   /* if high bits of swp word32 used - will be masked off here */
+   *dwp |= (*swp & __masktab[numbits]);
+  }
+ else
+  {
+   ubits = ubits_(numbits);
+   /* need set brackets here since macro is multiple statements */
+   if (ubits == 0) { cp_walign_(dwp, swp, numbits); }
+   else
+    {
+     wlen = wlen_(numbits);
+     save_val = dwp[wlen - 1] & ~__masktab[ubits];
+     /* in case high word32 of swp has 0 bits (too wide), */
+     /* copy will mask those bits off - high word32 ignored */
+     cp_walign_(dwp, swp, numbits);
+     dwp[wlen - 1] |= save_val;
+    }
+  }
+}
+
+/*
+ * insert value into dwp at index dbi from swp with length sblen
+ * assume swp part starts at bit 0 but dwp and dbi corrected so dbi < WBITS
+ * preserves high unused bits of new high word32 of dwp
+ */
+extern void __ins_wval(register word32 *dwp, register int32 dbi,
+ register word32 *swp, int32 numbits)
+{
+ register word32 save_val, mask;
+ int32 wlen, w2bits;
+
+ /* case 1a - fits in 1st actual word32 */
+ if (dbi + numbits <= WBITS)
+  {
+   mask = __masktab[numbits] << dbi;
+   *dwp = (*dwp & ~mask) | ((*swp << dbi) & mask);
+   return;
+  }
+ /* case 2 - less than 32 bits but crosses word32 boundary */
+ if (numbits <= WBITS)
+  {
+   /* preserve low bits */
+   *dwp = (*dwp & __masktab[dbi]);
+   *dwp |= (*swp << dbi);
+
+   w2bits = numbits - (WBITS - dbi);
+   dwp[1] = (dwp[1] & ~__masktab[w2bits])
+    | ((*swp >> (WBITS - dbi)) & __masktab[w2bits]);
+   return;
+  }
+ /* case 3 - general multiword case */
+ w2bits = numbits + dbi;
+ /* w2bits is length in bits starting from start of dest word32 */
+ wlen = wlen_(w2bits);
+ save_val = dwp[wlen - 1] & ~__masktab[ubits_(w2bits)];
+ cp_dofs_wval(dwp, swp, dbi, numbits);
+ dwp[wlen - 1] |= save_val;
+}
+
+/*
+ * routine to copy one value to another assuming dest. 1st bit is non 0
+ * but copies from source bit 0
+ * notice preserves bits to right of dbit1 but does not preserve high
+ * bits of high word
+ * dbit1 is offset in 1st word32 of dest. (>0 and <WBITS)
+ *
+ * copy from non 0 bit of source to 0 bitb of destionation use cp_sofs_wval
+ *
+ * chgs high unused bits of dest. word32 to 0's - caller must save if needed
+ * this should probably be macro
+ */
+static void cp_dofs_wval(register word32 *dwp, register word32 *swp,
+ int32 dbit1, int32 numbits)
+{
+ int32 dbit2;
+
+ /* do 1st word32 as special case */
+ dwp[0] &= __masktab[dbit1];
+ dwp[0] |= (swp[0] << dbit1);
+ dbit2 = WBITS - dbit1;
+ if (dbit2 >= numbits) return;
+ numbits -= dbit2;
+ __cp_sofs_wval(&(dwp[1]), swp, dbit2, numbits);
+}
+
+/*
+ * copy one value to another assuming source 1st bit is non 0
+ * but copies into destination starting at bit 0
+ * sbit1 is offset in 1st word32 (>0 and <WBITS)
+ *
+ * to copy into dwp non bit 0 copy use cp_dofs_wval
+ * and then use this routine with WBITS - dbit1 for rest
+ *
+ * chgs high unused bits of dest. word32 to 0's - caller must save and restore
+ * this should probably be macro
+ */
+extern void __cp_sofs_wval(register word32 *dwp, register word32 *swp,
+ register int32 sbit1, register int32 numbits)
+{
+ register int32 wi, bi, sbit2;
+
+ sbit2 = WBITS - sbit1;
+ for (bi = 0, wi = 0; ; wi++)
+  {
+   dwp[wi] = (swp[wi] >> sbit1);
+   if ((bi += sbit2) >= numbits) break;
+   dwp[wi] |= (swp[wi + 1] << sbit2);
+   if ((bi += sbit1) >= numbits) break;
+  }
+ /* bits in high source word32 will probably be on but must not be selected */
+ dwp[wi] &= __masktab[ubits_(numbits)];
+}
+
+/*
+ * change store a part select - only for non strength vector
+ *
+ * LOOKATME - notice no non chg form store into psel
+ */ 
+static void chg_st_psel(struct net_t *np, int32 ri1, int32 ri2,
+ register word32 *ap, register word32 *bp)
+{
+ register int32 bi, bi2;
+ int32 pslen;
+ byte *netsbp, *newsbp;
+
+ /* SJM 07/15/00 - now all non mem vecs in at least 2 wrds - scalars in byte */
+ /* while this needs words since always some number of words */
+ if (np->srep == SR_VEC)
+  chg_st_unpckpsel(np->nva.wp, np->nwid, ri1, ri2, ap, bp);
+ else
+  {
+   netsbp = &(np->nva.bp[np->nwid*__inum]);
+   newsbp = (byte *) ap;
+   pslen = ri1 - ri2 + 1;
+   /* case 1: part select size same or narrower than rhs - truncation */
+   for (bi = ri2, bi2 = 0; bi2 < pslen; bi++, bi2++)
+    {
+     if (netsbp[bi] != newsbp[bi2])
+      { netsbp[bi] = newsbp[bi2]; __lhs_changed = TRUE; } 
+    }
+  }
+ /* notice since know dce and npps never ranges unless possible */
+ /* do not need to correct vectored or reg subrange to entire wire */
+ /* SJM 07/24/00 - because only ch store psel - no record if no dces/lds */ 
+ /* SJM 03/15/01 - change to fields in net record */
+ if (__lhs_changed && np->nchg_nd_chgstore)
+  {
+   record_sel_nchg_(np, ri1, ri2);
+  }
+}
+
+/*
+ * change version of store psel for unpacked vector
+ */
+static void chg_st_unpckpsel(word32 *wp, int32 blen, int32 bith, int32 bitl,
+ register word32 *ap, register word32 *bp)
+{
+ register word32 *rap;
+ int32 wlen, numbits;
+
+ /* this is rightmost in word32, leftmost among words bit */
+ numbits = bith - bitl + 1;
+ wlen = wlen_(blen);
+ rap = &(wp[2*wlen*__inum]);
+ __chg_lhspsel(rap, bitl, ap, numbits);
+ rap = &(rap[wlen]);
+ __chg_lhspsel(rap, bitl, bp, numbits);
+}
+
+/*
+ * only store if change form of lhs psel
+ */
+extern void __chg_lhspsel(register word32 *dwp, register int32 dbi,
+ register word32 *swp, register int32 numbits)
+{
+ register int32 wi;
+ int32 wlen, ubits;
+
+ /* correct so part select goes into 1st word32 */
+ if (dbi >= WBITS)
+  { wi = get_wofs_(dbi); dwp = &(dwp[wi]); dbi = ubits_(dbi); }
+ /* if swp too short must correct */
+ if (dbi == 0)
+  {
+   if (numbits <= WBITS)
+    {
+     if ((dwp[0] & __masktab[numbits]) != (swp[0] & __masktab[numbits])) 
+      {
+       ins_walign(dwp, swp, numbits);
+       __lhs_changed = TRUE;
+      }
+    }
+   else
+    {
+     wlen = wlen_(numbits);
+     ubits = ubits_(numbits);
+
+     /* if any differences copy all */
+     /* when comparing high word32 - dest. high bits are masked off */
+     if ((dwp[wlen - 1] & __masktab[ubits])
+      != (swp[wlen - 1] & __masktab[ubits]) 
+      || memcmp(dwp, swp, WRDBYTES*(wlen - 1)) != 0) 
+      {
+       ins_walign(dwp, swp, numbits);
+       __lhs_changed = TRUE;
+      }
+    }
+   return;
+  }
+ /* unaligned case */
+ chg_ins_wval(dwp, dbi, swp, numbits);
+}
+
+/*
+ * only assign if changed form of unaligned ins_wval 
+ */
+static void chg_ins_wval(register word32 *dwp, register int32 dbi,
+ register word32 *swp, register int32 numbits)
+{
+ register word32 mask;
+ word32 save_val;
+ int32 wlen, w2bits;
+
+ /* case 1a - fits in 1st actual word32 */
+ if (dbi + numbits <= WBITS)
+  {
+   mask = __masktab[numbits] << dbi;
+   save_val = (swp[0] << dbi) & mask;
+   if ((dwp[0] & mask) != save_val)
+    { dwp[0] = (dwp[0] & ~mask) | save_val; __lhs_changed = TRUE; }
+   return;
+  }
+ /* case 2 - less than 32 bits but crosses word32 boundary */
+ if (numbits <= WBITS)
+  {
+   w2bits = numbits - (WBITS - dbi);
+
+   /* compare 1st word32 dbi to 31 versus 32 - dbi low bits of source */ 
+   /* compare 2nd word32 numbits - 32 - dbi  to dbi to numbits of source */
+   mask = __masktab[w2bits];
+   if ((dwp[0] & ~__masktab[dbi]) != (swp[0] << dbi) ||
+    ((dwp[1] & mask) != ((swp[0] >> (WBITS - dbi)) & mask)))
+    {
+     /* remove high (WBITS - dbi) bits (0s) */
+     dwp[0] &= (dwp[0] & __masktab[dbi]);
+     /* or into 0's low (WBITS - dbi) into range [31:dbi] */
+     dwp[0] |= (swp[0] << dbi);
+     /* remove low w2bits and or in all but low (WBITS - dbi) from new */
+     dwp[1] = (dwp[1] & ~mask) | ((swp[0] >> (WBITS - dbi)) & mask);
+     __lhs_changed = TRUE;
+    }
+   return;
+  }
+
+ /* case 3 - general multiword case */
+ if (chg_ofs_cmp(dwp, swp, dbi, numbits) == 0) return;
+
+ /* SJM 03/29/02 - handles restoring high big problem by saving and putting */
+ /* back - these copies always zero high bits when done so or works */
+ w2bits = numbits + dbi;
+ /* w2bits is length in bits starting from start of dest word32 */
+ wlen = wlen_(w2bits);
+ save_val = dwp[wlen - 1] & ~__masktab[ubits_(w2bits)];
+ cp_dofs_wval(dwp, swp, dbi, numbits);
+ dwp[wlen - 1] |= save_val;
+ __lhs_changed = TRUE;
+}
+
+/*
+ * compare source versus destination ofset by dbi bits
+ * returns 0 for equal 1 for not
+ * know source (new) always aligned to bit 0
+ *
+ * 03/17/02 - changed so saves and zeros high bits so compe works  
+ */
+static int32 chg_ofs_cmp(register word32 *dwp, register word32 *swp,
+ int32 dbi, int32 numbits)
+{
+ register int32 bi; 
+ register word32 mask1, mask2;
+ int32 wi, sbit2, w2bits, w2len, chged;
+ word32 save_val;
+
+ sbit2 = WBITS - dbi;
+
+ mask1 = __masktab[dbi];
+ mask2 = __masktab[sbit2];
+
+ w2bits = numbits + dbi;
+ w2len = wlen_(w2bits);
+ /* trick here is to save and set high bits to 0's so do not need */
+ /* high bit special case and can use saved val if copy needed */
+ save_val = dwp[w2len - 1] & ~__masktab[ubits_(w2bits)];
+ dwp[w2len - 1] &= __masktab[ubits_(w2bits)];
+
+ /* assume chged */
+ chged = 1;
+
+ /* 1st word32 is special case */
+ if ((dwp[0] & ~__masktab[dbi]) != (swp[0] << dbi)) goto done_putback;
+ numbits -= sbit2;
+
+ for (bi = 0, wi = 1; ; wi++)
+  {
+   if ((dwp[wi] & mask1) != ((swp[wi - 1] >> sbit2) & mask1))
+    goto done_putback;
+   if ((bi += dbi) >= numbits) break;
+
+   if (((dwp[wi] >> dbi) & mask2) != (swp[wi] & mask2))
+    goto done_putback;
+   if ((bi += sbit2) >= numbits) break;
+  }
+ chged = 0;
+
+done_putback:
+ /* finally put back high bits of dest word32 */
+ dwp[w2len - 1] |= save_val;
+ return(chged); 
+}
+
+/* SJM 07/15/00 - now 2 to 16 bit vectors not packed - in 2 words */
+
+/*
+ * SIZE CHANGE AND Z EXTENSION ROUTINES
+ */
+
+/*
+ * widen or narrow a stack value (only for rhs exprs)
+ * know bit widths differ or will not be called
+ * this may need to widen stack value width (alloc-free) 
+ * also if widens zeros all bits
+ *
+ * this is not for z filling but for normal operators where no z filling
+ * allowed - may z fill in assignment after this size change done
+ * also does not work for strengths
+ */
+extern void __sizchgxs(register struct xstk_t *xsp, int32 nblen)
+{
+ register int32 wi;
+ register word32 *wpna, *wpnb, *wpob;
+ int32 nwlen, nubits, stkwlen, xtrabits;
+
+ /* case 1: widening */
+ if (xsp->xslen < nblen)
+  {
+   /* case 1a: stays in one word32 */ 
+   if (nblen <= WBITS) goto done;
+   nwlen = wlen_(nblen);
+   /* case 1b: multiword but into same number of words - does nothing */
+   stkwlen = wlen_(xsp->xslen);
+   if (nwlen == stkwlen) goto done;
+   nubits = ubits_(nblen);
+   /* case 1c: wider needs bigger area */
+   if (nwlen > xsp->xsawlen)
+    {
+     /* SJM 05/16/04 sign change was wrong - need to copy low parts */ 
+     /* of a and b separately */
+     wpna = (word32 *) __my_malloc(2*WRDBYTES*nwlen);
+     memcpy(wpna, xsp->ap, WRDBYTES*xsp->xsawlen);
+     /* SJM 09/29/04 widening b part is new wlen offset from a part */
+     /* SJM 10/02/04 wasn't fixed right was using wrong old xsp ap part */
+     wpnb = &(wpna[nwlen]);
+     memcpy(wpnb, xsp->bp, WRDBYTES*xsp->xsawlen);
+
+     __my_free((char *) xsp->ap, 2*WRDBYTES*xsp->xsawlen);
+     xsp->ap = wpna;
+     xsp->bp = wpnb;
+     xsp->xsawlen = nwlen;
+    }
+   else
+    { 
+     /* case 1d: wider by adjusting loc in region of b part and copying */
+     wpob = xsp->bp;
+     /* SJM 09/29/04 widening b part should be new wlen offset from a part */
+     wpnb = &(xsp->ap[nwlen]);
+
+     /* must copy high to low to preserve high old */ 
+     for (wi = stkwlen - 1; wi >= 0; wi--) wpnb[wi] = wpob[wi]; 
+     xsp->bp = wpnb; 
+    }
+   /* 0 wide new high bits */
+   xtrabits = (nblen - WBITS*stkwlen);
+   zero_allbits_(&(xsp->ap[stkwlen]), xtrabits);
+   zero_allbits_(&(xsp->bp[stkwlen]), xtrabits);
+   goto done;
+  }
+ /* case 2 narrowing case - know cannot be 1 bit to start */
+ /* case 2a: narrow to 1 bit */
+ nwlen = wlen_(nblen);
+ nubits = ubits_(nblen);
+ stkwlen = wlen_(xsp->xslen);
+ /* case 2b: narrowing where narrower same number of words */
+ if (stkwlen == nwlen)
+  {
+   xsp->ap[nwlen - 1] &= __masktab[nubits];
+   xsp->bp[nwlen - 1] &= __masktab[nubits];
+   goto done;
+  }
+ /* case 2c: general narrowing */
+ /* SJM 09/29/04 widening b part should be new wlen offset from a part */
+ wpnb = &(xsp->ap[nwlen]);
+ wpob = xsp->bp;
+ /* need loop because must make sure copy low first */
+ for (wi = 0; wi < nwlen; wi++) wpnb[wi] = wpob[wi];
+ xsp->bp = wpnb;
+ xsp->ap[nwlen - 1] &= __masktab[nubits];
+ xsp->bp[nwlen - 1] &= __masktab[nubits];
+done:
+ xsp->xslen = nblen;
+}
+
+/*
+ * zero widen a stack value (only for rhs exprs) - not for sign extend
+ * know need to widen or will not be called
+ * this may need to widen stack value width (alloc-free) 
+ * also if widens zeros all bits (not for sign extend widening)
+ */
+extern void __sizchg_widen(register struct xstk_t *xsp, int32 nblen)
+{
+ register int32 wi;
+ register word32 *wpna, *wpnb, *wpob;
+ int32 nwlen, nubits, stkwlen, xtrabits;
+
+ /* case 1: widening */
+ if (nblen <= WBITS) { xsp->xslen = nblen; return; }
+ nwlen = wlen_(nblen);
+ /* case 2: multiword but into same number of words - does nothing */
+ stkwlen = wlen_(xsp->xslen);
+ if (nwlen == stkwlen) { xsp->xslen = nblen; return; }
+ nubits = ubits_(nblen);
+ /* case 1c: wider needs bigger area */
+ if (nwlen > xsp->xsawlen)
+  {
+   /* SJM 05/16/04 - 9-29 sign change was wrong - need to copy low parts */ 
+   /* of a and b separately */
+   wpna = (word32 *) __my_malloc(2*WRDBYTES*nwlen);
+   memcpy(wpna, xsp->ap, WRDBYTES*xsp->xsawlen);
+   /* SJM 09/29/04 widening b part should be new wlen offset from a part */
+   /* SJM 10/02/04 wasn't fixed right was using wrong old xsp ap part */
+   wpnb = &(wpna[nwlen]);
+   memcpy(wpnb, xsp->bp, WRDBYTES*xsp->xsawlen);
+
+   __my_free((char *) xsp->ap, 2*WRDBYTES*xsp->xsawlen);
+   xsp->ap = wpna;
+   xsp->bp = wpnb;
+   xsp->xsawlen = nwlen;
+  }
+ else
+  { 
+   /* case 1d: wider by adjusting loc in region of b part and copying */
+   wpob = xsp->bp;
+   /* SJM 09/29/04 widening b part should be new wlen offset from a part */
+   wpnb = &(xsp->ap[nwlen]);
+   /* must copy high to low to preserve high old */ 
+   for (wi = stkwlen - 1; wi >= 0; wi--) wpnb[wi] = wpob[wi]; 
+   xsp->bp = wpnb; 
+  }
+ /* 0 wide new high bits */
+ xtrabits = (nblen - WBITS*stkwlen);
+ zero_allbits_(&(xsp->ap[stkwlen]), xtrabits);
+ zero_allbits_(&(xsp->bp[stkwlen]), xtrabits);
+ xsp->xslen = nblen;
+}
+
+/*
+ * widen a stack using signed extension (narrow case handled in other routine)
+ *
+ * know need widening (maybe within one word32) - checks and extends sign
+ * if needed
+ *
+ * this may need to widen stack value width (alloc-free) but never pops/pushes
+ * also routine does not work for strens
+ */
+extern void __sgn_xtnd_widen(struct xstk_t *xsp, int32 nblen)
+{
+ register int32 wi, osgn_bofs;
+ register word32 mask;
+ word32 *wpna, *wpnb, *wpob;
+ int32 nwlen, stkwlen, widen_amt, xtra_wbits, ival;
+
+ /* case 1: stays in one word32 */ 
+ if (nblen <= WBITS)
+  {
+   osgn_bofs = xsp->xslen - 1;
+   /* if signed, sign extend, otherwise nothing to do */
+   if ((xsp->ap[0] & (1 << (osgn_bofs))) != 0)
+    {
+     mask = __masktab[nblen - osgn_bofs + 1] << (osgn_bofs + 1);
+     xsp->ap[0] |= mask;
+     /* if x/z x/z extend */
+     if ((xsp->bp[0] & (1 << (osgn_bofs))) != 0) xsp->bp[0] |= mask;
+    }
+   else
+    {
+     if ((xsp->bp[0] & (1 << (osgn_bofs))) != 0)
+      {
+       /* since sign bit off, 0 extend a part but if z, z extend b part */
+       mask = __masktab[nblen - osgn_bofs + 1] << (osgn_bofs + 1);
+       if ((xsp->bp[0] & (1 << (osgn_bofs))) != 0) xsp->bp[0] |= mask;
+      }
+    }
+   xsp->xslen = nblen;
+   return;
+  }
+ nwlen = wlen_(nblen);
+ /* case 2: multiword but into same number of words */
+ stkwlen = wlen_(xsp->xslen);
+
+ if (nwlen == stkwlen)
+  {
+   osgn_bofs = get_bofs_(xsp->xslen - 1);
+
+   /* if signed, sign extend, otherwise nothing to do */
+   /* notice nwlen and stkwlen same */
+   if ((xsp->ap[nwlen - 1] & (1 << osgn_bofs)) != 0)
+    {
+     mask = ((__masktab[ubits_(nblen) - osgn_bofs + 1]) << (osgn_bofs + 1));
+     xsp->ap[nwlen - 1] |= mask;
+     /* SJM 09/29/04 - was checking word32 after high end not high word32 */
+     /* if x/z, x/z extend */
+     if ((xsp->bp[nwlen - 1] & (1 << (osgn_bofs))) != 0)
+      xsp->bp[nwlen - 1] |= mask;
+    }
+   else
+    {
+     if ((xsp->bp[0] & (1 << (osgn_bofs))) != 0)
+      {
+       mask = ((__masktab[ubits_(nblen) - osgn_bofs + 1]) << (osgn_bofs + 1));
+       /* SJM 09/29/04 - was masking word32 after high end not high word32 */
+       xsp->bp[nwlen - 1] |= mask;
+      }
+    }
+   xsp->xslen = nblen;
+  }
+
+ /* case 3: wider - first create the larger area */
+ if (nwlen > xsp->xsawlen)
+  {
+   /* SJM 05/16/04 - 9-29 sign change was wrong - need to copy low parts */ 
+   /* of a and b separately */
+   wpna = (word32 *) __my_malloc(2*WRDBYTES*nwlen);
+   memcpy(wpna, xsp->ap, WRDBYTES*xsp->xsawlen);
+   /* SJM 09/29/04 widening b part should be new wlen offset from a part */
+   wpnb = &(wpna[nwlen]);
+   memcpy(wpnb, xsp->bp, WRDBYTES*xsp->xsawlen);
+
+   __my_free((char *) xsp->ap, 2*WRDBYTES*xsp->xsawlen);
+   xsp->ap = wpna;
+   xsp->bp = wpnb;
+   xsp->xsawlen = nwlen;
+  }
+ else
+  { 
+   /* case 1d: wider by adjusting loc in region of b part and copying */
+   wpob = xsp->bp;
+   /* SJM 09/29/04 widening b part should be new wlen offset from a part */
+   wpnb = &(xsp->ap[nwlen]);
+   /* must copy high to low to preserve high old */ 
+   for (wi = stkwlen - 1; wi >= 0; wi--) wpnb[wi] = wpob[wi]; 
+   xsp->bp = wpnb; 
+  }
+
+ /* widen amount is number of bits to set to 1 (sign extend into) */
+ widen_amt = nblen - xsp->xslen; 
+ /* this is position in old narrower value */
+ osgn_bofs = get_bofs_(xsp->xslen - 1);
+ /* xtra bits is bit num bits with high bits of sign words subtracted */
+ xtra_wbits = widen_amt - (WBITS - osgn_bofs - 1);
+
+ /* AIV 06/23/05 - special case don't check for sign if 32 bits */
+ /* just cast to int and copy high part */
+ if (xsp->xslen == WBITS)
+  {
+   ival = (int32) xsp->ap[0];
+   if (ival < 0) one_allbits_(&(xsp->ap[stkwlen]), xtra_wbits);
+   else zero_allbits_(&(xsp->ap[stkwlen]), xtra_wbits);
+   ival = (int32) xsp->bp[0];
+   if (ival < 0) one_allbits_(&(xsp->bp[stkwlen]), xtra_wbits);
+   else zero_allbits_(&(xsp->bp[stkwlen]), xtra_wbits);
+   xsp->xslen = nblen;
+   return;
+  }
+
+ /* now can set new widened size */
+ xsp->xslen = nblen;
+
+ /* sign extend if sign bit on, x/z extend if sign bit x/z, else 0 extend */
+ if ((xsp->ap[stkwlen - 1] & (1 << osgn_bofs)) != 0)
+  {
+   mask = __masktab[WBITS - osgn_bofs - 1] << (osgn_bofs + 1);
+   /* one high bits of this word32 */
+   xsp->ap[stkwlen - 1] |= mask;
+   /* then all bits of rest */
+   one_allbits_(&(xsp->ap[stkwlen]), xtra_wbits);
+
+   /* if x/z x/z extend */
+   if ((xsp->bp[stkwlen - 1] & (1 << osgn_bofs)) != 0)
+    {
+     xsp->bp[stkwlen - 1] |= mask;
+     one_allbits_(&(xsp->bp[stkwlen]), xtra_wbits);
+    } 
+   /* know high bits of high old size word32 0, but 0 all new words */
+   else zero_allbits_(&(xsp->bp[stkwlen]), xtra_wbits);
+   return;
+  }
+ /* a part sign bit off, 0 all high a part words */
+ zero_allbits_(&(xsp->ap[stkwlen]), xtra_wbits);
+ if ((xsp->bp[stkwlen - 1] & (1 << osgn_bofs)) != 0)
+  {
+   mask = __masktab[WBITS - osgn_bofs - 1] << (osgn_bofs + 1);
+   xsp->bp[stkwlen - 1] |= mask;
+   one_allbits_(&(xsp->bp[stkwlen]), xtra_wbits);
+   return;
+  }
+ /* 0 wide new high bits */
+ zero_allbits_(&(xsp->bp[stkwlen]), xtra_wbits);
+}
+
+/*
+ * sign extend widen within one word
+ */
+extern void __sgn_xtnd_wrd(register struct xstk_t *xsp, int32 nblen)
+{
+ register int32 oubits;
+ register word32 mask;
+
+ oubits = xsp->xslen;
+ /* if signed, sign extend, otherwise nothing to do */
+ if ((xsp->ap[0] & (1 << (oubits - 1))) != 0)
+  {
+   mask = (__masktab[WBITS - oubits]) << oubits;
+   xsp->ap[0] |= mask;
+   /* if x/z x/z extend */
+   if ((xsp->bp[0] & (1 << (oubits - 1))) != 0) xsp->bp[0] &= mask;
+  }
+ else
+  {
+   mask = (__masktab[WBITS - oubits]) << oubits;
+   if ((xsp->bp[0] & (1 << (oubits - 1))) != 0)
+    xsp->bp[0] |= mask;
+  }
+ xsp->xslen = nblen;
+}
+
+/*
+ * special case narrow to 1 routine 
+ */
+extern void __narrow_to1bit(register struct xstk_t *xsp)
+{
+ register int32 stkwlen;
+
+ stkwlen = wlen_(xsp->xslen);
+ /* case 1: narrowing within one word32 */
+ if (stkwlen == 1) { xsp->ap[0] &= 1; xsp->bp[0] &= 1; }
+ else
+  {
+   /* case 2: wide to 1 bit narrow */
+   xsp->ap[0] &= 1; 
+   xsp->ap[1] = xsp->bp[0] & 1;
+   xsp->bp = &(xsp->ap[1]); 
+  }
+ xsp->xslen = 1;
+}
+
+/*
+ * special case narrow to WBITS routine 
+ */
+extern void __narrow_to1wrd(register struct xstk_t *xsp)
+{
+ register int32 stkwlen;
+
+ stkwlen = wlen_(xsp->xslen);
+ /* DBG remove -- */
+ if (stkwlen == 1) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ xsp->ap[1] = xsp->bp[0];
+ xsp->bp = &(xsp->ap[1]); 
+ xsp->xslen = WBITS;
+}
+
+/*
+ * narrow a stack value (only for rhs exprs)
+ * know need to narrow or will not be called
+ */
+extern void __narrow_sizchg(register struct xstk_t *xsp, int32 nblen)
+{
+ register int32 wi;
+ register word32 *wpnb, *wpob;
+ int32 nwlen, nubits, stkwlen;
+
+ /* know cannot be 1 bit to start */
+ nwlen = wlen_(nblen);
+ nubits = ubits_(nblen);
+ stkwlen = wlen_(xsp->xslen);
+ /* case 2b: narrowing where narrower same number of words */
+ if (stkwlen == nwlen)
+  {
+   xsp->ap[nwlen - 1] &= __masktab[nubits];
+   xsp->bp[nwlen - 1] &= __masktab[nubits];
+   xsp->xslen = nblen;
+   return;
+  }
+ /* case 2c: general narrowing */
+ /* SJM 09/29/04 widening b part should be new wlen offset from a part */
+ wpnb = &(xsp->ap[nwlen]);
+ wpob = xsp->bp;
+ /* need loop because must make sure copy low first */
+ /* this insures a/b parts contiguous */ 
+ for (wi = 0; wi < nwlen; wi++) wpnb[wi] = wpob[wi];
+ xsp->bp = wpnb;
+ xsp->ap[nwlen - 1] &= __masktab[nubits];
+ xsp->bp[nwlen - 1] &= __masktab[nubits];
+ xsp->xslen = nblen;
+}
+
+/*
+ * after widening stack, z extend new high bits if needed
+ * know nblen greater than oblen
+ *
+ * this is only for non stren case since stren never assigned only added
+ * from something that drives strength (gates are exception and handled as
+ * special case elsewhere)
+ */
+extern void __fix_widened_tozs(struct xstk_t *xsp, int32 oblen)
+{
+ register int32 wi;
+ int32 nblen, owlen, nwlen, oubits, nubits;
+
+ /* case 1: same number of words */
+ nblen = xsp->xslen;
+ nubits = ubits_(nblen);
+ oubits = ubits_(oblen);
+ owlen = wlen_(oblen);
+ nwlen = wlen_(nblen);
+ if (owlen == nwlen)
+  {
+   xsp->bp[owlen - 1] |= (__masktab[nubits] & ~__masktab[oubits]); 
+   return;
+  }
+ /* case 2 widen to more words */
+ /* set b part high bits of high old word32 to 1s */ 
+ xsp->bp[owlen - 1] |= ~__masktab[oubits];
+ /* set b part of all high words */
+ for (wi = owlen; wi < nwlen; wi++) xsp->bp[wi] = ALL1W;
+ /* except unused high bit of new high word32 */
+ xsp->bp[nwlen - 1] &= __masktab[nubits];
+}
+
+/*
+ * after widening stack, x extend new high bits if needed
+ * know nblen greater than oblen
+ * this is only for non strength initialization case
+ */
+extern void __fix_widened_toxs(register struct xstk_t *xsp, int32 oblen)
+{
+ register int32 wi;
+ int32 nblen, owlen, nwlen, oubits, nubits;
+
+ /* case 1: same number of words */
+ nblen = xsp->xslen;
+ nubits = ubits_(nblen);
+ oubits = ubits_(oblen);
+ owlen = wlen_(oblen);
+ nwlen = wlen_(nblen);
+ if (owlen == nwlen)
+  {
+   xsp->ap[owlen - 1] |= (__masktab[nubits] & ~__masktab[oubits]); 
+   xsp->bp[owlen - 1] |= (__masktab[nubits] & ~__masktab[oubits]); 
+   return;
+  }
+ /* case 2 widen to more words */
+ /* set b part high bits of high old word32 to 1s */ 
+ /* SJM 02/18/03 WRONG - also need to mask in 1's for a part */
+ /* code came from widen to z's so a part was missing */ 
+ xsp->ap[owlen - 1] |= ~__masktab[oubits];
+ xsp->bp[owlen - 1] |= ~__masktab[oubits];
+ /* set all high words to x */
+ for (wi = owlen; wi < nwlen; wi++) xsp->ap[wi] = ALL1W;
+ for (wi = owlen; wi < nwlen; wi++) xsp->bp[wi] = ALL1W;
+ /* except unused high bit of new high word32 */
+ xsp->ap[nwlen - 1] &= __masktab[nubits];
+ xsp->bp[nwlen - 1] &= __masktab[nubits];
+}
+
+/*
+ * widen a stacked strength byte value (only for rhs exprs)
+ * know bit widths differ or will not be called
+ * this may need to widen stack value width (alloc-free) 
+ * also if widens z's 00z all bits
+ *
+ * 07/08/00 SJM - also used to widen fi>1 strength driver competition results
+ *
+ * for strength all extension must be z
+ * for narrow just adjust xslen 
+ */
+extern void __strenwiden_sizchg(struct xstk_t *xsp, int32 nblen)
+{
+ register int32 bi;
+ byte *sbp, *sbp2;
+ int32 oblen, numavailbytes, wlen;
+
+ /* DBG remove -- */
+ if ((xsp->xslen % 4) != 0) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ oblen = xsp->xslen/4;
+ sbp = (byte *) xsp->ap;
+ /* case 1: widening */
+ if (oblen < nblen)
+  {
+   numavailbytes = 2*WRDBYTES*xsp->xsawlen; 
+   if (numavailbytes < nblen)
+    {
+     /* just widen to enough room plus 1 word32 */
+     wlen = (nblen + WRDBYTES - 1)/WRDBYTES + 1;
+     /* SJM 05/23/03 - freed and realloced with size 2 times - was not */
+     /* allocing both a and b parts but was freeing */
+     xsp->ap = (word32 *) __my_malloc(2*wlen*WRDBYTES);
+     xsp->xsawlen = wlen;
+     sbp2 = (byte *) xsp->ap;
+     /* LOOKATME - think overlap possible here */
+     memmove(sbp2, sbp, oblen); 
+     __my_free((char *) sbp, numavailbytes);
+     sbp = sbp2;
+    }
+   for (bi = oblen; bi < nblen; bi++) sbp[bi] = ST_HIZ;
+   xsp->xslen = 4*nblen;
+  }
+ /* case 2: narrow */
+ else xsp->xslen = 4*nblen;
+}
+
+/*
+ * BUILT-IN GATE AND UDP EVALUATION ROUTINES
+ */
+
+/*
+ * evaluate logic gate - know input changed and changes recorded in gstate
+ * set new value in new gateval and if needs strength in new gate stren 
+ * and if return T sets old gateval
+ * returns F if no change (new value and old the same)
+ * gate values here never have strength - maybe added when stored in wire
+ * 
+ * i is position of gate input expr. starting at 1, bi bit starting at 0
+ */
+extern int32 __eval_logic_gate(struct gate_t *gp, word32 i, int32 *out_chg)
+{
+ register word32 *rap, uwrd, ouwrd, ngav, ngbv;
+ register word32 gav, gbv, mask;
+ int32 gwid, wlen, bi, gatid;
+ struct xstk_t *xsp;
+
+ gwid = gp->gpnum;
+ xsp = __eval_xpr(gp->gpins[i]);
+ bi = i - 1; 
+ ngav = xsp->ap[0] & 1L;
+ ngbv = xsp->bp[0] & 1L;
+ __new_inputval = ngav | (ngbv << 1);
+ __pop_xstk();
+
+ /* always set strength even if not needed - always constant here */
+ /* rare wide case */
+ if (gwid > 16)
+  {
+   wlen = wlen_(gwid);
+   /* rap is base of vector for current inst */
+   rap = &(gp->gstate.wp[2*wlen*__inum]);
+   chg_lhsbsel(rap, bi, ngav);
+   chg_lhsbsel(&(rap[wlen]), bi, ngbv);
+   if (!__lhs_changed) return(FALSE);
+   /* this set global new and old gate values */
+   *out_chg = __eval_1wide_gate(gp, gwid);
+   return(TRUE);
+  }
+
+ /* eval changed input expr. and store in gstate if needed */
+ /* know packed both a and b sections in same word32 */
+ /* SJM 12/16/99 still packing gate state as usual */
+ ouwrd = get_packintowrd_(gp->gstate, __inum, gwid);
+ uwrd = ouwrd & ~(1L << bi) & ~(1L << (gwid + bi));
+ uwrd |= ((ngav << bi) | (ngbv << (gwid + bi))); 
+ if (uwrd == ouwrd) return(FALSE);
+ st_packintowrd_(gp->gstate, __inum, uwrd, gwid);
+
+ /* now need gate id */
+ gatid = gp->gmsym->el.eprimp->gateid;
+ /* buf (assign buf) or not short circuit */
+ /* now reusing ngav/ngbv as new output value no longer new input value */
+ /* FIXME not allowing multiple output nots and bufs yet */
+ if (gwid == 2)
+  {
+   /* old gate value b part in 3 and a part in bit 1 */
+   __old_gateval = ((uwrd >> 1) & 1L) | ((uwrd >> 2) & 2L); 
+   ngbv = (uwrd >> 2) & 1L;
+   /* buf and not always convert z to x */ 
+   if (gatid == G_NOT) ngav = !(uwrd & 1L) | ngbv;
+   else if (gatid == G_BUF) ngav = (uwrd & 1L) | ngbv;
+   /* but cont. ASSIGN passes z */
+   else if (gatid == G_ASSIGN) ngav = (uwrd & 1L);
+   else 
+    {
+     switch ((byte) gatid) {
+      case G_BITREDAND: case G_BITREDOR: case G_BITREDXOR:
+       ngav = (uwrd & 1L) | ngbv;
+       break;
+      case G_NAND: case G_NOR: case G_REDXNOR:
+       ngav = !(uwrd & 1L) | ngbv;
+       break;
+     }
+    }
+   goto done;
+  }
+
+ /* need to handle 2 input gates as partial special case */
+ if (gwid == 3)
+  {
+   mask = __masktab[2];
+   gav = uwrd & 3L;
+   gbv = (uwrd >> 3) & 3L;
+   __old_gateval = ((uwrd >> 2) & 1L) | ((uwrd >> 4) & 2L);
+  }
+ else
+  {
+   /* gav and gbv are inputs only */
+   mask = __masktab[gwid - 1];
+   /* this masks off a/b output bit - but gav/gbv all inputs */
+   gav = uwrd & mask;
+   gbv = (uwrd >> gwid) & mask;
+   /* works since know n ins at least 1 - b shifts 1 less, goes b bit */
+   __old_gateval = ((uwrd >> (gwid - 1)) & 1L) | ((uwrd >> (2*gwid - 2)) & 2L); 
+  }
+ ngav = ngbv = 1L;
+ switch ((byte) gatid) {
+  case G_BITREDAND:
+   /* if even 1 0 value in any used bit, result is 0 */
+   if (gbv == 0L) { ngav = (gav != mask) ? 0L : 1L; ngbv = 0L; }
+   else if ((gav | gbv) != mask) ngav = ngbv = 0L;
+   break;
+  case G_NAND:
+   /* if even 1 0 value in any used bit, result is 1 */
+   if (gbv == 0L) { ngav = (gav != mask) ? 1L : 0L; ngbv = 0L; }
+   else if ((gav | gbv) != mask) ngbv = 0L;
+   break;
+  case G_BITREDOR:
+   /* if even 1 1 value in any used bit, result is 1 */
+   if (gbv == 0L) { ngav = (gav != 0L) ? 1L : 0L; ngbv = 0L; }
+   else if ((gav & ~gbv) != 0L) ngbv = 0L;
+   break;
+  case G_NOR:
+   /* if even 1 1 value in any used bit, result is 0 */
+   if (gbv == 0L) { ngav = (gav != 0L) ? 0L : 1L; ngbv = 0L; }
+   else if ((gav & ~gbv) != 0L) ngav = ngbv = 0L;
+   break;
+  case G_BITREDXOR:
+   if (gbv == 0L) { ngbv = 0L; ngav = __wrd_redxor(gav); }
+   break;
+  case G_REDXNOR:
+   if (gbv == 0L) { ngbv = 0L; ngav = !__wrd_redxor(gav); }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ /* these gates can drive constant strengths on wire - handled at assign */
+ /* need gate as 2 bit value for delay selection */
+done:
+ __new_gateval = ngav | (ngbv << 1);
+ /* set to T (non 0) if not equal if changed (different) */
+ *out_chg = (__old_gateval != __new_gateval);
+ return(TRUE);
+} 
+
+/*
+ * evaluate a gate that has at least 15 inputs
+ * could do 15 and 16 input gates slightly better since gate inputs fit
+ * in 1 word32 but stored as 2 words per gate here
+ */
+extern int32 __eval_1wide_gate(struct gate_t *gp, int32 gwid)
+{
+ struct xstk_t *xsp;
+ int32 bi, wi;
+
+ push_xstk_(xsp, gwid);
+ /* notice this includes output */
+ __ld_gate_wide_val(xsp->ap, xsp->bp, gp->gstate.wp, gwid); 
+
+ /* notice width it total bits while bit is index */
+ /* must acess output value but in load must mask off high output bit */
+ wi = get_wofs_(gwid - 1);
+ bi = get_bofs_(gwid - 1);
+ /* 2 shifts for b part because bit can be low bit in both halves */
+ /* extract output value before masking off output */
+ __old_gateval = ((xsp->ap[wi] >> bi) & 1L)
+  | (((xsp->bp[wi] >> bi) & 1L) << 1);  
+
+ /* input state minus output for gate eval */
+ xsp->ap[wi] &= __masktab[bi];
+ xsp->bp[wi] &= __masktab[bi];
+ /* this sets new gateval */
+ eval_wide_gate(gp, xsp); 
+ __pop_xstk();
+ if (__new_gateval == __old_gateval) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * load a wide form gate value from wp into ap and bp
+ */
+extern void __ld_gate_wide_val(word32 *ap, word32 *bp, word32 *gsp, int32 gwid)
+{
+ int32 wlen;
+ word32 *rap;
+
+ wlen = wlen_(gwid);
+ rap = &(gsp[2*wlen*__inum]);
+ memcpy(ap, rap, WRDBYTES*wlen);
+ memcpy(bp, &(rap[wlen]), WRDBYTES*wlen);
+}
+
+/*
+ * evaluate a wide gate (> 15 inputs)
+ * know xsp a and b parts have high output bit masked off
+ * and operations here in place so state replaced by 1 bit value
+ */
+static void eval_wide_gate(struct gate_t *gp, struct xstk_t *xsp)
+{
+ int32 rta, rtb;
+ int32 nins;
+
+ nins = gp->gpnum - 1;
+ switch (gp->gmsym->el.eprimp->gateid) {
+  case G_BITREDAND: /* and */
+   __lunredand(&rta, &rtb, xsp->ap, xsp->bp, nins);
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = (word32) rta;
+   xsp->bp[0] = (word32) rtb;
+   break;
+  case G_NAND: /* nand */
+   __lunredand(&rta, &rtb, xsp->ap, xsp->bp, nins);
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = (word32) rta;
+   xsp->bp[0] = (word32) rtb;
+invert:
+   __new_gateval = ((~xsp->ap[0] | xsp->bp[0]) & 1L) | (xsp->bp[0] << 1);
+   return;
+  case G_BITREDOR: /* or */
+   __lunredor(&rta, &rtb, xsp->ap, xsp->bp, nins);
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = (word32) rta;
+   xsp->bp[0] = (word32) rtb;
+   break;
+  case G_NOR: /* nor */
+   __lunredor(&rta, &rtb, xsp->ap, xsp->bp, nins);
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = (word32) rta;
+   xsp->bp[0] = (word32) rtb;
+   goto invert;
+  case G_BITREDXOR: /* xor */
+   __lunredxor(&rta, &rtb, xsp->ap, xsp->bp, nins);
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = (word32) rta;
+   xsp->bp[0] = (word32) rtb;
+   break;
+  case G_REDXNOR: /* xnor */
+   __lunredxor(&rta, &rtb, xsp->ap, xsp->bp, nins);
+   __narrow_to1bit(xsp);
+   xsp->ap[0] = (word32) rta;
+   xsp->bp[0] = (word32) rtb;
+   goto invert;
+  default: __case_terr(__FILE__, __LINE__);
+ } 
+ /* know stack value replaced to 1 bit result by here */
+ __new_gateval = xsp->ap[0] | (xsp->bp[0] << 1);
+}
+
+/* --
+-- value is 000111vv table is 6 bits lllhhh - 1 if has 0 strength --
+-- i.e. st0 is val shifted 5 let and st1 is val shifted 2 --
+0 - 15
+000 000 00 - 0
+000 000 01 - 0
+000 000 10 - 0x02
+000 000 11 - 0
+000 001 00 - 0x02
+000 001 01 - 001001 01 = 0x25
+000 001 10 - 0
+000 001 11 - 0x07
+
+000 010 00   0x02
+000 010 01   01001001 = 0x49 
+000 010 10   0
+000 010 11   0x0b
+000 011 00   0x02
+000 011 01   01101101 = 0x6d
+000 011 10   0
+000 011 11   0x0f
+
+16-31
+000 100 00 - 0x02
+000 100 01 - 10010001 = 0x91
+000 100 10 - 0
+000 100 11 - 0x13
+000 101 00 - 0x02
+000 101 01 - 101101 01 = 0xb5
+000 101 10 - 0
+000 101 11 - 0x17
+
+000 110 00   0x02
+000 110 01   11011001 = 0xd9
+000 110 10   0
+000 110 11   0x1b 
+000 111 00   0x02
+000 111 01   11111101 = 0xfd
+000 111 10   0
+000 111 11   0x1f
+
+32-47
+001 000 00 - 00100100 = 0x24
+001 000 01 - 0x02
+001 000 10 - 0
+001 000 11 - 0x23
+001 001 00 - 0x24
+001 001 01 - 0x25
+001 001 10 - 0
+001 001 11 - 0x27
+
+*001 010 00  00100100 = 0x24 not 0x28
+* 001 010 01 01001001 = 0x49 not 0x29
+001 010 10   0
+001 010 11   0x2b
+*001 011 00  00100100 = 0x24 not 0x2c
+*001 011 01  01101101 = 0x6d not 0x2d
+001 011 10   0
+001 011 11   0x2f
+
+48-63
+*001 100 00 - 00100100 = 0x24 not 0x30
+*001 100 01 - 10010001 = 0x91 not 0x31
+001 100 10 - 0
+001 100 11 - 0x33
+*001 101 00 - 00100100 = 0x24 not 0x34
+*001 101 01 - 10110101 = 0xb5 not 0x35
+001 101 10 - 0
+001 101 11 - 0x37
+
+*001 110 00 - 00100100 = 0x24 not 0x38
+*001 110 01 - 11011001 = 0xd9 not 0x39
+001 110 10   0
+001 110 11   0x3b
+*001 111 00 - 00100100 = 0x24 not 0x3c
+*001 111 01 - 11111101 = 0xfd not 0x3d
+001 111 10   0
+001 111 11   0x3f
+
+64-79
+010 000 00 - 01001000 = 0x48
+010 000 01 - 0x02
+010 000 10 - 0
+010 000 11 - 0x43
+*010 001 00 - 01001000 = 0x48 not 0x44
+*010 001 01 - 00100101 = 0x25 not 0x45
+010 001 10 - 0
+010 001 11 - 0x47
+
+010 010 00   0x48
+010 010 01   0x49
+010 010 10   0
+010 010 11   0x4b
+*010 011 00 - 01001000 = 0x48 not 0x4c
+*010 011 01 - 01101101 = 0x6d not 0x4d
+010 011 10   0
+010 011 11   0x4f
+
+80-95
+*010 100 00 - 01001000 = 0x48 not 0x50
+*010 100 01 - 10010001 = 0x91 not 0x51
+010 100 10 - 0
+010 100 11 - 0x53
+*010 101 00 - 01001000 = 0x48 not 0x54
+*010 101 01 - 10110101 = 0xb5 not 0x55
+010 101 10 - 0
+010 101 11 - 0x57
+
+*010 110 00 - 01001000 = 0x48 not 0x58
+*010 110 01 - 11011001 = 0xd9 not 0x59
+010 110 10   0
+010 110 11   0x5b
+*010 111 00 - 01001000 = 0x49 not 0x5c
+*010 111 01 - 11111101 = 0xfd not 0x5d
+010 111 10   0
+010 111 11   0x5f
+
+96-111
+011 000 00 - 01101100 = 0x6c
+011 000 01 - 0x02
+011 000 10 - 0
+011 000 11 - 0x63
+*011 001 00 - 01101100 = 0x6c not 0x64
+*011 001 01 - 00100101 = 0x25 not 0x65
+011 001 10 - 0
+011 001 11 - 0x67
+
+*011 010 00 - 01101100 = 0x6c not 0x68
+*011 010 01 - 01001001 = 0x49 not 0x69
+011 010 10   0
+011 010 11   0x6b
+011 011 00   0x6c
+011 011 01   0x6d
+011 011 10   0
+011 011 11   0x6f
+
+112-127
+*011 100 00 - 01101100 = 0x6c not 0x70
+*011 100 01 - 10010001 = 0x91 not 0x71
+011 100 10 - 0
+011 100 11 - 0x73
+*011 101 00 - 01101100 = 0x6c not 0x74
+*011 101 01 - 10110101 = 0xb5 not 0x75
+011 101 10 - 0
+011 101 11 - 0x77
+
+*011 110 00 - 01101100 = 0x6c not 0x78
+*011 110 01 - 11011001 = 0xd9 not 0x79
+011 110 10   0
+011 110 11   0x7b
+*011 111 00 - 01101100 = 0x6c not 0x7c
+*011 111 01 - 11111101 = 0xfd not 0x7d
+011 111 10   0
+011 111 11   0x7f
+
+128-143
+100 000 00 - 10010000 = 0x90
+100 000 01 - 0x02
+100 000 10 - 0
+100 000 11 - 0x83
+*100 001 00 - 10010000 = 0x90 not 0x84
+*100 001 01 - 00100101 = 0x25 not 0x85
+100 001 10 - 0
+100 001 11 - 0x87
+
+*100 010 00 - 10010000 = 0x90 not 0x88
+*100 010 01 - 01001001 = 0x49 not 0x89
+100 010 10   0
+100 010 11   0x8b
+*100 011 00 - 10010000 = 0x90 not 0x8c
+*100 011 01 - 01101101 = 0x6d not 0x8d
+100 011 10   0
+100 011 11   0x8f
+
+144-159
+100 100 00 - 0x90
+100 100 01 - 0x91
+100 100 10 - 0
+100 100 11 - 0x93
+*100 101 00 - 10010000 = 0x90 not 0x94
+*100 101 01 - 10110101 = 0xb5 not 0x95
+100 101 10 - 0
+100 101 11 - 0x97
+
+*100 110 00 - 10010000 = 0x90 not 0x98
+*100 110 01 - 11011001 = 0xd9 not 0x99
+100 110 10   0
+100 110 11   0x9b
+*100 111 00 - 10010000 = 0x90 not 0x9c
+*100 111 01 - 11111101 = 0xfd not 0x9d
+100 111 10   0
+100 111 11   0x9f
+
+160-175
+101 000 00 - 10110100 = 0xb4
+101 000 01 - 0x02
+101 000 10 - 0
+101 000 11 - 0xa3
+*101 001 00 - 10110100 = 0xb4 not 0xa4
+*101 001 01 - 00100101 = 0x25 not 0xa5
+101 001 10 - 0
+101 001 11 - 0xa7
+
+*101 010 00 - 10110100 = 0xb4 not 0xa8
+*101 010 01 - 01001001 = 0x49 not 0xa9
+101 010 10   0
+101 010 11   0xab
+*101 011 00 - 10110100 = 0xb4 not 0xac
+*101 011 01 - 01101101 = 0x6d not 0xad
+101 011 10   0
+101 011 11   0xaf
+
+176-191
+*101 100 00 - 10110100 = 0xb4 not 0xb0
+*101 100 01 - 10010001 = 0x91 not 0xb1
+101 100 10 - 0
+101 100 11 - 0xb3
+101 101 00 - 0xb4
+101 101 01 - 0xb5
+101 101 10 - 0
+101 101 11 - 0xb7
+
+*101 110 00 - 10110100 = 0xb4 not 0xb8
+*101 110 01 - 11011001 = 0xb9 not 0xb9
+101 110 10   0
+101 110 11   0xbb
+*101 111 00 - 10110100 = 0xb4 not 0xbc
+*101 111 01 - 11111101 = 0xfd not 0xbd
+101 111 10   0
+101 111 11   0xbf
+
+192-207
+110 000 00 - 11011000 = 0xd8
+110 000 01 - 0x02
+110 000 10 - 0
+110 000 11 - 0xc3
+*110 001 00 - 11011000 = 0xd8 not 0xc4
+*110 001 01 - 00100101 = 0x25 not 0xc5
+110 001 10 - 0
+110 001 11 - 0xc7
+
+*110 010 00 - 11011000 = 0xd8 not 0xc8
+*110 010 01 - 01001001 = 0x49 not 0xc9
+110 010 10   0
+110 010 11   0xcb
+*110 011 00 - 11011000 = 0xd8 not 0xcc
+*110 011 01 - 01101101 = 0x6d not 0xcd
+110 011 10   0
+110 011 11   0xcf
+
+208-223
+*110 100 00 - 11011000 = 0xd8 not 0xd0
+*110 100 01 - 10010001 = 0x91 not 0xd1
+110 100 10 - 0
+110 100 11 - 0xd3
+*110 101 00 - 11011000 = 0xd8 not 0xd4
+*110 101 01 - 10110101 = 0xb5 not 0xd5
+110 101 10 - 0
+110 101 11 - 0xd7
+
+110 110 00   0xd8
+110 110 01   0xd9
+110 110 10   0
+110 110 11   0xdb
+*110 111 00 - 11011000 = 0xd8 not 0xdc
+*110 111 01 - 11111101 = 0xfd not 0xdd
+110 111 10   0
+110 111 11   0xdf
+
+224-239
+111 000 00 - 11111100 = 0xfc
+111 000 01 - 0x02
+111 000 10 - 0
+111 000 11 - 0xe3
+*111 001 00 - 11111100 = 0xfc not 0xe4
+*111 001 01 - 00100101 = 0x25 not 0xe5
+111 001 10 - 0
+111 001 11 - 0xe7
+
+*111 010 00 - 11111100 = 0xfc not 0xe8
+*111 010 01 - 01001001 = 0x49 not 0xe9
+111 010 10   0
+111 010 11   0xeb
+*111 011 00 - 11111100 = 0xfc not 0xec
+*111 011 01 - 01101101 = 0x6d not 0xed
+111 011 10   0
+111 011 11   0xef
+
+240-255
+*111 100 00 - 11111100 = 0xfc not 0xf0
+*111 100 01 - 10010001 = 91 not 0xf1
+111 100 10 - 0
+111 100 11 - 0xf3
+*111 101 00 - 11111100 = 0xfc not 0xf4
+*111 101 01 - 10110101 = 0xb5 not 0xf5
+111 101 10 - 0
+111 101 11 - 0xf7
+
+*111 110 00 - 11111100 = 0xfc not 0xf8
+*111 110 01 - 11011001 = 0xd9 not 0xf9
+111 110 10   0
+111 110 11   0xfb
+111 111 00   0xfc
+111 111 01   0xfd
+111 111 10   0
+111 111 11   0xff
+
+--- */
+
+/* table to determine if special strength delay calculation needed */
+/* index is 6 stren bits - value removed */
+byte __hizstren_del_tab[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,  
+ 1, 0, 0, 0, 0, 0, 0, 0, 
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0 
+};
+
+/* SJM 08/07/01 - table always needed to map from gate/conta logic val */
+/* to driving stren (or connected net stren if only one driver) */
+/* old version just mapped the hiz strens to hiz instead of 0 or 1 */
+/* now also maps 0 and 1 and uses identity map for x */
+
+/* table to map gate or conta driving stren to driving stren val */
+/* if stren component hiz, value replaced by hiz else if 0 or 1 selects */
+/* that component from the 0 and 1 components, if x uses both components */
+/* if 0, both stren components have stren0, i 1, both stren1, if x both */
+/* as coded in source if either component hiz logic value replaced by z */
+
+/* for open collector nor gate, the 1 stren is highz1 so gate output val */
+/* of 1 causes gate to output hiz */ 
+byte __stren_map_tab[] = {
+
+ 0, 0, 0x02, 0, 0x02, 0x25, 0, 0x07,
+ 0x02, 0x49, 0, 0x0b, 0x02, 0x6d, 0, 0x0f,
+
+ 0x02, 0x91, 0, 0x13, 0x02, 0xb5, 0, 0x17,
+ 0x02, 0xd9, 0, 0x1b, 0x02, 0xfd, 0, 0x1f,
+
+ 0x24, 0x02, 0, 0x23, 0x24, 0x25, 0, 0x27,
+ 0x24, 0x49, 0, 0x2b, 0x24, 0x6d, 0, 0x2f,
+
+ 0x24, 0x91, 0, 0x33, 0x24, 0xb5, 0, 0x37,
+ 0x24, 0xd9, 0, 0x3b, 0x24, 0xfd, 0, 0x3f,
+
+ 0x48, 0x02, 0, 0x43, 0x48, 0x25, 0, 0x47,
+ 0x48, 0x49, 0, 0x4b, 0x48, 0x6d, 0, 0x4f,
+
+ 0x48, 0x91, 0, 0x53, 0x48, 0xb5, 0, 0x57,
+ 0x48, 0xd9, 0, 0x5b, 0x49, 0xfd, 0, 0x5f,
+
+ 0x6c, 0x02, 0, 0x63, 0x6c, 0x25, 0, 0x67,
+ 0x6c, 0x49, 0, 0x6b, 0x6c, 0x6d, 0, 0x6f,
+
+ 0x6c, 0x91, 0, 0x73, 0x6c, 0xb5, 0, 0x77,
+ 0x6c, 0xd9, 0, 0x7b, 0x6c, 0xfd, 0, 0x7f,
+
+ 0x90, 0x02, 0, 0x83, 0x90, 0x25, 0, 0x87,
+ 0x90, 0x49, 0, 0x8b, 0x90, 0x6d, 0, 0x8f,
+
+ 0x90, 0x91, 0, 0x93, 0x90, 0xb5, 0, 0x97,
+ 0x90, 0xd9, 0, 0x9b, 0x90, 0xfd, 0, 0x9f,
+
+ 0xb4, 0x02, 0, 0xa3, 0xb4, 0x25, 0, 0xa7,
+ 0xb4, 0x49, 0, 0xab, 0xb4, 0x6d, 0, 0xaf,
+
+ 0xb4, 0x91, 0, 0xb3, 0xb4, 0xb5, 0, 0xb7,
+ 0xb4, 0xb9, 0, 0xbb, 0xb4, 0xfd, 0, 0xbf,
+
+ 0xd8, 0x02, 0, 0xc3, 0xd8, 0x25, 0, 0xc7,
+ 0xd8, 0x49, 0, 0xcb, 0xd8, 0x6d, 0, 0xcf,
+
+ 0xd8, 0x91, 0, 0xd3, 0xd8, 0xb5, 0, 0xd7,
+ 0xd8, 0xd9, 0, 0xdb, 0xd8, 0xfd, 0, 0xdf,
+
+ 0xfc, 0x02, 0, 0xe3, 0xfc, 0x25, 0, 0xe7,
+ 0xfc, 0x49, 0, 0xeb, 0xfc, 0x6d, 0, 0xef,
+
+ 0xfc, 0x91, 0, 0xf3, 0xfc, 0xb5, 0, 0xf7,
+ 0xfc, 0xd9, 0, 0xfb, 0xfc, 0xfd, 0, 0xff
+};
+
+/* bufif table */
+ /* ---
+  format is (cb)(ca)(db)(da) 
+  0   0   0   0  (d0,c0) 0x0
+  0   0   0   1  (d1,c0) 0x1
+  0   0   1   0  (dz,c0) 0x2
+  0   0   1   1  (dx,c0) 0x3
+  0   1   0   0  (d0,c1) 0x4
+  0   1   0   1  (d1,c1) 0x5
+  0   1   1   0  (dz,c1) 0x6
+  0   1   1   1  (dx,c1) 0x7
+  1   0   0   0  (d0,cz) 0x8
+  1   0   0   1  (d1,cz) 0x9
+  1   0   1   0  (dz,cz) 0xa
+  1   0   1   1  (dx,cz) 0xb
+  1   1   0   0  (d0,cx) 0xc
+  1   1   0   1  (d1,cx) 0xd
+  1   1   1   0  (dz,cx) 0xe
+  1   1   1   1  (dx,cx) 0xf
+  --- */
+
+/* assume value is strength and in and tab and or in or tab */
+/* and tab no value is ff, or tab no value is 0 */
+byte __bufif_and_tab[] = {  
+ /* 0-15 bufif0 */
+ 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0,
+ 0xe0, 0x1c, 0xff, 0xff, 0xe0, 0x1c, 0xff, 0xff,  
+ /* 16-31 bufif1 */
+ 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0x1c, 0xff, 0xff, 0xe0, 0x1c, 0xff, 0xff, 
+ /* 32-47 notif0 */
+ 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0,
+ 0x1c, 0xe0, 0xff, 0xff, 0x1c, 0xe0, 0xff, 0xff,  
+ /* 48-63 notif1 */
+ 0, 0,  0, 0, 0xff, 0xff, 0xff, 0xff,
+ 0x1c, 0xe0, 0xff, 0xff, 0x1c, 0xe0, 0xff, 0xff,
+};
+
+byte __bufif_or_tab[] = {  
+ /* 0-15 bufif0 */
+ 0, 1, 3, 3, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3,  
+ /* 16-31 bufif1 */
+ 2, 2, 2, 2, 0, 1, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ /* 32-47 notif0 */
+ 1, 0, 3, 3, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ /* 48-63 notif1 */
+ 2, 2, 2, 2, 1, 0, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3  
+};
+
+/* interpreter bufif gate type base table */
+/* BEWARE - assumes LAST_GSYM is 36 - if changes intialize at start */
+/* and G_BUFIF0 is 13, G_BUFIF1 is 14, G_NOTIF0 is 20, G_NOTIF1 is 21 */
+int32 __bufif_base_tab[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 0, 16, -1, -1, -1, -1, -1,
+ 32, 48, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1 };
+
+/*
+ * evaluate bufif gate style gate where state stores output strength
+ * this routine does not evaluate if input same
+ *
+ * input strength not passed thru but driven strength non constant
+ * storage is data port 2 bits, control 2 bit and output 8 bits and
+ * stored as half word32 that is access as such
+ *
+ * wires drives by bufifs must be marked as strength
+ * i is gate expr. index (0th is out)
+ * and since gate state stores strength need to correct for hiz strength
+ *
+ * if inputs differ and evals, it must set __new_gateval to value
+ * with added in or driven strength
+ *
+ */
+extern int32 __eval_bufif_gate(register struct gate_t *gp, word32 i,
+ int32 *out_chg)
+{
+ register word32 gwrd;
+ register struct xstk_t *xsp;
+ int32 base;
+
+ if (__debug_flg && __ev_tracing)
+  __tr_msg("--changing bufif - old: %s\n",
+   __gstate_tostr(__xs, gp, FALSE));
+
+ /* this loads value part if driver has strength */
+ xsp = __eval_xpr(gp->gpins[i]);
+ /* gate inputs can be wider than 1 bit */
+ xsp->ap[0] &= 1L;
+ xsp->bp[0] &= 1L;
+
+ gwrd = (word32) gp->gstate.hwp[__inum];
+ __old_inputval = (i == 1) ? (gwrd & 3L) : ((gwrd >> 2) & 3L); 
+ __new_inputval = xsp->ap[0] | (xsp->bp[0] << 1);
+ __pop_xstk();
+ if (__new_inputval == __old_inputval) return(FALSE);
+
+ /* update the changed input state */
+ if (i == 1) { gwrd &= ~3L; gwrd |= __new_inputval; }
+ else { gwrd &= ~(3L << 2); gwrd |= (__new_inputval << 2); }
+ gp->gstate.hwp[__inum] = (hword) gwrd;
+ /* buf always has strength (maybe strong if no explicit) */ 
+ __old_gateval = (gwrd >> 4);
+
+ /* use input 4 bits as case access - output not just simple 8 bit value */
+ gwrd &= 0xf;
+ 
+ /* assume 0 value with driven strength (strong if none) */
+ __new_gateval = (gp->g_stval << 2);
+
+ base = __bufif_base_tab[gp->gmsym->el.eprimp->gateid];
+ /* DEBUG remove ---
+ if (base == -1) __misc_terr(__FILE__, __LINE__);
+ --- */
+ __new_gateval &= __bufif_and_tab[gwrd + base];
+ __new_gateval |= __bufif_or_tab[gwrd + base];
+
+ /* strength is lllhhhvv table is 6 bits lllhhh - 1 if has 0 strength*/  
+ /* must correct for special case where 1 strength is hiz (no drive) */
+ __new_gateval = __stren_map_tab[__new_gateval];
+
+ /* if no change, nothing to do */
+ /* set to T (non 0) if not equal if changed (different) */
+ *out_chg = (__new_gateval != __old_gateval);
+ return(TRUE);
+}
+
+/* normal mos mapping only supply changed to strong */
+word32 __mos_stmap[] = { 0, 1, 2, 3, 4, 5, 6, 6 };
+/* resistive devices reduce strengths */
+word32 __rmos_stmap[] = { 0, 1, 1, 2, 2, 3, 5, 5 }; 
+
+/* ----
+0 => d=0,c=0 4 => d=0,c=1 8 => d=0,c=z 0c=> d=0,c=x -> 0,4,8,0xc
+1 => d=1,c=0 5 => d=1,c=1 9 => d=1,c=z 0d=> d=1,c=x -> 1,5,9,0xd
+3 => d=x,c=0 7 => d=x,c=1 0b=> d=x,c=z 0f=> d=x,c=x -> 3,7,0xb,0xf 
+2 => d=z,c=0 6 => d=z,c=1 0a=> d=z,c=z 0e=> d=z,c=x -> 2,6,0xa,0xe
+--- */
+
+/*
+ * evaluate nmos gate 
+ * special format for all mos gates is 3 8 bit values (0-7) data
+ * (1st input stren val, * 8-9 control value (2nd input) (10-15 unused stren
+ * ignored), * 16-23 output with strength
+ *
+ * this is passed state word32 for instance and set globals __old gateval
+ * and __new gateval
+ *
+ * for r style reduce strength according to table for non resistive only
+ * changes supply to strong (also uses table)
+ */
+extern void __eval_nmos_gate(word32 gwrd)
+{
+ register word32 ivec, st0, st1;
+
+ /* state here is 2 8 bit inputs and 1 8 bit strength format output */
+ /* 1 word32 per gate */
+ __old_gateval = (gwrd >> 16) & 0xffL; 
+ /* 4 bit value is index (bits 0-1 data value, 2-3 control value */
+ ivec = ((gwrd >> 6) & 0x0c) | (gwrd & 3L);
+ st0 = (gwrd >> 5) & 7;
+ st1 = (gwrd >> 2) & 7;
+
+ switch ((byte) ivec) {
+  /* control 0 or data z - driven to z */
+  case 0: case 1: case 2: case 3: case 6: case 10: case 14:
+   __new_gateval = 2; 
+   break;
+  /* control 1 - non x/z data passed thru */
+  case 4:
+   __new_gateval = 0 | (__mos_stmap[st0] << 5) | (__mos_stmap[st1] << 2); 
+   break;
+  case 5:
+   __new_gateval = 1 | (__mos_stmap[st0] << 5) | (__mos_stmap[st1] << 2); 
+   break;
+  case 7: case 11: case 15:
+   __new_gateval = 3 | (__mos_stmap[st0] << 5) | (__mos_stmap[st1] << 2); 
+   break;
+  case 8: case 12:
+    /* control x/z - data 0 - L */
+    /* high 3 bits are 0 strength */
+   if (st0 == 0) __new_gateval = 2;
+   else __new_gateval = (__mos_stmap[st0] << 5) | 3;
+   break;
+  case 9: case 13:
+   if (st1 == 0) __new_gateval = 2;
+   else __new_gateval = (__mos_stmap[st1] << 2) | 3;
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+extern void __eval_rnmos_gate(word32 gwrd)
+{
+ register word32 ivec, st0, st1;
+
+ /* state here is 2 8 bit inputs and 1 8 bit strength format output */
+ /* 1 word32 per gate */
+ __old_gateval = (gwrd >> 16) & 0xffL; 
+ /* 4 bit value is index (bits 0-1 data value, 2-3 control value */
+ ivec = ((gwrd >> 6) & 0x0c) | (gwrd & 3L);
+ st0 = (gwrd >> 5) & 7;
+ st1 = (gwrd >> 2) & 7;
+
+ switch ((byte) ivec) {
+  /* control 0 or data z - driven to z */
+  case 0: case 1: case 2: case 3: case 6: case 10: case 14:
+   __new_gateval = 2; 
+   break;
+  /* control 1 - non x/z data passed thru */
+  case 4:
+   __new_gateval = 0 | (__rmos_stmap[st0] << 5) | (__rmos_stmap[st1] << 2); 
+   break;
+  case 5:
+   __new_gateval = 1 | (__rmos_stmap[st0] << 5) | (__rmos_stmap[st1] << 2); 
+   break;
+  case 7: case 11: case 15:
+   __new_gateval = 3 | (__rmos_stmap[st0] << 5) | (__rmos_stmap[st1] << 2); 
+   break;
+  case 8: case 12:
+    /* control x/z - data 0 - L */
+    /* high 3 bits are 0 strength */
+   if (st0 == 0) __new_gateval = 2;
+   else __new_gateval = (__rmos_stmap[st0] << 5) | 3;
+   break;
+  case 9: case 13:
+   if (st1 == 0) __new_gateval = 2;
+   else __new_gateval = (__rmos_stmap[st1] << 2) | 3;
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+extern void __eval_pmos_gate(word32 gwrd)
+{
+ register word32 ivec, st0, st1;
+
+ /* state here is 2 8 bit inputs and 1 8 bit strength format output */
+ /* 1 word32 per gate */
+ __old_gateval = (gwrd >> 16) & 0xffL; 
+ /* 4 bit value is index (bits 0-1 data value, 2-3 control value */
+ ivec = ((gwrd >> 6) & 0x0c) | (gwrd & 3L);
+ st0 = (gwrd >> 5) & 7;
+ st1 = (gwrd >> 2) & 7;
+
+ switch ((byte) ivec) {
+  /* control 0 - non x/z data passed thru */
+  case 0:
+   __new_gateval = 0 | (__mos_stmap[st0] << 5) | (__mos_stmap[st1] << 2); 
+   break;
+  case 1:
+   __new_gateval = 1 | (__mos_stmap[st0] << 5) | (__mos_stmap[st1] << 2); 
+   break;
+  case 3: case 11: case 15:
+    /* data x, ctrl 0, data x, ctrl z, data x cntrl x become strength x */  
+    /* 3, 11, 15 */
+   __new_gateval = 3 | (__mos_stmap[st0] << 5) | (__mos_stmap[st1] << 2); 
+   break;
+  /* control 1 or data z - driven to z */
+  case 2: case 4: case 5: case 6: case 7: case 10: case 14:
+   __new_gateval = 2; 
+    break;
+  case 8: case 12: 
+   /* if H becomes hiz */
+   if (st0 == 0) __new_gateval = 2;
+   else __new_gateval = (__mos_stmap[st0] << 5) | 3;
+   break;
+  case 9: case 13:
+   /* if L goes to Hiz not H */
+   if (st1 == 0) __new_gateval = 2;
+   else __new_gateval = (__mos_stmap[st1] << 2) | 3;
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+extern void __eval_rpmos_gate(word32 gwrd)
+{
+ register word32 ivec, st0, st1;
+
+ /* state here is 2 8 bit inputs and 1 8 bit strength format output */
+ /* 1 word32 per gate */
+ __old_gateval = (gwrd >> 16) & 0xffL; 
+ /* 4 bit value is index (bits 0-1 data value, 2-3 control value */
+ ivec = ((gwrd >> 6) & 0x0c) | (gwrd & 3L);
+ st0 = (gwrd >> 5) & 7;
+ st1 = (gwrd >> 2) & 7;
+
+ switch ((byte) ivec) {
+  /* control 0 - non x/z data passed thru */
+  case 0:
+   __new_gateval = 0 | (__rmos_stmap[st0] << 5) | (__rmos_stmap[st1] << 2); 
+   break;
+  case 1:
+   __new_gateval = 1 | (__rmos_stmap[st0] << 5) | (__rmos_stmap[st1] << 2); 
+   break;
+  case 3: case 11: case 15:
+   /* data x, ctrl 0, data x, ctrl z, data x cntrl x become strength x */  
+   /* 3, 11, 15 */
+   __new_gateval = 3 | (__rmos_stmap[st0] << 5) | (__rmos_stmap[st1] << 2); 
+   break;
+  /* control 1 or data z - driven to z */
+  case 2: case 4: case 5: case 6: case 7: case 10: case 14:
+   __new_gateval = 2; 
+   break;
+  case 8: case 12: 
+   /* if H becomes hiz */
+   if (st0 == 0) __new_gateval = 2;
+   else __new_gateval = (__rmos_stmap[st0] << 5) | 3;
+   break;
+  case 9: case 13:
+   /* if L goes to Hiz not H */
+   if (st1 == 0) __new_gateval = 2;
+   else __new_gateval = (__rmos_stmap[st1] << 2) | 3;
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * evaluate cmos style gate that passes thru input strength
+ *
+ * special format is 4 8 bit values (0-7) data (1st input stren val,
+ * 8-9 nmos control value (2nd input) (10-15 unused stren ignored),
+ * 16-17 pmos control value (3rd input) (18-23 unused stren ignored),
+ * 24-31 output with strength
+ *
+ * this is passed gate record and sets globals __old gateval
+ * and __new gateval 
+ *
+ * values only changed if inputs differ
+ *
+ * for r style reduce strength according to table for non resistive only
+ * changes supply to strong
+ * this uses the output port net for strength competition
+ * scheme builds tree so 2 halves of cmos converted to one drive val here
+ */
+extern void __eval_cmos_gate(struct gate_t *gp)
+{
+ register word32 gwrd, tmpwrd;
+ int32 nchged, pchged;
+ word32 wtyp, gid;
+ word32 new_nval, new_pval;
+ struct expr_t *xp;
+
+ gwrd = gp->gstate.wp[__inum];
+ /* ---
+ stren combined gate state [31-24] => always bits 23:16
+ 3nd pmos control [23-16] => removed 1st, to bits 15-8 2nd
+ 2rd nmos control [15-8] => same place 1st, removed 2nd
+ 1st input state [7-0] = always same place
+ -- */
+
+ /* LOOKATME - maybe should add bit or use g gone also for this */
+ gid = gp->gmsym->el.eprimp->gateid;
+
+ /* controls: 1st nmos 8-15, 2nd pmos 16-23 */
+ tmpwrd = (gwrd & 0xffffL) | ((gwrd >> 8) & 0x00ff0000L);
+ nchged = TRUE;
+ if (gid == G_RCMOS) __eval_rnmos_gate(tmpwrd); else __eval_nmos_gate(tmpwrd);
+ if (__new_gateval == __old_gateval) nchged = FALSE; 
+ new_nval = __new_gateval;
+
+ tmpwrd = (gwrd & 0xffL) | ((gwrd >> 8) & 0x00ffff00L);
+ pchged = TRUE;
+ if (gid == G_RCMOS) __eval_rpmos_gate(tmpwrd);
+ else __eval_pmos_gate(tmpwrd);
+ if (__new_gateval == __old_gateval) pchged = FALSE;
+ new_pval = __new_gateval;
+
+ /* now can set old values */
+ __old_gateval = gwrd >> 24;
+
+ /* since here old value always old value of cmos, no change means */
+ /* no change since if some sort of wired or/and effect will be different */
+ if (!nchged && !pchged) return;
+ 
+ /* know at least one different from old, need tournament */
+ /* hard part is need wire type of output */
+ xp = gp->gpins[0];
+ wtyp = (word32) N_REG;
+ switch ((byte) xp->optyp) {
+  case ID: case GLBREF: wtyp = xp->lu.sy->el.enp->ntyp; break;
+  case LSB: wtyp = xp->lu.x->lu.sy->el.enp->ntyp; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ __new_gateval = __comb_1bitsts(wtyp, new_nval, new_pval); 
+}
+
+/*
+ * convert assigned to expression to value
+ */
+extern char *__to_gassign_str(char *s, struct expr_t *xp) 
+{
+ struct xstk_t *xsp;
+ byte *sbp;
+
+ if (!xp->x_stren)
+  {
+   xsp = __eval_xpr(xp);
+   __regab_tostr(s, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE);
+  }
+ else
+  {
+   xsp = __ndst_eval_xpr(xp);
+   sbp = (byte *) xsp->ap;
+   __st_regab_tostr(s, sbp, xp->szu.xclen); 
+  }
+ __pop_xstk();
+ return(s);
+}
+
+word32 __to_uvaltab[] = {0, 1, 2, 2 };
+word32 __to_noztab[] = {0, 1, 3, 3 };
+
+/*
+ * change input and if different evaluate udp
+ *
+ * notice input stored as 2 bit scalars not a and b sections
+ * sets 2 bit value byte and restores updated gstate
+ * notice extra input does not exist - include output in index if not comb.
+ *
+ * must pass is edge because initialize treats edge as seq.
+ * expects __cur_udp to point to current udp record
+ * pi is gstate bit index (starting at 0), i is gate expr. index (from 1)
+ * gate values never have strength here maybe added when stored
+ *
+ * output always stored in high 2 bits of state but 0th gpins pin
+ */
+extern int32 __eval_udp(register struct gate_t *gp, word32 i, int32 *out_chg,
+ int32 is_edge)
+{
+ register int32 pi;
+ register word32 uwrd;
+ register struct xstk_t *xsp;
+ int32 ndx, bi, wi, outbi, tabi;
+ word32 *wp;
+ extern word32 __pow3tab[];
+
+ /* combinatorial can be sequential or not */
+ /* DBG remove --
+ if (__debug_flg && __ev_tracing)
+  __tr_msg("-- changing udp - old: %s\n",
+   __gstate_tostr(__xs, gp, FALSE));
+ --- */
+
+ xsp = __eval_xpr(gp->gpins[i]);
+ /* normal udp - just using scalar form as index - i.e. x/z must be 3 */
+ __new_inputval = __to_noztab[(xsp->ap[0] & 1L) | ((xsp->bp[0] & 1L) << 1)];
+ __pop_xstk();
+
+ outbi = 2*__cur_udp->numins;
+ pi = i - 1;
+ if (!__cur_udp->u_wide)
+  {
+   uwrd = (word32) gp->gstate.hwp[__inum];
+   __old_inputval = (uwrd >> (2*pi)) & 3L;
+   /* DBG remove ---
+   if (__old_inputval == 2) __misc_terr(__FILE__, __LINE__);
+   --- */
+
+   if (__new_inputval == __old_inputval) return(FALSE);
+   /* update the state */
+   uwrd &= ~(3L << (2*pi));
+   uwrd |= ((hword) __new_inputval << (2*pi));
+   gp->gstate.hwp[__inum] = (hword) uwrd;
+   /* finally compute the index - will include output if sequential */ 
+   /* index since table look up always 3 for x or z */ 
+   ndx = (int32) 2*(uwrd & __masktab[2*__cur_udp->numstates]);
+   __old_gateval = (uwrd >> outbi) & 3L;
+  }
+ /* in wide, case need 2nd running value index word32 */
+ else 
+  {
+   wp = &(gp->gstate.wp[2*__inum]);
+   /* know all input 0,1, x (2) only */
+   __old_inputval = (wp[0] >> (2*pi)) & 3L;
+   /* DBG remove --- 
+   if (__old_inputval == 2) __misc_terr(__FILE__, __LINE__);
+   --- */
+   if (__new_inputval == __old_inputval) return(FALSE);
+
+   /* change the input - here x/z is 3 */
+   wp[0] &= ~(3L << (2*pi));
+   wp[0] |= (__new_inputval << (2*pi));
+
+   /* must correct running index - subtract off contribution of port i */
+   /* here x must be 2 not 3 */
+   wp[1] -= ((__old_inputval == 3) ? 2 : __old_inputval)*__pow3tab[pi];
+   /* add in new contribution of port i */
+   wp[1] += ((__new_inputval == 3) ? 2 : __new_inputval)*__pow3tab[pi];  
+   /* --- RELEASE remove --
+   if (__debug_flg && __ev_tracing)
+    __tr_msg("## wide udp word0=%x, word1=%x(%d)\n", wp[0], wp[1], wp[1]); 
+   --- */
+   /* notice word32 1 index is bit - times 2 to get 2 bit output val. ind */
+   ndx = (int32) 2*wp[1];
+   __old_gateval = (wp[0] >> outbi) & 3L;
+  }
+
+ /* notice ndx already multiplied by 2 for 2 bit table values */
+ wi = get_wofs_(ndx);
+ bi = get_bofs_(ndx); 
+ __new_gateval = (__cur_udp->utab->ludptab[wi] >> bi) & 3L;
+ /* RELEASE remove ---
+ if (__debug_flg && __ev_tracing)
+  __tr_msg(
+   "## in=%d, old in=%d, gval=%d, old gval=%d, bi=%d, wi=%d, twrd=%lx\n",
+   __new_inputval, __old_inputval, __new_gateval, __old_gateval, bi, wi, 
+   __cur_udp->utab->ludptab[wi]);
+ --- */
+
+ if (__new_gateval == 3 && is_edge)
+  {
+   /* level sensitive has state but no edge table */
+   tabi =3*pi + ((__old_inputval == 3) ? 2 : __old_inputval);
+   wp = __cur_udp->utab->eudptabs[tabi];
+   __new_gateval = (wp[wi] >> bi) & 3L;
+   /* --- RELEASE remove
+   if (__debug_flg && __ev_tracing)
+    __tr_msg("## eval edge - new gval=%d, tabi=%d, twrd=%lx\n",
+     __new_gateval, tabi, wp[wi]);
+   --- */
+  }
+ /* set to T (non 0) if not equal if changed (different) */
+ /* know strengths will always be same */
+ *out_chg = (__old_gateval != __new_gateval);
+ return(TRUE);
+}
diff --git a/src/v_ex4.c b/src/v_ex4.c
new file mode 100644
index 0000000..b61a8a3
--- /dev/null
+++ b/src/v_ex4.c
@@ -0,0 +1,5641 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * run time execution routines - assigns, strength and gate evaluation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* sytem stuff */
+extern int32 errno;
+
+/* local prototypes */
+static void set_from_mpp_unopts(struct mod_t *, struct mod_pin_t *, int32);
+static void set_from_hconn_unopts(struct mod_t *, struct inst_t *, int32,
+ struct expr_t *, struct mod_pin_t *, int32);
+static void dbg_unopt_msg(struct mod_t *, struct mod_pin_t *, int32, char *);
+static void dbg_unopt2_msg(struct mod_t *, struct inst_t *, int32,
+ struct mod_pin_t *, int32, char *);
+static void std_downtomdport(register struct expr_t *,
+ register struct expr_t *, struct itree_t *);
+static void prt_assignedto_val(struct expr_t *, char *);
+static void multfi_acc_downtomdport( register struct expr_t *,
+ struct expr_t *, struct itree_t *);
+static void stacc_downtomdport(register struct expr_t *,
+ register struct expr_t *, struct itree_t *);
+static void stbsel_acc_downtomdport(register struct expr_t *,
+ register struct expr_t *, struct itree_t *);
+static void acc_downtomdport(register struct expr_t *,
+ register struct expr_t *, struct itree_t *);
+static void bsel_acc_downtomdport(register struct expr_t *,
+ register struct expr_t *, struct itree_t *);
+static void std_uptoiconn(register struct expr_t *, register struct expr_t *,
+ struct itree_t *);
+static void multfi_acc_uptoiconn(register struct expr_t *, struct expr_t *,
+ struct itree_t *);
+static void stacc_uptoiconn(register struct expr_t *, register struct expr_t *,
+ struct itree_t *);
+static void stbsel_acc_uptoiconn(register struct expr_t *,
+ register struct expr_t *, struct itree_t *);
+static void acc_uptoiconn(register struct expr_t *, register struct expr_t *,
+ struct itree_t *);
+static void bsel_acc_uptoiconn(register struct expr_t *,
+ register struct expr_t *, struct itree_t *);
+static void ldcomb_driver(struct xstk_t *, struct net_t *,
+ register struct net_pin_t *);
+static word32 widegate_ld_bit(word32 *, int32, int32);
+static void ldcomb_stdriver(register byte *, struct net_t *,
+ register struct net_pin_t *);
+static struct xstk_t *init_stwire_accum(struct net_t *);
+static struct xstk_t *ld_stgate_driver(struct net_pin_t *);
+static struct xstk_t *ld_stconta_driver(struct net_pin_t *);
+static struct xstk_t *ld_stvpiputv_driver(struct net_pin_t *);
+static struct xstk_t *ld_sticonn_up_driver(register struct net_pin_t *);
+static struct xstk_t *ld_pb_sticonn_up_driver(register struct net_pin_t *);
+static struct xstk_t *ld_stmodport_down_driver(register struct net_pin_t *);
+static struct xstk_t *ld_pb_stmodport_down_driver(
+register struct net_pin_t *);
+static struct xstk_t *ld_stpull_driver(struct net_pin_t *);
+static void ndst_eval2_xpr(register byte *, register struct expr_t *);
+static void access_stpsel(register byte *, register struct expr_t *);
+static void rhs_stconcat(register byte *, struct expr_t *);
+static void eval_stwire(word32, register byte *, int32, int32,
+ register byte *);
+static void adds_evgate_ins(word32 *, word32 *, int32);
+static void show2_allvars(struct itree_t *);
+static void emit1_driver(struct net_t *, struct net_pin_t *, int32);
+static char *drive_tostr(char *, word32 *, word32 *, struct net_pin_t *,
+ int32, int32);
+static char *stdrive_tostr(char *, byte *, struct net_pin_t *, int32, int32);
+static char *bld_wire_telltale(char *, struct net_t *);
+static void emit1_load(struct net_t *, struct net_pin_t *);
+static struct mdvmast_t *alloc_mdvmast(void);
+static void setup_all_dvars(void);
+static void setup_1argdvars(struct mdvmast_t *);
+static void setup_1subtree_allvars(struct itree_t *, int32);
+static void setup_1installvars(struct mod_t *, struct itree_t *);
+static void turnon_1net_dmpv(struct net_t *, struct itree_t *,
+ struct task_t *, struct mod_t *, int32);
+static char *to_dvcode(register char *, register int32);
+static void wr_1argdvhdr(struct mdvmast_t *);
+static void wr_1subtree_allvars(struct itree_t *, int32);
+static void wr_1inst_dvhdrs(struct itree_t *);
+static void wr_tasks_dvhdrs(struct itree_t *, register struct symtab_t *);
+static char *to_dvtsktyp(char *, word32);
+static void wr_fromtop_iscopeto(struct itree_t *);
+static void wr_totop_iscopeback(struct itree_t *);
+static void wr_tskscopeto(struct symtab_t *);
+static void wr_tskscopeback(struct symtab_t *);
+static void wr_1vectored_dvdef(struct net_t *, char *, struct itree_t *);
+static void dump_allvars_vals(void);
+static void dmp_insts_ofwire(struct mod_t *, struct net_t *);
+static void bld1_scal_dvval(struct net_t *, char *, struct itree_t *);
+static void bld1_vec_dvval(struct net_t *, char *, struct itree_t *);
+static void bld1_xdvval(register struct net_t *, char *);
+static void dv_wr(int32);
+static char *to_dvtimstr(char *, register word64);
+static void access_stbsel(register byte *, register struct expr_t *);
+
+/* extern prototypes (maybe defined in this module) */
+extern void __set_mpp_assign_routines(void);
+extern void __set_pb_mpp_assign_routines(void);
+extern void __set_mpp_aoff_routines(void);
+extern void __vpi_set_downtomdport_proc(struct mod_pin_t *, struct net_t *);
+extern void __vpi_set_upiconnport_proc(struct mod_pin_t *);
+extern void __init_instdownport_contas(struct itree_t *, struct itree_t *);
+extern void __init_instupport_contas(struct itree_t *);
+extern void __mdr_assign_or_sched(register struct expr_t *);
+extern void __assign_1mdrwire(register struct net_t *);
+extern void __sched_1mdrwire(register struct net_t *);
+extern struct xstk_t *__load_mdrwire(register struct net_t *);
+extern int32 __move_to_npprefloc(struct net_pin_t *);
+extern struct xstk_t *__ld_wire_driver(register struct net_pin_t *);
+extern struct xstk_t *__ld_tfrwarg_driver(struct net_pin_t *);
+extern struct xstk_t *__ld_conta_driver(struct net_pin_t *);
+extern struct xstk_t *__ld_vpiputv_driver(struct net_pin_t *);
+extern struct xstk_t *__ld_gate_driver(struct net_pin_t *);
+extern struct xstk_t *__ld_iconn_up_driver(register struct net_pin_t *);
+extern struct xstk_t *__ld_pb_iconn_up_driver(register struct net_pin_t *);
+extern struct xstk_t *__ld_modport_down_driver(register struct net_pin_t *);
+extern struct xstk_t *__ld_pb_modport_down_driver(register struct net_pin_t *);
+
+
+extern word32 __ld_gate_out(register struct gate_t *, int32 *);
+extern void __eval_wire(word32 *, word32 *, struct net_t *,
+ struct net_pin_t *); 
+extern void __eval_wide_wire(word32 *, word32 *, word32 *, word32 *, int32,
+ word32);
+extern void __eval_1w_nonstren(register word32 *, register word32 *,
+ register word32, register word32, word32);
+extern struct xstk_t *__stload_mdrwire(struct net_t *);
+extern struct xstk_t *__ld_stwire_driver(register struct net_pin_t *);
+extern struct xstk_t *__ld_sttfrwarg_driver(struct net_pin_t *);
+extern struct xstk_t *__ndst_eval_xpr(struct expr_t *);
+extern int32 __get_const_bselndx(register struct expr_t *);
+extern void __st_standval(register byte *, register struct xstk_t *, byte);
+extern word32 __comb_1bitsts(word32, register word32, register word32);
+extern char *__gstate_tostr(char *, struct gate_t *, int32);
+extern void __show_allvars(void);
+extern void __emit_1showvar(struct net_t *, struct gref_t *);
+extern char *__bld_valofsched(char *, struct tev_t *);
+extern char *__bld_showvars_prefix(char *, struct net_t *, struct gref_t *);
+extern void __exec_dumpvars(struct expr_t *);
+extern void __setup_dmpvars(void);
+extern void __do_dmpvars_baseline(char *);
+extern void __do_dmpvars_chg(void);
+extern int32 __cnt_dcelstels(register struct dcevnt_t *);
+
+extern char *__to_ptnam(char *, word32);
+extern char *__to_mpnam(char *, char *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern void __strenwiden_sizchg(struct xstk_t *, int32);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern void __sizchgxs(register struct xstk_t *, int32);
+extern void __sgn_xtnd_widen(struct xstk_t *, int32);
+extern void __sizchg_widen(register struct xstk_t *, int32);
+extern void __narrow_sizchg(register struct xstk_t *, int32);
+extern void __fix_widened_toxs(register struct xstk_t *, int32);
+extern void __stren_exec_ca_concat(struct expr_t *, byte *, int32);
+extern void __exec_conta_assign(struct expr_t *, register word32 *,
+ register word32 *, int32);
+extern void __exec_ca_concat(struct expr_t *, register word32 *,
+ register word32 *, int32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char *__to_gassign_str(char *, struct expr_t *);
+extern void __ld_perinst_val(register word32 *, register word32 *,
+ union pck_u, int32);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __lhsbsel(register word32 *, register int32, word32);
+extern void __my_free(char *, int32);
+extern char *__my_malloc(int32);
+extern char *__to_vvstnam(char *, word32);
+extern char *__to_vvnam(char *, word32);
+extern char *__to_timstr(char *, word64 *);
+extern int32 __correct_forced_newwireval(struct net_t *, word32 *, word32 *);
+extern void __chg_st_val(struct net_t *, register word32 *, register word32 *);
+extern void __ld_wire_val(register word32 *, register word32 *,
+ struct net_t *);
+extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
+extern void __ld_bit(register word32 *, register word32 *,
+ register struct net_t *, int32);
+extern int32 __forced_inhibit_bitassign(struct net_t *, struct expr_t *,
+ struct expr_t *);
+extern void __assign_to_bit(struct net_t *, struct expr_t *, struct expr_t *,
+ register word32 *, register word32 *);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern int32 __has_vpi_driver(struct net_t *np, struct net_pin_t *npp);
+extern int32 __update_tran_harddrvs(struct net_t *);
+extern void __eval_tran_bits(register struct net_t *);
+extern void __ld_addr(word32 **, word32 **, register struct net_t *);
+extern void __st_val(struct net_t *, register word32 *, register word32 *);
+extern char *__st_regab_tostr(char *, byte *, int32);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern void __pth_stren_schd_allofwire(struct net_t *, register byte *, int32);
+extern void __wdel_stren_schd_allofwire(struct net_t *, register byte *,
+ int32);
+extern void __pth_schd_allofwire(struct net_t *, register word32 *,
+ register word32 *, int32);
+extern void __wdel_schd_allofwire(struct net_t *, register word32 *,
+ register word32 *, int32);
+extern void __rhspsel(register word32 *, register word32 *, register int32,
+ register int32);
+extern void __lhspsel(register word32 *, register int32, register word32 *,
+ register int32);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_wtnam2(char *, word32);
+extern void __adds(char *);
+extern void __chg_xprline_size(int32);
+extern void __disp_itree_path(register struct itree_t *, struct task_t *);
+extern void __ld_gate_wide_val(word32 *, word32 *, word32 *, int32);
+extern void __trunc_cstr(char *, int32, int32);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern int32 __get_arrwide(struct net_t *);
+extern char *__var_tostr(char *, struct net_t *, int32, int32, int32);
+extern void __disp_var(struct net_t *, int32, int32, int32, char);
+extern int32 __unnormalize_ndx(struct net_t *, int32);
+extern void __get_cor_range(register int32, union intptr_u, register int32 *,
+ register int32 *);
+extern void __getarr_range(struct net_t *, int32 *, int32 *, int32 *);
+extern void __getwir_range(struct net_t *, int32 *, int32 *);
+extern int32 __unmap_ndx(int32, int32, int32);
+extern char *__schop(char *, char *);
+extern char *__get_tfcellnam(struct tfrec_t *);
+extern int32 __vval_isallzs(word32 *, word32 *, int32);
+extern int32 __st_vval_isallzs(byte *, int32);
+extern char *__to_wrange(char *, struct net_t *);
+extern char *__to_arr_range(char *, struct net_t *);
+extern char *__to1_stren_nam(char *, int32, int32);
+extern int32 __fr_cap_size(int32);
+extern void __bld_forcedbits_mask(word32 *, struct net_t *);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern int32 __match_push_targ_to_ref(word32, struct gref_t *);
+extern char *__to_tcnam(char *, word32);
+extern int32 __get_eval_word(struct expr_t *, word32 *);
+extern int32 __ip_indsrch(char *);
+extern char *__to_timunitnam(char *, word32);
+extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
+extern void __sdispb(register word32 *, register word32 *, int32, int32);
+extern int32 __trim1_0val(word32 *, int32);
+extern void __declcnv_tostr(char *, word32 *, int32, int32);
+extern struct task_t *__getcur_scope_tsk(void);
+extern void __add_nchglst_el(register struct net_t *);
+extern void __add_dmpv_chglst_el(struct net_t *);
+extern void __wakeup_delay_ctrls(register struct net_t *, register int32,
+ register int32);
+extern char *__to_npptyp(char *, struct net_pin_t *);
+
+extern void __cv_msg(char *, ...);
+extern void __cvsim_msg(char *, ...);
+extern void __tr_msg(char *, ...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __pv_warn(int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+
+extern word32 __masktab[];
+extern byte __stren_map_tab[];
+extern word32 __cap_to_stren[];
+
+/*
+ * ROUTINES TO SET PORT ASSIGN
+ */
+
+/*
+ * set module port assign routines (type of acceleration)
+ */ 
+extern void __set_mpp_assign_routines(void)
+{
+ register int32 pi, ii;
+ register struct mod_pin_t *mpp;
+ int32 pnum;
+ struct mod_t *mdp, *imdp;
+ struct inst_t *ip;
+ struct expr_t *xp;
+
+ /* step 1: set the - down from iconn to mod port from module ports */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if ((pnum = mdp->mpnum) == 0) continue;
+
+   /* SJM - PORT REMOVE */
+   /* for top module set assign routine to nil - will force early core dump */
+   /* if error */
+   if (mdp->minstnum == 0)
+    {
+     /* leave port assign routines as nil for top level */
+     for (pi = 0; pi < mdp->mpnum; pi++) 
+      { mpp = &(mdp->mpins[pi]); mpp->assgnfunc_set = TRUE; }
+     continue;
+    }
+
+   for (pi = 0; pi < mdp->mpnum; pi++) 
+    {
+     mpp = &(mdp->mpins[pi]);
+
+     /* never have NP ICONN or NP MDPRT for inout */
+     if (mpp->mptyp == IO_BID) { mpp->assgnfunc_set = TRUE; continue; }
+
+     /* need iconn lhs info for setting output assign routines */
+     if (mpp->mptyp == IO_OUT) continue;
+
+
+     set_from_mpp_unopts(mdp, mpp, -1);
+    }
+  }
+ /* step 2: look at all up instance connections to see if can optimize */ 
+ /* can only be down after all low conn mod ports processed in step 1 */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* first process all instances in module */
+   for (ii = 0; ii < mdp->minum; ii++)
+    {
+     ip = &(mdp->minsts[ii]);
+     imdp = ip->imsym->el.emdp;
+     if ((pnum = imdp->mpnum) == 0) continue;
+
+     for (pi = 0; pi < pnum; pi++)
+      {
+       mpp = &(imdp->mpins[pi]);
+       if (mpp->assgnfunc_set)
+        {
+         /* if assgn func set turned on, must not try to optimize more */
+         continue;
+        }
+
+       /* port (either in or out) down must be simple ID for any accelerate */
+       if (mpp->mpref->optyp != ID)  
+        {
+         if (__debug_flg)
+          dbg_unopt2_msg(imdp, ip, pi, mpp, -1, "port is expression");
+         if (mpp->mptyp == IO_IN)
+          mpp->mpaf.mpp_downassgnfunc = std_downtomdport;
+         else mpp->mpaf.mpp_upassgnfunc = std_uptoiconn;
+         mpp->assgnfunc_set = TRUE;
+         continue;
+        }
+
+       /* if assign not know, down must be simple wire */
+       xp = ip->ipins[pi];
+
+       /* set the best possible optimization routine from highconn */
+       set_from_hconn_unopts(imdp, ip, pi, xp, mpp, -1);
+      }
+    }
+  } 
+}
+
+/*
+ * set decomposed from hconn concat per bit mod port assign routines
+ * i.e. set type of acceleration for interpreter
+ *
+ * -O does much better job of optimizing these
+ */ 
+extern void __set_pb_mpp_assign_routines(void)
+{
+ register int32 pi, ii, pbi;
+ register struct mod_pin_t *mpp;
+ int32 pnum;
+ struct mod_pin_t *mast_mpp;
+ struct mod_t *mdp, *imdp;
+ struct inst_t *ip;
+ struct expr_t *xp;
+
+ /* step 1: set the - down from iconn to mod port from module ports */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if ((pnum = mdp->mpnum) == 0) continue;
+
+   /* no top level ports do not have any highconn - so never decomposed */
+   if (mdp->minstnum == 0) continue;
+
+   for (pi = 0; pi < mdp->mpnum; pi++) 
+    {
+     mast_mpp = &(mdp->mpins[pi]);
+     if (!mast_mpp->has_scalar_mpps) continue; 
+
+     for (pbi = 0; pbi < mast_mpp->mpwide; pbi++)
+      {
+       mpp = &(mast_mpp->pbmpps[pbi]);
+       
+       /* need iconn lhs info for setting output assign routines */
+       if (mpp->mptyp == IO_OUT) continue;
+       set_from_mpp_unopts(mdp, mpp, pbi);
+      }
+    }
+  }
+ /* step 2: look at all up instance connections to see if can optimize */ 
+ /* can only be down after all low conn mod ports processed in step 1 */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* first process all instances in module */
+   for (ii = 0; ii < mdp->minum; ii++)
+    {
+     ip = &(mdp->minsts[ii]);
+     imdp = ip->imsym->el.emdp;
+     if ((pnum = imdp->mpnum) == 0) continue;
+
+     for (pi = 0; pi < pnum; pi++)
+      {
+       mast_mpp = &(imdp->mpins[pi]);
+       /* if low conn of this high conn not dcomposed into per bit, done */
+       if (!mast_mpp->has_scalar_mpps) continue; 
+
+       /* if this one's up iconn not separable - ignore for setting accel */
+       if (ip->pb_ipins_tab == NULL || ip->pb_ipins_tab[pi] == NULL)
+        continue;
+
+       for (pbi = 0; pbi < mast_mpp->mpwide; pbi++)
+        {
+         mpp = &(mast_mpp->pbmpps[pbi]);
+         if (mpp->assgnfunc_set) continue;
+
+         /* LOOKATME ??? - down will almost always be bsel for these */ 
+         /* port (in or out) down must be simple ID for any accelerate */
+         if (mpp->mpref->optyp != ID)  
+          {
+           if (__debug_flg)
+            dbg_unopt2_msg(imdp, ip, pi, mpp, pbi,
+             "per bit port is expression");
+
+           if (mpp->mptyp == IO_IN)
+            mpp->mpaf.mpp_downassgnfunc = std_downtomdport;
+           else mpp->mpaf.mpp_upassgnfunc = std_uptoiconn;
+           mpp->assgnfunc_set = TRUE;
+
+           continue;
+          }
+
+         /* if assign not know, down must be simple wire */
+         xp = ip->pb_ipins_tab[pi][pbi];
+         /* set the best possible optimization routine from highconn */
+         set_from_hconn_unopts(imdp, ip, pi, xp, mpp, pbi);
+        }
+      }
+    }
+  } 
+}
+
+/*
+ * set ports that can't be optimized determinable only from down mpp
+ * also sets input port fi>1 down assign since independent of iconn 
+ *
+ * if pbi not -1 then this is bit of per bit decomposed input port
+ */
+static void set_from_mpp_unopts(struct mod_t *mdp, struct mod_pin_t *mpp,
+ int32 pbi)
+{
+ struct net_t *down_np;
+
+ if (mpp->mpref->optyp != ID)
+  {  
+   if (__debug_flg) dbg_unopt_msg(mdp, mpp, pbi, "port is expression");
+   mpp->mpaf.mpp_downassgnfunc = std_downtomdport;
+   mpp->assgnfunc_set = TRUE;
+   return;
+  }
+ down_np = mpp->mpref->lu.sy->el.enp;
+ /* path destinations are stored as delay wires */
+ if (down_np->ntraux != NULL || down_np->nrngrep == NX_DWIR)
+  {
+   if (__debug_flg)
+    dbg_unopt_msg(mdp, mpp, pbi, "port in tran chan., delay or path dest.");
+   mpp->mpaf.mpp_downassgnfunc = std_downtomdport;
+   mpp->assgnfunc_set = TRUE;
+   return;
+  }
+ /* if port wire multfi - all will be so now know fits fi>1 acc case */
+ if (down_np->n_multfi)
+  {
+   if (__debug_flg) dbg_unopt_msg(mdp, mpp, pbi,
+    "port fi>1 - optimized some");
+   mpp->mpaf.mpp_downassgnfunc = multfi_acc_downtomdport;
+   mpp->assgnfunc_set = TRUE;
+  }
+}
+
+/*
+ * set optimized routines from high conn iconn info
+ *
+ * uses up iconn expr info and optimize info set in step 1 mpp processing 
+ * know down is simple ID or not called 
+ *
+ * works for both normal ports and per bit decomposed input ports
+ * from concat high conns where pbi is bit, and xp/mpp are per bit decomposed
+ */
+static void set_from_hconn_unopts(struct mod_t *imdp, struct inst_t *ip,
+ int32 pi, struct expr_t *xp, struct mod_pin_t *mpp, int32 pbi)
+{
+ struct net_t *up_np, *down_np;
+
+ down_np = mpp->mpref->lu.sy->el.enp;
+ /* always non acc if not same width */
+ if (mpp->mpref->szu.xclen != xp->szu.xclen)
+  {
+   if (__debug_flg) dbg_unopt2_msg(imdp, ip, pi, mpp, pbi, "widths differ");
+set_unoptim:
+   if (mpp->mptyp == IO_IN) mpp->mpaf.mpp_downassgnfunc = std_downtomdport;
+   else mpp->mpaf.mpp_upassgnfunc = std_uptoiconn;
+   mpp->assgnfunc_set = TRUE;
+   return;
+  }
+ if (mpp->mptyp == IO_IN)
+  {
+   /* down input port assign, know port lhs is optimizable */
+   /* make sure rhs up iconn optimizable */
+   if (xp->optyp == ID)
+    {
+     up_np = xp->lu.sy->el.enp;
+     /* both up and down must be have or not have stren */
+     if ((up_np->n_stren && !down_np->n_stren)
+      || (!up_np->n_stren && down_np->n_stren))
+      { 
+       if (__debug_flg) dbg_unopt2_msg(imdp, ip, pi, mpp, pbi,
+        "strength needed differs");
+       goto set_unoptim;
+      }  
+     if (down_np->n_stren) 
+      {
+       if (xp->szu.xclen == 1) 
+        mpp->mpaf.mpp_downassgnfunc = stbsel_acc_downtomdport;
+       else mpp->mpaf.mpp_downassgnfunc = stacc_downtomdport;
+       return;
+      }
+     /* non strength ID case */  
+     if (xp->szu.xclen == 1)
+      mpp->mpaf.mpp_downassgnfunc = bsel_acc_downtomdport;
+     else mpp->mpaf.mpp_downassgnfunc = acc_downtomdport;
+     return;
+    }
+   /* bit select for this up iconn case */
+   /* SJM 07/24/03 - bit select from XMR high conn must not be optimized */
+   if (xp->optyp != LSB || xp->lu.x->optyp != ID
+    || mpp->mpref->szu.xclen != 1)
+    {   
+     if (__debug_flg)
+      dbg_unopt2_msg(imdp, ip, pi, mpp, pbi,
+       "vector port but not bit select from ID highconn");
+     goto set_unoptim;
+    } 
+   /* maybe up bit select or scalar - must be constant index */
+   if (xp->ru.x->optyp != NUMBER)
+    {
+     if (__debug_flg)
+      dbg_unopt2_msg(imdp, ip, pi, mpp, pbi, "bit select highconn expr.");
+     goto set_unoptim;
+    }
+   up_np = xp->lu.x->lu.sy->el.enp;
+   /* both must be same strength */
+   if ((up_np->n_stren && !down_np->n_stren)
+    || (!up_np->n_stren && down_np->n_stren))
+    {  
+     if (__debug_flg)
+      dbg_unopt2_msg(imdp, ip, pi, mpp, pbi, "bsel strength needed differs");
+     goto set_unoptim;
+    }
+   /* may reduce optimlzation level to bsel form */ 
+   if (down_np->n_stren)
+    mpp->mpaf.mpp_downassgnfunc = stbsel_acc_downtomdport;
+   else mpp->mpaf.mpp_downassgnfunc = bsel_acc_downtomdport;
+   return;
+  }
+
+ /* hard output port case - assign to varying up iconns */ 
+ /* know mod port is ID and widths same or will not get here */
+ if (xp->optyp == ID) up_np = xp->lu.sy->el.enp; 
+ else if (xp->optyp == LSB) up_np = xp->lu.x->lu.sy->el.enp;
+ /* no debug message needed here because assign never happens */
+ else if (xp->optyp == OPEMPTY) goto set_unoptim;
+ else
+  {
+   if (__debug_flg)
+    dbg_unopt2_msg(imdp, ip, pi, mpp, pbi, "iconn not bsel or wire");
+   goto set_unoptim;
+  }
+
+ /* cannot have delay (also path dest.) or be in tran channel */
+ if (up_np->nrngrep == NX_DWIR || up_np->ntraux != NULL)
+  {
+   if (__debug_flg)
+    dbg_unopt2_msg(imdp, ip, pi, mpp, pbi,
+    "iconn in tran chan or delay/path dest.");
+   goto set_unoptim;
+  }
+ if (up_np->n_multfi)
+  {
+   if (mpp->mpaf.mpp_upassgnfunc == NULL)
+    { mpp->mpaf.mpp_upassgnfunc = multfi_acc_uptoiconn; return; }
+   /* if some instance connections, fi>1 and other not, not acc */ 
+   if (mpp->mpaf.mpp_upassgnfunc != multfi_acc_uptoiconn)
+    goto mixed_multfi;
+   return;
+  }
+ if (mpp->mpaf.mpp_upassgnfunc == multfi_acc_uptoiconn)
+  {
+mixed_multfi:
+   if (__debug_flg)
+    dbg_unopt2_msg(imdp, ip, pi, mpp, pbi, 
+     "mixed fi>1 and non fi>1 highconns");
+   goto set_unoptim;
+  }  
+
+ /* both strengths must be same */
+ if ((up_np->n_stren && !down_np->n_stren)
+  || (!up_np->n_stren && down_np->n_stren)) goto set_unoptim;
+ if (xp->optyp == ID)
+  {
+   if (up_np->n_stren) 
+    {
+     /* must be acc. bsel */
+     if (xp->szu.xclen == 1) mpp->mpaf.mpp_upassgnfunc = stbsel_acc_uptoiconn;
+     else mpp->mpaf.mpp_upassgnfunc = stacc_uptoiconn;
+     return;
+    }
+   if (xp->szu.xclen == 1) mpp->mpaf.mpp_upassgnfunc = bsel_acc_uptoiconn;
+   else mpp->mpaf.mpp_upassgnfunc = acc_uptoiconn;
+   return;
+  }
+ /* bit select case */
+ if (down_np->n_stren) mpp->mpaf.mpp_upassgnfunc = stbsel_acc_uptoiconn;
+ else mpp->mpaf.mpp_upassgnfunc = bsel_acc_uptoiconn;
+}
+
+/*
+ * assign std port assign routines if accelerate (port assign optimize off)
+ */
+extern void __set_mpp_aoff_routines(void)
+{
+ register int32 pi, pbi;
+ register struct mod_t *mdp;
+ register struct mod_pin_t *mpp, *mpp2;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->minstnum == 0)
+    {
+     for (pi = 0; pi < mdp->mpnum; pi++)
+      {
+       mpp = &(mdp->mpins[pi]);
+       mpp->assgnfunc_set = TRUE;
+      }
+     continue;
+    }
+
+   for (pi = 0; pi < mdp->mpnum; pi++) 
+    {
+     mpp = &(mdp->mpins[pi]);
+     mpp->assgnfunc_set = TRUE;
+
+     /* lhs destination from port type determines routine */
+     if (mpp->mptyp == IO_OUT) mpp->mpaf.mpp_upassgnfunc = std_uptoiconn;
+     else if (mpp->mptyp == IO_IN)
+      mpp->mpaf.mpp_downassgnfunc = std_downtomdport;
+     else continue;
+
+     for (pbi = 0; pbi < mpp->mpwide; pbi++)    
+      {
+       mpp2 = &(mpp->pbmpps[pbi]);
+       /* only per bit for input ports */
+       mpp2->mpaf.mpp_downassgnfunc = std_downtomdport;
+       mpp2->assgnfunc_set = TRUE;
+      }
+    }
+  }
+}
+
+/*
+ * set new routine when mod port wire has added vpi put value driver added 
+ *
+ * SJM 09/20/02 - this may be separated per bit mod port 
+ */
+extern void __vpi_set_downtomdport_proc(struct mod_pin_t *mpp,
+ struct net_t *np)
+{
+ /* if not accelerated when fi==1, then cannot be when fi>1 */
+ if (mpp->mpaf.mpp_downassgnfunc == std_downtomdport) return;
+
+ /* driver of wire np in module is module port from up inst. */
+ if (mpp->mpref->optyp == ID && np->ntraux == NULL && np->nrngrep != NX_DWIR)
+   mpp->mpaf.mpp_downassgnfunc = multfi_acc_downtomdport;
+ else mpp->mpaf.mpp_downassgnfunc = std_downtomdport;
+}
+
+/*
+ * for up to iconn that is now multfi, cannot optimize
+ * because do not know other instances  
+ */
+extern void __vpi_set_upiconnport_proc(struct mod_pin_t *mpp)
+{
+ mpp->mpaf.mpp_upassgnfunc = std_uptoiconn;
+}
+
+/*
+ * write a debug reason message for why port not optimized 
+ * this is port side message for input ports
+ */
+static void dbg_unopt_msg(struct mod_t *mdp, struct mod_pin_t *mpp, int32 pbi,
+ char *reason)
+{
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (pbi == -1) __to_mpnam(s2, mpp->mpsnam);
+ else sprintf(s2, "%s bit %d", __to_mpnam(s3, mpp->mpsnam), pbi);
+ __dbg_msg("module %s %s port %s unoptimized: %s\n", mdp->msym->synam,
+  __to_ptnam(s1, mpp->mptyp), s2, reason);  
+}
+
+/*
+ * write a debug reason message for why port not optimized 
+ * this is inst conn. side message for output ports
+ */
+static void dbg_unopt2_msg(struct mod_t *mdp, struct inst_t *ip, int32 pi,
+ struct mod_pin_t *mpp, int32 pbi, char *reason)
+{
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[RECLEN];
+
+ if (pbi == -1) __to_mpnam(s3, mpp->mpsnam);
+ else sprintf(s3, "%s bit %d", __to_mpnam(s4, mpp->mpsnam), pbi);
+
+ __dbg_msg("inst. %s(%s) at %s %s port %s (pos. %d) unoptimized: %s\n",
+  ip->isym->synam, mdp->msym->synam, __bld_lineloc(s1, ip->isym->syfnam_ind,
+  ip->isym->sylin_cnt), __to_ptnam(s2, mpp->mptyp), s3, pi, reason);  
+}
+
+/*
+ * PORT UP AND DOWN ASSIGN ROUTINES
+ */
+
+/*
+ * assign all input ports downward into lower itree instance
+ * called from up_itp where itp (down) is under itree place
+ *
+ * assumes called with nothing pushed on itree stack
+ * never called for inout in tran channel - initialized elsewhere
+ */
+extern void __init_instdownport_contas(struct itree_t *up_itp,
+ struct itree_t *down_itp)
+{
+ register int32 pi;
+ register struct mod_pin_t *mpp;
+ struct expr_t *xp;
+ struct inst_t *ip;
+ struct mod_t *down_mdp;
+ int32 pnum;
+
+ ip = down_itp->itip;
+ down_mdp = ip->imsym->el.emdp;
+ if ((pnum = down_mdp->mpnum) == 0) return;
+
+ /* this must work from up itree loc */
+ __push_itstk(up_itp);
+ for (pi = 0; pi < pnum; pi++) 
+  {
+   xp = ip->ipins[pi];
+   mpp = &(down_mdp->mpins[pi]);
+   if (mpp->mptyp != IO_IN) continue;
+   
+   __immed_assigns++;
+   /* must be call with current itree location up (rhs) but passed down */
+   /* exec inst. input expr. downward to port changed assign */
+   /* notice down always take only 4 args, down do not have first mpp */
+   (*mpp->mpaf.mpp_downassgnfunc)(mpp->mpref, xp, down_itp);
+  }
+ __pop_itstk();
+}
+
+/*
+ * initialize cross module out instance ports continuous assigns 
+ *
+ * can get to up itree loc. but following up ptr
+ * never called for inout in tran channel - initialized elsewhere
+ */
+extern void __init_instupport_contas(struct itree_t *down_itp)
+{
+ register int32 pi;
+ register struct mod_pin_t *mpp;
+ struct expr_t *xp;
+ struct inst_t *ip;
+ struct mod_t *down_mdp;
+ struct itree_t *up_itp;
+ int32 pnum;
+
+ ip = down_itp->itip;
+ down_mdp = ip->imsym->el.emdp;
+ if ((pnum = down_mdp->mpnum) == 0) return;
+
+ /* cannot assume current itree location - need down starting */
+ __push_itstk(down_itp);
+ for (pi = 0; pi < pnum; pi++) 
+  {
+   xp = ip->ipins[pi];
+   mpp = &(down_mdp->mpins[pi]);
+   
+   if (mpp->mptyp != IO_OUT) continue;
+
+   __immed_assigns++;
+   /* called from down module itree location */ 
+   /* SJM - PORT REMOVE - no assign if top level module - ports remain */
+   if ((up_itp = __inst_ptr->up_it) == NULL) continue;
+
+   /* assign from rhs down mpp ref. to up lhs iconn */
+   /* notice up always take only 3 args, down have extra 1st arg mpp */
+   (*mpp->mpaf.mpp_upassgnfunc)(xp, mpp->mpref, up_itp);
+  }
+ __pop_itstk();
+}
+
+/*
+ * ROUTINES FOR VARIOUS CASES OF DOWN INPUT PORT FROM ICONN TO MDPRT ASSIGN
+ */
+
+/*
+ * down from iconn to port assign - for all non special cases
+ *
+ * called from up iconn rhs itree loc.
+ * this is standard (general) function that must handle all cases 
+ *
+ * if any inst. size change, in tran channel, lhs has delay, some but not
+ * all fi>1, any iconn is xmr, any iconn is concat, down port is expr.,
+ * up is not wire or reg expr, this routine used - must be some more reasons?
+ * called from up rhs iconn itree loc.
+ */
+static void std_downtomdport(register struct expr_t *lhsx,
+ register struct expr_t *rhsx, struct itree_t *down_itp)
+{
+ register struct xstk_t *xsp;
+ int32 schd_wire, orhslen;
+
+ if (lhsx->x_multfi)
+  {
+   /* always must evaluate drivers with itstk of lhs (i.e. down) */
+   __push_itstk(down_itp);
+   /* all lhs expr. containging tran chan wire mult fi and handled here */
+   __mdr_assign_or_sched(lhsx);
+
+   /* assigned to down (destination) wire loads of this new assigned to */
+   /* wire will be added to net chg list */
+   /* DBG remove ---
+   if (__debug_flg && __ev_tracing)
+    prt_assignedto_val(lhsx, "fi>1 down port assign");
+   --- */
+   __pop_itstk();
+   return;
+  }
+
+ /* if inst. input expr. is empty, nothing to do */
+ if (rhsx->optyp == OPEMPTY) return;
+ if (lhsx->x_stren)
+  {
+   /* handle lhs stren assign - pass strength through */
+   /* other side always marked strength and if rhs reg, will add in strong */ 
+   xsp = __ndst_eval_xpr(rhsx);
+   /* widen to lhs width with z's - if too narrow, high part just unused */
+   /* SJM 05/10/04 - no sign extension because widening to z'x */
+   if (xsp->xslen < lhsx->szu.xclen)
+    __strenwiden_sizchg(xsp, lhsx->szu.xclen);
+  }
+ else
+  {
+   xsp = __eval_xpr(rhsx);
+   if (lhsx->szu.xclen != xsp->xslen)
+    {
+     orhslen = xsp->xslen;
+
+     /* SJM 09/29/03 - change to handle sign extension and separate types */
+     if (xsp->xslen > lhsx->szu.xclen)
+      __narrow_sizchg(xsp, lhsx->szu.xclen);
+     else if (xsp->xslen < lhsx->szu.xclen)
+      {
+       if (rhsx->has_sign) __sgn_xtnd_widen(xsp, lhsx->szu.xclen);
+       else __sizchg_widen(xsp, lhsx->szu.xclen);
+      }
+
+     /* widened, set bits higher than orhslen to z */ 
+     /* LOOKATME - only strength continuous assignments widen to z */
+     /* all others widen to 0 */
+     /* ??? if (orhslen < xsp->xslen) __fix_widened_tozs(xsp, orhslen); */
+     /* SJM 05/10/04 - widening to x's eliminates need for sign difference */
+     if (__wire_init) __fix_widened_toxs(xsp, orhslen);
+    }
+  }
+ /* eval. in up itree side but assign on to lhs in down */ 
+ __push_itstk(down_itp);
+ if (lhsx->lhsx_ndel && !__wire_init) schd_wire = TRUE;
+ else schd_wire = FALSE;
+ if (lhsx->x_stren)
+  {
+   /* port conta just assigns strengths */ 
+   if (lhsx->optyp == LCB)
+    __stren_exec_ca_concat(lhsx, (byte *) xsp->ap, schd_wire);
+   else __exec_conta_assign(lhsx, xsp->ap, xsp->bp, schd_wire);
+  }
+ else
+  {
+   if (lhsx->optyp == LCB)
+    __exec_ca_concat(lhsx, xsp->ap, xsp->bp, schd_wire);
+   else __exec_conta_assign(lhsx, xsp->ap, xsp->bp, schd_wire);
+  }
+ __pop_xstk();
+ /* DBG remove --
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "port down assign");
+ --- */  
+ /* notice cannot pop until here since lhs is down */
+ __pop_itstk();
+}
+
+/*
+ * print value of assign to output wire 
+ * only called when debug flag and some kind of tracing on
+ */
+static void prt_assignedto_val(struct expr_t *xp, char *nppnam)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ if (xp->x_stren) strcpy(s2, "strength "); else strcpy(s2, "");
+ __tr_msg("== %s lvalue %swire %s set or scheduled to %s\n", nppnam, s2,
+  __msgexpr_tostr(__xs, xp), __to_gassign_str(s1, xp));
+}
+
+/*
+ * mulfi lhs upward instance port assign from down module port assign 
+ * for output port
+ *
+ * only for down port multi-fi wire (could handle selects but rare)
+ * since port expressions rare
+ * since down lhs is module port all will be same 
+ * if port expr. or inout in tran channel, cannot use this routine
+ * can be either strength or non strength
+ * called from up rhs iconn itree location
+ */
+static void multfi_acc_downtomdport(register struct expr_t *lhsx,
+ struct expr_t *rhsx, struct itree_t *down_itp)
+{
+ /* for mdport fi>1, eval all drivers */
+ /* must evaluate drivers with itstk of lhs (i.e. down here) */
+ __push_itstk(down_itp);
+ __assign_1mdrwire(lhsx->lu.sy->el.enp);
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "fi>1 down port assign");
+ --- */
+ __pop_itstk();
+} 
+
+/*
+ * stren both wire/reg up iconn down to mod port assign special case routine 
+ * only called if all instances both same width IDs
+ * never for scalar - use bit select version for that 
+ *
+ * called from up rhs iconn itree location
+ */
+static void stacc_downtomdport(register struct expr_t *lhsx,
+ register struct expr_t *rhsx, struct itree_t *down_itp)
+{
+ byte *bp, *sbp;
+ struct net_t *lhsnp;
+ struct xstk_t *xsp;
+
+ push_xstk_(xsp, 4*rhsx->szu.xclen);
+ sbp = (byte *) xsp->ap;
+ get_stwire_addr_(bp, rhsx->lu.sy->el.enp);
+ memcpy(sbp, bp, rhsx->szu.xclen); 
+
+ /* assign in down */
+ __push_itstk(down_itp);
+ lhsnp = lhsx->lu.sy->el.enp;
+ /* this adds the changed wire to nchglst if needed */
+ /* return F if all of wire forced, nothing to do */ 
+ if (lhsnp->frc_assgn_allocated)
+  {
+   if (!__correct_forced_newwireval(lhsnp, (word32 *) sbp, (word32 *) NULL))
+    { __pop_itstk(); __pop_xstk(); return; }
+  }
+ __chg_st_val(lhsnp, (word32 *) sbp, (word32 *) NULL);
+ __pop_xstk();
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "strength mod. port down assign");
+ --- */
+ __pop_itstk();
+}
+
+/*
+ * stren both wire/reg up iconn down to mod port assign special case routine 
+ * this is also called for all scalars on up inst. 
+ *
+ * only called if all instances both scalar IDs or up bsel and down
+ * and nothing special such as delay wire
+ * only strength scalars handled here
+ */
+static void stbsel_acc_downtomdport(register struct expr_t *lhsx,
+ register struct expr_t *rhsx, struct itree_t *down_itp)
+{
+ struct net_t *lhsnp;
+ byte sb2, *bp, *sbp;
+
+ /* eval rhs up iconn in current itree up loc. */
+ if (rhsx->optyp == LSB) access_stbsel(&sb2, rhsx);
+ else { get_stwire_addr_(bp, rhsx->lu.sy->el.enp); sb2 = bp[0]; }
+
+ /* assign in down */
+ __push_itstk(down_itp);
+ lhsnp = lhsx->lu.sy->el.enp;
+ /* this is needed so for endian differences - cast of ptr does nothing */
+ sbp = &sb2;
+ /* this adds the changed wire to nchglst if needed */
+ /* return F if all of wire forced, nothing to do */ 
+ if (lhsnp->frc_assgn_allocated)
+  {
+   if (!__correct_forced_newwireval(lhsnp, (word32 *) sbp, (word32 *) NULL))
+    { __pop_itstk(); return; }
+  }
+ __chg_st_val(lhsnp, (word32 *) sbp, (word32 *) NULL);
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "strength scalar mod. port assign");
+ --- */
+ __pop_itstk();
+}
+
+/*
+ * non stren both wire upward to instance port assign special case routine 
+ * only called if all instances both same width IDs
+ * acc bsel routine called for scalars 
+ */
+static void acc_downtomdport(register struct expr_t *lhsx,
+ register struct expr_t *rhsx, struct itree_t *down_itp)
+{
+ register struct xstk_t *xsp;
+ struct net_t *lhsnp;
+
+ /* up rhs always wire/reg or not fast routine */
+ /* eval rhs up iconn in current itree up loc. */
+ push_xstk_(xsp, rhsx->szu.xclen);
+ __ld_wire_val(xsp->ap, xsp->bp, rhsx->lu.sy->el.enp);
+
+ /* assign in down */
+ __push_itstk(down_itp);
+ lhsnp = lhsx->lu.sy->el.enp;
+ /* this adds the changed wire to nchglst if needed */
+ /* return F if all of wire forced, nothing to do */ 
+ if (lhsnp->frc_assgn_allocated)
+  {
+   if (!__correct_forced_newwireval(lhsnp, xsp->ap, xsp->bp))
+    { __pop_itstk(); __pop_xstk(); return; }
+  }
+ __chg_st_val(lhsnp, xsp->ap, xsp->bp);
+ __pop_xstk();
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "mod. port assign");
+ --- */
+ __pop_itstk();
+}
+
+/*
+ * up wire bsel to instance port scalar assign special case routine 
+ *
+ * only called if up rhs is scalar or bit select and down port
+ * is scalar wire - all insts must also be simple and not in tran channel
+ * this is only for scalars and at least one bsel
+ */
+static void bsel_acc_downtomdport(register struct expr_t *lhsx,
+ register struct expr_t *rhsx, struct itree_t *down_itp)
+{
+ int32 biti;
+ word32 av, bv;
+ struct net_t *lhsnp, *rhsnp;
+
+ /* down rhs always wire/reg or not accelerated routine */
+ if (rhsx->optyp == LSB)
+  {
+   rhsnp = rhsx->lu.x->lu.sy->el.enp;
+   /* know biti never -1 since only fixed non -1 for this routine */
+   biti = __comp_ndx(rhsnp, rhsx->ru.x);
+   __ld_bit(&av, &bv, rhsnp, biti);
+  }
+ else __ld_wire_val(&av, &bv, rhsx->lu.sy->el.enp);
+
+ /* assign in down - never an expr. */
+ __push_itstk(down_itp);
+ lhsnp = lhsx->lu.sy->el.enp;
+ /* this adds the changed wire to nchglst if needed */
+ /* return F if all of wire forced, nothing to do */ 
+ if (lhsnp->frc_assgn_allocated)
+  {
+   if (!__correct_forced_newwireval(lhsnp, &av, &bv))
+    { __pop_itstk(); return; }
+  }
+ __chg_st_val(lhsnp, &av, &bv);
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "mod. port scalar assign");
+ --- */
+ __pop_itstk();
+}
+
+/*
+ * ROUTINES FOR THE VARIOUS CASES OF FROM DOWN MDPRT TO UP ICONN ASSIGN
+ */
+
+/*
+ * upward to instance port assign - for all non special cases
+ * this is standard (general) function that must handle all cases 
+ *
+ * if any inst. size change, in tran channel, lhs has delay, some but not
+ * all fi>1, any iconn is xmr, any iconn is concat, down port is expr.,
+ * up is not wire or reg expr, this routine used - must be some more reasons?
+ */
+static void std_uptoiconn(register struct expr_t *lhsx,
+ register struct expr_t *rhsx, struct itree_t *up_itp)
+{
+ register struct xstk_t *xsp;
+ int32 schd_wire, orhslen;
+
+ /* if destination driven by module output is empty, nothing to do */
+ if (lhsx->optyp == OPEMPTY) return;
+
+ /* for iconn part of fi>1, eval all drivers code */
+ if (lhsx->x_multfi)
+  {
+   /* always must evaluate drivers with itstk of lhs (i.e. up here) */
+   __push_itstk(up_itp);
+   __mdr_assign_or_sched(lhsx);
+
+   /* DBG remove ---
+   if (__debug_flg && __ev_tracing)
+    prt_assignedto_val(lhsx, "fi>1 upto highconn assign");
+   --- */
+   __pop_itstk();
+   return;
+  }
+ /* load rhs according to lhs expr. type and make size equal to lhs */
+ /* if port has no connections - LOOKATME maybe illegal, nothing to do */
+ if (rhsx->optyp == OPEMPTY) return;
+
+ /* eval rhs on current itree down loc. */
+ if (lhsx->x_stren)
+  {
+   /* handle lhs stren assign - pass strength through */
+   /* if reg, will add strong strength */
+   xsp = __ndst_eval_xpr(rhsx);
+   /* widen to lhs width with z's - if too narrow, high part just unused */
+   /* SJM 05/10/04 - no sign extension because widening to z'x */
+   if (xsp->xslen < lhsx->szu.xclen)
+    __strenwiden_sizchg(xsp, lhsx->szu.xclen);
+  }
+ else
+  {
+   xsp = __eval_xpr(rhsx);
+   if (lhsx->szu.xclen != xsp->xslen)
+    {
+     orhslen = xsp->xslen;
+
+     /* SJM 09/29/03 - change to handle sign extension and separate types */
+     if (xsp->xslen > lhsx->szu.xclen)
+      __narrow_sizchg(xsp, lhsx->szu.xclen);
+     else if (xsp->xslen < lhsx->szu.xclen)
+      {
+       if (rhsx->has_sign) __sgn_xtnd_widen(xsp, lhsx->szu.xclen);
+       else __sizchg_widen(xsp, lhsx->szu.xclen);
+      }
+
+     /* widened, set bits higher than orhslen to z */ 
+     /* LOOKATME - only strength continuous assignments widen to z */
+     /* all others widen to 0 except x during initialization */
+     /* ??? if (orhslen < xsp->xslen) __fix_widened_tozs(xsp, orhslen); */
+     /* SJM 05/10/04 - widening to x's eliminates need for sign difference */
+     if (__wire_init) __fix_widened_toxs(xsp, orhslen);
+    }
+  }
+ /* but assign on lhs up iconn itree location */
+ __push_itstk(up_itp);
+ if (lhsx->lhsx_ndel && !__wire_init) schd_wire = TRUE;
+ else schd_wire = FALSE;
+ /* notice here is lhs is gref, assign handles finding right itree loc. */
+ if (lhsx->x_stren)
+  {
+   /* port conta just assigns strengths */ 
+   if (lhsx->optyp == LCB)
+    __stren_exec_ca_concat(lhsx, (byte *) xsp->ap, schd_wire);
+   else __exec_conta_assign(lhsx, xsp->ap, xsp->bp, schd_wire);
+  }
+ else
+  {
+   if (lhsx->optyp == LCB)
+    __exec_ca_concat(lhsx, xsp->ap, xsp->bp, schd_wire);
+   else __exec_conta_assign(lhsx, xsp->ap, xsp->bp, schd_wire);
+  }
+ __pop_xstk();
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "inst. conn. up assign");
+ --- */
+ __pop_itstk();
+}
+
+/*
+ * mulfi lhs upward instance port assign from down module port assign 
+ *
+ * only for down wire and up any multi-fi non concat simple and non tran
+ * if one multfi and any other not, std all cases routine must be used
+ * can be either strength or non strength
+ */
+static void multfi_acc_uptoiconn(register struct expr_t *lhsx,
+ struct expr_t *rhsx, struct itree_t *up_itp)
+{
+ /* for iconn part of fi>1, eval all drivers code */
+ /* must evaluate drivers with itstk of lhs (i.e. up here) */
+ __push_itstk(up_itp);
+ if (lhsx->optyp == ID) __assign_1mdrwire(lhsx->lu.sy->el.enp);
+ else __assign_1mdrwire(lhsx->lu.x->lu.sy->el.enp);
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "fi>1 up to highconn assign");
+ --- */
+ __pop_itstk();
+} 
+
+/*
+ * stren both wire upward to instance port assign special case routine 
+ * only called if all instances both same width IDs
+ */
+static void stacc_uptoiconn(register struct expr_t *lhsx,
+ register struct expr_t *rhsx, struct itree_t *up_itp)
+{
+ byte *bp, *sbp;
+ struct net_t *lhsnp;
+ struct xstk_t *xsp;
+
+ /* eval rhs mod port in current itree down loc. */
+ /* for accelerated know down port rhs is not an expression */
+ push_xstk_(xsp, 4*rhsx->szu.xclen);
+ sbp = (byte *) xsp->ap;
+ get_stwire_addr_(bp, rhsx->lu.sy->el.enp);
+ memcpy(sbp, bp, rhsx->szu.xclen); 
+
+ /* assign in up */
+ __push_itstk(up_itp);
+ lhsnp = lhsx->lu.sy->el.enp;
+ /* this adds the changed wire to nchglst if needed */
+ /* return F if all of wire forced, nothing to do */ 
+ if (lhsnp->frc_assgn_allocated)
+  {
+   if (!__correct_forced_newwireval(lhsnp, (word32 *) sbp, (word32 *) NULL))
+    { __pop_itstk(); __pop_xstk(); return; }
+  }
+ __chg_st_val(lhsnp, (word32 *) sbp, (word32 *) NULL);
+ __pop_xstk();
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "strength inst. conn. up assign");
+ --- */
+ __pop_itstk();
+}
+
+/*
+ * stren up wire bsel to instance port scalar assign special case routine 
+ *
+ * only called if up lhs is strength bit select or scalar and down
+ * is scalar wire, all insts must also be simple and not in tran channel
+ */
+static void stbsel_acc_uptoiconn(register struct expr_t *lhsx,
+ register struct expr_t *rhsx, struct itree_t *up_itp)
+{
+ byte *bp, sb2, *sbp;
+ struct net_t *lhsnp;
+ struct expr_t *idndp, *ndx1;
+
+ /* eval rhs mod port in current itree down loc. */
+ /* for accelerated know down port rhs is not an expression */
+ get_stwire_addr_(bp, rhsx->lu.sy->el.enp);
+ sb2 = bp[0];
+ sbp = &sb2;
+
+ __push_itstk(up_itp);
+ /* here can be either stren scalar or bit select */
+ if (lhsx->optyp == ID)
+  {
+   lhsnp = lhsx->lu.sy->el.enp;
+   if (lhsnp->frc_assgn_allocated)
+    {
+     if (!__correct_forced_newwireval(lhsnp, (word32 *) sbp, (word32 *) NULL))
+      { __pop_itstk(); return; }
+    }
+   __chg_st_val(lhsnp, (word32 *) sbp, (word32 *) NULL);
+  }
+ else
+  {
+   idndp = lhsx->lu.x;
+   ndx1 = lhsx->ru.x;
+   lhsnp = idndp->lu.sy->el.enp;
+   /* the 1 bit is forced nothing to do else normal assign */
+   if (lhsnp->frc_assgn_allocated
+    && __forced_inhibit_bitassign(lhsnp, idndp, ndx1))
+    { __pop_itstk(); return; }
+   __assign_to_bit(lhsnp, idndp, ndx1, (word32 *) sbp, (word32 *) NULL);
+  }  
+ /* DBG remove --
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "strength scalar inst. conn. up assign");
+ --- */
+ __pop_itstk();
+}
+
+/*
+ * non stren both wire upward to instance port assign special case routine 
+ * only called if all instances both same width IDs
+ */
+static void acc_uptoiconn(register struct expr_t *lhsx,
+ register struct expr_t *rhsx, struct itree_t *up_itp)
+{
+ register struct xstk_t *xsp;
+ struct net_t *lhsnp;
+
+ /* down rhs always wire/reg or not accerated routine */
+ push_xstk_(xsp, rhsx->szu.xclen);
+ __ld_wire_val(xsp->ap, xsp->bp, rhsx->lu.sy->el.enp);
+
+ /* assign in up */
+ __push_itstk(up_itp);
+ lhsnp = lhsx->lu.sy->el.enp;
+ /* this adds the changed wire to nchglst if needed */
+ /* return F if all of wire forced, nothing to do */ 
+ if (lhsnp->frc_assgn_allocated)
+  {
+   if (!__correct_forced_newwireval(lhsnp, xsp->ap, xsp->bp))
+    { __pop_itstk(); __pop_xstk(); return; }
+  }
+ __chg_st_val(lhsnp, xsp->ap, xsp->bp);
+ __pop_xstk();
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "inst. conn. up assign");
+ --- */
+ __pop_itstk();
+}
+
+/*
+ * up wire bsel to instance port scalar assign special case routine 
+ *
+ * only called if up lhs is strength bit select and down is scalar wire
+ * all insts must also be simple and not in tran channel
+ */
+static void bsel_acc_uptoiconn(register struct expr_t *lhsx,
+ register struct expr_t *rhsx, struct itree_t *up_itp)
+{
+ word32 av, bv;
+ struct net_t *lhsnp;
+ struct expr_t *idndp, *ndx1;
+
+ /* down rhs always wire/reg or not accerated routine */
+ __ld_wire_val(&av, &bv, rhsx->lu.sy->el.enp);
+
+ /* assign in up */
+ __push_itstk(up_itp);
+ /* here can be either stren scalar or bit select */
+ if (lhsx->optyp == ID)
+  {
+   lhsnp = lhsx->lu.sy->el.enp;
+   if (lhsnp->frc_assgn_allocated)
+    {
+     if (!__correct_forced_newwireval(lhsnp, &av, &bv))
+      { __pop_itstk(); return; }
+    }
+   __chg_st_val(lhsnp, &av, &bv);
+  }
+ else if (lhsx->optyp == LSB)
+  {
+   idndp = lhsx->lu.x;
+   ndx1 = lhsx->ru.x;
+   lhsnp = idndp->lu.sy->el.enp;
+   /* the 1 bit is forced nothing to do else normal assign */
+   if (lhsnp->frc_assgn_allocated
+    && __forced_inhibit_bitassign(lhsnp, idndp, ndx1))
+    { __pop_itstk(); return; }
+   __assign_to_bit(lhsnp, idndp, ndx1, &av, &bv);
+  }  
+ /* DBG remove (also above bsel if) -- */
+ else __case_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  prt_assignedto_val(lhsx, "strength scalar inst. conn. up assign");
+ --- */
+ __pop_itstk();
+}
+
+/*
+ * MULTI FAN IN NON STRENGTH WIRE ASSIGN ROUTINES
+ * ASSIGN BY EVALUATING ALL DRIVERS
+ */
+
+/*
+ * continuous assign for multi-fi and stren (even if fi=1) wires
+ * conta, mod and inst. ports
+ *
+ * this is called from itree loc. of lhsx, each driver eval may need
+ * to move to driving itree loc. load driver routine handles moving
+ *
+ * notice even if only a few bits are changed - must reevaluate all bits
+ * idea is that strengths are almost always scalars and multi-fi
+ */
+extern void __mdr_assign_or_sched(register struct expr_t *lhsx)
+{
+ register struct net_t *np;
+ int32 nd_itpop;
+ struct expr_t *idndp, *catndp;
+ struct gref_t *grp;
+
+ nd_itpop = FALSE;
+ switch ((byte) lhsx->optyp) {
+  case GLBREF:
+   idndp = lhsx;
+mdr_glb:
+   grp = idndp->ru.grp;
+   /* move from xmr ref. itree location to wire definition location */
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+   goto mdr_id;
+  case ID:
+   idndp = lhsx;
+mdr_id:
+   np = idndp->lu.sy->el.enp;
+   /* handle fi>1 eval and store of bits not in any tran channel */
+   if (np->ntraux != NULL)
+    {
+     /* if hard drivers of np do not change, channel cannot change */
+     /* SJM 12/18/00 - for tran/tranif switch channels may just add to list */
+     if (__update_tran_harddrvs(np))
+      {
+       /* can't eval (relax) tran channels until all hard drivers known */
+       /* so first relax can be done */
+       __eval_tran_bits(np);
+      }
+     break;
+    }
+   if (np->nrngrep == NX_DWIR) __sched_1mdrwire(np);
+   else __assign_1mdrwire(np);
+   break;
+  case LSB:
+  case PARTSEL:
+   idndp = lhsx->lu.x;
+   if (idndp->optyp == GLBREF) goto mdr_glb; else goto mdr_id;
+  case LCB:
+   /* must treat all wires in lhs multi-fan-in concat as special */ 
+   /* this means every lhs element needs re-eval of rhs */
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    __mdr_assign_or_sched(catndp->lu.x);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * assign to one entire wire with multiple fan-in
+ *
+ * it can have strength (or not) but delayed wire handled elsewhere
+ * cannot be either inout iconn or inout port wire
+ * called in lhs itree loc. of np (wire definition)
+ */
+extern void __assign_1mdrwire(register struct net_t *np)
+{
+ register struct xstk_t *xsp;
+ register byte *sbp;
+ int32 sbi;
+ byte *abp;
+ word32 *app, *bpp;
+
+ /* separate routines for rare multi-fi wires with delay */
+ /* here since schedule lhs changed always off */
+ sbp = NULL;
+ /* first most common strength case since know muliple drive */
+ if (np->n_stren)
+  {
+   /* get new value of wire from combination of all drivers */
+   xsp = __stload_mdrwire(np);
+   sbp = (byte *) xsp->ap;
+
+   /* notice any force overrides even tri reg */
+   if (np->frc_assgn_allocated
+    && !__correct_forced_newwireval(np, xsp->ap, xsp->bp))
+    { __pop_xstk(); return; }
+   /* short circuit chg store into strength wire */
+   get_stwire_addr_(abp, np);
+
+   /* no delay form trireg wire, correct for same value cap. strength */
+   if (np->ntyp == N_TRIREG)
+    {
+     for (sbi = 0; sbi < np->nwid; sbi++)
+      {
+       if (sbp[sbi] == ST_HIZ)
+        sbp[sbi] = (byte) ((abp[sbi] & 3) | __cap_to_stren[np->n_capsiz]);
+      }
+    }
+   if (memcmp(abp, sbp, np->nwid) != 0)
+    {
+     memcpy(abp, sbp, np->nwid);
+     __lhs_changed = TRUE;
+    }
+  }
+ else
+  {
+   /* multiple driver non strength no delay case */
+   /* xsp is new wire value */
+   /* load address and store value use current (np lhs) itree place */
+   xsp = __load_mdrwire(np);
+
+   if (np->frc_assgn_allocated
+    && !__correct_forced_newwireval(np, xsp->ap, xsp->bp))
+    { __pop_xstk(); return; }
+
+   /* notice this address because of packing cannot be stored into */
+   __ld_addr(&app, &bpp, np);
+   if (np->nwid <= WBITS)
+    { if (app[0] == xsp->ap[0] && bpp[0] == xsp->bp[0]) goto done; }
+   else
+    {
+     if (cmp_vval_(app, xsp->ap, np->nwid) == 0
+      && cmp_vval_(bpp, xsp->bp, np->nwid) == 0) goto done;
+    }
+   __st_val(np, xsp->ap, xsp->bp); 
+   __lhs_changed = TRUE;
+  }
+
+done:
+ if (__ev_tracing)
+  {
+   char s1[RECLEN];
+
+   if (np->n_stren) strcpy(s1, " strength"); else strcpy(s1, "");
+   __tr_msg(" drivers of%s wire %s combined", s1, np->nsym->synam);
+   if (__lhs_changed)
+    {
+     if (np->n_stren) __st_regab_tostr(__xs, sbp, np->nwid); 
+     else __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE);
+     __tr_msg(" and assigned value %s\n", __xs);
+    }
+   else __tr_msg(" value unchanged\n"); 
+  }
+ if (__lhs_changed) record_nchg_(np);
+ __pop_xstk();
+}
+
+/*
+ * sched assign for one entire wire with multiple fan-in
+ * that has delay and be strength (or not)
+ * but cannot be either inout iconn or inout port wire
+ *
+ * if forced, still must schedule because by assign force may be off later 
+ */
+extern void __sched_1mdrwire(register struct net_t *np)
+{
+ register struct xstk_t *xsp;
+ register byte *sbp;
+
+ /* separate routines for rare multi-fi wires with delay */
+ /* here since schedule lhs changed always off */
+ sbp = NULL;
+ if (np->n_stren)
+  {
+   /* this must run in location of ref. not dest. target */
+   xsp = __stload_mdrwire(np);
+   sbp = (byte *) xsp->ap;
+   /* but rest for xmr must store into dest. target */
+   /* if np is trireg this will handle (decays known from sbp z's) */ 
+   if (np->nu.rngdwir->n_delrep == DT_PTHDST)
+    __pth_stren_schd_allofwire(np, sbp, np->nwid);
+   else __wdel_stren_schd_allofwire(np, sbp, np->nwid);
+  } 
+ else
+  {
+   xsp = __load_mdrwire(np);
+   if (np->nu.rngdwir->n_delrep == DT_PTHDST)
+    __pth_schd_allofwire(np, xsp->ap, xsp->bp, np->nwid);
+   else __wdel_schd_allofwire(np, xsp->ap, xsp->bp, np->nwid);
+  }
+ if (__ev_tracing)
+  {
+   char s1[RECLEN];
+
+   if (np->n_stren) strcpy(s1, " strength"); else strcpy(s1, "");
+   __tr_msg(" drivers of%s wire %s combined", s1, 
+    np->nsym->synam);
+   if (np->n_stren) __st_regab_tostr(__xs, sbp, np->nwid); 
+   else __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE);
+   __tr_msg(" and scheduled to value %s\n", __xs);
+  }
+ __pop_xstk();
+}
+
+/*
+ * ROUTINES TO LOAD AND COMBINE NON STRENGTH MULTI DRIVER WIRE
+ */
+
+/* 
+ * load entire wire with at least some bits of multiple fan-in
+ * onto stack - leaves value on top of stack that caller must pop
+ *
+ * this is for non strength case 
+ * for xmr the drivers are drivers for wire target wire
+ * loads only hard drivers - tran channel code handles tran components
+ */
+extern struct xstk_t *__load_mdrwire(register struct net_t *np)
+{
+ register struct net_pin_t *npp;
+ register struct xstk_t *xsp;
+
+ /* allocate accumulator with undriven bits set to z */
+ push_xstk_(xsp, np->nwid);
+ /* initialize to high z - only possibility in non strength case */
+ zero_allbits_(xsp->ap, np->nwid);
+ one_allbits_(xsp->bp, np->nwid);
+
+ /* must reevaluate every driver since no algorithm for undoing */
+ /* 1 driver to add new one even if could store old value somewhere */
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   /* filter new rooted and up. rel col. forms */ 
+   if (npp->npproctyp == NP_PROC_FILT
+    && npp->npaux->npu.filtitp != __inst_ptr) continue;
+   ldcomb_driver(xsp, np, npp);
+  }
+ return(xsp);
+}
+
+/*
+ * load and combine in to passed z initial acumulator one npp driver
+ *
+ * filters for downward relative xmrs if npp does not match this inst.
+ * know definition itree loc on itstk
+ */
+static void ldcomb_driver(struct xstk_t *acc_xsp, struct net_t *np,
+ register struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp, *tmpxsp;
+ int32 lhswid, nd_itpop;
+ struct npaux_t *npauxp;
+
+ /* --- DBG remove
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg("## loading %s driver of wire %s\n",
+    __to_npptyp(__xs, npp), np->nsym->synam);
+  }
+ --- */
+ if (npp->npproctyp != NP_PROC_INMOD)
+  {
+   /* SJM 04/17/03 - if XMR does not match - do not combine in */
+   if (!__move_to_npprefloc(npp)) return;
+   nd_itpop = TRUE;
+  }
+ else nd_itpop = FALSE;
+
+ /* this puts the driving value (normal rhs with rhs width) on stack */
+ /* notice tran strength only so error if appears here */
+ switch ((byte) npp->npntyp) {
+  case NP_CONTA: xsp = __ld_conta_driver(npp); break;
+  case NP_TFRWARG: xsp = __ld_tfrwarg_driver(npp); break;
+  case NP_VPIPUTV: xsp = __ld_vpiputv_driver(npp); break;
+  case NP_GATE: xsp = __ld_gate_driver(npp); break;
+  /* these are up to highconn output port drivers */
+  case NP_ICONN: xsp = __ld_iconn_up_driver(npp); break;
+  case NP_PB_ICONN: xsp = __ld_pb_iconn_up_driver(npp); break;
+  /* these are down to lowconn input port drivers */
+  case NP_MDPRT: xsp = __ld_modport_down_driver(npp); break;
+  case NP_PB_MDPRT: xsp = __ld_pb_modport_down_driver(npp); break;
+  default: __case_terr(__FILE__, __LINE__); xsp = NULL; 
+ }
+ if (nd_itpop) __pop_itstk();
+
+ /* if lhs of concatenate, must select section out of rhs value */
+ if ((npauxp = npp->npaux) != NULL && npauxp->lcbi1 != -1)
+  {
+   /* loaded value always matches lhs width exactly with z extension */
+   /* if too wide just will not rhs psel from section */
+   lhswid = npauxp->lcbi1 - npauxp->lcbi2 + 1;
+   push_xstk_(tmpxsp, lhswid);
+   __rhspsel(tmpxsp->ap, xsp->ap, npauxp->lcbi2, lhswid); 
+   __rhspsel(tmpxsp->bp, xsp->bp, npauxp->lcbi2, lhswid); 
+
+   __eval_wire(acc_xsp->ap, tmpxsp->ap, np, npp);
+   __pop_xstk();
+  }
+ else __eval_wire(acc_xsp->ap, xsp->ap, np, npp);
+ __pop_xstk();
+}
+
+/*
+ * routine to move from xmr definition location of wire npp driver
+ * or load net on back to reference location so can get gate/conta
+ * driving or conducting value
+ *
+ * push onto itstk and leave on
+ */
+extern int32 __move_to_npprefloc(struct net_pin_t *npp)
+{
+ if (npp->npproctyp == NP_PROC_GREF)
+  {
+   if (!__match_push_targ_to_ref(npp->np_xmrtyp, npp->npaux->npu.npgrp))
+    return(FALSE);
+  }
+ /* all rooted xmrs here */
+ else __push_itstk(npp->npaux->npdownitp);
+ return(TRUE);
+}
+
+/*
+ * load a wire driver for use by count drivers
+ * puts the driving value (normal rhs with rhs width) on stack 
+ *
+ * this is not normal routine - for case where just need one with fi>1 comb.
+ * must set returned NULL to all z's
+ */
+extern struct xstk_t *__ld_wire_driver(register struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ int32 nd_itpop;
+
+ /* for new col or xmr npp forms that need to match inst */
+ /* instance filter already done */  
+ if (npp->npproctyp != NP_PROC_INMOD)
+  {
+   /* SJM 04/17/03 - if XMR does not match - do not combine in */
+   if (!__move_to_npprefloc(npp)) return(NULL);
+   nd_itpop = TRUE;
+  }
+ else nd_itpop = FALSE;
+
+ /* iconn and mod port may return xsp of nil - caller does not pop */
+ switch ((byte) npp->npntyp) {
+  case NP_CONTA: xsp = __ld_conta_driver(npp); break;
+  case NP_TFRWARG: xsp = __ld_tfrwarg_driver(npp); break;
+  case NP_VPIPUTV: xsp = __ld_vpiputv_driver(npp); break;
+  case NP_GATE: xsp = __ld_gate_driver(npp); break;
+  /* these are up to highconn output port drivers */
+  case NP_ICONN: xsp = __ld_iconn_up_driver(npp); break;
+  case NP_PB_ICONN: xsp = __ld_pb_modport_down_driver(npp); break;
+  /* these are down to lowconn input port drivers */
+  case NP_MDPRT: xsp = __ld_modport_down_driver(npp); break;
+  case NP_PB_MDPRT: xsp = __ld_pb_modport_down_driver(npp); break;
+  /* tran strength only */
+  default: __case_terr(__FILE__, __LINE__); return(NULL);
+ }
+ if (nd_itpop) __pop_itstk();
+ return(xsp);
+}
+
+/*
+ * load a continuous assignment driver npp
+ * caller must have moved to right itree loc. for xmr form
+ *
+ * if rhs conta concat causes sep into bits, this is PB conta
+ */
+extern struct xstk_t *__ld_conta_driver(struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register int32 blen;
+ register struct conta_t *cap;
+ int32 orhslen;
+
+ /* SJM 09/18/02 - no separate per bit NP type, check for pb sim on */
+ cap = npp->elnpp.ecap; 
+ if (cap->ca_pb_sim)
+  {
+   cap = &(cap->pbcau.pbcaps[npp->pbi]);
+  }
+
+ blen = cap->lhsx->szu.xclen;
+ /* case 1: fi=1 - for showvars driver is wire section [nbi1:nbi2] itself */
+ /* for fi == 1 and no delay need this for wire display */
+ /* will never get here normally since just assign */
+ /* accessing rhs for consistency check but lhs should always be same */ 
+ if (cap->ca_drv_wp.wp == NULL)
+  {
+   xsp = __eval2_xpr(cap->rhsx);
+   if (blen != xsp->xslen)
+    {
+     orhslen = xsp->xslen;
+
+     /* SJM 09/29/03 - change to handle sign extension and separate types */
+     if (xsp->xslen > blen) __narrow_sizchg(xsp, blen);
+     else if (xsp->xslen < blen)
+      {
+       if (cap->rhsx->has_sign) __sgn_xtnd_widen(xsp, blen);
+       else __sizchg_widen(xsp, blen);
+      }
+
+     /* LOOKATME - only strength continuous assignments widen to z */
+     /* all others widen to 0 unless during initialization when x */
+     /* ??? if (orhslen < xsp->xslen) __fix_widened_tozs(xsp, orhslen); */
+     /* SJM 05/10/04 - widening to x's eliminates need for sign difference */
+     if (__wire_init) __fix_widened_toxs(xsp, orhslen);
+    }
+   return(xsp);
+  }
+ /* case 2: multi-fi or delay - know driver rhs exists */
+ /* but if delay 0 no scheduled (since same) */
+ push_xstk_(xsp, blen);
+ /* know this is exactly lhs width */
+ __ld_perinst_val(xsp->ap, xsp->bp, cap->ca_drv_wp, blen); 
+ return(xsp);
+}
+
+/*
+ * load a tf_ task/func argument rw parameter driver
+ *
+ * caller must have moved to right itree loc. for xmr form
+ * never strength
+ */
+extern struct xstk_t *__ld_tfrwarg_driver(struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register int32 blen;
+ register struct tfrec_t *tfrp;
+ struct tfarg_t *tfap;
+ struct expr_t *xp;
+
+ tfrp = npp->elnpp.etfrp;
+ tfap = &(tfrp->tfargs[npp->obnum]);
+ xp = tfap->arg.axp;
+ blen = xp->szu.xclen;
+ if (tfap->tfdrv_wp.wp == NULL)
+  {
+   xsp = __eval2_xpr(xp);
+   /* here because lhs is width self determing should never differ */
+   /* DBG remove */
+   if (blen != xsp->xslen) __misc_terr(__FILE__, __LINE__);
+   /* -- */ 
+   return(xsp);
+  }
+ /* case 2: multi-fi */
+ push_xstk_(xsp, blen);
+ /* know this is exactly lhs r/w arg width */
+ __ld_perinst_val(xsp->ap, xsp->bp, tfap->tfdrv_wp, blen); 
+ return(xsp);
+}
+
+/*
+ * load a vpi put value wire driver (non strength case)
+ *
+ * always entire wire stored (bits with no drivers will be z)
+ * obnum is index into possibly multiple drivers
+ *
+ * for the net bit case must load entire (allowing sharing of driver storage
+ * for per bit) then select out the needed bit which is later combined in
+ *
+ * if any bits unused z's will never be seen
+ */
+extern struct xstk_t *__ld_vpiputv_driver(struct net_pin_t *npp)
+{
+ register struct net_t *np;
+ register struct xstk_t *xsp;
+ register struct vpi_drv_t *drvp;
+ int32 bi;
+
+ np = npp->elnpp.enp;
+ drvp = np->vpi_ndrvs[npp->obnum];
+ push_xstk_(xsp, np->nwid);
+ __ld_perinst_val(xsp->ap, xsp->bp, drvp->vpi_drvwp, np->nwid); 
+ if (npp->npaux != NULL && (bi = npp->npaux->nbi1) != -1)
+  {
+   word32 av, bv;
+    
+   av = rhsbsel_(xsp->ap, bi);
+   bv = rhsbsel_(xsp->bp, bi);
+   __pop_xstk();
+   push_xstk_(xsp, 1);
+   xsp->ap[0] = av;
+   xsp->bp[0] = bv;
+  }
+ return(xsp);
+}
+
+/*
+ * load a gate driver npp - also for strength case
+ * caller must have moved to right itree loc. for xmr form
+ */
+extern struct xstk_t *__ld_gate_driver(struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register word32 uwrd;
+ int32 has_stren;
+
+ /* load output port - must remove strengths since wire is non strength */
+ push_xstk_(xsp, 1);
+ uwrd = __ld_gate_out(npp->elnpp.egp, &has_stren);
+ /* this must load value and remove strength since drives constant */
+ /* notice this is non stren case - stren passing gates not proc. here */
+ xsp->ap[0] = uwrd & 1L;
+ xsp->bp[0] = (uwrd >> 1) & 1L;
+ return(xsp);
+}
+
+/*
+ * load a gate or udp output - value determined from gate type
+ * and set has_stren and return stren byte value if gate drives st.
+ * some gates always drive varying stren or some have constant non
+ * (st0,st1) strength
+ *
+ * this is passed net pin since need pin number for trans
+ */
+extern word32 __ld_gate_out(register struct gate_t *gp, int32 *has_stren)
+{
+ register word32 wrd, uwrd;
+ register int32 nins;
+ struct udp_t *udpp;
+
+ /* here just using a part of stack */ 
+ *has_stren = FALSE;
+ nins = gp->gpnum - 1;
+ switch ((byte) gp->g_class) {
+  case GC_UDP:
+   udpp = gp->gmsym->el.eudpp;
+   if (!udpp->u_wide)
+    wrd = (((word32) (gp->gstate.hwp[__inum])) >> (2*nins)) & 3L;
+   else wrd = (gp->gstate.wp[2*__inum] >> (2*nins)) & 3L;
+   /* must or in driving strength - if (st0,st1) already removed */
+   /* key here is that know wire driven is n_stren */
+   /* state here does not have strength */
+adjust_stren:
+   if (gp->g_hasst)
+    {
+     /* z value does not have strength */
+     if (wrd != 2) wrd |= (gp->g_stval << 2L);
+     wrd = (word32) __stren_map_tab[wrd];
+     *has_stren = TRUE;
+    }
+   break;
+  case GC_LOGIC:
+   if (nins > 15) wrd = widegate_ld_bit(gp->gstate.wp, nins + 1, nins);
+   else
+    {
+     wrd = get_packintowrd_(gp->gstate, __inum, nins + 1);
+     wrd = ((wrd >> nins) & 1L) | (((wrd >> (2*nins + 1)) & 1L) << 1);
+    }
+   if (gp->g_hasst) goto adjust_stren;
+   break;
+  case GC_BUFIF:
+   uwrd = (word32) gp->gstate.hwp[__inum];
+   wrd = (uwrd >> 4) & 0xff;
+   *has_stren = TRUE;
+  break;
+  case GC_MOS: 
+   /* state here has strength */
+   wrd = (gp->gstate.wp[__inum] >> 16) & 0xffL;
+   *has_stren = TRUE;
+   break;
+  case GC_CMOS:
+   wrd = (gp->gstate.wp[__inum] >> 24) & 0xffL;
+   *has_stren = TRUE;
+   break;
+  default: __case_terr(__FILE__, __LINE__); wrd = 0;
+ }
+ return(wrd);
+}
+
+/*
+ * load a gate or udp input - value determined from gate type
+ * and set has_stren and return stren byte value if input has strength
+ *
+ * pin number pi starts from 1 for first input since output is 0
+ */
+extern word32 __ld_gate_in(struct gate_t *gp, int32 pi, int32 *has_stren)
+{
+ register word32 wrd, uwrd, tmp;
+ register int32 nins;
+ struct udp_t *udpp;
+
+ /* here just using a part of stack */ 
+ *has_stren = FALSE;
+ nins = gp->gpnum - 1;
+ wrd = 0;
+ switch ((byte) gp->g_class) {
+  case GC_UDP:
+   udpp = gp->gmsym->el.eudpp;
+   if (!udpp->u_wide) uwrd = (word32) (gp->gstate.hwp[__inum]);
+   else uwrd = gp->gstate.wp[2*__inum];
+   wrd = (uwrd >> (pi - 1)) & 1;
+   tmp = (uwrd >> (nins + pi - 1)) & 1;
+   wrd |= (tmp << 1);
+   break;
+  case GC_LOGIC:
+   if (nins > 15) wrd = widegate_ld_bit(gp->gstate.wp, nins + 1, pi - 1);
+   else
+    {
+     wrd = get_packintowrd_(gp->gstate, __inum, nins + 1);
+     wrd = ((wrd >> (pi - 1)) & 1L) | (((wrd >> (nins + pi - 1)) & 1L) << 1);
+    }
+   break;
+  case GC_BUFIF:
+   uwrd = (word32) gp->gstate.hwp[__inum];
+   if (pi == 1) wrd = (uwrd & 3);
+   else if (pi == 2) wrd = (uwrd >> 2) & 3;
+   else __case_terr(__FILE__, __LINE__);
+   break;
+  case GC_MOS: 
+   /* state here has strength */
+   uwrd = gp->gstate.wp[__inum];
+   if (pi == 1) { *has_stren = TRUE; wrd = (uwrd & 0xff); }
+   else if (pi == 2) wrd = ((uwrd >> 8) & 3);
+   else __case_terr(__FILE__, __LINE__);
+   break;
+  case GC_CMOS:
+   /* this has one stren data input and 2 control inputs */
+   uwrd = gp->gstate.wp[__inum];
+   if (pi == 1) { *has_stren = TRUE; wrd = uwrd & 0xff; }
+   else if (pi == 2) wrd = (wrd >> 8) & 3;
+   else if (pi == 3) wrd = (wrd >> 16) & 3;
+   else __case_terr(__FILE__, __LINE__);
+   break;
+  default: __case_terr(__FILE__, __LINE__); wrd = 0;
+ }
+ return(wrd);
+}
+
+/* 
+ * load the output bit for wide gate
+ * format for wide gate is a part in one word32 group, b in other  
+ * bit 0 is 0 (inputs [0:nins - 1]), output is bit nins
+ */
+static word32 widegate_ld_bit(word32 *gsp, int32 gwid, int32 biti)
+{
+ int32 wlen;
+ register word32 av, bv, *rap;
+
+ /* rap is start of instance coded vector a b groups */
+ wlen = wlen_(gwid);
+ rap = &(gsp[2*wlen*__inum]);
+ av = rhsbsel_(rap, biti);
+ bv = rhsbsel_(&(rap[wlen]), biti);
+ return(av | (bv << 1));
+}
+
+/*
+ * load a iconn (down module port rhs to up iconn lhs) driver npp
+ * caller must have moved to right itree loc. for xmr form
+ *
+ * driver is down module output port (inout handled in switch channel) 
+ * called from up iconn itree location
+ */
+extern struct xstk_t *__ld_iconn_up_driver(register struct net_pin_t *npp)
+{
+ register struct mod_pin_t *mpp;
+ register struct expr_t *xlhs;
+ register struct itree_t *itp;
+ int32 orhslen;
+ struct xstk_t *xsp;
+ struct mod_t *downmdp;
+
+ itp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+ downmdp = itp->itip->imsym->el.emdp;
+ mpp = &(downmdp->mpins[npp->obnum]);
+ /* notice this can never be xmr */
+ __push_itstk(itp);
+ xsp = __eval2_xpr(mpp->mpref);
+
+ /* lvalue is iconn pos. port number */ 
+ xlhs = itp->itip->ipins[npp->obnum];
+ /* needed iconn connection width may differ from port width */
+ if (xlhs->szu.xclen != xsp->xslen)
+  {
+   orhslen = xsp->xslen;
+
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp->xslen > xlhs->szu.xclen)
+    __narrow_sizchg(xsp, xlhs->szu.xclen);
+   else if (xsp->xslen < xlhs->szu.xclen)
+    {
+     if (mpp->mpref->has_sign) __sgn_xtnd_widen(xsp, xlhs->szu.xclen);
+     else __sizchg_widen(xsp, xlhs->szu.xclen);
+    }
+
+   /* LOOKATME - only strength continuous assignments widen to z */
+   /* all others widen to 0 */
+   /* ??? if (orhslen < xlhs->szu.xclen) __fix_widened_tozs(xsp, orhslen); */
+   /* SJM 05/10/04 - widening to x's eliminates need for sign difference */
+   if (__wire_init) __fix_widened_toxs(xsp, orhslen);
+  }
+ __pop_itstk();
+ return(xsp);
+}
+
+/*
+ * load per bit iconn (down module port rhs to up iconn lhs) driver npp
+ * caller must have moved to right itree loc. if xmr form
+ *
+ * driver is down module output port (inouts handled in tran channels)
+ * called from up iconn itree location
+ */
+extern struct xstk_t *__ld_pb_iconn_up_driver(register struct net_pin_t *npp)
+{
+ register struct mod_pin_t *mpp;
+ register struct itree_t *itp;
+ struct xstk_t *xsp;
+ struct mod_t *downmdp;
+
+ itp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+ downmdp = itp->itip->imsym->el.emdp;
+ mpp = &(downmdp->mpins[npp->obnum]);
+ mpp = &(mpp->pbmpps[npp->pbi]);
+ /* notice this can never be xmr */
+ __push_itstk(itp);
+ xsp = __eval2_xpr(mpp->mpref);
+ __pop_itstk();
+
+ /* lvalue is iconn pos. port number */ 
+ /* since per bit, never need size convert */
+ /* DBG remove --
+ {
+  struct expr_t *xlhs;
+
+  xlhs = itp->itip->pb_ipins_tab[npp->obnum][npp->pbi];
+  if (mpp->mpref->szu.xclen != xsp->xslen) __misc_terr(__FILE__, __LINE__);
+ }
+ --- */
+
+ return(xsp);
+}
+
+/*
+ * load a mod. port (up iconn rhs to down mod port lhs) driver npp
+ *
+ * xmr form impossible here
+ * driver is up iconn rhs connection for input port
+ * called from down module itree location
+ */
+extern struct xstk_t *__ld_modport_down_driver(register struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register struct mod_pin_t *mpp;
+ int32 orhslen;
+ struct itree_t *itp;
+ struct mod_t *downmdp;
+ struct expr_t *xlhs, *up_rhsx;
+
+ itp = __inst_ptr; 
+ /* --- DBG remove
+ if (itp->up_it == NULL) __misc_terr(__FILE__, __LINE__);
+ --- */
+ downmdp = itp->itip->imsym->el.emdp;
+
+ /* instance of lhs has module type that provides port lhs expr. */
+ up_rhsx = itp->itip->ipins[npp->obnum];
+ /* but variables in ndp come from inside up instance's module */
+ __push_itstk(itp->up_it);
+ /* this may access from different itree place if iconn xmr */
+ xsp = __eval2_xpr(up_rhsx);
+
+ /* up iconn width may differ from port width */
+ mpp = &(downmdp->mpins[npp->obnum]);
+ xlhs = mpp->mpref;
+ if (xlhs->szu.xclen != xsp->xslen)
+  {
+   orhslen = xsp->xslen;
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp->xslen > xlhs->szu.xclen)
+    __narrow_sizchg(xsp, xlhs->szu.xclen);
+   else if (xsp->xslen < xlhs->szu.xclen)
+    {
+     if (up_rhsx->has_sign) __sgn_xtnd_widen(xsp, xlhs->szu.xclen);
+     else __sizchg_widen(xsp, xlhs->szu.xclen);
+    }
+
+   /* LOOKATME - only strength continuous assignments widen to z */
+   /* all others widen to 0 */
+   /* ?? if (orhslen < xlhs->szu.xclen) __fix_widened_tozs(xsp, orhslen); */
+   /* SJM 05/10/04 - widening to x's eliminates need for sign difference */
+   if (__wire_init) __fix_widened_toxs(xsp, orhslen);
+  }
+ __pop_itstk();
+ return(xsp); 
+}
+
+/*
+ * load per bit mod. port (up iconn rhs to down mod port lhs) driver npp
+ * for input ports where high conn is concat
+ *
+ * xmr form impossible here
+ * driver of this down iput port is up highconn iconn rhs expr
+ * called from down module itree location
+ */
+extern struct xstk_t *__ld_pb_modport_down_driver(
+ register struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register struct itree_t *itp;
+ struct expr_t *up_rhsx;
+
+ itp = __inst_ptr; 
+ /* --- DBG remove
+ if (itp->up_it == NULL) __misc_terr(__FILE__, __LINE__);
+ --- */
+
+ /* instance of lhs has module type that provides port lhs expr. */
+ up_rhsx = itp->itip->pb_ipins_tab[npp->obnum][npp->pbi];
+ /* but variables in ndp come from inside up instance's module */
+
+ __push_itstk(itp->up_it);
+ /* this may access from different itree place if iconn xmr */
+ /* FIXME ??? - since up rhs decomposes into 1 bit, this can be faster */
+ xsp = __eval2_xpr(up_rhsx);
+ __pop_itstk();
+
+ /* since per bit, never need size convert */
+ /* DBG remove --
+ {
+  struct mod_pin_t *mpp;
+  struct mod_t *downmdp;
+
+  downmdp = itp->itip->imsym->el.emdp;
+  mpp = &(downmdp->mpins[npp->obnum]);
+  mpp = &(mpp->pbmpps[npp->pbi]);
+  if (mpp->mpref->szu.xclen != xsp->xslen) __misc_terr(__FILE__, __LINE__);
+ }
+ --- */
+
+ return(xsp); 
+}
+
+/*
+ * ROUTINES TO COMBINE DRIVERS USING NON-STRENGTH RULES
+ */
+
+/*
+ * apply values from npp npcxsp to a/b accumulator for net pin npp
+ *
+ * this is for non strength case
+ * wire here is used for type - does not need itree place
+ * can pass entire wire since section evaled determined by passed npp
+ *
+ * SJM 11/13/02 - not handling IS -2 per inst param range select right
+ * SJM 11/15/02 - need to pass the a/b word32 ptr so can call from compiled
+ *
+ * FIXME - think this can never happen
+ */
+extern void __eval_wire(word32 *acc_wp, word32 *drv_wp, struct net_t *np,
+ struct net_pin_t *npp)
+{
+ register struct npaux_t *npauxp;
+ word32 resa, resb, *wp;
+ int32 wlen, pselwid, i1, i2;
+ struct xstk_t *tmpxsp;
+
+ wlen = wlen_(np->nwid);
+ /* entire wire */
+ if ((npauxp = npp->npaux) == NULL || npauxp->nbi1 == -1)
+  {
+   if (np->nwid > WBITS)
+    {
+     __eval_wide_wire(acc_wp, &(acc_wp[wlen]), drv_wp, &(drv_wp[wlen]),
+      np->nwid, np->ntyp);
+    } 
+   else __eval_1w_nonstren(acc_wp, &(acc_wp[1]), drv_wp[0], drv_wp[1],
+    np->ntyp);
+   return;
+  }
+
+ /* know that driver is section of lhs wire - i.e. lhs select decl assign */
+ /* know npaux field exists */
+ if (npauxp->nbi1 == -2)
+  {
+   /* SJM 10/12/04 - because contab realloced, must be ndx base of IS */
+   wp = &(__contab[npauxp->nbi2.xvi]);
+   wp = &(wp[2*__inum]);
+   i1 = i2 = (int32) wp[0];
+  }
+ else { i1 = npauxp->nbi1; i2 = npauxp->nbi2.i; }
+ if (i1 == i2) 
+  {
+   resa = rhsbsel_(acc_wp, i1);
+   resb = rhsbsel_(&(acc_wp[wlen]), i1);
+   /* know thing driving wire is 1 bit - will eval. to 1 bit */
+   __eval_1w_nonstren(&resa, &resb, drv_wp[0], drv_wp[1], np->ntyp);
+   /* assign back to bit */
+   __lhsbsel(acc_wp, i1, resa);
+   __lhsbsel(&(acc_wp[wlen]), i1, resb);
+   return;
+  }
+
+ /* part select inefficient but think still better than if done bit by bit */
+ /* part select - net pin range is normalized */
+ pselwid = i1 - i2 + 1; 
+ /* load accumulator region into tmp xsp */ 
+ push_xstk_(tmpxsp, pselwid);
+ __rhspsel(tmpxsp->ap, acc_wp, i2, pselwid); 
+ __rhspsel(tmpxsp->bp, &(acc_wp[wlen]), i2, pselwid); 
+
+ /* eval. - notice if fits in 1 word32 do not need width */
+ if (pselwid > WBITS)
+  __eval_wide_wire(tmpxsp->ap, tmpxsp->bp, drv_wp, &(drv_wp[wlen_(pselwid)]),
+   pselwid, np->ntyp);
+ /*11/21/2002 AIV was nwid for the last arg should be type*/
+ else __eval_1w_nonstren(tmpxsp->ap, tmpxsp->bp, drv_wp[0], drv_wp[1],
+  np->ntyp);
+
+ /* store back into accumulator */
+ __lhspsel(acc_wp, i2, tmpxsp->ap, pselwid); 
+ __lhspsel(&(acc_wp[wlen]), i2, tmpxsp->bp, pselwid); 
+ __pop_xstk();
+}
+
+/*
+ * evaluate stack elements into depending on wire type
+ * any selection handled above here rxsp and xsp1 can be same
+ * since all have same width here, no need to remove unused bits
+ *
+ * SJM 11/15/02 - change so pass a/b word32 ptrs so compiled code can call
+ */
+extern void __eval_wide_wire(word32 *acc_ap, word32 *acc_bp,
+ word32 *drv_ap, word32 *drv_bp, int32 opbits, word32 wtyp)
+{
+ register int32 wi;
+
+ /* DBG remove - only these can have multi-fi and no strength */
+ /* tri0, tri1 and trireg always strength -- 
+ switch ((byte) wtyp) {
+  case N_WIRE: case N_TRI: case N_TRIAND: case N_WA: case N_TRIOR: case N_WO:
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ --- */
+ for (wi = 0; wi < wlen_(opbits); wi++)
+  {
+   __eval_1w_nonstren(&(acc_ap[wi]), &(acc_bp[wi]), drv_ap[wi],
+    drv_bp[wi], wtyp);
+  }
+}
+
+/*
+ * evaluate a 1 word32 normal tri wire
+ * notice res and op can be same object since op by value
+ * for non strength case if one z, use other, if both z leave as z 
+ * since fits in one bit do not need width - high bits will just be 0
+ *
+ * eval is word32 by word32 then after stren competition, used section
+ * extracted with select if needed
+ *
+ * LOOKATME - think this can never happen
+ */
+extern void __eval_1w_nonstren(register word32 *resa, register word32 *resb,
+ register word32 op2a, register word32 op2b, word32 wtyp)
+{
+ register word32 zmask, donemask;
+ register word32 op1a, op1b;
+
+ op1a = resa[0];
+ op1b = resb[0];
+ /* first all bits that are the same - common case */
+ /* notice wand and wor same bits always same */
+ /* unused bits handled here - since will both be 0 */
+ /* mask has 1 if same else 0 */
+ zmask = ~((op1a ^ op2a) | (op1b ^ op2b));
+ resa[0] = op1a & zmask;
+ resb[0] = op1b & zmask;
+ donemask = zmask;
+ if (donemask == __masktab[0]) goto done;
+
+ /* next op1 z bits, use op2 bits */
+ zmask = (op1a ^ op1b) & op1b; 
+ /* if z in op1, value is op2 */
+ resa[0] |= (op2a & zmask);
+ resb[0] |= (op2b & zmask);
+ donemask |= zmask;
+ if (donemask == __masktab[0]) goto done;
+
+ /* next op2 zbits, use op1 bits */
+ zmask = (op2a ^ op2b) & op2b; 
+ /* if z in op2, value is op2 */
+ resa[0] |= op1a & zmask;
+ resb[0] |= op1b & zmask;
+ donemask |= zmask; 
+ if (donemask == __masktab[0]) goto done;
+
+ zmask = ~donemask;
+ /* finally net type determines algorithm - know b bit 0 for these bits */
+ switch ((byte) wtyp) {
+  case N_WIRE: case N_TRI:
+   /* know remaining bits must be x, neither and not the same */
+   resa[0] |= zmask; resb[0] |= zmask;
+   break;
+  case N_TRIAND: case N_WA:
+   /* if either 0, result 0, else x, since 1 1 done */ 
+   resa[0] |= ((op1a | op1b) & (op2a | op2b)) & zmask;
+   resb[0] |= (resa[0] & (op1b | op2b)) & zmask;
+   break;  
+  case N_TRIOR: case N_WO:
+   resb[0]
+    |= ((op2b ^ op1b ^ ((op1a | op1b) & (op2b | (op2a & op1b)))) & zmask);
+   resa[0] |= ((resb[0] | op2a | op1a) & zmask);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+done:
+ /* DBG --- */
+ if (__debug_flg && __ev_tracing) 
+  {
+   char s1[RECLEN];
+
+   __tr_msg(
+    "+> fi>1 nonstren: %s op1a=%lx,op1b=%lx,op2a=%lx,op2b=%lx,resa=%lx,resb=%lx,zmask=%lx\n", 
+    __to_wtnam2(s1, wtyp), op1a, op1b, op2a, op2b, resa[0], resb[0], zmask);
+  }
+ /* --- */
+}
+
+/*
+ * MULTI FAN IN STRENGTH WIRE ASSIGN ROUTINES
+ * ALL STRENGTH ASSIGN THROUGH HERE
+ */
+
+/*
+ * load an entire strength wire value onto top of stack
+ * by evaluating all drivers
+ *
+ * for normal wire itstk must be lhs wire place - for mod. in this is down
+ * (rhs up) and for inst. output this is up (rhs down) 
+ * for xmr wire current itree place is target (define) inst of wire
+ *
+ * the driver evaluation may change to xmr itree place but always restores
+ *
+ * loads only hard drivers - tran channel code handles tran components
+ */
+extern struct xstk_t *__stload_mdrwire(struct net_t *np)
+{
+ register struct net_pin_t *npp;
+ register struct xstk_t *xsp;
+ register byte *sbp;
+
+ /* allocate accumulator - initialize all bits to z in case not driven */
+ /* notice built in 8 bits per byte but also no b part so need half size */
+ xsp = init_stwire_accum(np);
+ sbp = (byte *) xsp->ap;
+
+ /* evaluation of every net and channel driver against current accum. value */
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   /* filter new rooted and up. rel col. forms */ 
+   if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != __inst_ptr)
+    continue;
+
+   ldcomb_stdriver(sbp, np, npp);
+  }
+ return(xsp);
+}
+
+/*
+ * load and combine in to passed z initial acumulator the driver for 1 val
+ * may not add if npp does not apply to this inst. or driver off
+ */
+static void ldcomb_stdriver(register byte *acc_sbp, struct net_t *np,
+ register struct net_pin_t *npp)
+{
+ register byte *sbp2;
+ register int32 i1;
+ register struct xstk_t *xsp;
+ int32 nd_itpop;
+ word32 *wp;
+ byte *sbp;
+ struct npaux_t *npauxp;
+
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg("## loading %s strength driver of wire %s\n",
+    __to_npptyp(__xs, npp), np->nsym->synam);
+  }
+ --- */
+
+ /* trace from target (definition location) back to ref. inst. itree loc */
+ if (npp->npproctyp != NP_PROC_INMOD)
+  {
+   /* SJM 04/17/03 - if XMR does not match - do not combine in */
+   if (!__move_to_npprefloc(npp)) return;
+   nd_itpop = TRUE;
+  }
+ else nd_itpop = FALSE;
+
+ /* load driver onto new top of stack (this always pushes) */
+ /* know rhs driver width will be changed to match lhs width exactly */
+
+ switch ((byte) npp->npntyp) {
+  case NP_CONTA: xsp = ld_stconta_driver(npp); break;
+  case NP_TFRWARG: xsp = __ld_sttfrwarg_driver(npp); break;
+  case NP_VPIPUTV: xsp = ld_stvpiputv_driver(npp); break;
+  case NP_GATE: xsp = ld_stgate_driver(npp); break;
+  /* these are up to highconn strength output port drivers */
+  case NP_ICONN: xsp = ld_sticonn_up_driver(npp); break;
+  case NP_PB_ICONN: xsp = ld_pb_sticonn_up_driver(npp); break;
+  /* these are down to lowconn strength input port drivers */
+  case NP_MDPRT: xsp = ld_stmodport_down_driver(npp); break;
+  case NP_PB_MDPRT: xsp = ld_pb_stmodport_down_driver(npp); break;
+  case NP_PULL: xsp = ld_stpull_driver(npp); break;
+  /* TRAN impossible here */
+  default: __case_terr(__FILE__, __LINE__); xsp = NULL;
+ }
+ if (nd_itpop) __pop_itstk();
+
+ /* SJM 07/08/00 - need high z's if gate driver or narrow conta */
+ /* need at least when stren gate output drives vector */ 
+ /* SJM 11/11/02 - slightly wrong - works because only needed for gate */
+ /* wich never has lhs concat sink */
+
+ /* SJM 05/10/04 - no sign extension because widening to z'x */
+ if (xsp->xslen/4 < np->nwid) __strenwiden_sizchg(xsp, np->nwid);
+
+ sbp = (byte *) xsp->ap;
+
+ /* first if this is lhs concat, must isolate relevant from rhs (sbp2) */
+ /* all indices normalized here to h:0 */
+ if ((npauxp = npp->npaux) != NULL && npauxp->lcbi1 != -1)
+  sbp2 = &(sbp[npauxp->lcbi2]);
+ else sbp2 = sbp;
+ /* first entire wire case */
+ if (npauxp == NULL || npauxp->nbi1 == -1)
+  {
+   eval_stwire(np->ntyp, acc_sbp, np->nwid - 1, 0, sbp2);
+   goto done;
+  }
+ /* IS bit select cases */
+ if (npauxp->nbi1 == -2)
+  {
+   /* SJM 10/12/04 - because contab realloced, must be ndx base of IS */
+   wp = &(__contab[npauxp->nbi2.xvi]);
+   wp = &(wp[2*__inum]);
+   i1 = (int32) wp[0];
+   /* here strength competition of sbp2[0] against sbp[i1] accum. */
+   eval_stwire(np->ntyp, acc_sbp, i1, i1, sbp2);
+   goto done;
+  }
+ /* --- DBG
+ if (__debug_flg) __st_regab_tostr(s1, acc_sbp, np->nwid);
+ --- */ 
+
+ /* finally competition of accum sbp[nbi1:nbi2] to low of sbp2 */
+ eval_stwire(np->ntyp, acc_sbp, npauxp->nbi1, npauxp->nbi2.i, sbp2);
+
+ /* --- DBG 
+ if (__debug_flg)
+  {
+   int32 ti1, ti2, lci1, lci2;
+   char s2[RECLEN], s3[RECLEN];
+
+   if ((npauxp = npp->npaux) != NULL) 
+    {
+     ti1 = npauxp->nbi1;
+     ti2 = npauxp->nbi2.i;
+     lci1 = npauxp->lcbi1;
+     lci2 = npauxp->lcbi2;
+    }
+   else ti1 = ti2 = lci1 = lci2 = -1;
+
+   __dbg_msg(
+    "## stren driver before %s, after %s,\n  value %s, rhs [%d:%d] lhs [%d:%d]\n",
+    s1, __st_regab_tostr(s2, acc_sbp, np->nwid), __st_regab_tostr(s3, sbp2,
+    ti1 - ti2 + 1), lci1, lci2, ti1, ti2);
+  }
+ --- */
+done: 
+ __pop_xstk();
+}
+
+/*
+ * initialize a wire for multi-fi combination (depends on wire type)
+ * this push value on to expr. stack
+ */
+static struct xstk_t *init_stwire_accum(struct net_t *np)
+{
+ register byte *sbp;
+ struct xstk_t *xsp;
+ byte stval;
+
+ push_xstk_(xsp, 4*np->nwid);
+ sbp = (byte *) xsp->ap;
+
+ /* 0,0,2 is high z */
+ /* initialize in case unc., */
+ switch ((byte) np->ntyp) {
+  case N_TRI0: stval = ST_PULL0; goto set_stren;
+  case N_TRI1: stval = ST_PULL1; goto set_stren;
+  case N_SUPPLY0:
+   set_byteval_(sbp, np->nwid, ST_SUPPLY0);
+   return(xsp);
+  case N_SUPPLY1:
+   set_byteval_(sbp, np->nwid, ST_SUPPLY1);
+   return(xsp);
+  default:
+   stval = ST_HIZ;
+set_stren:
+  set_byteval_(sbp, np->nwid, stval);
+ }
+ return(xsp);
+}
+
+/*
+ * load a wire's driven value (maybe not driven z) on to top of stack
+ * routines called from here must do stack pushing themselves
+ *
+ * this is only called by count drivers
+ */
+extern struct xstk_t *__ld_stwire_driver(register struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp; 
+ int32 nd_itpop;
+
+ /* move from target back to itree loc of ref. */ 
+ if (npp->npproctyp != NP_PROC_INMOD)
+  {
+   /* SJM 04/17/03 - if XMR does not match - do not combine in */
+   if (!__move_to_npprefloc(npp)) return(NULL);
+   nd_itpop = TRUE;
+  }
+ else nd_itpop = FALSE;
+
+ /* this puts the driving value (normal rhs with rhs width) on stack */
+ /* notice md port or tran or iconn may return nil, caller does not pop */
+ switch ((byte) npp->npntyp) {
+  case NP_CONTA: xsp = ld_stconta_driver(npp); break;
+  case NP_TFRWARG: xsp = __ld_sttfrwarg_driver(npp); break;
+  case NP_VPIPUTV: xsp = ld_stvpiputv_driver(npp); break;
+  case NP_GATE: xsp = ld_stgate_driver(npp); break;
+  /* these are up to highconn strength output port drivers */
+  case NP_ICONN: xsp = ld_sticonn_up_driver(npp); break;
+  case NP_PB_ICONN: xsp = ld_pb_sticonn_up_driver(npp); break;
+  /* these are down to lowconn strength input port drivers */
+  case NP_MDPRT: xsp = ld_stmodport_down_driver(npp); break;
+  case NP_PB_MDPRT: xsp = ld_pb_stmodport_down_driver(npp); break;
+  default: __case_terr(__FILE__, __LINE__); return(NULL);
+ }
+ if (nd_itpop) __pop_itstk();
+ return(xsp);
+}
+
+/*
+ * load a strength gate driver npp
+ * caller must have moved to right itree loc. for xmr form
+ */
+static struct xstk_t *ld_stgate_driver(struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register byte *sbp;
+ int32 has_stren;
+
+ /* here must add (st0,st0) if no strength */
+ push_xstk_(xsp, 4);
+ sbp = (byte *) xsp->ap;
+ sbp[0] = (byte) __ld_gate_out(npp->elnpp.egp, &has_stren);
+ if (!has_stren && sbp[0] != 2) sbp[0] |= (ST_STRVAL << 2); 
+ return(xsp);
+}
+
+/*
+ * load a strength continuous assignment (not port conta) driver npp
+ * caller must have moved to right itree loc. for xmr form
+ *
+ * for rhs concat separated into per bit, this is PB conta el
+ */
+static struct xstk_t *ld_stconta_driver(struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register int32 blen;
+ register struct conta_t *cap;
+ int32 orhslen;
+ byte *sbp; 
+ struct xstk_t *xsp2;
+
+ /* case 1: fi of 1 - driver if npp range of net itself */
+ /* fi == 1 subcase only for driver (show vars) display */
+ /* SJM 09/18/02 - no separate per bit NP type, checkfor pb sim on */
+ cap = npp->elnpp.ecap;
+ if (cap->ca_pb_sim) cap = &(cap->pbcau.pbcaps[npp->pbi]);
+
+ blen = cap->lhsx->szu.xclen;
+ /* if fi == 1 and no delay, no driver field driver is size changed rhs */
+ /* could access lhs since should be same but this is consistency check */
+ /* notice display whole wire with range value printed if cat */
+ push_xstk_(xsp, 4*blen); 
+ sbp = (byte *) xsp->ap;
+ if (cap->ca_drv_wp.wp == NULL)
+  {
+   xsp2 = __eval2_xpr(cap->rhsx);
+   if (blen != xsp2->xslen)
+    {
+     orhslen = xsp2->xslen;
+
+     /* SJM 09/29/03 - change to handle sign extension and separate types */
+     /* SJM 06/20/05 - rare case but needs signed widen (stren maybe added?) */
+     if (xsp2->xslen > blen) __narrow_sizchg(xsp2, blen);
+     else if (xsp2->xslen < blen)
+      {
+       if (cap->rhsx->has_sign) __sgn_xtnd_widen(xsp2, blen);
+       else __sizchg_widen(xsp2, blen);
+      }
+
+     if (__wire_init) __fix_widened_toxs(xsp2, orhslen);
+    }
+  }
+ else
+  {
+   /* complicated has delay or multi-fi case, driver is saved value */
+   /* know width will always be correct lhs */
+   /* for multi-fi, must save driver else rhs may re-eval too many times */
+   push_xstk_(xsp2, blen);
+   __ld_perinst_val(xsp2->ap, xsp2->bp, cap->ca_drv_wp, blen);
+  }
+ /* add strength */
+ __st_standval(sbp, xsp2, cap->ca_stval);
+ __pop_xstk();
+ return(xsp);
+}
+
+/*
+ * load a tf_ task/func argument rw parameter strength driver
+ * caller must have moved to right itree loc. for xmr form
+ */
+extern struct xstk_t *__ld_sttfrwarg_driver(struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register int32 blen;
+ register struct tfrec_t *tfrp;
+ byte *sbp, *sbp2;
+ struct tfarg_t *tfap;
+ struct expr_t *xp;
+
+ tfrp = npp->elnpp.etfrp;
+ tfap = &(tfrp->tfargs[npp->obnum]);
+ xp = tfap->arg.axp;
+ blen = xp->szu.xclen;
+ /* tf arg fi == 1 case */  
+ if (tfap->tfdrv_wp.wp == NULL)
+  {
+   xsp = __ndst_eval_xpr(xp);
+   /* know this is lhs so width loaded must be arg width */
+   /* DBG remove */
+   if (blen != xsp->xslen/4) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+  }
+ else
+  {
+   /* tf arg r/w lhs wire has multiple drivers */ 
+   push_xstk_(xsp, 4*blen); 
+   sbp = (byte *) xsp->ap;
+   sbp2 = &(tfap->tfdrv_wp.bp[__inum*blen]);
+   memcpy(sbp, sbp2, blen); 
+  }
+ return(xsp);
+}
+
+/*
+ * load a putv added terminal strength driver
+ *
+ * inst. or bit may not have added driver if so will just load z's
+ * z's do not hurt and faster to load entire wire
+ */
+static struct xstk_t *ld_stvpiputv_driver(struct net_pin_t *npp)
+{
+ register struct net_t *np;
+ register struct xstk_t *xsp;
+ register struct vpi_drv_t *drvp;
+ register byte *sbp, *sbp2;
+ int32 bi;
+
+ np = npp->elnpp.enp;
+ drvp = np->vpi_ndrvs[npp->obnum];
+ if (npp->npaux != NULL && (bi = npp->npaux->nbi1) != -1)
+  {
+   push_xstk_(xsp, 4);
+   sbp = (byte *) xsp->ap;
+   sbp[0] = drvp->vpi_drvwp.bp[np->nwid*__inum + bi];
+   return(xsp);
+  }
+ /* SJM 08/11/00 - was wrongly not 4 times width so widen over-wrote hiz */
+ push_xstk_(xsp, 4*np->nwid);
+ sbp = (byte *) xsp->ap;
+ sbp2 = &(drvp->vpi_drvwp.bp[np->nwid*__inum]);
+ memcpy(sbp, sbp2, np->nwid);
+ return(xsp);
+}
+
+/*
+ * load a strength iconn (down module port rhs to up iconn lhs) driver npp
+ * caller must have moved to right itree loc. for xmr form
+ *
+ * called from up iconn itree location
+ */
+static struct xstk_t *ld_sticonn_up_driver(register struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register struct mod_pin_t *mpp;
+ register struct expr_t *xlhs;
+ struct itree_t *itp;
+ struct mod_t *downmdp;
+
+ /* assign from down module port rhs into up iconn lhs expr. */
+ /* driver is down module port - called with itree location of up */
+ itp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+ downmdp = itp->itip->imsym->el.emdp;
+ mpp = &(downmdp->mpins[npp->obnum]);
+ xlhs = itp->itip->ipins[npp->obnum];
+
+ /* this must load preserving strengths - here know mod. port has stren */
+ /* inout port output half driver is always port value */
+ __push_itstk(itp);
+ /* if down rhsx is reg, will add stron strength */ 
+ xsp = __ndst_eval_xpr(mpp->mpref);
+
+ /* only if rhs too narrow, need to add in HIZ and maybe widen alloc area */
+ /* if too wide just ignores high bytes */
+ if (xlhs->szu.xclen > mpp->mpref->szu.xclen)
+  {
+   /* SJM 05/10/04 - no sign extension because widening to z'x */
+   __strenwiden_sizchg(xsp, xlhs->szu.xclen);
+  }
+ __pop_itstk();
+ return(xsp);
+}
+
+/*
+ * load per bit stren iconn (down module port rhs to up iconn lhs) driver
+ *
+ * driver is down module output port
+ * called from up iconn itree location
+ * caller must have moved to right itree loc. for xmr form
+ */
+static struct xstk_t *ld_pb_sticonn_up_driver(register struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register struct mod_pin_t *mpp;
+ struct itree_t *itp;
+ struct mod_t *downmdp;
+
+ /* assign from down module port rhs into up iconn lhs expr. */
+ /* driver is down module port - called with itree location of up */
+ itp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+ downmdp = itp->itip->imsym->el.emdp;
+ mpp = &(downmdp->mpins[npp->obnum]);
+ mpp = &(mpp->pbmpps[npp->pbi]);
+
+ /* this must load preserving strengths - here know mod. port has stren */
+ /* inout port output half driver is always port value */
+ __push_itstk(itp);
+ /* if down rhsx is reg, will add stron strength */ 
+ xsp = __ndst_eval_xpr(mpp->mpref);
+ __pop_itstk();
+
+ /* since per bit, never need size convert */
+ /* DBG remove --
+ {
+  struct expr_t *lhsx;
+
+  lhsx = itp->itip->pb_ipins_tab[npp->obnum][npp->pbi];
+  if (lhsx->szu.xclen != xsp->xslen) __misc_terr(__FILE__, __LINE__);
+ }
+ --- */
+ return(xsp);
+}
+
+/*
+ * load a mod. port (up iconn rhs to down mod port lhs) driver npp
+ *
+ * xmr form impossible here
+ * driver is down module input or inout port (strength model)
+ * called from down module itree location
+ */
+static struct xstk_t *ld_stmodport_down_driver(register struct net_pin_t *npp)
+{
+ register struct mod_pin_t *mpp;
+ register struct itree_t *itp;
+ register struct xstk_t *xsp;
+ struct mod_t *downmdp;
+ struct expr_t *xlhs, *up_rhsx;
+
+ itp = __inst_ptr; 
+ /* --- DBG remove
+ if (itp->up_it == NULL) __misc_terr(__FILE__, __LINE__);
+ --- */
+
+ up_rhsx = itp->itip->ipins[npp->obnum];
+ downmdp = itp->itip->imsym->el.emdp;
+ mpp = &(downmdp->mpins[npp->obnum]);
+ xlhs = mpp->mpref;
+ __push_itstk(itp->up_it);
+ /* if down rhsx is reg, will add strong */ 
+ xsp = __ndst_eval_xpr(up_rhsx);
+ /* only if rhs too narrow, need to add in HIZ and maybe widen alloc area */
+ /* if too wide just ignores high bytes */
+ /* SJM 05/10/04 - no sign extension because widening to z'x */
+ if (xlhs->szu.xclen > up_rhsx->szu.xclen)
+  __strenwiden_sizchg(xsp, xlhs->szu.xclen);
+ __pop_itstk();
+ return(xsp);
+}
+
+/*
+ * load a mod. port (up iconn rhs to down mod port lhs) driver npp
+ *
+ * xmr form impossible here
+ * driver is down module input or inout port (strength model)
+ * called from down module itree location
+ */
+static struct xstk_t *ld_pb_stmodport_down_driver(
+ register struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ register struct itree_t *itp;
+ struct expr_t *up_rhsx;
+
+ itp = __inst_ptr; 
+ /* --- DBG remove
+ if (itp->up_it == NULL) __misc_terr(__FILE__, __LINE__);
+ --- */
+
+ __push_itstk(itp->up_it);
+ up_rhsx = itp->itip->pb_ipins_tab[npp->obnum][npp->pbi];
+ /* if down rhsx is reg, will add strong */ 
+ xsp = __ndst_eval_xpr(up_rhsx);
+
+ /* since per bit never need size change */
+ /* DBG remove --
+ {
+  struct mod_pin_t *mpp;
+  struct mod_t *downmdp;
+
+  downmdp = itp->itip->imsym->el.emdp;
+  mpp = &(downmdp->mpins[npp->obnum]);
+  mpp = &(mpp->pbmpps[npp->pbi]);
+  if (mpp->mpref->szu.xclen > up_rhsx->szu.xclen)
+   __misc_terr(__FILE__, __LINE__);
+ }
+ --- */
+
+ __pop_itstk();
+ return(xsp);
+}
+
+/*
+ * load a strength pull driver (only strength possible) 
+ */
+static struct xstk_t *ld_stpull_driver(struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp;
+ byte *sbp;
+ struct gate_t *gp;
+ struct expr_t *ndp;
+
+ /* get pull out lhs wire or select */
+ gp = npp->elnpp.egp;
+ ndp = gp->gpins[npp->obnum]; 
+ push_xstk_(xsp, 4*ndp->szu.xclen);
+ sbp = (byte *) xsp->ap;
+ set_byteval_(sbp, ndp->szu.xclen, (byte) ((gp->g_stval << 2) | npp->pullval));
+ return(xsp);
+}
+
+/*
+ * STRENGTH EXPRESSION EVALUATION ROUTINES 
+ */
+
+/*
+ * evaluate a rhs expression producing a strength format result
+ * even if needs to add (st0,st1) for non strength expr.
+ * this is equivalent of __eval_xpr when strength required
+ *
+ * pushes and pops temps and leaves result on top of reg stack
+ * caller must pop value from stack
+ * no stack checks underflow checks - maybe would help debugging
+ */
+extern struct xstk_t *__ndst_eval_xpr(struct expr_t *ndp)
+{
+ byte *sbp;
+ struct xstk_t *stxsp;
+
+ /* strength uses only a part of stack register */
+ push_xstk_(stxsp, 4*ndp->szu.xclen);
+ sbp = (byte *) stxsp->ap;
+ ndst_eval2_xpr(sbp, ndp);
+ return(stxsp);
+}
+
+/*
+ * in place evaluate at least top node strength expression
+ * this is for port feed thru assignments that pass strength thru
+ * this does not leave value on top of stack
+ */
+static void ndst_eval2_xpr(register byte *sbp, register struct expr_t *ndp)
+{
+ register byte *bp; 
+ int32 nd_itpop;
+ struct net_t *np;
+ struct expr_t *idndp;
+ struct gref_t *grp;
+ struct xstk_t *xsp;
+
+ /* possible for this to be non stength reg. where strong added */
+ if (!ndp->x_stren)
+  {
+   xsp = __eval2_xpr(ndp);
+   __st_standval(sbp, xsp, ST_STRVAL);
+   __pop_xstk();
+   return;
+  }
+
+ /* in this case, must put value on tos */
+ nd_itpop = FALSE;
+ switch ((byte) ndp->optyp) {
+  case UNCONNPULL:
+   /* connection is unconnected but directives causes unc. to be pulled */
+   /* know width here always exactly port width and stren */
+   set_byteval_(sbp, ndp->szu.xclen, (ndp->unc_pull == UNCPULL0) ? ST_PULL0
+    : ST_PULL1);
+   return;
+  case GLBREF:
+   grp = ndp->ru.grp;
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+   /*FALLTHRU */
+  case ID:
+   np = ndp->lu.sy->el.enp;
+   /* RELEASE remove ---
+   if (!np->n_stren) __misc_terr(__FILE__, __LINE__);
+   --- */
+   /* get strength wire address */
+   get_stwire_addr_(bp, np);
+   memcpy(sbp, bp, ndp->szu.xclen); 
+   break;
+  case LSB:
+   /* can never be array */
+   idndp = ndp->lu.x;
+   np = idndp->lu.sy->el.enp;
+   /* SJM - 03/26/00 - was setting grp to bsel node not lhs id */
+   if (idndp->optyp == GLBREF)
+    { grp = idndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+   access_stbsel(sbp, ndp);
+   break;
+  case PARTSEL:
+   idndp = ndp->lu.x;
+   np = idndp->lu.sy->el.enp;
+   /* SJM - 03/26/00 - was setting grp to bsel node not lhs id */
+   if (idndp->optyp == GLBREF)
+    { grp = idndp->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+   access_stpsel(sbp, ndp);
+   break;
+  case LCB: rhs_stconcat(sbp, ndp); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * access a selected bit to sbp (width 1 for bit)
+ *
+ * this if for cases where accessing strength and know it is needed and
+ * know value has strength
+ */
+static void access_stbsel(register byte *sbp, register struct expr_t *ndp)
+{
+ register int32 biti;
+ register byte *bp;
+ register struct net_t *np;
+
+ np = ndp->lu.x->lu.sy->el.enp;
+ biti = __get_const_bselndx(ndp);
+ /* unknown index is strong x - cannot emit warning happens too often */
+ /* strong x 6,6,3 - 11011011 */
+ if (biti == -1) { *sbp = 0xdb; return; }
+ /* get strength wire address */
+ get_stwire_addr_(bp, np);
+ *sbp = bp[biti]; 
+}
+
+/*
+ * get a bit select index from an expr. node
+ * need to be in correct current itree loc.
+ * only for constant index cases
+ */
+extern int32 __get_const_bselndx(register struct expr_t *ndp)
+{
+ register int32 biti;
+ register word32 *wp;
+
+ /* know will either be constant or expr. here */
+ if (ndp->ru.x->optyp == NUMBER)
+  {
+   wp = &(__contab[ndp->ru.x->ru.xvi]);
+   if (wp[1] != 0) biti = -1; else biti = (int32) wp[0];
+  }
+ else if (ndp->ru.x->optyp == ISNUMBER)
+  {
+   wp = &(__contab[ndp->ru.x->ru.xvi]);
+   wp = &(wp[2*__inum]);
+   if (wp[1] != 0) biti = -1; else biti = (int32) wp[0];
+  }
+ else { __case_terr(__FILE__, __LINE__); biti = -1; }
+ return(biti);
+}
+
+/*
+ * push (access) a selected range into sbp
+ * one bit ok but cannot part select from scalar
+ */
+static void access_stpsel(register byte *sbp, register struct expr_t *ndp)
+{
+ register int32 bi2;
+ register byte *abp;
+ struct expr_t *idndp, *ndx2;
+ struct net_t *np;
+
+ /* know these are both constant nodes, in range, and are h:0 normalized */
+ /* and non IS form */
+ idndp = ndp->lu.x;
+ np = idndp->lu.sy->el.enp;
+ /* notice 2nd range is low */
+ ndx2 = ndp->ru.x->ru.x;
+
+ /* bi2 cannot be -1 (out of range) or will not get here */
+ bi2 = (int32) __contab[ndx2->ru.xvi];
+
+ /* get strength wire address */
+ get_stwire_addr_(abp, np);
+
+ memcpy(sbp, &(abp[bi2]), ndp->szu.xclen);
+}
+
+/*
+ * evaluate a known strength expr node rhs concatenate
+ * key is that { op. node width is same as starting high bit of value
+ *
+ * notice that subexpressions of strength concat can be non strength
+ * strength stored low bit (0) to high bit (n)
+ */
+static void rhs_stconcat(register byte *sbp, struct expr_t *lcbndp)
+{
+ register struct expr_t *ndp; 
+ register byte *sbp2;
+ register int32 i;
+ register int32 bi2;
+ struct expr_t *catndp;
+
+ for (ndp = lcbndp->ru.x; ndp != NULL; ndp = ndp->ru.x)
+  {
+   catndp = ndp->lu.x;
+
+   /* bi2 is low bit, LCB node xclen start high bit, catndp is id/num width */
+   bi2 = ndp->szu.xclen - catndp->szu.xclen;
+   sbp2 = &(sbp[bi2]);
+   /* here know cat width must match rhs width */
+   ndst_eval2_xpr(sbp2, catndp);
+  }
+ if (__debug_flg && __ev_tracing)
+  {
+   __cur_sofs = 0;
+   for (i = lcbndp->szu.xclen - 1; i >= 0; i--)
+    {
+     __adds(__to_vvstnam(__xs, (word32) sbp[i]));
+     addch_('|');
+     __exprline[__cur_sofs] = '\0';
+    }
+   __tr_msg("++ strength concatenate result: %s\n", __exprline);
+   __cur_sofs = 0;
+  }
+}
+
+/*
+ * store a/b value into strength byte array - set value or in new stregth
+ * byte order for strength bytes [h:l] just like word32 bits
+ * notice this needs to be called with blen less that actual stacked blen
+ * also must and off possibly unused parts
+ *
+ * notice z must not have strong added for non strength case
+ * and need to map to right 0 val/1 val strengths
+ */
+extern void __st_standval(register byte *sbp, register struct xstk_t *xsp,
+ byte new_st)
+{
+ register int32 bi, aw, bw;
+
+ /* short circuit for 1 bit case */
+ if (xsp->xslen == 1)
+  {
+   aw = (xsp->ap[0] & 1L) | ((xsp->bp[0] << 1) & 2L);
+   /* if z, no strength */
+   if (aw == 2) sbp[0] = (byte) aw;
+   else
+     {
+      /* SJM 08/07/01 - need to use stren map table so val 0 has 0 stren etc */
+      aw |= (new_st << 2);
+      sbp[0] = __stren_map_tab[aw];
+     }
+   return;
+  }
+
+ for (bi = 0; bi < xsp->xslen; bi++)
+  {
+   aw = rhsbsel_(xsp->ap, bi);
+   bw = rhsbsel_(xsp->bp, bi);
+   aw |= (bw << 1);
+   /* if z no strength */
+   if (aw == 2) sbp[bi] = (byte) aw;
+   else
+    {
+     /* SJM 08/07/01 - need to use stren map table so val 0 has 0 stren etc */
+     aw |= (new_st << 2);
+     /* SJM 08/15/01 - this is vector - from typo was only set 0 */
+     sbp[bi] = __stren_map_tab[aw];
+    }
+  }
+}
+
+/*
+ * pairwise combine driving value into section (or all) of wire
+ * know abi1 (high) and abi2 (low) already corrected for h:0 form
+ */
+static void eval_stwire(word32 wtyp, register byte *accsbp,
+ int32 abi1, int32 abi2, register byte *sbp)
+{
+ register int32 bi, bi2;
+ 
+ for (bi = abi2, bi2 = 0; bi <= abi1; bi++, bi2++)
+  accsbp[bi] = (byte) __comb_1bitsts(wtyp, (word32) accsbp[bi], (word32) sbp[bi2]);
+}
+
+/*
+ * combine into first 2nd 1 bit (byte form) strength value that is not
+ * wired logic
+ *
+ * format [s000,s111,vv] - 3 high bits st 0, 3 middle bits st 1, 2 low val 
+ * convention for non x/z value s0 is highest and s1 is lowest
+ *
+ * routine works for everything except trireg - need special "array" for it
+ * because for tri0/tri1 initialized to state if no drivers
+ * supply0 nets cannot be effected by driver so just init and return above
+ *
+ * notice storing H and L as x value with 1 or other strength 0 - since
+ * no different from real way where strengths same but value z (2)
+ *
+ * LOOKATME - myabe this should use word32 variables
+ */
+extern word32 __comb_1bitsts(word32 wtyp, register word32 acc, register word32 op)
+{
+ word32 str0acc, str1acc, vacc, str0op, str1op, vop;
+ word32 s0hop, s0lop, s1hop, s1lop, s0hacc, s0lacc, s1hacc, s1lacc;
+ word32 s0h, s0l, s1h, s1l, s0, s1;
+
+ /* eliminate either HiZ because HiZ loses to anything */
+ /* notice H and L cannot be eliminated here */
+ if (acc == 2)
+  {
+   /* DBG remove -- */
+   if (__debug_flg && __ev_tracing) { vop = op; goto do_outmsg; }
+   /* --- */
+   return(op);
+  }
+ if (op == 2)
+  {
+   /* DBG remove - */
+   if (__debug_flg && __ev_tracing) { vop = acc; goto do_outmsg; }
+   /* --- */
+   return(acc);
+  }
+
+ /* extract values, */
+ vacc = acc & 3; 
+ vop = op & 3; 
+ str0acc = (acc >> 5) & 7;  
+ str1acc = (acc >> 2) & 7;
+ str0op = (op >> 5) & 7;  
+ str1op = (op >> 2) & 7;
+
+ /* handle special cases that are independent of wired logic type */
+ /* both 1 or both 0 - strength always largest */
+ if ((vacc == 1 && vop == 1) || (vacc == 0 && vop == 0))
+  {
+   /* in case of both strength in 0 or 1 region, 0 st higher than 1 st */ 
+   s0 = (str0acc >= str0op) ? str0acc : str0op;
+   s1 = (str1acc >= str1op) ? str1acc : str1op;
+   goto done;
+  }
+ /* both have fixed strength (<s:s>=? and <t:t>=?) */ 
+ /* notice for H and L, strength never same */
+ if (str0acc == str1acc && str0op == str1op) 
+  {
+   /* case 1: strengths same - may need wired logic compare */
+   s0 = s1 = str0acc;
+   if (str0acc == str0op)
+    {
+     switch ((byte) wtyp) {
+      /* since know differ and know stren same, non wired must be x */
+      case N_TRI: case N_WIRE: case N_TRI0: case N_TRIREG: case N_TRI1:
+      /* SJM 11/16/00 - supplies possible here, but how */
+      case N_SUPPLY0: case N_SUPPLY1:
+       vacc = 3;
+       break;
+      case N_WA: case N_TRIAND: 
+       /* if either 0, result 0, else result X */
+       if (vacc == 0 || vop == 0) vacc = 0; else vacc = 3;
+       break;
+      case N_WO: case N_TRIOR:
+       /* if either 1, result 1, else result X */
+       if (vacc == 1 || vop == 1) vacc = 1; else vacc = 3;
+       break;
+      default: __case_terr(__FILE__, __LINE__);
+     }
+     goto done; 
+    }
+   /* case 1: strengths differ - value of stronger stren wins */
+   if (str0acc <= str0op) { s0 = s1 = str0op; vacc = vop; }
+   goto done;
+  }
+
+ /* separate into low-high for both 0 and 1 for both operands */
+ s0hacc = s0lacc = s1hacc = s1lacc = 0;
+ switch ((byte) vacc) {
+  case 0: s0hacc = str0acc; s0lacc = str1acc; break; 
+  case 1: s1hacc = str0acc; s1lacc = str1acc; break; 
+  case 3: s0hacc = str0acc; s1hacc = str1acc; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ s0hop = s0lop = s1hop = s1lop = 0;
+ switch ((byte) vop) {
+  case 0: s0hop = str0op; s0lop = str1op; break; 
+  case 1: s1hop = str0op; s1lop = str1op; break; 
+  case 3: s0hop = str0op; s1hop = str1op; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ /* tournament 1 - op and acc 0 strengths and 1 strengths */
+ s0h = (s0hacc >= s0hop) ? s0hacc : s0hop; 
+ s0l = (s0lacc >= s0lop) ? s0lacc : s0lop;
+ s1h = (s1hacc >= s1hop) ? s1hacc : s1hop; 
+ s1l = (s1lacc >= s1lop) ? s1lacc : s1lop;
+
+ /* tournament 2 - 0 and 1 strengths */
+ /* if lowest 0 higher than highest 1, remove 1 strengths */
+ if (s0l > s1h) { s0 = s0h; s1 = s0l; vacc = 0; }
+ /* if lowest 1 higher than highest 0, remove 0 strengths */  
+ else if (s1l > s0h) { s0 = s1h; s1 = s1l; vacc = 1; } 
+ /* x - strengths in both regions (fill in smaller gap) */
+ else { s0 = s0h; s1 = s1h; vacc = 3; }
+
+ /* ? believe that for wired logic, if 1 strength range */
+ /* then value is outer range x - no wired logic here - is it true */
+
+done:
+ /* --- DBG remove */
+ if (__debug_flg && __ev_tracing)
+  {
+   char vs1[10], vs2[10], vs3[10];
+
+   vop = (s0 << 5) | (s1 << 2) | vacc;
+do_outmsg:
+   __tr_msg("+> fi>1 strength: %s acc=%s,op=%s,res=%s\n", 
+    __to_wtnam2(__xs, (word32) wtyp), __to_vvstnam(vs1, (word32) acc),   
+    __to_vvstnam(vs2, (word32) op), __to_vvstnam(vs3, (word32) vop));
+   return(vop);
+  }
+/* --- */
+ return((s0 << 5) | (s1 << 2) | vacc); 
+}
+
+/*
+ * EXECUTION OUTPUT ROUTINES INCLUDING SHOWVARS (NEEDS EXEC VALUES)
+ */
+
+/*
+ * build the state of a gate into string
+ * can only be called during exec when current inst. on itstk
+ * caller must do any needed truncating
+ *
+ * handles strengths and bufif and mos style gates
+ * all values extracted from gate state
+ */
+extern char *__gstate_tostr(char *s, struct gate_t *gp, int32 fullpath)
+{
+ int32 srep, pi, nins, sav_sofs, conducting;
+ word32 tmp, tmp2, uwrd, av, bv;
+ i_tev_ndx tevpi;
+ struct xstk_t *xsp;
+ struct udp_t *udpp;
+ char s1[RECLEN], s2[10], s3[10], s4[10];
+
+ sav_sofs = __cur_sofs;
+ __adds(gp->gmsym->synam);
+
+ addch_(' ');
+ if (fullpath)
+  {
+   __disp_itree_path(__inst_ptr, (struct task_t *) NULL);
+   addch_('.');
+  }
+ __adds(gp->gsym->synam);
+ addch_('(');
+
+ nins = gp->gpnum - 1;
+ switch ((byte) gp->g_class) {
+  case GC_LOGIC:
+   if (gp->gpnum > 16) srep = SR_VEC; else srep = SR_PVEC;
+   push_xstk_(xsp, nins + 1);
+   if (srep == SR_VEC)
+    {
+     __ld_gate_wide_val(xsp->ap, xsp->bp, gp->gstate.wp, nins + 1); 
+     /* SJM 11/26/00 - need to select from multi-word32 xsp if wider than 16 */
+     /* put output value in tmp - since low bit is 0 right index is nins **/
+     tmp = rhsbsel_(xsp->ap, nins);
+     tmp2 = rhsbsel_(xsp->bp, nins);
+     tmp |= (tmp2 << 1);
+     __adds(__to_vvnam(s1, tmp));
+     adds_evgate_ins(xsp->ap, xsp->bp, nins);
+    }
+   else
+    {
+     /* extract current output value */
+     uwrd = get_packintowrd_(gp->gstate, __inum, nins + 1);
+     tmp = ((uwrd >> nins) & 1L) | ((uwrd >> (2*nins)) & 2L);
+     __adds(__to_vvnam(s1, tmp));
+     av = uwrd & __masktab[nins + 1];
+     bv = uwrd >> (nins + 1);
+     adds_evgate_ins(&av, &bv, nins);
+    }
+   addch_(')');
+   __pop_xstk();
+   break;
+  case GC_UDP:
+   udpp = gp->gmsym->el.eudpp;
+   nins = udpp->numins;
+   if (udpp->u_wide) uwrd = gp->gstate.wp[2*__inum];
+   else uwrd = (word32) gp->gstate.hwp[__inum];
+   tmp = (uwrd >> (2*nins)) & 3L;
+   /* DBG remove ---
+   if (tmp == 2) __misc_terr(__FILE__, __LINE__);
+   --- */
+   __adds(__to_vvnam(s1, tmp));
+   for (pi = 0; pi < nins; pi++)
+    {
+     __adds(", ");
+     tmp = (uwrd >> (2*pi)) & 3L;
+     /* DBG remove ---
+     if (tmp == 2) __misc_terr(__FILE__, __LINE__);
+     --- */
+     __adds( __to_vvnam(s1, tmp));
+    }
+   addch_(')');
+   /* --- RELEASE REMOVE --- 
+   if (udpp->u_wide)
+    {
+     tmp = gp->gstate.wp[2*__inum + 1];
+     sprintf(s1, "<%lu>", tmp);
+     __adds(s1);
+    }
+   --- */
+   break;
+  case GC_BUFIF:
+   uwrd = (word32) gp->gstate.hwp[__inum];
+   __adds(__to_vvstnam(s1, (uwrd >> 4) & 0xffL));
+   __adds(", ");
+   __adds(__to_vvnam(s2, (uwrd & 0x3L)));
+   __adds(", ");
+   __adds(__to_vvnam(s3, (uwrd >> 2) & 3L));
+   addch_(')');
+   break;
+  case GC_MOS:
+   /* notice packing bit ranges for mos and bufif different */
+   uwrd = gp->gstate.wp[__inum];
+   __adds(__to_vvstnam(s1, ((uwrd >> 16) & 0xffL)));
+   __adds(", ");
+   __adds(__to_vvstnam(s2, (uwrd & 0xffL)));
+   __adds(", ");
+   __adds(__to_vvnam(s3, ((uwrd >> 8) & 0x3L)));
+   addch_(')');
+   break;
+  case GC_CMOS:
+   uwrd = gp->gstate.wp[__inum];
+   __adds(__to_vvstnam(s1, ((uwrd >> 24) & 0xffL)));
+   __adds(", ");
+   __adds(__to_vvstnam(s2, (uwrd & 0xffL)));
+   __adds(", ");
+   __adds(__to_vvnam(s3, ((uwrd >> 8) & 0x3L)));
+   __adds(", ");
+   __adds(__to_vvnam(s4, ((uwrd >> 16) & 0x3L)));
+   addch_(')');
+   break;
+  case GC_TRANIF:
+   /* only called for tranif input gate */
+   conducting = get_tranif_onoff_(gp);
+   if (conducting == 1) __adds("**ON**)");
+   else if (conducting == 0) __adds("**OFF**)");
+   else __adds("**UNKNOWN**)");
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ /* if pending event, write it */
+ if (gp->schd_tevs != NULL
+  && (tevpi = gp->schd_tevs[__inum]) != -1)
+  { __bld_valofsched(s1, &(__tevtab[tevpi])); __adds(s1); }
+ __exprline[__cur_sofs] = '\0';
+ 
+ /* finally truncate suffix */
+ __trunc_cstr(&(__exprline[sav_sofs]), MSGTRUNCLEN, FALSE);
+ strcpy(s, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0'; 
+ return(s);
+}
+
+/*
+ * write gate inputs - only for normal logic gates
+ * notice ports are numbered 0 (output) to gpnum (rightmost input)
+ * but storage is inputs bit 0 to gpnum and output in gpnum (sep. a and b) 
+ */
+static void adds_evgate_ins(word32 *gatap, word32 *gatbp, int32 nins)
+{
+ register int32 bi;
+ word32 tmp, tmp2;
+ char s1[RECLEN];
+ 
+ for (bi = 0; bi < nins; bi++)
+  {
+   tmp = rhsbsel_(gatap, bi);
+   tmp2 = rhsbsel_(gatbp, bi);
+   tmp |= (tmp2 << 1);
+   __adds(", ");
+   __adds(__to_vvnam(s1, tmp));
+  }
+}
+
+/*
+ * SIMULATION TIME DUMP (SHOWVARS) ROUTINES
+ */
+
+/*
+ * dump all variables in a design
+ * this can only be called after prep done
+ */
+extern void __show_allvars(void)
+{
+ register int32 ii;
+ struct itree_t *itp; 
+
+ for (ii = 0; ii < __numtopm; ii++)
+  { itp = __it_roots[ii]; show2_allvars(itp); }
+ __cvsim_msg("\n");
+}
+
+/*
+ * convert global for module whose type corresponds to itree itp
+ */
+static void show2_allvars(struct itree_t *itp)
+{
+ register int32 ii; 
+ register struct net_t *np;
+ struct mod_t *imdp;
+ struct itree_t *itp2;
+
+ imdp = itp->itip->imsym->el.emdp;
+ __cvsim_msg("==> showing all variables in %s type %s.\n",
+  __msg2_blditree(__xs, itp), imdp->msym->synam);
+
+ /* notice using ii as ni here */
+ if (imdp->mnnum != 0)
+  {
+   for (ii = 0, np = &(imdp->mnets[0]); ii < imdp->mnnum; ii++, np++) 
+    { __push_itstk(itp); __emit_1showvar(np, NULL); __pop_itstk(); }
+  }
+ for (ii = 0; ii < imdp->minum; ii++)
+  { itp2 = &(itp->in_its[ii]); show2_allvars(itp2); }
+}
+
+/*
+ * show variable prefix from current itp instance
+ * assumes scope location already emitted
+ *
+ * expects __stlevel to be set to 0 here
+ * this must happen after all processing within one time unit
+ * itree must be on top of stack to call this
+ */
+extern void __emit_1showvar(struct net_t *np, struct gref_t *grp)
+{
+ register int32 i, bi;
+ register struct net_pin_t *npp;
+ int32 arrwid, obwid;
+ i_tev_ndx tevpi, *teviarr;
+ char s1[RECLEN], s2[RECLEN];
+
+ /* for parameters (still in symb. table but replace) no showvars */ 
+ if (np->n_isaparam) return;
+
+ __cur_sofs = 0;
+ /* emit the variable information prefix */
+ __bld_showvars_prefix(s1, np, grp);
+
+ if (np->ntyp == N_EVENT)
+  { __cvsim_msg("%s **event**\n", s1); goto disp_drvs; }
+
+ /* emit the current value of entire variable */
+ /* for array print the first 4 */
+ if (np->n_isarr)
+  {
+   __adds(" [");
+   arrwid = __get_arrwide(np);
+   /* this should be setable in the debugger by the user */
+   if (arrwid > 4) obwid = 4; else obwid = arrwid;
+   for (i = 0; i < obwid; i++)
+    {
+     if (i != 0) __adds(", ");
+     __var_tostr(s2, np, i, i, BBIN);
+     __adds(s2);
+    }
+   if (arrwid > obwid)
+    { sprintf(__xs, ", ... <%d more>", arrwid - obwid); __adds(__xs); }
+   __adds("]");
+  }
+ /* emit variable current value - also handles strength variables */ 
+ /* LOOKATME - this should use base from net or at least give base */
+ else __disp_var(np, -1, -1, BHEX, '?');
+ __cvsim_msg("%s = %s\n", s1, __exprline);
+ __cur_sofs = 0;
+
+ /* if wire has delay or path dest., there may be a scheduled value */
+ if (np->nrngrep == NX_DWIR)
+  {
+   /* access per bit array of possibly scheduled values for wire */
+   /* pointer to array element that is first bit of current inst. */
+   teviarr = &(np->nu.rngdwir->wschd_pbtevs[np->nwid*__inum]);
+   if (np->n_isavec)
+    {
+     __cvsim_msg("   Per bit wire with delay scheduled values:\n"); 
+     for (bi = np->nwid - 1; bi >= 0; bi--)
+      {
+       if ((tevpi = teviarr[bi]) != -1) 
+        {
+         /* form: [i] (schedule %s at %s) */
+         __cvsim_msg("    [%d] %s\n", __unnormalize_ndx(np, bi),
+          __bld_valofsched(s1, &(__tevtab[tevpi])));
+        }
+      }
+    }
+   else if ((tevpi = teviarr[0]) != -1)
+    {
+    __cvsim_msg("scalar wire scheduled %s\n",
+      __bld_valofsched(s1, &(__tevtab[tevpi])));
+    }
+  }
+
+ /* emit drivers - regs never have drivers but can have loads */
+disp_drvs:
+ /* here no filter for rooted xmr since one inst is driver */
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  emit1_driver(np, npp, FALSE);
+ /* emit loads - no inst. filter for rooted xmr npp */
+ for (npp = np->nlds; npp != NULL; npp = npp->npnxt) emit1_load(np, npp);
+ __cur_sofs = 0;
+}
+
+/*
+ * emit a driver string - if nonz_only only emit non floating drivers
+ *
+ * only for use at end of time unit
+ * when called itree location is wire from which npp driver connected to
+ * notice np tchg can never be a driver
+ */
+static void emit1_driver(struct net_t *np, struct net_pin_t *npp,
+ int32 nonz_only)
+{
+ int32 i1, i2, obwid, ri1, ri2, nd_itpop;
+ i_tev_ndx tevpi;
+ word32 wrd;
+ byte *sbp;
+ struct gate_t *gp;
+ struct conta_t *cap, *cap2;
+ struct xstk_t *xsp;
+ struct itree_t *dritp;
+ struct inst_t *ip;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+ struct npaux_t *npauxp;
+ struct tfrec_t *tfrp;
+ struct tfarg_t *tfap;
+ char ndxs[RECLEN], s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ /* think sbp and xsp always set here - lint warning from  if separation */
+ sbp = NULL;
+ xsp = NULL;
+ ri1 = ri2 = -1;
+ /* this is needed to get this instances pattern for IS form */ 
+ 
+ if ((npauxp = npp->npaux) == NULL) i1 = i2 = -1;
+ else __get_cor_range(npauxp->nbi1, npauxp->nbi2, &i1, &i2);
+ /* also need to print lhs select range but leave rhs width as is */
+ /* assignment will widen or truncate if needed but driver is rhs */
+ if (i1 != -1)
+  {
+   /* need range of array for umapping index for message */
+   if (np->n_isarr) __getarr_range(np, &ri1, &ri2, &obwid);
+   else if (np->n_isavec) __getwir_range(np, &ri1, &ri2);
+   else __arg_terr(__FILE__, __LINE__);
+   if (i1 == i2) sprintf(ndxs, " [%d]", __unmap_ndx(i1, ri1, ri2));
+   else sprintf(ndxs, " [%d:%d]", __unmap_ndx(i1, ri1, ri2),
+   __unmap_ndx(i2, ri1, ri2));
+  }
+ else strcpy(ndxs, "");
+
+ /* this traces from target (where var. is) back to ref. itree loc. */
+ if (npp->npproctyp != NP_PROC_INMOD)
+  {
+   /* SJM 04/17/03 - if XMR does not match - do not combine in */
+   if (!__move_to_npprefloc(npp)) return;
+   nd_itpop = TRUE;
+  }
+ else nd_itpop = FALSE;
+
+ /* special handling for getpattern on rhs */
+ if (npp->npntyp == NP_CONTA)
+  { 
+   cap = npp->elnpp.ecap;
+   if (cap->lhsx->getpatlhs)
+    { 
+     __cvsim_msg("%s   driver: continuous assign of $getpattern to %s\n",
+      ndxs, __msgexpr_tostr(__xs, cap->lhsx)); 
+     if (nd_itpop) __pop_itstk();
+     return;
+    }
+  }
+
+ /* here for inouts (up iconn and down mdprt) and trans need driver value */ 
+ /* notice this insure that returned xsp never nil */
+ switch ((byte) npp->npntyp) {
+  case NP_GATE:
+   /* current value of gate is state output - next value is event state */
+   /* if driver (gate output) wide just accesses low bit here */
+   gp = npp->elnpp.egp;
+   /* get driving value */ 
+   if (np->n_stren)
+    {
+     xsp = ld_stgate_driver(npp);
+     sbp = (byte *) xsp->ap;
+     /* high impedance z will always have z value and 0 strengths */
+     if (nonz_only && sbp[0] == 2) break;
+     __to_vvstnam(s1, (word32) sbp[0]);
+    }
+   else
+    {
+     xsp = __ld_gate_driver(npp);
+     wrd = xsp->ap[0] | (xsp->bp[0] << 1);
+     if (nonz_only && wrd == 2L) break;
+     __to_vvnam(s1, wrd);
+    }
+   if (gp->g_class == GC_UDP)
+    sprintf(s2, "%s udp %s", __schop(__xs, gp->gmsym->synam),
+    __schop(__xs2, gp->gsym->synam));
+   else
+    {
+     if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
+      strcpy(s2,  "1 bit continuous assign"); 
+     else sprintf(s2, "%s gate %s", __schop(__xs, gp->gmsym->synam),
+      __schop(__xs2, gp->gsym->synam));
+    }
+   if (gp->schd_tevs != NULL && 
+    (tevpi = gp->schd_tevs[__inum]) != -1)
+    __bld_valofsched(s3, &(__tevtab[tevpi]));
+   else strcpy(s3, ""); 
+
+   __cvsim_msg("%s   driver: %s (port %d) at %s = %s%s\n", ndxs, s2,
+    npp->obnum + 1, __bld_lineloc(__xs, gp->gsym->syfnam_ind,
+    gp->gsym->sylin_cnt), s1, s3);
+   break;
+  case NP_CONTA:
+   /* value for driver that is cont. assign is: 1) ca driver wp per inst if */
+   /* set, 2) ca_rhsval if for 0 delay case, else evaled lhs if fi == 1 */
+   cap = npp->elnpp.ecap;
+   if (cap->ca_pb_sim) cap2 = &(cap->pbcau.pbcaps[npp->pbi]);
+   else cap2 = cap;
+   if (np->n_stren)
+    {
+     xsp = ld_stconta_driver(npp);
+     sbp = (byte *) xsp->ap;  
+     /* this returns NULL on all drivers z if nonz only on */
+     /* SJM 11/13/00 - must use lhs width here in rhs wider truncated */
+     if (stdrive_tostr(s1, sbp, npp, cap2->lhsx->szu.xclen, nonz_only)
+      == NULL) break;
+    }
+   else
+    {
+     xsp = __ld_conta_driver(npp);
+     if (drive_tostr(s1, xsp->ap, xsp->bp, npp, cap2->rhsx->szu.xclen,
+      nonz_only) == NULL) break;
+    }
+   if (cap2->caschd_tevs != NULL && (tevpi = cap2->caschd_tevs[__inum]) != -1)
+     __bld_valofsched(s2, &(__tevtab[tevpi]));
+   else strcpy(s2, ""); 
+
+   if (cap->ca_pb_sim)
+    {
+     __cvsim_msg("%s   driver: continuous assign to %s per bit %d at %s = %s%s\n",
+      ndxs, __msgexpr_tostr(__xs, cap2->lhsx), npp->pbi, 
+      __bld_lineloc(__xs2, cap->casym->syfnam_ind, cap->casym->sylin_cnt),
+      s1, s2);
+    }
+   else
+    {
+     __cvsim_msg("%s   driver: continuous assign to %s at %s = %s%s\n",
+      ndxs, __msgexpr_tostr(__xs, cap->lhsx), 
+      __bld_lineloc(__xs2, cap->casym->syfnam_ind, cap->casym->sylin_cnt),
+      s1, s2);
+    }
+   break;
+  case NP_TFRWARG:
+   tfrp = npp->elnpp.etfrp;
+   tfap = &(tfrp->tfargs[npp->obnum]);
+   if (np->n_stren)
+    {
+     xsp = __ld_sttfrwarg_driver(npp);
+     sbp = (byte *) xsp->ap;  
+     /* this returns NULL on all drivers z if nonz only on */
+     if (stdrive_tostr(s1, sbp, npp, tfap->arg.axp->szu.xclen, nonz_only)
+      == NULL) break;
+    }
+   else
+    {
+     xsp = __ld_tfrwarg_driver(npp);
+     if (drive_tostr(s1, xsp->ap, xsp->bp, npp, tfap->arg.axp->szu.xclen,
+      nonz_only) == NULL) break;
+    }
+   __cvsim_msg("%s   driver: tf_ call of %s arg %s (pos. %d) at %s = %s\n",
+    ndxs, __get_tfcellnam(tfrp), __msgexpr_tostr(__xs, tfap->arg.axp), npp->obnum,
+    __bld_lineloc(__xs2, tfrp->tffnam_ind, tfrp->tflin_cnt), s1);
+   break;
+  case NP_VPIPUTV:
+   /* DBG remove -- */
+   if (npp->elnpp.enp != np) __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   /* if this instance does not have driver, do not emit */
+   if (!__has_vpi_driver(np, npp))
+    {
+     if (nd_itpop) __pop_itstk();
+     return;
+    }
+
+   if (np->n_stren)
+    {
+     xsp = ld_stvpiputv_driver(npp); 
+     sbp = (byte *) xsp->ap;  
+     /* this returns NULL on all drivers z if nonz only on */
+     if (stdrive_tostr(s1, sbp, npp, np->nwid, nonz_only) == NULL) break;
+    }
+   else
+    {
+     xsp = __ld_vpiputv_driver(npp); 
+     if (drive_tostr(s1, xsp->ap, xsp->bp, npp, np->nwid, nonz_only) == NULL)
+      break;
+    }
+   __cvsim_msg("%s   driver: vpi_put_value driving %s %s = %s\n", ndxs,
+    np->nsym->synam, __to_wtnam(__xs2, np), s1);
+   break;
+  case NP_ICONN:
+   /* called from up itree loc. */
+   dritp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   ip = dritp->itip;
+   /* need to make sure driver is loaded - no concept of changing one here */
+   if (np->n_stren)
+    {
+     xsp = ld_sticonn_up_driver(npp);
+     sbp = (byte *) xsp->ap;
+     /* this returns NULL on all drivers z if nonz only on */
+     if (stdrive_tostr(s1, sbp, npp, xsp->xslen/4, nonz_only) == NULL) break;
+    }
+   else
+    {
+     xsp = __ld_iconn_up_driver(npp);
+     if (drive_tostr(s1, xsp->ap, xsp->bp, npp, xsp->xslen, nonz_only)
+      == NULL) break;
+    }
+   __cvsim_msg("%s   driver: instance %s port %s at %s = %s\n",
+    ndxs, ip->isym->synam, np->nsym->synam, __bld_lineloc(__xs,
+    ip->isym->syfnam_ind, ip->isym->sylin_cnt), s1);
+   break;
+  case NP_PB_ICONN:
+   /* called from up itree loc. */
+   dritp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   ip = dritp->itip;
+   /* need to make sure driver is loaded - no concept of changing one here */
+   if (np->n_stren)
+    {
+     xsp = ld_pb_sticonn_up_driver(npp);
+     sbp = (byte *) xsp->ap;
+     /* this returns NULL on all drivers z if nonz only on */
+     if (stdrive_tostr(s1, sbp, npp, xsp->xslen/4, nonz_only) == NULL) break;
+    }
+   else
+    {
+     xsp = __ld_pb_iconn_up_driver(npp);
+     if (drive_tostr(s1, xsp->ap, xsp->bp, npp, xsp->xslen, nonz_only)
+      == NULL) break;
+    }
+   __cvsim_msg("%s   driver: instance %s port %s bit %d at %s = %s\n",
+    ndxs, ip->isym->synam, np->nsym->synam, npp->pbi, __bld_lineloc(__xs,
+    ip->isym->syfnam_ind, ip->isym->sylin_cnt), s1);
+   break;
+  case NP_MDPRT:
+   /* called from down mod port itree loc. */
+   mdp = npp->elnpp.emdp;
+   mpp = &(mdp->mpins[npp->obnum]);
+   if (np->n_stren)
+    {
+     xsp = ld_stmodport_down_driver(npp);
+     sbp = (byte *) xsp->ap;      
+     /* this returns NULL on all drivers z if nonz only on */
+     if (stdrive_tostr(s1, sbp, npp, xsp->xslen/4, nonz_only) == NULL)
+      break;
+    }
+   else
+    {
+     xsp = __ld_modport_down_driver(npp);
+     if (drive_tostr(s1, xsp->ap, xsp->bp, npp, xsp->xslen, nonz_only)
+      == NULL) break;
+    }
+   __cvsim_msg("%s   driver: module %s port %s at %s = %s\n",
+    ndxs, mdp->msym->synam, np->nsym->synam, __bld_lineloc(__xs,
+    mpp->mpfnam_ind, mpp->mplin_cnt), s1);
+   break;
+  case NP_PB_MDPRT:
+   /* called from down mod port itree loc. */
+   mdp = npp->elnpp.emdp;
+   mpp = &(mdp->mpins[npp->obnum]);
+   mpp = &(mpp->pbmpps[npp->pbi]);
+   if (np->n_stren)
+    {
+     xsp = ld_pb_stmodport_down_driver(npp);
+     sbp = (byte *) xsp->ap;      
+     /* this returns NULL on all drivers z if nonz only on */
+     if (stdrive_tostr(s1, sbp, npp, xsp->xslen/4, nonz_only) == NULL)
+      break;
+    }
+   else
+    {
+     xsp = __ld_pb_modport_down_driver(npp);
+     if (drive_tostr(s1, xsp->ap, xsp->bp, npp, xsp->xslen, nonz_only)
+      == NULL) break;
+    }
+   __cvsim_msg("%s   driver: module %s port %s bit %d at %s = %s\n",
+    ndxs, mdp->msym->synam, np->nsym->synam, npp->pbi, __bld_lineloc(__xs,
+    mpp->mpfnam_ind, mpp->mplin_cnt), s1);
+   break;
+  case NP_PULL:
+   /* notice do not need to call ld_pull stren - fixed so get from gstate */
+   gp = npp->elnpp.egp;
+   __cvsim_msg("%s   driver: pull to %s at %s of %s\n",
+    ndxs, __to_vvstnam(s1, (word32) ((gp->g_stval << 2) | npp->pullval)),
+    __bld_lineloc(__xs, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt),
+    __msgexpr_tostr(__xs2, gp->gpins[npp->obnum]));
+   if (nd_itpop) __pop_itstk();
+   return;
+  default: __case_terr(__FILE__, __LINE__); return;
+ }
+ __pop_xstk();
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * convert driver to string with non z only processing
+ * ap and bp rhs conta expr. 
+ * rhs is driver of entire conta which is right unless lhs is
+ * concat, if so lcb i1 used to select part driving this net
+ *
+ * notice truncating this then truncating entire drive message
+ */
+static char *drive_tostr(char *s, word32 *ap, word32 *bp, struct net_pin_t *npp, 
+ int32 rhswid, int32 nonz_only)
+{
+ int32 nd_xpop;
+ int32 wlen, ubits;
+ struct xstk_t *tmpxsp;
+ struct npaux_t *npauxp;
+
+ nd_xpop = FALSE;
+ /* if lhs is concatenate, must isolate part dirving this npp wire section */ 
+ if ((npauxp = npp->npaux) != NULL && npauxp->lcbi1 != -1)
+  {
+   rhswid = npauxp->lcbi1 - npauxp->lcbi2 + 1;
+   if (npauxp->lcbi2 != 0)
+    {
+     push_xstk_(tmpxsp, rhswid);
+     __rhspsel(tmpxsp->ap, ap, npauxp->lcbi2, rhswid); 
+     __rhspsel(tmpxsp->bp, bp, npauxp->lcbi2, rhswid); 
+     nd_xpop = TRUE;
+     ap = tmpxsp->ap; 
+     bp = tmpxsp->bp;
+    }
+   else
+    {
+     /* conta lhs concatenate section starts at low bit */
+     wlen = wlen_(rhswid);
+     if ((ubits = ubits_(rhswid)) != 0)
+      { ap[wlen - 1] &= __masktab[ubits]; bp[wlen - 1] &= __masktab[ubits]; }
+    }
+  }
+ /* notice all z test after selection of actual bits that drive this net */
+ if (nonz_only && !__vval_isallzs(ap, bp, rhswid)) return(FALSE);
+
+ __regab_tostr(s, ap, bp, rhswid, BBIN, FALSE);
+ if (nd_xpop) __pop_xstk();
+ return(s);
+}
+
+/*
+ * copy a strength driving expr. value to a string with select if lhs concat
+ */
+static char *stdrive_tostr(char *s, byte *sbp, struct net_pin_t *npp,
+ int32 rhswid, int32 nonz_only)
+{
+ struct npaux_t *npauxp;
+
+ /* if conta has lhs concat, only emit bits that drive this wire */
+ /* know form here always internal h:l */
+ if ((npauxp = npp->npaux) != NULL && npauxp->lcbi1 != -1)
+  {
+   sbp = &(sbp[npauxp->lcbi2]);
+   rhswid = npauxp->lcbi1 - npauxp->lcbi2 + 1;
+  }
+ /* notice all z test after selection of actual bits that drive this net */
+ if (nonz_only && !__st_vval_isallzs(sbp, rhswid)) return(NULL);
+ __st_regab_tostr(s, sbp, rhswid);
+ return(s);
+}
+
+/*
+ * for message build event value and time in passed string
+ *
+ * notice cannot use __xs strings here since caller will pass as s 
+ * this must only be called if there is a scheduled value
+ */
+extern char *__bld_valofsched(char *s, struct tev_t *tevp)
+{
+ word32 outv;
+ int32 blen;
+ byte *sbp;
+ struct gate_t *gp;
+ struct conta_t *cap;
+ struct tenp_t *tenp;
+ struct xstk_t *xsp, *xsp2;
+ char s1[RECLEN], s2[RECLEN];
+
+ switch ((byte) tevp->tetyp) {
+  case TE_G:
+   gp = tevp->tu.tegp;
+   outv = tevp->outv;
+   /* only input TRANIF separate gate can have delay */
+   if (gp->g_class == GC_TRANIF)
+    {
+     if (gp->gpnum != 1) __case_terr(__FILE__, __LINE__);
+     if (tevp->outv == 0) strcpy(s1, "**OFF**");
+     else if (tevp->outv == 1) strcpy(s1, "**ON**");
+     else strcpy(s1, "**UNKNOWN**");  
+     break;
+    }
+   if (gp->g_hasst) __to_vvstnam(s1, outv);
+   else __to_vvnam(s1, outv);
+   break;
+  case TE_CA: 
+   /* SJM 09/28/02 - this is passed the per bit conta indexed above */
+   cap = tevp->tu.tecap;
+   /* first access the rhs value - that is thing scheduled to change to */
+   /* if rhs changed, previous scheduled replaced with new */
+   /* if delay and multi-fi know schedule will exist */
+   blen = cap->lhsx->szu.xclen;
+   push_xstk_(xsp, blen);
+   /* FIXME - think this should not be called from lhs itree loc. for xmr */
+   __ld_perinst_val(xsp->ap, xsp->bp, cap->schd_drv_wp, blen);
+   if (cap->ca_hasst)
+    {
+     push_xstk_(xsp2, 4*blen);
+     sbp = (byte *) xsp2->ap;
+     /* since rhs eval or saved, never stored with strength - must add here */
+     /* conta may drive strength but any input strengths removed */ 
+     __st_standval(sbp, xsp, cap->ca_stval);
+     __st_regab_tostr(s1, sbp, blen);
+     __pop_xstk();
+    }
+   else __regab_tostr(s1, xsp->ap, xsp->bp, blen, BBIN, FALSE);
+   __pop_xstk();
+   break;
+  case TE_WIRE: case TE_BIDPATH:
+   tenp = tevp->tu.tenp;
+   outv = tevp->outv;
+   if (tenp->tenu.np->n_stren) __to_vvstnam(s1, outv);
+   else __to_vvnam(s1, outv);
+   break;
+  case TE_MIPD_NCHG:
+   strcpy(s1, "*NONE*");
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ sprintf(s, "(scheduled %s at %s)", s1, __to_timstr(s2, &(tevp->etime))); 
+ return(s);
+}
+
+/*
+ * emit the showvars variable information prefix
+ */
+extern char *__bld_showvars_prefix(char *s, struct net_t *np,
+ struct gref_t *grp)
+{
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[RECLEN], s5[RECLEN];
+
+ /* always emit prefix info */
+ if (np->iotyp != NON_IO) sprintf(s1, " %s", __to_ptnam(s3, np->iotyp));
+ else strcpy(s1, "");
+ if (np->n_isavec && np->ntyp != N_INT && np->ntyp != N_TIME
+  && np->ntyp != N_REAL) sprintf(s2, " %s", __to_wrange(s3, np));
+ else strcpy(s2, "");
+ if (np->n_isarr) sprintf(s4, __to_arr_range(s3, np)); else strcpy(s4, "");
+
+ /* if xmr form must emit path given as arg */
+ if (grp == NULL) __schop(s3, np->nsym->synam); else __schop(s3, grp->gnam); 
+ sprintf(s, "%s%s %s%s %s", s1, s2, s3, s4, bld_wire_telltale(s5, np));
+ return(s);
+}
+
+/*
+ * build special flag tell-tale
+ * know NX_CT gone after prep before this called
+ */
+static char *bld_wire_telltale(char *s, struct net_t *np)
+{
+ char s1[RECLEN], s2[RECLEN];
+ struct xstk_t *xsp;
+
+ sprintf(s, "<%s", __to_wtnam(s1, np));
+ if (np->n_signed) strcat(s, " signed");
+ if (np->n_isavec && !np->vec_scalared) strcat(s, " vectored");
+ if (np->nrngrep == NX_DWIR)
+  {
+   if (np->nu.rngdwir->n_delrep == DT_PTHDST) strcat(s, " path dest.");
+   else strcat(s, " delay");
+  }
+ if (np->n_isapthsrc) strcat(s, " path src.");
+ if (np->n_stren) strcat(s, " strength");
+ if (np->n_capsiz != CAP_NONE)
+  {
+   sprintf(s1, " %s capacitor", __to1_stren_nam(s2,
+    __fr_cap_size((int32) np->n_capsiz), 0));
+   strcat(s, s1); 
+  }
+ if (np->n_multfi) strcat(s, " multi-fi");
+ if (np->ntraux != NULL) strcat(s, " in tran channel");
+ if (np->nlds != NULL) strcat(s, " fo"); 
+ if (np->n_hasdvars) strcat(s, " dumpvar"); 
+ /* SJM 07/19/02 - if all off no events */
+ if (np->dcelst != NULL && __cnt_dcelstels(np->dcelst) > 0)
+  strcat(s, " evnts");
+ if (np->n_gone) strcat(s, " disconnected");
+ if (np->frc_assgn_allocated)
+  {
+   if (np->ntyp >= NONWIRE_ST)
+    {
+     if (np->nu2.qcval[2*__inum].qc_active) strcat(s, " forced");
+     else if (np->nu2.qcval[2*__inum + 1].qc_active) strcat(s, " assigned");
+    }
+   else
+    {
+     push_xstk_(xsp, np->nwid);
+     __bld_forcedbits_mask(xsp->ap, np);
+     if (!vval_is0_(xsp->ap, np->nwid)) strcat(s, " forced");
+     __pop_xstk();
+    }
+  }
+ strcat(s, ">");
+ return(s);
+}
+
+/*
+ * emit a load string - static information - should be emitted only once 
+ * load on xmr target 
+ */
+static void emit1_load(struct net_t *np, struct net_pin_t *npp)
+{
+ int32 i1, i2, nd_itpop, obwid, ri1, ri2;
+ struct inst_t *ip;
+ struct itree_t *dritp;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+ struct gate_t *gp;
+ struct conta_t *cap, *cap2;
+ struct tchk_t *tcp;
+ struct spcpth_t *pthp;
+ struct npaux_t *npauxp;
+ char ndxs[RECLEN];
+
+ /* SJM 06/03/02 - only call get cor range if npaux exists */
+ if ((npauxp = npp->npaux) == NULL) i1 = i2 = -1;
+ else __get_cor_range(npauxp->nbi1, npauxp->nbi2, &i1, &i2);
+ if (i1 != -1)
+  {
+   if (np->n_isarr) __getarr_range(np, &ri1, &ri2, &obwid);
+   else if (np->n_isavec) __getwir_range(np, &ri1, &ri2);
+   else { __arg_terr(__FILE__, __LINE__); ri1 = ri2 = 0; }
+
+   if (i1 == i2) sprintf(ndxs, " [%d]", __unmap_ndx(i1, ri1, ri2));
+   else sprintf(ndxs, " [%d:%d]", __unmap_ndx(i1, ri1, ri2),
+   __unmap_ndx(i2, ri1, ri2));
+  }
+ else strcpy(ndxs, "");
+
+ nd_itpop = TRUE;
+ switch ((byte) npp->npproctyp) {
+  case NP_PROC_INMOD: nd_itpop = FALSE; break; 
+  case NP_PROC_GREF:
+   /* SJM 04/17/03 - if not end instance of matching downrel path do not */ 
+   /* print */
+   if (!__match_push_targ_to_ref(npp->np_xmrtyp, npp->npaux->npu.npgrp))
+    return;
+   break;
+  case NP_PROC_FILT:
+   /* all rooted xmrs here */
+   __push_itstk(npp->npaux->npdownitp);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+
+ switch ((byte) npp->npntyp) {
+  case NP_ICONN:
+   dritp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   ip = dritp->itip;
+   mdp = ip->imsym->el.emdp;
+   mpp = &(mdp->mpins[npp->obnum]);
+   __cvsim_msg("%s   load: instance %s port %s at %s\n",
+    ndxs, ip->imsym->el.emdp->msym->synam, __to_mpnam(__xs2, mpp->mpsnam),
+    __bld_lineloc(__xs, ip->isym->syfnam_ind, ip->isym->sylin_cnt));
+   break;
+  case NP_PB_ICONN:
+   /* per bit load same except know scalar/bsel */
+   dritp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   ip = dritp->itip;
+   mdp = ip->imsym->el.emdp;
+   /* notic since not emitting decomposed per bit exprs, need master port */
+   mpp = &(mdp->mpins[npp->obnum]);
+   __cvsim_msg("%s   load: instance %s port %s bit %d at %s\n",
+    ndxs, ip->imsym->el.emdp->msym->synam, __to_mpnam(__xs2, mpp->mpsnam),
+    npp->pbi, __bld_lineloc(__xs, ip->isym->syfnam_ind, ip->isym->sylin_cnt));
+   break;
+  case NP_GATE:
+   /* current value of gate is state output - next value is event state */
+   gp = npp->elnpp.egp;
+   if (gp->g_class == GC_UDP) strcpy(__xs2, "udp");
+   else strcpy(__xs2, "gate");
+   __cvsim_msg("%s   load: %s %s %s (port %d) at %s\n" , ndxs, __xs2,
+    gp->gmsym->synam, gp->gsym->synam, npp->obnum + 1, __bld_lineloc(__xs,
+    gp->gsym->syfnam_ind, gp->gsym->sylin_cnt));
+   break;
+  case NP_TRANIF:
+   /* this is only for third port of tranif */
+   gp = npp->elnpp.egp;
+   __cvsim_msg("%s   load: %s %s (port %d - enable) at %s\n" , ndxs,
+    gp->gmsym->synam, gp->gsym->synam, npp->obnum + 1, __bld_lineloc(__xs,
+    gp->gsym->syfnam_ind, gp->gsym->sylin_cnt));
+   break;
+  case NP_CONTA:
+   cap = npp->elnpp.ecap;
+   if (cap->ca_pb_sim)
+    {
+     cap2 = &(cap->pbcau.pbcaps[npp->pbi]);
+     __cvsim_msg("%s   load: continuous assign to %s per bit %d at %s\n",
+      ndxs, __msgexpr_tostr(__xs, cap2->lhsx), npp->pbi, 
+      __bld_lineloc(__xs2, cap->casym->syfnam_ind, cap->casym->sylin_cnt));
+    }
+   else
+    {
+     __cvsim_msg("%s   load: continuous assign to %s at %s\n", ndxs,
+      __msgexpr_tostr(__xs, cap->lhsx), 
+      __bld_lineloc(__xs2, cap->casym->syfnam_ind, cap->casym->sylin_cnt));
+    } 
+   break;
+  case NP_MDPRT:
+   /* notice mipd module port is only driver not load */
+   mdp = npp->elnpp.emdp;
+   mpp = &(mdp->mpins[npp->obnum]);
+   __cvsim_msg("%s   load: module %s port %s at %s\n", ndxs,
+    mdp->msym->synam, __to_mpnam(__xs2, mpp->mpsnam),
+    __bld_lineloc(__xs, mpp->mpfnam_ind, mpp->mplin_cnt));
+   break;
+  case NP_PB_MDPRT:
+   /* notice mipd module port is only driver not load */
+   mdp = npp->elnpp.emdp;
+   mpp = &(mdp->mpins[npp->obnum]);
+   mpp = &(mpp->pbmpps[npp->pbi]);
+   /* here since not emitting exprs, need master mod port */
+   __cvsim_msg("%s   load: module %s port %s bit %d at %s\n", ndxs,
+    mdp->msym->synam, __to_mpnam(__xs2, mpp->mpsnam), npp->pbi,
+    __bld_lineloc(__xs, mpp->mpfnam_ind, mpp->mplin_cnt));
+   break;
+  case NP_TCHG:
+   switch ((byte) npp->chgsubtyp) {
+    case NPCHG_TCSTART:
+     tcp = npp->elnpp.etchgp->chgu.chgtcp;
+     __cvsim_msg(
+     "%s   change: %s timing check line %s reference change event\n",
+      ndxs, __to_tcnam(__xs, tcp->tchktyp), __bld_lineloc(__xs2,
+      tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt));
+     break; 
+    case NPCHG_TCCHK:
+     tcp = npp->elnpp.echktchgp->startchgp->chgu.chgtcp;
+     __cvsim_msg("%s   change: %s timing check line %s data check event\n",
+      ndxs, __to_tcnam(__xs, tcp->tchktyp),__bld_lineloc(__xs2,
+      tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt));
+     break; 
+    case NPCHG_PTHSRC:
+     pthp = npp->elnpp.etchgp->chgu.chgpthp;
+     __cvsim_msg("%s   change: path source and %s source port bit change\n",
+      ndxs, __bld_lineloc(__xs, pthp->pthsym->syfnam_ind,
+      pthp->pthsym->sylin_cnt));
+     break; 
+    default: __case_terr(__FILE__, __LINE__);
+   }  
+   break;
+  case NP_MIPD_NCHG:
+   /* LOOKATME - should maybe add more details to data structure */
+   __cvsim_msg("%s   load: MIPD delay device\n", ndxs);
+   break;
+  /* pull or tfrw arg can only be driver */
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * ROUTINES TO IMPLEMENT $DUMPVARS SYSTEM TASK
+ */
+
+/*
+ * ROUTINES TO COLLECT DUMPVARS INFO DURING ONE TIME
+ */
+
+/*
+ * execute a dumpvars system task - just collect information - written 
+ * at end of this time unit __dv_calltime triggers end of slot dump var
+ * file output - if off must still always write header 
+ *
+ * this must be called with nil if none or func. call. operator (hd of list) 
+ */
+extern void __exec_dumpvars(struct expr_t *argx)
+{
+ register struct mdvmast_t *mdvp;
+ int32 dpth, anum, ii;
+ word32 tmp;
+ struct mdvmast_t *mdvp2;
+ struct itree_t *itp;
+ struct gref_t *grp;
+ struct sy_t *syp;
+
+ /* multiple dumpvars legal during first time where dumpvars seen */
+ /* dv seen means previous dumpvars call failed */
+ if (__dv_seen)
+  {
+   __sgferr(729,
+    "all $dumpvars calls must be at same time - previously called at %s",
+    __to_timstr(__xs, &__dv_calltime));
+   return;
+  }
+ __dv_calltime = __simtime;
+ 
+ if (argx == NULL)
+  {
+   if (__dv_hdr != NULL)
+    {
+     __sgfwarn(516,
+      "$dumpvars no argument form replaces previous $dumpvars call");
+     /* free master records - wire records will be reused if present */
+     for (mdvp = __dv_hdr; mdvp->mdvnxt != NULL;)
+      {
+       mdvp2 = mdvp->mdvnxt;
+       __my_free((char *) mdvp, sizeof(struct mdvmast_t));
+       mdvp = mdvp2;
+      }
+     __dv_hdr = __dv_end = NULL;
+    }
+   /* mdv_iprt NULL means entire design - common case */
+   mdvp = alloc_mdvmast();
+   __dv_hdr = __dv_end = mdvp;
+   __dv_isall_form = TRUE; 
+   goto done;
+  }
+ /* argument list form, know first is level */
+ if (!__get_eval_word(argx->lu.x, &tmp))
+  {
+   __sgferr(715,
+    "$dumpvar depth argument illegal numeric expression %s - 1 used",
+    __msgexpr_tostr(__xs, argx->lu.x));
+   tmp = 1;
+  }
+ dpth = (int32) tmp; 
+ argx = argx->ru.x;
+ for (anum = 0; argx != NULL; argx = argx->ru.x, anum++)
+  {
+   if (__dv_isall_form)
+    {
+     __sgfwarn(500,
+      "$dumpvars argument %s (number %d) ignored - follows all of design form",
+      __msgexpr_tostr(__xs, argx->lu.x), anum);
+     continue;
+    }
+
+   /* do not need checking since checked at fixup time */
+   if (argx->lu.x->optyp == GLBREF)
+    {
+     grp = argx->lu.x->ru.grp;
+     syp =  grp->targsyp; 
+     mdvp = alloc_mdvmast();
+     /* xmr wire */
+     switch ((byte) syp->sytyp) {
+      case SYM_N:
+       __xmrpush_refgrp_to_targ(grp);
+       mdvp->mdv_itprt = __inst_ptr;
+       __pop_itstk();
+       mdvp->mdv_tskp = grp->targtskp;
+       mdvp->mdv_np = syp->el.enp;
+       break;
+      case SYM_I:
+       __xmrpush_refgrp_to_targ(grp);
+       itp = __inst_ptr;
+       __pop_itstk();
+       goto inst_form;
+      case SYM_M:
+       if ((ii = __ip_indsrch(syp->synam)) == -1)
+        __case_terr(__FILE__, __LINE__);
+       itp = __it_roots[ii];
+inst_form:
+       mdvp->mdv_itprt = itp;
+       mdvp->mdv_levels = dpth;
+       break;
+      default: __case_terr(__FILE__, __LINE__);
+     }
+    }
+   /* know this is local wire form */
+   else
+    {
+     mdvp = alloc_mdvmast();
+     mdvp->mdv_itprt = __inst_ptr;
+     mdvp->mdv_np = argx->lu.x->lu.sy->el.enp;
+     if (__cur_thd == NULL) __misc_terr(__FILE__, __LINE__);  
+
+     /* SJM 02/29/00 - need to also get var's containing func task */
+     /* LOOKATME - shoudl $dumpvars work in functions - think yes? */
+     /* SJM 07/05/01 - if var form dumpvars called not task no no task cntxt */
+     if (__cur_thd->assoc_tsk != NULL) mdvp->mdv_tskp = __getcur_scope_tsk();
+     syp = mdvp->mdv_np->nsym; 
+    }
+   if (__dv_end == NULL) __dv_hdr = mdvp; else __dv_end->mdvnxt = mdvp; 
+   __dv_end = mdvp;
+  }
+done:
+ __slotend_action |= SE_DUMPVARS;
+ __dv_seen = FALSE;
+}
+
+/*
+ * allocate a new dumpvars argument master record
+ * notice these can never be freed - needed for dumping all vars
+ */
+static struct mdvmast_t *alloc_mdvmast(void)
+{
+ struct mdvmast_t *mdvp;
+
+ mdvp = (struct mdvmast_t *) __my_malloc(sizeof(struct mdvmast_t));
+ mdvp->mdv_levels = 0;
+ mdvp->mdv_itprt = NULL;
+ mdvp->mdv_tskp = NULL;
+ mdvp->mdv_np = NULL;
+ mdvp->mdvnxt = NULL;
+ return(mdvp);
+}
+
+/*
+ * ROUTINES TO SETUP DMPV EVENTS AND DUMP DUMPVARS HEADER AT SETUP SLOT END
+ */
+
+/*
+ * setup the dumpvars header
+ * called at end of time when first $dumpvars executed
+ */
+extern void __setup_dmpvars()
+{
+ register struct mdvmast_t *mdvp;
+
+ /* SJM 04/20/00 - in case of reset, must not reallocate */ 
+ /* but possible for after reset to invoke dumpvars but not original */
+ if (__dv_buffer == NULL) __dv_buffer = __my_malloc(DVBUFSIZ);
+ __dv_nxti = 0;
+ /* case 1 - all form - know only one mdv master */
+ if (__dv_isall_form)
+  {
+   if (__dv_hdr == NULL || __dv_hdr->mdvnxt != NULL
+    || __dv_hdr->mdv_itprt != NULL) __misc_terr(__FILE__, __LINE__);
+
+   setup_all_dvars();
+  }
+ else
+  {
+   for (mdvp = __dv_hdr; mdvp != NULL; mdvp = mdvp->mdvnxt)
+    setup_1argdvars(mdvp);
+  }
+ sprintf(__xs2, "$date\n    %s\n$end\n", __pv_timestamp);
+ __adds(__xs2);
+ dv_wr(FALSE);
+
+ sprintf(__xs2, "$version\n    %s%s of %s\n$end\n", __vers, __vers2, __ofdt);
+ __adds(__xs2);
+ dv_wr(FALSE);
+
+ /* need to use actual time scale - is default right */
+ sprintf(__xs2, "$timescale\n    %s\n$end\n", __to_timunitnam(__xs,
+  __des_timeprec));
+ __adds(__xs2);
+ dv_wr(FALSE);
+
+ /* first write the header info for variables form */
+ for (mdvp = __dv_hdr; mdvp != NULL; mdvp = mdvp->mdvnxt)
+  wr_1argdvhdr(mdvp);
+ sprintf(__xs2, "$enddefinitions $end\n");
+ __adds(__xs2);
+ dv_wr(FALSE);
+}
+
+/*
+ * set up dumpvars for all instances of all variables of all modules
+ * called at end of time slot, $dumpvars called in
+ */
+static void setup_all_dvars(void)
+{
+ register int32 ni;
+ register struct net_t *np;
+ register struct mod_t *mdp;
+ register struct task_t *tskp; 
+
+ /* each module */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  { 
+   /* add to each variable */
+   if (mdp->mnnum != 0)
+    {
+     for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+      {
+       if (np->n_isarr) continue;
+       turnon_1net_dmpv(np, (struct itree_t *) NULL, (struct task_t *) NULL,
+        mdp, FALSE);
+      }
+    }
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt) 
+    {
+
+     if (tskp->trnum != 0) 
+      {
+       for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+        {
+         if (np->n_isarr) continue;
+         turnon_1net_dmpv(np, (struct itree_t *) NULL, tskp, mdp, FALSE);
+        }
+      }
+    }
+  }
+}
+
+/*
+ * setup the dumpvar delays controls for 1 master dumpvars arg record
+ *
+ * separate routine writes the headers 
+ * know if dump entire design will not get here
+ */
+static void setup_1argdvars(struct mdvmast_t *mdvp)
+{
+ struct net_t *np;
+ struct mod_t *mdp;
+ struct itree_t *itp;
+
+ /* case 1 simple variable */
+ if ((np = mdvp->mdv_np) != NULL)
+  {
+   /* think flatinum not needed here since 1 itree loc. place */
+   if (np->n_isarr) return;
+
+
+   itp = mdvp->mdv_itprt;
+   mdp = itp->itip->imsym->el.emdp;
+   turnon_1net_dmpv(np, itp, mdvp->mdv_tskp, mdp, FALSE);
+  }
+ else
+  {
+   /* case 2 subtree */
+   /* descend number of levels - 0 is all, 1 is just current */
+   setup_1subtree_allvars(mdvp->mdv_itprt, mdvp->mdv_levels);
+  }
+}
+
+/*
+ * set all varaibles in an instance and under for dumping
+ */
+static void setup_1subtree_allvars(struct itree_t *itp, int32 level)
+{
+ register int32 ii;
+ struct mod_t *mdp; 
+ struct itree_t *down_itp;
+
+ /* must always try to do current */
+ mdp = itp->itip->imsym->el.emdp;
+ /* notice cannot stop if one mod dv setup since level may have been less */
+ /* than current level (i.e. this ones descends more) */ 
+ setup_1installvars(mdp, itp);
+ mdp->mod_hasdvars = TRUE;
+
+ if (level == 1) return; 
+ for (ii = 0; ii < mdp->minum; ii++)
+  { 
+   down_itp = &(itp->in_its[ii]);
+   setup_1subtree_allvars(down_itp, (level != 0) ? level - 1 : 0);
+  }
+}
+
+/*
+ * set up dumpvars for all variables of module at one itree location 
+ */
+static void setup_1installvars(struct mod_t *mdp, struct itree_t *itp)
+{
+ register int32 ni;
+ register struct net_t *np;
+ struct task_t *tskp; 
+
+ /* add to each variable */
+ if (mdp->mnnum != 0)
+  {
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+    {
+     if (np->n_isarr) continue;
+     turnon_1net_dmpv(np, itp, NULL, mdp, FALSE);
+    }
+  }
+ for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt) 
+  {
+
+   if (tskp->trnum != 0)
+    {
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       if (np->n_isarr) continue;
+
+       turnon_1net_dmpv(np, itp, tskp, mdp, FALSE);
+      }
+    } 
+  }
+}
+
+/*
+ * turn on dumpvars for one net - called only at end of time slot
+ *
+ * if already turned on for for other instance, just set bit
+ * if itp nil, set all bits
+ *
+ * only get here if at least one net in mod
+ */
+static void turnon_1net_dmpv(struct net_t *np, struct itree_t *itp,
+ struct task_t *tskp, struct mod_t *mdp, int32 repeat_ok)
+{ 
+ register int32 ni, ii, jj;
+ char s1[RECLEN];
+
+ mdp->mod_hasdvars = TRUE;
+
+ /* assign dump vars id numbers for every inst. even if only some used */
+ /* LOOKATME - could eliminate bad (hard to read) codes, but for now no */
+ /* reason to bother - also problem with continuous regions */
+ /* would need to find good contiguous region */
+ /* __next_dvnum = skip_bad_codes(np, __next_dvnum); */ 
+
+ /* if this net already has some instance dumpvared do not set up codes */
+ if (!np->n_hasdvars)
+  {
+   np->n_hasdvars = TRUE;
+   /* if net has any dumpvars must always use change stores */
+   /* but recording now unrelated to dumpvars */ 
+   /* SJM 03/15/01 - change to fields in net record */
+   /* SJM 12/30/02 - must be turned on by dumpvar in src processing */
+   /* DBG remove -- */
+   if (!np->nchg_nd_chgstore) __misc_terr(__FILE__, __LINE__);
+   /* -- */
+
+   /* if first time any net of module has dumpvars - alloc table */
+   /* for all nets in module */ 
+   if (mdp->mndvcodtab == NULL)
+    {
+     mdp->mndvcodtab = __my_malloc(5*mdp->mtotvarnum*mdp->flatinum);
+     memset(mdp->mndvcodtab, 0, 5*mdp->mtotvarnum*mdp->flatinum);
+    }
+   /* 07/02/00 - SJM - fill module net dvcod table for this net */
+   /* FIXME - think size should be 8 for alignment */
+   ni = np - mdp->mnets;
+   for (ii = 0, jj = 5*ni*mdp->flatinum; ii < mdp->flatinum; ii++, jj += 5)
+    {
+     strcpy(&(mdp->mndvcodtab[jj]), to_dvcode(s1, __next_dvnum + ii));
+    }
+   /* RELEASE remove ---
+   if (__debug_flg)
+    {
+    __dbg_msg("$$$ setting dvnum base %d for net %s (%d) in %s\n",
+     __next_dvnum, np->nsym->synam, ni, mdp->msym->synam); 
+    }
+   --- */
+   __next_dvnum += mdp->flatinum;
+  }
+
+ /* set bits in nets nchg action tab for this dumpvared net and maybe inst */
+ if (itp == NULL)
+  {
+   for (ii = 0; ii < mdp->flatinum; ii++)
+    {
+     /* LOOKATME - here just turn on fact that dumpvared */
+     /* otherwide would start too early - before next time step */
+     /* i.e. mark not changed but set master dmpv copied to now flag */ 
+     np->nchgaction[ii] |=
+      (NCHG_DMPVARED | NCHG_DMPVARNOW | NCHG_DMPVNOTCHGED);
+    }
+   return;
+  }
+ if (!repeat_ok && ((np->nchgaction[itp->itinum] & NCHG_DMPVARED) != 0))
+  {
+   __sgfinform(435, "variable %s in instance %s repeated in $dumpvars list",
+    np->nsym->synam, __msg_blditree(__xs, itp, tskp));
+  }
+ np->nchgaction[itp->itinum]
+  |= (NCHG_DMPVARED | NCHG_DMPVARNOW | NCHG_DMPVNOTCHGED);
+}
+
+/*
+ * convert a number to a special character base 93 char number
+ * this should be moved to v_cnv
+ * notice requires ascii
+ * LOOKATME - code ! is possible - is it legal?
+ */
+static char *to_dvcode(register char *s, register int32 vnum)
+{
+ s[4] = '\0';
+ s[3] = '!' + vnum % 93;
+ if (vnum < 93) return(&(s[3]));
+ vnum /= 93;
+ s[2] = '!' + vnum % 93;
+ if (vnum < 93) return(&(s[2]));
+ vnum /= 93;
+ s[1] = '!' + vnum % 93;
+ if (vnum < 93) return(&(s[1]));
+ vnum /= 93;
+ s[0] = '!' + vnum;
+ return(s);
+}
+
+/*
+ * routine which skip number that are illegal codes
+ * for now # (must be illegal) plus one digit and one letter x, z, X, Z 
+ */
+/* --
+static int32 skip_bad_codes(struct net_t *np, int32 nextcod)
+{
+ register char *cp;
+ int32 fr, to, bad;
+ char s1[RECLEN];
+
+ if (nextcod > 93) return(nextcod);
+
+ -- notice this list must be in numerical order --
+ strcpy(s1, "#0123456789XZxz");
+ fr = nextcod;
+ to = nextcod + np->nwid - 1; 
+
+ for (cp = s1; *cp != '\0'; cp++) 
+  {
+   bad = *cp - '!';
+   if (fr <= bad && bad <= to)
+    {
+     if (isdigit(*cp)) nextcod = '9' - '!' + 1;
+     else nextcod = bad + 1;
+     fr = nextcod;
+     to = nextcod + np->nwid - 1;
+    }
+  }
+ return(nextcod);
+}
+--- */
+
+/*
+ * ROUTINES TO WRITE THE DUMPVAR HEADER REFERENCE INFO
+ */
+
+/*
+ * write the header for 1 master dumpvars arg record
+ * done at end of setup time slot 
+ */
+static void wr_1argdvhdr(struct mdvmast_t *mdvp)
+{
+ register int32 ii;
+ int32 ni, jj;
+ struct itree_t *itp, *itp2;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+ struct net_t *np;
+ char *dvcodp;
+
+ /* case 0: all of design */
+ if (mdvp->mdv_itprt == NULL)
+  {
+   for (ii = 0; ii < __numtopm; ii++)
+    {
+     itp = __it_roots[ii];
+     sprintf(__xs2, "$scope module %s $end\n", itp->itip->isym->synam); 
+     __adds(__xs2);
+     dv_wr(FALSE);
+
+     wr_1subtree_allvars(itp, 0);
+     sprintf(__xs2, "$upscope $end\n");
+     __adds(__xs2);
+     dv_wr(FALSE);
+    }
+   return;
+  }
+
+ /* case 1 simple variable */
+ if ((np = mdvp->mdv_np) != NULL)
+  {
+   /* DBG remove --- */
+   if (np->n_isarr) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   
+   /* no need to check for array 1 wire form - illegal if array */
+   wr_fromtop_iscopeto(mdvp->mdv_itprt);
+   itp2 = mdvp->mdv_itprt;
+   mdp = itp2->itip->imsym->el.emdp;
+   if ((tskp = mdvp->mdv_tskp) != NULL)
+    {
+     wr_tskscopeto(tskp->tsksymtab);
+     ni = np - mdp->mnets;
+     /* 07/02/00 - SJM - find right dvcod table code */
+     jj = 5*ni*mdp->flatinum + itp2->itinum; 
+     dvcodp = &(mdp->mndvcodtab[jj]);
+    }  
+   else  
+    {
+     /* 07/02/00 - SJM - find right dvcod table code */
+     ni = np - mdp->mnets;
+     jj = 5*(ni*mdp->flatinum + itp2->itinum); 
+     dvcodp = &(mdp->mndvcodtab[jj]);
+    }
+   wr_1vectored_dvdef(np, dvcodp, itp2);
+   if (tskp != NULL) wr_tskscopeback(mdvp->mdv_tskp->tsksymtab);
+   wr_totop_iscopeback(mdvp->mdv_itprt);
+  }
+ else
+  {
+   /* case 2 inst. scope */
+   /* this handles all its own scope movements */
+   /* case inst. with some levels underneath */
+   /* descend number of levels - 0 is all, 1 is just current */
+   wr_fromtop_iscopeto(mdvp->mdv_itprt);
+   wr_1subtree_allvars(mdvp->mdv_itprt, mdvp->mdv_levels);
+   wr_totop_iscopeback(mdvp->mdv_itprt);
+
+   /* AIV 01/28/05 - removed an extra upscope printing */ 
+  }
+}
+
+/*
+ * write the variables for all instances in and under 1 itree module loc.
+ * descends level numbers 0 - all
+ * when called expects scope to be moved upon return leaves scope at itp
+ */
+static void wr_1subtree_allvars(struct itree_t *itp, int32 level)
+{
+ register int32 ii;
+ struct mod_t *imdp;
+ struct symtab_t *sytp;
+ struct itree_t *down_itp;
+
+ wr_1inst_dvhdrs(itp);
+ imdp = itp->itip->imsym->el.emdp;
+ /* when done scope left at instance same as called */
+ if ((sytp = imdp->msymtab->sytofs) != NULL) wr_tasks_dvhdrs(itp, sytp);
+ if (level != 1)
+  { 
+   for (ii = 0; ii < imdp->minum; ii++)
+    { 
+     down_itp = &(itp->in_its[ii]);
+     sprintf(__xs2, "$scope module %s $end\n", down_itp->itip->isym->synam); 
+     __adds(__xs2);
+     dv_wr(FALSE);
+
+     wr_1subtree_allvars(down_itp, (level != 0) ? level - 1 : 0);
+     sprintf(__xs2, "$upscope $end\n");
+     __adds(__xs2);
+     dv_wr(FALSE);
+    }
+  }
+}
+
+/*
+ * write the dv header variables in one module
+ * scope set and does not descend or change scope
+ */
+static void wr_1inst_dvhdrs(struct itree_t *itp)
+{
+ register int32 ni;
+ register struct net_t *np;
+ int32 jj;
+ struct mod_t *mdp;
+ struct itree_t *itp2;
+ char *dvcodp;
+
+ mdp = itp->itip->imsym->el.emdp;
+ /* write all wires */
+ if (mdp->mnnum == 0) return;
+ for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+  {
+   if (np->n_isarr) continue;
+
+
+   /* SJM - 07/02/00 - now dvcods pre-built as strings */
+   jj = 5*(ni*mdp->flatinum + itp->itinum); 
+   dvcodp = &(mdp->mndvcodtab[jj]);
+   itp2 = itp;   
+   wr_1vectored_dvdef(np, dvcodp, itp2);
+  } 
+}
+
+/*
+ * dump the header info for task and all contained tasks
+ * handles scoping but assume all dmpvar dces already set up
+ */
+static void wr_tasks_dvhdrs(struct itree_t *itp,
+ register struct symtab_t *sytp)
+{
+ register int32 ni, ni2;
+ register struct net_t *np;
+ int32 jj;
+ struct task_t *tskp;
+ struct mod_t *mdp;
+ char *dvcodp;
+
+ mdp = itp->itip->imsym->el.emdp;
+ /* write all contained tasks/funcs/lbs - through symbol table list */
+ for (; sytp != NULL; sytp = sytp->sytsib)
+  {
+   tskp = sytp->sypofsyt->el.etskp;
+   /* notice must set up scope even if no variables */
+   /* if (tskp->tsk_regs == NULL) continue; */
+   sprintf(__xs2, "$scope %s %s $end\n", to_dvtsktyp(__xs, tskp->tsktyp),
+    tskp->tsksyp->synam);
+   __adds(__xs2);
+   dv_wr(FALSE);
+
+   if (tskp->trnum != 0)
+    {
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       if (np->n_isarr) continue;
+       /* 04/15/00 - net index for dmpvars is from mod first net */
+       ni2 = np - mdp->mnets;
+
+       /* 07/02/00 - SJM - dvcod values not pre-built */
+       jj = 5*(ni2*mdp->flatinum + itp->itinum); 
+       dvcodp = &(mdp->mndvcodtab[jj]);
+       wr_1vectored_dvdef(np, dvcodp, itp);
+      } 
+    }
+   if (sytp->sytofs != NULL) wr_tasks_dvhdrs(itp, sytp->sytofs);
+   sprintf(__xs2, "$upscope $end\n");
+   __adds(__xs2);
+   dv_wr(FALSE);
+  } 
+}
+
+/*
+ * build string name of task for $dumpvars - all blocks labeled
+ */
+static char *to_dvtsktyp(char *s, word32 tskt) 
+{
+ switch ((byte) tskt) {
+  case Begin: strcpy(s, "begin"); break;
+  case FORK: strcpy(s, "fork"); break;
+  case FUNCTION: strcpy(s, "function"); break;
+  case TASK: strcpy(s, "task"); break;
+ }
+ return(s);
+}
+
+/*
+ * write commands to scope to an itree place
+ */
+static void wr_fromtop_iscopeto(struct itree_t *itp)
+{
+ register int32 i;
+ register struct itree_t *witp;
+ int32 frtoplevs;
+
+ for (witp = itp, frtoplevs = 1;; frtoplevs++)
+  { 
+   __push_itstk(witp);
+   if ((witp = witp->up_it) == NULL) break;
+  }
+ for (i = 1; i <= frtoplevs; i++) 
+  {
+   sprintf(__xs2, "$scope module %s $end\n", __inst_ptr->itip->isym->synam); 
+   __adds(__xs2);
+   dv_wr(FALSE);
+
+   __pop_itstk();
+  }
+}
+
+static void wr_totop_iscopeback(struct itree_t *itp)
+{
+ register struct itree_t *witp;
+
+ for (witp = itp;;)
+  {
+   sprintf(__xs2, "$upscope $end\n");
+   __adds(__xs2);
+   dv_wr(FALSE);
+
+   if ((witp = witp->up_it) == NULL) break;  
+  }
+}
+
+/*
+ * write the scope into the task/lb/func - must pass tasks symbol
+ */
+static void wr_tskscopeto(struct symtab_t *sytp)
+{
+ struct task_t *tskp;
+
+ if (sytp->sytpar != NULL && sytp->sytpar->sypofsyt->sytyp != SYM_M)
+  wr_tskscopeto(sytp->sytpar);
+ tskp = sytp->sypofsyt->el.etskp;
+ sprintf(__xs2, "$scope %s %s $end\n", to_dvtsktyp(__xs, tskp->tsktyp),
+  tskp->tsksyp->synam);
+ __adds(__xs2);
+ dv_wr(FALSE);
+}
+
+static void wr_tskscopeback(struct symtab_t *sytp)
+{
+ struct symtab_t *wsytp;
+
+ for (wsytp = sytp->sytpar;;)
+  {
+   sprintf(__xs2, "$upscope $end\n");
+   __adds(__xs2);
+   dv_wr(FALSE);
+
+   /* keep going until back to containing module scope */
+   if (wsytp->sypofsyt->sytyp == SYM_M) break;
+  }
+}
+
+/*
+ * write dv define for 1 scalar or vectored wire 
+ * never call for array
+ */
+static void wr_1vectored_dvdef(struct net_t *np, char *dvcod,
+ struct itree_t *itp)
+{
+ int32 r1, r2;
+ char s1[15];
+
+ if ((np->nchgaction[itp->itinum] & NCHG_DMPVARED) == 0) return;
+
+ if (np->n_isavec || np->ntyp == N_REAL)
+  {
+   __getwir_range(np, &r1, &r2);
+   /* this must be wire name */ 
+   sprintf(__xs2, "$var %s ", __to_wtnam2(s1, np->ntyp)); 
+   __adds(__xs2);
+   dv_wr(FALSE);
+
+   /* SJM 06/18/01 - no range for dumpvar of reals and width 64 */
+   if (np->ntyp == N_REAL)
+    {
+     sprintf(__xs2, "     64 %-4s %s $end\n", dvcod, np->nsym->synam);
+    }
+   else
+    {
+     /* SJM 09/13/99 - range but be MSB to LSB - was internal h:0 */
+     sprintf(__xs2, "%7d %-4s %s [%d:%d] $end\n", np->nwid, dvcod,
+      np->nsym->synam, r1, r2);
+    }
+   __adds(__xs2);
+   dv_wr(FALSE);
+  }
+ else
+  {
+   sprintf(__xs2, "$var %s ", __to_wtnam2(s1, np->ntyp)); 
+   __adds(__xs2);
+   dv_wr(FALSE);
+   sprintf(__xs2, "      1 %-4s %s $end\n", dvcod, np->nsym->synam);
+   __adds(__xs2);
+   dv_wr(FALSE);
+  }
+}
+
+/* 07/02/00 - now only one dvcod for each net - never scalared */
+
+/*
+ * ROUTINES TO TURN ON/OFF DUMPVARS RECORDING
+ */
+
+/*
+ * turn off all dumpvars - uses being dumpvared template
+ */
+extern void __turnoff_all_dumpvars(void)
+{
+ register int32 ii;
+ register struct net_t *np;
+ register struct task_t *tskp;
+ register struct mod_t *mdp;
+ int32 ni;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (!mdp->mod_hasdvars) continue;
+
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+    {
+     if (!np->n_hasdvars) continue;
+
+     for (ii = 0; ii < mdp->flatinum; ii++)
+      {
+       /* if not dumpvared nothing to do */
+       if ((np->nchgaction[ii] & NCHG_DMPVARED) == 0) continue;
+
+       /* dumpv now off and not changed on (even if changed in slot) */
+       np->nchgaction[ii] &= ~NCHG_DMPVARNOW;
+       np->nchgaction[ii] |= NCHG_DMPVNOTCHGED;
+      }
+    }
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       if (!np->n_hasdvars) continue;
+
+       for (ii = 0; ii < mdp->flatinum; ii++)
+        {
+         if ((np->nchgaction[ii] & NCHG_DMPVARED) == 0) continue;
+
+         /* dumpv now off and not changed on (even if changed in slot) */
+         np->nchgaction[ii] &= ~NCHG_DMPVARNOW;
+         np->nchgaction[ii] |= NCHG_DMPVNOTCHGED;
+        }
+      }
+    }
+  }
+}
+
+/*
+ * turn on all dumpvars (from previous turn-off) 
+ */
+extern void __turnon_all_dumpvars(void)
+{
+ register int32 ii;
+ register struct net_t *np;
+ register struct task_t *tskp;
+ register struct mod_t *mdp;
+ int32 ni;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (!mdp->mod_hasdvars) continue;
+
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+    {
+     if (!np->n_hasdvars) continue;
+
+     for (ii = 0; ii < mdp->flatinum; ii++)
+      {
+       /* if not dumpvared nothing to do */
+       if ((np->nchgaction[ii] & NCHG_DMPVARED) == 0) continue;
+
+       /* dumpv now off and not changed on (even if changed in slot) */
+       np->nchgaction[ii] |= NCHG_DMPVARNOW;
+       /* not changed bit already on */
+      }
+    }
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       if (!np->n_hasdvars) continue;
+
+       for (ii = 0; ii < mdp->flatinum; ii++)
+        {
+         if ((np->nchgaction[ii] & NCHG_DMPVARED) == 0) continue;
+
+         /* dumpv now off and not changed on (even if changed in slot) */
+         np->nchgaction[ii] |= NCHG_DMPVARNOW;
+         /* not changed bit already on */
+        }
+      }
+    }
+  }
+}
+
+/*
+ * ROUTINES TO ACTUALLY DUMP VARIABLES
+ */
+
+/*
+ * dump all variables for baseline - for start ($dumpvars), dumpon,
+ * dumpoff (need x's) and dumpall - keywrds determines which
+ * set flags
+ */
+extern void __do_dmpvars_baseline(char *keyws)
+{
+ __cur_sofs = 0;
+ if (__dv_outlinpos != 0)
+  {
+   addch_('\n');
+   __exprline[__cur_sofs] = '\0'; 
+   dv_wr(FALSE);
+  }
+ if (!__dv_time_emitted)
+  {
+   sprintf(__xs2, "#%s\n", to_dvtimstr(__xs, __simtime));
+   __adds(__xs2);
+   __dv_time_emitted = TRUE;
+   dv_wr(FALSE);
+  }
+ 
+ __adds(keyws);
+ dv_wr(TRUE);
+ __dv_outlinpos = 0;
+ if (strcmp(keyws, "$dumpoff") == 0) __dv_func = DMPV_DUMPX;
+ else __dv_func = DMPV_DMPALL; 
+ dump_allvars_vals();
+ if (__dv_outlinpos != 0) addch_('\n');
+ __adds("$end\n");
+ dv_wr(FALSE);
+ __dv_outlinpos = 0;
+}
+
+/*
+ * dumpvars convert a 64 bit internal tick time to a decimal string
+ *
+ * SJM 11/21/03 - now all systems but OSX support word32 64 printf
+ */
+static char *to_dvtimstr(char *s, register word64 t)
+{
+#ifdef __APPLE__
+ int32 trimblen, widnumlen;
+ word32 t1a[2];
+ char *cp;
+
+ t1a[0] = (word32) (t & WORDMASK_ULL);
+ if (t < WORDMASK_ULL) { sprintf(s, "%lu", t1a[0]); return(s); }
+
+ t1a[1] = (word32) ((t >> 32) & WORDMASK_ULL);
+ /* notice this case makes use of c require that fields are in order */
+ trimblen = __trim1_0val(t1a, TIMEBITS);
+ /* need ceil here */
+ widnumlen = (int32) (trimblen*LG2_DIV_LG10 + 0.999999);
+ __declcnv_tostr(s, t1a, trimblen, widnumlen);
+ /* AIV 11/20/03 need to trim the spaces for #time in vcd files */
+ if (*s == ' ')
+  {
+   for(cp = s; *cp == ' '; cp++);
+  } 
+ return(cp);
+#else
+ sprintf(s, "%llu", t);
+ return(s);
+#endif
+}
+
+/*
+ * dump all variables for various types of check pointing
+ * know when this called positioned at beginning of new line
+ */
+static void dump_allvars_vals(void)
+{
+ register int32 ni;
+ register struct mod_t *mdp;
+ register struct net_t *np;
+ register struct task_t *tskp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (!mdp->mod_hasdvars) continue; 
+   if (mdp->mnnum != 0)
+    {
+     for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+      {
+       /* if using default only dump vals for col. to col will never */
+       /* have dumpvars so do not need special checking */
+       /* if dump all even col. from, this is normal code */ 
+       if (np->n_hasdvars)
+        dmp_insts_ofwire(mdp, np);
+      }
+    }
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+
+     if (tskp->trnum == 0) continue;
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      { if (np->n_hasdvars) dmp_insts_ofwire(mdp, np); }
+    }
+  }
+}
+
+/*
+ * for a given net dump all instances of it - do not check change bit
+ * this is for base lines and any change info left unchanged
+ *
+ * loop here could be unwound to make it faster
+ * must never be called for arrays
+ *
+ * bld1 dvval uses global xs strings
+ */
+static void dmp_insts_ofwire(struct mod_t *mdp, struct net_t *np)
+{
+ register int32 ii; 
+ register struct itree_t *itp;
+ int32 jj;
+ char *dvcodp;
+
+ /* dump all dumpvared instances */
+ /* LOOKATME - this is only step much slower in new approach - problem? */ 
+ for (ii = 0; ii < mdp->flatinum; ii++) 
+  {
+   if ((np->nchgaction[ii] & NCHG_DMPVARED) == 0) continue;
+
+   itp = mdp->moditps[ii];
+
+   /* 07/02/00 - SJM - find right dvcod table code */
+   jj = 5*((np - mdp->mnets)*mdp->flatinum + itp->itinum); 
+   dvcodp = &(mdp->mndvcodtab[jj]);
+
+   /* here for strength vector pass 0th (first-low) bit of vector */
+   if (__dv_func == DMPV_DUMPX) bld1_xdvval(np, dvcodp);
+   else
+    {
+     if (np->n_isavec) bld1_vec_dvval(np, dvcodp, itp);
+     else bld1_scal_dvval(np, dvcodp, itp);
+    }
+   dv_wr(TRUE);
+  }
+} 
+
+/*
+ * do the dumpvars changes 
+ * this routine requires at least one dv change entry
+ */
+extern void __do_dmpvars_chg()
+{ 
+ register struct dvchgnets_t *dvchgnp;
+ register struct dvchgnets_t *dvchg_last;
+ register struct net_t *np;
+ register struct itree_t *itp;
+ int32 jj;
+ struct mod_t *mdp;
+ char *dvcodp;
+
+ if (__dv_outlinpos != 0)
+  {
+   addch_('\n'); 
+   __exprline[__cur_sofs] = '\0'; 
+   dv_wr(FALSE);
+  }
+ if (!__dv_time_emitted)
+  {
+   sprintf(__xs2, "#%s\n", to_dvtimstr(__xs, __simtime));
+   __adds(__xs2);
+   dv_wr(FALSE);
+   __dv_time_emitted = TRUE;
+   /* notice can only check for over limit when emitting new change time */
+   if (__dv_dumplimit_size != 0)
+    {
+     if (__dv_file_size > __dv_dumplimit_size)
+      {
+       __dv_outlinpos = 0;
+       sprintf(__xs2,
+        "$comment - Note: $dumplimit %d limit exceeded at %s $end\n",
+        __dv_dumplimit_size, __to_timstr(__xs, &__simtime));
+       __adds(__xs2);
+       dv_wr(FALSE);
+
+       __dv_state = DVST_OVERLIMIT;
+       __turnoff_all_dumpvars();
+
+       __cv_msg(
+        "  *** Dumping of variables stopped at %s because $dumplimit %d exceeded.\n",
+        __to_timstr(__xs, &__simtime), __dv_dumplimit_size);
+
+
+       /* need to move to end of change list so can free in chunk */
+       for (dvchg_last = NULL, dvchgnp = __dv_chgnethdr; dvchgnp != NULL;
+         dvchgnp = dvchgnp->dvchgnxt) dvchg_last = dvchgnp;
+       goto free_chglist;
+      }
+    }
+  }
+ __dv_outlinpos = 0;
+ __dv_func = DMPV_CHGONLY;
+
+ dvchg_last = NULL;
+ for (dvchgnp = __dv_chgnethdr; dvchgnp != NULL; dvchgnp = dvchgnp->dvchgnxt)
+  {
+   /* do the dumpvars for one var instance */
+   np = dvchgnp->dvchg_np;
+   itp = dvchgnp->dvchg_itp;
+   mdp = itp->itip->imsym->el.emdp;
+
+   jj = 5*((np - mdp->mnets)*mdp->flatinum + itp->itinum); 
+   dvcodp = &(mdp->mndvcodtab[jj]);
+   if (np->n_isavec) bld1_vec_dvval(np, dvcodp, itp);
+   else bld1_scal_dvval(np, dvcodp, itp);
+   dv_wr(TRUE);
+   /* reset this inst. not changed flag - i.e. must be on (not changed) */
+   /* for next time */ 
+   np->nchgaction[itp->itinum] |= NCHG_DMPVNOTCHGED;
+   dvchg_last = dvchgnp;
+  }
+ /* splice list on front of change free list all at once */
+ /* if last nil, no changes */
+free_chglist:
+ if (dvchg_last != NULL)
+  {
+   dvchg_last->dvchgnxt = __dv_netfreelst;
+   __dv_netfreelst = __dv_chgnethdr;
+   __dv_chgnethdr = NULL;
+  }
+}
+
+/*
+ * special routine to emit time stamp at end of dumpvars file
+ *
+ * LOOKATME - does not write if over file size limit but maybe should 
+ */
+extern void __wr_dvtimstr(void)
+{
+ if (__dv_state != DVST_DUMPING) return;
+ sprintf(__xs2, "#%s\n", to_dvtimstr(__xs, __simtime));
+ __adds(__xs2);
+ dv_wr(FALSE);
+}
+
+static char valtoch_tab[] = { '0', '1', 'z', 'x' };
+
+/*
+ * build 1 scalar variable's dumpvar value string into exprline
+ * caller must make sure right inum on top of itstk
+ * format for vector b[value] [up to 4 char id] - for scale [v][4 char id]
+ * for non x/z vector h[value] [id] - for real r[value][id]
+ * called only when change known or need to dump all vals
+ * notice __exprline can never be in use here 
+ */
+static void bld1_scal_dvval(struct net_t *np, char *dvcodp,
+ struct itree_t *itp)
+{
+ register word32 v;
+
+ __cur_sofs = 0;
+ /* when changed written with 1 - never have value 0 and always 1 bit */
+ /* will only be on changed list if cause during this time slot */
+ if (np->ntyp == N_EVENT) addch_('1');
+ else
+  {
+   v = (word32) np->nva.bp[itp->itinum];
+   addch_(valtoch_tab[v & 3]);
+  }
+ __adds(dvcodp);  
+}
+
+/*
+ * build 1 vector variable's dumpvar value string into exprline
+ * caller must make sure right inum on top of itstk
+ * format for vector b[value] [up to 4 char id] - for scale [v][4 char id]
+ * for non x/z vector h[value] [id] - for real r[value][id]
+ * called only when change known or need to dump all vals
+ * notice __exprline can never be in use here 
+ */
+static void bld1_vec_dvval(struct net_t *np, char *dvcodp, struct itree_t *itp)
+{
+ double d1; 
+ register struct xstk_t *xsp;
+
+ __cur_sofs = 0;
+ /* normal case */
+ if (np->ntyp == N_REAL)
+  {
+   /* double is always 8 bytes stored using b part as extra 4 bytes */
+   /* net width is 32 */
+   memcpy(&d1, &(np->nva.wp[2*itp->itinum]), sizeof(double));
+   sprintf(__xs2, "r%.16g ", d1);   
+   __adds(__xs2);
+  }
+ else
+  {
+   __push_itstk(itp);
+   push_xstk_(xsp, np->nwid);
+   __ld_wire_val(xsp->ap, xsp->bp, np);
+   addch_('b');
+   __sdispb(xsp->ap, xsp->bp, np->nwid, TRUE);
+   addch_(' ');
+   __pop_xstk();
+   __pop_itstk();
+  }
+ __adds(dvcodp);  
+}
+
+/*
+ * build 1 variable's dumpvar x value string into exprline
+ * format is x[up to 4 char id name] for scalar or bx [id] for vector
+ */
+static void bld1_xdvval(register struct net_t *np, char *dvcodp)
+{
+ __cur_sofs = 0;
+ if (!np->n_isavec)
+  { if (np->ntyp == N_EVENT) addch_('1'); else addch_('x'); }
+ /* real x is 0.0 */
+ else if (np->ntyp == N_REAL) __adds("r0.0 ");
+ else __adds("bx ");
+ __adds(dvcodp);
+}
+
+/*
+ * write the built dump var value
+ * know by here line always has ending new line
+ */
+static void dv_wr(int32 nd_nl)
+{
+ register int32 new_fsiz;
+
+ if (__cur_sofs == 0) return;
+ if (__dv_dumplimit_size != 0)
+  {
+   if (__dv_state == DVST_OVERLIMIT) return;
+
+   /* LOOKATME - +1 right since it points to \0? */
+   /* SJM 11/13/99 - no adding one makes file too small (now matches 1862) */
+   new_fsiz = __dv_file_size + __cur_sofs; 
+   __dv_file_size = new_fsiz;
+  }
+ /* know __cur_sofs points one past end of buffer */
+ /* 2 overflow cases current line bigger than buffer or does not fit */
+ if (__dv_nxti + __cur_sofs >= DVBUFSIZ - 2) 
+  {
+   /* SJM 03/03/00 - no longer adding nil to end of dv buffer */
+   if (__dv_nxti > 0)
+    {
+     /* DBG remove --
+     __cv_msg("writing dumpvars buffer of size %d\n", __dv_nxti);
+     --- */
+     write(__dv_fd, __dv_buffer, __dv_nxti);
+    }
+   __dv_nxti = 0;
+   /* immediate write if larger than buffer */
+   if (__cur_sofs >= DVBUFSIZ - 2)
+    {
+     if (nd_nl)
+      {
+       __exprline[__cur_sofs++] = '\n';
+       __dv_file_size++;
+      }
+     write(__dv_fd, __exprline, __cur_sofs); 
+     /* DBG remove --
+     __cv_msg("writing dumpvars buffer of size %d\n", __cur_sofs + 1);
+     --- */
+     goto done;
+    }
+  }
+ memcpy(&(__dv_buffer[__dv_nxti]), __exprline, __cur_sofs);
+
+ __dv_nxti += __cur_sofs;
+ if (nd_nl)
+  {
+   __dv_file_size++;
+   __dv_buffer[__dv_nxti++] = '\n';
+  }
+
+done:
+ /* FIXME - what if wrote without new line to add or in string - then wrong? */
+ __dv_outlinpos = 0;
+ __cur_sofs = 0;
+}
+
+/*
+ * flush a dumpvars - empty buffer then do OS flush 
+ */
+extern void __my_dv_flush(void)
+{
+ if (__dv_nxti > 0) write(__dv_fd, __dv_buffer, __dv_nxti);
+ __dv_nxti = 0;
+
+ /* SJM 07/02/00 - now avoiding fwrite buffering -- 
+ if (fflush(__dv _ s) == EOF)
+  {
+   __sgferr(701, "OS failure when flushing $dumpvars file %s: %s",
+    __dv_fnam, strerror(errno));
+  }
+ --- */
+}
diff --git a/src/v_fx.c b/src/v_fx.c
new file mode 100644
index 0000000..dc080f9
--- /dev/null
+++ b/src/v_fx.c
@@ -0,0 +1,7745 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * module that fixes and checks net list after all source read
+ * all defparam and global processing in v_grf
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/types.h>
+
+#if defined(__SVR4) || defined(__hpux) || defined(__CYGWIN32__)
+#include <dirent.h>
+#else
+#include <sys/dir.h>
+#endif
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void resolve_undef_mods(void);
+static void process_lib(void);
+static void resolve_from_ydir(struct vylib_t *);
+static struct undef_t *add_undef_el(struct sy_t *, struct undef_t **,
+ struct undef_t **);
+static void bld_ylb_dirfiles(struct vylib_t *);
+static int32 srch_yfiles(char *, struct mydir_t *, word32);
+static int32 fn_cmp(const void *, const void *);
+static void rd_vlibfil(struct undef_t *);
+static void rescan_process_lib(void);
+static void rescan_resolve_from_ydir(struct vylib_t *, struct undef_t *);
+static void free_tnblks(void);
+static void sep_mdgates(void);
+static int32 count_minum_and_mgnum(int32 *, struct mod_t *);
+static void cellrep_to_gate(struct cell_t *, struct gate_t *);
+static void add_mod_attrs_toinst(struct inst_t *);
+static int32 pndparams_explicit(struct namparam_t *, int32 *);
+static struct paramlst_t *bld_gate_paramlst(struct namparam_t *);
+static void bld_giarr(struct mod_t *, int32, struct cell_t *, int32);
+static void init_giarr(struct giarr_t *);
+static int32 cnt_gateprts(struct cell_t *);
+static void cellrep_to_inst(struct cell_t *, struct inst_t *);
+static void init_inst(struct inst_t *);
+static struct expr_t **inst_nparms_to_xtab(struct namparam_t *,
+ struct inst_t *);
+static struct expr_t **match_namparam_exprtab(struct namparam_t *,
+ struct inst_t *);
+static int32 chk1_pndparam(char *, struct inst_t *, struct namparam_t *,
+ int32, int32);
+static int32 prmtab_cmp(const void *, const void *);
+static struct expr_t **match_implprm_exprtab(struct namparam_t *,
+ struct inst_t *);
+static void bld_miarr(struct mod_t *, int32, struct cell_t *, int32);
+static int32 fix_modcell_nl(void);
+static int32 count_static_instances(struct mod_t *);
+static int32 chk_dag(void);
+static void fix_port_conns(void);
+static void setchk_modports(void);
+static int32 chk_prtref(struct expr_t *, struct mod_pin_t *, int32);
+static int32 chk_prtntyp(struct mod_pin_t *, struct net_t *);
+static void conn_mod_insts(void);
+static void conn_impl_mports(struct inst_t *, struct cell_pin_t *,
+ struct mod_t *, struct expr_t **, struct srcloc_t *);
+static void conn_expl_mports(struct inst_t *, struct cell_pin_t *,
+ struct mod_t *, struct expr_t **, struct srcloc_t *);
+static int32 chk_mdports_named(struct inst_t *, struct mod_t *, struct expr_t **);
+static void bld_srted_mdpins(struct mod_t *);
+static int32 smp_cmp(const void *, const void *);
+static int32 bld_srted_ipins(struct inst_t *, register struct cell_pin_t *,
+ int32, struct cell_pin_t **);
+static int32 cpn_cmp(const void *, const void *);
+static void free_cpblks(void);
+static void free_cppblks(void);
+static void count_flat_insts(void);
+static void count2_flat_insts(struct mod_t *);
+static void chg_params_to_tab(void);
+static int32 cnt_prms(struct net_t *);
+static void free_param_listform(struct net_t *);
+static void do_giarr_splitting(void);
+static void mark_gia_rng_params(struct mod_t *);
+static int32 in_giarng_markparam(struct giarr_t *, struct expr_t *);
+static int32 down_hasgiarngdet_param(struct mod_t *);
+static void bld_top_virtinsts(void);
+static int32 topip_cmp(const void *, const void *);
+static void save_all_param_vals(void);
+static void free_all_param_vals(void);
+static void set_giarr_ranges(void);
+static void eval1_arr_of_gates_rng(struct giarr_t *, struct mod_t *,
+ struct itree_t *, int32);
+static int32 gi_ndxexpr_chk(struct expr_t *, int32, int32, char *); 
+static int32 gi_ndxval_chk(struct xstk_t *, int32, int32, char *);
+static void eval1_arr_of_insts_rng(struct giarr_t *, struct mod_t *,
+ struct itree_t *, int32);
+static void set_pnd_gi_rnges(void);
+static void set2_pnd_gi_rnges(struct mod_t *, struct itree_t *);
+static void set_gia_expr_pndparms(struct expr_t *, struct itree_t *);
+static void set1_giarr_pndparm(struct net_t *, struct itree_t *); 
+static void unsave_gia_expr_pndparms(struct expr_t *, struct itree_t *);
+static void rebld_mod_giarrs(void);
+static int32 gia_sym_cmp(const void *, const void *);
+static void add_new_gsym(struct gate_t *, int32);  
+static void add_new_isym(struct inst_t *, int32); 
+static void chk_defparams(void);
+static int32 lhs_chk1dfparam(struct dfparam_t *);
+static int32 gref_has_giarr_ndxes(struct gref_t *);
+static void set_1defparam_iis(struct dfparam_t *, struct gref_t *);
+static void resolve_xmrs(void);
+static int32 resolve_local_path(struct gref_t *, struct expr_t *);
+static int32 chk_xmr_tail_wire(struct gref_t *, struct sy_t *, int32);
+static int32 fill_dfp_gsymhead(struct gref_t *, struct expr_t *);
+static int32 fill_gsymhead(struct gref_t *, struct expr_t *);
+static int32 chk_all_uprels_same(struct gref_t *, struct sy_t *, char *,
+ struct expr_t *);
+static struct sy_t *fnd_uprel_inst(char *, struct itree_t *);
+static int32 fnd_uprel_mod(struct sy_t *, struct itree_t *);
+static struct mod_t *fnd_uprel_tskfunc(struct sy_t **, char *,
+ struct itree_t *);
+static struct sy_t *fnd_tskfunc_inscope(char *, struct symtab_t *);
+static int32 fill_grestsyms(struct gref_t *, struct expr_t *);
+static struct sy_t *find_inmod_sym(struct gref_t *, struct expr_t *,
+ struct sy_t *, struct symtab_t **);
+static int32 chk_glb_inst_sels(struct gref_t *);
+static void free_gone_glbs(void);
+static void mark_poundparam_splitinsts(void);
+static int32 indir_widthdet_markparam(struct expr_t *);
+static void do_poundparam_splitting(void);
+static void split_upd_mod(struct mod_t *, struct inst_t *, int32); 
+static void copy_mod(struct mod_t *, char *);
+static void copy_modsymtabs(void);
+static void copy_lowsymtab(register struct symtab_t *, struct symtab_t *);
+static struct symtab_t *copy_1symtab(struct symtab_t *);
+static struct sy_t **copy_stsyms(struct sy_t **, word32);
+static void copy_modports(void);
+static void copy_wires(struct symtab_t *);
+static struct net_t *copy_params(struct net_t *, int32, int32);
+static void copy_defparams(void);
+static void copy_insts(void);
+static struct attr_t *copy_attrs(struct attr_t *);
+static struct varinitlst_t *copy_varinits(struct varinitlst_t *);
+static void copy_1inst(struct inst_t *, struct inst_t *, int32);
+static struct expr_t **copy_pndxtab(struct inst_t *);
+static void copy_iports(struct inst_t *, struct inst_t *);
+static void copy_miarr(void);
+static void copy_gates(void);
+static void copy_1gate(struct gate_t *, struct gate_t *, int32);
+static void copy_mgarr(void);
+static void copy_contas(void);
+static void copy_mdtasks(void);
+static struct task_pin_t *copy_tskargs(struct task_t *);
+static struct st_t *copy_stmt(struct st_t *);
+static struct st_t *copy_lstofsts(register struct st_t *);
+static struct ialst_t *copy_ialst(register struct ialst_t *);
+static struct csitem_t *copy_csitemlst(register struct csitem_t *);
+static struct exprlst_t *copy_xprlst(struct exprlst_t *);
+static void copy_mgrefs(void);
+static void copy_1gref_flds(struct gref_t *, struct gref_t *);
+static void copy_specify(void);
+static void copy_spcpths(struct spfy_t *, struct spfy_t *);
+static void copy_timchks(struct spfy_t *, struct spfy_t *);
+static struct tchk_t *copy1_tchk(struct tchk_t *);
+static void bld2_flat_itree(struct itree_t *);
+static int32 dmp_down_itree(struct itree_t *, int32, int32);
+static void do_dmp(struct itree_t *, int32);
+static void free2_flat_itree(struct itree_t *);
+static void bld_moditps(void);
+static void bld2_itnum_to_itp(struct itree_t *);
+
+
+/* extern prototypes (maybe defined in this module) */
+extern char *__my_malloc(int32);
+extern char *__my_realloc(char *, int32, int32);
+extern char *__pv_stralloc(char *);
+extern struct ncomp_t *__alloc_arrncomp(void);
+extern char *__prt_vtok(void);
+extern struct xstk_t *__eval2_xpr(struct expr_t *);
+extern int32 __isleaf(struct expr_t *);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern struct expr_t *__alloc_newxnd(void);
+extern struct exprlst_t *__alloc_xprlst(void);
+extern char *__to_ptnam(char *, word32);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_sytyp(char *, word32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern struct expr_t *__copy_expr(struct expr_t *);
+extern void __bld_flat_itree(void);
+extern void __free_flat_itree(void);
+/* DBG */
+extern void __dmp_itree(struct itree_t *); 
+/* --- */
+extern struct sy_t *__zget_sym(char *, struct sy_t **, word32);
+extern struct sy_t *__add_modsym(char *);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern struct symtab_t *__alloc_symtab(int32);
+extern struct paramlst_t *__alloc_pval(void);
+extern struct delctrl_t *__alloc_dctrl(void);
+extern struct csitem_t *__alloc_csitem(void);
+extern struct paramlst_t *__copy_dellst(struct paramlst_t *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern void __process_defparams(void);
+extern void __set_poundparams(void);
+extern void __process_timescales(void);
+extern void __recalc_param_vals(void);
+extern void __chk_1mdecls(void);
+extern void __mark_st_wires(void);
+extern void __setchk_mpwidths(void);
+extern void __chk_shorted_bids(void);
+extern void __reconn_gia_pins(void);
+extern void __reset_modport_strens(void);
+extern void __prt_top_mods(void);
+extern void __chk_mod(void);
+extern void __free_icptab(void);
+extern void __chkfix_spfy(void);
+extern void __free_specify(struct mod_t *);
+extern void __free_tchks(struct tchk_t *);
+extern void __emit_param_informs(void);
+extern void __grow_infils(int32);
+extern void __my_free(char *, int32);
+extern void __get_vtok(void);
+extern void __process_cdir(void);
+extern int32 __vskipto_modend(int32);
+extern int32 __vskipto2_modend(int32, int32);
+extern int32 __rd_moddef(struct symtab_t *, int32);
+extern int32 __rd_udpdef(struct symtab_t *);
+extern void __my_rewind(FILE *);
+extern void __my_fclose(FILE *);
+extern FILE *__tilde_fopen(char *, char *);
+extern void __free_xtree(struct expr_t *);
+extern void __free2_xtree(struct expr_t *);
+extern void __bld_unc_expr(void);
+extern void __in_xpr_markparam(struct expr_t *);
+extern int32 __chk_paramexpr(struct expr_t *, int32);
+extern void __set_numval(struct expr_t *, word32, word32, int32);
+extern void __free_1dfparam(struct dfparam_t *);
+extern struct gref_t *__alloc_grtab(struct gref_t *, int32);
+extern void __resolve_glbnam(struct gref_t *);
+extern int32 __ip_indsrch(char *);
+extern void __free_1glb_flds(struct gref_t *);
+extern void __bld_mlevel_lists(void);
+extern void __mark_widdet_params(struct mod_t *);
+extern void __do_mdsplit(struct mod_t *);
+extern void __init_itree_node(struct itree_t *);
+extern int32 __chk_giarr_ndx_expr(struct expr_t *);
+extern int32 __get_giarr_wide(struct giarr_t *);
+extern void __dmp_dsgn_minst(char *);
+extern void __dmp_1minst(struct inst_t *);
+extern int32 __expr_has_glb(struct expr_t *);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern void __free_namedparams(struct namparam_t *);
+extern int32 __chkndx_expr(struct expr_t *, char *);
+extern void __cnvt_param_stkval(struct xstk_t *, struct expr_t *,
+ struct net_t *, char *);
+extern void __assgn_nonis_param(struct net_t *, struct expr_t *,
+ struct xstk_t *);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern int32 __get_arrwide(struct net_t *);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern struct mod_t *__get_mast_mdp(struct mod_t *);
+extern void __set_drvr_bits(void);
+extern void __chk_chg_port_dir(int32);
+extern int32 __open_lbfil(int32);
+
+extern void __cv_msg(char *, ...);
+extern void __crit_msg(char *, ...);
+extern void __pv_ferr(int32, char *, ...);
+extern void __pv_err(int32, char *, ...);
+extern void __pv_warn(int32, char *,...);
+extern void __gfwarn(int32, word32, int32, char *, ...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __pv_fwarn(int32, char *, ...);
+extern void __gfinform(int32, word32, int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __finform(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __pv_terr(int32, char *, ...);
+extern void __gfterr(int32, word32, int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __misc_gfterr(char *, int32, word32, int32);
+
+/*
+ * DESIGN WIDE SYNTAX/SEMANTICS CHECKING ROUTINES
+ */
+
+/*
+ * fixup the net list after all modules read
+ * this is second pass on internal data structure
+ * returns T to get cannot continue message
+ */
+extern int32 __fixup_nl(void)
+{
+ register struct mod_t *mdp;
+
+ /* find and resolve unsatisfied module/udp refs - process lib. in here */
+ /* SJM 05/19/04 - following new P1364 LRM, config can't be in src */
+ if (__map_files_hd == NULL && __undef_mods != 0)
+  {
+   resolve_undef_mods();
+   if (__undef_mods != 0)
+    {
+     __crit_msg(
+      "  %d modules or udps unresolved after library processing - cannot continue.\n",
+      __undef_mods);
+     return(FALSE);
+    }
+  }
+
+ /* at this point all module and task symbol tables frozen so can free */
+ /* the tree nodes (can be large) and change formats */
+ free_tnblks();
+ chg_params_to_tab();
+
+ /* separate into gates and module instances */
+ /* also converts cell term expr. list to array of exprs (never explicit) */
+ sep_mdgates();
+
+ /* build static instance information */ 
+ if (!fix_modcell_nl()) return(TRUE);
+
+ /* check module ports and connect inst ports (for iarrs conns unexpanded) */
+ fix_port_conns();
+
+ /* AIV 06/01/04 FIXME ### ??? bug if config used and free these blocks */
+ /* now finished with cell pins and cells */
+ if (__map_files_hd != NULL)
+  {
+   free_cpblks();
+   /* this also frees cell pins (optional explicit port name) */
+   free_cppblks();
+  }
+
+ count_flat_insts();
+
+ /* need well formed static instance tree to continue */
+ if (__pv_err_cnt != 0) return(TRUE);
+
+ /* build the levelized module table - rebuilt later again after splitting */
+ __bld_mlevel_lists();
+
+ /* do split - needed because pound param used in array of gate/inst ranges */
+ if (__design_gi_arrays && __num_inst_pndparams != 0) do_giarr_splitting();
+
+ /* build top of itree table now so can search tops when build dfpii */
+ bld_top_virtinsts();
+
+ /* after here, all g/i array ranges known */
+ /* current value of pound params used then value thrown away because */
+ /* defparam setting and splitting may change again */
+ if (__design_gi_arrays)
+  {
+   /* save all module (not task/func) parameter values */
+   save_all_param_vals();
+
+   set_giarr_ranges();
+   /* rebuild array and gate tables in module with g/i arrays */
+   rebld_mod_giarrs();
+
+   /* final step free saved param value records */
+   free_all_param_vals();
+  }
+
+ /* check all defparams lhs and move globals to defparam struct */
+ chk_defparams();
+
+ /* do all splitting for all pound params */
+ /* must set pound params after all splitting since need itree inst num. */
+ if (__num_inst_pndparams != 0)
+  {
+   mark_poundparam_splitinsts();
+   do_poundparam_splitting();
+  }
+
+ /* build the as if flattened instance tree and assign instance numbers */
+ __bld_flat_itree();
+
+ /* -- v_fx2.c routines start here -- */
+
+ /* handle defparam setting and associated splitting and param expr array */
+ /* building - finally reassigns itree place numbers */
+ /* after here all parameters have a numeric value (but maybe IS form) */
+ /* therefore can fold and evaluate constant expressions */
+ 
+ /* notice if have defparams must process pound params at same time */
+ /* else do just pound params separately */
+ if (__num_dfps != 0) __process_defparams();
+ else if (__num_inst_pndparams != 0) __set_poundparams();
+
+ /* final itree instance numbers now assigned, build mod by num to inst tab */
+ bld_moditps();
+
+ /* resolve all global variables */
+ /* this reuses much of freed defparam storage if needed */
+ resolve_xmrs();
+
+ /* must stop here if errors since will not have value for xmrs */
+ if (__pv_err_cnt != 0) return(TRUE);
+
+ /* fixup - 2nd pass done - connectivity now known and no errors */
+
+ /* set timescale info before module checking that converts delays to ticks */
+ __process_timescales();
+
+ /* re-calculate parameter values, for params with other rhs params */
+ /* may have been changed by pount or defparam setting */ 
+ /* SJM 02/28/02 - need so parameter values use post pound/def val */
+ __recalc_param_vals();
+
+ /* now all parameter values known */
+ /* must check decl. and eval. wire params before setting port widths */
+ /* must always have at least dummy itree context set for these */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+ 
+   /* LOOKATME maybe could change to scheme where one mod net table */
+   /* contains all mod nets and regs decled in all tasks since one set */
+   /* per task - SJM 02/29/00 - yes moved chk taskvars to chk 1 mdecls */
+   __chk_1mdecls();
+   
+   __pop_wrkitstk();
+  }
+
+ /* SJM 05/23/01 - can't guess port types until ranges known as exprs */
+ /* set net per bit drvrs class (type) and change port dir if option on, */
+ /* else warns */
+ /* must do this after xmr's resolved and know ranges so can access xmr net */ 
+ __set_drvr_bits();
+ __chk_chg_port_dir(__chg_portdir);
+
+ /* at this point all wire widths known */
+
+ /* if no arrays of gate or instances in design, can set strengths now */ 
+ if (!__design_gi_arrays) __mark_st_wires();
+
+ /* mod port widths set here, widths now known - inst. width set in chk mod */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   __setchk_mpwidths();
+   __chk_shorted_bids();
+
+   /* must make sure module level symbols are all marked as top level */
+   mdp->msym->spltsy = NULL;
+   __pop_wrkitstk();
+  }
+
+ if (__design_gi_arrays)
+  {
+   __reconn_gia_pins();
+   /* mark wire that have strength storage format */
+   __mark_st_wires();
+   /* now set strength in port expr. bits if lhs with strength variable */
+   /* only check exprs (because need size) at this point are ports */
+   __reset_modport_strens();
+  }
+
+ /* if decl. errors cannot continue - do not know port widths */
+ /* and probably have missing expr. node fields */
+ if (__pv_err_cnt != 0) return(TRUE);
+
+ if (!__quiet_msgs) __prt_top_mods();
+
+ /* check mainly element usage semantics */
+ /* expression node widths and constant optimizations here */
+ /* statement checking here */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   __chk_mod();
+   __pop_wrkitstk();
+  }
+
+ /* free iploctab (line no. per contained mod port) shared among split */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   __free_icptab();
+   __pop_wrkitstk();
+  }
+
+ /* -- specify fixup (pass 2) routines in v fx3 but also expr checking */
+
+ /* check and fix up expressions from specify section */
+ /* also emit all unused parameter (both types warnings */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   if (mdp->mspfy != NULL)
+    {
+     __chkfix_spfy();
+     if (__no_specify)
+      { __free_specify(mdp); mdp->mspfy = NULL; } 
+     else if (mdp->mspfy->tchks != NULL && __no_tchks)
+      {
+       __free_tchks(mdp->mspfy->tchks);
+       mdp->mspfy->tchks = NULL;
+      }
+    }
+   __emit_param_informs();
+   __pop_wrkitstk();
+  }
+ return(TRUE);
+}
+
+/*
+ * routine to print top level modules - on one line
+ * always printed unless -q on
+ */
+extern void __prt_top_mods(void)
+{
+ register int32 tpii;
+ struct inst_t *ip;
+
+ __cv_msg("Highest level modules:\n");
+ for (tpii = 0; tpii < __numtopm; tpii++)
+  {
+   ip = __top_itab[tpii];
+   __cv_msg("%s\n", ip->imsym->synam);
+  }
+}
+
+/*
+ * MODULE DECLARATION CHECKING AND LIBRARY RESOLUTION ROUTINES
+ */
+
+/*
+ * resolve all undefined modules and udps
+ */
+static void resolve_undef_mods(void)
+{
+ register struct undef_t *undefp;
+ struct sy_t *syp;
+
+ /* try to satisfy unresolved modules/udps from -y, -v or - lib. */
+ /* check for remaining unresolveds, cannot continue if any */
+ if (__vyhdr != NULL)
+  {
+   if (__lib_rescan) rescan_process_lib();
+   else process_lib();
+  }
+ if (__undef_mods > 0)
+  {
+   /* notice this must be printed no matter what */
+   __crit_msg("Unresolved modules or udps:\n");
+   for (undefp = __undefhd; undefp != NULL; undefp = undefp->undefnxt)
+    {
+     syp = undefp->msyp;
+     if(syp->sydecl || !syp->syundefmod) __misc_terr(__FILE__, __LINE__);
+     __crit_msg("  %s\n", syp->synam);
+    }
+   __crit_msg("\n");
+  }
+ /* if libverbose messages need to separate */
+ else if (__lib_verbose) __cv_msg("\n");
+}
+
+/*
+ * process library to attempt to resolve all unresolved libraries
+ * only called if unresolved modules/udps remain
+ */
+static void process_lib(void)
+{
+ register struct undef_t *undefp;
+ register struct vylib_t *vyp;
+ int32 num_passes, sav_last_lbf;
+ struct sy_t *syp;
+
+ /* go thru libs in order */
+ for (num_passes = 1;; num_passes++)
+  {
+   if (num_passes > 1) __rescanning_lib = TRUE;
+
+   __cur_passres = 0;
+   if (__lib_verbose)
+    {
+     /* notice only unresolved after 1st pass are interesting */
+     if (num_passes > 1) 
+      {
+       __cv_msg("\n  Library scan pass %d with the following %d undefined:\n",
+        num_passes, __undef_mods);
+       for (undefp = __undefhd; undefp != NULL; undefp = undefp->undefnxt)
+        {
+         syp = undefp->msyp;
+         __cv_msg("    %s (first reference %s)\n", syp->synam,
+          __bld_lineloc(__xs, syp->syfnam_ind, syp->sylin_cnt));
+        }
+      }
+     else __cv_msg("\n  Begin library scan pass %d (%d undefined).\n",
+      num_passes, __undef_mods);
+    }
+
+   for (vyp = __vyhdr; vyp != NULL; vyp = vyp->vynxt)
+    {
+     /* AIV 11/11/03 - if -y dir is empty changed to 'e' so do nothing */
+     /* this handles multiple passes empty directories */
+     if (vyp->vytyp == 'e') continue;
+
+     if (vyp->vytyp == 'y')
+      {
+       if (vyp->yfiles == NULL) bld_ylb_dirfiles(vyp);
+
+       /* AIV 11/11/03 - if -y dir is empty made 'e' and must do nothing */
+       if (vyp->vytyp == 'e') continue;
+
+       resolve_from_ydir(vyp);
+       if (__undef_mods <= 0) return;
+       continue;
+      }
+
+     /* add or reuse -v library file to in_fils */
+     if (vyp->vyfnam_ind == 0)
+      {
+       /* this dies if >64k */
+       if (++__last_lbf >= __siz_in_fils) __grow_infils(__last_lbf);
+       vyp->vyfnam_ind = __last_lbf;
+       __in_fils[__last_lbf] = __pv_stralloc(vyp->vyu.vyfnam);
+      }
+
+     sav_last_lbf = __last_lbf;
+     __last_lbf = vyp->vyfnam_ind;
+     /* know this will leave undef_mods with correct value */
+     if (__open_lbfil(FALSE)) rd_vlibfil(NULL);
+     __last_lbf = sav_last_lbf;
+     if (__undef_mods <= 0) return;
+    }
+   if (__cur_passres == 0)
+    {
+     __pv_err(706,
+      "%d modules or primitives unresolved after pass %d with no progress",
+      __undef_mods, num_passes);
+     return;
+    }
+  }
+}
+
+/*
+ * resolve unresolved references from a library directory
+ * tricky because resolve as go along effecting __undefhd list
+ *
+ * algorithm is:
+ * 1) go through all unresolved and find all files that match any suffix
+ *    and add to list
+ * 2) then read and scan all files for any (not just names that produced
+ *    file by adding +lbext+ suffix) unresolved - quits in case all resolved
+ */
+static void resolve_from_ydir(struct vylib_t *vyp)
+{
+ register int32 lbxi;
+ register struct undef_t *undefp;
+ int32 dfi, sav_last_lbf, got_err;
+ struct undef_t *tmphd, *tmptail, *tmpundefp, *undefp2;
+ char fnam[IDLEN], stem[IDLEN];
+
+ tmphd = tmptail = NULL;
+ /* build stem that gives current path to directory */
+ sprintf(stem, "%s/", vyp->vyu.vydirpth);
+ /* case 1: no lbext - module name must exactly match file name */
+ if (__last_lbx == -1)
+  {
+   for (undefp = __undefhd; undefp != NULL; undefp = undefp->undefnxt)
+    {
+     if ((dfi = srch_yfiles(undefp->msyp->synam, vyp->yfiles, vyp->vyfnam_ind))
+      == -1 ) continue;
+     /* add to tmp list since parsing changes __undefhd list */ 
+     tmpundefp = add_undef_el(undefp->msyp, &tmphd, &tmptail); 
+     tmpundefp->dfi = dfi;
+     vyp->yfiles[dfi].ylbxi = 0;
+    }
+  }
+ else
+  {
+   /* case 2: must add lbext to module name and see if matches */
+   /* build temporary list of all */
+   for (undefp = __undefhd; undefp != NULL; undefp = undefp->undefnxt)
+    {
+     for (lbxi = 0; lbxi <= __last_lbx; lbxi++)
+      {
+       sprintf(fnam, "%s%s", undefp->msyp->synam, __lbexts[lbxi]);
+       if ((dfi = srch_yfiles(fnam, vyp->yfiles, vyp->vyfnam_ind)) == -1)
+        continue;
+
+       /* add to tmp list since parsing changes __undefhd list */ 
+       tmpundefp = add_undef_el(undefp->msyp, &tmphd, &tmptail); 
+       tmpundefp->dfi = dfi;
+       vyp->yfiles[dfi].ylbxi = lbxi;
+       /* when found, from precedence rules must stop looking */
+       break;
+      }
+    }
+  }
+ /* go through temp list reading file */
+ for (undefp = tmphd; undefp != NULL; undefp = undefp->undefnxt)
+  {
+   dfi = undefp->dfi;
+   if (vyp->yfiles[dfi].ydirfnam_ind == 0)
+    {
+     /* this dies if >64k */
+     if (++__last_lbf >= __siz_in_fils) __grow_infils(__last_lbf);
+     vyp->yfiles[dfi].ydirfnam_ind = __last_lbf;
+     if (__last_lbx == -1) sprintf(fnam, "%s%s", stem, undefp->msyp->synam);
+     else
+      {
+       lbxi = vyp->yfiles[dfi].ylbxi;
+       sprintf(fnam, "%s%s%s", stem, undefp->msyp->synam, __lbexts[lbxi]);
+      }
+     __in_fils[__last_lbf] = __pv_stralloc(fnam);
+    }
+   /* notice each lib. file increments this by 1 */
+   sav_last_lbf = __last_lbf;
+   __last_lbf = vyp->yfiles[dfi].ydirfnam_ind;
+   got_err = FALSE;
+
+   if (__open_lbfil(FALSE)) rd_vlibfil(NULL); else got_err = TRUE;
+   __last_lbf = sav_last_lbf;
+   if (got_err) continue;
+   /* if scanned because of a module and still unresolved after scanning */
+   /* need warning - i.e. it is legal to not resolve in name matching */
+   /* module but unrecommended */
+   if (!undefp->msyp->sydecl)
+    {
+     __pv_warn(510,
+      "module %s still unresolved after processing library directory file %s",
+      undefp->msyp->synam, __in_fils[vyp->yfiles[dfi].ydirfnam_ind]);
+    }
+   else break;
+  }
+ /* final step is to free temp undef list */
+ for (undefp = tmphd; undefp != NULL;) 
+  {
+   undefp2 = undefp->undefnxt;
+   __my_free((char *) undefp, sizeof(struct undef_t)); 
+   undefp = undefp2;
+  }
+}
+
+/*
+ * add to tail of undef list that is only singly linked
+ */
+static struct undef_t *add_undef_el(struct sy_t *syp,
+ struct undef_t **hd, struct undef_t **tail)
+{
+ struct undef_t *undefp;
+
+ undefp = (struct undef_t *) __my_malloc(sizeof(struct undef_t));
+ undefp->msyp = syp;
+ undefp->dfi = -1; 
+ undefp->modnam = NULL; 
+ undefp->undefprev = undefp->undefnxt = NULL;
+ if (*tail == NULL) *hd = *tail = undefp;
+ else { (*tail)->undefnxt = undefp; *tail = undefp; }
+ return(undefp);
+}
+
+/*
+ * preprocess 1 -y library directory - build entry for each file
+ * this builds sorted yfiles array
+ *
+ * notice done only once and saved
+ */
+static void bld_ylb_dirfiles(struct vylib_t *vyp)
+{
+ register int32 last_fi;
+ register int32 numdfils, siz_mydir, bytlen, obytlen;
+ DIR *dirp;
+#if defined(__SVR4) || defined(__hpux) || defined(__CYGWIN32__)
+ struct dirent *dp;
+#else
+ /* all BSD cases and special case interface for non unices */
+ struct direct *dp;
+#endif
+ struct mydir_t *mdtab; 
+
+ if ((dirp = opendir(vyp->vyu.vyfnam)) == NULL)
+  {
+   __pv_warn(511, "-y directory name %s not found - ignored",
+    vyp->vyu.vydirpth);
+   return;
+  }
+ siz_mydir = 256;
+ bytlen = siz_mydir*sizeof(struct mydir_t);
+ mdtab = (struct mydir_t *) __my_malloc(bytlen);
+ for (last_fi = -1;;)
+  {
+   /* should check error number here for other than end of file */
+   if ((dp = readdir(dirp)) == NULL) break;
+   if (*dp->d_name == '.' && (strcmp(dp->d_name, ".") == 0
+    || strcmp(dp->d_name, "..") == 0)) continue;
+
+   if (++last_fi >= siz_mydir)
+    {
+     obytlen = bytlen;
+     siz_mydir = 2*siz_mydir; 
+     bytlen = siz_mydir*sizeof(struct mydir_t); 
+     /* know initial section copied */
+     mdtab = (struct mydir_t *) __my_realloc((char *) mdtab, obytlen, bytlen); 
+    }  
+   mdtab[last_fi].ydirfnam_ind = 0;
+   mdtab[last_fi].ylbxi = 0;
+   mdtab[last_fi].dirfnam = __pv_stralloc(dp->d_name);
+  }
+ closedir(dirp);
+ numdfils = last_fi + 1;
+
+ /* AIV 11/11/03 could be an empty directory for -y, free, return */
+ if (numdfils == 0)
+  {
+   __my_free((char *) mdtab, bytlen);
+   __pv_warn(3114, "-y directory %s empty - ignored", vyp->vyu.vydirpth);
+   /* set vy type to 'e' to prevent any further attmpts to rebuild */
+   vyp->vytyp = 'e';
+   return;
+  }
+
+ /* final step, shrink my directory table back to exact size */
+ if (numdfils != siz_mydir) 
+  {
+   obytlen = bytlen;
+   bytlen = numdfils*sizeof(struct mydir_t); 
+   mdtab = (struct mydir_t *) __my_realloc((char *) mdtab, obytlen, bytlen); 
+  } 
+ qsort((char *) mdtab, (word32) numdfils, sizeof(struct mydir_t), fn_cmp); 
+ vyp->vyfnam_ind = numdfils;
+ vyp->yfiles = mdtab;
+ __num_ys++;
+}
+
+/*
+ * find index in sorted -y directory yfiles table
+ */
+static int32 srch_yfiles(char *nam, struct mydir_t *mdtab, 
+ word32 numdfiles)
+{
+ int32 l, h;
+ register int32 m, cv;
+
+ if (numdfiles == 0) return(-1);
+ l = 0; h = numdfiles - 1;
+ for (;;)
+  {
+   m = (l + h)/2;
+   if ((cv = strcmp(mdtab[m].dirfnam, nam)) == 0) return(m);
+   if (cv < 0) l = m + 1; else h = m - 1;
+   if (h < l) break;
+  }
+ return(-1);
+}
+
+/*
+ * module port name comparison routine
+ */
+static int32 fn_cmp(const void *dp1, const void *dp2)
+{
+ return(strcmp(((struct mydir_t *) dp1)->dirfnam,
+  ((struct mydir_t *) dp2)->dirfnam));
+}
+
+/*
+ * process a -v or in -y directory file - must try to resolve all modules
+ * know file open and no token read and normal source input env. set
+ * caller must open and close file
+ *
+ *
+ * if lib rescan only resolve one passed undefp and stop when resolved
+ *
+ * LOOKATME _ better here to save byte location from ftell and seek to byte
+ * for defined before used definitions but for now cannot do because do
+ * not have mechanism for saving and restoring compiler directive state?
+ */
+static void rd_vlibfil(struct undef_t *res_undefp)
+{
+ int32 nd_repeat, len, rewind_pass;
+ struct undef_t *hd, *tail, *undefp, *undefp2;
+ struct sy_t *syp;
+ char *chp, savtoken[IDLEN];
+
+ rewind_pass = 0;
+again:
+ rewind_pass++;
+ hd = tail = NULL; 
+ __get_vtok();
+ if (__toktyp == TEOF)
+  { __pv_fwarn(609, "library file contains no tokens"); return; }
+
+ for (;;)
+  {
+   /* may be a compiler directive */
+   if (__toktyp >= CDIR_TOKEN_START && __toktyp <= CDIR_TOKEN_END)
+    {
+     __process_cdir();
+     goto nxt_tok;
+    }
+   switch ((byte) __toktyp) {
+    case MACROMODULE:
+     __get_vtok();
+     __finform(423,
+      "macromodules in library not expanded - %s translated as module",
+      __token);
+     goto chk_name;
+    case MODULE:
+     __get_vtok();
+chk_name:
+     if (__toktyp != ID)
+      {
+       __pv_ferr(707, "in library file, module name expected - %s read",
+        __prt_vtok());
+       /* since error, just try to resynchronize */
+       __vskipto_modend(ENDMODULE);
+       goto nxt_tok;
+      }
+
+     /* if rescan specific one to resolve skip all but that one */
+     if ((syp = __get_sym(__token, __modsyms)) == NULL || syp->sydecl
+      || (res_undefp != NULL && syp != res_undefp->msyp))
+      { 
+       /* must save module name - skip overwrites */
+       strcpy(savtoken, __token);
+       if (!__vskipto_modend(ENDMODULE))
+        { 
+         __pv_ferr(767, 
+         "syntax error in skipped (defined or not referenced) library module %s",
+          __token);
+         goto nxt_tok;
+        }
+try_add_unref:
+       /* if symbol never referenced up to here may be define before use */
+       /* so need to add to list in case reference nearer end */
+       /* for rescan mode, this inhibits any rescanning */
+       if (syp == NULL && !__lib_rescan)
+        {
+         undefp = add_undef_el((struct sy_t *) NULL, &hd, &tail); 
+         chp = __pv_stralloc(savtoken);
+         undefp->modnam = chp;
+        }
+       goto nxt_tok;
+      }   
+
+     /* notice name token read - also undef_mods not changed */
+     if (__lib_verbose)
+      __cv_msg("  Compiling library module (%s).\n", __token);
+     /* know error here will cause skipping to file level thing */
+     if (!__rd_moddef(NULL, FALSE)) goto nxt_tok;
+     /* when reading source this was set only if in cell define region */
+     /* now turn on (maybe again) if all library modules are cells */
+     /* dummy itstk empty here but if good module read mark as cell */
+     if (__lib_are_cells && __last_libmdp != NULL)
+      {
+       __last_libmdp->m_iscell = TRUE;
+       __design_has_cells = TRUE;
+      }
+     __last_libmdp = NULL;
+     /* know to get here 1 more resolved */
+     __cur_passres++;
+     if (__undef_mods <= 0 || __lib_rescan) return;
+     break;
+
+    case PRIMITIVE:
+     __get_vtok();
+     if (__toktyp != ID)
+      {
+       __pv_ferr(708, "library file udp primitive name expected - %s read",
+	__prt_vtok());
+       /* since err, just try to skip to end primitive */
+       __vskipto_modend(ENDPRIMITIVE);
+       goto nxt_tok;
+      }
+     /* if rescan specific one to resolve skip all but that one */
+     if ((syp = __get_sym(__token, __modsyms)) == NULL || syp->sydecl
+      || (res_undefp != NULL && syp != res_undefp->msyp))
+      { 
+       /* must save module name - skip overwrites */
+       strcpy(savtoken, __token);
+       if (!__vskipto_modend(ENDPRIMITIVE))
+        {
+         __pv_ferr(702,
+	  "syntax error in skipped (defined or not referenced) library primitive %s",
+          __token);
+         goto nxt_tok;
+        }
+       goto try_add_unref;
+      }
+     /* notice name token read */
+     if (__lib_verbose)
+      __cv_msg("  Compiling library udp primitive (%s).\n", __token);
+     if (!__rd_udpdef(NULL)) goto nxt_tok;
+     /* if all modules resolved, nothing more to do */
+     __cur_passres++;
+     if (__undef_mods <= 0 || __lib_rescan) return;
+     break;
+    default:
+     __pv_ferr(709,
+     "library file module, primitive or directive expected - %s read",
+      __prt_vtok());
+     /* here just ignores extra semicolons */
+     if (__toktyp != SEMI) __vskipto2_modend(ENDMODULE, ENDPRIMITIVE);
+   }
+nxt_tok:
+   /* why checking this twice */
+   if (__toktyp == TEOF)
+    {
+chk_ifdef:
+     if (__in_ifdef_level != 0)
+      {
+       __pv_err(924, "last `ifdef unterminated in libary file %s",
+        __cur_fnam);
+      }
+     break;
+    }
+   __get_vtok();
+   if (__toktyp == TEOF) goto chk_ifdef;
+ }
+ /* need to determine if any of the skipped modules or udp's now undefined */
+ nd_repeat = FALSE;
+ for (undefp = hd; undefp != NULL; undefp = undefp->undefnxt) 
+  {
+   /* SJM 06/03/02 - change so undef list no longer shares undefprev */
+   chp = (char *) undefp->modnam;
+   /* DBG remove --- */
+   if (chp == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   
+   if ((syp = __get_sym(chp, __modsyms)) != NULL && !syp->sydecl)
+    {
+     nd_repeat = TRUE; 
+     if (!__lib_verbose) break;
+     __cv_msg(
+      "  Rereading %s library element %s defined before use (pass %d).\n",
+      __cur_fnam, syp->synam, rewind_pass);
+    }
+  } 
+
+ /* go through freeing list */
+ for (undefp = hd; undefp != NULL;) 
+  {
+   undefp2 = undefp->undefnxt;
+   /* LOOKATME - think will always be set here */ 
+   if (undefp->modnam != NULL)
+    {
+     chp = undefp->modnam;
+     len = strlen(chp);
+     __my_free(chp, len + 1);
+    }
+   __my_free((char *) undefp, sizeof(struct undef_t)); 
+   undefp = undefp2;
+  }
+ if (nd_repeat)
+  {
+   __my_rewind(__in_s);
+   /* in case hit eof with push back make sure reads 1st token */
+   __lasttoktyp = UNDEF;
+   __lin_cnt = 1;
+   __file_just_op = TRUE;
+   goto again;
+  }
+}
+
+/*
+ * try to open the next library file and repl. top of stack with its info
+ * file must be openable and have contents
+ * return F on no success
+ * in fils of last lbf must be filled with file name
+ * since know last_lbf > last_inf - on EOF get_vtok will resturn to caller
+ */
+extern int32 __open_lbfil(int32 is_dir)
+{
+ /* if not first time, close previous file */
+ if (__visp->vi_s != NULL) { __my_fclose(__visp->vi_s); __visp->vi_s = NULL; }
+ /* know called with last_lbf index of file to process */
+ __cur_fnam = __in_fils[__last_lbf];
+ if ((__in_s = __tilde_fopen(__cur_fnam, "r")) == NULL)
+  {
+   if (is_dir) strcpy(__xs, " directory"); else strcpy(__xs, "");
+   __pv_err(710, "cannot open Verilog library%s file %s - skipped", __xs,
+    __cur_fnam);
+   return(FALSE);
+  }
+ if (feof(__in_s))
+  {
+   __pv_warn(512, "Verilog library file %s empty", __cur_fnam);
+   return(FALSE);
+  }
+ /* whenever open new file must discard pushed back */
+ __lasttoktyp = UNDEF;
+ __visp->vi_s = __in_s;
+ __visp->vifnam_ind = __last_lbf;
+ __cur_fnam_ind = __last_lbf;
+ __cur_fnam = __in_fils[__cur_fnam_ind];
+ __lin_cnt = 1;
+ __file_just_op = TRUE;
+ if (__lib_verbose)
+  {
+   if (is_dir)
+    __cv_msg("  Opening library directory file \"%s\".\n", __cur_fnam);
+   else __cv_msg("  Scanning library file \"%s\".\n", __cur_fnam);
+  }
+ return(TRUE);
+}
+
+/*
+ * RESCAN LIBRARY RESOLUTION ROUTINES 
+ */
+ 
+/*
+ * process library to attempt to resolve all unresolved libraries
+ * only called if unresolved modules/udps remain
+ *
+ * BEWARE - must not free memory of linked out resolved undefp for
+ * 2 reasons: 1) need it for error msgs, 2) need next field to move in list
+ */
+static void rescan_process_lib(void)
+{
+ register struct undef_t *undefp;
+ register struct vylib_t *vyp;
+ struct undef_t *sav_undefhd;
+ struct sy_t *syp;
+ int32 sav_last_lbf, passi;
+
+ if (__lib_verbose)
+  {
+   __cv_msg("\n  Begin rescan mode library resolution (%d undefined).\n",
+    __undef_mods);
+  }
+
+ /* goto through unresolved resolving one per pass */
+ /* resolution of one may add other to end, but next field will */
+ /* be right for new */
+ passi = 1; 
+ for (undefp = __undefhd; undefp != NULL; passi++)
+  {
+   /* AIV 10/10/03 - undefhd may be removed and then new undefhd added as */
+   /* unresolved so must save and replace if changed */
+   sav_undefhd = __undefhd;
+
+   if (passi > 1) __rescanning_lib = TRUE;
+
+   if (__lib_verbose)
+    {
+     syp = undefp->msyp;
+     __cv_msg("\n  Resolving %s (first reference %s)(pass %d)\n",
+      syp->synam, __bld_lineloc(__xs, syp->syfnam_ind, syp->sylin_cnt), passi);
+    }
+   __cur_passres = 0;
+   for (vyp = __vyhdr; vyp != NULL; vyp = vyp->vynxt)
+    {
+     /* AIV 11/11/03 - if -y dir is empty changed to 'e' so do nothing */
+     /* this handles empty directories for rescanning */
+     if (vyp->vytyp == 'e') continue;
+
+     if (vyp->vytyp == 'y')
+      {
+       if (vyp->yfiles == NULL) bld_ylb_dirfiles(vyp);
+
+       /* AIV 11/11/03 - if -y dir is empty made 'e' and must do nothing */
+       if (vyp->vytyp == 'e') continue;
+
+       rescan_resolve_from_ydir(vyp, undefp);
+       if (__cur_passres == 0) continue;
+
+       /* DBG remove -- */
+       if (__cur_passres != 1) __misc_terr(__FILE__, __LINE__);
+       /* --- */
+       goto resolve_nxt;
+      }
+
+     /* add or reuse -v library file to in_fils */
+     if (vyp->vyfnam_ind == 0)
+      {
+       /* this dies if >64k */
+       if (++__last_lbf >= __siz_in_fils) __grow_infils(__last_lbf);
+       vyp->vyfnam_ind = __last_lbf;
+       __in_fils[__last_lbf] = __pv_stralloc(vyp->vyu.vyfnam);
+      }
+
+     sav_last_lbf = __last_lbf;
+     __last_lbf = vyp->vyfnam_ind;
+     /* know this will leave undef_mods with correct value */
+     if (__open_lbfil(FALSE)) rd_vlibfil(undefp);
+     __last_lbf = sav_last_lbf;
+     if (__cur_passres == 0) continue;
+     /* DBG remove -- */
+     if (__cur_passres != 1) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     goto resolve_nxt;
+    }
+   __pv_err(706,
+    "lib rescan module %s unresolved after all libaries searched - skipping to next",
+      undefp->msyp->synam);
+
+resolve_nxt:;
+   /* AIV 10/07/03 - if new head it is "next" else move one down list */ 
+   if (sav_undefhd != __undefhd) undefp = __undefhd;
+   else undefp = undefp->undefnxt;
+  }
+}
+
+/*
+ * rescan resolve one current unresolved references from a library dir
+ * simpler than non rescan cases because at most one resolved 
+ *
+ * algorithm is:
+ * 1) go through one current unresolved and find all files that match suffix
+ *    and add to list
+ * 2) then read and scan all files for the one unresolved now working on
+ */
+static void rescan_resolve_from_ydir(struct vylib_t *vyp,
+ struct undef_t *undefp)
+{
+ register int32 lbxi;
+ int32 dfi, sav_last_lbf, got_err;
+ struct undef_t *tmpundefp, *undefp2, *tmphd, *tmptail;
+ char fnam[IDLEN], stem[IDLEN];
+
+ /* build stem that gives current path to directory */
+ sprintf(stem, "%s/", vyp->vyu.vydirpth);
+ /* case 1: no lbext - module name must exactly match file name */
+ tmphd = tmptail = NULL;
+ if (__last_lbx == -1)
+  {
+   if ((dfi = srch_yfiles(undefp->msyp->synam, vyp->yfiles, vyp->vyfnam_ind))
+    != -1)
+    {
+     /* add to tmp list since parsing changes __undefhd list */ 
+     tmpundefp = add_undef_el(undefp->msyp, &tmphd, &tmptail); 
+     tmpundefp->dfi = dfi;
+     vyp->yfiles[dfi].ylbxi = 0;
+    }
+  }
+ else
+  {
+   /* case 2: must add lbext to module name and see if matches */
+   /* build temporary list of all */
+   for (lbxi = 0; lbxi <= __last_lbx; lbxi++)
+    {
+     sprintf(fnam, "%s%s", undefp->msyp->synam, __lbexts[lbxi]);
+     if ((dfi = srch_yfiles(fnam, vyp->yfiles, vyp->vyfnam_ind)) == -1)
+      continue;
+
+     /* add to tmp list since parsing changes __undefhd list */ 
+     tmpundefp = add_undef_el(undefp->msyp, &tmphd, &tmptail); 
+     tmpundefp->dfi = dfi;
+     vyp->yfiles[dfi].ylbxi = lbxi;
+     /* when found, from precedence rules must stop looking */
+     break;
+    }
+  }
+ /* go through temp (will always be exactly one long) list reading file */
+ /* DBG remove -- */
+ if (tmphd != NULL && tmphd->undefnxt != NULL)
+  __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ for (undefp = tmphd; undefp != NULL; undefp = undefp->undefnxt)
+  {
+   dfi = undefp->dfi;
+   if (vyp->yfiles[dfi].ydirfnam_ind == 0)
+    {
+     /* this dies if >64k */
+     if (++__last_lbf >= __siz_in_fils) __grow_infils(__last_lbf);
+     vyp->yfiles[dfi].ydirfnam_ind = __last_lbf;
+     if (__last_lbx == -1) sprintf(fnam, "%s%s", stem, undefp->msyp->synam);
+     else
+      {
+       lbxi = vyp->yfiles[dfi].ylbxi;
+       sprintf(fnam, "%s%s%s", stem, undefp->msyp->synam, __lbexts[lbxi]);
+      }
+     __in_fils[__last_lbf] = __pv_stralloc(fnam);
+    }
+   /* notice each lib. file increments this by 1 */
+   sav_last_lbf = __last_lbf;
+   __last_lbf = vyp->yfiles[dfi].ydirfnam_ind;
+   got_err = FALSE;
+
+   if (__open_lbfil(FALSE)) rd_vlibfil(undefp); else got_err = TRUE;
+   __last_lbf = sav_last_lbf;
+   if (got_err) continue;
+   /* if scanned because of a module and still unresolved after scanning */
+   /* need warning - i.e. it is legal to not resolve in name matching */
+   /* module but unrecommended */
+   if (!undefp->msyp->sydecl)
+    {
+     __pv_warn(510,
+      "module %s still unresolved after processing library directory file %s",
+      undefp->msyp->synam, __in_fils[vyp->yfiles[dfi].ydirfnam_ind]);
+    }
+   else break;
+  }
+ /* final step is to free temp undef list */
+ for (undefp = tmphd; undefp != NULL;) 
+  {
+   undefp2 = undefp->undefnxt;
+   __my_free((char *) undefp, sizeof(struct undef_t)); 
+   undefp = undefp2;
+  }
+}
+
+/*
+ * PRELIMINARY FIXUP ROUTINES USUALLY FORMAT CHANGES 
+ */
+
+/*
+ * routine to free all allocated tnode blks from unfrozen part of symtabs
+ */
+static void free_tnblks(void)
+{
+ register struct tnblk_t *tnbp, *tnbp2;
+
+ /* free all cell pin blks since ncomp form now gone */
+ for (tnbp = __hdr_tnblks; tnbp != NULL;)
+  {
+   tnbp2 = tnbp->tnblknxt;
+   __my_free((char *) tnbp->tnblks, BIG_ALLOC_SIZE);
+   __my_free((char *) tnbp, sizeof(struct tnblk_t));
+   tnbp = tnbp2;
+  }
+ __hdr_tnblks = NULL;
+}
+
+/*
+ * change all module and task parameter lists to table from list
+ *
+ * also sets mprmnum and tprmnum so know size of tables
+ * after completion, param nu2 field nnxt field no longed needed
+ */
+static void chg_params_to_tab(void)
+{
+ register int32 pi;
+ register struct net_t *pnp, *pnp2;
+ register struct mod_t *mdp;
+ int32 pnum;
+ struct net_t *nptab;
+ struct task_t *tskp;
+ struct spfy_t *spfyp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   /* first module params */
+   pnum = cnt_prms(mdp->mprms);
+   if (pnum != 0)
+    {
+     nptab = (struct net_t *) __my_malloc(pnum*sizeof(struct net_t));
+     pi = 0;
+     for (pnp = mdp->mprms; pnp != NULL; pnp = pnp->nu2.nnxt, pi++)
+      {
+       pnp2 = &(nptab[pi]);
+       *pnp2 = *pnp;
+       /* symbol points back to net - because copied to table change ptr */
+       pnp2->nsym->el.enp = pnp2;
+       /* ptr filds in pnp unique so will just get moved to new */
+       /* except must nil out new table pnp2 nu2 because needed for saving */
+       pnp2->nu2.wp = NULL;
+      }
+     mdp->mprmnum = pnum;
+     free_param_listform(mdp->mprms);
+     mdp->mprms = nptab;
+    }
+
+   /* next parameters in each task */
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if ((pnum = cnt_prms(tskp->tsk_prms)) == 0) continue;
+
+     nptab = (struct net_t *) __my_malloc(pnum*sizeof(struct net_t));
+     pi = 0;
+     for (pnp = tskp->tsk_prms; pnp != NULL; pnp = pnp->nu2.nnxt, pi++)
+      {
+       pnp2 = &(nptab[pi]);
+       *pnp2 = *pnp;
+       /* symbol points back to net - because copied to table change ptr */
+       pnp2->nsym->el.enp = pnp2;
+       /* ptr filds in pnp uniue so will just get moved to new */
+       /* except must nil out new table pnp2 nu2 because needed for saving */
+       pnp2->nu2.wp = NULL;
+      }
+     tskp->tprmnum = pnum;
+     free_param_listform(tskp->tsk_prms);
+     tskp->tsk_prms = nptab;
+    }
+   /* finally specparams */
+   if ((spfyp = mdp->mspfy) == NULL) goto nxt_mod;
+   if ((pnum = cnt_prms(spfyp->msprms)) == 0) goto nxt_mod;
+
+   nptab = (struct net_t *) __my_malloc(pnum*sizeof(struct net_t));
+   pi = 0;
+   for (pnp = spfyp->msprms; pnp != NULL; pnp = pnp->nu2.nnxt, pi++)
+    {
+     pnp2 = &(nptab[pi]);
+     *pnp2 = *pnp;
+     /* symbol points back to net - because copied to table change ptr */
+     pnp2->nsym->el.enp = pnp2;
+     /* ptr filds in pnp unique so will just get moved to new */
+     /* except must nil out new table pnp2 nu2 because needed for saving */
+     pnp2->nu2.wp = NULL;
+    }
+   spfyp->sprmnum = pnum;
+   free_param_listform(spfyp->msprms);
+   spfyp->msprms = nptab;
+nxt_mod:
+   __pop_wrkitstk();
+  }
+
+}
+
+/*
+ * count params in list form
+ */
+static int32 cnt_prms(struct net_t *np)
+{
+ register struct net_t *parm_np;
+ int32 pnum;
+
+ for (pnum = 0, parm_np = np; parm_np != NULL; parm_np = parm_np->nu2.nnxt)
+  { pnum++; }
+ return(pnum);
+}
+
+/*
+ * free parameter list form
+ *
+ * no freeing of ncomp or expressions pointed to from inside since moved
+ * to table form element
+ */
+static void free_param_listform(struct net_t *parm_np)
+{
+ register struct net_t *pnp, *pnp2;
+
+ for (pnp = parm_np; pnp != NULL;)
+  {
+   pnp2 = pnp->nu2.nnxt;
+   __my_free((char *) pnp, sizeof(struct net_t)); 
+   pnp = pnp2;
+  }
+}
+
+/*
+ * ROUTINES TO SEPARATE CELLS INTO GATES AND INSTANCES
+ */
+
+/*
+ * separate module gate and insts into separate lists
+ * contas already separated by here 
+ * relocate, free cell_t, and build array form port lists
+ *
+ * also checks for unnamed module instances and number cells with type range
+ * could save some space by make insts and gates array of thing rather
+ * than array of ptrs to things
+ */
+static void sep_mdgates(void)
+{
+ register struct cell_t *cp;
+ int32 modinum, modgnum, ii, gi, nbytes;
+ struct mod_t *mdp;
+ struct inst_t *iptab;
+ struct gate_t *gptab;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   /* first allocate array of pointers to instances */
+   modinum = count_minum_and_mgnum(&modgnum, mdp);
+   if (modinum != 0)
+    {
+     nbytes = modinum*sizeof(struct inst_t);
+     iptab = (struct inst_t *) __my_malloc(nbytes);
+    }
+   else iptab = NULL;
+   if (modgnum != 0)
+    {
+     nbytes = modgnum*sizeof(struct gate_t);
+     gptab = (struct gate_t *) __my_malloc(nbytes);
+    }
+   else gptab = NULL;
+
+   ii = gi = -1;
+   for (cp = mdp->mcells; cp != NULL; cp = cp->cnxt)
+    {
+     /* if not declared error above can still get here */
+     /* but undeclared udp symbol with always be actually undcl mod */
+     /* case 1: udp */ 
+     if (cp->cmsym->sytyp == SYM_UDP)
+      {
+       cellrep_to_gate(cp, &(gptab[++gi]));
+       if (cp->cx1 != NULL) bld_giarr(mdp, gi, cp, modgnum);
+       continue;
+      }
+     /* case 2: built in primitive */ 
+     if (cp->cmsym->sytyp == SYM_PRIM)
+      {
+       /* notice pullup becomes gate but can have only 1 (or more) ports */
+       cellrep_to_gate(cp, &(gptab[++gi]));
+       if (cp->cx1 != NULL) bld_giarr(mdp, gi, cp, modgnum);
+       continue;
+      }
+     /* case 3: instance */
+     if (!cp->c_named)
+      {
+       __gferr(731, cp->csym->syfnam_ind, cp->csym->sylin_cnt,
+        "required module instance name missing (type is %s)",
+        cp->cmsym->synam);
+       cp->c_named = FALSE;
+      }
+     if (cp->cmsym != NULL && cp->cmsym->sydecl)
+      {
+       cellrep_to_inst(cp, &(iptab[++ii]));
+       if (cp->cx1 != NULL) bld_miarr(mdp, ii, cp, modinum);
+      }
+    }
+   mdp->minum = modinum; 
+   mdp->minsts = iptab; 
+   mdp->mgnum = modgnum;
+   mdp->mgates = gptab; 
+   mdp->mcells = NULL;
+
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * count number of instances in module
+ * need array that is parallel to itree array for instances so must
+ * count in order to allocate before building array
+ */
+static int32 count_minum_and_mgnum(int32 *gnum, struct mod_t *mdp)
+{
+ register struct cell_t *cp;
+ int32 inum;
+ struct sy_t *syp;
+
+ for (inum = *gnum = 0, cp = mdp->mcells; cp != NULL; cp = cp->cnxt)
+  {
+   syp = cp->cmsym;
+   if (syp == NULL || !syp->sydecl) continue;
+
+   if (syp->sytyp == SYM_UDP || syp->sytyp == SYM_PRIM) (*gnum)++;
+   else inum++;
+  }
+ return(inum);
+}
+
+/*
+ * convert a syntax analysis format general cell struct to a sim gate struct
+ * cell pin list changed to expression list later
+ */
+static void cellrep_to_gate(struct cell_t *cp, struct gate_t *gp)
+{
+ register int32 pi;
+ register struct cell_pin_t *cpp;
+ int32 pnum, nbytes, all_named;
+ char s1[RECLEN];
+
+ /* how is a port connect lost */
+ if ((pnum = cnt_gateprts(cp)) == 0L)
+  {
+   __gferr(732, cp->csym->syfnam_ind, cp->csym->sylin_cnt,
+    "%s %s illegal - at least one gate required", __to_sytyp(__xs,
+    cp->cmsym->sytyp), cp->cmsym->synam);
+  }
+ /* must fit in 16 bits */
+ if (pnum >= 0x3fffL)
+  {
+   __gferr(732, cp->csym->syfnam_ind, cp->csym->sylin_cnt,
+    "%s %s has too many terminals (%d)", __to_sytyp(__xs, cp->cmsym->sytyp),
+    cp->cmsym->synam, 0x3fffL);
+   pnum = 0x3fffL;
+  }
+
+ /* notice symbol type is still SYM_I here */
+ gp->gsym = cp->csym;
+ gp->gsym->el.egp = gp;
+ gp->gmsym = cp->cmsym;
+ gp->gpnum = pnum;
+ gp->g_hasst = (cp->c_hasst) ? TRUE : FALSE;
+ gp->g_stval = cp->c_stval;
+ gp->g_delrep = DT_CMPLST;
+ gp->g_gone = FALSE;
+ gp->g_pdst = FALSE;
+ if (gp->gmsym->sytyp == SYM_UDP)
+  { gp->g_class = GC_UDP; gp->gsym->sytyp = SYM_PRIM; }
+ else
+  {
+   gp->g_class = gp->gmsym->el.eprimp->gclass;
+   gp->gsym->sytyp = SYM_PRIM;
+  }
+
+ gp->schd_tevs = NULL;
+ /* since before cells numbered non zero means unnamed */
+ if (!cp->c_named) gp->g_unam = TRUE; else gp->g_unam = FALSE;
+
+ gp->g_du.pdels = NULL;
+ if (cp->c_nparms != NULL)
+  {
+   /* explicit parameter name form illegal for udps or gates */
+   /* T returned if some named */
+   if (pndparams_explicit(cp->c_nparms, &all_named))
+    {
+     if (all_named) strcpy(s1, "all"); else strcpy(s1, "some");
+     __gferr(809, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+      "%s explicit .[parameter name]([expr]) # delay forms illegal for %s %s",
+      s1, __to_sytyp(__xs, gp->gmsym->sytyp), gp->gmsym->synam);
+     __free_namedparams(cp->c_nparms);
+     gp->g_du.pdels = NULL;
+    }
+   else
+    {
+     gp->g_du.pdels = bld_gate_paramlst(cp->c_nparms);
+     __free_namedparams(cp->c_nparms);
+     cp->c_nparms = NULL;
+    }
+  }
+ gp->gstate.wp = NULL;
+
+ /* just move ptr since not shared */
+ gp->gattrs = cp->cattrs;
+
+ nbytes = pnum*sizeof(struct expr_t *);
+ /* SJM 05/05/03 - from previous syntax errors where can't recover */ 
+ /* this may be nil, but since errors still works */
+ if (pnum > 0) gp->gpins = (struct expr_t **) __my_malloc(nbytes);
+ else gp->gpins = NULL;
+ gp->gchg_func = NULL;
+ for (cpp = cp->cpins, pi = 0; cpp != NULL; pi++, cpp = cpp->cpnxt)
+  {
+   /* this should always be at least 'bx by here */
+   if (cpp->pnam != NULL)
+    {
+     __gferr(733, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+      "explicit port connection illegal for %s %s",
+      __to_sytyp(__xs, gp->gmsym->sytyp), gp->gmsym->synam);
+     /* all freeing later */
+    }
+   /* this copies expr. (not freed) from cpins so when entire */
+   /* cpin blocks freed later, no interlinking */ 
+   if (pi < pnum) gp->gpins[pi] = cpp->cpxnd;
+  }
+}
+
+/*
+ * return T if param name list has any explicit named forms
+ * if returns T, also sets flag if all are explicit form
+ */
+static int32 pndparams_explicit(struct namparam_t *npmphdr, int32 *all_named)
+{
+ register struct namparam_t *npmp;
+ int32 has_named, all2_named;
+
+ *all_named = FALSE;
+ has_named = FALSE;
+ all2_named = TRUE;
+ for (npmp = npmphdr; npmp != NULL; npmp = npmp->nprmnxt)
+  {
+   if (npmp->pnam != NULL) has_named = TRUE;
+   else all2_named = FALSE;
+  }
+ if (has_named) *all_named = all2_named; 
+ return(has_named);
+}
+
+/*
+ * build a delay parameter list from a named parameter list for gates
+ *
+ * know all unnamed comma separated form list or will not be called
+ * also know delay list with at least one element present or not called
+ */
+static struct paramlst_t *bld_gate_paramlst(struct namparam_t *npmphdr)
+{
+ register struct namparam_t *npmp;
+ int32 pi;
+ struct paramlst_t *nplphdr, *nplp, *last_nplp;
+
+ nplphdr = last_nplp = NULL;
+ for (pi = 0, npmp = npmphdr; npmp != NULL; npmp = npmp->nprmnxt, pi++)
+  {
+   if (npmp->pxndp->optyp == OPEMPTY)
+    {
+     __pv_ferr(1190,
+      "empty ,, form primitive pound delay value illegal (pos. %d)", pi + 1);
+     continue;
+    }
+   nplp = __alloc_pval();
+   nplp->plxndp = npmp->pxndp; 
+   npmp->pxndp = NULL;
+   if (last_nplp == NULL) nplphdr = nplp; else last_nplp->pmlnxt = nplp;
+   nplp->pmlnxt = NULL;
+   last_nplp = nplp;
+  }
+ if (nplphdr == NULL)
+  {
+   __pv_ferr(1095, "empty primitive #() delay expression illegal");
+  }
+ return(nplphdr);
+}
+
+/*
+ * build parallel array to mgates index element 
+ * only called if array form has range expr
+ */
+static void bld_giarr(struct mod_t *mdp, int32 gi, struct cell_t *cp, int32 mgnum)
+{
+ int32 i;
+ struct giarr_t *giap;
+
+ if (mdp->mgarr == NULL)
+  {
+   mdp->mgarr = (struct giarr_t **) __my_malloc(mgnum*sizeof(struct giarr_t *));
+   for (i = 0; i < mgnum; i++) mdp->mgarr[i] = NULL;
+  }
+ mdp->mgarr[gi] = (struct giarr_t *)__my_malloc(sizeof(struct giarr_t)); 
+ giap = mdp->mgarr[gi];
+ init_giarr(giap);
+ giap->giax1 = cp->cx1;  
+ giap->giax2 = cp->cx2;
+ __design_gi_arrays = TRUE;
+}
+
+/*
+ * initialize a giarr
+ */
+static void init_giarr(struct giarr_t *giap)
+{
+ giap->gia_xpnd = FALSE;
+ giap->gia_rng_has_pnd = FALSE;
+ giap->giax1 = giap->giax2 = NULL;
+ giap->gia1 = giap->gia2 = -1; 
+ giap->gia_bi = -1;
+ giap->giapins = NULL;
+ giap->gia_base_syp = NULL;
+}
+
+/*
+ * build parallel array to marrs index element 
+ * only called if module has arrays of insts
+ */
+static void bld_miarr(struct mod_t *mdp, int32 ii, struct cell_t *cp, int32 minum)
+{
+ int32 i;
+ struct giarr_t *giap;
+
+ if (mdp->miarr == NULL)
+  {
+   mdp->miarr = (struct giarr_t **) __my_malloc(minum*sizeof(struct giarr_t *));
+   for (i = 0; i < minum; i++) mdp->miarr[i] = NULL;
+  }
+ mdp->miarr[ii] = (struct giarr_t *) __my_malloc(sizeof(struct giarr_t)); 
+ giap = mdp->miarr[ii];
+ init_giarr(giap);
+ giap->giax1 = cp->cx1;  
+ giap->giax2 = cp->cx2;
+ __design_gi_arrays = TRUE;
+}
+
+/*
+ * count the number of ports a gate has
+ */
+static int32 cnt_gateprts(struct cell_t *cp)
+{
+ register struct cell_pin_t *cpp;
+ int32 pnum;
+
+ for (pnum = 0, cpp = cp->cpins; cpp != NULL; cpp = cpp->cpnxt) pnum++;
+ return(pnum);
+}
+
+/*
+ * convert a syntax analysis format general cell struct to a sim gate struct
+ *
+ * by here know module declared params converted to table from list
+ * this also checked passed instance # params constant expressions
+ */
+static void cellrep_to_inst(struct cell_t *cp, struct inst_t *ip)
+{
+ /* if module not defined, nothing to do */
+ if (cp->c_hasst)
+  {
+   __gferr(734, cp->csym->syfnam_ind, cp->csym->sylin_cnt,
+    "module instance %s type %s strength specification illegal",
+    cp->csym->synam, cp->cmsym->synam);
+  }
+
+ init_inst(ip);
+
+ ip->isym = cp->csym;
+ ip->isym->el.eip = ip;
+ ip->imsym = cp->cmsym;
+ ip->pprm_explicit = FALSE;
+ /* instance numbers assigned later because splitting can change */
+ /* convert named param list to parallel table of pound param exprs */
+
+ /* must set instance type flags before processing pound params */
+ ip->i_iscell = (cp->c_iscell) ? TRUE : FALSE;
+ ip->i_pndsplit = FALSE;
+
+ /* this also checks pound paremeter's since know each params loc. */
+ if (cp->c_nparms == NULL) ip->ipxprtab = NULL;
+ else ip->ipxprtab = inst_nparms_to_xtab(cp->c_nparms, ip);
+
+ ip->ip_explicit = (cp->cp_explicit) ? TRUE : FALSE;
+
+ /* count instances with pound params */
+ if (ip->ipxprtab != NULL) __num_inst_pndparams++;
+
+ /* just move ptr since not shared */
+ ip->iattrs = cp->cattrs;
+ /* if has instance attributes combine mod attributes into inst attrs */
+ if (ip->iattrs != NULL && ip->imsym->el.emdp->mattrs != NULL)
+  add_mod_attrs_toinst(ip);
+
+ /* for now must leave inst-pin list form */
+ ip->ipins = (struct expr_t **) cp->cpins;
+}
+
+/*
+ * routine to initialize inst_t record
+ *
+ * SJM 10/16/00 - needed to avoid errors and for top_ip
+ */
+static void init_inst(struct inst_t *ip)
+{
+ ip->ip_explicit = FALSE;
+ ip->pprm_explicit = FALSE;
+ ip->i_iscell = FALSE;
+ ip->i_pndsplit = FALSE;
+ ip->isym = NULL;
+ ip->imsym = NULL;
+ ip->ipxprtab = NULL;
+ ip->iattrs = NULL;
+ ip->ipins = NULL;
+ ip->pb_ipins_tab = NULL;
+}
+
+/*
+ * merge attributes from mod into inst
+ *
+ * only called if both inst and mod have at least one attr
+ * if same attr name in both use inst value
+ * if name only in mod add to inst list so can use list to make iterator  
+ */
+static void add_mod_attrs_toinst(struct inst_t *ip)
+{
+ register struct attr_t *iattrp, *mattrp, *iattr_end;
+ struct attr_t *new_iattrp, *new_iattrhd, *new_iattrend;
+ struct mod_t *mdp;
+
+ new_iattrhd = new_iattrend = NULL;
+ iattr_end = NULL;
+ for (iattrp = ip->iattrs; iattrp != NULL; iattrp = iattrp->attrnxt) 
+  { iattr_end = iattrp; }
+ mdp = ip->imsym->el.emdp;
+
+ for (mattrp = mdp->mattrs; mattrp != NULL; mattrp = mattrp->attrnxt) 
+  {
+   for (iattrp = ip->iattrs; iattrp != NULL; iattrp = iattrp->attrnxt)
+    {
+     /* attribute attached to both inst and mod - use inst value */
+     if (strcmp(mattrp->attrnam, iattrp->attrnam) == 0) goto nxt_mod_attr;
+    }
+   /* attr attached to mod but not inst and inst has at least one attr */ 
+   /* add mod attr to inst */
+   new_iattrp = (struct attr_t *) __my_malloc(sizeof(struct attr_t));
+   *new_iattrp = *mattrp;
+   new_iattrp->attrnam = __pv_stralloc(mattrp->attrnam);
+   new_iattrp->attr_xp = __copy_expr(mattrp->attr_xp);
+   new_iattrp->attrnxt = NULL;
+   if (new_iattrhd == NULL) new_iattrhd = new_iattrp;
+   else new_iattrend->attrnxt = new_iattrp;
+   new_iattrend = new_iattrp;
+nxt_mod_attr:;
+  }
+ /* possible for all to be duplicated so none to add */
+ if (iattr_end != NULL && new_iattrhd != NULL)
+  iattr_end->attrnxt = new_iattrhd;
+}
+
+/*
+ * build expr table from named param list
+ *
+ * know instance has pound param(s) or routine not called 
+ * list needed because must be able to index pound parameters when building
+ * arrays of instance 
+ *
+ * this assumes module pound params converted to table from list
+ * happens just before cell rep to inst for each module
+ *
+ * when routine done no longer need nqc_u union (i.e. done with npi)
+ */
+static struct expr_t **inst_nparms_to_xtab(struct namparam_t *npmphdr,
+ struct inst_t *ip)
+{
+ int32 all_named;
+ struct expr_t **npxtab;
+
+ /* new explicitly named form */
+ if (pndparams_explicit(npmphdr, &all_named))
+  {
+   if (!all_named)
+    {
+     __gferr(829, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+      "mixed implicit and explicit # parameters illegal for instance %s",
+      ip->isym->synam);
+     __free_namedparams(npmphdr);
+     return(NULL);
+    }
+   npxtab = match_namparam_exprtab(npmphdr, ip);
+   if (npxtab != NULL) ip->pprm_explicit = TRUE;
+  }
+ else
+  {
+   /* old unnamed list - but ,, allowed and becomes nil (no param) */
+   npxtab = match_implprm_exprtab(npmphdr, ip);
+  }
+ __free_namedparams(npmphdr);
+ return(npxtab);
+} 
+
+/*
+ * routine to build inst param expr table from named param list
+ *
+ * by here module definition pound parameters converted to table
+ * param nu2 field union member npi used here as temp, can reuse after here 
+ */
+static struct expr_t **match_namparam_exprtab(struct namparam_t *npmphdr,
+ struct inst_t *ip)
+{
+ register int32 pi;
+ register struct namparam_t *npmp;
+ struct mod_t *mdp;
+ struct net_t *np, **prmtab;
+ struct expr_t **npxtab;
+ struct sy_t *syp;
+ char s1[2*IDLEN];
+
+ sprintf(s1, "instance %s", ip->isym->synam); 
+
+ mdp = ip->imsym->el.emdp;
+ if (mdp->mprmnum == 0)
+  {
+   __gferr(865, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+    "%s has explicit pound parameters but none declared in module %s",
+    s1, mdp->msym->synam);
+   return(NULL);
+  }
+
+ /* build sorted by name param declaration list */
+ prmtab = (struct net_t **) __my_malloc(mdp->mprmnum*sizeof(struct net_t *));
+ for (pi = 0; pi < mdp->mprmnum; pi++)
+  {
+   prmtab[pi] = &(mdp->mprms[pi]);
+   /* need original ndx of param (net) in table so can set after sorting */
+   prmtab[pi]->nu2.npi = pi;
+  }
+ qsort((char *) prmtab, (word32) mdp->mprmnum, sizeof(struct net_t *),
+  prmtab_cmp); 
+ /* allocate inst named param expr ptr table and set to unuused (ni) */
+ npxtab = (struct expr_t **) __my_malloc(mdp->mprmnum*sizeof(struct expr_t *));
+ for (pi = 0; pi < mdp->mprmnum; pi++) npxtab[pi] = NULL;
+
+ for (npmp = npmphdr, pi = 0; npmp != NULL; npmp = npmp->nprmnxt, pi++)
+  {
+   /* DBG remove --- */
+   if (npmp->pnam == NULL) __misc_terr(__FILE__, __LINE__); 
+   /* --- */
+   
+   syp = __zget_sym(npmp->pnam, mdp->msymtab->stsyms, mdp->msymtab->numsyms);
+   if (syp == NULL || syp->sytyp != SYM_N)
+    {
+undcl_param:
+     __gferr(865, npmp->prmfnam_ind, npmp->prmlin_cnt,
+      "%s explicit pound parameter %s (pos. %d) not a declared parameter",
+      s1, npmp->pnam, pi);
+     /* if no declared parameters, always continue here */
+     continue; 
+    }
+   np = syp->el.enp;
+   if (!np->n_isaparam || np->nu.ct->p_specparam) goto undcl_param;
+
+   if (npxtab[np->nu2.npi] != NULL)
+    {
+     __gferr(935, npmp->prmfnam_ind, npmp->prmlin_cnt,
+      "%s explicit pound parameter %s (pos. %d) repeated (declared pos. %d)",
+      s1, npmp->pnam, pi, np->nu2.npi);
+     continue;
+    }
+   /* empty .[pnam]() form legal and becomes nil with warning */
+   if (npmp->pxndp->optyp == OPEMPTY)
+    {
+     __gfwarn(545, npmp->prmfnam_ind, npmp->prmlin_cnt,
+      "%s explicit pound parameter %s expression empty (pos. %d) - no pound override",
+      s1, npmp->pnam, pi);
+     continue;
+    }
+   /* on error (returns F), leave location in npx tab nil */
+   if (chk1_pndparam(s1, ip, npmp, pi, np->nu2.npi))
+    {
+     npxtab[np->nu2.npi] = npmp->pxndp;
+     /* this needed to prevent freeing when namparams freed */
+     npmp->pxndp = NULL;
+    }
+  }
+ /* if all are errors - i.e. table or none decled still empty return nil */
+ for (pi = 0; pi < mdp->mprmnum; pi++)
+  { if (npxtab[pi] != NULL) goto some_good; }
+ return(NULL);
+
+some_good:
+ return(npxtab);
+}
+
+/*
+ * compare for sort of table of ptrs order module parameter table
+ */
+static int32 prmtab_cmp(const void *np1, const void *np2)
+{
+ return(strcmp((*((struct net_t **) np1))->nsym->synam,
+ ((*(struct net_t **) np2))->nsym->synam));
+}
+
+/*
+ * check one pound param to make sure parameter constant expression
+ *
+ * if error, return -1 so caller does not add to ipx table
+ * folding done later
+ */
+static int32 chk1_pndparam(char *s1, struct inst_t *ip, struct namparam_t *npmp,
+ int32 pi, int32 npi)
+{
+ int32 rv, sav_sfnam_ind, sav_slin_cnt;
+ struct mod_t *imdp;
+ struct net_t *parm_np;
+
+ /* SJM 10/01/99 - improve error location for param checking */
+ /* chk param expr needs sim locations set - set temporary guess here */
+ sav_sfnam_ind = __sfnam_ind;
+ sav_slin_cnt = __slin_cnt;
+ __sfnam_ind = npmp->prmfnam_ind;
+ __slin_cnt = npmp->prmlin_cnt;
+ 
+ imdp = ip->imsym->el.emdp;
+ parm_np = &(imdp->mprms[npi]);
+
+ /* notice must check #(parms) rhs here since can be any parameter*/
+ /* even one defined later in source according to LRM */
+ if (!__chk_paramexpr(npmp->pxndp, 0))
+  {
+   __sgferr(753,
+    "%s pound parameter %s (pos. %d) expression %s only parameters and constants - is parameter from other module?",
+    s1, parm_np->nsym->synam, pi, __msgexpr_tostr(__xs, npmp->pxndp));
+   rv = FALSE;
+  }
+ else rv = TRUE;
+
+ __sfnam_ind = sav_sfnam_ind;
+ __slin_cnt = sav_slin_cnt;
+ return(rv);
+}
+
+/*
+ * routine to build inst param expr table from implicit unnamed # param list
+ *
+ * no error possible here
+ */
+static struct expr_t **match_implprm_exprtab(struct namparam_t *npmphdr,
+ struct inst_t *ip)
+{
+ register int32 pi;
+ register struct namparam_t *npmp;
+ struct mod_t *mdp;
+ struct expr_t **npxtab;
+ char s1[2*IDLEN];
+
+ /* can never see connector parameters here */
+ sprintf(s1, "instance %s", ip->isym->synam); 
+
+ mdp = ip->imsym->el.emdp;
+ /* FIXME - SJM 06/01/99 - if syntax error and no mod params */
+ /* was wrongly allocating 0 size array here */
+ /* notice 1 bit enough since once malloced exits pound param loop */
+ if (mdp->mprmnum == 0)
+  {
+   npxtab = (struct expr_t **) __my_malloc(1*sizeof(struct expr_t *));
+   npxtab[0] = NULL;
+  }
+ else
+  {
+   /* allocate inst named param expr ptr table and set to unuused (ni) */
+   npxtab = (struct expr_t **)
+    __my_malloc(mdp->mprmnum*sizeof(struct expr_t *));
+  }
+ for (pi = 0; pi < mdp->mprmnum; pi++) npxtab[pi] = NULL;
+
+ /* unnamed so must match by position */
+ for (npmp = npmphdr, pi = 0; npmp != NULL; npmp = npmp->nprmnxt, pi++)
+  {
+   /* too few ok, but too many is error */
+   if (pi >= mdp->mprmnum) 
+    {
+     /* need to count all in list */
+     for (; npmp != NULL; npmp = npmp->nprmnxt) pi++;
+
+     __gferr(752, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+      "%s # parameter list too long (%d) - only %d parameters declared",
+      s1, pi, mdp->mprmnum); 
+     break;
+    }
+   /* because now translating like ports allowing ,, that become nil */
+   if (npmp->pxndp->optyp == OPEMPTY) continue;
+   if (chk1_pndparam(s1, ip, npmp, pi, pi))
+    {
+     npxtab[pi] = npmp->pxndp;
+     npmp->pxndp = NULL;
+    }
+  }
+ /* if list short, tail will be correctly nil but need inform */
+ if (pi < mdp->mprmnum)
+  {
+   __gfinform(408, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+    "%s only first %d of %d pound parameters set", s1, pi + 1, mdp->mprmnum);
+  }
+ return(npxtab); 
+}
+
+/*
+ * ROUTINES TO ANALYZE INSTANTIATION CONNECTIVITY STRUCTURE
+ */
+
+/*
+ * rearrange and build module and inst. connections for further processing
+ * also set dag levels and connect inst. pins to module ports
+ *
+ * parameter values still unknown but this builds global strength anal. and
+ * splitting info
+ */
+static int32 fix_modcell_nl(void)
+{
+ register struct mod_t *mdp;
+
+ /* first need to know static instantiations */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   /* F for self instantiation and cannot continue */
+   if (!count_static_instances(mdp)) return(TRUE);
+
+   __pop_wrkitstk();
+  }
+
+ /* set dag levels */
+ if (!chk_dag()) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * distinguish number of times module statically instantiated
+ * 0 means top, 1 exactly once, 2 more than once
+ * value here is static unflattened number of instantiations
+ */
+static int32 count_static_instances(struct mod_t *mdp)
+{
+ register int32 ii; 
+ register struct inst_t *ip;
+ struct sy_t *syp;
+ struct mod_t *imdp;
+
+ for (ii = 0; ii < mdp->minum; ii++)
+  {
+   ip = &(mdp->minsts[ii]);
+   syp = ip->imsym;
+   imdp = syp->el.emdp;
+   if (mdp == imdp)
+    __gfterr(312, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+     "INTERNAL - module instantiates itself");
+   /* only need counts of 0 (never), 1 (exactly once), 2 (more than once) */
+   if (imdp->minstnum == 0) imdp->minstnum = 1;
+   else if (imdp->minstnum == 1) imdp->minstnum = 2;
+  }
+ return(TRUE);
+}
+
+/*
+ * check to see if any instantiation loops and set levelized level
+ * for multiple instantiations level is level of lowest one
+ */
+static int32 chk_dag(void)
+{
+ register int32 ii;
+ register struct mod_t *mdp;
+ int32 i, change, allmark;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+
+ __dagmaxdist = 0;
+ /* previously initialized to -1 (unmarked) */
+ for (allmark = TRUE, mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->minsts == NULL) mdp->mlpcnt = 0;
+   else allmark = FALSE;
+  }
+ if (allmark) return(TRUE);
+ /* level 0 means no contained instances, mark all level i modules */
+ for (i = 1; i < MAXCIRDPTH; i++)
+  {
+   change = FALSE;
+   /* assume all marked */
+   allmark = TRUE;
+   for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+    {
+     /* if marked nothing to do */
+     if (mdp->mlpcnt != -1) continue;
+
+     for (ii = 0; ii < mdp->minum; ii++)
+      {
+       ip = &(mdp->minsts[ii]);
+       imdp = ip->imsym->el.emdp;
+       /* cannot mark if unmarked or mark this time == i */
+       if (imdp->mlpcnt == -1 || imdp->mlpcnt == i)
+	{
+         /* ---
+	 if (__debug_flg)
+          {
+  	   __dbg_msg("++at level %d cannot mark %s because of %s\n", i,
+	     mdp->msym->synam, imdp->msym->synam);
+          }
+         ---- */
+ 	 goto cannot_mark;
+	}
+      }
+     mdp->mlpcnt = i;
+     /* ---
+     if (__debug_flg)
+      __dbg_msg("++at level %d marking %s\n", i, mdp->msym->synam);
+     --- */
+     change = TRUE;
+     continue;
+
+cannot_mark:
+     allmark = FALSE;
+    }
+   if (allmark) { __dagmaxdist = i; return(TRUE); }
+   if (!change) break;
+  }
+ __pv_err(735,
+  "design contains indirect (length > 1) self instantiation loop");
+ return(FALSE);
+}
+
+/*
+ * ROUTINES TO CONNECT PORTS
+ */
+
+/*
+ * check module ports and make instance connections
+ * handles implicit and explicit form port matching
+ */
+static void fix_port_conns(void)
+{
+ register struct mod_t *mdp;
+
+ /* set implicit module port form names and I/O directions */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   setchk_modports();
+   __pop_wrkitstk();
+  }
+
+ /* connect module ports and change to instance port expr. list */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   conn_mod_insts();
+   __pop_wrkitstk();
+  }
+
+ /* finally can free any sorted work mod port pointer arrays */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->smpins == NULL) continue;
+   __my_free((char *) mdp->smpins, mdp->mpnum*sizeof(struct srtmp_t));
+   mdp->smpins = NULL;
+  }
+}
+
+/*
+ * set and check module header port connections
+ * needed because .[port]([expr]), legal, unnamed ports legal, and
+ * repeated nets legal
+ *
+ * since wire width not known yet, structural checking here only, widths
+ * set and checked later
+ */
+static void setchk_modports(void)
+{
+ register int32 pi;
+ register struct mod_pin_t *mpp;
+ int32 pnum, port_gd;
+
+ if ((pnum = __inst_mod->mpnum) == 0) return;
+ for (pi = 0; pi < pnum; pi++)
+  {
+   mpp = &(__inst_mod->mpins[pi]);
+   __pr_iodir = IO_UNKN;
+   port_gd = chk_prtref(mpp->mpref, mpp, TRUE);
+   mpp->mptyp = __pr_iodir;
+
+   /* notice empty and concatenate port lists remain unnamed */
+   if (port_gd)
+    {
+     /* SJM 08/23/00 - now OPEMPTY ports also legal and unnamed */
+     if (mpp->mpsnam == NULL && mpp->mpref->optyp != LCB
+      && mpp->mpref->optyp != OPEMPTY)
+      {
+       if (mpp->mpref->optyp == ID) mpp->mpsnam = mpp->mpref->lu.sy->synam;
+       else mpp->mpsnam = mpp->mpref->lu.x->lu.sy->synam;
+      }
+    }
+   else
+    {
+     __free_xtree(mpp->mpref);
+     __bld_unc_expr();
+     mpp->mpref = __root_ndp;
+    }
+  }
+}
+
+/*
+ * check a module port def. expression to make sure it is a prtref
+ * return F on error else T
+ * prtref is lhs value or concatenate (including nested) of port refs.
+ * also checks and sets I/O direction
+ * this is called before wire and port ranges known
+ */
+static int32 chk_prtref(struct expr_t *ndp, struct mod_pin_t *mpp,
+ int32 is_top)
+{
+ struct net_t *np;
+ struct expr_t *idndp;
+ char s1[RECLEN], s2[RECLEN];
+
+ switch ((byte) ndp->optyp) {
+  case GLBREF:
+bad_prtglb:
+   __gferr(736, mpp->mpfnam_ind, mpp->mplin_cnt,
+    "module header list of ports hierarchical path reference %s illegal",
+     ndp->ru.grp->gnam);
+   return(FALSE);
+  case ID:
+   /* when ID appears in mod. def. port header, converted to undecl net */ 
+   np = ndp->lu.sy->el.enp;
+   idndp = ndp;
+chk_dir:
+   if (!idndp->lu.sy->sydecl)
+    {
+     __gferr(737, mpp->mpfnam_ind, mpp->mplin_cnt,
+      "I/O port %s required direction declaration missing", np->nsym->synam);
+     return(FALSE);
+    }
+   if (np->iotyp == NON_IO)
+    {
+     __gferr(738, mpp->mpfnam_ind, mpp->mplin_cnt,
+      "module header list of ports %s %s must be I/O port",
+       __to_wtnam(s1, np), np->nsym->synam);
+     return(FALSE);
+    }
+   if (__pr_iodir == IO_UNKN) __pr_iodir = np->iotyp;
+   else if (__pr_iodir != np->iotyp)
+    {
+     __gferr(739, mpp->mpfnam_ind, mpp->mplin_cnt,
+     "module header list of ports %s wire %s has conflicting %s port type",
+      __to_ptnam(s1, np->iotyp), np->nsym->synam, __to_ptnam(s2, __pr_iodir));
+     return(FALSE);
+    }
+   /* count times wire repeated in port list */
+   if (np->nu.ct->num_prtconns != 2 && is_top) np->nu.ct->num_prtconns += 1;
+
+   /* notice in and inout ports must be wires but out can be reg */
+   if (!chk_prtntyp(mpp, np)) return(FALSE);
+   break;
+  case PARTSEL:
+   /* since check module port syntax before splitting, mark params that */
+   /* can effect expr. width here to later possibly cause split not IS form */
+   __in_xpr_markparam(ndp->ru.x->lu.x);
+   __in_xpr_markparam(ndp->ru.x->ru.x);
+   /* FALLTHRU */
+  case LSB:
+   if (ndp->lu.x->optyp == GLBREF) goto bad_prtglb;
+   idndp = ndp->lu.x;
+   np = idndp->lu.sy->el.enp;
+   /* inout port expr. may need to go in tran channel so can't be IS form */
+   if (np->iotyp == IO_BID) __in_xpr_markparam(ndp->ru.x);
+   goto chk_dir;
+  case LCB:
+   if (!is_top)
+    {
+     __gferr(740, mpp->mpfnam_ind, mpp->mplin_cnt,
+      "module header list of ports nested concatenate illegal");
+     return(FALSE);
+    }
+   {
+    register struct expr_t *ndp2;
+
+    /* ndp2 left can still be nested concatenate by here */
+    /* but can find rep. number */
+    for (ndp2 = ndp->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     {
+      /* check I/O direction from subcomponents one down */
+      /* also check for incorrect reg one down */
+      if (!chk_prtref(ndp2->lu.x, mpp, FALSE)) return(FALSE);
+     }
+   }
+   break;
+  case CATREP:
+   __gferr(741, mpp->mpfnam_ind, mpp->mplin_cnt,
+    "module header list of ports port ref. concatenate repeat form illegal");
+   return(FALSE);
+  case OPEMPTY:
+   break;
+  default:
+   __gferr(742, mpp->mpfnam_ind, mpp->mplin_cnt,
+    "%s illegal module header list of ports port reference",
+    __msgexpr_tostr(__xs, ndp));
+   return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * check a port wire to make sure net type legal
+ */
+static int32 chk_prtntyp(struct mod_pin_t *mpp, struct net_t *np)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ if (np->iotyp == IO_OUT)
+  {
+   if (np->ntyp == N_REAL)
+    {
+     __gferr(743, mpp->mpfnam_ind, mpp->mplin_cnt,
+      "%s port %s type real illegal", __to_ptnam(__xs, np->iotyp),
+      np->nsym->synam);
+     return(FALSE);
+    }
+  }
+ else
+  {
+   if (np->ntyp >= NONWIRE_ST)
+    {
+     __gferr(744, mpp->mpfnam_ind, mpp->mplin_cnt,
+      "%s port %s of net type %s illegal - must be a wire",
+       __to_ptnam(s1, np->iotyp), np->nsym->synam, __to_wtnam(s2, np));
+     return(FALSE);
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * check/connect cell pins to defined down one module
+ * no processing of gates here
+ */
+static void conn_mod_insts(void)
+{
+ register int32 ii;
+ register struct cell_pin_t *cpp;
+ int32 nbytes;
+ struct inst_t *ip;
+ struct sy_t *syp;
+ struct mod_t *imdp;
+ struct expr_t **xphdr;
+ struct srcloc_t *srcloc;
+
+ if (__inst_mod->minum == 0) return;
+ 
+ /* allocate the || to minsts per contained inst pin src loc table */  
+ nbytes = __inst_mod->minum*sizeof(struct srcloc_t *);
+ __inst_mod->iploctab = (struct srcloc_t **) __my_malloc(nbytes);
+
+ for (ii = 0; ii < __inst_mod->minum; ii++)
+  {
+   ip = &(__inst_mod->minsts[ii]);
+   syp = ip->imsym;
+   /* module instance declaration info lost */
+   if (!syp->sydecl)
+    __misc_gfterr(__FILE__, __LINE__, ip->isym->syfnam_ind,
+     ip->isym->sylin_cnt);
+   imdp = ip->imsym->el.emdp;
+
+   /* instance must contain at least () which will cause 1 unc. pin */
+   cpp = (struct cell_pin_t *) ip->ipins;
+   /* DBG remove --- */
+   /* know there will be at least one pin if no error */
+   if (cpp == NULL && imdp->mpnum != 0)
+    {
+     if (__pv_err_cnt == 0) __misc_terr(__FILE__, __LINE__); else continue;
+    }
+   /* --- */
+
+   /* allocate new expression table */
+   /* special case of module with no ports instantiated as () */
+   /* it will have one unc. port - legal for 1 port case */
+   /* but since no module ports this special port must be thrown away */
+   if (imdp->mpnum == 0)
+    {
+     ip->ipins = NULL;
+     srcloc = NULL;
+     /* only set to NULL if has 1 unc. port - else will be null */
+     /* LOOKATME - not freeing case of one unc. port */  
+     if (cpp == NULL || (cpp->cpnxt == NULL && cpp->cpxnd->optyp == OPEMPTY))
+      goto nxt_cell;
+
+     __gferr(746, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+      "instance %s module type %s has ports but module does not",
+       ip->isym->synam, imdp->msym->synam);
+     goto nxt_cell;
+    }
+   nbytes = imdp->mpnum*sizeof(struct expr_t *);
+   xphdr = (struct expr_t **) __my_malloc(nbytes);
+   nbytes = imdp->mpnum*sizeof(struct srcloc_t);
+   srcloc = (struct srcloc_t *) __my_malloc(nbytes);
+
+   /* allocate cell-pin expression table */
+   /* all implicit connection case */
+   if (cpp->pnam == NULL) conn_impl_mports(ip, cpp, imdp, xphdr, srcloc);
+   /* all explicit connection case */
+   else conn_expl_mports(ip, cpp, imdp, xphdr, srcloc);
+   ip->ipins = xphdr;
+
+nxt_cell:
+
+   /* must connect to current mod since need port locs for expr check */
+   /* since parallel to insts, for insts. with no cell pin list will be nil */ 
+   __inst_mod->iploctab[ii] = srcloc;
+  }
+}
+
+/*
+ * connect implicit instance ports
+ * mdp is instance module type
+ * various checking goes here
+ * ,, form here already made appropriate unc. 
+ * 
+ * know module port num at least one or not called 
+ */
+static void conn_impl_mports(struct inst_t *ip, struct cell_pin_t *cpp,
+ struct mod_t *mdp, struct expr_t **xphdr, struct srcloc_t *srclocp)
+{
+ register int32 pi;
+ struct cell_pin_t *last_cpp;
+ int32 pnum, num_unc_ports;
+
+ ip->ip_explicit = FALSE;
+ pnum = mdp->mpnum;
+ num_unc_ports = 0;
+ for (pi = 0; pi < pnum;)
+  {
+   if (cpp->pnam != NULL)
+    {
+     __gferr(747, cpp->cpfnam_ind, cpp->cplin_cnt,
+     "%s(%s) explicit port %s (pos. %d) mixed in implicit connection list",
+      ip->isym->synam, ip->imsym->synam, cpp->pnam, pi + 1);
+    }
+   /* SJM 11/13/00 - now also emit warning if ,, unc. form in implicit list */
+   if (cpp->cpxnd->optyp == OPEMPTY) num_unc_ports++;
+   xphdr[pi] = cpp->cpxnd;
+   /* here implicit means port in order def. i and inst i same */ 
+   srclocp[pi].sl_fnam_ind = cpp->cpfnam_ind;
+   srclocp[pi].sl_lin_cnt = cpp->cplin_cnt;
+   last_cpp = cpp;
+   if ((cpp = cpp->cpnxt) == NULL && pi < pnum - 1) goto too_few;
+   pi++;
+  }
+ if (cpp != NULL)
+  {
+   __gferr(748, cpp->cpfnam_ind, cpp->cplin_cnt,
+    "%s(%s) implicit connection list more ports than type with %d",
+    ip->isym->synam, ip->imsym->synam, pnum);
+  }
+ if (num_unc_ports > 0)
+  {
+   __gfwarn(531, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+    "%s(%s) implicit connection list fewer ports %d connected than type's %d",
+    ip->isym->synam, ip->imsym->synam, pnum - num_unc_ports, pnum);
+  }
+ return;
+
+too_few:
+ pi++;
+ /* warn because ,,s should be included */
+  {
+   __gfwarn(531, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+    "%s(%s) implicit connection list fewer ports %d in list than type's %d",
+    ip->isym->synam, ip->imsym->synam, pi, pnum);
+  }
+ for (; pi < pnum; pi++)
+  {
+   __bld_unc_expr(); 
+   xphdr[pi] = __root_ndp;
+   /* for missing use last or if no conn use isym loc. */
+   if (last_cpp == NULL)
+    {
+     srclocp[pi].sl_fnam_ind = ip->isym->syfnam_ind;
+     srclocp[pi].sl_lin_cnt = ip->isym->sylin_cnt;
+    }
+   else
+    {
+     srclocp[pi].sl_fnam_ind = last_cpp->cpfnam_ind;
+     srclocp[pi].sl_lin_cnt = last_cpp->cplin_cnt;
+    }
+  }
+}
+
+/*
+ * connect explicit instance connection form ports
+ *
+ * builds ipins table (of prts to exprs) size is always num mod ports
+ * even if some unconnected (will be unc. expr)
+ *
+ * know module port num at least one or not called 
+ */
+static void conn_expl_mports(struct inst_t *ip, struct cell_pin_t *cpp,
+ struct mod_t *imdp, struct expr_t **xphdr, struct srcloc_t *srclocp)
+{
+ register int32 pi, mpi;
+ register int32 cpnum, pnum;
+ register int32 cv;
+ int32 num_unc_ports;
+ struct cell_pin_t **srtcptab;
+ struct srtmp_t *srtmptab;
+ struct cell_pin_t *scpp;
+ struct srtmp_t *smpp;
+
+ ip->ip_explicit = TRUE;
+ /* if module has unnamed ports, cannot continue */
+ if (!chk_mdports_named(ip, imdp, xphdr)) return;
+
+ /* if no sorted port list for this module type, build one */
+ if (imdp->smpins == NULL) bld_srted_mdpins(imdp);
+ srtmptab = imdp->smpins;
+
+ /* build the sorted cell pin table for instance */
+ pnum = imdp->mpnum; 
+ for (scpp = cpp, cpnum = 0; scpp != NULL; scpp = scpp->cpnxt) cpnum++;
+ srtcptab = (struct cell_pin_t **)
+  __my_malloc(cpnum*sizeof(struct cell_pin_t *));
+ if (!bld_srted_ipins(ip, cpp, cpnum, srtcptab)) goto free_pin_tab;
+
+ pi = 0; scpp = srtcptab[0];
+ mpi = 0; smpp = &(srtmptab[0]);
+ /* know both lists sorted so move through */
+ /* if past end of either done - if no match, left as nil, made unc. */ 
+ for (; pi < cpnum && mpi < pnum;)
+  {
+   /* scpp is cell (inst.) port and smpp is module port */
+   if ((cv = strcmp(scpp->pnam, smpp->smp->mpsnam)) == 0)
+    {
+     xphdr[smpp->mppos] = scpp->cpxnd;
+     /* index here is type def. order, def. i line no. if for i conn. */ 
+     srclocp[smpp->mppos].sl_fnam_ind = scpp->cpfnam_ind; 
+     srclocp[smpp->mppos].sl_lin_cnt = scpp->cplin_cnt;
+     /* if at end of instance ports, done */
+     pi++; if (pi < cpnum) scpp = srtcptab[pi];
+     mpi++; if (mpi < pnum) smpp = &(srtmptab[mpi]);
+     continue;
+    }
+   /* module instance port extra or repeated - fits between type ports */
+   /* cell port alphabetically less than module port - is non mod port */
+   /* becasue both sorted - if repeated, moved to next mod port so same */
+   /* cell port now less than */
+   if (cv < 0)
+    {
+     if (pi > 0 && strcmp(srtcptab[pi - 1]->pnam, scpp->pnam) == 0) 
+      {
+       __gferr(745, scpp->cpfnam_ind, scpp->cplin_cnt,
+        "%s(%s) explicit connection port %s repeated",
+        ip->isym->synam, imdp->msym->synam, scpp->pnam);
+      } 
+     else __gferr(749, scpp->cpfnam_ind, scpp->cplin_cnt,
+      "%s(%s) explicit connection port %s is not a module port",
+      ip->isym->synam, imdp->msym->synam, scpp->pnam);
+     pi++;
+     if (pi < cpnum) scpp = srtcptab[pi];
+     continue;
+    }
+   /* cell port alphabetically greater than module port */
+   /* module type port is extra (unc.) - fits between module inst ports */
+   mpi++; if (mpi < pnum) smpp = &(srtmptab[mpi]);
+  }
+ /* if more cell ports, know are non port - emit error */
+ for (; pi < cpnum; pi++)
+  {
+   scpp = srtcptab[pi];
+   __gferr(749, scpp->cpfnam_ind, scpp->cplin_cnt,
+    "%s(%s) explicit connection port %s is not a module port",
+    ip->isym->synam, imdp->msym->synam, scpp->pnam);
+  }  
+free_pin_tab:
+ __my_free((char *) srtcptab, cpnum*sizeof(struct cell_pin_t *));
+ srtcptab = NULL;
+
+ /* for all unc. (NULL) expressions convert to real unconnected */
+ num_unc_ports = 0;
+ for (pi = 0; pi < pnum; pi++)
+  {
+   if (xphdr[pi] == NULL)
+    {
+     __bld_unc_expr();
+     xphdr[pi] = __root_ndp;
+     /* use instance location for these */
+     srclocp[pi].sl_fnam_ind = ip->isym->syfnam_ind; 
+     srclocp[pi].sl_lin_cnt = ip->isym->sylin_cnt;
+     num_unc_ports++;
+    }
+  }
+ if (num_unc_ports > 0)
+  {
+   __gfwarn(531, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+    "%s(%s) explicit connection list fewer ports %d connected than type's %d",
+    ip->isym->synam, ip->imsym->synam, pnum - num_unc_ports, pnum);
+  }
+}
+
+/*
+ * check to make sure for explicit instance form all module ports named 
+ * also initialized instance port expression table to NULL
+ * only called for explicit conn. instances
+ */
+static int32 chk_mdports_named(struct inst_t *ip,
+ struct mod_t *mdp, struct expr_t **xphdr)
+{
+ register int32 pi;
+ register struct mod_pin_t *mpp;
+ int32 pnum, __err_seen;
+
+ if ((pnum = mdp->mpnum) == 0) return(FALSE);
+
+ __err_seen = FALSE;
+ for (pi = 0; pi < pnum; pi++)
+  {
+   mpp = &(mdp->mpins[pi]);
+   if (mpp->mpsnam == NULL)
+    {
+     __gferr(750, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+      "%s(%s) explicit connection form illegal - port %d unnamed",
+     ip->isym->synam, mdp->msym->synam, pi + 1);
+     __err_seen = TRUE;
+    }
+   xphdr[pi] = NULL;
+  }
+ return(!__err_seen);
+}
+
+/*
+ * build sorted table of module ports - once built saved so not rebuilt
+ * each time - freed when port connection phase completed
+ * only called when know all module ports named and at least 1 port
+ */
+static void bld_srted_mdpins(struct mod_t *mdp)
+{
+ register int32 pi; 
+ register struct srtmp_t *smpp;
+ register struct mod_pin_t *mpp;
+ struct srtmp_t *smptab;  
+ int32 pnum;
+
+ pnum = mdp->mpnum;
+ smptab = (struct srtmp_t *) __my_malloc(pnum*sizeof(struct srtmp_t)); 
+ mdp->smpins = smptab;
+ mpp = &(mdp->mpins[0]);
+ for (pi = 0, smpp = &(smptab[0]); pi < pnum; pi++, smpp++, mpp++)
+  {
+   smpp->smp = mpp;
+   smpp->mppos = pi;
+  }
+ qsort((char *) smptab, (word32) pnum, sizeof(struct srtmp_t), smp_cmp); 
+}
+
+/*
+ * module port name comparison routine
+ */
+static int32 smp_cmp(const void *srp1, const void *srp2)
+{
+ return(strcmp(((struct srtmp_t *) srp1)->smp->mpsnam,
+ ((struct srtmp_t *) srp2)->smp->mpsnam));
+}
+
+/*
+ * build sorted table of instance ports
+ * built for each explicitly connected instance
+ * free when instance connections made
+ */
+static int32 bld_srted_ipins(struct inst_t *ip,
+ register struct cell_pin_t *cpp, int32 pnum, struct cell_pin_t **scptab)
+{
+ register int32 pi; 
+ register struct cell_pin_t *cpp2;
+ char *chp;
+
+ for (pi = 0; pi < pnum; pi++, cpp = cpp->cpnxt)
+  {
+   if (cpp->pnam == NULL)
+    {
+     __gferr(751, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+      "%s(%s) explicit connection list but port connection %d is implicit",
+      ip->isym->synam, ip->imsym->synam, pi + 1);
+     return(FALSE);
+    }
+   scptab[pi] = cpp;
+  }
+ qsort((char *) scptab, (word32) pnum, sizeof(struct cell_pin_t *), cpn_cmp); 
+
+ /* must check for duplicate of same name since illegal */
+ /* LOOKATME - think none impossible but doing nothing is right if happens */ 
+ if (pnum <= 0) return(TRUE);
+
+ chp = scptab[0]->pnam; 
+ for (pi = 1; pi < pnum; pi++)
+  {
+   cpp2 = scptab[pi];
+   if (strcmp(chp, cpp2->pnam) == 0)
+    {
+     __gferr(1038, cpp2->cpfnam_ind, cpp2->cplin_cnt,
+      "%s(%s) explicit connection list named port %s repeated",
+      ip->isym->synam, ip->imsym->synam, chp);
+    }
+   else chp = scptab[pi]->pnam;
+  }
+ return(TRUE);
+}
+
+/*
+ * module port name comparison routine
+ */
+static int32 cpn_cmp(const void *cpp1, const void *cpp2)
+{
+ return(strcmp((*((struct cell_pin_t **) cpp1))->pnam,
+  (*(struct cell_pin_t **) cpp2)->pnam));
+}
+
+/*
+ * routine to free all allocated ncmp blks when no longed used at all
+ */
+static void free_cpblks(void)
+{
+ register struct cpblk_t *cpbp, *cpbp2;
+
+ /* free all cell pin blks since ncomp form now gone */
+ for (cpbp = __hdr_cpblks; cpbp != NULL;)
+  {
+   cpbp2 = cpbp->cpblknxt;
+   __my_free((char *) cpbp->cpblks, BIG_ALLOC_SIZE);
+   __my_free((char *) cpbp, sizeof(struct cpblk_t));
+   cpbp = cpbp2;
+  }
+}
+
+/*
+ * routine to free all allocated ncmp blks when no longed used at all
+ */
+static void free_cppblks(void)
+{
+ register struct cppblk_t *cppbp, *cppbp2;
+ register struct cpnblk_t *cpnbp, *cpnbp2;
+
+ /* free all cell pin blks since ncomp form now gone */
+ for (cppbp = __hdr_cppblks; cppbp != NULL;)
+  {
+   cppbp2 = cppbp->cppblknxt;
+   __my_free((char *) cppbp->cppblks, BIG_ALLOC_SIZE);
+   __my_free((char *) cppbp, sizeof(struct cppblk_t));
+   cppbp = cppbp2;
+  }
+ for (cpnbp = __hdr_cpnblks; cpnbp != NULL;)
+  {
+   cpnbp2 = cpnbp->cpnblknxt;
+   __my_free((char *) cpnbp->cpnblks, BIG_ALLOC_SIZE);
+   __my_free((char *) cpnbp, sizeof(struct cpnblk_t));
+   cpnbp = cpnbp2;
+  }
+}
+
+/*
+ * set the as if flattended instance counts for all modules
+ * know flat insts initialized to 0 and m insts already counted
+ * this also links every module inst. upward (parent) instance
+ *
+ * count here counts only 1 for each cell array - fixed up later
+ */
+static void count_flat_insts(void)
+{
+ register int32 ii;
+ register struct mod_t *mdp;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+
+ /* must always reinitialize flat count because maybe called multiple times */ 
+ /* i.e. after arrays of instances expanded */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  mdp->flatinum = 0;
+
+ /* inc. count of all instances in each top level module */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* descend to count only from top level modulss */
+   if (mdp->minstnum != 0) continue;
+   mdp->flatinum = 1;
+
+   /* count depth first */
+   for (ii = 0; ii < mdp->minum; ii++)
+    {
+     ip = &(mdp->minsts[ii]);
+     imdp = ip->imsym->el.emdp;
+     imdp->flatinum++;
+
+     /* DBG remove ---
+     if (__debug_flg)
+      {
+       __dbg_msg(
+        "+++ incing count (%d) of inst. %s type %s in top level module %s\n",
+        imdp->flatinum, ip->isym->synam, imdp->msym->synam,
+        __inst_mod->msym->synam);
+      }
+     ---- */ 
+     count2_flat_insts(imdp);
+    }
+  }
+}
+
+/*
+ * traverse 1 down flattened inst. count
+ */
+static void count2_flat_insts(struct mod_t *mdp)
+{
+ register int32 ii;
+ register struct inst_t *ip;
+ struct mod_t *imdp;
+
+ for (ii = 0; ii < mdp->minum; ii++)
+  {
+   ip = &(mdp->minsts[ii]); 
+   imdp = ip->imsym->el.emdp;
+   imdp->flatinum++;
+   /* DBG remove ---
+   if (__debug_flg)
+    { 
+     __dbg_msg("+++ traverse inc count (%d) inst %s type %s in mod %s\n",
+      imdp->flatinum, ip->isym->synam, imdp->msym->synam, mdp->msym->synam);
+    }
+   --- */
+   if (imdp->mlpcnt > 0) count2_flat_insts(imdp);
+  }
+}
+
+/*
+ * ROUTINES TO SPLIT INSTS, REBUILD AND EXPAND FOR GATE/INST ARRAYS 
+ */
+
+/*
+ * split (copy) module types for which pound params used in arrays of
+ * gates or instances declaration width ranges
+ */
+static void do_giarr_splitting(void)
+{
+ register int32 ii, mlevel;
+ register struct mod_t *mdp; 
+ struct inst_t *ip;
+ struct mod_t *imdp;
+
+ /* start will all modules that contain instances only of modules */
+ /* which themselves contain no instances and work upward */ 
+ for (mlevel = 1; mlevel <= __dagmaxdist; mlevel++) 
+  {
+   /* SJM 03/16/04 - notice processing one up and splitting (if needed) */
+   /* contained instances - therefore mlevel of md lev hdr list not chged */
+   /* inside this loop */
+   for (mdp = __mdlevhdr[mlevel]; mdp != NULL; mdp = mdp->mlevnxt)
+    {
+     __push_wrkitstk(mdp, 0);
+     
+     /* go through instances in current module */
+     for (ii = 0; ii < __inst_mod->minum; ii++)
+      {
+       ip = &(__inst_mod->minsts[ii]);
+       if (ip->ipxprtab == NULL) continue;
+
+       /* imdp is module type of instance that has pound params */
+       imdp = ip->imsym->el.emdp;
+       __sfnam_ind = ip->isym->syfnam_ind;
+       __slin_cnt = ip->isym->sylin_cnt;
+
+       /* because static src inst loc. has pnd params, if any gate must */
+       /* try to set any gate range params */
+       /* AIV 07/12/04 - old checking and was wrong nad mark gia rng checks */
+       if (!imdp->mgiarngdone)
+        {
+         mark_gia_rng_params(imdp);
+         imdp->mgiarngdone = TRUE;
+        }
+
+       /* eliminate if instance not arrayed at this src loc. */ 
+       if (__inst_mod->miarr == NULL || __inst_mod->miarr[ii] == NULL)
+        continue;
+
+       /* mark parameters used in gi array ranges exprs once for each mod */
+       if (!imdp->mgiarngdone)
+        { mark_gia_rng_params(imdp); imdp->mgiarngdone = TRUE; }
+
+       if (!down_hasgiarngdet_param(imdp)) continue;
+
+       /* even if no split (one place in source instantiated) need to eval */ 
+       /* mark that some modules have width determining pnd params and mark */
+       /* that this one does */
+       ip->imsym->el.emdp->mpndprm_ingirng = TRUE;
+
+       /* if only one place in source instantiated, must not split */
+       /* because would create never instantiated instance */
+       if (imdp->flatinum == 1 || imdp->flatinum == __inst_mod->flatinum)
+        continue; 
+
+       /* this does not need to update miarr since parallel minsts updated */
+       split_upd_mod(imdp, ip, mlevel); 
+      }
+     __pop_wrkitstk();
+    }
+  }
+}
+
+/*
+ * mark all parameters that are used in arrays of gate/inst ranges
+ * inside module pmdp
+ *
+ * splitting later only if these parameters are passed as pound params
+ * caller will mark module 
+ */
+static void mark_gia_rng_params(struct mod_t *pmdp)
+{
+ register int32 gi, ii;
+ struct giarr_t *giap;
+
+ if (pmdp->mgarr != NULL)
+  {
+   for (gi = 0; gi < pmdp->mgnum; gi++)
+    {
+     if ((giap = pmdp->mgarr[gi]) == NULL) continue;
+
+     if (in_giarng_markparam(giap, giap->giax1))
+      pmdp->mpndprm_ingirng = TRUE;
+     if (in_giarng_markparam(giap, giap->giax2))
+      pmdp->mpndprm_ingirng = TRUE;
+    }
+  }
+  
+ if (pmdp->miarr != NULL)
+  {
+   for (ii = 0; ii < pmdp->minum; ii++)
+    {
+     if ((giap = pmdp->miarr[ii]) == NULL) continue;
+
+     if (in_giarng_markparam(giap, giap->giax1))
+      pmdp->mpndprm_ingirng = TRUE;
+     if (in_giarng_markparam(giap, giap->giax2))
+      pmdp->mpndprm_ingirng = TRUE;
+    }
+  }
+}
+
+/*
+ * mark parmeters (nets) in arrays of gate/inst range parameters
+ *
+ * only called for expressions in gate/inst range indices
+ */
+static int32 in_giarng_markparam(struct giarr_t *giap, struct expr_t *xp)
+{
+ int32 rv1, rv2;
+ struct net_t *np;
+
+ rv1 = rv2 = FALSE;
+ if (__isleaf(xp))
+  {
+   if (xp->optyp == ID && xp->lu.sy->sytyp == SYM_N)
+    {
+     np = xp->lu.sy->el.enp; 
+     if (np->n_isaparam)
+      {
+       np->nu.ct->n_in_giarr_rng = TRUE;
+       giap->gia_rng_has_pnd = TRUE;
+       __design_gia_pndparams = TRUE;
+       rv1 = TRUE; 
+      }
+    }
+   return(rv1);
+  }
+ if (xp->lu.x != NULL) rv1 = in_giarng_markparam(giap, xp->lu.x);
+ if (xp->ru.x != NULL) rv2 = in_giarng_markparam(giap, xp->ru.x);
+ return(rv1 || rv2);
+}
+
+/*
+ * return T if any down instance (module type ipmdp) pound parameter
+ * determines array of gates or instances range
+ */
+static int32 down_hasgiarngdet_param(struct mod_t *ipmdp)
+{
+ register int32 pi;
+ struct net_t *parm_np;
+ 
+ /* if # param list short ok, do not bother changing missing at end */
+ /* only check params actually set if short list */
+ for (pi = 0; pi < ipmdp->mprmnum; pi++)
+  {
+   parm_np = &(ipmdp->mprms[pi]);
+
+   if (parm_np->nu.ct->n_in_giarr_rng)
+    {
+     if (__debug_flg)
+      {
+       __dbg_msg(
+        "+++ split module %s, # param %s in array of inst/gate range expr.\n",
+        ipmdp->msym->synam, parm_np->nsym->synam);
+      }
+     return(TRUE);
+    }
+   /* move to next target module pound param */
+  }
+ if (__debug_flg)
+  __dbg_msg(
+   "+++ no need to split module %s because of pound param in gate/inst range",
+   ipmdp->msym->synam);
+ return(FALSE);
+} 
+
+/*
+ * ROUTINES TO BUILD TOP VIRTUAL INSTANCES
+ */
+
+/*
+ * build the list of instances for uninstantiated top level modules
+ * this builds inst_t (static inst) for each top level modules
+ * and makes top itab of index point to it
+ *
+ * notice top module may be split, so this new elements can be added later
+ *
+ * top_iptab points to created instances since for top module and instance
+ * have same name - top_iptab and it_roots are parallel arrays, top_ipind 
+ * ins sorted index into both top_iptab and it_roots since they are ||
+ *
+ */
+static void bld_top_virtinsts(void)
+{
+ register int32 tpii;
+ register struct mod_t *mdp;
+ int32 ii;
+ struct inst_t *ip;
+ struct sy_t *syp;
+ struct itree_t *itp;
+
+ /* count number of top level modules */ 
+ __numtopm = 0;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* descend to count only from top level modules */
+   if (mdp->minstnum != 0) continue;
+
+   /* top modules will have is cell bit on if configs used */
+   if (mdp->m_iscell && __map_files_hd == NULL)
+    {
+     __gfwarn(597, mdp->msym->syfnam_ind, mdp->msym->sylin_cnt,
+      "top level module %s in `celldefine region but cannot be a cell",
+       mdp->msym->synam);
+     mdp->m_iscell = FALSE;
+    }
+   __numtopm++;
+  }
+ if (__numtopm == 0) return;
+ __top_itab = (struct inst_t **)
+  __my_malloc(__numtopm*sizeof(struct inst_t *));
+ for (tpii = -1, mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->minstnum != 0) continue;
+   /* need 1 itree inst for each top level module because itp->itip */
+   /* accessed during simulation */
+   ip = (struct inst_t *) __my_malloc(sizeof(struct inst_t));
+   __top_itab[++tpii] = ip;
+   /* initialize for unused by top fields */
+   init_inst(ip);
+
+   /* need to allocate symbol here - because may need name */
+   /* but this symbol is in no symbol table - cannot be looked up */
+   /* because there is no virtual top level module */
+   syp = (struct sy_t *) __my_malloc(sizeof(struct sy_t));
+   /* copying here in case implementing name removal comp. directives */
+   syp->synam = __pv_stralloc(mdp->msym->synam);
+   syp->sytyp = SYM_I;
+   /* notice all symbols add during input phase */
+   syp->sydecl = TRUE;
+   syp->el.eip = ip;
+   syp->syfnam_ind = mdp->msym->syfnam_ind;
+   syp->sylin_cnt = mdp->msym->sylin_cnt;
+   syp->spltsy = NULL;
+
+   ip->isym = syp; 
+   ip->imsym = mdp->msym;
+   /* top level modules have exactly 1 instance */
+   mdp->flatinum = 1;
+   ip->ipxprtab = NULL;
+   ip->pprm_explicit = FALSE;
+   ip->ip_explicit = FALSE;
+   ip->ipins = NULL;
+  }
+ __top_ipind = (int32 *) __my_malloc(__numtopm*sizeof(int32)); 
+ for (ii = 0; ii < __numtopm; ii++) __top_ipind[ii] = ii;
+ qsort((char *) __top_ipind, (word32) __numtopm, sizeof(int32), topip_cmp);
+
+ /* table of pointers to root entries */
+ __it_roots = (struct itree_t **)
+  __my_malloc(__numtopm*sizeof(struct itree_t *));
+
+ /* allocate root itp entries for each top level module */
+ for (ii = 0; ii < __numtopm; ii++)
+  {
+   /* alloc sets itree value */
+   itp = (struct itree_t *) __my_malloc(sizeof(struct itree_t));
+   __it_roots[ii] = itp;
+   __init_itree_node(itp);
+   itp->itip = __top_itab[ii];
+   itp->up_it = NULL;
+   /* since top instance number must be 0 */
+   itp->itinum = 0;
+  }
+}
+
+/*
+ * comparison routines for sorting top modules index
+ */
+static int32 topip_cmp(const void *ii1, const void *ii2)
+{
+ struct inst_t *ip1, *ip2;
+
+ ip1 = __top_itab[*((int32 *) ii1)];
+ ip2 = __top_itab[*((int32 *) ii2)];
+ return(strcmp(ip1->imsym->synam, ip2->imsym->synam));
+}
+
+extern void __init_itree_node(struct itree_t *itp)
+{
+ itp->up_it = NULL;
+ itp->in_its = NULL;
+ itp->itip = NULL;
+ itp->itinum = 0;
+}
+
+/*
+ * ROUTINES TO DETERMINE ARRAYS OF GATES/INSTANCES RANGES 
+ */
+
+/*
+ *
+ * save all design instance (not task/func) parameters values
+ *
+ * only called if need to set gia ranges from params 
+ *
+ * this is point where gia ranges set so parameters evaluated but must
+ * be put back because later defparams may change final values
+ */
+static void save_all_param_vals(void)
+{
+ register int32 pi;
+ register struct mod_t *mdp;
+ register struct net_t *parm_np;
+ int32 nbytes;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mprmnum == 0) continue;
+
+   for (pi = 0, parm_np = &(mdp->mprms[0]); pi < mdp->mprmnum; pi++, parm_np++)
+    {
+     nbytes = 2*WRDBYTES*wlen_(parm_np->nwid);
+     parm_np->nu2.wp = (word32 *) __my_malloc(nbytes);
+     memcpy(parm_np->nu2.wp, parm_np->nva.wp, nbytes);
+    }
+  }
+}
+
+/*
+ * free all param values - must do this so can reuse nu2 field 
+ */
+static void free_all_param_vals()
+{
+ register int32 pi;
+ register struct mod_t *mdp;
+ register struct net_t *parm_np;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mprmnum == 0) continue;
+
+   for (pi = 0, parm_np = &(mdp->mprms[0]); pi < mdp->mprmnum; pi++, parm_np++)
+    {
+     /* DBG remove --- */
+     if (parm_np->nu2.wp == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     __my_free((char *) parm_np->nu2.wp, 2*WRDBYTES*wlen_(parm_np->nwid));
+     parm_np->nu2.wp = NULL;
+    }
+  }
+}
+
+/*
+ * evaluate arrays of gates and instances ranges to number
+ *
+ * depends on convention that arrays of gate/inst range indices can use
+ * pound params (parmeter values changed by # parameters) but evaluation
+ * happens before defparams set (and splitting occurs) so values converted
+ * to number because component parameters may ultimately have different value
+ *
+ * here because no defparams values are static instance tree dependent, i.e. 
+ * do not need to build and use itree
+ *
+ * trick is that because by here all modules with array of gate or instance
+ * ranges determined by pound params, can set range as number
+ */
+static void set_giarr_ranges(void)
+{
+ register int32 gi, ii2;
+ register struct mod_t *mdp;
+ struct giarr_t *giap;
+
+ /* assume some ranges do not have pound params because not much work */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   /* if module has arrays of gates expand first */
+   if (mdp->mgarr != NULL)
+    {
+     for (gi = 0; gi < mdp->mgnum; gi++)
+      {
+       /* skip non array style gates */ 
+       if ((giap = mdp->mgarr[gi]) == NULL) continue;
+       /* if has pound param need to handle in special code below */
+       if (giap->gia_rng_has_pnd) continue;
+
+       eval1_arr_of_gates_rng(giap, mdp, (struct itree_t *) NULL, gi);
+      }
+    }
+   if (mdp->miarr != NULL)
+    {
+     for (ii2 = 0; ii2 < mdp->minum; ii2++)
+      {
+       /* skip non array style instances */ 
+       if ((giap = mdp->miarr[ii2]) == NULL) continue;
+       /* if has pound param need to handle in special code below */
+       if (giap->gia_rng_has_pnd) continue;
+
+       eval1_arr_of_insts_rng(giap, mdp, (struct itree_t *) NULL, ii2);
+      }
+    }
+   __pop_wrkitstk();
+  }
+
+ /* if design has no pound params in arrays of g/i ranges, nothing to do */
+ if (__design_gia_pndparams) set_pnd_gi_rnges();
+}
+
+/*
+ * evaluate array of gates ranges in module mdp 
+ *
+ * for non pound param case just works on raw expr
+ * for pound param case, code called to save and set elaborated (fixed)
+ * param values from propagating pound params down then afterwards unsaving
+ * elaborated values because defparams may change
+ */
+static void eval1_arr_of_gates_rng(struct giarr_t *giap, struct mod_t *mdp,
+ struct itree_t *itp, int32 gi)
+{
+ int32 bad_rng;
+ struct gate_t *gp;
+ struct xstk_t *xsp1, *xsp2;
+
+ /* if error, since do not know range, convert to non array of gates */
+ bad_rng = FALSE;
+ /* know only first (master) auxiliary extra array non nil */
+ gp = &(mdp->mgates[gi]);
+
+ if (!gi_ndxexpr_chk(giap->giax1, gp->gsym->syfnam_ind,
+  gp->gsym->sylin_cnt, "of gates first")) bad_rng = TRUE;
+
+ /* save and set pound params by propagating up initial vals down */
+ if (!bad_rng && itp != NULL) set_gia_expr_pndparms(giap->giax1, itp);
+
+ /* although impossible to have any inst. specific values here */
+ /* need something on it stk */
+ if (itp == NULL)
+  {
+   /* if no passed itp - use wrk dummy inst (right mod) */
+   xsp1 = __eval_xpr(giap->giax1);
+  }
+ else
+  {
+   __push_itstk(itp);
+   xsp1 = __eval_xpr(giap->giax1);
+   __pop_itstk();
+  }
+
+ /* unsave if pound case */
+ if (!bad_rng && itp != NULL) unsave_gia_expr_pndparms(giap->giax1, itp);
+
+ if (!gi_ndxval_chk(xsp1, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+  "of gates first")) bad_rng = TRUE;
+
+ if (!gi_ndxexpr_chk(giap->giax2, gp->gsym->syfnam_ind,
+  gp->gsym->sylin_cnt, "of gates second")) bad_rng = TRUE;
+
+ /* save and set pound params by propagating up initial vals down */
+ if (!bad_rng && itp != NULL) set_gia_expr_pndparms(giap->giax2, itp);
+
+ if (itp == NULL)
+  {
+   /* if no passed itp - use wrk dummy inst (right mod) */
+   xsp2 = __eval_xpr(giap->giax2);
+  }
+ else
+  {
+   __push_itstk(itp);
+   xsp2 = __eval_xpr(giap->giax2);
+   __pop_itstk();
+  }
+
+ if (!bad_rng && itp != NULL) unsave_gia_expr_pndparms(giap->giax2, itp);
+
+ if (!gi_ndxval_chk(xsp2, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+  "of gates second")) bad_rng = TRUE;
+ /* if error do not know range - convert back to one gate */
+ if (!bad_rng) 
+  {
+   giap->gia1 = (int32) xsp1->ap[0];
+   giap->gia2 = (int32) xsp2->ap[0];
+  }
+ __pop_xstk();
+ __pop_xstk();
+}
+
+/*
+ * check a gate or instance array index constant expression 
+ * returns F on error 
+ */
+static int32 gi_ndxexpr_chk(struct expr_t *xp, int32 lfnind, int32 lcnt,
+ char *emsg) 
+{
+ if (__expr_has_glb(xp) || !__chk_giarr_ndx_expr(xp))
+  {
+   __gferr(1161, lfnind, lcnt, 
+    "array %s declaration index expression %s error - pound parameters and constants only",
+    emsg, __msgexpr_tostr(__xs, xp));
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * check a gate or instance array value for 32 bits non x/z
+ * emits error and returns F on error
+ *
+ * LOOKATME - maybe need warn or inform if >32 bits but higher 0's
+ */
+static int32 gi_ndxval_chk(struct xstk_t *xsp, int32 lfnind, int32 lcnt, char *emsg)
+{
+ if (xsp->xslen > WBITS)
+  {
+   if (!vval_is0_(&(xsp->ap[1]), xsp->xslen - 64)
+    || !vval_is0_(xsp->bp, xsp->xslen))
+    {
+     __gferr(1189, lfnind, lcnt,
+      "array %s declaration index value %s not required %d bit non x/z number",
+      emsg, __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE),
+      WBITS);
+     return(FALSE);
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * evaluate array of instances ranges in mdp
+ *
+ * for non pound param case just works on raw expr
+ * for pound param case, code called to save and set elaborated (fixed)
+ * param values from propagating pound params down then afterwards unsaving
+ * elaborated values because defparams may change
+ */
+static void eval1_arr_of_insts_rng(struct giarr_t *giap, struct mod_t *mdp,
+ struct itree_t *itp, int32 ii)
+{
+ int32 bad_rng;
+ struct inst_t *ip;
+ struct xstk_t *xsp1, *xsp2;
+
+ /* if error, since do not know range, convert to non array of gates */
+ bad_rng = FALSE;
+ /* know only first (master) auxiliary extra array non nil */
+ ip = &(mdp->minsts[ii]);
+
+ if (!gi_ndxexpr_chk(giap->giax1, ip->isym->syfnam_ind,
+  ip->isym->sylin_cnt, "of instances first")) bad_rng = TRUE;
+
+ /* save and set pound params by propagating up initial vals down */
+ if (!bad_rng && itp != NULL) set_gia_expr_pndparms(giap->giax1, itp);
+
+ /* although impossible to have any inst. specific values here */
+ /* need something on it stk */
+ if (itp == NULL)
+  {
+   /* if no passed itp - use wrk dummy inst (right mod) */
+   xsp1 = __eval_xpr(giap->giax1);
+  }
+ else
+  {
+   __push_itstk(itp);
+   xsp1 = __eval_xpr(giap->giax1);
+   __pop_itstk();
+  }
+
+ /* unsave if pound case */
+ if (!bad_rng && itp != NULL) unsave_gia_expr_pndparms(giap->giax1, itp);
+
+ if (!gi_ndxval_chk(xsp1, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+  "of instances first")) bad_rng = TRUE;
+
+ if (!gi_ndxexpr_chk(giap->giax2, ip->isym->syfnam_ind,
+  ip->isym->sylin_cnt, "of gates second")) bad_rng = TRUE;
+
+ /* save and set pound params by propagating up initial vals down */
+ if (!bad_rng && itp != NULL) set_gia_expr_pndparms(giap->giax2, itp);
+
+ if (itp == NULL)
+  {
+   /* if no passed itp - use wrk dummy inst (right mod) */
+   xsp2 = __eval_xpr(giap->giax2);
+  }
+ else
+  {
+   __push_itstk(itp);
+   xsp2 = __eval_xpr(giap->giax2);
+   __pop_itstk();
+  }
+
+ /* unsave if pound case */
+ if (!bad_rng && itp != NULL) unsave_gia_expr_pndparms(giap->giax2, itp);
+
+ if (!gi_ndxval_chk(xsp2, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+  "of instances second")) bad_rng = TRUE;
+ /* if error do not know range - convert back to one gate */
+ if (!bad_rng)
+  {
+   giap->gia1 = (int32) xsp1->ap[0];
+   giap->gia2 = (int32) xsp2->ap[0];
+  }
+ __pop_xstk();
+ __pop_xstk();
+}
+
+/*
+ * set all module instance gi ranges with pound params
+ *
+ * only need to do once per module because modules with pound params
+ * in gi ranges always split off to one instance
+ *
+ * final hard case where need itree that is discarded after this step
+ */
+static void set_pnd_gi_rnges(void)
+{
+ register int32 ii;
+ struct itree_t *itp;
+ struct mod_t *mdp;
+
+ __bld_flat_itree();
+
+ /* know top modules never have pound params */
+ for (ii = 0; ii < __numtopm; ii++)
+  {
+   itp = __it_roots[ii];
+   mdp = itp->itip->imsym->el.emdp;
+   set2_pnd_gi_rnges(mdp, itp);
+  }
+
+ /* last step free itree - need to rebuild after defparam splitting */
+ __free_flat_itree();
+}
+
+/*
+ * descend down in itree setting pound param gia ranges
+ * 
+ * when see first instance of module set ranges for all instances
+ * and mark - after that just ignore instances of module
+ */
+static void set2_pnd_gi_rnges(struct mod_t *up_mdp, struct itree_t *up_itp)
+{
+ register int32 gi, ii, ii2;
+ struct mod_t *imdp;
+ struct itree_t *itp;
+ struct giarr_t *giap;
+
+ /* first descend */
+ for (ii = 0; ii < up_mdp->minum; ii++)
+  {
+   itp = &(up_itp->in_its[ii]);
+   /* once module done, know all under also done - no need to descend */
+   imdp = itp->itip->imsym->el.emdp;
+   if (imdp->mpnd_girng_done) continue;
+
+   /* need to descend even if does not have any in gia range pnd params */
+   set2_pnd_gi_rnges(imdp, itp);
+  }
+ /* when this returns will be done even if none in range */
+ up_mdp->mpnd_girng_done = TRUE;
+ if (!up_mdp->mpndprm_ingirng) return;
+
+ /* eval arrays of g/i ranges containing pnd params - others already done */
+ if (up_mdp->mgarr != NULL)
+  {
+   for (gi = 0; gi < up_mdp->mgnum; gi++)
+    {
+     /* skip non array style gates */ 
+     if ((giap = up_mdp->mgarr[gi]) == NULL) continue;
+
+     /* if does not contain pound param already done */
+     if (!giap->gia_rng_has_pnd) continue;
+
+     __push_wrkitstk(up_mdp, 0);
+     eval1_arr_of_gates_rng(giap, up_mdp, up_itp, gi);
+     __pop_wrkitstk();
+    }
+  }
+ if (up_mdp->miarr != NULL)
+  {
+   for (ii2 = 0; ii2 < up_mdp->minum; ii2++)
+    {
+     /* skip non array style instances */ 
+     if ((giap = up_mdp->miarr[ii2]) == NULL) continue;
+     /* if does not contain pound param already done */
+     if (!giap->gia_rng_has_pnd) continue;
+
+     __push_wrkitstk(up_mdp, 0);
+     eval1_arr_of_insts_rng(giap, up_mdp, up_itp, ii2);
+     __pop_wrkitstk();
+    }
+  }
+}
+    
+/*
+ * set all pound params in one g/i array range expression
+ *
+ * when done know all params in g/i array range expr. values elaborated (fixed)
+ */
+static void set_gia_expr_pndparms(struct expr_t *xp, struct itree_t *itp)
+{
+ struct net_t *np;
+
+ if (__isleaf(xp))
+  {
+   if (xp->optyp == ID && xp->lu.sy->sytyp == SYM_N)
+    {
+     np = xp->lu.sy->el.enp; 
+     if (np->n_isaparam) set1_giarr_pndparm(np, itp); 
+    }
+   return;
+  }
+ if (xp->lu.x != NULL) set_gia_expr_pndparms(xp->lu.x, itp);
+ if (xp->ru.x != NULL) set_gia_expr_pndparms(xp->ru.x, itp);
+}
+
+/*
+ * for parameter determine if pound and if so set value by setting
+ * values in up instance pound expr and evaluating it
+ * new up value is then set as value of down parameter 
+ * may need to work up to top of itree
+ */
+static void set1_giarr_pndparm(struct net_t *np, struct itree_t *itp) 
+{
+ int32 pndpi;
+ struct itree_t *up_itp;
+ struct mod_t *up_mdp;
+ struct inst_t *up_ip;
+ struct expr_t *up_pndxp;
+ struct xstk_t *xsp;
+ char s1[RECLEN];
+
+ /* may need to access parameter (not pound) in top level module */
+ up_itp = itp->up_it;
+ /* if top or no pound params or no pound expr. passed down for this, done */
+ up_ip = itp->itip;
+ if (up_ip->ipxprtab == NULL) return;
+ up_mdp = up_ip->imsym->el.emdp;
+ pndpi = ((byte *) np - (byte *) up_mdp->mprms)/sizeof(struct net_t);
+ if (up_ip->ipxprtab[pndpi] == NULL) return;
+
+ /* know this is pound param */
+ up_pndxp = up_ip->ipxprtab[pndpi];
+
+ /* work up evaluating parmeters changing pound params to passed down val */
+ /* this sets values in pound passed (up) expr - if it contains pound */
+ /* params recursively repeats up as far as needed (maybe to top) */
+ set_gia_expr_pndparms(up_pndxp, up_itp);
+ /* now all pound param in expr. replaced by passed down pound value */
+   
+ /* although pound params never instance specific must access constants */
+ /* from up module con tab */
+ __push_itstk(up_itp);
+ xsp = __eval_xpr(up_pndxp);
+ __pop_itstk();
+
+ /* change value - IS form impossible here */
+ sprintf(s1, "%s (pound param)", __msg2_blditree(__xs, itp));
+ __cnvt_param_stkval(xsp, up_pndxp, np, s1);
+ __assgn_nonis_param(np, up_pndxp, xsp);
+ __pop_xstk();
+
+ /* free and put back temporary "as of now" parameter values of params */
+ /* in up pound expr */
+ unsave_gia_expr_pndparms(up_pndxp, up_itp);
+}
+
+/*
+ * free and unsave pound params in expression 
+ *
+ * non up pound params just ignored initial in source value was not changed
+ * only needed for this expr. because if pnds worked up, evaled and unsaved
+ */
+static void unsave_gia_expr_pndparms(struct expr_t *xp, struct itree_t *itp)
+{
+ int32 pndpi;
+ struct net_t *np;
+ struct itree_t *up_itp;
+ struct inst_t *ip;
+ struct mod_t *mdp;
+
+ if (__isleaf(xp))
+  {
+   if (xp->optyp == ID && xp->lu.sy->sytyp == SYM_N)
+    {
+     np = xp->lu.sy->el.enp; 
+     if (np->n_isaparam)
+      {
+       if ((up_itp = itp->up_it) == NULL) return;
+       ip = up_itp->itip;
+       if (ip->ipxprtab == NULL) return;
+       mdp = itp->itip->imsym->el.emdp;
+       pndpi = ((byte *) np - (byte *) mdp->mprms)/sizeof(struct net_t);
+       if (ip->ipxprtab[pndpi] == NULL) return;
+ 
+       /* DBG remove --- */
+       if (np->srep != SR_PNUM) __misc_terr(__FILE__, __LINE__);
+       if (np->nu2.wp == NULL) __misc_terr(__FILE__, __LINE__);
+       /* --- */
+
+       /* need to unsave param value by copying back */
+       /* this puts back intial value that is always SR_PNUM */
+       memcpy(np->nva.wp, np->nu2.wp, 2*WRDBYTES*wlen_(np->nwid));
+      }
+    }
+   return;
+  }
+ if (xp->lu.x != NULL) unsave_gia_expr_pndparms(xp->lu.x, itp);
+ if (xp->ru.x != NULL) unsave_gia_expr_pndparms(xp->ru.x, itp);
+}
+
+/*
+ * ROUTINES TO SPLIT ARRAY OF GATES AND INSTANCES  
+ */
+
+/*
+ * rebuild mgates and miarr tables for each module with arrays of g/i
+ *
+ * for g/i arrays original symbol and pins store in giap
+ * BEWARE - can not access symbol table in here until sorted and reconnected
+ *          at end of gate and inst expansion
+ */
+static void rebld_mod_giarrs(void)
+{
+ register int32 i, i2, i3;
+ register struct mod_t *mdp, *imdp;
+ int32 has_iarrs, newgnum, newinum, giawid, j;
+ int32 arrsynum, bi, gia_dir, new_stsiz;
+ struct gate_t *gptab, *gp;
+ struct inst_t *iptab, *ip;
+ struct giarr_t *giap, **giatab;
+ struct srcloc_t **sloctabp;
+
+ has_iarrs = FALSE;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mgarr == NULL && mdp->miarr == NULL) continue;
+
+   __push_wrkitstk(mdp, 0);
+   arrsynum = 0;
+   /* first count number of new */ 
+   if (mdp->mgarr != NULL)
+    {
+     /* compute new size of mgates table */
+     for (i = 0, newgnum = 0; i < mdp->mgnum; i++) 
+      {
+       if ((giap = mdp->mgarr[i]) == NULL) { newgnum++; continue; }
+       giap->gia_bi = newgnum;
+       newgnum += __get_giarr_wide(giap);
+       /* one extra symbol for every element of array but original gate */
+       /* counted as one */
+       arrsynum++;
+      }
+    } 
+   else newgnum = mdp->mgnum;
+
+   if (mdp->miarr != NULL)
+    {
+     has_iarrs = TRUE;
+     /* compute new size of minsts table */
+     for (i = 0, newinum = 0; i < mdp->minum; i++) 
+      {
+       if ((giap = mdp->miarr[i]) == NULL) { newinum++; continue; }
+       giap->gia_bi = newinum;
+       newinum += __get_giarr_wide(giap);
+       arrsynum++;
+      }
+    }
+   else newinum = mdp->minum;
+
+   /* allocate room for new symbols now that know how many */
+   /* notice every gate name symbol including first added */ 
+   /* original moved to giap */
+   new_stsiz = mdp->msymtab->numsyms + (newgnum - mdp->mgnum)
+    + (newinum - mdp->minum) + arrsynum;
+   /* SJM 07/02/05 - can't use realloc because need old stsyms during */
+   /* build of new minst iptab - old worked only if realloc didn't move */
+   /* can't free stsyms yet */
+   __wrkstab = (struct sy_t **) __my_malloc(new_stsiz*sizeof(struct sy_t *));
+   memcpy(__wrkstab, mdp->msymtab->stsyms,
+    mdp->msymtab->numsyms*sizeof(struct sy_t *));
+
+   __last_sy = mdp->msymtab->numsyms - 1;
+   /* DBG remove --- */
+   if (!mdp->msymtab->freezes) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   if (mdp->mgarr != NULL)
+    {
+     giatab = (struct giarr_t **)
+      __my_malloc(newgnum*sizeof(struct giarr_t *));
+     gptab = (struct gate_t *) __my_malloc(newgnum*sizeof(struct gate_t));
+     /* copy from old to new gia and gate tables */
+     /* i moves through old mgates, i2 through new */ 
+     for (i = 0, i2 = 0; i < mdp->mgnum; i++) 
+      {
+       if ((giap = mdp->mgarr[i]) == NULL)
+        {
+         giatab[i2] = NULL;
+         /* copy body (insides) */
+         gp = &(gptab[i2]);
+         *gp = mdp->mgates[i];
+         /* SJM 07/02/05 - for non arrayed insts in mod with inst arrays, */ 
+         /* need to connect the sym to new iptab entry - needed because */
+         /* ip tab is array of inst_t records not array of ptrs */
+         gp->gsym->el.egp = gp;
+         i2++;
+         continue;
+        }
+       /* move original gpins to giap and point all to it */
+       /* for now all gpins lists same and >1 ptrs to it */
+       giap->giapins = mdp->mgates[i].gpins;
+       giap->gia_base_syp = mdp->mgates[i].gsym;
+       giap->gia_base_syp->el.egp = &(gptab[i2]);
+       giap->gia_base_syp->sy_giabase = TRUE;
+       giap->gia_xpnd = TRUE;
+       giawid = __get_giarr_wide(giap);
+       bi = giap->gia1;
+       gia_dir = (giap->gia1 > giap->gia2) ? -1 : 1;
+
+       /* stored in gia1 to gia2 order - not normalized to h:l as for nets */
+       for (i3 = i2; i3 < i2 + giawid; i3++, bi += gia_dir)
+        {
+         /* point all expanded to same index record - can always find first */
+         giatab[i3] = giap;
+
+         /* copy body of declared array of gates */
+         gp = &(gptab[i3]);
+         *gp = mdp->mgates[i];
+         gp->g_du.pdels = __copy_dellst(mdp->mgates[i].g_du.pdels);
+         add_new_gsym(gp, bi);  
+        }
+       i2 += giawid;
+      }
+     /* finally free old gate tables and allocate new */
+     __my_free((char *) mdp->mgates, mdp->mgnum*sizeof(struct gate_t));
+     mdp->mgates = gptab;
+     mdp->mgarr = giatab;
+     mdp->mgnum = newgnum;
+    }
+   if (mdp->miarr != NULL)
+    {
+     giatab = (struct giarr_t **)
+      __my_malloc(newinum*sizeof(struct giarr_t *));
+     iptab = (struct inst_t *) __my_malloc(newinum*sizeof(struct inst_t));
+     sloctabp = (struct srcloc_t **)
+      __my_malloc(newinum*sizeof(struct srcloc_t *));
+
+     /* copy from old to new gia and gate tables */
+     /* i moves through old minsts, i2 through new */ 
+     for (i = 0, i2 = 0; i < mdp->minum; i++) 
+      {
+       if ((giap = mdp->miarr[i]) == NULL)
+        {
+         /* non array inst - just copy */
+         giatab[i2] = NULL;
+
+         ip = &(iptab[i2]);
+         *ip = mdp->minsts[i];
+         /* SJM 07/02/05 - for non arrayed insts in mod with inst arrays, */ 
+         /* need to connect the sym to new iptab entry - needed because */
+         /* ip tab is array of inst_t records not array of ptrs */
+         ip->isym->el.eip = ip; 
+
+         /* here just move ptr */
+         sloctabp[i2] = mdp->iploctab[i];
+         mdp->iploctab[i] = NULL;
+         i2++;
+         continue;
+        }
+
+       giap->giapins = mdp->minsts[i].ipins;
+       giap->gia_base_syp = mdp->minsts[i].isym;
+       giap->gia_base_syp->el.eip = &(iptab[i2]);
+       giap->gia_base_syp->sy_giabase = TRUE;
+       giap->gia_xpnd = TRUE;
+
+       /* stored in gia1 to gia2 order - not normalized to h:l as for nets */
+       giawid = __get_giarr_wide(giap);
+       bi = giap->gia1;
+       gia_dir = (giap->gia1 > giap->gia2) ? -1 : 1;
+       /* stored in gia1 to gia2 order - not normalized to h:l as for nets */
+       for (i3 = i2; i3 < i2 + giawid; i3++, bi += gia_dir)
+        {
+         /* point all expanded to same index record - can always find first */
+         giatab[i3] = giap;
+         ip = &(iptab[i3]);
+         /* copy body of declared array of insts - no need to initialize */
+         *ip = mdp->minsts[i];
+         imdp = ip->imsym->el.emdp;
+
+         /* symbol from base array of insts must point to first */
+         if (i3 == i2)
+          {
+           /* first time move */
+           sloctabp[i3] = mdp->iploctab[i];
+           mdp->iploctab[i] = NULL;
+          }
+         else
+          {
+           /* thereafter alloc and copy */
+           if (imdp->mpnum == 0) sloctabp[i3] = NULL; 
+           else
+            { 
+             /* array of ptr to array of src locs each size different */
+             /* because each inst. has different number of pins */
+             sloctabp[i3] = (struct srcloc_t *)
+              __my_malloc(imdp->mpnum*sizeof(struct srcloc_t));  
+             /* copy each source loc record */
+             for (j = 0; j < imdp->mpnum; j++)
+              sloctabp[i3][j] = sloctabp[i2][j];
+            }
+          }
+         ip->ipxprtab = copy_pndxtab(&(mdp->minsts[i]));
+         add_new_isym(ip, bi);  
+        }
+       i2 += giawid;
+       if (mdp->minstnum == 1 && giawid > 1) mdp->minstnum = 2;
+      }
+     /* finally free old insts tables and allocate new */
+     __my_free((char *) mdp->minsts, mdp->minum*sizeof(struct inst_t));
+     __my_free((char *) mdp->miarr, mdp->minum*sizeof(struct giarr_t *));
+     __my_free((char *) mdp->iploctab, mdp->minum*sizeof(struct srcloc_t *));
+     mdp->minsts = iptab;
+     mdp->miarr = giatab;
+     mdp->iploctab = sloctabp; 
+     mdp->minum = newinum;
+    }
+
+   /* must re-sort symbol table - because table of ptr el union right */
+   qsort((char *) __wrkstab, (word32) new_stsiz, sizeof(struct sy_t *),
+    gia_sym_cmp);
+   /* SJM 07/02/05 - free the mod's symbtab stsyms to fix memory leak */
+   /* symtab is ptr to syms - for non i/g array's sym record still used */
+   __my_free((char *) mdp->msymtab->stsyms,
+    mdp->msymtab->numsyms*sizeof(struct sy_t *)); 
+   mdp->msymtab->numsyms = new_stsiz;
+   mdp->msymtab->stsyms = __wrkstab;
+   __pop_wrkitstk();
+  }
+ /* if any any arrays of instances, must recount */  
+ if (has_iarrs) count_flat_insts();
+ /* mod level table remains same since more instance but no more types */
+}
+
+/*
+ * comparison routine for sorting symbol table after expand g/i added 
+ */
+static int32 gia_sym_cmp(const void *sy1, const void *sy2)
+{
+ return(strcmp((*((struct sy_t **) sy1))->synam,
+  (*(struct sy_t **) sy2)->synam));
+}
+
+/*
+ * get width of array of inst/gate
+ */
+extern int32 __get_giarr_wide(struct giarr_t *giap)
+{
+ int32 r1, r2;
+
+ r1 = giap->gia1;
+ r2 = giap->gia2;
+ /* DBG remove -- */
+ if (r1 == -1 || r2 == -1) __arg_terr(__FILE__, __LINE__); 
+ /* --- */
+ return((r1 >= r2) ? (r1 - r2 + 1) : (r2 - r1 + 1));
+}
+
+/*
+ * routine to add new (still unusuable and unsorted) symbol table
+ * because stored in range order never need to normalize here
+ */
+static void add_new_gsym(struct gate_t *gp, int32 bi)  
+{
+ struct sy_t *gsyp;
+ char nsynam[2*IDLEN];
+
+ gsyp = (struct sy_t *) __my_malloc(sizeof(struct sy_t)); 
+ *gsyp = *(gp->gsym);
+ sprintf(nsynam, "%s[%d]", gp->gsym->synam, bi); 
+ gsyp->synam = __pv_stralloc(nsynam);
+ __wrkstab[++__last_sy] = gsyp;
+ gp->gsym = gsyp;
+ gsyp->el.egp = gp;
+}
+
+/*
+ * routine to update new (still unusuable and unsorted) symbol table
+ * because stored in range order never need to normalize here
+ */
+static void add_new_isym(struct inst_t *ip, int32 bi)  
+{
+ struct sy_t *isyp;
+ char nsynam[2*IDLEN];
+
+ isyp = (struct sy_t *) __my_malloc(sizeof(struct sy_t)); 
+ *isyp = *(ip->isym);
+ sprintf(nsynam, "%s[%d]", ip->isym->synam, bi); 
+ isyp->synam = __pv_stralloc(nsynam);
+ __wrkstab[++__last_sy] = isyp;
+ ip->isym = isyp;
+ isyp->el.eip = ip;
+}
+
+/*
+ * routine to dump minsts for every module in the design
+ */
+extern void __dmp_dsgn_minst(char *hdr_s)
+{
+ register struct mod_t *mdp;
+ int32 ii;
+ struct inst_t *ip;
+
+ __dbg_msg("%s ===>\n", hdr_s);
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __dbg_msg("+++ dumping instances in module %s:\n", mdp->msym->synam);
+   for (ii = 0; ii < mdp->minum; ii++)
+    {
+     ip = &(mdp->minsts[ii]);
+     __dmp_1minst(ip);
+    }
+  }
+}
+
+/*
+ * dmp one minst element 
+ */
+extern void __dmp_1minst(struct inst_t *ip)
+{
+ char s1[RECLEN];
+
+ if (ip->ipxprtab != NULL)
+  {
+   sprintf(s1, "ipxprtab[0]=%s", __msgexpr_tostr(__xs, ip->ipxprtab[0]));
+  }
+ else strcpy(s1, "[no ipxprtab]");
+ __dbg_msg("     inst %s type %s %s\n", ip->isym->synam, ip->imsym->synam,
+  s1);
+ if (ip->isym->el.eip != ip)
+  {
+   __dbg_msg("inst %s type %s - other inst %s type %s\n",
+     ip->isym->el.eip->isym->synam, ip->isym->el.eip->imsym->synam, 
+     ip->isym->synam, ip->imsym->synam); 
+   __misc_terr(__FILE__, __LINE__);
+  }
+}
+
+/*
+ * ROUTINES TO CHECK DEFPARAMS
+ */
+
+/*
+ * check defparam format parameter statements 
+ *
+ * must be done before pound splitting because pound splitting copy
+ * of defparam grefs must copy glb ref components
+ *
+ * if error, undef symbol - must ignore undef. symbols later
+ */
+static void chk_defparams(void)
+{
+ register struct dfparam_t *dfpp;
+ register struct mod_t *mdp;
+ struct dfparam_t *dfpp2, *last_dfpp;
+
+ __num_dfps = 0;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   for (last_dfpp = NULL, dfpp = __inst_mod->mdfps; dfpp != NULL;)
+    {
+     dfpp2 = dfpp->dfpnxt;
+     __sfnam_ind = dfpp->dfpfnam_ind;
+     __slin_cnt = dfpp->dfplin_cnt;
+
+     /* must check and set widths here since can contain parameters defined */ 
+     /* later in source according to LRM */
+     if (!__chk_paramexpr(dfpp->dfpxrhs, 0))
+      {
+       __sgferr(1035,
+        "defparam %s right hand side error - parameters and constants only",
+        __msgexpr_tostr(__xs, dfpp->dfpxlhs));
+       __free2_xtree(dfpp->dfpxrhs);
+       __set_numval(dfpp->dfpxrhs, ALL1W, ALL1W, WBITS);
+      }
+     /* check and set value during src read since only previously defined */
+     /* params on rhs and must use initial values */
+
+     /* SJM 01/27/04 - old code was wrongly evaling defparam rhs to number */
+     /* must be left as expr since dfps may need changed dependend param */
+
+     if (!lhs_chk1dfparam(dfpp))
+      {
+       /* if error, remove from list on error */
+       if (last_dfpp == NULL) __inst_mod->mdfps = dfpp2;
+       else last_dfpp->dfpnxt = dfpp2;
+       /* free the defparam - compeletly removed from circuit */
+       __free_1dfparam(dfpp);
+      }
+     else { last_dfpp = dfpp; __num_dfps++; }
+     dfpp = dfpp2;
+    }
+   __pop_wrkitstk();
+  }
+ /* final step is freeing all defparams in gref table, no longer needed */
+ free_gone_glbs();
+}
+
+/*
+ * check parameter lhs expression and return
+ * resolution of defparam lhs global in here
+ *
+ * array of instance selects illegal in defparams  
+ */
+static int32 lhs_chk1dfparam(struct dfparam_t *dfpp)
+{
+ struct gref_t *grp;
+ struct expr_t *lhsndp;
+ struct sy_t *syp;
+
+ lhsndp = dfpp->dfpxlhs;
+ grp = NULL;
+ if (lhsndp->optyp == GLBREF)
+  { 
+   grp = lhsndp->ru.grp;
+   grp->gr_defparam = TRUE;
+   /* know here none of the special scope or dumpvars bits set */
+   __resolve_glbnam(grp);
+   if (lhsndp->optyp == ID) goto is_local;
+   __num_glbdfps++;
+   /* if error in resolving global cannot check here - syp not set */
+   if (grp->gr_err) return(FALSE);
+   /* upward relative defparams illegal to match Cadence */
+   if (grp->upwards_rel)
+    {
+     __sgferr(760,
+      "upward relative defparam lvalue %s illegal - must be rooted or downward relative",
+      grp->gnam);
+     grp->upwards_rel = FALSE;      
+     grp->gr_err = TRUE;
+     return(FALSE);
+    }
+
+   syp = lhsndp->lu.sy;
+   if (syp->sytyp != SYM_N || !syp->el.enp->n_isaparam)
+    {
+     __sgferr(755, "defparam hierarchical name lvalue %s is not a parameter",
+      grp->gnam);
+     grp->gr_err = TRUE;
+     return(FALSE);
+    }
+
+   /* for any array of inst selects in defparams are illegal */ 
+   if (gref_has_giarr_ndxes(grp))
+    {
+     __sgferr(691, 
+      "defparam lvalue %s instance array select illegal - use pound param",
+      grp->gnam);
+     grp->gr_err = TRUE;
+     return(FALSE);
+    }
+
+   /* now have defparam global lhs path - so done with global move to defp */
+   /* move guts of gref to defparam nil fields and mark global as gone */
+   set_1defparam_iis(dfpp, grp);
+   dfpp->gdfpnam = grp->gnam;
+   grp->gnam = NULL;
+
+   grp->last_gri = -1;
+   dfpp->targsyp = grp->targsyp;
+   dfpp->dfptskp = grp->targtskp;
+   grp->targsyp = NULL;
+   /* must remove gref since contents in defparam */
+   grp->gr_gone = TRUE;
+   lhsndp->ru.grp = NULL;
+   return(TRUE); 
+  }
+
+is_local:
+ /* this is local - if in module gref - converted to simple by here */
+ syp = lhsndp->lu.sy;
+ if (syp->sytyp != SYM_N || !syp->el.enp->n_isaparam)
+  {
+   __sgferr(756, "defparam local lvalue variable %s not a parameter",
+    syp->synam);
+   if (grp != NULL) grp->gr_err = TRUE;
+   return(FALSE);
+  }
+ dfpp->dfp_local = TRUE;
+ dfpp->gdfpnam = __pv_stralloc(syp->synam);
+ dfpp->in_mdp = __inst_mod;
+ dfpp->targsyp = syp;
+ __num_locdfps++;
+ return(TRUE);
+}
+
+/*
+ * return T if resolved global name has instance array index component
+ */
+static int32 gref_has_giarr_ndxes(struct gref_t *grp)
+{
+ register int32 gri;
+
+ for (gri = 0; gri <= grp->last_gri; gri++) 
+  {
+   if (grp->grxcmps[gri] != NULL) return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * set defparam itree ii paths 
+ *
+ * needed now because copying changes instance symbols
+ * later will convert downward relative dfpiis to rooted and 1 design list
+ */
+static void set_1defparam_iis(struct dfparam_t *dfpp,
+ struct gref_t *grp)
+{
+ register int32 gi;
+ int32 ii;
+ byte *bp1, *bp2;
+ struct sy_t *syp;
+ struct inst_t *ip;
+ struct mod_t *up_mdp;
+
+ dfpp->last_dfpi = grp->last_gri;
+ dfpp->dfpiis = (int32 *) __my_malloc((dfpp->last_dfpi + 1)*sizeof(int32));
+ dfpp->dfp_rooted = (grp->is_rooted) ? TRUE : FALSE;
+ if (dfpp->dfp_rooted)
+  {
+   /* defparam path root wrong */
+   syp = grp->grcmps[0];
+   if ((ii = __ip_indsrch(syp->synam)) == -1) __misc_terr(__FILE__, __LINE__);
+   dfpp->dfpiis[0] = ii;
+   gi = 1;
+   up_mdp = __top_itab[ii]->imsym->el.emdp;
+  }
+ else { gi = 0; up_mdp = __inst_mod; }  
+
+ for (; gi <= grp->last_gri; gi++)
+  {
+   /* grcmps components parallel here */
+   syp = grp->grcmps[gi];
+   ip = syp->el.eip;
+   /* making use of c pointer subtraction correction object size here */
+   /* changing to byte ptr because not sure of c ptr size object rules */
+   bp1 = (byte *) ip;
+   bp2 = (byte *) up_mdp->minsts;
+   ii = (bp1 - bp2)/sizeof(struct inst_t);
+
+   /* DBG remove --- */
+   if (__debug_flg)
+    {
+     __dbg_msg(
+      "^^ defparam %s component %s index %d instance %s type %s in module %s\n",
+      grp->gnam, syp->synam, ii, ip->isym->synam, ip->imsym->synam,
+      up_mdp->msym->synam);
+    }
+   /* --- */
+   dfpp->dfpiis[gi] = ii;
+   up_mdp = syp->el.eip->imsym->el.emdp;
+  }
+}
+
+/*
+ * resolve all non defparam xmrs in all modules
+ *
+ * since this is done after all splitting and fix up of itree and static
+ * inst tree - all grefs will have correct syms
+ * all defparams set by here 
+ */
+static void resolve_xmrs(void)
+{
+ register int32 gri;
+ register struct gref_t *grp; 
+ register struct mod_t *mdp;
+
+ /* notice must include any newly split off modules here */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   grp = &(__inst_mod->mgrtab[0]);
+   for (gri = 0; gri < __inst_mod->mgrnum; gri++, grp++)
+    {
+     /* FIXME - for now leaving defparams but marked as gone here */
+     /* why not remove? */
+     if (grp->gr_err) continue;
+     __resolve_glbnam(grp);
+     /* must count here because must resolve globals from pli and debugger */
+     if (!grp->gr_err) __num_glbs++;
+    }
+   __pop_wrkitstk();
+  }
+ /* must free because can be many PLI systf args that are converted back */  
+ free_gone_glbs();
+}
+
+/*
+ * build the global path name component symbol list for 1 global
+ *
+ * SJM 01/14/00 
+ * this requires that inst mod be set usually by push wrk itstk routine
+ * it just decompoes xmr into path components so does not need itree context
+ */
+extern void __resolve_glbnam(struct gref_t *grp)
+{
+ register int32 gi;
+ struct sy_t *syp;
+ struct sy_t **syarr;
+ struct expr_t *gcmp_ndp, **syxarr;
+
+ __sfnam_ind = grp->grfnam_ind;
+ __slin_cnt = grp->grflin_cnt;
+
+ /* DBG remove --- */
+ if (grp->gxndp->optyp != GLBREF) __arg_terr(__FILE__, __LINE__);
+ if (grp->glbref->optyp != GLBPTH) __arg_terr(__FILE__, __LINE__);
+ if (grp->glbref->ru.x == NULL || grp->glbref->ru.x->optyp != XMRCOM)
+  __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ gcmp_ndp = grp->glbref->ru.x;
+
+ /* separate handling for intra-module (really local) hierarchical paths */
+ /* does all processing and then returns */
+ /* defparam lhs may be hierarchical local - changed to def param later */
+ /* all 1 component special instance/prim globals caught here */
+ /* also any illegal selects caught because know non-inst scope objects */
+ if (resolve_local_path(grp, gcmp_ndp)) return;
+
+ /* SJM 09/15/00 - because of inst tree dependent upward rel forms */
+ /* reauired by LRM must use old routine for defparams to fill head */
+ if (grp->gr_defparam)
+  {
+   /* fill the defparam lhs head - notice after first component found */
+   /* and filled rest is same as normal XMR */
+   /* different needed because itree needed for full XMR processing */
+   if (!fill_dfp_gsymhead(grp, gcmp_ndp)) goto bad_end;
+  }
+ else
+  {
+   /* fill root of non defparam xmr path */
+   if (!fill_gsymhead(grp, gcmp_ndp)) goto bad_end;
+  }
+
+ /* handle special scope form 1 component global */
+ /* only scope place [top mod] or [inst] as simple name can get here */ 
+ /* LOOKATME think this case handled in resolve local path */
+ if (gcmp_ndp->ru.x == NULL)
+  {
+   /* fake last component index - since only access one back from end */
+   syp = NULL;
+   if (grp->gr_inst_ok)
+    {
+     /* this needs to be 1 component global where targsyp and path same */
+     /* here both target and last inst. scope symbol are the same */ 
+     syp = __glbsycmps[0]; 
+     grp->targsyp = syp;
+    }
+   else if (grp->is_upreltsk)
+    {
+     /* upward rel converts to [mod name].[func name] */
+     syp = __glbsycmps[0]; 
+     grp->targsyp = __glbsycmps[1]; 
+    }
+   else __case_terr(__FILE__, __LINE__);
+   goto fill_glb;
+  }
+ /* this is a normal xmr - fill rest of xmr path */
+ /* this removes the intra-module path (except last) from glb sy cmps */
+ if (!fill_grestsyms(grp, gcmp_ndp->ru.x)) goto bad_end;
+
+ /* fill various gref fields - target symbol always last even if inst. */
+ grp->targsyp = __glbsycmps[__last_gsc];
+
+ /* need to set syp as ending inst. not var for setting targmdp */
+ if (grp->targsyp->sytyp == SYM_I || grp->targsyp->sytyp == SYM_M)
+  syp = grp->targsyp;
+ /* notice syp is 1 before target end - usually will be inst. */
+ else syp = __glbsycmps[__last_gsc - 1]; 
+
+fill_glb:
+ /* may be dumpvars or scope style instance reference */
+ if (syp->sytyp == SYM_I) grp->targmdp = syp->el.eip->imsym->el.emdp;
+ else if (syp->sytyp == SYM_M) grp->targmdp = syp->el.emdp;
+ else 
+  {
+   __sgferr(1107,
+    "hierarchical path reference %s target symbol %s type %s illegal",  
+    grp->gnam, syp->synam, __to_sytyp(__xs, syp->sytyp)); 
+   goto bad_end;   
+  }
+
+ /* handle special scope globals */
+ /* can be module for top only or upward relative one component */
+ if (grp->targsyp->sytyp == SYM_I || grp->targsyp->sytyp == SYM_M) 
+  {
+   /* notice task scope form looks like normal here and checked elsewhere */
+   if (!grp->gr_inst_ok)
+    {
+     __sgferr(1030,
+      "special system task instance form argument %s not allowed here",
+      grp->gnam);
+     goto bad_end;
+    }
+   /* adjust last component so it stays as part of path here */
+   /* targsyp and last are same symbol */
+   grp->last_gri = (short int) __last_gsc;
+  }
+ else grp->last_gri = (short int) __last_gsc - 1;
+ if (!chk_glb_inst_sels(grp)) goto bad_end;
+
+ /* allocate the array of symbols in malloced storage */
+ syarr = (struct sy_t **)
+   __my_malloc((__last_gsc + 1)*sizeof(struct sy_t *));
+ grp->grcmps = syarr;
+
+ syxarr = (struct expr_t **)
+   __my_malloc((__last_gsc + 1)*sizeof(struct expr_t *));
+ grp->grxcmps = syxarr;
+
+ /* tail pointed to by targsyp end of syarr is last instance symbol */
+ /* for scope object targsyp and last syarr same */ 
+ for (gi = 0; gi <= __last_gsc; gi++)
+  {
+   syarr[gi] = __glbsycmps[gi];
+   /* will be nil for non inst. select */
+   syxarr[gi] = __glbxcmps[gi];
+  }
+
+ /* check and fold gref instance array select constant select expressions */
+ if (grp->path_has_isel)
+  {
+   char s1[RECLEN];
+
+   for (gi = 0; gi <= grp->last_gri; gi++) 
+    {
+     if (grp->grxcmps[gi] == NULL) continue;
+
+     sprintf(s1, "hierarchical reference instance array index (pos. %d)",
+      gi + 1);
+     if (!__chkndx_expr(grp->grxcmps[gi], s1)) goto bad_end;
+    }
+  }
+
+ /* even though downward really rooted, must not treat as rooted */
+ /* until variable xmr converted to location - for defparam need to */
+ /* add module name (1 level) prefix */
+
+ /* fill symbol grp expr and grp ru expr field already cross linked */
+ /* for disable will point to disable expr. */
+ /* LOOKATME - although XMRCOM expr contents no longer accessible */
+ /* can not free because grp points to grcmps - slight memory leak here */
+ grp->gxndp->ru.grp = grp;
+ grp->gxndp->lu.sy = grp->targsyp;
+ return;
+
+bad_end:
+ grp->gr_err = TRUE;
+}
+
+/*
+ * resolve a local name that is a qualified path name
+ * if really local path, converted and checked as id later
+ *
+ * here caller handled instance arrays - know in module scope symbols
+ * are never arrayed (error emitted if select appears)
+ */
+static int32 resolve_local_path(struct gref_t *grp, struct expr_t *ghd_ndp)
+{
+ struct symtab_t *sytp;
+ struct sy_t *syphd, *syptail;
+ struct expr_t *ndp, *locndp;
+ char *ncmp;
+
+ if (ghd_ndp->lu.x->optyp == XMRID) ndp = ghd_ndp->lu.x;
+ else if (ghd_ndp->lu.x->optyp == LSB) ndp = ghd_ndp->lu.x->lu.x;
+ else { __case_terr(__FILE__, __LINE__); return(FALSE); }
+
+ ncmp = ndp->ru.qnchp;
+ /* work up task chains searching for local */
+ for (syphd = NULL, sytp = grp->grsytp; sytp != NULL; sytp = sytp->sytpar)
+  {
+   if ((syphd = __zget_sym(ncmp, sytp->stsyms, sytp->numsyms)) != NULL) break;
+  }
+ if (syphd == NULL) return(FALSE);
+
+ /* handle xmr's that were guessed to be xmrs but are really either errors */
+ /* or guessed wrong and just simple wires - if this is place wire cannot */
+ /* go, error will be caught in item (such as task enable) checking */
+ if (syphd->sytyp == SYM_N)
+  {
+   /* if this is hierarchical global whose head is wire - error */
+   /* i.e. if only 1 component ok */
+   if (ghd_ndp->ru.x != NULL || !grp->gr_inst_ok)
+    {
+     __sgferr(754, "hierarchical reference %s first component %s %s illegal",
+      grp->gnam, __to_wtnam(__xs, syphd->el.enp), syphd->synam);
+     grp->gr_err = TRUE;
+     return(TRUE);
+    }
+   /* must be wire not parameter here at end - param use xmr's illegal */
+   if (!chk_xmr_tail_wire(grp, syphd, TRUE))
+    { grp->gr_err = TRUE; return(TRUE); }
+
+local_1cmp:
+   /* if this is xmr that is 1 component - change back to simple wire */
+   grp->gr_gone = TRUE;
+   /* LOOKATME - why is this needed since removing glb */
+   if (syphd->sytyp == SYM_TSK || syphd->sytyp == SYM_F ||
+    syphd->sytyp == SYM_LB) grp->targtskp = syphd->el.etskp;
+   /* this can be local task call too - not just wire */
+   if (ghd_ndp->lu.x->optyp == XMRID)
+    {
+     /* first free the XMRCOM grp expr. part */  
+     locndp = grp->gxndp;
+     __free2_xtree(locndp);
+     locndp->optyp = ID;
+     locndp->ru.grp = NULL;
+     locndp->lu.sy = syphd;
+    }
+   else 
+    {
+     /* here gxndp is GLB REF with ru ptr to XMR COM (list) */     
+     /* here rearranging so can not free */
+     locndp = grp->gxndp;
+     locndp->optyp = LSB;
+     locndp->ru.grp = NULL;
+     locndp->lu.x = ghd_ndp->lu.x->lu.x;
+     locndp->lu.x->optyp = ID;
+     locndp->lu.x->lu.sy = syphd;
+     locndp->ru.x = ghd_ndp->lu.x->ru.x; 
+    }
+   /* global is now removed and do not need to save name since only one comp */
+   return(TRUE);
+  }
+ /* know only way for this to happen is gr loc is scope object */  
+ /* if this is 1 component task enable or function call will never be */
+ /* seen as global in source reading */
+ /* handle in normal global code since it cannot be local */
+
+ /* not a wire - handle case of 1 component scope object */
+ /* this is global caused by appearing in scope legal place */
+ if (ghd_ndp->ru.x == NULL)
+  {
+   /* can be task/func/named block in which case convert back to local */
+   /* also can be udp or gate primitive */
+   /* and no need to check for possibility of wrong param will check in */
+   /* sys task enable code */
+   if (syphd->sytyp == SYM_TSK || syphd->sytyp == SYM_F ||
+    syphd->sytyp == SYM_LB)
+    {
+     /* any scope array that is not array of insts is illegal */
+     if (ghd_ndp->lu.x->optyp == LSB)
+      {
+local_sel_err:
+       __sgferr(690,
+        "hierarchical reference %s illegal - array of %s illegal",
+        grp->gnam, __to_sytyp(__xs, syphd->sytyp));
+       grp->gr_err = TRUE;
+       return(TRUE);
+      }
+     goto local_1cmp; 
+    }
+
+   /* normal 1 component inst. or top mod. global - handled elsewhere */
+   return(FALSE);
+  }
+ /* if in module symbol head instance, then not local */
+ if (syphd->sytyp != SYM_TSK && syphd->sytyp != SYM_F &&
+  syphd->sytyp != SYM_LB) return(FALSE); 
+
+ /* know this local name expressed with qualified path */
+ /* 1st check head to see if also a module name */
+ if (__get_sym(ncmp, __modsyms) != NULL)
+  {
+   __sgfwarn(532,
+    "local hierarchical name %s path head is also module name - local used",  
+    grp->gnam);
+  }
+ /* NULL means undecl. - error but getting here still means local */
+ /* checks for parameter at end of path in here */
+ /* getting here means first symbol is is declared in module */  
+ if ((syptail = find_inmod_sym(grp, ghd_ndp, syphd, &sytp)) == NULL)
+  {
+   grp->gr_err = TRUE;
+   return(TRUE);
+  }
+ /* after end of instances, local scope object can not be array ref. */
+ if (ghd_ndp->lu.x->optyp == LSB) goto local_sel_err;
+
+ /* know task/func/mod */
+ /* notice ...lb.lb as scope is ok - just like local - and >2 elements */
+ if (syphd->sytyp == SYM_LB && ghd_ndp->ru.x != NULL
+  && ghd_ndp->ru.x->ru.x != NULL)
+  {
+   __sgfinform(401, 
+    "local hierarchical path %s first component is named block", grp->gnam);
+  }
+ /* finally convert to ID but save name for printing */
+ grp->gr_gone = TRUE;
+ /* LOOKATME - again why is this needed since gone turned on */
+ grp->targtskp = syphd->el.etskp;
+
+ locndp = grp->gxndp;
+ __free2_xtree(locndp);
+ /* must set non xmr node tail */
+ locndp->lu.sy = syptail;
+ locndp->optyp = ID;
+ /* re-allocate this so can eventually if needed free global */
+ /* notice must not free gnam field in case free globals (shouldn't) */  
+ /* FIXME - should for inst. array references need to convert to numbers */
+ locndp->ru.qnchp = grp->gnam;
+ grp->gnam = NULL;
+ locndp->locqualnam = TRUE;
+ /* global is now removed */
+ return(TRUE);
+}
+
+/*
+ * check a wire tail to make sure not illegal parameter wire form
+ * know symbol is wire to be called 
+ */
+static int32 chk_xmr_tail_wire(struct gref_t *grp, struct sy_t *tailsyp,
+ int32 is_loc1cmp)
+{
+ struct net_t *np;
+
+ switch ((byte) tailsyp->sytyp) {
+  /* these are legal in some places - various kinds of xmrs checked for in */
+  /* place of use */
+  case SYM_I: case SYM_M: case SYM_LB: case SYM_F: case SYM_TSK: break;
+  case SYM_N:
+   /* this if fixup of guessed wrong because sys. task special arg xmr */
+   /* that is really net */
+   np = tailsyp->el.enp;
+   /* if resolving defparam lhs xmr, parameter ok and required but */
+   /* if not error caught later */
+   if (grp->gr_defparam) break;
+
+   if (!is_loc1cmp && np->n_isaparam)
+    {
+     __sgferr(769,
+      "hierarchical reference %s tail variable %s cannot be a parameter",
+      grp->gnam, np->nsym->synam);
+     return(FALSE);
+    }
+   break;
+  default:
+   __sgferr(766, "hierarchical reference %s tail %s cannot be a %s",
+    grp->gnam, tailsyp->synam, __to_sytyp(__xs, tailsyp->sytyp));
+  }
+ return(TRUE);
+}
+
+/*
+ * fill defparam component symbol array first element 
+ * this forces symbol location of all remaining components 
+ *
+ * only legal possibilites are 1) instance in current module 2) top level
+ * module, and 3) upward module type reference (this is error caught by
+ * caller)
+ *
+ * return F on error else T - error message emitted here
+ */
+static int32 fill_dfp_gsymhead(struct gref_t *grp, struct expr_t *ghd_ndp)
+{
+ int32 comp_isel; 
+ struct sy_t *syp, *modsyp;
+ struct symtab_t *sytp;
+ struct expr_t *ndp;
+ char *ncmp;
+
+ comp_isel = FALSE;
+ if (ghd_ndp->lu.x->optyp == XMRID) ndp = ghd_ndp->lu.x;
+ else if (ghd_ndp->lu.x->optyp == LSB)
+   { ndp = ghd_ndp->lu.x->lu.x; comp_isel = TRUE; }
+ else { __case_terr(__FILE__, __LINE__); return(FALSE); }
+
+ ncmp = ndp->ru.qnchp;
+ /* if can possibly be rooted from top module or above module, save symbol */
+ modsyp = __get_sym(ncmp, __modsyms);
+
+ /* 1st priority is instance (must exist) in mod where glb ref. appeared */
+ /* but maybe accessed from contained task or named block scope */
+ for (sytp = grp->grsytp; sytp != NULL; sytp = sytp->sytpar)
+  { if (sytp->sypofsyt->sytyp == SYM_M) goto got_inst; } 
+ __misc_terr(__FILE__, __LINE__);
+  
+ /* look up in inst. symbol table only */
+got_inst:
+ if ((syp = __zget_sym(ncmp, sytp->stsyms, sytp->numsyms)) != NULL)
+  {
+   if (syp->sytyp != SYM_I)
+    {
+     __sgfwarn(533,
+      "defparam left hand side %s head %s %s in %s not instance - assuming rooted",
+      grp->gnam, __to_sytyp(__xs, syp->sytyp), ncmp, sytp->sypofsyt->synam);
+     syp = NULL;
+     goto try_mod1st;
+    }
+   /* emit warning if also could be rooted but use inst. */
+   if (modsyp != NULL)
+    {
+     __sgfwarn(534,
+      "defparam left hand side %s head %s both upward module and downward instance - instance used",
+      grp->gnam, ncmp);
+    }
+   __glbsycmps[0] = syp;
+   if (comp_isel)
+    {
+     __glbxcmps[0] = ghd_ndp->lu.x->ru.x;
+     grp->path_has_isel = TRUE;
+    }
+   else __glbxcmps[0] = NULL;
+   __last_gsc = 0;
+   return(TRUE);
+  }
+
+ /* did not find instance name - see if matches module name */
+try_mod1st:
+ if (modsyp == NULL)
+  {
+   __sgferr(757,
+    "rooted or upward relative defparam left hand side %s first component %s illegal or undeclared",
+    grp->gnam, ncmp);
+   return(FALSE);
+  }
+ /* since upward module not instance, error if select */
+ if (comp_isel) 
+  {
+   __sgferr(692,
+    "rooted or upward relative path %s head %s not instance array - select illegal",
+    grp->gnam, ncmp);
+   return(FALSE);
+  }
+
+ /* know this is module and if non rooted for now assume above */
+ __glbsycmps[0] = modsyp;
+ __glbxcmps[0] = NULL;
+ __last_gsc = 0;
+ /* notice cannot check if upward really above in itree until prep. time */
+ if (modsyp->el.emdp->minstnum != 0) grp->upwards_rel = TRUE; 
+ else grp->is_rooted = TRUE;
+ return(TRUE);
+}
+
+/*
+ * fill global component symbol array first element 
+ * this forces symbol location of all remaining components 
+ *
+ * 09/14/00 - SJM now allow insts above this inst as first to check
+ * LOOKATME - for now module type found above must be same for all insts
+ *            but can come from inst or mod (happens when same name)
+ *
+ * only legal possibilites are 1) instance in current module 2) instance
+ * above 3) top level module, and 4) upward module
+ *
+ * return F on error else T - error message emitted here
+ */
+static int32 fill_gsymhead(struct gref_t *grp, struct expr_t *ghd_ndp)
+{
+ int32 comp_isel; 
+ struct sy_t *syp, *syp2, *modsyp, *scope_syp;
+ struct symtab_t *sytp;
+ struct expr_t *ndp;
+ struct mod_t *imdp;
+ struct itree_t *in_itp;
+ char *ncmp;
+
+ comp_isel = FALSE;
+ if (ghd_ndp->lu.x->optyp == XMRID) ndp = ghd_ndp->lu.x;
+ else if (ghd_ndp->lu.x->optyp == LSB)
+   { ndp = ghd_ndp->lu.x->lu.x; comp_isel = TRUE; }
+ else { __case_terr(__FILE__, __LINE__); return(FALSE); }
+
+ ncmp = ndp->ru.qnchp;
+ /* if can possibly be rooted from top module or above module, save symbol */
+ /* but first priority is instance in module and then instance above */
+ modsyp = __get_sym(ncmp, __modsyms);
+
+ /* if ref in task/named block, first move up to inst sym tab */
+ /* will always find it and usually already there */
+ /* know if is it not XMR but really local path ref, won't get here */
+ for (sytp = grp->grsytp; sytp != NULL; sytp = sytp->sytpar)
+  { if (sytp->sypofsyt->sytyp == SYM_M) goto inst_sytab; } 
+ __misc_terr(__FILE__, __LINE__);
+  
+inst_sytab:
+ /* case 1: first priority downward relative inst name */
+ syp = __zget_sym(ncmp, sytp->stsyms, sytp->numsyms);
+ if (syp == NULL) goto try_rooted; 
+ if (syp->sytyp != SYM_I)
+  {
+   /* LOOKATME - think this can only happen for top level named blocks */
+   __sgfwarn(533,
+    "hierarchical path %s head defined as %s %s in %s not instance - assuming upward name or rooted",
+    grp->gnam, __to_sytyp(__xs, syp->sytyp), ncmp, sytp->sypofsyt->synam);
+   syp = NULL;
+   goto try_rooted;
+  }
+ /* emit inform if can also be rooted */
+ if (modsyp != NULL && modsyp->el.emdp->minstnum == 0)
+  {
+   __sgfinform(464,
+    "hierarchical path %s head %s downward relative but also top level module - could be rooted path",
+    grp->gnam, ncmp);
+  }
+ /* emit inform if can be upward relative instance - just check one 0th inst */
+ if (fnd_uprel_inst(ncmp, grp->gin_mdp->moditps[0]) != NULL)
+  {
+   __sgfinform(464,
+    "hierarchical path %s head %s downward relative but also upward instance - could be upward relative path",
+    grp->gnam, ncmp);
+  }
+ /* emit inform if can be upward relative instance - just check 0th inst */
+ if (modsyp != NULL && fnd_uprel_mod(modsyp, grp->gin_mdp->moditps[0]))
+  {
+   __sgfinform(464,
+    "hierarchical path %s head %s downward relative but also upward module type name - could be upward relative path",
+    grp->gnam, ncmp);
+  }
+ __glbsycmps[0] = syp;
+ if (comp_isel)
+  {
+   __glbxcmps[0] = ghd_ndp->lu.x->ru.x;
+   grp->path_has_isel = TRUE;
+  }
+ else __glbxcmps[0] = NULL;
+ __last_gsc = 0;
+ return(TRUE);
+
+try_rooted: 
+ /* SJM 09/18/00 - LRM says upward relative inst before rooted-think wrong */
+ if (modsyp != NULL && modsyp->el.emdp->minstnum == 0)
+  {
+   imdp = modsyp->el.emdp;
+   /* first inform if upward instance but not top */
+   if ((syp2 = fnd_uprel_inst(ncmp, grp->gin_mdp->moditps[0])) != NULL
+    && syp2->el.emdp->minstnum != 0)
+    {
+     __sgfinform(464,
+      "hierarchical path %s rooted but head %s also other and lower upward instance - rooted path used",
+      grp->gnam, ncmp);
+   }
+   /* notice can't be upward module since module is top or not get here */
+   goto found_ref;
+  }
+ /* see if upward inst that is not rooted - use 0th instance for find */
+ /* works because all upward relative paths must find same module type */
+ in_itp = grp->gin_mdp->moditps[0];
+ if ((syp = fnd_uprel_inst(ncmp, in_itp)) != NULL)
+  {
+   /* found an upward relative inst, if more than one in src, error */
+   /* if do not find same module for all */
+   if (grp->gin_mdp->minstnum > 1) 
+    {
+     /* if instantiated in many places must always find exactly same */
+     /* uprel module type */
+     if (!chk_all_uprels_same(grp, modsyp, ncmp, ghd_ndp)) return(FALSE);
+    }
+
+   /* inform if found inst and head also upward mod name - know not rooted */
+   if (modsyp != NULL && fnd_uprel_mod(modsyp, in_itp))
+    {
+     __sgfinform(464,
+      "hierarchical path %s head %s upward relative instance but %s also upward module - instance used",
+      grp->gnam, ncmp, ncmp);
+    }
+   /* if found, uprel instance it becomes mod sym */
+   modsyp = syp; 
+   if (grp->gin_mdp->minstnum > 1) 
+    {
+     /* if instantiated in many places must always find exactly same */
+     /* uprel module type */
+     if (!chk_all_uprels_same(grp, modsyp, ncmp, ghd_ndp)) return(FALSE);
+    }
+   goto found_ref;
+  }
+ /* see if upward relative module - inst array select impossible */
+ if (comp_isel) 
+  {
+   __sgferr(692,
+    "rooted or upward relative path %s head instance array select %s not found",
+    grp->gnam, ncmp);
+   return(FALSE);
+  }
+ /* if head is type name, see if upward relative module name */
+ if (modsyp != NULL)
+  {
+   if (!fnd_uprel_mod(modsyp, in_itp)) goto try_tskscope;
+
+   /* here no conflict possible but check for all same module containing */ 
+   /* reference instantiated in source in different places */
+
+   if (grp->gin_mdp->minstnum > 1) 
+    {
+     /* if instantiated in many places must always find exactly same */
+     /* uprel module type */
+     if (!chk_all_uprels_same(grp, modsyp, ncmp, ghd_ndp)) return(FALSE);
+    }
+   goto found_ref;
+  } 
+
+try_tskscope:
+ /* FIXME - will this be seen as XMR? - think not and test */
+ /* finally try to find name as task/func/named block (other scope) */
+ /* anywhere in upward module - must be one component non select form */
+ if (ghd_ndp->ru.x == NULL)
+  {
+   if ((imdp = fnd_uprel_tskfunc(&scope_syp, ncmp, in_itp)) == NULL)
+    goto ref_err;
+
+   __last_gsc = 1;
+   __glbsycmps[0] = imdp->msym;
+   __glbxcmps[0] = NULL;
+   __glbsycmps[__last_gsc] = scope_syp;
+   __glbxcmps[__last_gsc] = NULL; 
+
+   /* this must always be upward relative even if in top module */
+   grp->upwards_rel = TRUE; 
+   grp->is_upreltsk = TRUE;
+   grp->targtskp = scope_syp->el.etskp;
+   /* here can't call fill grest syms */
+   return(TRUE);
+  }
+
+ /* finally, not found */
+ref_err:
+ /* SJM 03/29/02 - for 1 component - assume undeclared */
+ if (ghd_ndp->ru.x == NULL)
+  {
+   /* DBG remove */
+   if (strcmp(ncmp, grp->gnam) != 0) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   __sgferr(757,
+    "%s undeclared - possibly undeclared one component cross module reference",
+    grp->gnam);
+  }
+ else
+  {
+   __sgferr(757,
+    "rooted, downward relative or upward relative hierarchical reference %s first component %s not found - illegal path head or undeclared",
+    grp->gnam, ncmp);
+  }
+ return(FALSE);
+ 
+found_ref:
+ /* know this is module and if non rooted for now assume above */
+ __glbsycmps[0] = modsyp;
+ __glbxcmps[0] = NULL;
+ __last_gsc = 0;
+ /* notice cannot check if upward really above in itree until prep. time */
+ if (modsyp->el.emdp->minstnum != 0) grp->upwards_rel = TRUE; 
+ else grp->is_rooted = TRUE;
+ return(TRUE);
+}
+
+/*
+ * for every instance of gin module type, find uprel dest and check to
+ * make sure destination the same
+ *
+ * also checks each instance's uprel
+ */
+static int32 chk_all_uprels_same(struct gref_t *grp, struct sy_t *modsyp,
+ char *ncmp, struct expr_t *ghd_ndp)
+{
+ register int32 ii;
+ register struct itree_t *in_itp;
+ int32 uprel_typ, got_one, fnd_ii, sav_ecnt; 
+ struct sy_t *uprel_syp, *scope_syp, *syp;
+ struct mod_t *imdp;
+
+ uprel_typ = -1;
+ uprel_syp = NULL;
+ fnd_ii = -1;
+ got_one = FALSE;
+ sav_ecnt = __pv_err_cnt;
+ for (ii = 0; ii < grp->gin_mdp->flatinum; ii++)
+  {
+   in_itp = grp->gin_mdp->moditps[ii];
+   /* upward relative instance name - symbol is module not inst */
+   if ((syp = fnd_uprel_inst(ncmp, in_itp)) != NULL)
+    {
+     if (!got_one)
+      { uprel_typ = SYM_I; uprel_syp = syp; got_one = TRUE; fnd_ii = ii; }
+     else
+      {
+       if (uprel_typ != SYM_I || syp != uprel_syp) 
+        {
+        __sgferr(939,
+         "rooted or upward relative instance reference %s for instance %s differs from upward reference for instance %s",
+         grp->gnam, __msg2_blditree(__xs, in_itp),
+         __msg2_blditree(__xs2, grp->gin_mdp->moditps[fnd_ii]));
+        }
+      }
+     continue; 
+    }
+
+   /* upward relative type name */
+   if (modsyp != NULL)
+    { 
+     /* this returns T on success */
+     if (fnd_uprel_mod(modsyp, in_itp))
+      {
+       if (!got_one)
+        { uprel_typ = SYM_M; uprel_syp = modsyp; got_one = TRUE; fnd_ii = ii; }
+       else
+        {
+         if (uprel_typ != SYM_M || modsyp != uprel_syp) 
+          {
+           __sgferr(3402,
+           "upward relative module type reference %s for instance %s differs from upward reference for instance %s",
+           grp->gnam, __msg2_blditree(__xs, in_itp),
+           __msg2_blditree(__xs2, grp->gin_mdp->moditps[fnd_ii]));
+          }
+        }
+       continue; 
+      }
+    }
+
+   /* if only one component, look for upward somwhere task/func */
+   if (ghd_ndp->ru.x == NULL)
+    {
+     if ((imdp = fnd_uprel_tskfunc(&scope_syp, ncmp, in_itp)) != NULL)
+      { 
+       if (!got_one)
+        {
+         uprel_typ = SYM_TSK;
+         uprel_syp = scope_syp;
+         got_one = TRUE;
+         fnd_ii = ii;
+        }
+       else
+        {
+         if (uprel_typ != SYM_TSK || scope_syp != uprel_syp) 
+          {
+           __sgferr(3402,
+           "upward relative task/func/named block reference %s for instance %s differs from upward reference for instance %s",
+           grp->gnam, __msg2_blditree(__xs, in_itp),
+           __msg2_blditree(__xs2, grp->gin_mdp->moditps[fnd_ii]));
+          }
+        }
+       continue; 
+      }
+    } 
+   __sgferr(757,
+    "rooted or upward relative hierarchical reference %s first component %s not found for instance %s - illegal symbol or undeclared",
+    grp->gnam, ncmp, __msg2_blditree(__xs, in_itp));
+  }
+ if (__pv_err_cnt > sav_ecnt) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * match upward relative instance - if found returns mod symbol
+ */
+static struct sy_t *fnd_uprel_inst(char *ncmp, struct itree_t *in_itp)
+{
+ register struct itree_t *up_itp;
+ struct inst_t *ip;
+
+ for (up_itp = in_itp; up_itp != NULL;)
+  { 
+   ip = up_itp->itip;
+   /* know insts in split off module types have unchanged inst name */
+   /* FIXME - should compare inst exprs not just iarr element name */
+   if (strcmp(ncmp, ip->isym->synam) == 0) return(ip->imsym);
+   up_itp = up_itp->up_it;
+  }
+ return(NULL);
+}
+
+/*
+ * match upward relative instance - if found returns T else FALSE
+ */
+static int32 fnd_uprel_mod(struct sy_t *modsyp, struct itree_t *in_itp)
+{
+ register struct itree_t *up_itp;
+ struct mod_t *up_mdp, *up_mast_mdp, *imdp, *mast_imdp;
+ struct inst_t *ip;
+
+ up_mdp = modsyp->el.emdp;
+ up_mast_mdp = __get_mast_mdp(up_mdp);
+ for (up_itp = in_itp; up_itp != NULL;)
+  {
+   /* must match master mod type */
+   ip = up_itp->itip;
+   imdp = ip->imsym->el.emdp;
+   mast_imdp = __get_mast_mdp(imdp);
+   if (mast_imdp == up_mast_mdp) return(TRUE);
+   up_itp = up_itp->up_it;
+  }
+ return(FALSE);
+}
+
+/*
+ * find an upward relative task/func/named block anywhere in uprel inst
+ * if found return module type and set scope syp 
+ */
+static struct mod_t *fnd_uprel_tskfunc(struct sy_t **scope_syp, char *ncmp,
+ struct itree_t *in_itp)
+{
+ register struct itree_t *up_itp;
+ struct sy_t *tskfunc_syp; 
+ struct mod_t *imdp;
+
+ for (up_itp = in_itp; up_itp != NULL;)
+  { 
+   imdp = up_itp->itip->imsym->el.emdp;
+   if ((tskfunc_syp = fnd_tskfunc_inscope(ncmp, imdp->msymtab)) != NULL)
+    {
+     *scope_syp = tskfunc_syp;
+     return(imdp);
+    }
+   up_itp = up_itp->up_it;
+  }
+ return(NULL);
+}
+
+/*
+ * find a scope symbol inside one symbol table scope level    
+ */
+static struct sy_t *fnd_tskfunc_inscope(char *ncmp,
+ struct symtab_t *scope_sytp)
+{
+ struct symtab_t *sytp;
+ struct sy_t *match_syp;
+
+ for (sytp = scope_sytp->sytofs; sytp != NULL; sytp = sytp->sytsib)  
+  {
+   if (strcmp(sytp->sypofsyt->synam, ncmp) == 0) return(sytp->sypofsyt);
+   if ((match_syp = fnd_tskfunc_inscope(ncmp, sytp)) != NULL)
+    return(match_syp);
+  }
+ return(NULL);
+}
+
+/*
+ * set hierarchical global reference symbols for rest of path
+ * know head (pos. 0) filled
+ */
+static int32 fill_grestsyms(struct gref_t *grp, struct expr_t *gcmp_ndp)
+{
+ register int32 gi;
+ int32 comp_isel;
+ struct sy_t *syp;
+ struct symtab_t *sytp;
+ struct expr_t *ndp;
+ char *ncmp;
+
+ syp = __glbsycmps[0];
+ if (syp->sytyp == SYM_I) sytp = syp->el.eip->imsym->el.emdp->msymtab;
+ else sytp = syp->el.emdp->msymtab;
+
+ for (gi = 1;; gi++)
+  {
+   comp_isel = FALSE;
+   if (gcmp_ndp->lu.x->optyp == XMRID) ndp = gcmp_ndp->lu.x;
+   else if (gcmp_ndp->lu.x->optyp == LSB)
+    { ndp = gcmp_ndp->lu.x->lu.x; comp_isel = TRUE; }
+   /* SJM 02/02/05 - part select legal but same as ID here */
+   else if (gcmp_ndp->lu.x->optyp == PARTSEL) ndp = gcmp_ndp->lu.x->lu.x;
+   else { __case_terr(__FILE__, __LINE__); return(FALSE); }
+
+   ncmp = ndp->ru.qnchp;
+   if ((syp = __zget_sym(ncmp, sytp->stsyms, sytp->numsyms)) == NULL)
+    {
+     __sgferr(758, "hierarchical path %s component %s undeclared in %s",
+      grp->gnam, ncmp, sytp->sypofsyt->synam);
+     return(FALSE);
+    }
+   if (++__last_gsc >= MAXGLBCOMPS - 1)
+    {
+     __pv_terr(310, "hierarchical path %s has too many components (%d)",
+      grp->gnam, MAXGLBCOMPS);
+    }
+   __glbsycmps[__last_gsc] = syp;
+   if (comp_isel)
+    {
+     __glbxcmps[__last_gsc] = gcmp_ndp->lu.x->ru.x;
+     grp->path_has_isel = TRUE;
+    }
+   else __glbxcmps[__last_gsc] = NULL;
+  
+   /* here global ending with instance name is ok - non scope caught later */
+   if (syp->sytyp == SYM_I)
+    {
+     /* if instance, move to it module type symbol table */
+     sytp = syp->el.eip->imsym->el.emdp->msymtab;
+     if ((gcmp_ndp = gcmp_ndp->ru.x) == NULL) return(TRUE);
+     continue;
+    }
+   /* if not legal in module hierarchical name type, error */
+   if (syp->sytyp == SYM_N)
+    {
+     if (gcmp_ndp->ru.x != NULL)
+      {
+       __sgferr(761,
+        "hierarchical path %s net %s not rightmost path element",
+        grp->gnam, ncmp); 
+       return(FALSE);
+      }
+     /* SJM 05/02/00 - hierarchical params legal following XL - add if not */
+     /* --
+     if (syp->el.enp->n_isaparam)
+      {
+       __sgferr(762, "path %s component %s illegal hierachical reference to parameter",
+        grp->gnam, ncmp, __to_sytyp(__xs, syp->sytyp)); 
+       return(FALSE);
+      }
+     --- */
+     break;
+    }
+   if (syp->sytyp != SYM_TSK && syp->sytyp != SYM_F && syp->sytyp != SYM_LB)
+    {
+     __sgferr(762, "hierarchical path %s component %s illegal %s symbol type",
+      grp->gnam, ncmp, __to_sytyp(__xs, syp->sytyp)); 
+     return(FALSE);
+    }
+   /* if last symbol, end with task not wire type symbol which is ok */
+   if (gcmp_ndp->ru.x == NULL)
+    {
+     if (gcmp_ndp->lu.x->optyp == LSB)
+      {
+       __sgferr(693,
+        "hierarchical reference %s select of last symbol task %s illegal",
+        grp->gnam, __to_sytyp(__xs, syp->sytyp));
+       return(FALSE);
+      }
+     grp->targtskp = syp->el.etskp;
+     break;
+    }
+
+   /* must be some kind of task or will not get here */
+   sytp = syp->el.etskp->tsksymtab; 
+   /* section of path containing in module symbols removed since only need */
+   /* pointer to symbol and inst. number for var. access same */
+   /* will check for parameter at end of path or wrong thing in here */
+   gcmp_ndp = gcmp_ndp->ru.x;
+   if ((syp = find_inmod_sym(grp, gcmp_ndp, syp, &sytp)) != NULL) 
+    {
+     /* by here skipped over all in module symbols, syp is the end */
+     __last_gsc = gi;
+     __glbsycmps[__last_gsc] = syp;
+     /* since in mod, can never be select - error already caught */
+     __glbxcmps[__last_gsc] = NULL; 
+     grp->targtskp = sytp->sypofsyt->el.etskp;
+     break;
+    }
+   /* if found match but rest is not in module global - keep looking */
+   /* and will emit error */
+  }
+ return(TRUE);
+}
+
+/*
+ * find in module symbol - know previous symbol selected module  
+ * or local task/block/function hierarchical name root
+ *
+ * end of path here can be scope named block/func/task/mod/inst etc.
+ * this must also return (set) symbol table where last symbol declared
+ */
+static struct sy_t *find_inmod_sym(struct gref_t *grp, struct expr_t *gcmp_ndp,
+ struct sy_t *syp, struct symtab_t **endsytp)
+{
+ struct expr_t *ndp;
+ struct symtab_t *sytp;
+
+ sytp = *endsytp;
+ for (;;)
+  {
+   if (gcmp_ndp->lu.x->optyp == XMRID) ndp = gcmp_ndp->lu.x;
+   else if (gcmp_ndp->lu.x->optyp == LSB)
+    {
+     __sgferr(694,
+     "hierarchical path %s select of %s component illegal - not instance array",
+      grp->gnam, __to_sytyp(__xs, syp->sytyp));
+     return(NULL);
+    }
+   else { __case_terr(__FILE__, __LINE__); return(FALSE); }
+
+   syp = __zget_sym(ndp->ru.qnchp, sytp->stsyms, sytp->numsyms);
+   if (gcmp_ndp->ru.x == NULL) break;
+
+   if (syp == NULL)
+    {
+     /* did not find next path component */
+     __sgferr(763, "hierarchical path %s component %s undeclared", grp->gnam,
+      ndp->ru.qnchp);
+     return(NULL);
+    } 
+   if (syp->sytyp != SYM_LB)
+    {
+     __sgferr(764, 
+      "hierarchical path %s internal component %s type %s instead of expected named block",
+      grp->gnam, ndp->ru.qnchp, __to_sytyp(__xs, syp->sytyp));
+     return(NULL);
+    }
+   sytp = syp->el.etskp->tsksymtab; 
+   gcmp_ndp = gcmp_ndp->ru.x;
+  }
+ /* syp is tail (actual variable), if declared replace - checking later */
+ if (syp == NULL)
+  {
+   __sgferr(765,
+    "internal hierarchical path %s part last component %s undeclared",
+    grp->gnam, ndp->ru.qnchp);
+   return(NULL);
+  }
+ if (!chk_xmr_tail_wire(grp, syp, FALSE)) return(NULL);
+ *endsytp = sytp;
+ return(syp);
+}
+
+/*
+ * check global selects 
+ *
+ * error if select of non inst array and non select of inst. array
+ * this is called during global input, can not check select exprs
+ */
+static int32 chk_glb_inst_sels(struct gref_t *grp)
+{
+ register int32 gi;
+ int32 good, ii;
+ struct sy_t *syp, *up_syp;
+ struct inst_t *ip;
+ struct mod_t *mdp, *up_mdp;
+
+ for (good = TRUE, up_syp = NULL, gi = 0; gi <= __last_gsc; gi++)
+  {
+   syp = __glbsycmps[gi];
+   if (syp->sytyp != SYM_I)
+    {
+     if (__glbxcmps[gi] != NULL)
+      {
+       __sgferr(695,
+        "hierarchical path %s illegal select of %s symbol - never arrayed",
+        grp->gnam, __to_sytyp(__xs, syp->sytyp));
+       good = FALSE;
+      }
+     continue;
+    }
+   /* know symbol is instance */
+   /* if inst select but not array of instances, select illegal */
+   ip = syp->el.eip;
+   mdp = ip->imsym->el.emdp;
+   /* know this component inst, need to access up module */
+   if (gi == 0)
+    {
+     /* first component instance mean down relative */
+     /* DBG remove -- */
+     if (grp->is_rooted) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     up_mdp = grp->gin_mdp;
+    }
+   else
+    {
+     up_syp = __glbsycmps[gi - 1];
+     if (up_syp->sytyp == SYM_I) up_mdp = up_syp->el.eip->imsym->el.emdp;
+     else if (up_syp->sytyp == SYM_M) up_mdp = up_syp->el.emdp;
+     else { up_mdp = NULL;__case_terr(__FILE__, __LINE__); }
+    }
+   ii = ((byte *) ip - (byte *) up_mdp->minsts)/sizeof(struct inst_t);
+
+   if (up_mdp->miarr == NULL || up_mdp->miarr[ii] == NULL)
+    {
+     if (__glbxcmps[gi] == NULL) continue;
+     __sgferr(696,
+      "hierarchical path %s select illegal for non vectored instance %s (type %s)",
+      grp->gnam, ip->isym->synam, mdp->msym->synam);
+     good = FALSE;
+     continue;
+    }
+   /* final case vectored instance - select required */ 
+   if (__glbxcmps[gi] != NULL) continue;
+   __sgferr(697,
+    "hierarchical path %s missing required select of vectored instance %s (type %s)",
+    grp->gnam, ip->isym->synam, mdp->msym->synam);
+   good = FALSE;
+  }
+ return(good);
+}
+
+/*
+ * ROUTINES TO ACCESS AND BUILD GLOBALS USING STRINGS
+ */
+
+/*
+ * convert global reference as string into global path expression
+ *
+ * no white space allowed except to end escaped IDs
+ * handles escaped IDs (\...[white space] and ending [<number>] for inst arrays 
+ * source xmr's can have spaces but not allowed here - make sure documented
+ *
+ * this can return one component xmr
+ */
+extern struct expr_t *__glbnam_to_expr(char *irefs)
+{
+ int32 slen, ind, esc_name;
+ struct expr_t *glbndp, *gcmp_ndp, *sel_ndp;
+ char *chp, *chp2, *chp3, *sepchp;
+ char s1[IDLEN], s2[IDLEN], s3[IDLEN];
+
+ /* allocate top node */
+ glbndp = __alloc_newxnd();
+ glbndp->optyp = GLBREF;
+ gcmp_ndp = glbndp;
+ for (chp = irefs;;)
+  {
+   /* separate out one component */
+   /* case 1: escaped name */
+   esc_name = FALSE;
+   if (*chp == '\\') 
+    {
+     if (chp[1] == ' ') 
+      {
+       __sgferr(1138, 
+        "global reference %s illegal - empty escaped component illegal",
+        irefs); 
+bad_end:
+       __free_xtree(glbndp);
+       return(NULL);
+      }
+     if ((chp2 = strchr(chp, ' ')) == NULL)
+      {
+       __sgferr(1138, 
+        "global reference %s illegal - escaped component ending space missing",
+        irefs); 
+       goto bad_end;
+      }
+     /* include one space in escaped ID */
+     chp2++;
+     strncpy(s1, chp, chp2 - chp);
+     /* escaped ID now extracted into s1 */
+     s1[chp2 - chp] = '\0';
+     while (*chp2 == ' ') chp2++;
+     if (*chp2 == '[')
+      {
+       if ((chp3 = strchr(chp2, ']')) == NULL)
+        {
+         __sgferr(1139, 
+          "global reference %s illegal - instance array select missing ']'",
+          irefs);
+         goto bad_end; 
+        }
+       chp3++;
+       strncpy(s2, chp2, chp3 - chp2); 
+       s2[chp3 - chp2] = '\0';
+       strcat(s1, s2); 
+       /* one past ending ']' */ 
+       sepchp = chp3;
+      }
+     else sepchp = chp2;
+     esc_name = TRUE;
+    }
+   else
+    { 
+     /* case 2: non escaped maybe instance array select */ 
+     if ((chp2 = strchr(chp, '.')) != NULL)
+      {
+       strncpy(s1, chp, chp2 - chp);
+       s1[chp2 - chp] = '\0';
+       /* point to '.' separator */
+       sepchp = chp2;
+      }
+     else
+      {
+       strcpy(s1, chp);
+       slen = strlen(chp);
+       /* point to '\0' */
+       sepchp = &(chp[slen]);
+      }
+    }
+   /* s1 contains component maybe with select */
+   if (esc_name || (chp = strchr(s1, '[')) == NULL) 
+    {
+     /* case 1: non instance select form */
+     gcmp_ndp->ru.x = __alloc_newxnd();
+     gcmp_ndp->ru.x->optyp = XMRCOM;
+     gcmp_ndp = gcmp_ndp->ru.x;
+     gcmp_ndp->lu.x = __alloc_newxnd();
+     gcmp_ndp->lu.x->optyp = XMRID;
+     gcmp_ndp->lu.x->ru.qnchp = __pv_stralloc(s1);
+    }
+   else 
+    {
+     /* case 2: instance select form */
+     /* chp points into [ in s1 */
+     strncpy(s2, s1, chp - s1); 
+     s2[chp - s1] = '\0';
+     if ((chp2 = strchr(chp, ']')) == NULL)
+      {
+       __sgferr(1139, 
+        "global reference %s illegal - instance array select missing ']'",
+        irefs);
+       goto bad_end; 
+      }
+     chp++;
+     /* chp point to first digit that gets put into s3 */
+     strncpy(s3, chp, chp2 - chp); 
+     s3[chp2 - chp] = '\0';
+     for (chp = s3; *chp != '\0'; chp++)
+      {
+       if (!isdigit(*chp))
+        {
+bad_sel_index:
+          __sgferr(1139, 
+          "global reference %s illegal - instance select must be number",
+          irefs);
+         goto bad_end;
+        }
+      }
+     if (sscanf(s3, "%d", &ind) != 1 || ind < 0) goto bad_sel_index;
+     sel_ndp = __alloc_newxnd();
+     sel_ndp->optyp = LSB;
+     sel_ndp->lu.x = __alloc_newxnd();
+     sel_ndp->lu.x->optyp = XMRID;
+     sel_ndp->lu.x->ru.qnchp = __pv_stralloc(s2);
+     sel_ndp->ru.x = __alloc_newxnd();
+     __set_numval(sel_ndp->ru.x, (word32) ind, 0L, WBITS);
+
+     gcmp_ndp->ru.x = __alloc_newxnd();
+     gcmp_ndp->ru.x->optyp = XMRCOM;
+     gcmp_ndp = gcmp_ndp->ru.x;
+     gcmp_ndp->lu.x = sel_ndp;
+    } 
+   /* sepchp points into separae iref string */
+   if (*sepchp  == '\0') break;
+   else if (*sepchp != '.') 
+    {
+     __sgferr(1139, 
+      "global reference %s internal component not followed by '.' separator",
+      irefs);
+     goto bad_end; 
+    } 
+   chp = sepchp;
+   chp++;
+  }
+ return(glbndp);
+}
+
+/*
+ * return pointer to component name of current component of global expr 
+ *
+ * FIXME - this returns instance name but does not deal with number index
+ */
+extern char *__to_glbcmp_nam(struct expr_t *gcmp_ndp)
+{
+ char *chp;
+
+ if (gcmp_ndp->lu.x->optyp == XMRID) chp = gcmp_ndp->lu.x->ru.qnchp;
+ else if (gcmp_ndp->lu.x->optyp == LSB || gcmp_ndp->lu.x->optyp == PARTSEL)
+  chp = gcmp_ndp->lu.x->lu.x->ru.qnchp;
+ else { __case_terr(__FILE__, __LINE__); return(NULL); }
+ return(chp);
+}
+
+/*
+ * ROUTINES TO FREE GLOBAL DATA STRUCTURES
+ */
+
+/*
+ * free a defparam
+ * may want to keep defparams and global for debugging
+ * but latest value of parameter is what is needed not defparam
+ *
+ * global marked as gone so will be freed later
+ */
+extern void __free_1dfparam(struct dfparam_t *dfpp)
+{
+ if (dfpp->last_dfpi > -1 && dfpp->dfpiis != NULL)
+  __my_free((char *) dfpp->dfpiis, (dfpp->last_dfpi + 1)*sizeof(int32));
+ __free_xtree(dfpp->dfpxlhs);
+ /* notice cannot free rhs since moved to parameter value rhs */
+ /* if error, will stop so no need to free */
+ __my_free((char *) dfpp, sizeof(struct dfparam_t));
+}
+
+/*
+ * free globals marked to be freed - mostly for defparam tmp globals
+ *
+ * must remove gone and err from grtab and fix up gxndp ptrs or
+ * will process with empty guts and can't skip steps if only defparams
+ */
+static void free_gone_glbs(void)
+{ 
+ register int32 gri, ngri;
+ register struct gref_t *grp;
+ register struct mod_t *mdp;
+ struct gref_t *ngrtab;
+ int32 ngrnum;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mgrnum == 0) continue;
+   __push_wrkitstk(mdp, 0);
+
+   /* first count remaining */
+   grp = &(mdp->mgrtab[0]);
+   for (ngrnum = gri = 0; gri < __inst_mod->mgrnum; grp++, gri++) 
+    {
+     /* if global gone or error will not get counted at all */
+     if (grp->gr_err || grp->gr_gone) continue; 
+     ngrnum++;
+    }
+   /* nothing to remove */
+   if (ngrnum == __inst_mod->mgrnum) goto nxt_mod;
+   /* all removed */
+   if (ngrnum == 0)
+    {
+     __my_free((char *) __inst_mod->mgrtab,
+      __inst_mod->mgrnum*sizeof(struct gref_t));
+     __inst_mod->mgrtab = NULL;
+     __inst_mod->mgrnum = 0;
+     goto nxt_mod;
+    }
+
+   ngrtab = (struct gref_t *) __my_malloc(ngrnum*sizeof(struct gref_t));
+   grp = &(mdp->mgrtab[0]);
+   for (ngri = gri = 0; gri < __inst_mod->mgrnum; grp++, gri++) 
+    {
+     /* this frees contents of global but left in table */
+     if (grp->gr_err || grp->gr_gone) { __free_1glb_flds(grp); continue; }
+
+     ngrtab[ngri] = *grp; 
+     ngrtab[ngri].gxndp->ru.grp = &(ngrtab[ngri]);
+     ngri++;
+    }
+   __my_free((char *) __inst_mod->mgrtab,
+    __inst_mod->mgrnum*sizeof(struct gref_t));
+   __inst_mod->mgrtab = ngrtab;
+   __inst_mod->mgrnum = ngrnum;
+
+nxt_mod:
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * allocate and fill new gref table 
+ *
+ * also always fixes up r_u ptrs from expr. to to newly alloced global
+ */
+extern struct gref_t *__alloc_grtab(struct gref_t *oldgrtab, int32 grnum)
+{
+ register int32 gri;
+ register struct gref_t *grp; 
+ struct gref_t *ngrtab;
+
+ /* DBG remove -- */
+ if (grnum <= 0) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ ngrtab = (struct gref_t *) __my_malloc(grnum*sizeof(struct gref_t));
+ memcpy(ngrtab, oldgrtab, grnum*sizeof(struct gref_t));
+
+ /* pointer from expr nodes need to be fixed to point to new addr */
+ grp = &(ngrtab[0]);
+ for (gri = 0; gri < grnum; grp++, gri++) grp->gxndp->ru.grp = grp; 
+ return(ngrtab);
+}
+
+/*
+ * free 1 global's fields 
+ *
+ * caller must free table containing this global if needed
+ * LOOKATME - what if gnam in name table (think never calling this then)? 
+ */
+extern void __free_1glb_flds(struct gref_t *grp)
+{
+ /* if using this for local qualifed name will be set to nil */
+ if (grp->gnam != NULL) __my_free((char *) grp->gnam, strlen(grp->gnam + 1));
+ grp->gnam = NULL;
+ /* also free glb ref exprssion - always in malloced memory here */
+ __free_xtree(grp->glbref);
+
+ /* only sized targu is upwards rel list - may not have been alloced yet */
+ if (grp->upwards_rel && grp->targu.uprel_itps != NULL)
+  {
+   __my_free((char *) grp->targu.uprel_itps,
+    grp->gin_mdp->flatinum*sizeof(struct itree_t *));
+  } 
+ if (grp->grcmps != NULL)
+  {
+   __my_free((char *) grp->grcmps, (grp->last_gri + 1)*sizeof(struct sy_t *));
+   grp->grcmps = NULL;
+  }
+ if (grp->grxcmps != NULL)
+  {
+   __my_free((char *) grp->grxcmps,
+    (grp->last_gri + 1)*sizeof(struct expr_t *));
+   grp->grxcmps = NULL;
+  }
+}
+
+/*
+ * ROUTINES TO DO POUND PARAM SPLITTING
+ */
+
+/*
+ * work form bottom up marking all instances that need to be split
+ * and all params that are width determining or indirect width determining 
+ */
+static void mark_poundparam_splitinsts(void)
+{
+ register int32 ii, mlevel, pi;
+ int32 split_inst;
+ struct mod_t *mdp;
+ int32 giawid;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+ struct giarr_t *giap;
+ struct expr_t *pxp;
+ struct net_t *modnp;
+
+ /* bottom modules which do not instantiate anything special case */
+ for (mdp = __mdlevhdr[0]; mdp != NULL; mdp = mdp->mlevnxt)
+  {
+   /* for bottom pound params, if only one flat instance - nothing to do */
+   /* because if only one flat instance then know anything instantiating */
+   /* also only one flat inst */
+   if (mdp->flatinum == 1) continue;
+
+   __push_wrkitstk(mdp, 0);
+   /* this also set mod has width determining bit */
+   if (!mdp->mwiddetdone)
+    { __mark_widdet_params(mdp); mdp->mwiddetdone = TRUE; }
+   __pop_wrkitstk();
+  }
+
+ /* work upward in levelized dag marking width determining params and */ 
+ /* instance that need to be split */
+ __pndparam_splits = FALSE;
+ for (mlevel = 1; mlevel <= __dagmaxdist; mlevel++)
+  {
+   for (mdp = __mdlevhdr[mlevel]; mdp != NULL; mdp = mdp->mlevnxt)
+    {
+     __push_wrkitstk(mdp, 0);
+
+     /* width determining needs module context - always set here */
+     /* if has width determining, becomes probable if ever instantiated */
+     /* if only 1 inst in design no need to mark width determining */
+     if (mdp->flatinum > 1)
+      {
+       if (!mdp->mwiddetdone)
+        { __mark_widdet_params(mdp); mdp->mwiddetdone = TRUE; }
+      }
+
+     /* even if only one inst of mod, must still try to split insts of mod in*/ 
+
+     /* for every instance in module, see if need to split */
+     for (ii = 0; ii < __inst_mod->minum; ii++)
+      {
+       /* if instance in mod is inst array (first) never split and do not */
+       /* even check other expanded from in source instance array */
+       /* pound param splitting in inst arrays illegal */
+       /* LOOKATME - is error emitted somewhere? */
+       /* for contained insts that came from mi arrays, no pnd param split */
+       if (__inst_mod->miarr != NULL && (giap = __inst_mod->miarr[ii]) != NULL)
+        {
+         giawid = __get_giarr_wide(giap);
+         /* always inc by one in for loop above */
+         ii += (giawid - 1);
+         continue;
+        }
+
+       ip = &(__inst_mod->minsts[ii]);
+       if (ip->ipxprtab == NULL) continue;
+
+       /* LOOKATME - think these not used */
+       __sfnam_ind = ip->isym->syfnam_ind;
+       __slin_cnt = ip->isym->sylin_cnt;
+
+       /* imdp is module type of instance that has pound param */
+       imdp = ip->imsym->el.emdp;
+
+       /* if one inst never split - even if in later splitting by here */
+       /* spliting would result in 0 insts, mark here but stop when split */
+       if (imdp->flatinum == 1)
+        {
+         if (__debug_flg)
+          {
+           __dbg_msg("++ # form inst. %s(%s) not split - only one instance\n",
+           ip->isym->synam, imdp->msym->synam);
+          } 
+         continue;
+        }
+       /* know contained module has all width determining params set */
+       /* if no width determining and no indir width determining, done */
+       if (!imdp->mhas_widthdet && !imdp->mhas_indir_widdet)
+        {
+         if (__debug_flg)
+          {
+           __dbg_msg(
+            "++ # form inst. %s(%s) not split - no params in ranges\n",
+            ip->isym->synam, imdp->msym->synam);
+          } 
+         continue;
+        }
+
+       split_inst = FALSE;
+       /* go through defined params in one down mod */
+       for (pi = 0; pi < imdp->mprmnum; pi++)
+        {
+         pxp = ip->ipxprtab[pi];
+         /* explicit form this one unused or short list */
+         if (pxp == NULL) continue;
+
+         modnp = &(imdp->mprms[pi]);
+         /* if down mod has width determining, but none of the width */
+         /* determining passed down to this inst. as pound param, no split */
+         if (modnp->nu.ct->n_widthdet || modnp->nu.ct->n_indir_widthdet)
+          {
+           /* set indirect width determining */
+
+           /* if no up expr params set as indirect width determining, do not */
+           /* need to split, but other source locs insts of type may split */
+           /* returns T if any set */
+           if (indir_widthdet_markparam(pxp)) split_inst = TRUE;
+          }
+        }
+       /* if no width determining and no indir width determining, done */
+       if (!split_inst)
+        {
+         if (__debug_flg)
+          {
+           __dbg_msg(
+            "++ # form inst. %s(%s) not split - no range # params\n",
+            ip->isym->synam, imdp->msym->synam);
+          } 
+        }
+       ip->i_pndsplit = TRUE; 
+      }
+     __pop_wrkitstk();
+    }
+  }
+}
+
+/*
+ * set the indirect width determining bit for any wire up pound param expr
+ * return T if any params in this up expr else F
+ */
+static int32 indir_widthdet_markparam(struct expr_t *xp)
+{
+ int32 rv, rv2;
+ struct net_t *np;
+
+ rv = rv2 = FALSE;
+ if (__isleaf(xp))
+  {
+   if (xp->optyp == ID && xp->lu.sy->sytyp == SYM_N)
+    {
+     np = xp->lu.sy->el.enp; 
+     if (np->n_isaparam)
+      {
+       /* if already width determining, can't be indir width determining */
+       if (!np->nu.ct->n_widthdet)
+        {
+         np->nu.ct->n_indir_widthdet = TRUE;
+         __inst_mod->mhas_indir_widdet = TRUE;
+         rv = TRUE;
+        }
+      }
+    }
+   return(rv);
+  }
+ if (xp->lu.x != NULL) rv = indir_widthdet_markparam(xp->lu.x);
+ if (xp->ru.x != NULL) rv2 = indir_widthdet_markparam(xp->ru.x);
+ if (rv || rv2) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * work from top down splitting off static instance locations for
+ * pound parameters that are width determining or indirect width determining
+ * such instances are already marked
+ *
+ * splitting here may produce modules with more than 1 flat instance
+ */
+static void do_poundparam_splitting(void)
+{
+ register int32 ii, mlevel;
+ register struct mod_t *mdp;
+ int32 giawid;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+ struct giarr_t *giap;
+
+ __pndparam_splits = FALSE;
+ /* work from top (mod) down - since need fixed no pound param start */
+ /* LOOKATME - wonder if bottom up works - think not */
+ for (mlevel = __dagmaxdist; mlevel >= 1; mlevel--)
+  {
+   /* SJM 03/16/04 - notice processing from one up and splitting (if needed) */
+   /* contained insts - therefore mlevel of md lev hdr list not chged */
+   /* inside this loop - mlevel one less may use update list */
+   for (mdp = __mdlevhdr[mlevel]; mdp != NULL; mdp = mdp->mlevnxt)
+    {
+     __push_wrkitstk(mdp, 0);
+ 
+     /* do all splitting from pound params - also check but cannot set */
+     /* for every instance in module */
+     for (ii = 0; ii < __inst_mod->minum; ii++)
+      {
+       /* if instance in mod is inst array (first) never split and do not */
+       /* even check other expanded from in source instance array */
+       /* for contained insts that came from mi arrays, no pnd param split */
+       if (__inst_mod->miarr != NULL && (giap = __inst_mod->miarr[ii]) != NULL)
+        {
+         giawid = __get_giarr_wide(giap);
+         /* always inc by one in for loop above */
+         ii += (giawid - 1);
+         continue;
+        }
+
+       ip = &(__inst_mod->minsts[ii]);
+       if (!ip->i_pndsplit) continue;
+       
+       /* when splitting marked, marked for all but do not split last */
+       /* when splitting would result in nonsense 0 insts */
+
+       imdp = ip->imsym->el.emdp;
+       if (imdp->flatinum == 1 || imdp->flatinum == __inst_mod->flatinum)
+        {
+         if (__debug_flg)
+          {
+           __dbg_msg(
+            "++ # form inst. %s(%s) not split - last %d splittable insts\n",
+            ip->isym->synam, ip->imsym->synam, __inst_mod->flatinum);
+          } 
+         continue;
+        }
+
+       /* DBG remove -- */
+       if (__inst_mod->flatinum == 0) __misc_terr(__FILE__, __LINE__);
+       /* --- */
+
+       if (__debug_flg)
+        {
+         __dbg_msg(
+          "++ # form inst. %s(%s) split (%d new instances)\n",
+          ip->isym->synam, imdp->msym->synam, __inst_mod->flatinum);
+        } 
+
+       __sfnam_ind = ip->isym->syfnam_ind;
+       __slin_cnt = ip->isym->sylin_cnt;
+
+       /* imdp is module type of instance that has pound param */
+       /* SJM 03/16/04 - notice mlevel is one above imdp being split off */
+       split_upd_mod(imdp, ip, mlevel); 
+      }
+     __pop_wrkitstk();
+    }
+  }
+}
+
+/*
+ * split (copy) module from pound params or arrays of gate/insts where
+ * assumes tmp itree loc set and sets/uses various other globals
+ * 
+ * called after conditions for split determined to be true
+ * does copy and update the static (in source text) instance d.s.
+ */
+static void split_upd_mod(struct mod_t *imdp, struct inst_t *ip, int32 mlevel) 
+{
+ struct mod_t *ipmdp, *sav_inst_mod;
+
+ /* this is one up module containing instance for which new module split off */
+ sav_inst_mod = __inst_mod;
+ __do_mdsplit(imdp);
+ __pndparam_splits = TRUE;
+
+ /* after here new (in __inst_mod) set to new, and old set to old - 1 */ 
+ /* ipmdp is newly split off, sav cur mod if old split from */
+ ipmdp = __inst_mod;
+ /* adjust type of this instance */
+ ip->imsym = ipmdp->msym;
+ /* adjust inst numbers (spilt set new number to 1 and old to old - 1) */
+ ipmdp->flatinum = sav_inst_mod->flatinum; 
+ if (ipmdp->flatinum > 1) ipmdp->minstnum = 2;
+
+ /* imdp is old, reduce by number of times containing module instantiated */
+ imdp->flatinum -= sav_inst_mod->flatinum;
+ /* during splitting reduced count by one too many - adjust back */
+ imdp->flatinum++;
+ /* SJM 02/17/00 - must adjust new split off module to have right inst */
+ /* num */
+ if (imdp->flatinum > 1) imdp->minstnum = 2;
+
+ /* now adjust so both are masters that can be split from */
+ /* this may cause lots of $$[num] prefixes */
+ /* DBG remove --- */
+ if (imdp->msplit) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ ipmdp->msplit = FALSE;
+ /* if split off others from new, add new prefix starting at 1 */
+ ipmdp->mversno = 0;
+ imdp->mhassplit = FALSE;
+ /* this must remain a defparm master since master applies only to */
+ /* pealing off 1 instance paths from defparams */
+ ipmdp->mspltmst = NULL;
+ ipmdp->mpndsplit = TRUE;
+ /* but need to record master of pound split off */
+ ipmdp->mpndspltmst = imdp;
+
+ /* SJM 03/16/04 - passed mlevel is one higher than imdp being split */  
+ /* must add new split to dag list but for one down that is processed later */
+ /* but must incrementally update the md lev hdr list during splitting */
+ ipmdp->mlevnxt = __mdlevhdr[mlevel - 1];
+ __mdlevhdr[mlevel - 1] = ipmdp;
+ /* put back current module to up module instances in */
+ __inst_mod = sav_inst_mod;
+}
+
+/*
+ * ROUTINES TO SPLIT (COPY) MODULES
+ */
+
+/*
+ * copy the module and link in to list module list unless only 1 inst.
+ * __modsyms updated when this is done so split module insts. can be split
+ *
+ * if from pound param splitting must also copy non rooted defparams
+ * split off module, splitting sets __inst_mod to point to it
+ * so caller must save and restore __inst_mod
+ */
+extern void __do_mdsplit(struct mod_t *smdp)
+{
+ char s1[IDLEN];
+ struct sy_t *syp;
+
+ /* for master, version no. is highest of split off, else actual no. */
+ if (!smdp->msplit)
+  {
+   /* __splitting a module effects exactly one flattened inst. too */
+   /* flat inst counts and version numbers only kept in original master */
+   (smdp->mversno)++;
+   sprintf(s1, "%s$$%d", smdp->msym->synam, smdp->mversno);
+  }
+ else
+  {
+   /* for module, should never split from already split */
+   __misc_terr(__FILE__, __LINE__);
+  }
+ __splitting = TRUE;
+ copy_mod(smdp, s1);
+ /* new split off module now pointed to by __inst_mod */
+ __splitting = FALSE;
+
+ /* must link on end so gets processed later */
+ if (__end_mdp == NULL) __modhdr = __inst_mod;
+  else __end_mdp->mnxt = __inst_mod;
+ __end_mdp = __inst_mod;
+ syp = smdp->msym;
+ __gfinform(409, syp->syfnam_ind, syp->sylin_cnt,
+  "module %s converted to new type - defparam or # parameter changes width",
+  syp->synam); 
+}
+
+/*
+ * copy a module - point __inst_mod to new module
+ *
+ * this is passed the master to copy out of
+ * expects splitting to be true and adjust old module counts
+ * new module does not have any defparams since info from master's
+ * if from pound must copy non rooted defparams also
+ *
+ * this copies internal module components but does not insert new module
+ * type in itree or up module's inst_t list
+ *
+ * BEWARE - non standard use of inst mod required here no itstk value
+ */
+static void copy_mod(struct mod_t *omdp, char *newnam)
+{
+ struct sy_t *syp;
+
+ __oinst_mod = omdp;
+ __inst_mod = (struct mod_t *) __my_malloc(sizeof(struct mod_t));
+
+ /* notice this copies the flags which always stay the same */
+ *__inst_mod = *omdp;
+
+ __inst_mod->msplit = TRUE;
+ __oinst_mod->mhassplit = TRUE;
+ /* must add new name to modsyms - copy here can not effect undef mods */
+ /* because all references resolved or will not get here */
+ if ((syp = __add_modsym(newnam)) == NULL)
+  {
+   /* unable to split module to version and name */
+   __misc_gfterr(__FILE__, __LINE__, omdp->msym->syfnam_ind,
+    omdp->msym->sylin_cnt);
+  }
+
+ /* must set new sym and new version */
+ syp->sydecl = TRUE;
+ syp->el.emdp = __inst_mod;
+ syp->syfnam_ind = __oinst_mod->msym->syfnam_ind;
+ syp->sylin_cnt = __oinst_mod->msym->sylin_cnt;
+ /* never need to connect through old splt sym here */
+ __inst_mod->msym = syp;
+
+ /* __splitting off from already split impossible */
+ if (__oinst_mod->mspltmst != NULL) __misc_terr(__FILE__, __LINE__);
+
+ /* not decing non flattented module insts. = only used to determine tops */
+ (__oinst_mod->flatinum)--;
+ /* can never be 0 instances of old copied from */
+ if (__oinst_mod->flatinum == 1) __oinst_mod->minstnum = 1;
+ __inst_mod->minstnum = 1;
+ __inst_mod->flatinum = 1;
+
+ /* connect current module to module type that was its source */
+ /* if split off already split, link to real master */
+ /* once split off no way to resplit since params frozen at split point */
+ if (__oinst_mod->mspltmst != NULL)
+  __inst_mod->mspltmst = __oinst_mod->mspltmst;
+ else __inst_mod->mspltmst = __oinst_mod;
+
+ /* caller responsible for linking into list */
+ __inst_mod->mnxt = NULL;
+ /* copy symbol table including all lower such as tasks and named blocks */
+ copy_modsymtabs();
+
+ /* must copy global references before copy any expressions */
+ copy_mgrefs();
+
+ /* never copy module's defparams since already moved to design wide list */
+ /* also any grefs related to defparams removed by here */
+ __inst_mod->mdfps = NULL;
+
+ /* notice since params and ports really wires, must copy nets first */
+ /* but after symbol table copied */
+ copy_wires(__oinst_mod->msymtab);
+ copy_modports();
+ __inst_mod->mprms = copy_params(__oinst_mod->mprms, __oinst_mod->mprmnum,
+  MODULE);
+
+ if (__oinst_mod->mdfps != NULL) copy_defparams();
+ if (__oinst_mod->mattrs != NULL)
+  __inst_mod->mattrs = copy_attrs(__oinst_mod->mattrs);
+ if (__oinst_mod->mvarinits != NULL)
+  __inst_mod->mvarinits = copy_varinits(__oinst_mod->mvarinits);
+
+ copy_insts();
+ copy_miarr();
+ 
+ copy_gates();
+ copy_mgarr();
+
+ copy_contas();
+ copy_mdtasks();
+
+ __inst_mod->ialst = copy_ialst(__oinst_mod->ialst);
+ if (__oinst_mod->mspfy != NULL) copy_specify();
+}
+
+
+/*
+ * copy module symbol table structure
+ * expects __oinst_mod to be set to old inst mod, __inst_mod to newly alloced
+ * still must set all symbol el. union values
+ * this does not copy specify symbol table for specparams
+ */
+static void copy_modsymtabs(void)
+{
+ struct symtab_t *nsytp, *osytp;
+
+ osytp = __oinst_mod->msymtab;
+ nsytp = copy_1symtab(osytp);
+ nsytp->sytpar = NULL;
+ nsytp->sytsib = NULL;
+ nsytp->sytofs = NULL;
+ /* this copyeis and connects by linking in pointers */
+ if (osytp->sytofs != NULL) copy_lowsymtab(osytp->sytofs, nsytp);
+ __inst_mod->msymtab = nsytp;
+ nsytp->sypofsyt = __inst_mod->msym;
+}
+
+/*
+ * depth first symbol table tree traversal across offspring
+ */
+static void copy_lowsymtab(register struct symtab_t *osytp,
+ struct symtab_t *nupsytp)
+{
+ struct symtab_t *nsytp, *last_nsytp;
+
+ for (last_nsytp = NULL; osytp != NULL; osytp = osytp->sytsib)
+  {
+   nsytp = copy_1symtab(osytp);
+   if (last_nsytp == NULL) nupsytp->sytofs = nsytp;
+   else last_nsytp->sytsib = nsytp;
+
+   /* link up */
+   nsytp->sytpar = nupsytp;
+   /* copy underneath level (know only frozen tables copied) */
+   if (osytp->sytofs != NULL) copy_lowsymtab(osytp->sytofs, nsytp);
+   nsytp->sytsib = NULL;
+   last_nsytp = nsytp;
+  }
+}
+
+/*
+ * copy one symbol table
+ * caller fills in up and down links
+ */
+static struct symtab_t *copy_1symtab(struct symtab_t *osytp)
+{
+ int32 ofreezes;
+ struct symtab_t *nsytp;
+
+ ofreezes = osytp->freezes;
+ nsytp = __alloc_symtab(ofreezes);
+ *nsytp = *osytp;
+ /* must leave as NULL if empty table */
+ if (osytp->numsyms == 0) nsytp->stsyms = NULL;
+ else nsytp->stsyms = copy_stsyms(osytp->stsyms, osytp->numsyms);
+
+ /* when above symbol table was copied, old symbol links to new */
+ /* SJM 12/26/03 - specify symbol table has no associated symbol */
+ if (osytp->sypofsyt != NULL) nsytp->sypofsyt = osytp->sypofsyt->spltsy;
+ else nsytp->sypofsyt = NULL;
+
+ /* must link old to point to new (n_head now unused) */
+ osytp->n_head = (struct tnode_t *) nsytp;
+ return(nsytp);
+}
+
+/*
+ * copy stsyms - know at least one symbol in table
+ */
+static struct sy_t **copy_stsyms(struct sy_t **osytab,
+ word32 nsyms)
+{
+ register int32 i;
+ struct sy_t **sytbp;
+ struct sy_t *nsyp;
+ int32 bytes;
+
+ bytes = nsyms*sizeof(struct sy_t *);
+ __wrkstab = (struct sy_t **) __my_malloc(bytes);
+ for (i = 0; i < (int32) nsyms; i++)
+  {
+   /* allocate the new symbol */
+   nsyp = (struct sy_t *) __my_malloc(sizeof(struct sy_t));
+   *nsyp = *(osytab[i]);
+   /* set union to NULL, any member will do */
+   nsyp->el.ecp = NULL;
+   __wrkstab[i] = nsyp;
+   /* tmp link from old to new */
+   osytab[i]->spltsy = nsyp;
+  }
+ sytbp = __wrkstab;
+ return(sytbp);
+}
+
+/*
+ * copy module ports
+ */
+static void copy_modports(void)
+{
+ register int32 pi;
+ register struct mod_pin_t *ompp, *nmpp;
+ int32 pnum;
+
+ if ((pnum = __oinst_mod->mpnum) == 0) return;
+
+ __inst_mod->mpins = (struct mod_pin_t *)
+  __my_malloc(pnum*sizeof(struct mod_pin_t)); 
+
+ nmpp = &(__inst_mod->mpins[0]);  
+ for (pi = 0, ompp = &(__oinst_mod->mpins[0]); pi < pnum; pi++, ompp++, nmpp++)
+  {
+   *nmpp = *ompp;
+   nmpp->mpref = __copy_expr(ompp->mpref);
+  }
+}
+
+/*
+ * copy wires from __oinst_mod to __inst_mod
+ * also link in nsym and symbol table el.enp
+ * know decl. symbol tables for these
+ *
+ * at this point do not know if wire correct - must copy from symbol table
+ */
+static void copy_wires(struct symtab_t *sytp)
+{
+ register int32 syi;
+ struct sy_t **syms;
+ struct sy_t *syp;
+ struct net_t *onp, *nnp;
+
+ for (syms = sytp->stsyms, syi = 0; syi < (int32) sytp->numsyms; syi++)
+  {
+   syp = syms[syi];
+   if (syp->sytyp != SYM_N) continue;
+   onp = syp->el.enp;
+   /* do not copy parameters or specparams here */
+   if (onp->n_isaparam) continue;
+
+   /* must copy depending or original storage method */
+   nnp = (struct net_t *) __my_malloc(sizeof(struct net_t));
+   /* copy body */
+   *nnp = *onp;
+   /* allocate extra storage area */
+   nnp->nu.ct = __alloc_arrncomp(); 
+   /* copy ncomp body */
+   *(nnp->nu.ct) = *(onp->nu.ct); 
+   /* DBG remove --- */
+   if (nnp->nrngrep != NX_CT) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   if (nnp->n_isavec)
+    {
+     nnp->nu.ct->nx1 = __copy_expr(onp->nu.ct->nx1);
+     nnp->nu.ct->nx2 = __copy_expr(onp->nu.ct->nx2);
+    }
+   else nnp->nu.ct->nx1 = nnp->nu.ct->nx2 = NULL;
+
+   if (nnp->n_isarr)
+    {
+     nnp->nu.ct->ax1 = __copy_expr(onp->nu.ct->ax1);
+     /* notice this copies initial value expr. for params */
+     nnp->nu.ct->ax2 = __copy_expr(onp->nu.ct->ax2);
+    }
+   else nnp->nu.ct->ax1 = nnp->nu.ct->ax2 = NULL;
+
+   if (onp->nattrs != NULL) nnp->nattrs = copy_attrs(onp->nattrs);
+   else nnp->nattrs = NULL;
+
+   nnp->nu.ct->n_dels_u.pdels = __copy_dellst(onp->nu.ct->n_dels_u.pdels);
+
+   /* when symbol table copied old spltsy field pointed to new */
+   /* copying symbol table copies symbols */
+   syp = (struct sy_t *) onp->nsym->spltsy;
+   nnp->nsym = syp;
+   syp->el.enp = nnp;
+   /* mutual links now separated */
+   /* must not change splt sym since still needed by param type regs */
+  }
+}
+
+/*
+ * copy params (storage same as nets and also by here will be in tab form)
+ * for both module and task/func params 
+ *
+ * also links in nsym and symbol table el.enp
+ * know decl. symbol tables for these
+ *
+ * value of param as parm_var net is assumed to be in pxp format
+ * and expr. copied.
+ */
+static struct net_t *copy_params(struct net_t *onptab, int32 oprmnum,
+ int32 pclass)
+{
+ register int32 ni;
+ int32 nbytes, awid;
+ struct sy_t *syp;
+ struct net_t *nnp, *onp, *nnptab;
+
+ if (oprmnum == 0) return(NULL);
+ nbytes = oprmnum*sizeof(struct net_t);
+ /* allocate and copy new parameter (really nets) as a block */ 
+ nnptab = (struct net_t *) __my_malloc(nbytes);
+ memcpy(nnptab, onptab, nbytes);
+ 
+ /* need to also allocate and copy ncomp union field for each */
+ for (ni = 0; ni < oprmnum; ni++)
+  {
+   nnp = &(nnptab[ni]);
+   onp = &(onptab[ni]);
+   /* DBG remove --- */
+   if (pclass == MODULE)
+    { if (!onp->n_isaparam) __misc_terr(__FILE__, __LINE__); }
+   else if (pclass == SPECIFY)
+    { if (!onp->n_isaparam) __misc_terr(__FILE__, __LINE__); }
+   else __case_terr(__FILE__, __LINE__);
+   /* --- */
+
+   /* get area from special block */
+   nnp->nu.ct = __alloc_arrncomp(); 
+
+   *(nnp->nu.ct) = *(onp->nu.ct); 
+   if (nnp->n_isavec)
+    {
+     nnp->nu.ct->nx1 = __copy_expr(onp->nu.ct->nx1);
+     nnp->nu.ct->nx2 = __copy_expr(onp->nu.ct->nx2);
+    }
+   else nnp->nu.ct->nx1 = nnp->nu.ct->nx2 = NULL;
+
+   /* know rhs will still be one expr. (SR_PNUM) here pointed to by nva */
+   /* DBG remove --- */
+   if (onp->srep != SR_PNUM) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   
+   /* must also handle parameter arrays */
+   if (onp->n_isarr)
+    {
+     nnp->nu.ct->ax1 = __copy_expr(onp->nu.ct->ax1);
+     nnp->nu.ct->ax2 = __copy_expr(onp->nu.ct->ax2);
+     awid = __get_arrwide(onp); 
+     /* arrays of parameters never packed always take at least 8 bytes */
+     nbytes = 2*WRDBYTES*awid*wlen_(onp->nwid);
+    }
+   else
+    {
+     nnp->nu.ct->ax1 = nnp->nu.ct->ax2 = NULL;
+     nbytes = 2*WRDBYTES*wlen_(onp->nwid); 
+    }
+   /* alloc and copy value */
+   nnp->nva.wp = (word32 *) __my_malloc(nbytes);
+   memcpy(nnp->nva.wp, onp->nva.wp, nbytes);
+
+   /* and copy source expr for params kept in n_dels_u field */
+   /* DBG remove --- */
+   if (onp->nu.ct->parm_srep != SR_PXPR) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   nnp->nu.ct->n_dels_u.d1x = __copy_expr(onp->nu.ct->n_dels_u.d1x);
+
+   /* when symbol table copied old splt sym field pointed to new */
+   /* copying symbol table copies symbols */
+   syp = (struct sy_t *) onp->nsym->spltsy;
+   nnp->nsym = syp;
+   syp->el.enp = nnp;
+   /* mutual links now separated */
+   /* must not change splt sym since still needed by param type regs */
+  }
+ return(nnptab);
+}
+
+/*
+ * copy downward relative only defparams - know checking completed
+ */
+static void copy_defparams(void)
+{
+ register struct dfparam_t *odfpp, *ndfpp;
+ register int32 dfi;
+ struct dfparam_t *ndfphdr, *ndfpend;
+
+ ndfphdr = ndfpend = NULL;
+ for (odfpp = __oinst_mod->mdfps; odfpp != NULL; odfpp = odfpp->dfpnxt) 
+  {
+   /* for rooted defparam in copied has no effect */
+   /* if copying during splitting from defparams, down relative gone */ 
+   if (odfpp->dfp_rooted) continue; 
+
+   /* always copy local defparams */
+   ndfpp = (struct dfparam_t *) __my_malloc(sizeof(struct dfparam_t));
+   *ndfpp = *odfpp;
+   ndfpp->dfpxlhs = __copy_expr(odfpp->dfpxlhs);
+   ndfpp->dfpxrhs = __copy_expr(odfpp->dfpxrhs);
+   ndfpp->in_mdp = __inst_mod;
+   ndfpp->gdfpnam = __pv_stralloc(odfpp->gdfpnam);
+   /* since resetting do not need this code --
+   if (odfpp->dfptskp != NULL)
+    ndfpp->dfptskp = odfpp->dfptskp->tsksyp->spltsy->el.etskp;
+   --- */
+   ndfpp->dfpnxt = NULL;
+
+   /* must look up target symbols for defparam at end, no copy here */ 
+   ndfpp->dfpiis = (int32 *) __my_malloc((ndfpp->last_dfpi + 1)*sizeof(int32));
+   /* SJM 06/03/05 - index was wrongly not starting at 0 */
+   for (dfi = 0; dfi < ndfpp->last_dfpi + 1; dfi++)
+    ndfpp->dfpiis[dfi] = odfpp->dfpiis[dfi];
+
+   if (ndfphdr == NULL) ndfphdr = ndfpp;
+   else ndfpend->dfpnxt = ndfpp;  
+   ndfpend = ndfpp;
+  }
+ __inst_mod->mdfps = ndfphdr;
+}
+
+/*
+ * copy Verilog 2000 attributes
+ */
+static struct attr_t *copy_attrs(struct attr_t *oattrp)
+{
+ register struct attr_t *nattrp, *nattr_hd, *last_nattrp; 
+
+ last_nattrp = NULL;
+ nattr_hd = NULL;
+ for (; oattrp != NULL; oattrp = oattrp->attrnxt)
+  {
+   nattrp = (struct attr_t *) __my_malloc(sizeof(struct attr_t));
+   *nattrp = *oattrp;
+   nattrp->attrnam = __pv_stralloc(oattrp->attrnam);
+   if (oattrp->attr_xp != NULL)
+    nattrp->attr_xp = __copy_expr(oattrp->attr_xp);
+   nattrp->attrnxt = NULL;
+   if (last_nattrp == NULL) nattr_hd = nattrp;
+   else last_nattrp->attrnxt = nattrp;  
+   last_nattrp = nattrp;
+  }
+ return(nattr_hd);
+}
+
+/*
+ * routine for copy module variable initializ assign var init records
+ *
+ * notice this must be copied after copying wires and parameters 
+ */
+static struct varinitlst_t *copy_varinits(struct varinitlst_t *oinitp)
+{
+ register struct varinitlst_t *ninitp, *nvarinit_hd, *last_initp; 
+
+ last_initp = NULL;
+ nvarinit_hd = NULL;
+ ninitp = NULL;
+ for (; oinitp != NULL; oinitp = oinitp->varinitnxt)
+  {
+   ninitp = (struct varinitlst_t *) __my_malloc(sizeof(struct varinitlst_t));
+   *ninitp = *oinitp;
+   ninitp->init_syp = oinitp->init_syp->spltsy;
+   ninitp->init_xp = __copy_expr(oinitp->init_xp); 
+   ninitp->varinitnxt = NULL;
+   if (last_initp == NULL) nvarinit_hd = ninitp;
+   else last_initp->varinitnxt = ninitp;
+   last_initp = ninitp;
+  }
+ return(ninitp);
+}
+
+/*
+ * routine for copying module instances
+ */
+static void copy_insts(void)
+{
+ register int32 ii, ii2;
+ int32 giawid;
+ struct inst_t *oip, *nip;
+ struct giarr_t *giap;
+
+ /* if no instances - original copy set fields to nil and 0 */
+ if (__oinst_mod->minum == 0) return;
+
+ __inst_mod->minsts = (struct inst_t *)
+  __my_malloc(__oinst_mod->minum*sizeof(struct inst_t));
+
+ for (ii = 0; ii < __oinst_mod->minum;)
+  {
+   oip = &(__oinst_mod->minsts[ii]);
+   nip = &(__inst_mod->minsts[ii]);
+   /* notice for earliest copying miarr always nil */
+   /* giap here is old since new does not yet exist */
+   if (__oinst_mod->miarr != NULL && (giap = __oinst_mod->miarr[ii]) != NULL)
+    {
+     copy_1inst(nip, oip, TRUE);
+     giawid = __get_giarr_wide(giap);
+     for (ii2 = ii + 1; ii2 < ii + giawid; ii2++) 
+      {
+       oip = &(__oinst_mod->minsts[ii2]);
+       nip = &(__inst_mod->minsts[ii2]);
+       copy_1inst(nip, oip, FALSE);
+       nip->ipins = giap->giapins;
+      }
+     ii = ii2;
+    }
+   else { copy_1inst(nip, oip, TRUE); ii++; }
+  }
+}
+
+/*
+ * copy 1 instance
+ */
+static void copy_1inst(struct inst_t *nip, struct inst_t *oip, int32 nd_cp_ipins)
+{
+ struct sy_t *syp;
+
+ /* this copies instance must split for later if needed (>1 unsplit) */
+ *nip = *oip;
+ /* when symbol copied old splt sym field pointed to new */
+ syp = (struct sy_t *) oip->isym->spltsy;
+ if (syp == NULL) __misc_terr(__FILE__, __LINE__);
+ nip->isym = syp;
+ syp->el.eip = nip;
+ /* mutual links now separated */
+ /* notice module symbol (in modsyms) the same until splitting completed */
+ nip->ipxprtab = copy_pndxtab(oip);
+
+ if (oip->iattrs != NULL) nip->iattrs = copy_attrs(oip->iattrs);
+ else nip->iattrs = NULL;
+
+ if (nd_cp_ipins) copy_iports(nip, oip); else nip->ipins = NULL;
+}
+
+/*
+ * copy pound param expression table
+ *
+ * if pound param expr. table exists it has loc (maybe nil) for every mod param
+ */
+static struct expr_t **copy_pndxtab(struct inst_t *oip)
+{
+ register int32 pi;
+ struct expr_t **nnpxtab, **onpxtab;
+ struct mod_t *imdp;
+
+ if ((onpxtab = oip->ipxprtab) == NULL) return(NULL);
+
+ imdp = oip->imsym->el.emdp;
+ nnpxtab = (struct expr_t **)
+  __my_malloc(imdp->mprmnum*sizeof(struct expr_t *));
+ for (pi = 0; pi < imdp->mprmnum; pi++)
+  {
+   if (onpxtab[pi] == NULL) nnpxtab[pi] = NULL;
+   else nnpxtab[pi] = __copy_expr(onpxtab[pi]);
+  }
+ return(nnpxtab);
+}
+
+/*
+ * copy module instance ports
+ */
+static void copy_iports(struct inst_t *nip, struct inst_t *oip)
+{
+ register int32 pi, pnum;
+
+ if ((pnum = oip->imsym->el.emdp->mpnum) != 0)
+  {
+   nip->ipins = (struct expr_t **) __my_malloc(pnum*sizeof(struct expr_t *));
+   for (pi = 0; pi < pnum; pi++) nip->ipins[pi] = __copy_expr(oip->ipins[pi]);
+  }
+ else nip->ipins = NULL;
+}
+
+/*
+ * copy module array of instances (miarr) 
+ *
+ * this is copy of index into individual insts in normal insts tab 
+ */
+static void copy_miarr(void)
+{
+ register int32 ii, ii2;
+ int32 giawid;
+ struct giarr_t *ogiap, *ngiap;
+ struct sy_t *syp;
+
+ /* if no arrays of instances - original copy set fields to nil and 0 */
+ if (__oinst_mod->miarr == NULL) return;
+
+ /* this is pointer to elements not array of elements */
+ __inst_mod->miarr = (struct giarr_t **)
+  __my_malloc(__oinst_mod->minum*sizeof(struct giarr_t *));
+
+ for (ii = 0; ii < __oinst_mod->minum;)
+  {
+   ogiap = __oinst_mod->miarr[ii];
+   if (ogiap == NULL) { __inst_mod->miarr[ii] = NULL; continue; }
+
+   ngiap = (struct giarr_t *) __my_malloc(sizeof(struct giarr_t));
+   *ngiap = *ogiap;
+   /* new needs to point to right (its) module's ipins list */
+   ngiap->giapins = __inst_mod->minsts[ii].ipins;
+
+   syp = (struct sy_t *) ogiap->gia_base_syp->spltsy;
+   if (syp == NULL) __misc_terr(__FILE__, __LINE__);
+   ngiap->gia_base_syp = syp;
+   /* points back to first (base) */
+   /* LOOKATME - is this needed */
+   syp->el.eip = &(__inst_mod->minsts[ii]);
+   syp->sy_giabase = TRUE;
+
+   /* only other fields that need copying is expression */
+   ngiap->giax1 = __copy_expr(ogiap->giax1);
+   ngiap->giax2 = __copy_expr(ogiap->giax2);
+   __inst_mod->miarr[ii] = ngiap;
+   /* LOOKATME - for new generate maybe need to change this */
+   /* notice all giap's for expanded instances point to same master */
+   giawid = __get_giarr_wide(ogiap);
+   for (ii2 = ii + 1; ii2 < ii + giawid; ii2++) __inst_mod->miarr[ii2] = ngiap;
+   ii = ii2;
+  }
+}
+
+/*
+ * routine for copying module gates
+ */
+static void copy_gates(void)
+{
+ register int32 gi, gi2;
+ int32 giawid;
+ struct gate_t *ogp, *ngp;
+ struct giarr_t *giap;
+
+ /* inst mod is new */
+ if (__oinst_mod->mgnum != 0)
+  __inst_mod->mgates = (struct gate_t *)
+   __my_malloc(__oinst_mod->mgnum*sizeof(struct gate_t));
+
+ for (gi = 0; gi < __oinst_mod->mgnum;)
+  {
+   ogp = &(__oinst_mod->mgates[gi]);
+   ngp = &(__inst_mod->mgates[gi]);
+
+   /* notice for earliest copying miarr always nil */
+   /* giap here is old since new does not yet exist */
+   if (__oinst_mod->mgarr != NULL && (giap = __oinst_mod->mgarr[gi]) != NULL)
+    {
+     copy_1gate(ngp, ogp, TRUE);
+     giawid = __get_giarr_wide(giap);
+     for (gi2 = gi + 1; gi2 < gi + giawid; gi2++) 
+      {
+       ogp = &(__oinst_mod->mgates[gi2]);
+       ngp = &(__inst_mod->mgates[gi2]);
+       copy_1gate(ngp, ogp, FALSE);
+       ngp->gpins = giap->giapins;
+      }
+     gi = gi2;
+    }
+   else { copy_1gate(ngp, ogp, TRUE); gi++; }
+  }
+}
+
+/*
+ * copy 1 gate (passes already allocated address in gate tables)
+ */
+static void copy_1gate(struct gate_t *ngp, struct gate_t *ogp, int32 nd_cp_gpins)
+{
+ register int32 pi;
+ int32 pnum;
+ struct sy_t *syp;
+
+ pnum = ogp->gpnum;
+ /* copy everything but port connection expressions */
+ *ngp = *ogp;
+
+ /* when symbol copied old splt sym field pointed to new */
+ syp = (struct sy_t *) ogp->gsym->spltsy;
+ ngp->gsym = syp;
+ syp->el.egp = ngp;
+ /* mutual links now separated */
+ /* notice module symbol (in modsyms) the same until splitting completed */
+
+ /* copy output that is still expr.  - gets changed to wire later */
+ ngp->g_du.pdels = __copy_dellst(ogp->g_du.pdels);
+
+ if (ogp->gattrs != NULL) ngp->gattrs = copy_attrs(ogp->gattrs);
+ else ngp->gattrs = NULL;
+
+ ngp->gpins = (struct expr_t **) __my_malloc(pnum*sizeof(struct expr_t *));
+ if (nd_cp_gpins)
+  {
+   /* copy the input port expressions */
+   for (pi = 0; pi < pnum; pi++)
+    ngp->gpins[pi] = __copy_expr(ogp->gpins[pi]);
+  }
+ else ngp->gpins = NULL;
+}
+
+/*
+ * copy module array of gates (mgarr)
+ */
+static void copy_mgarr(void)
+{
+ register int32 gi, gi2;
+ int32 giawid;
+ struct giarr_t *ogiap, *ngiap;
+ struct sy_t *syp;
+
+ /* if no arrays of instances - original copy set fields to nil and 0 */
+ if (__oinst_mod->mgarr == NULL) return;
+
+ /* this is pointer to elements not array of elements */
+ __inst_mod->mgarr = (struct giarr_t **)
+  __my_malloc(__oinst_mod->mgnum*sizeof(struct giarr_t *));
+
+ for (gi = 0; gi < __oinst_mod->mgnum; gi++)
+  {
+   ogiap = __oinst_mod->mgarr[gi];
+   if (ogiap == NULL) { __inst_mod->mgarr[gi] = NULL; continue; }
+
+   ngiap = (struct giarr_t *) __my_malloc(sizeof(struct giarr_t));
+   *ngiap = *ogiap;
+
+   /* new needs to point to right (its) module's ipins list */
+   ngiap->giapins = __inst_mod->mgates[gi].gpins;
+
+   syp = (struct sy_t *) ogiap->gia_base_syp->spltsy;
+   if (syp == NULL) __misc_terr(__FILE__, __LINE__);
+   ngiap->gia_base_syp = syp;
+   /* points back to first (base) */
+   /* LOOKATME - is this needed */
+   syp->el.egp = &(__inst_mod->mgates[gi]);
+   syp->sy_giabase = TRUE;
+
+   /* only other fields that need copying is expression */
+   ngiap->giax1 = __copy_expr(ogiap->giax1);
+   ngiap->giax2 = __copy_expr(ogiap->giax2);
+   __inst_mod->mgarr[gi] = ngiap;
+
+   /* LOOKATME - for new generate maybe need to change this */
+   /* notice all giap's for expanded instances point to same master */
+   giawid = __get_giarr_wide(ogiap);
+   for (gi2 = gi + 1; gi2 < gi + giawid; gi2++)
+     __inst_mod->mgarr[gi2] = ngiap;
+   gi = gi2;
+  }
+}
+
+/*
+ * copy continuous assigns 
+ */
+static void copy_contas(void)
+{
+ register struct conta_t *ocap; 
+ struct conta_t *ncap, *last_ncap;
+ struct sy_t *syp;
+
+ __inst_mod->mcas = NULL; 
+ last_ncap = NULL;
+ for (ocap = __oinst_mod->mcas; ocap != NULL; ocap = ocap->pbcau.canxt)
+  {
+   ncap = (struct conta_t *) __my_malloc(sizeof(struct conta_t));
+
+   /* when symbol copied old splt sym field pointed to new */
+   *ncap = *ocap;
+   syp = (struct sy_t *) ocap->casym->spltsy;
+   ncap->casym = syp;
+   syp->el.ecap = ncap;
+
+   ncap->ca_du.pdels = __copy_dellst(ocap->ca_du.pdels);
+   ncap->lhsx = __copy_expr(ocap->lhsx);
+   ncap->rhsx = __copy_expr(ocap->rhsx);
+   if (last_ncap == NULL) __inst_mod->mcas = ncap;
+   else last_ncap->pbcau.canxt = ncap;
+   last_ncap = ncap;  
+  }
+ if (last_ncap != NULL) last_ncap->pbcau.canxt = NULL;
+}
+
+/*
+ * copy all mod tasks
+ */
+static void copy_mdtasks(void)
+{
+ register struct task_t *otskp, *ntskp;
+ struct task_t *last_ntskp;
+
+ last_ntskp = NULL;
+ __inst_mod->mtasks = NULL;
+ for (otskp = __oinst_mod->mtasks; otskp != NULL; otskp = otskp->tsknxt)
+  {
+   ntskp = (struct task_t *) __my_malloc(sizeof(struct task_t));
+   *ntskp = *otskp;
+   /* fill link from task to symbol table and symbol */
+   ntskp->tsksymtab = (struct symtab_t *) otskp->tsksymtab->n_head;
+   /* notice must link both directions */
+   ntskp->tsksyp = (struct sy_t *) otskp->tsksyp->spltsy;
+   ntskp->tsksyp->el.etskp = ntskp;
+
+   /* for tasks everything is a reg so must copy first */
+   copy_wires(otskp->tsksymtab);
+
+   /* for named blocks, connect from task to named block filled when named */
+   /* block statement filled (st_namblkin field) */
+
+   /* copy task pins */
+   ntskp->tskpins = copy_tskargs(otskp);
+
+   /* copy task params */
+   ntskp->tsk_prms = copy_params(otskp->tsk_prms, otskp->tprmnum, MODULE);
+
+   /* copy the 1 statement */
+   ntskp->tskst = copy_lstofsts(otskp->tskst);
+
+   if (last_ntskp == NULL) __inst_mod->mtasks = ntskp;
+   else last_ntskp->tsknxt = ntskp;
+   last_ntskp = ntskp;
+  }
+}
+
+/*
+ * copy task ports - only regs can be ports
+ */
+static struct task_pin_t *copy_tskargs(struct task_t *otskp)
+{
+ register struct task_pin_t *otpp;
+ struct task_pin_t *last_ntpp, *ntpp, *ntpp_hdr;
+
+ last_ntpp = NULL;
+ ntpp_hdr = NULL;
+ for (otpp = otskp->tskpins; otpp != NULL; otpp = otpp->tpnxt)
+  {
+   ntpp = (struct task_pin_t *) __my_malloc(sizeof(struct task_pin_t));
+   /* this copies trtyp field */
+   *ntpp = *otpp;
+   ntpp->tpsy = (struct sy_t *) otpp->tpsy->spltsy;
+   ntpp->tpnxt = NULL;
+   if (last_ntpp == NULL) ntpp_hdr = ntpp; else last_ntpp->tpnxt = ntpp;
+   last_ntpp = ntpp;
+  }
+ return(ntpp_hdr);
+}
+
+/*
+ * copy a statement entry
+ */
+static struct st_t *copy_stmt(struct st_t *ostp)
+{
+ struct st_t *nstp;
+ struct sy_t *nsyp;
+
+ if (ostp == NULL) return(NULL);
+
+ nstp = (struct st_t *) __my_malloc(sizeof(struct st_t));
+ *nstp = *ostp;
+ nstp->stnxt = NULL;
+
+ switch ((byte) ostp->stmttyp) {
+  /* null just has type value and NULL pointer (i.e. ; by itself) */
+  case S_NULL: case S_STNONE: break;
+  case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA: case S_NBPROCA:
+   nstp->st.spra.lhsx = __copy_expr(ostp->st.spra.lhsx);
+   nstp->st.spra.rhsx = __copy_expr(ostp->st.spra.rhsx);
+   break;
+  case S_IF:
+   nstp->st.sif.condx = __copy_expr(ostp->st.sif.condx);
+   nstp->st.sif.thenst = copy_lstofsts(ostp->st.sif.thenst);
+   nstp->st.sif.elsest = copy_lstofsts(ostp->st.sif.elsest);
+   break;
+  case S_CASE:
+   nstp->st.scs.castyp = ostp->st.scs.castyp;
+   nstp->st.scs.maxselwid = ostp->st.scs.maxselwid;
+   nstp->st.scs.csx = __copy_expr(ostp->st.scs.csx);
+
+   /* this also copies default which is first (always present) */
+   /* if case has no default, st field nil */ 
+   nstp->st.scs.csitems = copy_csitemlst(ostp->st.scs.csitems);
+   break;
+  case S_REPEAT:
+   nstp->st.srpt.repx = __copy_expr(ostp->st.srpt.repx);
+   /* per inst. temporaries not allocated by here */
+   nstp->st.srpt.reptemp = NULL;
+   nstp->st.srpt.repst = copy_lstofsts(ostp->st.srpt.repst);
+   break;
+  case S_FOREVER:
+  case S_WHILE:
+   nstp->st.swh.lpx = __copy_expr(ostp->st.swh.lpx);
+   nstp->st.swh.lpst = copy_lstofsts(ostp->st.swh.lpst);
+   break;
+  case S_WAIT:
+   nstp->st.swait.lpx = __copy_expr(ostp->st.swait.lpx);
+   nstp->st.swait.lpst = copy_lstofsts(ostp->st.swait.lpst);
+   /* until prep, this dctp is just allocated unfilled version */
+   nstp->st.swait.wait_dctp = __alloc_dctrl();
+   *(nstp->st.swait.wait_dctp) = *(ostp->st.swait.wait_dctp);
+   break;
+  case S_FOR:
+   {
+    struct for_t *nfrp, *ofrp;
+
+    nfrp = (struct for_t *) __my_malloc(sizeof(struct for_t));
+    nstp->st.sfor = nfrp;
+    ofrp = ostp->st.sfor;
+    nfrp->forassgn = copy_stmt(ofrp->forassgn);
+    nfrp->fortermx = __copy_expr(ofrp->fortermx);
+    nfrp->forinc = copy_stmt(ofrp->forinc);
+    nfrp->forbody = copy_lstofsts(ofrp->forbody);
+   }
+   break;
+  case S_DELCTRL:
+   {
+    struct delctrl_t *ndcp, *odcp;
+
+    ndcp = (struct delctrl_t *) __my_malloc(sizeof(struct delctrl_t));
+    nstp->st.sdc = ndcp;
+    odcp = ostp->st.sdc;
+    ndcp->dctyp = odcp->dctyp;
+    ndcp->dc_iact = odcp->dc_iact; 
+    /* SJM 08/02/02 - need to also explicitly copy new non blking flag */ 
+    ndcp->dc_nblking = odcp->dc_nblking;
+    /* SJM 08/17/04 - f2016 was failing because this was not set */
+    ndcp->implicit_evxlst = odcp->implicit_evxlst;
+    ndcp->dc_delrep = odcp->dc_delrep;
+    ndcp->dc_du.pdels = __copy_dellst(odcp->dc_du.pdels);
+    ndcp->repcntx = __copy_expr(odcp->repcntx);
+    /* SJM 08/17/04 - also repcnts was not set - used during sim */
+    ndcp->dce_repcnts = odcp->dce_repcnts;
+
+    ndcp->dceschd_tevs = NULL;
+    /* can be list because of #10 begin ... end */
+    ndcp->actionst = copy_lstofsts(odcp->actionst);
+   }
+   break;
+  case S_NAMBLK:
+   {
+    /* know task copied and old sy points to new - new el is new task */
+    nsyp = (struct sy_t *) ostp->st.snbtsk->tsksyp->spltsy;
+    nstp->st.snbtsk = nsyp->el.etskp;
+    nsyp->el.etskp->st_namblkin = nstp;
+   }
+   break;
+  case S_UNBLK:
+   nstp->st.sbsts = copy_lstofsts(ostp->st.sbsts);
+   break;
+  case S_UNFJ:
+   { 
+    register int32 fji;
+    int32 num_fji;
+    struct st_t *ofjstp;
+
+    /* first count number of statements in fj */
+    for (num_fji = 0;; num_fji++)
+     { if (ostp->st.fj.fjstps[num_fji] == NULL) break; }
+
+    nstp->st.fj.fjstps = (struct st_t **)
+     __my_malloc((num_fji + 1)*sizeof(struct st_t *));
+    nstp->st.fj.fjlabs = (int32 *) __my_malloc((num_fji + 1)*sizeof(int32));
+
+    /* know fork-join will always have at least 1 statement (maybe null) */
+    /* also if labeled it will be surrounded by named block */
+    for (fji = 0;; fji++)
+     {
+      if ((ofjstp = ostp->st.fj.fjstps[fji]) == NULL) break;
+      nstp->st.fj.fjstps[fji] = copy_lstofsts(ofjstp);
+
+      /* code gen label unused here but still copy */
+      nstp->st.fj.fjlabs[fji] = ostp->st.fj.fjlabs[fji];
+     }
+    nstp->st.fj.fjstps[num_fji] = NULL;
+    nstp->st.fj.fjlabs[num_fji] = -1;
+   }
+   break;
+  case S_TSKCALL:
+   /* find new task through old to new symbol */
+   /* for system tasks since points to itself gets same (right) sym */
+   nstp->st.stkc.tsksyx = __copy_expr(ostp->st.stkc.tsksyx);
+   nstp->st.stkc.targs = __copy_expr(ostp->st.stkc.targs);
+
+   /* field for pli tasks filled during prep */
+   nstp->st.stkc.tkcaux.trec = NULL;
+   break;
+  case S_QCONTA:
+   {
+    /* SJM 06/23/02 - now aneed more room in qcont stmt specific area */
+    struct qconta_t *nqcafs;
+
+    nqcafs = (struct qconta_t *) __my_malloc(sizeof(struct qconta_t));
+
+    nstp->st.sqca = nqcafs;
+    nstp->st.sqca->qcatyp = ostp->st.sqca->qcatyp;
+    nstp->st.sqca->regform = ostp->st.sqca->regform;
+    nstp->st.sqca->qclhsx = __copy_expr(ostp->st.sqca->qclhsx);
+    nstp->st.sqca->qcrhsx = __copy_expr(ostp->st.sqca->qcrhsx);
+    /* lst of dce lists field nil until near end of prep */
+    nstp->st.sqca->rhs_qcdlstlst = NULL;
+   }
+   break;
+  case S_QCONTDEA:
+   nstp->st.sqcdea.qcdatyp = ostp->st.sqcdea.qcdatyp;
+   nstp->st.sqcdea.regform = ostp->st.sqcdea.regform;
+   nstp->st.sqcdea.qcdalhs = __copy_expr(ostp->st.sqcdea.qcdalhs);
+   break;
+  case S_CAUSE:
+   /* must copy expr. even though know just event name */
+   nstp->st.scausx = __copy_expr(ostp->st.scausx);
+   break;
+  case S_DSABLE:
+   nstp->st.sdsable.dsablx = __copy_expr(ostp->st.sdsable.dsablx);
+   nstp->st.sdsable.func_nxtstp = NULL;
+   break;
+  /* name resolving statement type no. */
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(nstp);
+}
+
+/*
+ * copy a statement list (linked list of statements)
+ */
+static struct st_t *copy_lstofsts(register struct st_t *ostp)
+{
+ struct st_t *nstp_hdr, *nstp, *last_nstp;
+
+ nstp_hdr = NULL;
+ for (last_nstp = NULL; ostp != NULL; ostp = ostp->stnxt)
+  {
+   nstp = copy_stmt(ostp);
+   if (last_nstp == NULL) nstp_hdr = nstp; else last_nstp->stnxt = nstp;
+   nstp->stnxt = NULL;
+   last_nstp = nstp;
+  }
+ return(nstp_hdr);
+}
+
+/*
+ * copy a list of ialst blocks
+ */
+static struct ialst_t *copy_ialst(register struct ialst_t *oialp)
+{
+ struct ialst_t *nialp, *last_nialp, *nialst_hdr;
+ 
+ nialst_hdr = NULL;
+ for (last_nialp = NULL; oialp != NULL; oialp = oialp->ialnxt)
+  {
+   nialp = (struct ialst_t *) __my_malloc(sizeof(struct ialst_t));
+   *nialp = *oialp; 
+   /* notice here initial/always exactly 1 statement, for always 2nd loop */
+   /* back added during prep. */
+   nialp->iastp = copy_lstofsts(oialp->iastp);
+   nialp->ialnxt = NULL;
+
+   if (last_nialp == NULL) nialst_hdr = nialp;
+   else last_nialp->ialnxt = nialp;
+   last_nialp = nialp;
+  }
+ return(nialst_hdr);
+}
+
+/*
+ * copy the case item list
+ * notice in common case of no default, pass nil - returns nil
+ *
+ * this copies default which is first too
+ */
+static struct csitem_t *copy_csitemlst( register struct csitem_t *ocsip)
+{
+ struct csitem_t *ncsip, *ncsip_hdr, *last_ncsip;
+
+ ncsip_hdr = NULL;
+ for (last_ncsip = NULL; ocsip != NULL; ocsip = ocsip->csinxt)
+  {
+   ncsip = __alloc_csitem();
+   if (last_ncsip == NULL) ncsip_hdr = ncsip; else last_ncsip->csinxt = ncsip;
+   ncsip->csixlst = copy_xprlst(ocsip->csixlst);
+   if (ocsip->csist == NULL) ncsip->csist = NULL; 
+   else ncsip->csist = copy_lstofsts(ocsip->csist);
+   ncsip->csinxt = NULL;
+   last_ncsip = ncsip;
+  }
+ return(ncsip_hdr);
+}
+
+/*
+ * copy an expression list
+ */
+static struct exprlst_t *copy_xprlst(struct exprlst_t *oxplp)
+{
+ register struct exprlst_t *xplp;
+ struct exprlst_t *nxplp_hdr, *nxplp, *last_nxplp;
+
+ nxplp_hdr = NULL;
+ for (last_nxplp = NULL, xplp = oxplp; xplp != NULL; xplp = xplp->xpnxt)
+  {
+   nxplp = __alloc_xprlst();
+   if (last_nxplp == NULL) nxplp_hdr = nxplp; else last_nxplp->xpnxt = nxplp;
+   nxplp->xp = __copy_expr(xplp->xp);
+   last_nxplp = nxplp;
+  }
+ return(nxplp_hdr);
+}
+
+
+/*
+ * copy an expression
+ * this must deal with ID and symbol and globals (or need 2nd vers.)
+ * update expression nodes to point to new modules symbols not old
+ * if needed, caller must free src
+ *
+ */
+extern struct expr_t *__copy_expr(struct expr_t *src)
+{
+ struct expr_t *dst;
+ struct sy_t *syp;
+
+ /* loops can have null expr. slots */
+ if (src == NULL) return(NULL);
+
+ dst = __alloc_newxnd();
+ /* think long constant values can be shared but for now copying */
+ /* copy of number node does node body including type copy */
+ switch ((byte) src->optyp) {
+  case NUMBER: case REALNUM:
+   /* for non IS form constants can share (use same pointer) */
+   *dst = *src;
+   break;
+  case ISNUMBER: case ISREALNUM:
+   *dst = *src;
+   /* 2 cases - if splitting - IS forms impossible else can't share con tab */
+   if (__splitting)
+    {
+     __misc_terr(__FILE__, __LINE__);
+    }
+   break;
+  case ID:
+   /* must point new modules symbol - nothing points back */
+   *dst = *src;
+   /* if not splitting a module, copy has same symbol */
+   if (__splitting)
+    {
+     syp = src->lu.sy;
+     /* for system tasks/functions copied symbol is same as original */
+     if (syp->sytyp != SYM_STSK && syp->sytyp != SYM_SF
+      && syp->synam[0] != '$')
+      dst->lu.sy = (struct sy_t *) syp->spltsy;
+    }
+   break;
+  case XMRID:
+   /* LOOKATME - copying pointers to make sure no shared storage */
+   /* but since both read only maybe do not need to */
+   *dst = *src;
+   /* DBG remove ---*/
+   if (src->ru.qnchp == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   dst->ru.qnchp = __pv_stralloc(src->ru.qnchp);
+   break;
+  case GLBREF:
+   /* need to copy only top level expr because global already copied */
+   /* LOOKATME - if not splitting gref point to original not copied gxndp */
+   /* since not really copying gref think this must work - i.e. not using */
+   *dst = *src;
+   /* know symbol points to old gref entry - this sets new copied gref */
+   /* and expr. cross linking */
+   if (__splitting)
+    {
+     struct gref_t *dgrp, *sgrp;
+
+     /* trick is that src gref field points to dst gref */
+     sgrp = src->ru.grp;
+     /* SJM 06/03/05 - when copying checked defparam, grp gone */
+     /* happens when defparam definition in mode split from pound param */
+     if (sgrp == NULL) dst->ru.grp = NULL; 
+     else
+      {
+       /* destionation global reference saved */
+       dgrp = sgrp->spltgrp;
+       /* dest. gref points to new gref entry */
+       dst->ru.grp = dgrp;
+       /* also finally link dest. group entry expr. ID node ptr to new node */
+       dgrp->gxndp = dst;
+       /* do not need to set lu.sy since later global name resolution sets */
+       /* to target in some other part of design */
+      }
+    }
+   break;
+  default:
+   /* know this is a operator node */
+   /* must copy all contents - need optyp, rest mostly recomputed */
+   *dst = *src;
+   if (src->lu.x != NULL) dst->lu.x = __copy_expr(src->lu.x);
+   if (src->ru.x != NULL) dst->ru.x = __copy_expr(src->ru.x);
+ }
+ return(dst);
+}
+ 
+/*
+ * copy an expressions - special version for xform and vpi 
+ * that does not count in size of expr table
+ */
+extern struct expr_t *__sim_copy_expr(struct expr_t *src)
+{
+ int32 sav_stnum, sav_exprnum;
+ struct expr_t *dst;
+
+ sav_stnum = 0;
+ sav_exprnum = 0;
+ if (__inst_mod != NULL)
+  {
+   sav_stnum = __inst_mod->mstnum;
+   sav_exprnum = __inst_mod->mexprnum;
+  }
+   
+ dst = __copy_expr(src);
+
+ if (__inst_mod != NULL)
+  {
+   __inst_mod->mstnum = sav_stnum;
+   __inst_mod->mexprnum = sav_exprnum;
+  }
+ return(dst);
+}
+
+/*
+ * copy modules' global list
+ *
+ * must copy grefs before copying any expression so can link new expr
+ * to new global
+ */
+static void copy_mgrefs(void)
+{
+ register int32 gri;
+ register struct gref_t *ogrp, *ngrp;
+ int32 num_grefs;
+
+ if (__oinst_mod->mgrnum == 0) return;
+
+ num_grefs = __oinst_mod->mgrnum;
+ __inst_mod->mgrtab = (struct gref_t *)
+  __my_malloc(num_grefs*sizeof(struct gref_t));
+
+ ogrp = &(__oinst_mod->mgrtab[0]);
+ ngrp = &(__inst_mod->mgrtab[0]);
+ for (gri = 0; gri < __oinst_mod->mgrnum; gri++, ogrp++, ngrp++)
+  {
+   copy_1gref_flds(ngrp, ogrp);
+  }
+}
+
+/*
+ * copy 1 gref guts - operation depends on type (processing state) of gref
+ * copies from 2nd ogrp to new ngrp 
+ *
+ * notice copying done before xmr resolution - so only need to copy
+ * things that determine where appears 
+ */
+static void copy_1gref_flds(struct gref_t *ngrp, struct gref_t *ogrp)
+{
+ *ngrp = *ogrp; 
+ /* this will be set when, expr. copied */
+ ngrp->gxndp = NULL;
+ ngrp->grsytp = (struct symtab_t *) ogrp->grsytp->n_head;
+ ngrp->gin_mdp = __inst_mod; 
+ /* need to copy global path because later folding inst/gate array selects */
+ ngrp->glbref = __copy_expr(ogrp->glbref);
+
+ /* this is needed so when expr. copied will point to gref in copied mod */
+ ogrp->spltgrp = ngrp;
+ /* no need to copy grcmps because all copying before resolution */
+}
+
+/*
+ * copy specify section if old has specify
+ */
+static void copy_specify(void)
+{
+ struct spfy_t *ospfyp, *nspfyp;
+
+ /* first allocate new module's specify section */
+ ospfyp = __oinst_mod->mspfy;
+ nspfyp = (struct spfy_t *) __my_malloc(sizeof(struct spfy_t));
+ __inst_mod->mspfy = nspfyp;
+ /* if has symbol table for specparams copy */
+ /* this will link old specparams to new */ 
+ if (ospfyp->spfsyms != NULL) nspfyp->spfsyms = copy_1symtab(ospfyp->spfsyms);
+ /* copy parameters */
+ nspfyp->msprms = copy_params(ospfyp->msprms, ospfyp->sprmnum, SPECIFY);
+ copy_spcpths(ospfyp, nspfyp);
+ copy_timchks(ospfyp, nspfyp);
+}
+
+/*
+ * copy list of specify paths (port to port delay paths)
+ */
+static void copy_spcpths(struct spfy_t *ospfyp, struct spfy_t *nspfyp)
+{
+ struct spcpth_t *npthp, *opthp, *last_npthp, *npthp_hdr;
+ struct sy_t *syp;
+
+ last_npthp = NULL;
+ npthp_hdr = NULL;
+ for (opthp = ospfyp->spcpths; opthp != NULL; opthp = opthp->spcpthnxt)
+  {
+   npthp = (struct spcpth_t *) __my_malloc(sizeof(struct spcpth_t));
+   /* for path this copies most of fields (part of packed constants) */
+   *npthp = *opthp;
+   /* must link copied symbol */
+   syp = (struct sy_t *) opthp->pthsym->spltsy;
+   npthp->pthsym = syp;
+   syp->el.epthp = npthp;
+
+   /* copy the path input and and path output that is here a cast expr list */
+   npthp->peins = (struct pathel_t *)
+    copy_xprlst((struct exprlst_t *) opthp->peins);
+   npthp->peouts = (struct pathel_t *)
+    copy_xprlst((struct exprlst_t *) opthp->peouts);
+
+   /* copy the optional conditional path fields */
+   npthp->datasrcx = __copy_expr(opthp->datasrcx);
+   npthp->pthcondx = __copy_expr(opthp->pthcondx);
+
+   /* copy the delay list - always CMPLST and can be long (up to 12?) */
+   npthp->pth_du.pdels = __copy_dellst(opthp->pth_du.pdels);
+
+   /* finally, link on end */ 
+   npthp->spcpthnxt = NULL;
+   if (last_npthp == NULL) npthp_hdr = npthp;
+   else last_npthp->spcpthnxt = npthp;
+   last_npthp = npthp;
+  }
+ nspfyp->spcpths = npthp_hdr;
+}
+
+/*
+ * copy timing checks 
+ */
+static void copy_timchks(struct spfy_t *ospfyp, struct spfy_t *nspfyp)
+{
+ struct tchk_t *ntcp, *otcp, *last_ntcp, *ntcp_hdr;
+
+ last_ntcp = NULL;
+ ntcp_hdr = NULL;
+ for (otcp = ospfyp->tchks; otcp != NULL; otcp = otcp->tchknxt)
+  {
+   ntcp = copy1_tchk(otcp);
+   /* finally, link on end */ 
+   ntcp->tchknxt = NULL;
+   if (last_ntcp == NULL) ntcp_hdr = ntcp; else last_ntcp->tchknxt = ntcp;
+   last_ntcp = ntcp;
+  }
+ nspfyp->tchks = ntcp_hdr;
+}
+
+/*
+ * copy 1 timing check 
+ * notice here hold half of setuphold not yet copied
+ */
+static struct tchk_t *copy1_tchk(struct tchk_t *otcp)
+{
+ struct tchk_t *ntcp;
+ struct sy_t *syp;
+
+ ntcp = (struct tchk_t *) __my_malloc(sizeof(struct tchk_t));
+ /* this copies flags */
+ *ntcp = *otcp;
+ syp = (struct sy_t *) otcp->tcsym->spltsy;
+ ntcp->tcsym = syp;
+ syp->el.etcp = ntcp;
+
+ if (otcp->startxp != NULL) ntcp->startxp = __copy_expr(otcp->startxp);
+ if (otcp->startcondx != NULL)
+  ntcp->startcondx = __copy_expr(otcp->startcondx);
+ if (otcp->chkxp != NULL) ntcp->chkxp = __copy_expr(otcp->chkxp);
+ if (otcp->chkcondx != NULL) ntcp->chkcondx = __copy_expr(otcp->chkcondx);
+
+ /* know 1st delay limit always required - always CMPLST here */
+ ntcp->tclim_du.pdels = __copy_dellst(otcp->tclim_du.pdels);
+ if (otcp->tc_haslim2) 
+  ntcp->tclim2_du.pdels = __copy_dellst(otcp->tclim2_du.pdels);
+ else ntcp->tclim2_du.pdels = NULL;
+
+ /* at this point, if present, ntfy_np is a sy_t */ 
+ if (otcp->ntfy_np == NULL) ntcp->ntfy_np = NULL;
+ else
+  {
+   syp = (struct sy_t *) otcp->ntfy_np;
+   /* old symbols always have splt sym link to new */
+   syp = syp->spltsy;
+   ntcp->ntfy_np = (struct net_t *) syp;  
+  }
+ return(ntcp);
+}
+
+/*
+ * ROUTINES TO BUILD AS IF FLATTENED INSTANCE TREE
+ */
+
+/*
+ * build a linked tree as if flattened instance structure
+ * needed in simulation and for tracing xmrs
+ * try to set fields at as high a place in tree as possible
+ */
+extern void __bld_flat_itree(void)
+{
+ register int32 ii;
+
+ for (ii = 0; ii < __numtopm; ii++) bld2_flat_itree(__it_roots[ii]);
+ /* DBG remove ---
+ if (__debug_flg)
+  { for (ii = 0; ii < __numtopm; ii++) __dmp_itree(__it_roots[ii]); }
+ --- */
+}
+
+/*
+ * non top level built itree for inst. of one module
+ *
+ * know up instance pointers point to allocated but not set itree nodes
+ * for each inst. in module one up
+ * try to make as breadth first as possible
+ */
+static void bld2_flat_itree(struct itree_t *new_itp)
+{
+ register int32 ii;
+ struct inst_t *ip;
+ struct itree_t *itp;
+ struct mod_t *up_imdp, *imdp;
+
+ up_imdp = new_itp->itip->imsym->el.emdp;
+ /* if mod has no insts empty minsts ptr tab and empty up_itp ptr table */
+ if (up_imdp->minum == 0) return;
+
+ /* allocate pointer to contained itree instances */
+ new_itp->in_its = (struct itree_t *)
+  __my_malloc(up_imdp->minum*sizeof(struct itree_t));
+
+ /* fill contained itree instance contents */ 
+ for (ii = 0; ii < up_imdp->minum; ii++)
+  {
+   /* alloc sets inst_t value */
+   itp = &(new_itp->in_its[ii]);
+   __init_itree_node(itp);
+   ip = &(up_imdp->minsts[ii]);
+   imdp = ip->imsym->el.emdp;
+   itp->itip = ip;
+   itp->up_it = new_itp;
+   /* assign instance number */
+   itp->itinum = imdp->lastinum;
+   imdp->lastinum += 1;
+   /* DBG remove ---
+   if (__debug_flg)
+    {
+     __dbg_msg("==> building flat itree for instance %s of type %s\n",
+      ip->isym->synam, ip->imsym->synam);
+    }
+   --- */
+  }
+ /* finally down 1 level */
+ for (ii = 0; ii < up_imdp->minum; ii++)
+  bld2_flat_itree(&(new_itp->in_its[ii]));
+}
+
+/*
+ * dump a instance tree
+ */
+extern void __dmp_itree(struct itree_t *itp) 
+{
+ register int32 i;
+
+ __dbg_msg("--- dumping instance tree ---.\n");
+ /* dump top */
+ do_dmp(itp, 0);
+ for (i = 1;; i++) { if (!dmp_down_itree(itp, i, i)) return; }
+}
+
+/*
+ * dump a down level of a tree
+ */
+static int32 dmp_down_itree(struct itree_t *itp, int32 lev, int32 more_down)
+{
+ register int32 i; 
+ int32 ofsnum, retval;
+
+ if (more_down == 0) { do_dmp(itp, lev); return(TRUE); }
+ if ((ofsnum = itp->itip->imsym->el.emdp->minum) == 0) return(FALSE);
+ for (retval= FALSE, i = 0; i < ofsnum; i++)
+  {
+   if (dmp_down_itree(&(itp->in_its[i]), lev, more_down - 1))
+    retval = TRUE;
+  }
+ return(retval);
+}
+
+/*
+ * do actual dump for level of 1 itp at level lev
+ */
+static void do_dmp(struct itree_t *itp, int32 lev)
+{
+ int32 ofsnum;
+ char *chp, s1[RECLEN];
+
+ /* DBG remove --- */
+ if (itp->itip == 0) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ if (itp->up_it == NULL) { strcpy(s1, "(top module)"); chp = s1; }
+ else chp = itp->up_it->itip->isym->synam;
+ ofsnum = itp->itip->imsym->el.emdp->minum;
+ __dbg_msg("-- level %d: inst. %s(%s) itinum %d, up %s %d offspring\n",
+  __dagmaxdist - lev, itp->itip->isym->synam, itp->itip->imsym->synam,
+  itp->itinum, chp, ofsnum); 
+}
+
+/*
+ * free under root (top level) itree
+ */
+extern void __free_flat_itree(void)
+{
+ register int32 ii;
+ register struct mod_t *mdp;
+
+ for (ii = 0; ii < __numtopm; ii++) free2_flat_itree(__it_roots[ii]);
+
+ /* final step requires resetting last inum field in every module */ 
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt) mdp->lastinum = 0;
+}
+
+/*
+ * free itree in_its tables bottom up
+ */
+static void free2_flat_itree(struct itree_t *cur_itp)
+{
+ register int32 ii;
+ struct mod_t *cur_imdp;
+
+ cur_imdp = cur_itp->itip->imsym->el.emdp;
+
+ /* if mod has no insts, nothing to do, if not top up frees */ 
+ if (cur_imdp->minum == 0) return;
+
+ /* otherwise free all under first */
+ for (ii = 0; ii < cur_imdp->minum; ii++)
+  free2_flat_itree(&(cur_itp->in_its[ii]));
+
+ /* all under freed but in its table not yet freed */
+ __my_free ((char *) cur_itp->in_its, cur_imdp->minum*sizeof(struct itree_t)); 
+ cur_itp->in_its = NULL;
+}
+
+/*
+ * ROUTINES TO BUILD INSTANCE NUMBER TO ITREE TABLES
+ */
+
+/*
+ * build mod itp tabs for all modules
+ *
+ * look to improve this - either build only when needed or remove unneeded
+ * before run time
+ */
+static void bld_moditps(void)
+{
+ register struct mod_t *mdp;
+ register int32 ii;
+ struct itree_t *itp, *itp2;
+
+ /* first allocate the inst num to itree location tables */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   mdp->moditps = (struct itree_t **)
+   __my_malloc(mdp->flatinum*sizeof(struct itree_t *));
+   memset(mdp->moditps, 0, mdp->flatinum*sizeof(struct itree_t *));
+  }
+
+ for (ii = 0; ii < __numtopm; ii++)
+  {
+   itp = __it_roots[ii];
+   mdp = itp->itip->imsym->el.emdp;
+   mdp->moditps[itp->itinum] = itp;
+   bld2_itnum_to_itp(itp);
+  }
+
+
+ if (__debug_flg)
+  {
+   for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+    {
+     __dbg_msg("\n--- module %s instances:\n", mdp->msym->synam);
+     for (ii = 0; ii < mdp->flatinum; ii++)
+      {
+       itp2 = mdp->moditps[ii];
+       __dbg_msg("  instance %s type %s\n", __msg2_blditree(__xs, itp2),
+        itp2->itip->imsym->synam);
+      }
+    }
+   __dbg_msg("\n");
+  }
+}
+
+/*
+ * recusively build the table
+ */
+static void bld2_itnum_to_itp(struct itree_t *itp)
+{
+ register int32 ii;
+ struct mod_t *mdp;
+ 
+ mdp = itp->itip->imsym->el.emdp;
+ if (mdp->moditps != NULL) mdp->moditps[itp->itinum] = itp;
+ for (ii = 0; ii < mdp->minum; ii++) bld2_itnum_to_itp(&(itp->in_its[ii]));
+}
+
diff --git a/src/v_fx2.c b/src/v_fx2.c
new file mode 100644
index 0000000..0b93ff6
--- /dev/null
+++ b/src/v_fx2.c
@@ -0,0 +1,8854 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * module that fixes and checks net list after all source read
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void bld_root_dfpglbs(void);
+static int32 dfploc_cmp(const void *, const void *);
+static void dmp_dfps(int32, int32);
+static void bld_root2_dfpglbs(struct itree_t *, int32);
+static void bld_identdfparams(int32);
+static int32 ipth_cmp(const void *, const void *);
+static int32 ipth2_cmp(register struct dfparam_t *, register struct dfparam_t *);
+static void find_mustsplit_dfps(void);
+static void do_defparam_splitting(void);
+static void reset_dfp_targsyps(void);
+static void reset_1dfp_targsyp(struct dfparam_t *);
+static void reassign2_itnums(struct itree_t *);
+static void set2_poundparams(struct itree_t *);
+static void assgn_is_param(struct net_t *, struct xstk_t *, int32, int32, int32);
+static void replace_param_rhs_expr(struct net_t *, word32 *, struct mod_t *);
+static void set_1defparam(struct dfparam_t *);
+static void recalc_1mod_params(struct mod_t *);
+static void recalc_1mod_pndparams(struct mod_t *);
+static int32 xpr_has_is_param(struct expr_t *);
+static void set_parmval_from_isxpr(struct net_t *, struct expr_t *,
+ struct mod_t *);
+static int32 all_parent_mods_recalced(struct mod_t *);
+
+static void set_lhs_expr_drvrtyp(struct expr_t *, int32, int32, int32);
+static int32 comp_pre_elab_norm_con_ndx(struct net_t *, struct expr_t *, int32,
+ int32);
+static int32 is_nonis_const_expr(struct expr_t *);
+static void set_scalar_drvr_type(struct net_t *, int32);
+static void set_vec_drvr_type(struct net_t *, int32, int32, int32);
+static int32 port_expr_has_wrong_dir_drvr(struct expr_t *, int32, int32, int32, int32,
+ int32);
+static int32 find_max_rng_drvr_state(struct net_t *, int32, int32);
+static int32 expr_decl_lvalue(struct expr_t *);
+static void chg_mpx_to_bid(struct expr_t *);
+static void free_design_ndrvrs(void);
+
+static void bld_timstr_vals(void);
+static void inrnges_mark_params(struct symtab_t *);
+static void psel_set_allexprs(struct mod_t *);
+static void stmt_do_inpsel_set(struct st_t *);
+static void lstofsts_do_inpsel_set(register struct st_t *);
+static void csitemlst_do_inpsel_set(register struct csitem_t *);
+static void inpsel_xpr_markparam(struct expr_t *);
+static void chk_undef_syms(struct symtab_t *, word32);
+static void chkset_1mwire_rnges(void);
+static void chk_modsym(struct sy_t *);
+static void chk_1wire(struct net_t *);
+static void chk_1reg(struct net_t *);
+static void mark_sttypewires(void);
+static void mark_stdr_wires(void);
+static void mark_stdr_inout_wired_logic(void);
+static int32 has_non_stren_wired_net(struct expr_t *);
+static int32 net_type_tri(word32);
+static int32 chk_hasst_wires(struct mod_t *, struct expr_t *);
+static void mark_stwires(struct mod_t *, struct expr_t *);
+static void prop_stsdown(void);
+static void prop_stsup(void);
+static int32 chkdel_expr(struct expr_t *, char *, int32);
+static int32 nd_delnum(struct expr_t *, char *);
+static int32 nd_delisnum(struct expr_t *, char *);
+static void freeset_is0del(struct expr_t *, int32);
+static void wr_ndisdel_err(struct expr_t *, int32, char *);
+static void chk_wire_rng(struct net_t *);
+static void chg_rng_isnum_to_num(struct net_t *, struct expr_t *, char *);
+static void chk_taskvars(struct task_t *, int32);
+static int32 chk_prtwidth(struct expr_t *, struct mod_pin_t *);
+static void emit_shorted_informs(int32);
+static void emit_1net_shorted_informs(struct mod_pin_t *, int32,
+ struct net_t *, int32);
+static int32 net_in_expr(struct net_t *, struct expr_t *);
+static int32 xhas_multconn_wire(struct expr_t *);
+static void emit_nonbid_shortwarn(struct mod_pin_t *, struct expr_t *);
+static void reconn_1mod_gateterms(struct mod_t *);
+static struct expr_t *bld_bsel_expr(struct net_t *, int32);
+static void conn_1gateterm_concat(struct mod_t *, struct giarr_t *,
+ struct expr_t *, int32);
+static int32 legal_giarr_conn_concat(struct expr_t *);
+static void reconn_1mod_instports(struct mod_t *);
+static struct expr_t *bld_psel_expr(struct net_t *, int32, int32);
+static void conn_1instport_concat(struct mod_t *, struct giarr_t *,
+ struct expr_t *, int32, int32);
+static struct exprlst_t *splt_icat_align_xlist(struct expr_t *, int32);
+static struct expr_t *bld_num_expr(struct xstk_t *);
+static void set_1mpx_stren(struct expr_t *);
+static void chk_1tsk(struct task_t *);
+static void chk_inst_conns(void);
+static void chk_iconn_downxmr(struct inst_t *, struct expr_t *);
+static void chk_iconn_mixeddirrng(struct inst_t *, struct mod_pin_t *,
+ struct expr_t *);
+static void chk_gates(void);
+static int32 chk_1bltingate(struct gate_t *);
+static void gate_errifn(struct gate_t *, int32);
+static void chk_gate_nostren(struct gate_t *);
+static void chk_tran_gate(struct gate_t *);
+static int32 chk_tran_terms_same(struct gate_t *);
+static void set_unc_gateterm(struct gate_t *, int32);
+static void chk_1bit_tran(struct gate_t *, struct expr_t *, struct net_t *,
+ int32);
+static void chk_tranif_gate(struct gate_t *);
+static void chk_pull_gate(struct gate_t *);
+static int32 chk_1udp(struct gate_t *);
+static int32 chk_gate_source(struct gate_t *, struct expr_t *, int32, int32,
+ struct net_t **);
+static void chk_contas(void);
+static void cnv_1bcas_into_garr(int32, struct conta_t *); 
+static struct gate_t *convert_1bca_togate(struct gate_t *,
+ struct conta_t *);
+static void nd_1bit_concat(struct expr_t *);
+static void chk_getpat_nonscal(struct expr_t *);
+static void chk_funcdef(struct task_t *);
+static void chk_fdef_args(struct task_t *);
+static void chk_nodel_stmt(struct st_t *);
+static void chk_nodel_dsable(struct st_t *);
+static int32 lhsexpr_hassym(struct expr_t *, struct sy_t *);
+static void chk_varinits(void);
+static void chk_stmts(void);
+static void chk_1stmt(struct st_t *);
+static void chk_case(struct st_t *);
+static void chk_dctrl(struct delctrl_t *);
+static void bld_stlst_evxlst(struct st_t *);
+static void bld_stmt_evxlst(struct st_t *);
+static void bld_case_evxlst(struct st_t *);
+static void bld_tskenable_evxlst(struct st_t *);
+static void bld_rhs_impl_evxlst(struct expr_t *);
+static void bld_lhs_impl_evxlst(struct expr_t *);
+static int32 xp_in_evxlst(struct expr_t *); 
+static struct expr_t *bld_evlst_comma_expr(void);
+static void chk_qclvalue(struct expr_t *, word32, int32 *);
+static void set_qc_frcassgn_net(struct expr_t *);
+static int32 nd_qcreg(struct expr_t *);
+static void chk_circular_qc_stmt(struct st_t *);
+static int32 rhs_expr_has_net(struct expr_t *, struct net_t *);
+static void chk_disable(struct st_t *);
+static void reassign_itnums(void);
+
+/* extern prototypes (maybe defined in this module) */
+extern char *__my_malloc(int32);
+extern char *__my_realloc(char *, int32 , int32);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_ptnam(char *, word32);
+extern char *__to_sytyp(char *, word32);
+extern char *__to_sttyp(char *, word32);
+extern char *__to_qctyp(char *, word32);
+extern char *__to_idnam(struct expr_t *);
+extern char *__to_mpnam(char *, char *);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char *__msgnumexpr_tostr(char *, struct expr_t *, int32);
+extern struct expr_t *__copy_expr(struct expr_t *);
+extern struct xstk_t *__eval2_xpr(struct expr_t *);
+extern char *__pregab_tostr(char *, word32 *, word32 *, struct net_t *);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern struct expr_t *__alloc_newxnd(void);
+extern struct expr_t *__bld_rng_numxpr(word32, word32, int32);
+extern struct paramlst_t *__copy_dellst(struct paramlst_t *);
+extern void __set_poundparams(void);
+extern void __set_1inst_pound_params(struct itree_t *, int32);
+extern void __free_1dfparam(struct dfparam_t *);
+extern struct itree_t *__find_dfpbot_itp(struct dfparam_t *);
+extern int32 __ip_indsrch(char *);
+extern void __my_free(char *, int32);
+extern void __mark_widdet_params(struct mod_t *);
+extern void __do_mdsplit(struct mod_t *);
+extern void __dmp_itree(struct itree_t *); 
+extern void __sizchgxs(struct xstk_t *, int32);  
+extern void __narrow_sizchg(register struct xstk_t *, int32);
+extern void __sizchg_widen(register struct xstk_t *, int32);
+extern void __sgn_xtnd_widen(struct xstk_t *, int32);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern void __in_xpr_markparam(struct expr_t *);
+extern int32 __chk_delparams(struct paramlst_t *, char *, int32);
+extern void __free_dellst(struct paramlst_t *);
+extern void __bld_mlevel_lists(void);
+extern int32 __get_netwide(struct net_t *);
+extern int32 __chk_rhsexpr(struct expr_t *, int32);
+extern int32 __chk_numdelay(struct expr_t *, char *);
+extern void __free_xtree(struct expr_t *);
+extern void __free2_xtree(struct expr_t *);
+extern void __init_xnd(struct expr_t *);
+extern int32 __get_arrwide(struct net_t *);
+extern int32 __nd_ndxnum(struct expr_t *, char *, int32);
+extern int32 __chk_lhsexpr(struct expr_t *, int32);
+extern void __set_expr_onrhs(struct expr_t *);  
+extern void __chk_lstofsts(struct st_t *);
+extern struct expr_t *__widen_unsiz_rhs_assign(struct expr_t *, int);
+extern struct expr_t *__get_lvalue_idndp(struct expr_t *);
+extern void __chk_nodel_lstofsts(struct st_t *);
+extern int32 __isleaf(struct expr_t *);
+extern void __getwir_range(struct net_t *, int32 *, int32 *);
+extern int32 __unnormalize_ndx(struct net_t *, int32);
+extern int32 __chk_lhsdecl_scalared(struct expr_t *);
+extern void __push_nbstk(struct st_t *);
+extern void __pop_nbstk(void);
+extern int32 __is_upward_dsable_syp(struct sy_t *, struct symtab_t *, int32 *);
+extern void __chk_tskenable(struct st_t *);
+extern void __set_lhswidth(struct expr_t *);
+extern int32 __get_rhswidth(struct expr_t *);
+extern void __chk_evxpr(struct expr_t *);
+extern int32 __xhas_reg(struct expr_t *);
+extern int32 __get_giarr_wide(struct giarr_t *giap);
+extern void __rhspsel(register word32 *, register word32 *, register int32,
+ register int32);
+extern int32 __chkndx_expr(struct expr_t *, char *);
+extern int32 __expr_has_glb(struct expr_t *);
+extern void __bld_unc_expr(void);
+extern struct exprlst_t *__alloc_xprlst(void);
+extern void __chk_1mdecls(void);
+extern void __cnv_stk_fromreg_toreal(struct xstk_t *, int32);
+extern void __cnv_stk_fromreal_toreg32(struct xstk_t *);
+extern void __cnvt_param_stkval(struct xstk_t *, struct expr_t *,
+ struct net_t *, char *);
+extern void __set_drvr_bits(void);
+extern void __chk_chg_port_dir(int32);
+extern void __assgn_nonis_param(struct net_t *, struct expr_t *,
+ struct xstk_t *);
+extern void __chg_param_tois(struct net_t *, struct mod_t *);
+extern int32 __alloc_is_cval(int32);
+extern int32 __allocfill_cval_new(word32 *, word32 *, int32);
+extern int32 __alloc_shareable_cval(word32, word32, int32);
+extern int32 __alloc_shareable_rlcval(double);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern int32 __is_const_expr(struct expr_t *);
+extern int32 __xpr_has_param(struct expr_t *);
+extern void __bld_flat_itree(void);
+extern void __free_flat_itree(void);
+extern int32 __cmp_xpr(struct expr_t *, struct expr_t *);
+extern int32 __chk_paramexpr(struct expr_t *, int32);
+extern void __set_numval(struct expr_t *, word32, word32, int32);
+
+extern void __cv_msg(char *, ...);
+extern void __gfwarn(int32, word32, int32, char *, ...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __gfinform(int32, word32, int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __sgfterr(int32, char *, ...);
+extern void __pv_terr(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __misc_sgfterr(char *, int32);
+extern void __misc_gfterr(char *, int32, word32, int32);
+
+extern word32 __masktab[];
+
+/*
+ * ROUTINES TO SAVE INITIAL SOURCE FOR PLI USE
+ */
+
+/*
+ * ROUTINES TO PROCESS XMR TYPE DEFPARAMS 
+ */
+
+/*
+ * use all defparams in current module to change local param init values
+ * in other modules
+ * notice all defparams used to set module init values before values
+ * used in code
+ *
+ * notice defparams are not module items but parameters can be used on
+ * lvalues and defparams allowed in tasks where they can only
+ * be set with global ref. defparams
+ */
+extern void __process_defparams(void)
+{
+ struct dfparam_t *dfpp;
+
+ /* convert all downward relative defparams to rooted */
+ /* linked on by root nxt - even if 1 will be on root nxt */
+ bld_root_dfpglbs();
+
+ /* handle splitting of all defparams */
+ do_defparam_splitting();
+ /* by here arrays of instances have been converted into normal instances */
+ if (__pndparam_splits || __defparam_splits) reset_dfp_targsyps();
+
+ /* go through flat itree and reset all instance numbers */
+ reassign_itnums();
+
+ /* SJM 03/16/04 - rebuild the levelized static (src contents) if any */
+ /* defparam spliting - if only pound param splitting still good */
+ /* this is not strictly needed now but will be for future generate */
+ if (__defparam_splits) __bld_mlevel_lists();
+
+ /* set pound params if needed */
+ if (__num_inst_pndparams > 0) __set_poundparams();
+
+ /* fixup new target syps and mdps if needed and set defparams */
+ /* this must be in exact source order including in root or local */
+ for (dfpp = __dfphdr; dfpp != NULL; dfpp = dfpp->dfpnxt)
+  set_1defparam(dfpp);
+}
+
+/*
+ * ROUTINES TO CONVERT ALL DOWNWARD DEFPARAMS TO ROOTED
+ */
+
+/*
+ * convert defparam lhs non rooted globals to right number of rooted 
+ * links off non rooted and build 1 design wide list
+ *
+ * know will be at least one defparam or will not be called
+ * after here all design wide defparams in one list
+ * module mdfps unused after here
+ */
+static void bld_root_dfpglbs(void)
+{
+ register int32 ii;
+ register struct dfparam_t *dfpp, *dfpp2;
+ int32 num_defparams, num_locdefparams;
+ struct dfparam_t *last_dfpp, *dfpp3, **dfpptab;
+ struct mod_t *dfpmdp;
+
+ /* go through list of 1 inst. corresponding to each top level module */
+ /* this also sets itree place to eval. rhs in */
+ for (ii = 0; ii < __numtopm; ii++) bld_root2_dfpglbs(__it_roots[ii], 1);
+
+ /* convert to design wide linear defparam list */
+ last_dfpp = NULL;
+ num_defparams = num_locdefparams = 0;
+ for (dfpmdp = __modhdr; dfpmdp != NULL; dfpmdp = dfpmdp->mnxt)
+  {
+   for (dfpp = dfpmdp->mdfps; dfpp != NULL;)
+    {
+     if (dfpp->dfp_local || dfpp->dfp_rooted)
+      {
+       if (last_dfpp == NULL) __dfphdr = dfpp;
+       else last_dfpp->dfpnxt = dfpp;
+       last_dfpp = dfpp;
+       num_defparams++;
+       if (dfpp->dfp_local) num_locdefparams++;
+       dfpp = dfpp->dfpnxt;
+       continue;
+      }
+     dfpp2 = dfpp->rooted_dfps;
+     for (; dfpp2 != NULL; dfpp2 = dfpp2->rooted_dfps)
+      {
+       if (last_dfpp == NULL) __dfphdr = dfpp2;
+       else last_dfpp->dfpnxt = dfpp2;
+       last_dfpp = dfpp2;
+       num_defparams++;
+      }
+     dfpp3 = dfpp->dfpnxt;
+     /* finally free unrooted that has been replaced by rooted */
+     __free_1dfparam(dfpp);
+     dfpp = dfpp3;
+    }
+   /* SJM 02/18/01 - since freed need to set to nil to prevent copying */
+   /* when modules split - defparams are copied for giarr splitting */
+   dfpmdp->mdfps = NULL;
+  }
+ if (last_dfpp != NULL) last_dfpp->dfpnxt = NULL;
+
+ /* sort global defparams by location since last must override */
+ /* know there will always be a least one defparam here */
+ dfpptab = (struct dfparam_t **)
+  __my_malloc(num_defparams*sizeof(struct dfparam_t *));
+ for (ii = 0, dfpp = __dfphdr; ii < num_defparams; ii++, dfpp = dfpp->dfpnxt) 
+  dfpptab[ii] = dfpp;
+ qsort((char *) dfpptab, num_defparams, sizeof(struct dfparam_t *),
+  dfploc_cmp);
+ __dfphdr = dfpptab[0];
+ dfpp3 = __dfphdr;
+ for (ii = 1; ii < num_defparams; ii++)
+  {
+   dfpp3->dfpnxt = dfpptab[ii];
+   dfpp3 = dfpp3->dfpnxt;
+  }
+ dfpp3->dfpnxt = NULL;
+ /* design wide rooted (or local) def param list now ordered */
+ __my_free((char *) dfpptab, num_defparams*sizeof(struct dfparam_t *));
+
+ /* SJM 06/04/05 - nil the rooted dfps field since no longer needed */
+ /* could leave but nil makes debugging easier */
+ for (dfpp = __dfphdr; dfpp != NULL; dfpp = dfpp->dfpnxt)
+  dfpp->rooted_dfps = NULL;
+
+ /* only find identicals if at least one non local */
+ if (num_defparams - num_locdefparams != 0)
+  {
+   bld_identdfparams(num_defparams - num_locdefparams);
+   find_mustsplit_dfps();
+  } 
+ if (__debug_flg) dmp_dfps(TRUE, TRUE);
+}
+
+static int32 dfploc_cmp(const void *dfpp1, const void *dfpp2)
+{
+ int32 cv;
+
+ cv = (*((struct dfparam_t **) dfpp1))->dfpfnam_ind
+  - (*((struct dfparam_t **) dfpp2))->dfpfnam_ind;
+ if (cv != 0) return(cv);
+ return((*((struct dfparam_t **) dfpp1))->dfplin_cnt
+  - (*((struct dfparam_t **) dfpp2))->dfplin_cnt);
+}
+
+/*
+ * dump defparam list
+ * only called if debugging on
+ *
+ * SJM 05/25/05 - rewrote to work with converted to rooted dfps
+ */
+static void dmp_dfps(int32 emit_pth, int32 now_rted)
+{
+ struct dfparam_t *dfpp;
+ register int32 dfi, ii; 
+ char identtyp;
+ struct inst_t *ip;
+
+ __dbg_msg("$$$ Dumping all design defparams $$$\n");
+ for (dfpp = __dfphdr; dfpp != NULL; dfpp = dfpp->dfpnxt)
+  {
+   if (dfpp->dfp_has_idents) 
+    { if (dfpp->idntmastdfp == NULL) identtyp = 'M'; else identtyp = 'Y'; }
+   else identtyp = 'N';
+   __dbg_msg("==> defparam %s in %s at %s loc.=%u rooted=%u identical=%c\n",
+    dfpp->gdfpnam, dfpp->in_mdp->msym->synam,
+   __bld_lineloc(__xs, dfpp->dfpfnam_ind, dfpp->dfplin_cnt),
+    dfpp->dfp_local, dfpp->dfp_rooted, identtyp);
+
+   /* will not have component since accessed from master */
+   if (dfpp->idntmastdfp != NULL || !emit_pth || dfpp->dfp_local) continue;
+
+   /* here must still allocate dfpiis */
+   /* if root in module that is multiply instantiated must see table */
+   /* only once and rule is last source order is right instance to eval in */
+   ii = dfpp->dfpiis[0];
+   if (dfpp->dfp_rooted || now_rted) ip = __top_itab[ii];
+   else ip = &(dfpp->in_mdp->minsts[ii]);  
+   for (dfi = 0; dfi <= dfpp->last_dfpi; dfi++) 
+    {
+     sprintf(__xs, " (inst type %s)", ip->imsym->synam);
+     __dbg_msg("   component %s%s index %d\n", __xs, ip->isym->synam, ii);
+
+     ii = dfpp->dfpiis[dfi + 1];
+     if (dfi < dfpp->last_dfpi) ip = &(ip->imsym->el.emdp->minsts[ii]); 
+    }
+   __dbg_msg("\n");
+  }
+ __dbg_msg("$$$ end of defparms $$$\n");
+}
+
+/*
+ * dump all param expressions 
+ */
+extern void __dmp_all_param_exprs(void)
+{
+ register int32 pi, ii;
+ register struct mod_t *mdp;
+ register struct net_t *np;
+ int32 wlen;
+ word32 *wp;
+
+ __dbg_msg("*** dumping all params ***\n");
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (pi = 0; pi < mdp->mprmnum; pi++)
+    {
+     np = &(mdp->mprms[pi]);
+     wlen = wlen_(np->nwid);
+
+     /* parameter has IS form, eval rhs from itree place and set num */
+     if (np->srep == SR_PISNUM)
+      {
+       for (ii = 0; ii < mdp->flatinum; ii++)
+        {
+         wp = &(np->nva.wp[2*ii*wlen]);
+         __dbg_msg("module %s param %s value %s\n", mdp->msym->synam,
+          np->nsym->synam, __pregab_tostr(__xs, wp, &(wp[wlen]), np));
+        } 
+      }
+     else if (np->srep == SR_PNUM)
+      {
+       wp = np->nva.wp;
+       __dbg_msg("module %s param %s rhs expr. %s\n", mdp->msym->synam,
+        np->nsym->synam, __pregab_tostr(__xs, wp, &(wp[wlen]), np));
+      }
+     else __case_terr(__FILE__, __LINE__);
+     if (np->nrngrep != NX_CT) __misc_terr(__FILE__, __LINE__);
+     if (np->n_isarr)
+      {
+       __dbg_msg("  array range [%s:%s]", __msgexpr_tostr(__xs,
+        np->nu.ct->nx1), __msgexpr_tostr(__xs2, np->nu.ct->nx2));
+      }
+     else __dbg_msg(" ");
+     if (np->n_isavec)
+      {
+       __dbg_msg(" range [%s:%s]\n", __msgexpr_tostr(__xs, np->nu.ct->nx1),
+        __msgexpr_tostr(__xs2, np->nu.ct->nx2));
+      }
+     else __dbg_msg("\n");
+    }
+  }
+ __dbg_msg("*** end of dump ***\n");
+}
+
+/*
+ * under each top module's convert defparam lhs global to rooted form
+ * uses extra storage but reclaimed after defparams substituted
+ *
+ * this just updates dfpiis for downward relative
+ * downward relative symbols in top module are not rooted but can never
+ * be in list
+ */
+static void bld_root2_dfpglbs(struct itree_t *itp, int32 level)
+{
+ register struct dfparam_t *dfpp;
+ struct dfparam_t *new_dfpp;
+ int32 i, ii, rtlen, *newiis;
+ byte *bp1, *bp2;
+ struct mod_t *imdp;
+ struct itree_t *tmpitp, *upitp;
+
+ if (level >= MAXGLBCOMPS)
+  {
+too_deep:
+   __pv_terr(310,
+    "downward defparam hierarchical path has too many components (%d)",
+    MAXGLBCOMPS); 
+  } 
+ imdp = itp->itip->imsym->el.emdp;
+ /* --- */
+ if (__debug_flg)
+  {
+   __dbg_msg("==> building defparam globals in inst. %s type %s\n",
+    itp->itip->isym->synam, imdp->msym->synam);
+  }
+ /* --- */ 
+
+ /* convert unrooted to defparam rooted */
+ /* even if only one inst. of this need rooted form */ 
+ for (dfpp = imdp->mdfps; dfpp != NULL; dfpp = dfpp->dfpnxt)
+  {
+   /* SJM 05/26/05 - can't use indfp itp for dfps because splitting changes */
+   if (dfpp->dfp_local)
+    {
+     /* local defparams - NULL means in all instances - for dependent */
+     /* if rhs defparam is IS form must convert local value to IS form */
+     continue;
+    }
+
+   /* if root in module that is multiply instantiated must see table */
+   /* only once and rule is last source order is right instance to eval in */
+   if (dfpp->dfp_rooted) 
+    {
+     /* if rooted appears in multiply instantiated, possible that rhs */
+     /* expr. can contain IS form so that same target rooted defparam lhs */ 
+     /* gets assigned to once for each - using last one since arbitrary */
+     continue;
+    }
+   rtlen = level + dfpp->last_dfpi + 1;  
+   if (rtlen >= MAXGLBCOMPS) goto too_deep;
+   newiis = (int32 *) __my_malloc(rtlen*sizeof(int32));
+   /* fill the new prefix - need instance symbol except module at top */ 
+   /* this is downward relative in top level */
+   tmpitp = itp;
+   for (i = level; i > 0; i--)
+    {
+     if (tmpitp->up_it == NULL)
+      {
+       ii = __ip_indsrch(tmpitp->itip->imsym->synam);
+       /* DBG remove -- */
+       if (ii == -1) __misc_terr(__FILE__, __LINE__);
+       if (i != 1) __misc_terr(__FILE__, __LINE__);
+       /* --- */
+       newiis[i - 1] = ii;
+       continue;
+      }
+     upitp = tmpitp->up_it;
+     bp1 = (byte *) tmpitp->itip;
+     bp2 = (byte *) upitp->itip->imsym->el.emdp->minsts;
+     ii = (bp1 - bp2)/sizeof(struct inst_t);
+     newiis[i - 1] = ii;
+     tmpitp = upitp;
+    }
+   /* finish by copying rest of path */
+   __last_gsc = level;
+   for (i = 0; i <= dfpp->last_dfpi; __last_gsc++, i++)
+    newiis[__last_gsc] = dfpp->dfpiis[i];
+
+   /* if module has only 1 flattened instance just replace dfcmps */
+   /* notice tail param targsyp same for each */
+   if (imdp->flatinum == 1)
+    {
+     __my_free((char *) dfpp->dfpiis, (dfpp->last_dfpi + 1)*sizeof(int32));
+     dfpp->dfpiis = newiis;
+     dfpp->last_dfpi = __last_gsc - 1;
+     dfpp->dfp_rooted = TRUE;
+     continue;
+    }
+   new_dfpp = (struct dfparam_t *) __my_malloc(sizeof(struct dfparam_t));
+   *new_dfpp = *dfpp;
+   /* need to copy expressions here, since at least free requires sep. */
+   new_dfpp->dfpxlhs = __copy_expr(dfpp->dfpxlhs);
+   new_dfpp->dfpxrhs = __copy_expr(dfpp->dfpxrhs);
+   /* notice tail is pointed to by targsyp (not in cmps) */
+   new_dfpp->dfpiis = newiis;
+   new_dfpp->last_dfpi = __last_gsc - 1;
+
+   /* put on front */
+   new_dfpp->rooted_dfps = dfpp->rooted_dfps;
+   dfpp->rooted_dfps = new_dfpp;
+   /* downward relative stem freed when new rooted copied to design list */
+  }
+ /* process 1 down depth first */
+ for (ii = 0; ii < imdp->minum; ii++)
+  bld_root2_dfpglbs(&(itp->in_its[ii]), level + 1);
+}
+
+/*
+ * build the list of defparams independent of source module that have
+ * identical target module - goes through all defparams and connect
+ * those with identical target module
+ *
+ * this order identical path maybe same or maybe different defparams
+ * in source order so same will always use last source order
+ */
+static void bld_identdfparams(int32 nrtdfps)
+{
+ register int32 dfi, dfi2;
+ register struct dfparam_t *dfpp1, *dfpp2;
+ struct dfparam_t *mastdfp, *dfpend, **dfppndx;
+
+ /* build and sort index - ordered so all same rooted paths contingous */ 
+ /* within same paths ordered by source order */ 
+ dfppndx = (struct dfparam_t **)
+  __my_malloc(nrtdfps*sizeof(struct dfparam_t *));
+ for (dfi = -1, dfpp1 = __dfphdr; dfpp1 != NULL; dfpp1 = dfpp1->dfpnxt)
+  {
+   if (!dfpp1->dfp_local) dfppndx[++dfi] = dfpp1;
+  }
+ qsort((char *) dfppndx, nrtdfps, sizeof(struct dfparam_t *), ipth_cmp);
+
+ for (dfi = 0; dfi < nrtdfps;)
+  {
+   dfpp1 = dfppndx[dfi];
+   /* because of sorting - never see one already in equivalence class */ 
+   /* DBG remove -- */
+   if (dfpp1->dfp_has_idents) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   if ((dfi2 = dfi + 1) >= nrtdfps) break;
+   dfpp2 = dfppndx[dfi2];
+   /* DBG remove -- */
+   if (dfpp2->dfp_has_idents) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   if (ipth2_cmp(dfpp1, dfpp2) != 0) { dfi++; continue; }
+
+   /* know at least 2 equivalent - first is master */
+   mastdfp = dfpend = dfpp1;
+   dfpp1->idntmastdfp = NULL;
+   dfpp1->dfp_has_idents = TRUE;
+   for (;;)
+    {
+     /* DBG remove -- */
+     if (dfpp2->dfp_has_idents) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+
+     /* mark has ident and link on front of current work list */  
+     dfpp2->dfp_has_idents = TRUE;
+     dfpp2->idntmastdfp = mastdfp;
+     dfpend->idntnxt = dfpp2;
+     dfpend = dfpp2;
+     /* DBG remove --- */
+     if (__debug_flg)
+      {
+       __dbg_msg("defparam %s in %s at %s same target inst. as %s at %s\n",  
+        dfpp2->gdfpnam, dfpp2->in_mdp->msym->synam,     
+        __bld_lineloc(__xs, dfpp2->dfpfnam_ind, dfpp2->dfplin_cnt),
+        mastdfp->gdfpnam, __bld_lineloc(__xs2, mastdfp->dfpfnam_ind,
+        mastdfp->dfplin_cnt));
+      }
+     /* --- */
+     if (++dfi2 >= nrtdfps) break; 
+     dfpp2 = dfppndx[dfi2];
+     /* if not in current equiv. class, may start next one */ 
+     if (ipth2_cmp(dfpp1, dfpp2) != 0) break;
+    }
+   dfpend->idntnxt = NULL;
+   dfi = dfi2;
+  } 
+ __my_free((char *) dfppndx, nrtdfps*sizeof(struct dfparam_t *));
+}
+
+/*
+ * wrapper for sorting defparams - if same order by source loc.
+ */
+static int32 ipth_cmp(const void *dfpp1p, const void *dfpp2p)
+{
+ register int32 cv;
+ register struct dfparam_t *dfpp1, *dfpp2;
+
+ dfpp1 = *((struct dfparam_t **) dfpp1p);
+ dfpp2 = *((struct dfparam_t **) dfpp2p);
+  
+ if ((cv = ipth2_cmp(dfpp1, dfpp2)) != 0) return(cv);
+
+ /* if same, need source location order */ 
+ cv = dfpp1->dfpfnam_ind - dfpp2->dfpfnam_ind;
+ if (cv != 0) return(cv);
+ cv = (dfpp1->dfplin_cnt - dfpp2->dfplin_cnt);
+ if (cv != 0) return(cv);
+ return(0);
+}
+
+/*
+ * compare 2 defparam records (use address for order)
+ */
+static int32 ipth2_cmp(register struct dfparam_t *dfpp1,
+ register struct dfparam_t *dfpp2)
+{
+ register int32 ii;
+ register struct sy_t *sy1, *sy2;
+ int32 atend1, atend2;
+ struct itree_t *itp1, *itp2;
+
+ itp1 = __it_roots[dfpp1->dfpiis[0]];
+ itp2 = __it_roots[dfpp2->dfpiis[0]];
+ for (ii = 0;;)
+  {
+   /* DBG remove --
+   if (itp1->itip == NULL || itp2->itip == NULL)
+    __misc_terr(__FILE__, __LINE__);
+   --- */
+   sy1 = itp1->itip->isym;
+   sy2 = itp2->itip->isym;
+   /* SJM 06/03/02 - cast to int32 and minus not 64 bit portable */
+   if (sy1 != sy2)
+    {
+     if (sy1 > sy2) return(1);
+     return(-1);
+    }
+   ii++;
+   atend1 = (ii > dfpp1->last_dfpi);
+   atend2 = (ii > dfpp2->last_dfpi);
+   if (!atend1 && !atend2)
+    {
+     itp1 = &(itp1->in_its[dfpp1->dfpiis[ii]]);
+     itp2 = &(itp2->in_its[dfpp2->dfpiis[ii]]);
+     continue;
+    }
+   /* if both past end - done (know same length) */
+   if (atend1 && atend2) break;
+   /* know one but not other past end - done with shortest first */
+   if (atend1) return(-1); 
+   return(1);
+  }
+ return(0);
+}
+
+/*
+ * mark wires that can effect target module expression widths in
+ * target module and if defparam contains mark as must split
+ * if not marked, then can use IS form 
+ */
+static void find_mustsplit_dfps(void)
+{
+ register struct dfparam_t *dfpp, *dfpp2;
+ struct mod_t *imdp;
+ struct net_t *np;
+ struct itree_t *bot_itp; 
+
+ for (dfpp = __dfphdr; dfpp != NULL; dfpp = dfpp->dfpnxt)
+  {
+   /* only look at non local master's from identicals here */ 
+   if (dfpp->dfp_local || dfpp->idntmastdfp != NULL) continue;
+
+   bot_itp = __find_dfpbot_itp(dfpp);
+   imdp = bot_itp->itip->imsym->el.emdp;
+   /* if only 1 inst. no need to split */
+   if (imdp->flatinum == 1) continue;
+
+   /* if target module does not have expr. width params set, do it now */
+   if (!imdp->mwiddetdone)
+    {
+     /* width marking must be done with module context */
+     __push_wrkitstk(imdp, 0);
+     __mark_widdet_params(imdp);
+     __pop_wrkitstk();
+     imdp->mwiddetdone = TRUE;
+    }
+
+   /* if any of list with identical target width determining must split */
+   /* identical target means identical module type */
+   /* dfpp included in ident list */
+   if (dfpp->dfp_has_idents)
+    {
+     for (dfpp2 = dfpp; dfpp2 != NULL; dfpp2 = dfpp2->idntnxt)
+      {
+       np = dfpp2->targsyp->el.enp;
+       if (np->nu.ct->n_widthdet)
+        {
+         /* DBG remove --- */
+         if (__debug_flg)
+          {
+           __dbg_msg(
+	    "+++ mark module %s to split defparam %s (mast of equiv class) width determining.\n",
+            imdp->msym->synam, np->nsym->synam);
+          }
+         /* --- */
+         /* SJM 03/21/04 - because all are in same destination inst */
+         /* equivalence class, once know that the master split can stop */
+         dfpp->dfp_mustsplit = TRUE;
+        }
+      }
+    }
+   else
+    {
+     np = dfpp->targsyp->el.enp;
+     if (np->nu.ct->n_widthdet)
+      {
+       /* DBG remove --- */
+       if (__debug_flg)
+        {
+         __dbg_msg(
+          "+++ mark module %s to split since defparam %s width determining.\n",
+          imdp->msym->synam, np->nsym->synam);
+        }
+       /* --- */
+       dfpp->dfp_mustsplit = TRUE;
+       /* AIV 02/04/04 - was wrongly breaking so did not process all defps */
+      }
+    }
+  }
+}
+
+/*
+ * find bottom defparam itree loc.
+ */
+extern struct itree_t *__find_dfpbot_itp(struct dfparam_t *dfpp)
+{
+ register int32 dfi, ii;
+ register struct itree_t *bot_itp, *itp;
+ 
+ ii = dfpp->dfpiis[0];
+ bot_itp = __it_roots[ii];
+ /* may not go through this loop if in top */
+ for (dfi = 1; dfi <= dfpp->last_dfpi; dfi++)
+  { ii = dfpp->dfpiis[dfi]; itp = &(bot_itp->in_its[ii]); bot_itp = itp; }
+ return(bot_itp);
+}
+
+/*
+ * ROUTINES TO SPLIT MODULES AND UNWIND DEFPARAMS
+ */
+
+/*
+ * do all defparam splitting off
+ * since all rooted just descend from root in itree change itree imsym
+ * types and copy modules where needed
+ */
+static void do_defparam_splitting(void)
+{
+ register int32 ii2, dfi;
+ int32 ii, last_split;
+ struct dfparam_t *dfpp;
+ struct inst_t *ip;
+ struct itree_t *itp, *up_itp;
+ struct mod_t *orig_imdp, *imdp, *down_inst_mod;
+
+ __defparam_splits = FALSE;
+ last_split = FALSE;
+ for (dfpp = __dfphdr; dfpp != NULL; dfpp = dfpp->dfpnxt)
+  {
+   /* if has identical (i.e. more than one param in same inst set), */
+   /* then build path for 1 and at end copy same path for all idents */
+   if (dfpp->dfp_local || dfpp->idntmastdfp != NULL) continue;
+
+   /* SJM 03/23/04 - if needed to split must rebuild itree because */
+   /* need to renumber the split off ones and the ones split from */ 
+   if (last_split)
+    {
+     __free_flat_itree();
+     __bld_flat_itree();
+     last_split = FALSE;
+    }
+
+   /* first split module containing defparam target if needed */
+   dfi = dfpp->last_dfpi;
+   itp = __find_dfpbot_itp(dfpp);
+   ip = itp->itip;
+   imdp = ip->imsym->el.emdp;
+
+   if (imdp->flatinum == 1)
+    {
+     /* DBG remove --- */
+     if (__debug_flg)
+      {
+       __dbg_msg("-- defparam %s mod %s not split - only 1 instance\n",
+        dfpp->gdfpnam, imdp->msym->synam);
+      }
+     /* --- */
+     continue;
+    }
+
+   /* if can just change to IS expr. form, do not split */
+   if (!dfpp->dfp_mustsplit)
+    {
+     /* DBG remove --- */
+     if (__debug_flg)
+      {
+       __dbg_msg(
+        "-- defparam %s mod %s not split - can change param to inst. form\n",
+        dfpp->gdfpnam, imdp->msym->synam);
+      }
+     /* --- */
+     continue;
+    }
+
+   /* always split off master (original) if needed */ 
+   if (imdp->mspltmst != NULL)
+    {
+     __gfwarn(535, dfpp->dfpfnam_ind, dfpp->dfplin_cnt,
+      "INTERNAL - bottom of tree module of type \"%s\" should not have master %s",
+      imdp->msym->synam, imdp->mspltmst->msym->synam);
+     orig_imdp = imdp->mspltmst;
+    }
+   else orig_imdp = imdp;
+
+   /* DBG remove ---
+   if (__debug_flg)
+    {
+     __dbg_msg("==> before split of bottom mod %s and before split up\n",
+      orig_imdp->msym->synam);
+     __dmp_itree(__it_roots[0]);
+    }
+   --- */
+
+   /* notice this set __inst_mod to new split off - each defaparam has */
+   /* own in module so this use of __inst_mod does not require saving */
+   /* LOOKATME - should not set __inst_mod inside but return value here */
+   __do_mdsplit(orig_imdp);
+   __defparam_splits = TRUE;
+   last_split = TRUE;
+
+   /* DBG remove ---
+   if (__debug_flg)
+    {
+     __dbg_msg("==> after split but before split up without adjust to %s\n",
+      __inst_mod->msym->synam);
+     __dmp_itree(__it_roots[0]);
+    }
+   --- */
+    
+   /* DBG remove --- */
+   if (__debug_flg)
+    {
+     __dbg_msg("-- split defparam(s) %s type %s to %s target symbol %s.\n",
+      dfpp->gdfpnam, orig_imdp->msym->synam, __inst_mod->msym->synam,
+      dfpp->targsyp->synam);
+    }
+   /* --- */
+   /* do not need to update non master defparam since will never see */ 
+
+   up_itp = itp->up_it;
+try_split_up:
+   /* notice that level i, ii is index in one up itree in_its */
+   ii = dfpp->dfpiis[dfi];
+   /* move 1 level up tree */
+   dfi--;
+   itp = up_itp;
+   imdp = itp->itip->imsym->el.emdp;
+   up_itp = up_itp->up_it;
+   /* previous copied module */
+   down_inst_mod = __inst_mod;
+
+    /* DBG remove --- 
+    if (__debug_flg)
+     {
+      __dbg_msg("==> at beginning of try split up\n");
+      __dmp_itree(__it_roots[0]);
+     }
+    --- */
+
+   /* either fix 1 itree level above module type or split if needed */
+
+   /* rule 1: if 1 up itree place inst_t module type has 1 flat inst, */
+   /* just change imsym */
+   /* top modules will always cause rule 1 termination */
+   /* if already split off (common), know exactly one inst., do not split */
+   if (imdp->flatinum == 1)
+    {
+     (imdp->minsts[ii]).imsym = down_inst_mod->msym;
+
+     /* DBG remove --- */
+     if (__debug_flg)
+      {
+       __dbg_msg("-- defparam %s module %s needs split but has 1 inst.\n",
+	dfpp->gdfpnam, imdp->msym->synam);
+      }
+     /* --- */
+     continue;
+    }
+   
+   /* rule 2: if module flatinum > 1, has contained inst_t split off */
+   /* must copy module and work up tree */
+   if (imdp->mspltmst != NULL) orig_imdp = imdp->mspltmst;
+   else orig_imdp = imdp;
+   /* notice here __inst_mod changed to newly split off, so works */
+   /* but use of __inst mod makes code hard to follow */
+   __do_mdsplit(orig_imdp);
+
+   /* DBG remove ---
+   if (__debug_flg)
+    {
+     __dbg_msg("==> after split - before itree fix up\n");
+     __dmp_itree(__it_roots[0]);
+    }
+   --- */
+
+   /* inside split off mod always change instances down module type */
+   (__inst_mod->minsts[ii]).imsym = down_inst_mod->msym;
+
+   /* since entire insts list in __inst_mod copy of list in original mod */
+   /* each itip inside non leaf top module must be changed to address of */
+   /* inst in split of __inst_mod */
+   /* notice must update because other defparams may descend through here */
+   for (ii2 = 0; ii2 < __inst_mod->minum; ii2++)
+    (itp->in_its[ii2]).itip = &(__inst_mod->minsts[ii2]);
+
+   /* --- DBG remove
+   if (__debug_flg)
+    {
+     __dbg_msg("==> after split - after itree fix up\n");
+     __dmp_itree(__it_roots[0]);
+    }
+   --- */
+
+   /* DBG remove --- */
+   if (__debug_flg)
+    {
+     __dbg_msg("-- defparam %s needing split mod %s split to %s\n",
+      dfpp->gdfpnam, orig_imdp->msym->synam, __inst_mod->msym->synam);
+    }
+   /* --- */
+   goto try_split_up;
+  }
+
+ /* SJM 03/23/04 - if last one needed to split must rebuild itree here */
+ if (last_split)
+  {
+   __free_flat_itree();
+   __bld_flat_itree();
+  }
+ /* DBG remove --- */
+ if (__debug_flg)
+  { for (ii2 = 0; ii2 < __numtopm; ii2++) __dmp_itree(__it_roots[ii2]); }
+ /* --- */
+}
+
+/*
+ * if any splitting must reset all target symbols 
+ * problem is that end instance of path may be split from other defparam
+ */
+static void reset_dfp_targsyps(void)
+{
+ register struct dfparam_t *dfpp, *dfpp2;
+
+ for (dfpp = __dfphdr; dfpp != NULL; dfpp = dfpp->dfpnxt)
+  {
+   /* since local always copied and no xmr path no reset needed */
+   if (dfpp->dfp_local || dfpp->idntmastdfp != NULL) continue;
+
+   if (!dfpp->dfp_has_idents) { reset_1dfp_targsyp(dfpp); continue; }
+
+   /* SJM 03/16/04 - LOOKATME - could just go through lists ignoring */
+   /* idntmastdfp */
+   /* master included on this list */
+   for (dfpp2 = dfpp; dfpp2 != NULL; dfpp2 = dfpp2->idntnxt)
+    reset_1dfp_targsyp(dfpp2);
+  }  
+}
+
+/*
+ * in case splitting of target module (maybe from elsewhere)
+ * reset target symbol
+ */
+static void reset_1dfp_targsyp(struct dfparam_t *dfpp)
+{
+ register struct task_t *tskp;
+ struct itree_t *itp;
+ struct mod_t *mdp;
+ struct sy_t *syp;
+ char *chp;
+
+ itp = __find_dfpbot_itp(dfpp);
+ mdp = itp->itip->imsym->el.emdp;
+ chp = dfpp->targsyp->synam;
+ if (dfpp->dfptskp != NULL)
+  {
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if (strcmp(tskp->tsksyp->synam, dfpp->dfptskp->tsksyp->synam) == 0)
+      goto have_task;
+    }
+   __arg_terr(__FILE__, __LINE__);
+   
+have_task:
+   if ((syp = __get_sym(chp, tskp->tsksymtab)) == NULL)
+    __arg_terr(__FILE__, __LINE__);
+   if (dfpp->targsyp != syp) 
+    {
+     /* DBG remove -- */
+     if (__debug_flg)  
+      {
+       __dbg_msg(
+        "++ for task defparam %s new bottom %s replacing %s with %s\n",
+        dfpp->gdfpnam, __msg2_blditree(__xs, itp), dfpp->targsyp->synam,
+        syp->synam);
+      }
+     /* ---*/
+     dfpp->targsyp = syp;
+     /* DBG remove --- */
+     if (__debug_flg)
+      {
+       struct net_t *np;
+
+       np = syp->el.enp; 
+       /* using first instance of original expression */
+       __dbg_msg("-+- assigning params for %s in %s at %p - expr:%s\n",
+        np->nsym->synam, mdp->msym->synam, np, __msgexpr_tostr(__xs,
+        np->nu.ct->n_dels_u.d1x));
+      }
+     /* --- */
+    }
+   return;
+  }
+ /* DBG remove -- */
+ if ((syp = __get_sym(chp, mdp->msymtab)) == NULL)
+  __arg_terr(__FILE__, __LINE__);
+ if (dfpp->targsyp != syp)
+  {
+   /* DBG remove -- */
+   if (__debug_flg)
+    {
+     __dbg_msg("++ for defparam %s new bottom %s replacing %s with %s\n",
+      dfpp->gdfpnam, __msg2_blditree(__xs, itp), dfpp->targsyp->synam,
+      syp->synam);
+    }
+   /* ---*/
+   dfpp->targsyp = syp;
+  }
+}
+
+/*
+ * ROUTINES TO BUILD AS IF FLATTENED INSTANCE TREE
+ */
+
+/*
+ * go through itree setting all inst fields to possible new split off value 
+ * split off module has same inst pointer (type different) but underneath
+ * instances can be completeley different no. (structure unchanged though)
+ */
+static void reassign_itnums(void)
+{
+ register int32 ii;
+ register struct mod_t *flmdp;
+ struct itree_t *itp; 
+
+ for (flmdp = __modhdr; flmdp != NULL; flmdp = flmdp->mnxt)
+  flmdp->lastinum = 0;
+ /* notice types of top level modules cannot change */
+ for (ii = 0; ii < __numtopm; ii++)
+  {
+   itp = __it_roots[ii];
+   flmdp = itp->itip->imsym->el.emdp;
+   itp->itinum = (flmdp->lastinum)++;
+   reassign2_itnums(itp);
+  }
+ /* ---
+ if (__debug_flg)
+  {
+   __dbg_msg("==> dumping itree with reset inst numbers\n"); 
+   for (ii = 0; ii < __numtopm; ii++) __dmp_itree(__it_roots[ii]);
+  }
+ --- */
+}
+
+/*
+ * non top level built itree for inst. of one module
+ *
+ * know up instance pointers point to allocated but not set itree nodes
+ * for each inst. in module one up
+ * try to make as breadth first as possible
+ */
+static void reassign2_itnums(struct itree_t *new_itp)
+{
+ register int32 ii;
+ struct itree_t *itp;
+ struct mod_t *imdp, *mdp;
+
+ imdp = new_itp->itip->imsym->el.emdp;
+ /* fill contained itree instance contents */ 
+ for (ii = 0; ii < imdp->minum; ii++)
+  {
+   /* alloc sets inst_t value */
+   itp = &(new_itp->in_its[ii]);
+   mdp = itp->itip->imsym->el.emdp;
+   itp->itinum = (mdp->lastinum)++;
+  }
+ /* finally down 1 level */
+ for (ii = 0; ii < imdp->minum; ii++)
+  reassign2_itnums(&(new_itp->in_its[ii]));
+}
+
+/*
+ * ROUTINES TO SET POUND AND DEFPARAMS 
+ */
+
+/*
+ * must set pound params by top down scan of itree
+ * rule is first set all pound params
+ */
+extern void __set_poundparams(void)
+{
+ register int32 ii;
+ struct itree_t *itp; 
+
+ for (ii = 0; ii < __numtopm; ii++)
+  {
+   /* since pound params change params one level down - none at top */
+   itp = __it_roots[ii];
+   set2_poundparams(itp);
+  }
+}
+
+/*
+ * set pound params
+ * try to make as breadth first as possible
+ */
+static void set2_poundparams(struct itree_t *up_itp)
+{
+ register int32 ii, ii2;
+ int32 giawid, is_giarr;
+ struct itree_t *itp;
+ struct inst_t *ip;
+ struct mod_t *up_mdp;
+ struct giarr_t *giap;
+
+ up_mdp = up_itp->itip->imsym->el.emdp;
+ giap = NULL;
+ giawid = 0;
+ for (ii = 0; ii < up_mdp->minum; ii++)
+  {
+   if (up_mdp->miarr != NULL && (giap = up_mdp->miarr[ii]) != NULL)
+    {
+     giawid = __get_giarr_wide(giap);
+     is_giarr = TRUE;
+    }
+   else is_giarr = FALSE;
+
+   /* if module no params or none set nil, if some set non nil but some */
+   /* locations will be nil instead of pointing to up pound param expr. */
+   itp = &(up_itp->in_its[ii]);
+   ip = itp->itip;
+
+   /* for giarr's in each expanded instance although since no generate */
+   /* all are the same */
+   if (is_giarr)
+    {
+     if (ip->ipxprtab != NULL)
+      {
+       for (ii2 = ii; ii2 < ii + giawid; ii2++)
+        {
+         itp = &(up_itp->in_its[ii2]);
+         __set_1inst_pound_params(itp, TRUE);
+        }
+      } 
+    }
+   else { if (ip->ipxprtab != NULL) __set_1inst_pound_params(itp, FALSE); }
+
+   /* skip all but first instance of instance array expanded */
+   /* works because know all must have same type */
+   /* for array of instances, need master ip in giarr */ 
+   if (is_giarr) { giawid = __get_giarr_wide(giap); ii += (giawid - 1); }
+  }
+ /* finally down 1 level */
+ for (ii = 0; ii < up_mdp->minum; ii++)
+  {
+   set2_poundparams(&(up_itp->in_its[ii]));
+
+   /* skip all but first instance of instance array expanded */
+   /* works because know all must have same type */
+   /* for array of instances, need master ip in giarr */ 
+   if (up_mdp->miarr != NULL && (giap = up_mdp->miarr[ii]) != NULL)
+    {
+     giawid = __get_giarr_wide(giap);
+     ii += (giawid - 1);
+    }
+  }
+}
+
+/*
+ * set the pound parameters for all of 1 instance down
+ *
+ * only called if instance has at least one pound param
+ * 
+ * for anything set here must evaluate to number because this is the next
+ * place in sort order but must leave as expr. because some other
+ * instances of IS form parameter may need to use default
+ */
+extern void __set_1inst_pound_params(struct itree_t *itp, int32 is_giarr) 
+{
+ register int32 pi;
+ struct expr_t *pxp;
+ struct mod_t *imdp;
+ struct inst_t *ip;
+ struct xstk_t *xsp;
+ struct net_t *modnp;
+ char s1[RECLEN];
+ 
+ /* top module can not be destination of pound params */
+ /* DBG remove --- */
+ if (itp->up_it == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ ip = itp->itip;
+ imdp = itp->itip->imsym->el.emdp; 
+ /* pound parameters are nets (param var typ) defined in module */
+ /* if # param list short ok, do not change last */
+ for (pi = 0; pi < imdp->mprmnum; pi++)
+  {
+   pxp = ip->ipxprtab[pi];
+   /* explicit form with this one unused or short list */
+   if (pxp == NULL) continue;
+
+   modnp = &(imdp->mprms[pi]);
+
+   /* SJM 01/26/05 - mistake because if param set by def param was marking */
+   /* add preventing recalc param rhs from using expr but must also set */
+   /* bit for pound param overrides */
+   modnp->nu.ct->p_setby_defpnd = TRUE;
+   
+   /* use whatever parm values in rhs are current to freeze rhs to num */
+   /* here is the source order point for pound param */
+   /* must evaluate in instantiating module but set in lower */ 
+   __push_itstk(itp->up_it);
+   xsp = __eval_xpr(pxp);
+   __pop_itstk();
+
+   /* know this is parameter */
+   /* if not already in IS form convert and make each inst. old expr. */
+   /* providing more than one inst. - 1st inst. set from # parm if >1 insts */
+   /* causes change to IS form */
+   if (modnp->srep == SR_PNUM)
+    {
+     /* special case, if part of inst array, never convert to IS form */
+     /* because each inst array its own type and all params must be same */
+     if (is_giarr)
+      {
+       sprintf(s1, "%s (pound param)", __msg2_blditree(__xs, itp));
+       __cnvt_param_stkval(xsp, pxp, modnp, s1);
+       __assgn_nonis_param(modnp, pxp, xsp);
+       goto chk_dbg; 
+      }
+
+     /* this will replicate initial value and change srep */
+     if (imdp->flatinum > 1 && !modnp->nu.ct->n_widthdet)
+       __chg_param_tois(modnp, imdp);
+     else
+      {
+       sprintf(s1, "%s (pound param)", __msg2_blditree(__xs, itp));
+       __cnvt_param_stkval(xsp, pxp, modnp, s1);
+       __assgn_nonis_param(modnp, pxp, xsp);
+       goto chk_dbg; 
+      }
+    }
+   /* IS param case (was or newly converted to IS) */
+   sprintf(s1, "%s (per instance pound param)", __msg2_blditree(__xs, itp));
+   __cnvt_param_stkval(xsp, pxp, modnp, s1);
+   assgn_is_param(modnp, xsp, pxp->has_sign,
+    itp->itip->imsym->el.emdp->flatinum, itp->itinum);
+
+   /* update paramter value but leave original expr. - needed if user */
+   /* wants different parameter assign algorithm */
+
+   /* should dump parameter size info here */
+chk_dbg:
+   if (__debug_flg)
+    {
+     __push_itstk(itp);
+     __dbg_msg(
+      "+++ setting # param %s to %s in module %s (%d insts) from inst. %s\n",
+      modnp->nsym->synam, __pregab_tostr(__xs, xsp->ap, xsp->bp, modnp),
+      imdp->msym->synam, imdp->flatinum, ip->isym->synam);
+     __pop_itstk();
+    }
+   __pop_xstk();
+  }
+}
+
+/*
+ * assign new value to non IS parameter
+ */
+extern void __assgn_nonis_param(struct net_t *np, struct expr_t *xrhs,
+ struct xstk_t *xsp)
+{
+ int32 owlen, nwlen;
+
+ owlen = wlen_(np->nwid);
+ nwlen = wlen_(xsp->xslen);
+ /* if param real because declared or inital RHS real know xsp converted */
+ /* so just assign */
+ if (np->ntyp == N_REAL)
+  {
+   memcpy(np->nva.wp, xsp->ap, 2*owlen*WRDBYTES); 
+   return;
+  }
+ __my_free((char *) np->nva.wp, 2*WRDBYTES*owlen);
+ np->nva.wp = (word32 *) __my_malloc(2*WRDBYTES*nwlen);
+ memcpy(np->nva.wp, xsp->ap, 2*nwlen*WRDBYTES); 
+
+ /* change param width if needed */
+ if (xsp->xslen != np->nwid)
+  {
+   np->nwid = xsp->xslen;
+   if (np->nu.ct->nx1 != NULL) __free_xtree(np->nu.ct->nx1);
+   if (np->nu.ct->nx2 != NULL) __free_xtree(np->nu.ct->nx2);
+   if (np->nwid == 1)
+    {
+     np->n_isavec = FALSE;
+     np->nu.ct->nx1 = np->nu.ct->nx2 = NULL;
+    }
+   else
+    {
+     np->nu.ct->nx1 = __bld_rng_numxpr((word32) (np->nwid - 1), 0L, WBITS);
+     np->nu.ct->nx2 = __bld_rng_numxpr(0L, 0L, WBITS);
+     np->n_isavec = TRUE;
+    }
+  }
+
+ /* also use rhs constant value if string/non string */
+ if (xrhs->is_string) np->nu.ct->pstring = TRUE;
+ else { np->nu.ct->pstring = FALSE; np->nu.ct->pbase = BDEC; } 
+}
+
+/*
+ * assign new value to IS parameter
+ */
+static void assgn_is_param(struct net_t *np, struct xstk_t *xsp,
+ int32 rhs_sign, int32 ninsts, int32 iti)
+{
+ register int32 ii;
+ int32 owlen, nwlen;
+ word32 *wp, *wp2, *wp3, *wp4; 
+
+ owlen = wlen_(np->nwid);
+ nwlen = wlen_(xsp->xslen);
+ /* if param real because declared or inital RHS real know xsp converted */
+ /* just assign to right inst. loc */
+ if (np->ntyp == N_REAL)
+  {
+   wp = &(np->nva.wp[2*owlen*iti]);
+   memcpy(wp, xsp->ap, 2*owlen*WRDBYTES); 
+   return;
+  }
+
+ /* if new value wider must free and realloc so all wider */
+ /* also change new width - this is tricky case */ 
+ if (xsp->xslen > np->nwid)
+  {
+   /* save old area */ 
+   wp2 = np->nva.wp;
+   /* allocate new area of new wider size */
+   np->nva.wp = (word32 *) __my_malloc(2*ninsts*WRDBYTES*nwlen);
+   /* point to new area */
+   wp = np->nva.wp;
+   for (ii = 0; ii < ninsts; ii++)
+    {
+     /* right inst. area of old value */
+     wp3 = &(wp2[2*owlen*ii]);
+     /* right inst of new area */
+     wp4 = &(wp[2*nwlen*ii]);
+     /* since widening must zero first */
+     zero_allbits_(wp4, xsp->xslen);
+     zero_allbits_(&(wp4[nwlen]), xsp->xslen);
+     /* copy in to first arg - high bits 0 */
+     cp_walign_(wp4, wp3, np->nwid);
+     cp_walign_(&(wp4[nwlen]), &(wp3[owlen]), np->nwid);
+    }
+
+   /* finally free old */
+   __my_free((char *) wp2, 2*ninsts*WRDBYTES*owlen);
+   /* only widening case */
+   np->nwid = xsp->xslen;
+
+   /* need to change range */
+   if (np->nu.ct->nx1 != NULL) __free_xtree(np->nu.ct->nx1);
+   if (np->nu.ct->nx2 != NULL) __free_xtree(np->nu.ct->nx2);
+   np->nu.ct->nx1 = __bld_rng_numxpr((word32) (np->nwid - 1), 0L, WBITS);
+   np->nu.ct->nx2 = __bld_rng_numxpr(0L, 0L, WBITS);
+   np->n_isavec = TRUE;
+
+   /* adjust old word32 len since now widened */
+   owlen = wlen_(np->nwid);
+  }
+ else
+  {
+   /* if new narrower, widen */
+   /* use net's signedness since if param declared sign will be on in net */
+   if (xsp->xslen < np->nwid)
+    {
+     /* SJM 05/13/04 - rhs expr signedness determines if sign extend needed */ 
+     /* was wrongly using lhs */
+     if (rhs_sign) __sgn_xtnd_widen(xsp, np->nwid);
+     else __sizchgxs(xsp, np->nwid);
+    }
+  }
+
+ /* finally change this inst one */
+ wp = &(np->nva.wp[2*owlen*iti]);
+ memcpy(wp, xsp->ap, 2*owlen*WRDBYTES); 
+ /* here must not change param properties except width */
+}
+
+/*
+ * routine to replace all instances of original expression from
+ * local defparam
+ *
+ * needed so vpi_ access of rhs expr gets right one from pound/defparam
+ * not originale source
+ */
+static void replace_param_rhs_expr(struct net_t *np, word32 *wp,
+ struct mod_t *imdp)
+{
+ int32 wlen;
+ double d1;
+ struct expr_t *xp;
+
+ /* free expr table and convert back if already IS form */
+ if (np->nu.ct->parm_srep == SR_PISXPR)
+  {
+   __my_free((char *) np->nu.ct->n_dels_u.d4x,
+    imdp->flatinum*sizeof(struct expr_t *));
+   np->nu.ct->parm_srep = SR_PXPR;
+  }
+ xp = __alloc_newxnd();
+ wlen = wlen_(np->nwid);
+
+ if (np->ntyp == N_REAL)
+  {
+   xp->optyp = REALNUM;
+   xp->is_real = TRUE;
+   /* SJM 03/25/02 - still need width - since no x part WBITS */
+   xp->szu.xclen = WBITS;
+   xp->ibase = np->nu.ct->pbase;
+
+   memcpy(&d1, wp, sizeof(double)); 
+   xp->ru.xvi = __alloc_shareable_rlcval(d1);
+   np->nu.ct->n_dels_u.d1x = xp;
+   return;
+  }
+
+ if (np->nwid <= WBITS)
+  {
+   xp->ru.xvi = __alloc_shareable_cval(wp[0], wp[1], np->nwid);
+  }
+ else
+  {
+   xp->ru.xvi = __allocfill_cval_new(wp, &(wp[2*wlen]), wlen);
+  }
+
+ xp->optyp = NUMBER;
+ xp->ibase = np->nu.ct->pbase;
+ if (np->nu.ct->pstring) xp->is_string = TRUE;
+ if (np->n_signed) xp->has_sign = TRUE;
+
+ np->nu.ct->n_dels_u.d1x = xp;
+}
+
+/*
+ * set 1 defparam - know all splitting done 
+ *
+ * notice there be a slight memory leak here since old expression
+ * value of parameter is not freed but no longer accessible from here
+ * do not know if accessible form other place because no copy when
+ * convert to IS form just have each point to the one expr.
+ * 
+ * know all defparams converted to rooted by here - never specparams here
+ */
+static void set_1defparam(struct dfparam_t *dfpp)
+{
+ int32 wlen;
+ struct dfparam_t *mast_dfpp; 
+ struct expr_t *lhsndp;
+ struct net_t *np;
+ struct xstk_t *xsp;
+ struct mod_t *imdp;
+ struct itree_t *itp;
+ char s1[RECLEN];
+
+ __sfnam_ind = dfpp->dfpfnam_ind;
+ __slin_cnt = dfpp->dfplin_cnt;
+
+ if (dfpp->idntmastdfp != NULL) mast_dfpp = dfpp->idntmastdfp; 
+ else mast_dfpp = dfpp;
+
+ /* first step evaluate to make sure rhs is constant needs to be done */
+ /* here since source order and if leave param on rhs further defparam */
+ /* may change which invalidates source order */
+ if (dfpp->dfp_local)
+  {
+   imdp = dfpp->in_mdp;
+   __push_wrkitstk(imdp, 0);
+   xsp = __eval_xpr(dfpp->dfpxrhs);
+   __pop_wrkitstk();
+  }
+ else
+  {
+   /* SJM 04/24/05 - fix minor bug this must eval in actual defined in itree */
+   /* loc not the master's - LOOKATME - is master needed here? */
+   itp = __find_dfpbot_itp(dfpp);
+   __push_itstk(itp);
+   imdp = itp->itip->imsym->el.emdp;
+   xsp = __eval_xpr(dfpp->dfpxrhs);
+   __pop_itstk();
+  }
+
+ /* only possibilities here are ident or global ident */
+ lhsndp = dfpp->dfpxlhs;
+
+ /* key is that this np must be np in target split off module */
+ /* and know will be SYM N */
+ if (lhsndp->optyp == ID) np = lhsndp->lu.sy->el.enp;
+ else np = dfpp->targsyp->el.enp;
+ /* SJM 02/28/04 - added flag since must know set by defparam for recalc */
+ np->nu.ct->p_setby_defpnd = TRUE;
+ wlen = wlen_(np->nwid);
+
+ /* DBG remove -- */
+ if (!np->n_isaparam || np->nu.ct->p_specparam)
+  __arg_terr(__FILE__, __LINE__);
+ /* -- */
+
+ /* always convert parameter value to declared parameter */
+ sprintf(s1, "defparam in %s at %s", imdp->msym->synam,
+  __bld_lineloc(__xs, __sfnam_ind, __slin_cnt));
+ __cnvt_param_stkval(xsp, dfpp->dfpxrhs, np, s1);
+
+ /* if local applies to all instances and mast dfpp same */
+ if (dfpp->dfp_local)
+  {
+   imdp = dfpp->in_mdp;
+   /* since must be source order, change back from instance specific */
+   if (np->srep == SR_PISNUM)
+    {
+     __my_free((char *) np->nva.wp, imdp->flatinum*2*WRDBYTES*wlen);
+     np->srep = SR_PNUM;
+     np->nva.wp = (word32 *) __my_malloc(2*WRDBYTES*wlen);
+    }
+   memcpy(np->nva.wp, xsp->ap, 2*WRDBYTES*wlen);
+
+   /* change so original expression for all instances using new local */
+   /* defparam evaluated rhs numeric expr. */
+   /* makes vpi get value form parameter in vpi_ work */
+   /* this may allocate expr nodes so need mod - although expr not needed */
+   /* at run time */
+   __push_wrkitstk(imdp, 0);
+   replace_param_rhs_expr(np, xsp->ap, imdp);
+   __pop_wrkitstk();
+  }  
+ else 
+  {
+   /* set the target itree place - use master if part of identical group */
+   itp = __find_dfpbot_itp(mast_dfpp);
+   imdp = itp->itip->imsym->el.emdp;
+   /* change to IS NUM form only if more than 1 inst. of module */
+   if (np->srep == SR_PNUM && imdp->flatinum > 1) __chg_param_tois(np, imdp);
+
+   /* 06/06/00 - SJM - can't copy must use param assign routines */
+   /* can be either IS or non IS form */ 
+   if (np->srep == SR_PISNUM)
+    { 
+     assgn_is_param(np, xsp, dfpp->dfpxrhs->has_sign, imdp->flatinum,
+      itp->itinum);
+    }
+   else __assgn_nonis_param(np, dfpp->dfpxrhs, xsp);
+
+   /* leave original expr. - only value of lhs parameter changes */
+   /* allows using algorithm for assigning defparams */
+  }
+ /* DBG remove --- */
+ if (__debug_flg)
+  {
+   __dbg_msg("+++ setting defparam %s path %s to %s in module %s\n",
+    np->nsym->synam, dfpp->gdfpnam, __pregab_tostr(__xs, xsp->ap, xsp->bp, np),
+    imdp->msym->synam);
+  }
+ /* --- */
+ __pop_xstk();
+}
+
+/*
+ * for new parameter assignment algorithm - convert to declared or  
+ * implicit from rhs declared type and width
+ *
+ * this converts to type and size of param - new algorithm assumes
+ * that parameters are somehow declared (possibly from initial rhs expr)
+ */
+extern void __cnvt_param_stkval(struct xstk_t *xsp, struct expr_t *xrhs,
+ struct net_t *np, char *innam)
+{
+ char s1[RECLEN];
+
+ /* DBG remove -- */
+ if (!np->n_isaparam) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* case 1: declared or initial real - convert to real */
+ if (np->ntyp == N_REAL)
+  { 
+   if (!xrhs->is_real)
+    {
+     if (xrhs->szu.xclen == WBITS && xrhs->has_sign) strcpy(s1, "integer");
+     else sprintf(s1, "%d bit register", xrhs->szu.xclen);
+     __gfinform(486, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+      "parameter %s in %s assign required conversion from %s to real",
+      np->nsym->synam, innam, s1); 
+
+     __cnv_stk_fromreg_toreal(xsp, (xrhs->has_sign == 1));
+    }
+  }
+ else 
+  { 
+   /* know param is non real */ 
+   if (xrhs->is_real)
+    {
+     if (np->nwid == WBITS && np->n_signed) strcpy(s1, "integer");
+     else sprintf(s1, "%d bit register", np->nwid);
+
+     __gfinform(487, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+      "parameter %s in %s assign required conversion from real to %s",
+      np->nsym->synam, innam, s1); 
+
+     __cnv_stk_fromreal_toreg32(xsp);
+    }
+   /* but it may have wrong width - in new algorithm param assigns */
+   if (xsp->xslen != xrhs->szu.xclen)
+    {
+     __gfinform(488, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+      "parameter %s in %s assign width mismatch was %d new %d - widest used",
+      np->nsym->synam, innam, xsp->xslen, np->nwid); 
+
+     /* SJM 05/24/00 - now never narrow always use widest */
+     /* SJM 09/29/03 - change to handle sign extension and separate types */
+     /* never narrow */
+     if (xsp->xslen < np->nwid)
+      {
+       if (xrhs->has_sign) __sgn_xtnd_widen(xsp, np->nwid);
+       else __sizchg_widen(xsp, np->nwid);
+      }
+    }
+  }
+}
+
+/*
+ * recalculate all parameters with other params on rhs 
+ * needed in case rhs params, changed from def or pound setting
+ * 
+ * SJM 02/28/04 - fixes bug not match LRM when pound/def set rhs expr param
+ * LOOKATME - handling all cases although think some impossible
+ *
+ * LOOKATME - algorithm uses whatever net type is although strictly
+ * speaking conversion when no explicit width/type given in param decl
+ * could be needed - if change - then previous syntax checking invalidated
+ */
+extern void __recalc_param_vals(void)
+{
+ register struct mod_t *mdp;
+ int32 mlevel, chged, all_done;
+
+ for (;;)
+  {
+   all_done = TRUE;
+   chged = FALSE;
+
+   /* SJM 03/16/04 - if static (source content) mod level d.s. changed */ 
+   /* from splitting of pound params levelized lists updated dynamically */
+   /* and if from def params will have been rebuilt */ 
+   for (mlevel = __dagmaxdist; mlevel >= 0; mlevel--)
+    {
+     for (mdp = __mdlevhdr[mlevel]; mdp != NULL; mdp = mdp->mlevnxt)
+      {
+       if (mdp->mod_parms_gd) continue;
+
+       all_done = FALSE;
+       if (!all_parent_mods_recalced(mdp)) continue;
+       chged = TRUE;
+
+       /* if no params mark as done */ 
+       if (mdp->mprmnum == 0)
+        {
+         mdp->mod_parms_gd = TRUE;
+         continue;
+        }
+       /* LOOKATME - always recalculate since can't detect if recalced */
+       /* if no instance have pound params, does no extra checking */
+       /* but can't call if top mod */  
+       if (mdp->minstnum != 0) recalc_1mod_pndparams(mdp);
+
+       /* after any pound param recalc done, can set params to final vals */
+       recalc_1mod_params(mdp);
+
+       /* now all parameters in this module set to good final value */
+       mdp->mod_parms_gd = TRUE;
+      }
+    }
+   if (all_done) break;
+   /* if pass with no progress, internal error */
+   if (!chged) __misc_terr(__FILE__, __LINE__);
+  }
+}
+
+/*
+ * recalc all params for one module
+ *
+ * know all parameters set by pound and/or def params have right value
+ */
+static void recalc_1mod_params(struct mod_t *mdp)
+{
+ register int32 pi, ii;
+ int32 wlen;
+ word32 *wp;
+ struct net_t *np;
+ struct xstk_t *xsp;
+ struct expr_t *xp, **xtab;
+
+ for (pi = 0; pi < mdp->mprmnum; pi++)
+  {
+   np = &(mdp->mprms[pi]);
+
+   /* if rhs does not contain any parameter, or parameter set by defparam */
+   /* that removes the rhs expr, no need to recalculate */      
+   /* SJM 03/01/04 - if rhs set by defparam also can't recalc */  
+   if (!np->nu.ct->p_rhs_has_param || np->nu.ct->p_setby_defpnd) continue;
+
+   wlen = wlen_(np->nwid);
+   /* case 1: param representation IS expr form */
+   if (np->nu.ct->parm_srep == SR_PISXPR)
+    {
+     if (np->srep == SR_PNUM)
+      {
+       /* change to is num - not sure if can happen */
+       __my_free((char *) np->nva.wp, 2*WRDBYTES*wlen);
+       np->srep = SR_PISNUM;
+       np->nva.wp = (word32 *) __my_malloc(2*WRDBYTES*wlen*mdp->flatinum);
+      }
+     else if (np->srep != SR_PISNUM) __case_terr(__FILE__, __LINE__);
+     /* eval expr for every inst */
+     xtab = np->nu.ct->n_dels_u.d4x;
+     for (ii = 0; ii < mdp->flatinum; ii++)
+      {
+       __push_itstk(mdp->moditps[ii]);
+       xp = xtab[ii];
+       xsp = __eval_xpr(xp);
+
+       /* SJM 04/09/02 - need to also convert to/from real to match net */
+       if (xp->is_real && np->ntyp != N_REAL)
+        {
+         __cnv_stk_fromreal_toreg32(xsp);
+         if (np->nwid != xsp->xslen) __sizchgxs(xsp, np->nwid);
+        } 
+       else if (!xp->is_real && np->ntyp == N_REAL)
+        { 
+         __cnv_stk_fromreg_toreal(xsp, (xp->is_real == 1));
+        }
+       else if (np->nwid != xsp->xslen) __sizchgxs(xsp, np->nwid);
+
+       wp = &(np->nva.wp[ii*2*wlen]);
+       memcpy(wp, xsp->ap, 2*wlen*WRDBYTES);
+       __pop_xstk();
+       __pop_itstk();
+      }
+     continue;
+    }
+   if (np->nu.ct->parm_srep == SR_PXPR)
+    {
+     /* case 2: rhs expr non IS */
+     if (np->srep == SR_PNUM)
+      { 
+       xp = np->nu.ct->n_dels_u.d1x;
+       /* if any IS PNUM params on rhs, must also chg this to IS */
+       if (xpr_has_is_param(xp))
+        {
+         __my_free((char *) np->nva.wp, 2*WRDBYTES*wlen);
+         np->srep = SR_PISNUM;
+         np->nva.wp = (word32 *)
+         __my_malloc(2*WRDBYTES*wlen*mdp->flatinum);
+         set_parmval_from_isxpr(np, xp, mdp);
+         continue;
+        }
+       /* case 2a: both non IS - any inst context works */
+       __push_itstk(mdp->moditps[0]);
+       xsp = __eval_xpr(xp);
+       /* SJM 04/09/02 - need to also convert to/from real to match net */
+       if (xp->is_real && np->ntyp != N_REAL)
+        {
+         __cnv_stk_fromreal_toreg32(xsp);
+         if (np->nwid != xsp->xslen) __sizchgxs(xsp, np->nwid);
+        } 
+       else if (!xp->is_real && np->ntyp == N_REAL)
+        { 
+         __cnv_stk_fromreg_toreal(xsp, (xp->is_real == 1));
+        }
+       else if (np->nwid != xsp->xslen) __sizchgxs(xsp, np->nwid);
+
+       wp = np->nva.wp;
+       memcpy(wp, xsp->ap, 2*wlen*WRDBYTES);
+       __pop_xstk();
+       __pop_itstk();
+       continue;
+      }
+     if (np->srep == SR_PISNUM)
+      {
+       /* SJM 04/09/02 - LOOKATME - can this case ever happen? */
+       /* case 2b: param value IS but only one expr non IS) */
+       /* only one value - can use any itree loc to eval */
+       xp = np->nu.ct->n_dels_u.d1x;
+
+       /* case 2a: both non IS - any inst context works */
+       __push_itstk(mdp->moditps[0]);
+       xsp = __eval_xpr(xp);
+       /* SJM 04/09/02 - need to also convert to/from real to match net */
+       if (xp->is_real && np->ntyp != N_REAL)
+        {
+         __cnv_stk_fromreal_toreg32(xsp);
+         if (np->nwid != xsp->xslen) __sizchgxs(xsp, np->nwid);
+        } 
+       else if (!xp->is_real && np->ntyp == N_REAL)
+        { 
+         __cnv_stk_fromreg_toreal(xsp, (xp->is_real == 1));
+        }
+       else if (np->nwid != xsp->xslen) __sizchgxs(xsp, np->nwid);
+       __pop_itstk();
+
+       /* set same value for each */
+       for (ii = 0; ii < mdp->flatinum; ii++)
+        {
+         wp = &(np->nva.wp[ii*2*wlen]);
+         memcpy(wp, xsp->ap, 2*wlen*WRDBYTES);
+        }
+       __pop_xstk();
+       continue;
+      }
+     __case_terr(__FILE__, __LINE__);
+    }
+   /* if this param changed by pound/def, bit may be on but now number */
+  }
+}
+
+/*
+ * recalculate all pound that are set by instances instantiating this mod
+ *
+ * new pound params calculation never requires - to IS or size/type change
+ */
+static void recalc_1mod_pndparams(struct mod_t *mdp)
+{
+ register int32 ii, pi;
+ int32 wlen;
+ word32 *wp;
+ struct itree_t *itp, *up_itp;
+ struct inst_t *ip;
+ struct net_t *np; 
+ struct expr_t *pxp;
+ struct xstk_t *xsp;
+
+ for (ii = 0; ii < mdp->flatinum; ii++)
+  {
+   itp = mdp->moditps[ii];
+   ip = itp->itip;
+   if (ip->ipxprtab == NULL) continue;
+
+   if (itp->up_it == NULL) __misc_terr(__FILE__, __LINE__);
+   up_itp = itp->up_it;
+   /* if not pound params for this containing inst, nothing to do */
+
+   /* must push since converts need down mod itree loc */
+   __push_itstk(itp);
+   for (pi = 0; pi < mdp->mprmnum; pi++)
+    {
+     np = &(mdp->mprms[pi]);
+
+     pxp = ip->ipxprtab[pi];
+     /* explicit form with this one unused or short list */
+     if (pxp == NULL) continue;
+     /* if pound param high conn expr does not contain param, nothing to do */ 
+     /* SJM 03/01/04 - if rhs set by defparam can't recalc */  
+     if (!__xpr_has_param(pxp) || np->nu.ct->p_setby_defpnd)
+      continue;
+
+     /* eval in up and know then any parameters used in expr */
+     __push_itstk(up_itp);
+     xsp = __eval_xpr(pxp);
+     __pop_itstk();
+
+     /* SJM 04/09/02 - need to also convert to/from real to match net */
+     if (pxp->is_real && np->ntyp != N_REAL)
+      {
+       __cnv_stk_fromreal_toreg32(xsp);
+       if (np->nwid != xsp->xslen) __sizchgxs(xsp, np->nwid);
+      } 
+     else if (!pxp->is_real && np->ntyp == N_REAL)
+      { 
+       __cnv_stk_fromreg_toreal(xsp, (pxp->is_real == 1));
+      }
+     else if (np->nwid != xsp->xslen) __sizchgxs(xsp, np->nwid);
+
+     /* if parameter set by pound param, it must be IS */
+     wlen = wlen_(np->nwid);
+     if (np->srep == SR_PNUM)
+      {
+       /* SJM 03/01/04 - non IS form ok here for array of insts case */
+       /* ??? if (mdp->flatinum > 1) __misc_terr(__FILE__, __LINE__); */
+       memcpy(np->nva.wp, xsp->ap, 2*wlen*WRDBYTES);
+      }
+     else if (np->srep == SR_PISNUM)
+      {
+       wp = &(np->nva.wp[ii*2*wlen]);
+       memcpy(wp, xsp->ap, 2*wlen*WRDBYTES);
+      }
+     __pop_xstk();
+    }
+   __pop_itstk();
+  }
+}
+
+/*
+ * return T if parameter rhs expr contains IS rep param
+ */
+static int32 xpr_has_is_param(struct expr_t *ndp)
+{
+ struct sy_t *syp;
+ struct net_t *np;
+ struct expr_t *fandp;
+
+ switch ((byte) ndp->optyp) { 
+  case NUMBER: case REALNUM: case ISNUMBER: case ISREALNUM: return(FALSE);
+  case ID:
+   syp = ndp->lu.sy;
+   if (!syp->sydecl || syp->sytyp != SYM_N) return(FALSE);
+   np = syp->el.enp; 
+   if (np->n_isaparam && np->srep == SR_PISNUM) return(TRUE);
+   return(FALSE);
+  case GLBREF: return(FALSE);
+  case FCALL:
+   for (fandp = ndp->ru.x; fandp != NULL; fandp = fandp->ru.x)
+    {
+     /* LOOKATME - even if real param not allowed arg to const systf */
+     /* can be real */
+     if (xpr_has_is_param(fandp->lu.x)) return(TRUE);
+    }
+   return(FALSE);
+ } 
+ if (ndp->lu.x != NULL) if (xpr_has_is_param(ndp->lu.x)) return(TRUE);
+ if (ndp->ru.x != NULL) if (xpr_has_is_param(ndp->ru.x)) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * return T all paramters known in modules that use pound params to set
+ * params in this module 
+ *
+ */
+static int32 all_parent_mods_recalced(struct mod_t *mdp)
+{
+ register int32 ii;
+ struct itree_t *itp;
+
+ /* if mod has no params trivially true */
+ if (mdp->mprmnum == 0) return(TRUE);
+ /* if top mod, obviously T */ 
+ if (mdp->minstnum == 0) return(TRUE);
+
+ for (ii = 0; ii < mdp->flatinum; ii++)
+  {
+   itp = mdp->moditps[ii];
+   /* DBG remove -- */
+   if (itp->up_it == NULL) __misc_terr(__FILE__, __LINE__);
+   /* -- */
+   if (!itp->up_it->itip->imsym->el.emdp->mod_parms_gd) return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * set param value (nva) for P IS NUM net from one expr 
+ */
+static void set_parmval_from_isxpr(struct net_t *np, struct expr_t *xp,
+ struct mod_t *mdp)
+{
+ register int32 ii;
+ int32 wlen;
+ word32 *wp;
+ struct xstk_t *xsp;
+
+ wlen = wlen_(np->nwid);
+ for (ii = 0; ii < mdp->flatinum; ii++)
+  {
+   __push_itstk(mdp->moditps[ii]);
+   /* need to re-eval for every inst */
+   xsp = __eval_xpr(xp);
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp->xslen > np->nwid) __narrow_sizchg(xsp, np->nwid);
+   else if (xsp->xslen < np->nwid)
+    {
+     if (xp->has_sign) __sgn_xtnd_widen(xsp, np->nwid);
+     else __sizchg_widen(xsp, np->nwid);
+    }
+
+   wp = &(np->nva.wp[ii*2*wlen]);
+   memcpy(wp, xsp->ap, 2*wlen*WRDBYTES);
+   __pop_xstk();
+   __pop_itstk();
+  }
+}
+
+/*
+ * ROUTINES TO FIND PORT CONNECTED AS INOUTS AND CHG DIR OR EMIT WARN
+ */
+
+/*
+ * routine to set driver bits for nets
+ * if driven by internal instance output port up drvr, set iconn driver bit
+ * if driven by module input port down drvr, set mdprt driver bit 
+ * for all other drivers set inmod driver bit
+ *
+ * SJM 05/23/01 - now using per bit algorithm because otherwise can't
+ * detect shorted ports or 2nd iconn that is wrong direction driver
+ */
+extern void __set_drvr_bits(void)
+{
+ register int32 pi, ii, gi;
+ register struct mod_pin_t *mpp;
+ int32 ptyp, pnum;
+ struct inst_t *ip;
+ struct mod_t *mdp, *imdp;
+ struct gate_t *gp;
+ struct conta_t *cap;
+ struct expr_t *xp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   /* first process all instances in module to set the high conn iconns */
+   for (ii = 0; ii < mdp->minum; ii++)
+    {
+     ip = &(mdp->minsts[ii]);
+     imdp = ip->imsym->el.emdp;
+     if ((pnum = imdp->mpnum) == 0) continue;
+
+     for (pi = 0; pi < pnum; pi++)
+      {
+       mpp = &(imdp->mpins[pi]);
+       xp = ip->ipins[pi];
+       ptyp = mpp->mptyp;
+
+       /* for inout always marks high conn tran drvr */
+       if (ptyp == IO_BID) set_lhs_expr_drvrtyp(xp, DRVR_NON_PORT,
+        ip->isym->syfnam_ind, ip->isym->sylin_cnt);
+       else if (ptyp == IO_OUT) set_lhs_expr_drvrtyp(xp, DRVR_ICONN,
+        ip->isym->syfnam_ind, ip->isym->sylin_cnt);
+      }
+    }
+
+   /* next gates including udps */
+   for (gi = 0; gi < mdp->mgnum; gi++)
+    {
+     /* if this is array of gates, will cause direction chg to inout */
+     /* SJM 05/23/01 - FIXME - should unwind these and not change */
+     gp = &(mdp->mgates[gi]);
+     switch ((byte) gp->g_class) {
+      case GC_PULL:
+       /* one gate all drivers can have multiple pins */
+       for (pi = 0; pi < (int32) gp->gpnum; pi++)
+        {
+         xp = gp->gpins[pi];
+         /* pull will force change to inoutk so tran type */
+         set_lhs_expr_drvrtyp(xp, DRVR_NON_PORT, gp->gsym->syfnam_ind,
+          gp->gsym->sylin_cnt);
+        }
+       break;
+      case GC_TRAN: 
+       /* both terminals of tran, need drvr field set */
+       set_lhs_expr_drvrtyp(gp->gpins[0], DRVR_NON_PORT, gp->gsym->syfnam_ind,
+        gp->gsym->sylin_cnt);
+       set_lhs_expr_drvrtyp(gp->gpins[1], DRVR_NON_PORT, gp->gsym->syfnam_ind,
+        gp->gsym->sylin_cnt);
+       break;
+      case GC_TRANIF:
+       /* first two  terminals of tranif, need drvr field set */
+       set_lhs_expr_drvrtyp(gp->gpins[0], DRVR_NON_PORT, gp->gsym->syfnam_ind,
+        gp->gsym->sylin_cnt);
+       set_lhs_expr_drvrtyp(gp->gpins[1], DRVR_NON_PORT, gp->gsym->syfnam_ind,
+        gp->gsym->sylin_cnt);
+       break;
+      default:
+       /* for gate/udp, unless output unc. set drv type field in conn net */
+       /* if output unc. (OPEMPTY), chges are not seen (do not propagate) */
+       if (gp->gpins[0]->optyp == OPEMPTY) continue;
+       set_lhs_expr_drvrtyp(gp->gpins[0], DRVR_NON_PORT, gp->gsym->syfnam_ind,
+        gp->gsym->sylin_cnt);
+     }
+    }
+   for (cap = mdp->mcas; cap != NULL; cap = cap->pbcau.canxt)
+    {
+     set_lhs_expr_drvrtyp(cap->lhsx, DRVR_NON_PORT, cap->casym->syfnam_ind,
+      cap->casym->sylin_cnt);
+    }
+
+   /* LOOKATME - for top level module ports, still setting */
+   /* module ports (low conns) */
+   pnum = mdp->mpnum;
+   for (pi = 0; pi < pnum; pi++)
+    {
+     mpp = &(mdp->mpins[pi]);
+     xp = mpp->mpref;
+     ptyp = mpp->mptyp;
+     /* for inout always marks low conn tran drvr */
+     if (ptyp == IO_BID) set_lhs_expr_drvrtyp(xp, DRVR_NON_PORT,
+      mpp->mpfnam_ind, mpp->mplin_cnt);
+     else if (ptyp == IO_IN) set_lhs_expr_drvrtyp(xp, DRVR_MDPRT,
+      mpp->mpfnam_ind, mpp->mplin_cnt);
+    }
+   __pop_wrkitstk();
+  }
+ /* FIXME - not using tf_ drivers to change module port direction */
+ /* think this is right since not really structural drivers" */ 
+}
+
+/*
+ * set lhs lvalue expr driver bits (i.e. know will be lvalue expr)
+ */
+static void set_lhs_expr_drvrtyp(struct expr_t *xp, int32 drvr_typ, int32 fnind,
+ int32 flcnt)
+{
+ int32 ri1, ri2;
+ struct net_t *np;
+ struct expr_t *idndp, *catxp;
+
+ ri1 = ri2 = -1;
+ switch ((byte) xp->optyp) {
+  case ID: case GLBREF:
+   if (xp->lu.sy->sytyp != SYM_N)
+    {
+     /* SJM 11/12/01 - must catch syntax error of using non net as port */
+     /* iconn connection */
+     /* actual error will be found during pass 2 - needed for port coerce */
+     __gferr(3415, fnind, flcnt,
+      "lllegal declarative lvalue %s - see detailed pass 2 error",
+      __msgexpr_tostr(__xs, xp)); 
+     __pv_err_cnt--;
+     return;
+    }
+   np = xp->lu.sy->el.enp;
+   break;
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   return;
+  case LSB:
+   idndp = xp->lu.x;
+   np = idndp->lu.sy->el.enp;
+   /* SJM 09/24/01 - if syntax err where selecting from non vector emit */
+   /* error and do not set drive type */ 
+   if (np->nsym->sytyp != SYM_N || !np->n_isavec)
+    {
+     __gferr(3412, fnind, flcnt,
+      "attempt to bit select from non vector %s", np->nsym->synam);
+     return;
+    }
+   ri1 = ri2 = comp_pre_elab_norm_con_ndx(np, xp->ru.x, fnind, flcnt);
+   /* SJM 07/07/03 - for illegal negative index, can't set bit drvr types */
+   if (ri1 == -2) return;
+   break;
+  case PARTSEL:
+   idndp = xp->lu.x;
+   np = idndp->lu.sy->el.enp;
+   if (np->nsym->sytyp != SYM_N || !np->n_isavec)
+    {
+     __gferr(3412, fnind, flcnt,
+      "attempt to part select from non vector %s", np->nsym->synam);
+     return;
+    }
+   /* notice need to eval these const exprs since not folded yet */
+   ri1 = comp_pre_elab_norm_con_ndx(np, xp->ru.x->lu.x, fnind, flcnt);
+   ri2 = comp_pre_elab_norm_con_ndx(np, xp->ru.x->ru.x, fnind, flcnt);
+   /* SJM 07/07/03 - for illegal negative index, can't set bit drvr types */
+   if (ri1 == -2 || ri2 == -2) return;
+   break;
+  case LCB:
+   for (catxp = xp->ru.x; catxp != NULL; catxp = catxp->ru.x)
+    { set_lhs_expr_drvrtyp(catxp->lu.x, drvr_typ, fnind, flcnt); }
+   return;
+  default: 
+   /* SJM 10/22/01 - need to flag problem but not count as error since */
+   /* actual error will be found during pass 2 - needed for port coerce */
+   __gferr(3415, fnind, flcnt, "lllegal declarative lvalue %s - see detailed pass 2 error",
+    __msgexpr_tostr(__xs, xp)); 
+   __pv_err_cnt--;
+   return;
+ }
+ if (np->n_isavec) set_vec_drvr_type(np, ri1, ri2, drvr_typ);
+ else set_scalar_drvr_type(np, drvr_typ);
+}
+
+/*
+ * compute a known constant expr numeric index before elaboration and folding
+ * notice since constants not yet folded, must normalize constants too
+ */
+static int32 comp_pre_elab_norm_con_ndx(struct net_t *np, struct expr_t *xp,
+ int32 fnind, int32 flcnt)
+{
+ int32 nni1, nni2, biti, biti2, prtxpr_rng_bad;
+ struct xstk_t *xsp;
+
+ if (!is_nonis_const_expr(xp)) return(-1);
+
+ xsp = __eval_xpr(xp);
+ /* if wide or x/z, be pessimistic and assume all of range (i.e. out of rng) */
+ if (xsp->xslen > WBITS || xsp->bp[0] != 0)
+  { __pop_xstk(); return(-1); }
+ biti2 = (int32) xsp->ap[0];
+ __pop_xstk();
+
+ /* SJM 04/07/23 - nx1 may not be set for nets decl from implicit connect */
+ if (np->nu.ct->nx1 == NULL || np->nu.ct->nx2 == NULL)
+  {
+   biti = -1;
+  }
+ else
+  {
+   nni1 = (int32) __contab[np->nu.ct->nx1->ru.xvi];
+   nni2 = (int32) __contab[np->nu.ct->nx2->ru.xvi];
+   /* SJM 07/31/03 - because port drivers are needed before ranges set */
+   /* must make sure that mod port expr constant selects are in range */
+   /* notice - not yet normalized to h:0 */
+   prtxpr_rng_bad = FALSE;
+   if (nni1 >= nni2)
+    { if (biti2 > nni1 || biti2 < nni2) prtxpr_rng_bad  = TRUE; }
+   else { if (biti2 < nni1 || biti2 > nni2) prtxpr_rng_bad = TRUE; }
+   if (prtxpr_rng_bad) 
+    {
+     __gferr(3415, fnind, flcnt,
+      "module port expression select range index %d outside net range [%d:%d] - can't fix",
+      biti2, nni1, nni2); 
+     return(-2); 
+    }
+
+   if (nni1 < 0 || nni2 < 0 || biti2 < 0)
+    {
+     __gferr(3415, fnind, flcnt, "lllegal negative port declaration range");
+     return(-2); 
+    } 
+   biti = normalize_ndx_(biti2, nni1, nni2);
+  }
+ return(biti);
+}
+
+/*
+ * check to see if an expressions is pre elaboration non IS constant
+ * no folding before here and selects legal providing no variables appear
+ */
+static int32 is_nonis_const_expr(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ np = NULL;
+ if (__isleaf(ndp))
+  {
+   if (ndp->optyp == ID)
+    {
+     if (ndp->lu.sy->sytyp != SYM_N) return(FALSE);
+     np = ndp->lu.sy->el.enp;
+     if (!np->n_isaparam) return(FALSE);
+    }
+   if (ndp->optyp == GLBREF) return(FALSE);
+   /* here IS number is non constant */
+   if (ndp->optyp == ISNUMBER) return(FALSE); 
+
+   /* SJM 05/19/04 - because of driver bit setting needed to do later */
+   /* expr checking - only for parameters expr size not yet set */
+   /* therefore set it to parameter width here as kludge - value will be */
+   /* right but will be set again later */
+   if (ndp->optyp == ID && ndp->szu.xclen == 0)
+    {
+     ndp->szu.xclen = np->nwid;
+    }
+
+   return(TRUE);
+  }
+ if (ndp->lu.x != NULL)
+  { if (!is_nonis_const_expr(ndp->lu.x)) return(FALSE); }
+ if (ndp->ru.x != NULL)
+  { if (!is_nonis_const_expr(ndp->ru.x)) return(FALSE); }
+ return(TRUE);
+}
+
+/*
+ * set scalar driver type - know never passed drvr none
+ */
+static void set_scalar_drvr_type(struct net_t *np, int32 drvr_typ)
+{
+ /* if current state drvr none, set to passed new state */
+ if (np->n_drvtyp == DRVR_NONE) { np->n_drvtyp = drvr_typ; return; }
+
+ /* otherwide set to real driver - any 2nd driver becomes non port where */
+ /* always need to change to inout if possible */
+ np->n_drvtyp = DRVR_NON_PORT;
+}
+
+/*
+ * set driver type - know never passed drvr none
+ * if ri1 -1, then entire range - know ranges normalized before here
+ */
+static void set_vec_drvr_type(struct net_t *np, int32 ri1, int32 ri2, int32 drvr_typ)
+{
+ register int32 ri, bi;
+ int32 nni1, nni2, wid;
+
+ /* range convert to constants but not normalized by here */
+ nni1 = (int32) __contab[np->nu.ct->nx1->ru.xvi];
+ nni2 = (int32) __contab[np->nu.ct->nx2->ru.xvi];
+ wid = ((nni1 >= nni2) ? (nni1 - nni2 + 1) : (nni2 - nni1 + 1));
+ /* allocate per bit drv state if needed */
+ if (np->nu.ct->n_pb_drvtyp == NULL)
+  {
+   np->nu.ct->n_pb_drvtyp = (byte *) __my_malloc(wid);
+   for (bi = 0; bi < wid; bi++) np->nu.ct->n_pb_drvtyp[bi] = DRVR_NONE; 
+  }
+ 
+ if (ri1 == -1) { ri1 = wid - 1; ri2 = 0; }
+ for (ri = ri1; ri >= ri2; ri--)
+  {
+   /* if current state drvr none, set to passed new state */
+   if (np->nu.ct->n_pb_drvtyp[ri] == DRVR_NONE)
+    { np->nu.ct->n_pb_drvtyp[ri] = drvr_typ; continue; }
+   /* otherwide set to real driver - any 2nd driver becomes non port where */
+   /* always need to change to inout if possible */
+   np->nu.ct->n_pb_drvtyp[ri] = DRVR_NON_PORT;
+  }
+}
+
+/*
+ * check connection pattern for all input and output ports and change if 
+ * nd_chg T and return num_chged if any changed (0 if none changed)
+ *
+ * if input has lowconn driver and highconn is wire lvalue chg to inout
+ * if output has highconn driver and lowconn is wire lvalue chg to inout
+ *
+ * if option not used, emit warning else emit inform if option used
+ */
+extern void __chk_chg_port_dir(int32 nd_chg)
+{
+ register int32 pi, ii;
+ register struct mod_pin_t *mpp;
+ int32 pnum, num_chged, sav_num_chged;
+ struct inst_t *ip;
+ struct mod_t *mdp, *imdp;
+ struct expr_t *xp;
+ char s1[RECLEN];
+
+ for (num_chged = 0;;)
+  {
+   sav_num_chged = num_chged;
+   for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+    {
+     /* process for every instance in module */ 
+     for (ii = 0; ii < mdp->minum; ii++)
+      {
+       ip = &(mdp->minsts[ii]);
+       imdp = ip->imsym->el.emdp;
+       if ((pnum = imdp->mpnum) == 0) continue;
+
+       for (pi = 0; pi < pnum; pi++)
+        {
+         mpp = &(imdp->mpins[pi]);
+         /* any up iconn connection to inout is fi>1 here */
+         xp = ip->ipins[pi];
+
+         /* SJM 06/01/01 SJM - never change if either hiconn or loconn */
+         /* concatenate - idea is that concat is expr so must be declared */
+         /* with right direction or assume no backwards driving */
+         if (mpp->mpref->optyp == LCB || xp->optyp == LCB) continue;
+
+         /* SJM 11/15/00 - need to emit warnings for connections where */
+         /* XL port collapsing may produce wrong result */
+         /* case 1: instance input port where down lowconn has drivers */
+         if (mpp->mptyp == IO_IN)
+          {
+           /* SJM 05/23/01 - changeable if both hiconn and loconn decl lval */
+           /* and has wrong direction driver(s) */
+           /* for port, even if subrange, if any bits in vec, change */
+           if (expr_decl_lvalue(mpp->mpref) && expr_decl_lvalue(xp)
+            && port_expr_has_wrong_dir_drvr(mpp->mpref, IO_IN, -1, -1,
+             mpp->mpfnam_ind, mpp->mplin_cnt))
+            {
+             if (nd_chg)
+              {
+               __gfinform(3005, mpp->mpfnam_ind, mpp->mplin_cnt,
+                "input port %s (pos. %d) of instance at %s has lowconn driver(s) - changed to inout from +change_port_type option - otherwise value of %s in %s could differ",
+                __to_mpnam(__xs, mpp->mpsnam), pi + 1, 
+                __bld_lineloc(__xs2, ip->isym->syfnam_ind, ip->isym->sylin_cnt),
+                __msgexpr_tostr(s1, xp), mdp->msym->synam); 
+
+               mpp->mptyp = IO_BID;
+               chg_mpx_to_bid(mpp->mpref);
+               set_lhs_expr_drvrtyp(mpp->mpref, DRVR_NON_PORT,
+                mpp->mpfnam_ind, mpp->mplin_cnt);
+               set_lhs_expr_drvrtyp(xp, DRVR_NON_PORT, ip->isym->syfnam_ind,
+                ip->isym->sylin_cnt);
+               num_chged++;
+               continue;
+              }
+             if (mdp->mgarr != NULL || imdp->mgarr != NULL)
+              {
+               /* SJM 05/23/01 - if mod has arrays of gates just inform but */
+               /* still would change if change port types on */
+               __gfinform(3005, mpp->mpfnam_ind, mpp->mplin_cnt,
+                "input port %s (pos. %d) of instance at %s has lowconn driver(s), value of %s in %s may differ from simulators using port collapsing - use +change_port_type for compatibility",
+                __to_mpnam(__xs, mpp->mpsnam), pi + 1, 
+                __bld_lineloc(__xs2, ip->isym->syfnam_ind, ip->isym->sylin_cnt),
+                __msgexpr_tostr(s1, xp), mdp->msym->synam); 
+               continue;
+              }
+ 
+             __gfwarn(3107, mpp->mpfnam_ind, mpp->mplin_cnt,
+              "input port %s (pos. %d) of instance at %s has lowconn driver(s), value of %s in %s may differ from simulators using port collapsing - use +change_port_type for compatibility",
+              __to_mpnam(__xs, mpp->mpsnam), pi + 1, 
+              __bld_lineloc(__xs2, ip->isym->syfnam_ind, ip->isym->sylin_cnt),
+              __msgexpr_tostr(s1, xp), mdp->msym->synam); 
+            }
+           continue;
+          }
+         if (mpp->mptyp == IO_OUT) 
+          {
+           /* SJM 05/23/01 - changeable if both hiconn and loconn decl lval */
+           /* and has wrong direction driver(s) */
+           /* for output if bsel or psel, need range but decomposed here */
+           if (expr_decl_lvalue(mpp->mpref) && expr_decl_lvalue(xp)
+            && port_expr_has_wrong_dir_drvr(xp, IO_OUT, -1, -1,
+            mpp->mpfnam_ind, mpp->mplin_cnt))
+            {
+             if (nd_chg)
+              {
+               __gfinform(3004, mpp->mpfnam_ind, mpp->mplin_cnt,
+                "output port %s (pos. %d) of instance at %s has highconn driver(s) - changed to inout from +change_port_type option - otherwise value of %s in %s could differ",
+               __to_mpnam(__xs, mpp->mpsnam), pi + 1, 
+               __bld_lineloc(__xs2, ip->isym->syfnam_ind, ip->isym->sylin_cnt),
+               __msgexpr_tostr(s1, mpp->mpref), imdp->msym->synam); 
+
+               mpp->mptyp = IO_BID;
+               chg_mpx_to_bid(mpp->mpref);
+               set_lhs_expr_drvrtyp(mpp->mpref, DRVR_NON_PORT,
+                mpp->mpfnam_ind, mpp->mplin_cnt);
+               set_lhs_expr_drvrtyp(xp, DRVR_NON_PORT, ip->isym->syfnam_ind,
+                ip->isym->sylin_cnt);
+               num_chged++;
+               continue;
+              }
+             if (mdp->mgarr != NULL || imdp->mgarr != NULL)
+              {
+               /* SJM 05/23/01 - if mod has arrays of gates just inform but */
+               /* still would change if change port types on */
+               __gfinform(3005, mpp->mpfnam_ind, mpp->mplin_cnt,
+              "output port %s (pos. %d) of instance at %s has highconn driver(s), value of %s in %s may differ from simulators using port collapsing - use +change_port_type for compatibility",
+              __to_mpnam(__xs, mpp->mpsnam), pi + 1, 
+              __bld_lineloc(__xs2, ip->isym->syfnam_ind, ip->isym->sylin_cnt),
+              __msgexpr_tostr(s1, mpp->mpref), imdp->msym->synam); 
+               continue;
+              }
+             __gfwarn(3108, mpp->mpfnam_ind, mpp->mplin_cnt,
+              "output port %s (pos. %d) of instance at %s has highconn driver(s), value of %s in %s may differ from simulators using port collapsing - use +change_port_type for compatibility",
+              __to_mpnam(__xs, mpp->mpsnam), pi + 1, 
+              __bld_lineloc(__xs2, ip->isym->syfnam_ind, ip->isym->sylin_cnt),
+              __msgexpr_tostr(s1, mpp->mpref), imdp->msym->synam); 
+            }
+          }
+        }
+      }
+    }
+   /* if none changed, done - else try to find more */
+   if (sav_num_chged == num_chged) break;
+  }
+ if (nd_chg && __verbose)
+  {
+   __cv_msg(
+    "  %d input and/or output ports that are connected as inout changed to inout.\n", 
+    num_chged);
+  }
+ free_design_ndrvrs();
+}
+
+/*
+ * return T if expression has (can have) wrong direction drivers
+ * for input port, expect down mod port expr to have only MD PRT driver
+ * for output port, expect up iconn expr to have only up iconn driver
+ *
+ * this is run before tran channels built
+ * never called for ports already inouts or that can't be changed to inout 
+ */
+static int32 port_expr_has_wrong_dir_drvr(struct expr_t *xp, int32 pdir, int32 ri1,
+ int32 ri2, int32 fnind, int32 flcnt)
+{
+ register struct expr_t *catndp;
+ int32 elem_lval, has_drvrs, max_drv_state;
+ struct net_t *np;
+
+ /* SJM 07/07/03 - if neg range error - can't check dir - error later */
+ /* SJM 07/16/03 - for non vector expect ri2 to be -1 - can't check for */  
+ /* negative range */
+ if (ri1 < -1 || ri2 < -1) return(FALSE);
+
+ if (__isleaf(xp))
+  {
+   if (xp->optyp == ID || xp->optyp == GLBREF)
+    {
+     np = xp->lu.sy->el.enp;
+     /* if not wire, does not have wrong dir driver */
+     if (np->ntyp >= NONWIRE_ST) return(FALSE);
+
+     if (np->n_isavec) max_drv_state = find_max_rng_drvr_state(np, ri1, ri2);
+     else max_drv_state = np->n_drvtyp;
+
+     /* if no drivers, can't be wrong direction */
+     if (max_drv_state == DRVR_NONE) return(FALSE);
+
+     /* if has non port (inout non port here), always has wrog dir */
+     if (max_drv_state == DRVR_NON_PORT) return(TRUE);
+    
+     if (pdir == IO_IN)
+      {
+       /* if input port, wrong direction is non port or 1 up iconn driver */
+       if (max_drv_state != DRVR_MDPRT) return(TRUE);
+      }
+     else if (pdir == IO_OUT)
+      {
+       /* if output port, wrong direction is non port or 1 down mdprt drvr */
+       if (max_drv_state != DRVR_ICONN) return(TRUE);
+      }
+     else __case_terr(__FILE__, __LINE__);
+     return(FALSE);
+    }
+   /* if leaf, non id or global, can't have drivers */
+   return(FALSE);
+  }
+ /* arithmetic/logic operators exprs or fcalls can't have drivers */
+ switch ((byte) xp->optyp) {
+  /* for selects, ignore select expr. */
+  case LSB:
+   /* if not lvalue, never need to change */
+   if (!__is_const_expr(xp->ru.x)) return(FALSE);
+   /* if port is input, any driver (even outside bsel) still need dir chg */  
+   if (pdir == IO_IN) ri1 = -1;
+   else
+    {
+     np = xp->lu.x->lu.sy->el.enp;
+     ri1 = comp_pre_elab_norm_con_ndx(np, xp->ru.x, fnind, flcnt);
+     /* SJM 07/07/03 - if illegal neg rng - treat as right dir */
+     if (ri1 == -2) return(FALSE);
+    }
+   if (port_expr_has_wrong_dir_drvr(xp->lu.x, pdir, ri1, ri1, fnind,
+    flcnt)) return(TRUE);
+   return(FALSE);
+  case PARTSEL:
+   /* if port is input, any driver (even outside sel) still need dir chg */  
+   if (pdir == IO_IN) ri1 = ri2 = -1;
+   else
+    {
+     np = xp->lu.x->lu.sy->el.enp;
+     ri1 = comp_pre_elab_norm_con_ndx(np, xp->ru.x->lu.x, fnind, flcnt);
+     ri2 = comp_pre_elab_norm_con_ndx(np, xp->ru.x->ru.x, fnind, flcnt);
+     /* SJM 07/07/03 - if illegal neg rng - treat as right dir */
+     if (ri1 == -2 || ri2 == -2) return(FALSE);
+    }
+   if (port_expr_has_wrong_dir_drvr(xp->lu.x, pdir, ri1, ri2, fnind, flcnt))
+    return(TRUE);
+   return(FALSE);
+  case LCB:
+   /* if any component has drivers and all are decl lvals, then T */
+   has_drvrs = FALSE;
+   elem_lval = TRUE;
+   for (catndp = xp->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    {
+     /* if any expr has drivers and no regs, then concat can have drvrs */
+     if (port_expr_has_wrong_dir_drvr(catndp->lu.x, pdir, -1, -1, fnind,
+      flcnt)) has_drvrs = TRUE;
+     /* if not decl lvalue, concat can't be decl lvalue either */
+     if (!expr_decl_lvalue(catndp->lu.x)) elem_lval = FALSE;
+    }
+   if (has_drvrs && elem_lval) return(TRUE);
+   break;
+  default: break;
+ }
+ /* if not an lvalue, can't be changed to inout */
+ return(FALSE);
+}
+
+/*
+ * compute maximum driver state of expr 
+ * for module will always be entire expr, for up iconn may be for subrange
+ *
+ * if entire range -1, else normalized range
+ * only called for vectors
+ */
+static int32 find_max_rng_drvr_state(struct net_t *np, int32 ri1, int32 ri2)
+{
+ register int32 bi;
+ int32 max_drvr_state, nni1, nni2, wid;
+
+ nni1 = (int32) __contab[np->nu.ct->nx1->ru.xvi];
+ nni2 = (int32) __contab[np->nu.ct->nx2->ru.xvi];
+ wid = ((nni1 >= nni2) ? (nni1 - nni2 + 1) : (nni2 - nni1 + 1));
+ max_drvr_state = DRVR_NONE;
+ if (ri1 == -1) { ri1 = wid - 1; ri2 = 0; }
+ for (bi = ri1; bi >= ri2; bi--)
+  {
+   /* if current driver state, max. hard non port (maybe inout), found max */
+   if (np->nu.ct->n_pb_drvtyp[bi] == DRVR_NON_PORT) 
+    { max_drvr_state = DRVR_NON_PORT; break; }
+
+   /* if this one is driver none, nothing to do */
+   if (max_drvr_state == DRVR_NONE) continue;
+
+   /* if max same as this one, nothing to do */
+   if (np->nu.ct->n_pb_drvtyp[bi] == max_drvr_state) continue;
+     
+   /* if this one, non inout port, know will be different so set to max */  
+   max_drvr_state = DRVR_NON_PORT;
+   break;
+  }
+ return(max_drvr_state);
+}
+
+/*
+ * check to see if an expressions is constant 
+ *
+ * no folding and selects legal providing no variables appear
+ */
+extern int32 __is_const_expr(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ if (__isleaf(ndp))
+  {
+   if (ndp->optyp == ID)
+    {
+     if (ndp->lu.sy->sytyp != SYM_N) return(FALSE);
+     np = ndp->lu.sy->el.enp;
+     if (!np->n_isaparam) return(FALSE);
+    }
+   if (ndp->optyp == GLBREF) return(FALSE);
+   return(TRUE);
+  }
+ if (ndp->lu.x != NULL) { if (!__is_const_expr(ndp->lu.x)) return(FALSE); }
+ if (ndp->ru.x != NULL) { if (!__is_const_expr(ndp->ru.x)) return(FALSE); }
+ return(TRUE);
+}
+
+/*
+ * return T if expr is decl lvalue
+ * only if decl lvalue high conn and low conn can be changed to inout port
+ */
+static int32 expr_decl_lvalue(struct expr_t *xp)
+{
+ struct expr_t *catndp;
+ struct net_t *np;
+
+ switch ((byte) xp->optyp) {
+  case ID: case GLBREF:
+   np = xp->lu.sy->el.enp;
+   /* reg is not decl lvalue */
+   if (np->ntyp < NONWIRE_ST) return(TRUE);
+   break;
+  case LSB:
+   /* declarative lvalue only if constant expr */
+   /* SJM 05/23/01 - at this point const exprs not folded */
+   if (!__is_const_expr(xp->ru.x)) return(FALSE);
+   np = xp->lu.x->lu.sy->el.enp;
+   /* only wire is decl lvalue */
+   if (np->ntyp < NONWIRE_ST) return(TRUE);
+   break;
+  case PARTSEL:
+   np = xp->lu.x->lu.sy->el.enp;
+   /* only wire is decl lvalue */
+   if (np->ntyp < NONWIRE_ST) return(TRUE);
+   break;
+  case LCB:
+   /* if any element of concat not decl lvalue, concat can't be changed */
+   for (catndp = xp->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    {
+     if (!expr_decl_lvalue(catndp->lu.x)) return(FALSE);
+    }
+   return(TRUE);
+  default: break;
+ }
+ /* if not an lvalue, can't be changed to inout */
+ return(FALSE);
+}
+
+/*
+ * routine to change IO type of all port expr contaned nets 
+ * know will be lvalue or will not be called
+ */
+static void chg_mpx_to_bid(struct expr_t *mpx)
+{
+ register struct expr_t *catndp; 
+ struct net_t *np;
+
+ switch ((byte) mpx->optyp) {
+   case ID: case GLBREF:
+    np = mpx->lu.sy->el.enp;
+    np->iotyp = IO_BID;
+    break;
+   case LSB: case PARTSEL:
+    chg_mpx_to_bid(mpx->lu.x);
+    break;
+   case LCB:
+    for (catndp = mpx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+     { chg_mpx_to_bid(catndp->lu.x); }
+    break; 
+   default: __case_terr(__FILE__, __LINE__);
+  }
+}
+
+/*
+ * free all vector rng reps in design - never attached for task vars
+ */
+static void free_design_ndrvrs(void)
+{
+ register struct mod_t *mdp;
+ register int32 ni;
+ register struct net_t *np;
+ int32 nni1, nni2, wid;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* only free for wires, regs and task vars never pb drv fields */ 
+   for (np = &(mdp->mnets[0]), ni = 0; ni < mdp->mnnum; ni++, np++)
+    {
+     if (!np->n_isavec) continue;
+
+     if (np->nu.ct->n_pb_drvtyp != NULL)
+      {
+       nni1 = (int32) __contab[np->nu.ct->nx1->ru.xvi];
+       nni2 = (int32) __contab[np->nu.ct->nx2->ru.xvi];
+       wid = ((nni1 >= nni2) ? (nni1 - nni2 + 1) : (nni2 - nni1 + 1));
+       __my_free((char *) np->nu.ct->n_pb_drvtyp, wid);
+       np->nu.ct->n_pb_drvtyp = NULL;
+      }
+    }
+  }
+}
+
+/*
+ * ROUTINES TO SET TIME SCALE VALUES 
+ */
+
+/*
+ * process module and design timescales
+ * this is needed before any conversion of delay constant expressions
+ * to ticks 
+ * notice storing inverse so higher value is smaller time
+ */
+extern void __process_timescales(void)
+{
+ register struct mod_t *mdp;
+ 
+ /* notice implied - so 0 is max 1 sec. (10**-0 secs.) */
+ /* larger units is shorter tick */
+ __des_timeprec = 0;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mtime_units + mdp->mtime_prec > __des_timeprec)
+    __des_timeprec = mdp->mtime_units + mdp->mtime_prec;
+  } 
+ /* unless set %t time format defaults to ticks */
+ __tfmt_units = __des_timeprec;
+
+ /* next mark all modules with des time units - no scaling needed */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mtime_units == __des_timeprec) mdp->mno_unitcnv = TRUE;
+  }
+ bld_timstr_vals();
+}
+
+/*
+ * routine to build "absolute time" multiplier and suffix for to_timstr
+ * message times
+ */
+static void bld_timstr_vals(void)
+{
+ register struct mod_t *mdp;
+
+ strcpy(__timstr_unitsuf, "");
+ __timstr_mult = 1ULL;
+ __nd_timstr_suf = FALSE;
+ /* if module has scaled time timstr values need suffix and multiplier */ 
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* if not no unit conversion need absolute times */
+   if (!mdp->mno_unitcnv) { __nd_timstr_suf = TRUE; break; } 
+  }
+ /* if all modules have same time unit (no matter what), timstr no units */
+ if (!__nd_timstr_suf) return;
+ 
+ /* if any differ, need absolute units but still not scaled to module */
+ /* i.e. value will be absolute time of tick */
+ switch (__des_timeprec) {
+  case 0:
+   __timstr_mult = 1ULL;
+   strcpy(__timstr_unitsuf, " s");
+   break;
+  case 1:
+   __timstr_mult = 100ULL;
+   strcpy(__timstr_unitsuf, " ms");
+   break;
+  case 2:
+   __timstr_mult = 10ULL;
+   strcpy(__timstr_unitsuf, " ms");
+   break;
+  case 3:
+   __timstr_mult = 1ULL;
+   strcpy(__timstr_unitsuf, " ms");
+   break;
+  case 4:
+   __timstr_mult = 100ULL;
+   strcpy(__timstr_unitsuf, " us");
+   break;
+  case 5:
+   __timstr_mult = 10ULL;
+   strcpy(__timstr_unitsuf, " us");
+   break;
+  case 6:
+   __timstr_mult = 1ULL;
+   strcpy(__timstr_unitsuf, " us");
+   break;
+  case 7:
+   __timstr_mult = 100ULL;
+   strcpy(__timstr_unitsuf, " ns");
+   break;
+  case 8:
+   __timstr_mult = 10ULL;
+   strcpy(__timstr_unitsuf, " ns");
+   break;
+  case 9:
+   __timstr_mult = 1ULL;
+   strcpy(__timstr_unitsuf, " ns");
+   break;
+  case 10:
+   __timstr_mult = 100ULL;
+   strcpy(__timstr_unitsuf, " ps");
+   break;
+  case 11:
+   __timstr_mult = 10ULL;
+   strcpy(__timstr_unitsuf, " ps");
+   break;
+  case 12:
+   __timstr_mult = 1ULL;
+   strcpy(__timstr_unitsuf, " ps");
+   break;
+  case 13:
+   __timstr_mult = 100ULL;
+   strcpy(__timstr_unitsuf, " fs");
+   break;
+  case 14:
+   __timstr_mult = 10ULL;
+   strcpy(__timstr_unitsuf, " fs");
+   break;
+  case 15:
+   __timstr_mult = 1ULL;
+   strcpy(__timstr_unitsuf, " fs");
+   break;
+ default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * ROUTINES TO MARK PARAMS THAT EFFECT EXPRESSION WIDTHS
+ */
+
+/*
+ * mark all parameters that are in ranges or cats (or port def. psels)
+ *
+ * called first time when module is target of xmr defparam that needs to
+ * be split
+ *
+ * this marks all param net_t's that can effect width so that splitting is
+ * needed but unless actual xmr defparam marked, does not cause splitting
+ */
+extern void __mark_widdet_params(struct mod_t *pmdp)
+{
+ struct task_t *tskp;
+
+ /* check all wire and array declaration ranges - mark any param there */
+ inrnges_mark_params(pmdp->msymtab);
+
+ /* task list contains all symbols in task but if has named blocks */
+ /* symbols declared there will be checked in its task on list */
+ for (tskp = pmdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  inrnges_mark_params(tskp->tsksymtab);
+
+ /* for all modules since checked before splitting port header range */
+ /* params already marked */
+
+ /* finally find all psel params in any expressions */
+ /* insts, contas, task/functions, statements */
+ /* also any bit select expression connecting to output or inout port */ 
+ psel_set_allexprs(pmdp);
+}
+
+/*
+ * mark all parameters in declaration ranges for one symbol table 
+ *
+ * by here know symbol table format frozen form 
+ * must use symbol table because may not have nets list built when called
+ */
+static void inrnges_mark_params(struct symtab_t *sytp)
+{
+ register int32 syi;
+ struct sy_t **syms;
+ struct sy_t *syp;
+ struct net_t *np;
+
+ for (syi = 0, syms = sytp->stsyms; syi < (int32) sytp->numsyms; syi++)
+  {
+   syp = syms[syi];
+   if (syp->sytyp != SYM_N) continue;
+   np = syp->el.enp;
+
+   /* set in cat or range bit for wire range params */
+   if (np->n_isavec)
+    {
+     __in_xpr_markparam(np->nu.ct->nx1);
+     __in_xpr_markparam(np->nu.ct->nx2);
+    }
+   /* set in cat or range bit for array range params */
+   if (np->n_isarr)
+    {
+     __in_xpr_markparam(np->nu.ct->ax1);
+     __in_xpr_markparam(np->nu.ct->ax2);
+    }
+  }
+}
+
+/*
+ * set the width determining bit for any wire in expressions
+ * caller determined is expression used in width determing place
+ *
+ * expression not yet checked but just marks IDs that are there
+ * may mark wrong internal select params but selects here will cause
+ * error later since must be constant expr.
+ * any parameter including in "from param" select marked here
+ */
+extern void __in_xpr_markparam(struct expr_t *xp)
+{
+ struct net_t *np;
+
+ if (__isleaf(xp))
+  {
+   if (xp->optyp == ID && xp->lu.sy->sytyp == SYM_N)
+    {
+     np = xp->lu.sy->el.enp; 
+     if (np->n_isaparam)
+      {
+       np->nu.ct->n_widthdet = TRUE;
+       __inst_mod->mhas_widthdet = TRUE;
+      }
+    }
+   return;
+  }
+ if (xp->lu.x != NULL) __in_xpr_markparam(xp->lu.x);
+ if (xp->ru.x != NULL) __in_xpr_markparam(xp->ru.x);
+}
+
+/*
+ * mark params in all part selects and CATREP lhs repeat expressions
+ * and tran out bit select ranges anywhere in module
+ *
+ * width determining marked for params used in array of gate or inst
+ * ranges - only cause split if marked param a def or pound param and
+ * really needs to cause containing module to be split
+ */
+static void psel_set_allexprs(struct mod_t *pmdp)
+{
+ register int32 pi, j;
+ register struct inst_t *ip;
+ register struct gate_t *gp;
+ int32 pnum, skip_giarr;
+ struct task_t *tskp;
+ struct conta_t *cap;
+ struct ialst_t *ialp;
+ struct expr_t *xp;
+ struct mod_pin_t *mpp;
+ struct mod_t *down_mdp;
+ struct net_t *np;
+ struct giarr_t *giap;
+
+ /* any part select in module except specify where no defparams possible */ 
+ if ((pnum = pmdp->mpnum) != 0)
+  {
+   /* mark for module ports */
+   for (pi = 0; pi < pnum; pi++)
+    { mpp = &(pmdp->mpins[pi]); inpsel_xpr_markparam(mpp->mpref); }
+  }
+ giap = NULL;
+ for (j = 0; j < pmdp->minum; j++)
+  {
+   ip = &(pmdp->minsts[j]);
+   /* for array of instances, need master ip in giarr */ 
+   if (pmdp->miarr != NULL && (giap = pmdp->miarr[j]) != NULL)
+    skip_giarr = TRUE;
+   else skip_giarr = FALSE;
+
+   down_mdp = ip->imsym->el.emdp;
+   for (pi = 0; pi < (int32) down_mdp->mpnum; pi++)
+    {
+     xp = ip->ipins[pi];
+     /* DBG remove --- */
+     if (xp == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+
+     /* this will mark any part select even those that for arrays of insts */
+     /* become bit selects */
+     inpsel_xpr_markparam(xp);
+
+     /* instance connection bit selects to inout or output ports must be */
+     /* width det because effects tran channels */
+     mpp = &(down_mdp->mpins[pi]);
+     if (xp->optyp == LSB)
+      {
+       /* 05/19/01 SJM - for input and output that are param bsel from net */
+       /* must mark as splittable if relevant param passed down */
+       if (mpp->mptyp == IO_IN)
+        {
+         /* 06/01/01 SJM - if XMR, must always mark */
+         if (xp->lu.x->optyp != ID) __in_xpr_markparam(xp->ru.x);
+         else
+          {
+           np = xp->lu.x->lu.sy->el.enp;
+           if (np->ntyp < NONWIRE_ST) __in_xpr_markparam(xp->ru.x);
+          }
+         continue;
+        }
+       if (mpp->mptyp == IO_BID || mpp->mptyp == IO_OUT)
+        __in_xpr_markparam(xp->ru.x);
+      }
+    }
+   /* routine always called after inst arrays expanded into per bit but */
+   /* before connections apportioned to each expanded inst. - just do first */
+   if (skip_giarr)
+    {
+     /* DBG remove -- */
+     if (!giap->gia_xpnd) __misc_terr(__FILE__, __LINE__);
+     if (giap->gia_bi != j) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     j += __get_giarr_wide(giap) - 1;
+    }
+  }
+ for (cap = pmdp->mcas; cap != NULL; cap = cap->pbcau.canxt)
+  {
+   inpsel_xpr_markparam(cap->lhsx);
+   if (cap->lhsx->optyp == LSB)
+    {
+     /* if conta output could drive path dest. cannot be IS form */
+     np = cap->lhsx->lu.x->lu.sy->el.enp;
+     if (np->iotyp == IO_OUT || np->iotyp == IO_BID)
+      { __in_xpr_markparam(cap->lhsx->ru.x); continue; }
+    }
+   inpsel_xpr_markparam(cap->rhsx);
+  }
+ 
+ /* bit selects not width determining, except determines tran channel */
+ /* for trans */
+ /* now gates outputs that are IS form bit selects are ok just not acc. */
+ for (j = 0; j < pmdp->mgnum; j++)
+  {
+   gp = &(pmdp->mgates[j]);
+
+   /* array of gates is only place part select allowed */
+   /* any parameter used in part select is potentially width determing */
+   /* reason is that for width 1 will be replicated and for other widths */
+   /* will be apportioned so must split containing module */
+   if (pmdp->mgarr != NULL && (giap = pmdp->mgarr[j]) != NULL)
+    {
+     skip_giarr = TRUE;
+     for (pi = 0; pi < (int32) gp->gpnum; pi++)
+      {
+       xp = gp->gpins[pi];
+       inpsel_xpr_markparam(xp);
+      }
+    }
+   else skip_giarr = FALSE;
+
+   if (gp->g_class != GC_TRAN || gp->g_class == GC_TRANIF)
+    {
+     if (gp->gpins[0]->optyp == LSB)
+      {
+       /* 06/01/01 - if connection is xmr can never be port */
+       if (gp->gpins[0]->lu.x->optyp != ID) goto nxt_gate;
+
+       /* if gate output could drive path dest. cannot be IS form */
+       np = gp->gpins[0]->lu.x->lu.sy->el.enp;
+
+       if (np->iotyp == IO_OUT || np->iotyp == IO_BID)
+        { __in_xpr_markparam(gp->gpins[0]->ru.x); goto nxt_gate; }
+      }
+     goto nxt_gate;
+    }
+   /* for trans any bit select in either inout port is width determining */
+   xp = gp->gpins[0];
+   if (xp->optyp == LSB) __in_xpr_markparam(xp->ru.x);
+   /* mark the output bit select range - if present */ 
+   xp = gp->gpins[1];
+   if (xp->optyp == LSB) __in_xpr_markparam(xp->ru.x);
+
+   /* routine always called after gate arrays expanded into per bit but */
+   /* before connections apportioned to each expanded inst. - just do first */
+nxt_gate:
+   if (skip_giarr)
+    {
+     /* DBG remove -- */
+     if (!giap->gia_xpnd) __misc_terr(__FILE__, __LINE__);
+     if (giap->gia_bi != j) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     j += (__get_giarr_wide(giap) - 1);
+    }
+  }
+ /* notice processing name blocks here not inline */
+ for (tskp = pmdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  lstofsts_do_inpsel_set(tskp->tskst);
+ /* initial/always can only be stmt here - maybe extra added at prep. */
+ for (ialp = pmdp->ialst; ialp != NULL; ialp = ialp->ialnxt)
+  lstofsts_do_inpsel_set(ialp->iastp);
+ /* notice defparams cannot effect specify section */
+}
+
+/*
+ * mark all psels in concatenates in any statement expr.
+ */
+static void stmt_do_inpsel_set(struct st_t *stp)
+{
+ struct csitem_t *dflt_csip;
+
+ switch ((byte) stp->stmttyp) {
+  case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA: case S_NBPROCA:
+   inpsel_xpr_markparam(stp->st.spra.lhsx);
+   inpsel_xpr_markparam(stp->st.spra.rhsx);
+   break;
+  case S_IF:
+   inpsel_xpr_markparam(stp->st.sif.condx);
+   lstofsts_do_inpsel_set(stp->st.sif.thenst);
+   lstofsts_do_inpsel_set(stp->st.sif.elsest);
+   break;
+  case S_CASE:
+   inpsel_xpr_markparam(stp->st.scs.csx);
+   /* first is always default - st nil if no default */
+   dflt_csip = stp->st.scs.csitems;
+   csitemlst_do_inpsel_set(dflt_csip->csinxt);
+   if (dflt_csip->csist != NULL) lstofsts_do_inpsel_set(dflt_csip->csist);
+   break;
+  case S_FOREVER:
+  case S_WHILE:
+   inpsel_xpr_markparam(stp->st.swh.lpx);
+   lstofsts_do_inpsel_set(stp->st.swh.lpst);
+   break; 
+  case S_WAIT:
+   inpsel_xpr_markparam(stp->st.swait.lpx);
+   lstofsts_do_inpsel_set(stp->st.swait.lpst);
+   break; 
+  case S_REPEAT:
+   inpsel_xpr_markparam(stp->st.srpt.repx);
+   lstofsts_do_inpsel_set(stp->st.srpt.repst);
+   break;
+  case S_FOR:
+   {
+    struct for_t *frp;
+
+    frp = stp->st.sfor;
+    stmt_do_inpsel_set(frp->forassgn);
+    inpsel_xpr_markparam(frp->fortermx);
+    stmt_do_inpsel_set(frp->forinc);
+    lstofsts_do_inpsel_set(frp->forbody);
+   }
+   break;
+  case S_DELCTRL:
+   /* do not need to check delay expression - width will resolve to WBITS */
+   lstofsts_do_inpsel_set(stp->st.sdc->actionst);
+   break;
+  case S_NAMBLK:
+   /* do not need to process here - done when set bits for tasks defs */
+   break;
+  case S_UNBLK:
+   lstofsts_do_inpsel_set(stp->st.sbsts);
+   break;
+  case S_UNFJ:
+   { 
+    register int32 fji;
+    struct st_t *fjstp;
+
+    for (fji = 0;; fji++)
+     {
+      if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+      /* SJM 09/24/01 - this can be 2 stmts for for (for assgn then for) */
+      lstofsts_do_inpsel_set(fjstp);
+     }
+   }
+   break;
+  case S_TSKCALL:
+   {
+    register struct expr_t *xp;
+
+    for (xp = stp->st.stkc.targs; xp != NULL; xp = xp->ru.x)
+     inpsel_xpr_markparam(xp->lu.x);
+   }
+   break;
+  case S_QCONTA:
+   inpsel_xpr_markparam(stp->st.sqca->qclhsx);
+   inpsel_xpr_markparam(stp->st.sqca->qcrhsx);
+   break;
+  case S_CAUSE: case S_DSABLE: case S_NULL: case S_STNONE: case S_QCONTDEA:
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * process each statements of statement list for in psel exprs
+ */
+static void lstofsts_do_inpsel_set(register struct st_t *stp)
+{
+ for (; stp != NULL; stp = stp->stnxt) stmt_do_inpsel_set(stp);
+}
+
+static void csitemlst_do_inpsel_set(register struct csitem_t *csip)
+{
+ register struct exprlst_t *xplp;
+
+ for (; csip != NULL; csip = csip->csinxt)
+  {
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    inpsel_xpr_markparam(xplp->xp);
+   lstofsts_do_inpsel_set(csip->csist);
+  }
+}
+
+/*
+ * mark any param that is appears inside any part select range
+ * as sell as any CATREP repeat count expressions
+ *
+ * must process every module expr. through here if module target of
+ * xmr defparam and multiply instantiated
+ * since nested concatenates not yet expanded must handle nesting
+ */
+static void inpsel_xpr_markparam(struct expr_t *xp)
+{
+ /* loop statements expr. can be nil */
+ if (xp == NULL) return;
+  
+ switch ((byte) xp->optyp) {
+  case ID: case GLBREF: case NUMBER: case ISNUMBER:
+  case REALNUM: case ISREALNUM:
+   return;
+  case PARTSEL:
+   __in_xpr_markparam(xp->ru.x->lu.x);
+   __in_xpr_markparam(xp->ru.x->ru.x);
+   return;
+  case CATREP:
+   inpsel_xpr_markparam(xp->lu.x);
+   if (xp->ru.x != NULL) inpsel_xpr_markparam(xp->ru.x);
+   return;
+  }
+ /* for here can have expr. like a + {...} inside concat - so descend */
+ if (xp->lu.x != NULL) inpsel_xpr_markparam(xp->lu.x);
+ if (xp->ru.x != NULL) inpsel_xpr_markparam(xp->ru.x);
+}
+
+/*
+ * MODULE LEVEL DECLARATION CHECKING ROUTINES
+ */
+
+/*
+ * check undefined symbol and freeze ranges (eval. defparam rhs exprs)
+ * must stop if any pass 1 errors before calling this
+ */
+extern void __chk_1mdecls(void)
+{
+ register struct task_t *tskp;
+ int32 tregbasi;
+
+ chk_undef_syms(__inst_mod->msymtab, MODULE);
+
+ /* this also counts number of regs in tasks and set all nnum fields */
+ chkset_1mwire_rnges();
+
+ /* must check task variables before any statement checking because of */
+ /* xmrs - notice named blocked included here */
+ tregbasi = __inst_mod->mnnum;
+ for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  { 
+   chk_taskvars(tskp, tregbasi);
+   tregbasi += tskp->trnum;
+  }
+
+}
+
+/*
+ * check all symbols in given table (module/task/func/lab. block)
+ * notice this cannot be used to check decl. of specify specparams 
+ */
+static void chk_undef_syms(struct symtab_t *sytp, word32 objttyp)
+{
+ register int32 syi;
+ int32 save_obj;
+ struct sy_t *syp;
+
+ __wrkstab = sytp->stsyms;
+ save_obj = __cur_declobj;
+ __cur_declobj = objttyp;
+ for (syi = 0; syi < (int32) sytp->numsyms; syi++)
+  {
+   syp = __wrkstab[syi];
+   chk_modsym(syp);
+  }
+ __cur_declobj = save_obj;
+}
+
+/*
+ * check one symbol
+ */
+static void chk_modsym(struct sy_t *syp)
+{
+ switch ((byte) syp->sytyp) {
+  /* params still in symbol table but cannot be undeclared so works */
+  case SYM_N:
+   if (__cur_declobj == MODULE) chk_1wire(syp->el.enp);
+   else chk_1reg(syp->el.enp);
+   break;
+  case SYM_TSK: case SYM_F: case SYM_STSK: case SYM_SF:
+   if (!syp->sydecl)
+    __gferr(770, syp->syfnam_ind, syp->sylin_cnt,
+     "%s %s not declared", __to_sytyp(__xs, syp->sytyp), syp->synam);
+   break;
+  /* since non legal in expr. symbol error caught elsewhere */  
+  case SYM_CA: case SYM_TCHK: case SYM_PTH: break;  
+  /* things checked elsewhere that can be in mod. sym. table */
+  /* and are declared by usage */
+  case SYM_I: case SYM_LB: case SYM_UDP: case SYM_PRIM:
+  break;
+ default:
+  /* symbol decl. lost */
+  __misc_gfterr(__FILE__, __LINE__, syp->syfnam_ind, syp->sylin_cnt);
+ }
+}
+
+/*
+ * check 1 wire - just makes sure declared - must check attributes later
+ * wire here just means not in task/func.
+ */
+static void chk_1wire(struct net_t *np)
+{
+ struct sy_t *syp;
+
+ syp = np->nsym;
+ if (!syp->sydecl)
+  {
+   if (syp->sytyp == SYM_CA || syp->sytyp == SYM_PTH
+   || syp->sytyp == SYM_TCHK)
+    {
+     __gferr(1147, syp->syfnam_ind, syp->sylin_cnt,
+      "constructed internal %s %s may not appear in source - only as run time string",
+      __to_sytyp(__xs, syp->sytyp), syp->synam);
+     return;
+    }
+   if (np->iotyp == NON_IO)
+    {
+     __gferr(771, syp->syfnam_ind, syp->sylin_cnt,
+      "wire/reg/event %s not declared", syp->synam);
+    }
+   else
+    __gferr(772, syp->syfnam_ind, syp->sylin_cnt,
+     "module definition port %s not declared", syp->synam);
+   return;
+  }
+ /* LOOKATME - what trireg checking needed */
+}
+
+/*
+ * check 1 task/function/named block wire
+ * this can check everything because task declarations all at top
+ *
+ * this rotine is called through sybmol table checking for tasks
+ */
+static void chk_1reg(struct net_t *np)
+{
+ struct sy_t *syp;
+
+ syp = np->nsym;
+ if (!syp->sydecl)
+  {
+   __gferr(773, syp->syfnam_ind, syp->sylin_cnt,
+    "task/function/named block reg %s not declared", syp->synam);
+   return;
+  }
+}
+
+/*
+ * check and set the module's wire ranges
+ *
+ * also preprocesses wire delays to simulation form and builds wire tab by
+ * copying list elements to table and freeing list 
+ * notice key is that nothing before here points directly to net
+ * always through symbol table which is also updated here
+ *
+ * routine is passed total number of vars in modules so all vars
+ * including task regs are contigous and can be accessed as offset
+ * from mod base
+ *
+ */
+static void chkset_1mwire_rnges(void)
+{
+ register int32 syi, ni;
+ register struct sy_t *syp;
+ register struct net_t *np;
+ int32 dnum, nnum, mvarnum;
+ struct sy_t **syms;
+ struct symtab_t *sytp;
+ struct net_t *ntab, *np2;
+ struct paramlst_t *pmp, *dhdr;
+ struct task_t *tskp;
+
+ sytp = __inst_mod->msymtab;
+ /* count number of nets and store in mod field */
+ nnum = 0;
+ for (syi = 0, syms = sytp->stsyms; syi < (int32) sytp->numsyms; syi++)
+  {
+   syp = syms[syi];
+
+   if (syp->sytyp != SYM_N) continue;
+   np = syp->el.enp;
+   if (!np->n_isaparam) nnum++;
+  }
+ __inst_mod->mnnum = nnum; 
+ mvarnum = nnum;
+
+ /* then count number of regs in each task - set and keep running total */
+ for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+   sytp = tskp->tsksymtab;
+   nnum = 0;
+   for (syi = 0, syms = sytp->stsyms; syi < (int32) sytp->numsyms; syi++)
+    {
+     syp = syms[syi];
+     if (syp->sytyp != SYM_N) continue;
+     np = syp->el.enp;
+     if (np->n_isaparam) continue;
+     nnum++;
+    }
+   tskp->trnum = nnum;
+   mvarnum += nnum;
+  }
+ /* set total nnumber of vars in module for possible use by dmpv */
+ __inst_mod->mtotvarnum = mvarnum;
+
+ ntab = NULL;
+ if (mvarnum != 0)
+  {   
+   ntab = (struct net_t *) __my_malloc(mvarnum*sizeof(struct net_t)); 
+  }
+
+ /* SJM 08/30/00 must include task nets here in case only task's have */
+ /* declared variables */
+ if (__inst_mod->mtotvarnum == 0) return;
+ __inst_mod->mnets = ntab; 
+
+ /* fixing task vars in ntab later */
+ /* point sytp back to mod not task symbol table */
+ sytp = __inst_mod->msymtab;
+ /* not sure if saved needed here */
+ for (ni = 0, syi = 0, syms = sytp->stsyms; syi < (int32) sytp->numsyms; syi++)
+  {
+   syp = syms[syi];
+   if (syp->sytyp != SYM_N) continue;
+
+   np = syp->el.enp;
+   /* parameters checked elsewhere */
+   if (np->n_isaparam) continue;
+
+
+   np2 = &(ntab[ni]);
+   *np2 = *np;
+   __my_free((char *) np, sizeof(struct net_t));
+   syp->el.enp = np2;
+   ni++;
+   np = np2;
+
+   /* do not need to save these, never called with previous location */
+   __sfnam_ind = np->nsym->syfnam_ind;
+   __slin_cnt = np->nsym->sylin_cnt;
+
+   chk_wire_rng(np);
+
+   /* LOOKATME - maybe should allow expressions here but lrm says no */
+   /* can process expression at this early point since final value */
+   /* of all parameters know by here */
+   if ((pmp = np->nu.ct->n_dels_u.pdels) != NULL)
+    {
+     dhdr = __copy_dellst(pmp);
+     if ((dnum = __chk_delparams(dhdr, "wire delay", TRUE)) == -1)
+      np->nu.ct->n_dels_u.pdels = NULL;
+     else
+      {
+       if (dnum > 3)
+        {
+         __sgferr(792,
+          "wire delay for %s has more then 3 delays (%d)", np->nsym->synam,
+          dnum);
+         np->nu.ct->n_dels_u.pdels = NULL;
+        }
+      }
+     __free_dellst(dhdr);
+    }
+  }
+}
+
+/*
+ * debugging routine to dump net names of all nets in all modules
+ */
+extern void __dbg_dmpall_nets(void)
+{
+ register struct mod_t *mdp;
+ register struct net_t *np;
+ register int32 ni;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __dbg_msg("--- dumping nets for module %s\n", mdp->msym->synam);
+   if (mdp->mnnum == 0) continue;
+   for (np = &(mdp->mnets[0]), ni = 0; ni < mdp->mnnum; ni++, np++)
+    {
+     __dbg_msg("  setting symbol %s to point to net %s\n",
+      np->nsym->synam, np->nsym->el.enp->nsym->synam);
+    }
+  }
+}
+
+/*
+ * STRENGTH PROPOGATION TO WIRES ROUTINES
+ */
+
+/*
+ * mark wires that need strength storage and all strength expressions
+ * notice this is before splitting since strengths structural
+ */
+extern void __mark_st_wires(void)
+{
+ /* mark all wires that are strength from type (no wire strength decls) */
+ mark_sttypewires();
+ /* mark all wires immediately driven by strengths */
+ mark_stdr_wires();
+ mark_stdr_inout_wired_logic();
+ if (__design_no_strens) return;
+
+ /* must build module type levelized table after all splitting */
+ /* only used here but not freed since only 4 byte ptr per level */
+ /* field in mod_t needed anyway */  
+ __bld_mlevel_lists();
+
+ /* SJM 10/16/99 - need to keep propagating until no progress */
+ /* not sure why this is needed but missing strenght from 4 */
+ /* know need 4 for shorted inout ports - why more? */
+ for (;;)
+  {
+   __strenprop_chg = FALSE;
+   prop_stsdown();
+   /* prop strengths up through mod outs and inouts */
+   prop_stsup();
+   /* DBG remove -- */
+   if (__debug_flg) __dbg_msg("  >>> Complete one strength marking pass.\n");
+   /* --- */
+   if (!__strenprop_chg) break;
+  }
+}
+
+/*
+ * mark all wires that are strength from decl. type
+ * know if module in list - will be in output
+ */
+static void mark_sttypewires(void)
+{
+ register int32 syi;
+ register struct mod_t *mdp;
+ register struct net_t *np;
+ register struct sy_t *syp;
+ struct sy_t **syms;
+ struct symtab_t *sytp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   sytp = mdp->msymtab;
+   /* table (array) of nets still not built at this point */
+   for (syi = 0, syms = sytp->stsyms; syi < (int32) sytp->numsyms; syi++)
+    {
+     syp = syms[syi];
+     if (syp->sytyp != SYM_N) continue;
+     np = syp->el.enp;
+
+     /* notice N_TRI is just N_WIRE */
+
+     switch ((byte) np->ntyp) {
+      /* these are always marked strength */
+      case N_TRIREG: case N_TRI0: case N_TRI1: case N_SUPPLY0:
+      case N_SUPPLY1:
+       np->n_stren = TRUE;
+       mdp->mhassts = TRUE;
+       __design_no_strens = FALSE;
+
+       /* --- DBG remove
+       if (__debug_flg)
+        __dbg_msg("++marking direct decl. type wire %s in %s\n", np->nsym->synam,
+         mdp->msym->synam);
+       --- */
+
+       break;
+     }
+    }
+  }
+}
+
+/*
+ * for every module mark wire that are driven by strengths
+ * notice explicit conta output driving strength is treated as no strength
+ * think that may be wrong.
+ */
+static void mark_stdr_wires(void)
+{
+ register int32 gi;
+ register struct mod_t *mdp;
+ register struct conta_t *cap;
+ int32 i, skip_giarr;
+ struct gate_t *gp;
+ struct giarr_t *giap;
+
+ giap = NULL;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (gi = 0; gi < mdp->mgnum; gi++)
+    {
+     gp = &(mdp->mgates[gi]);
+     if (mdp->mgarr != NULL && (giap = mdp->mgarr[gi]) != NULL)
+      skip_giarr = TRUE;
+     else skip_giarr = FALSE;
+
+     switch ((byte) gp->g_class) {
+      case GC_PULL:
+       /* pull all connections */
+       for (i = 0; i < (int32) gp->gpnum; i++)
+        { mark_stwires(mdp, gp->gpins[i]); }
+       break;
+      case GC_MOS: case GC_TRAN: case GC_TRANIF: case GC_CMOS:
+       /* mos or tran gates first 2 ports only - rest are controls */
+       mark_stwires(mdp, gp->gpins[0]);
+       mark_stwires(mdp, gp->gpins[1]);
+       break;
+      case GC_BUFIF:
+       /* buffer only output is strength */
+       mark_stwires(mdp, gp->gpins[0]);
+       break;
+      case GC_LOGIC: case GC_UDP:
+       /* logic only mark output if has strength */
+       if (gp->g_hasst && gp->g_stval != ST_STRVAL)
+        mark_stwires(mdp, gp->gpins[0]);
+       break;
+      }
+     if (skip_giarr) gi += (__get_giarr_wide(giap) - 1);
+    }
+   for (cap = mdp->mcas; cap != NULL; cap = cap->pbcau.canxt)
+    {
+     if (!cap->ca_hasst || cap->ca_stval == ST_STRVAL) continue;
+     /* 1 bit continuous assign not converted to gate at this point */
+     mark_stwires(mdp, cap->lhsx);
+    }
+  }
+}
+
+/*
+ * routine to mark wires in port highconn or lowconn that have wired logic
+ * stren model - needed so will use wire type incremental switch relax proc
+ *
+ * 04/22/01 SJM - changed so wand/wor in inout port hi/low conn always stren
+ */
+static void mark_stdr_inout_wired_logic(void)
+{
+ register int32 ii, pi;
+ register struct mod_t *mdp;
+ int32 pnum;
+ struct mod_pin_t *mpp;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+ struct expr_t *xp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* if inout port and lowconn wor/wand, mark port expr as stren */ 
+   for (pi = 0; pi < mdp->mpnum; pi++)
+    {
+     mpp = &(mdp->mpins[pi]);
+     if (mpp->mptyp != IO_BID) continue;
+
+     if (has_non_stren_wired_net(mpp->mpref))
+      mark_stwires(mdp, mpp->mpref);
+    }
+
+   /* if iconn highconn wor/wand, mark expr as stren */
+   for (ii = 0; ii < mdp->minum; ii++)
+    {
+     ip = &(mdp->minsts[ii]);
+     imdp = ip->imsym->el.emdp;
+     if ((pnum = imdp->mpnum) == 0) continue;
+
+     for (pi = 0; pi < pnum; pi++)
+      {
+       mpp = &(imdp->mpins[pi]);
+       if (mpp->mptyp != IO_BID) continue;
+
+       xp = ip->ipins[pi];
+       if (has_non_stren_wired_net(xp)) mark_stwires(imdp, xp);
+      }
+    }
+  } 
+}
+
+/*
+ * return T if inout (lhs) expr, has wand or wor port
+ */
+static int32 has_non_stren_wired_net(struct expr_t *lhsx)
+{
+ register struct expr_t *catndp;
+ register struct net_t *np;
+
+ switch ((byte) lhsx->optyp) {
+  /* SJM 07/10/01 - if later syntax error non lvalues possible here */
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   break;
+  case ID: case GLBREF:
+   np = lhsx->lu.sy->el.enp;
+   if (net_type_tri(np->ntyp)) return(TRUE);
+   break;
+  case LSB: case PARTSEL:
+   np = lhsx->lu.x->lu.sy->el.enp;
+   if (net_type_tri(np->ntyp)) return(TRUE);
+   break;
+  case LCB:
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x) 
+    {
+     if (has_non_stren_wired_net(catndp->lu.x)) return(TRUE);
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(FALSE); 
+}
+
+/*
+ * return T if net type is wand or wor (wired logic) 
+ */
+static int32 net_type_tri(word32 ntyp)
+{
+ switch ((byte) ntyp) {
+  case N_TRIOR: case N_WO: case N_TRIAND: case N_WA: return(TRUE);
+  default: break;
+ }
+ return(FALSE);
+}
+
+/*
+ * check to see if expr has any stren wires, if yes return T else F 
+ *
+ * SJM 06/01/01 - need separate check routine because must return
+ * T if any concat el has stren but must always set all elements
+ * logic for combined routine was wrong
+ */
+static int32 chk_hasst_wires(struct mod_t *mdp, struct expr_t *lhsx)
+{
+ struct net_t *np;
+
+ switch ((byte) lhsx->optyp) {
+   /* if global has driven strength - all instances of wire must be */
+   /* strength */
+  case GLBREF: case ID:
+   np = lhsx->lu.sy->el.enp;
+   break;
+  case LSB: case PARTSEL:
+   /* this is bit select or array index */
+   np = lhsx->lu.x->lu.sy->el.enp;
+   break;
+  case LCB:
+   {
+    register struct expr_t *ndp2;
+
+    /* know lhs concatenates never nested */
+    for (ndp2 = lhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     {
+      /* if any strength, must other must be marked */
+      if (chk_hasst_wires(mdp, ndp2->lu.x)) return(TRUE);
+     }
+    return(FALSE);
+   }
+  default: return(FALSE);
+ }
+ /* know if non wire, n stren never true */
+ if (np->n_stren) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * for lhs expression driven with strength mark all wires
+ * if not good lhs, ignore error caught later
+ *
+ * SJM 06/01/15 - change so separate mark routine
+ */
+static void mark_stwires(struct mod_t *mdp, struct expr_t *lhsx)
+{
+ struct net_t *np;
+
+ switch ((byte) lhsx->optyp) {
+   /* if global has driven strength - all instances of wire must be */
+   /* strength */
+  case GLBREF: case ID:
+   np = lhsx->lu.sy->el.enp;
+   break;
+  case LSB: case PARTSEL:
+   /* this is bit select or array index */
+   np = lhsx->lu.x->lu.sy->el.enp;
+   break;
+  case LCB:
+   {
+    register struct expr_t *ndp2;
+
+    /* know lhs concatenates never nested */
+    /* mark all - if some els already marked, does nothing */
+    for (ndp2 = lhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     { mark_stwires(mdp, ndp2->lu.x); }
+    return;
+   }
+  default: return;
+ }
+ /* must be wire to have strength */
+ if (np->ntyp >= NONWIRE_ST) return;
+
+ /* SJM 10/15/99 - if mark and already marked, just return T */  
+ if (!np->n_stren)
+  {
+   /* --- DBG remove */
+   if (__debug_flg)
+    __dbg_msg("++marking wire %s in %s\n", np->nsym->synam,
+     mdp->msym->synam);
+   /* --- */
+   np->n_stren = TRUE;
+   __strenprop_chg = TRUE;
+   mdp->mhassts = TRUE;
+   __design_no_strens = FALSE;
+  }
+}
+
+/*
+ * build the levelized module type list 
+ *
+ * this is sometimes called before minsts exists (part of d.s. built)
+ */
+extern void __bld_mlevel_lists(void)
+{
+ register struct mod_t *mdp, *last_mdp;
+ register int32 mlevel;
+
+ /* then build the by level header table and link same level modules on it */
+ if (__mdlevhdr == NULL)
+  {
+   __mdlevhdr = (struct mod_t **)
+    __my_malloc((__dagmaxdist + 1)*sizeof(struct mod_t *)); 
+  }
+ /* need to initialize this to nil since may be rebuilt */
+ for (mlevel = 0; mlevel <= __dagmaxdist; mlevel++) __mdlevhdr[mlevel] = NULL;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt) mdp->mlevnxt = NULL;
+
+ for (mlevel = 0; mlevel <= __dagmaxdist; mlevel++)
+  {
+   last_mdp = NULL;
+   for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+    {
+     if (mdp->mlpcnt != mlevel) continue;
+     if (last_mdp == NULL) __mdlevhdr[mlevel] = mdp;
+     else last_mdp->mlevnxt = mdp;
+     last_mdp = mdp;
+    }
+  }
+}
+
+/*
+ * propagate strengths down
+ *
+ * 04/22/01 - changed so inout port either highconn or lowonn wired and or or
+ * now both marked as strength
+ */
+static void prop_stsdown(void)
+{
+ register int32 pi, ii;
+ register struct mod_t *smdp;
+ /* do all max. dag dist. modules first - level 1 has no insts. */
+ register struct inst_t *ip;
+ int32 mlevel, pnum, skip_giarr;
+ struct mod_pin_t *mpp;
+ struct mod_t *imdp;
+ struct giarr_t *giap;
+ struct expr_t *xp;
+
+ /* could stop one up (level 2 (1 from bottom)) here */
+ giap = NULL;
+ for (mlevel = __dagmaxdist; mlevel >= 0; mlevel--)
+  {
+   for (smdp = __mdlevhdr[mlevel]; smdp != NULL; smdp = smdp->mlevnxt)
+    {
+     /* even if no strength must still try to propagate down for */
+     /* possible unconndrive */
+     for (ii = 0; ii < smdp->minum; ii++)
+      {
+       ip = &(smdp->minsts[ii]);
+       if (smdp->miarr != NULL && (giap = smdp->miarr[ii]) != NULL)
+        skip_giarr = TRUE;
+       else skip_giarr = FALSE;
+
+       imdp = ip->imsym->el.emdp;
+       if ((pnum = imdp->mpnum) == 0) goto nxt_inst;
+
+       for (pi = 0; pi < pnum; pi++)
+        {
+	 mpp = &(imdp->mpins[pi]);
+	 if (mpp->mptyp == IO_OUT) continue;
+
+         xp = ip->ipins[pi];
+         /* --- DBG remove
+         if (__debug_flg)
+          __dbg_msg(
+           "++trying to prop stren down from %s (in %s) to %s (in %s)\n",
+           __msgexpr_tostr(__xs, xp), smdp->msym->synam,
+           __msgexpr_tostr(__xs2, mpp->mpref), imdp->msym->synam);  
+         --- */
+
+         /* if op empty `unconndrive, must propagate st. down */
+         if (xp->optyp == OPEMPTY && xp->unc_pull != NO_UNCPULL) 
+          { mark_stwires(imdp, mpp->mpref); continue; }
+
+	 /* if port inst. port has strength, propagate down */
+         if (chk_hasst_wires(smdp, xp))
+	  { mark_stwires(imdp, mpp->mpref); continue; }
+	}
+nxt_inst:
+       /* AIV 08/23/04 - was hanging should be += */ 
+       if (skip_giarr) ii += (__get_giarr_wide(giap) - 1);
+      }
+    }
+  }
+}
+
+/*
+ * propagate strengths up
+ */
+static void prop_stsup(void)
+{
+ register int32 pi, ii;
+ register struct mod_t *smdp;
+ register struct inst_t *ip;
+ int32 mlevel, pnum, skip_giarr;
+ struct mod_pin_t *mpp;
+ struct mod_t *imdp;
+ struct giarr_t *giap;
+ struct expr_t *xp;
+
+ giap = NULL;
+ /* start up 1 since propagating from one down to current */
+ for (mlevel = 1; mlevel <= __dagmaxdist; mlevel++)
+  {
+   for (smdp = __mdlevhdr[mlevel]; smdp != NULL; smdp = smdp->mlevnxt)
+    {
+     /* go through module instances marking down port wires */
+     for (ii = 0; ii < smdp->minum; ii++)
+      {
+       ip = &(smdp->minsts[ii]);
+       if (smdp->miarr != NULL && (giap = smdp->miarr[ii]) != NULL)
+        skip_giarr = TRUE;
+       else skip_giarr = FALSE;
+        
+       imdp = ip->imsym->el.emdp;
+       if ((pnum = imdp->mpnum) == 0) goto nxt_inst;
+       for (pi = 0; pi < pnum; pi++)
+        {
+         mpp = &(imdp->mpins[pi]);
+         xp = ip->ipins[pi];
+	 if (mpp->mptyp == IO_IN) continue;
+
+         /* --- DBG remove
+         if (__debug_flg)
+          __dbg_msg(
+           "++trying to prop stren up from %s (in %s) to %s (in %s)\n",
+           __msgexpr_tostr(__xs, mpp->mpref), imdp->msym->synam,  
+           __msgexpr_tostr(__xs2, xp), smdp->msym->synam);
+         --- */
+
+	 /* if down port has strength, need to propagate up */
+         if (chk_hasst_wires(imdp, mpp->mpref))
+          mark_stwires(smdp, xp);
+	}
+nxt_inst:
+         if (skip_giarr) ii += (__get_giarr_wide(giap) - 1);
+      }
+    }
+  }
+}
+
+/*
+ * ROUTINES TO CHECK CONSTANT DELAYS (IGNORES DELAY EXPRS)
+ */
+
+/*
+ * check a list of constant delays and convert to scaled non real ticks
+ * return number of delays - -1 on error
+ */
+extern int32 __chk_delparams(struct paramlst_t *pmp2, char *emsg,
+ int32 mustbeconst)
+{
+ register struct paramlst_t *pmp;
+ int32 pmnum, err;
+
+ err = FALSE;
+ for (pmnum = 0, pmp = pmp2; pmp != NULL; pmp = pmp->pmlnxt, pmnum++)
+  {
+   if (!chkdel_expr(pmp->plxndp, emsg, mustbeconst)) err = TRUE;
+   /* make sure actual delay expressions output as dec. */
+   pmp->plxndp->ibase = BDEC;
+   /* param expression evaluted to number during delay prep */  
+  }
+ if (err) return(-1);
+ return(pmnum);
+}
+
+/*
+ * check a delay expression but cannot convert until prep. time
+ * uses flag mustbeconst to cause error if expr. 
+ * returns F on error
+ */
+static int32 chkdel_expr(struct expr_t *dxp, char *emsg,
+ int32 mustbeconst)
+{
+ int32 sav_ecnt;
+
+ sav_ecnt = __pv_err_cnt;
+ __chk_rhsexpr(dxp, 0);
+ if (mustbeconst) return(__chk_numdelay(dxp, emsg));
+ /* case (procedural for now) where delay can be expression */
+ if (sav_ecnt != __pv_err_cnt) return(FALSE); 
+ /* delay expr. always output as decimal */
+ dxp->ibase = BDEC;
+ return(TRUE);
+}
+
+/*
+ * check to make sure a delay is a number
+ * returns F on error 
+ */
+extern int32 __chk_numdelay(struct expr_t *ndp, char *emsg)
+{
+ switch ((byte) ndp->optyp) {
+  case NUMBER: 
+   if (!nd_delnum(ndp, emsg)) return(FALSE);
+   break;
+  case ISNUMBER:
+   if (!nd_delisnum(ndp, emsg)) return(FALSE);
+   break;
+  case REALNUM: case ISREALNUM: return(TRUE);
+  default: 
+   __sgferr(845, "non constant %s delay illegal", emsg); 
+   __free2_xtree(ndp);
+   __init_xnd(ndp);
+
+   /* bad delay must be 0 */
+   ndp->ru.xvi = __alloc_shareable_cval(0, 0, WBITS);
+   ndp->szu.xclen = WBITS;
+   ndp->optyp = NUMBER;
+   return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * check NUMBER delay to make sure convert in prep. section will succeed
+ * catches too wide (non 0) and x/z forms - if expr. converts to 0 const.
+ */
+static int32 nd_delnum(struct expr_t *ndp, char *emsg)
+{
+ int32 err, wlen;
+ word32 *ap, *bp;
+ struct xstk_t *xsp;
+
+ err = FALSE;
+ ap = &(__contab[ndp->ru.xvi]);
+ wlen = wlen_(ndp->szu.xclen);
+ bp = &(ap[wlen]);
+ if (ndp->szu.xclen > TIMEBITS)
+  {
+   if (!vval_is0_(&(ap[2]), ndp->szu.xclen - TIMEBITS) 
+    || !vval_is0_(bp, ndp->szu.xclen))
+    {
+     __force_base = BDEC;
+     __msgexpr_tostr(__xs, ndp);
+     __force_base = BNONE;
+     err = TRUE;
+    }
+   /* always free-alloc */
+   __free2_xtree(ndp);
+   __init_xnd(ndp);
+   /* notice if not a number make into 32 bit x */
+   ndp->optyp = NUMBER;
+   if (err) 
+    {
+     ndp->szu.xclen = WBITS;
+     /* bad delay must be zero */
+     ndp->ru.xvi = __alloc_shareable_cval(0, 0, WBITS);
+     goto wr_msg;
+    }
+
+   /* LOOKATME - time width dependent */
+   ndp->szu.xclen = TIMEBITS;
+   ndp->ru.xvi = __allocfill_cval_new(ap, bp, 2);
+   return(TRUE);
+  }
+ if (ndp->szu.xclen > WBITS)
+  {
+   if (bp[0] != 0L || bp[1] != 0L) 
+    {
+     /* notice on error here just leave as 8 bytes - since non IS form */
+     ndp->szu.xclen = TIMEBITS;
+
+     push_xstk_(xsp, 2*WBITS);
+     memset(xsp->ap, 0, 4*WRDBYTES);
+     ndp->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, 2);
+     __pop_xstk();
+     goto fill_xs;
+    }
+   return(TRUE);
+  }
+ ndp->szu.xclen = WBITS;
+ if (bp[0] == 0L) return(TRUE); 
+ ndp->ru.xvi = __alloc_shareable_cval(0, 0, WBITS);
+
+fill_xs:
+ __force_base = BDEC;
+ __msgexpr_tostr(__xs, ndp);
+ __force_base = BNONE;
+
+wr_msg:
+ __sgferr(848,
+  "%s value %s not required up to %d bit non x/z delay number - set to 0",
+  emsg, __xs, TIMEBITS);
+ return(FALSE);
+}
+
+/*
+ * need an delay up to 64 bit number - same as nd_ndxisnum except 64 bits  
+ * changed in prep - this just checks but if error converts to 0
+ * LOOKATME - should change from TIMEBITS 8 bytes to 4 bytes if all high 0
+ * SIZEDEPENDENT notice this routine has built in 32 bit word32 and 64 bit time
+ *
+ * FIXME - this routine looks wrong or can be improved
+ */
+static int32 nd_delisnum(struct expr_t *ndp, char *emsg)
+{
+ register int32 iti;
+ int32 err, wlen, wsiz;
+ word32 *wp, *wp2, *ap, *bp;
+ 
+ err = FALSE;
+ wlen = wlen_(ndp->szu.xclen);
+ wp = &(__contab[ndp->ru.xvi]);
+ /* case 1: wider than TIMEBITS (64) */
+ if (ndp->szu.xclen > 64)
+  {
+   /* check all high bits if 0 and not z just extract low 8 byte sections */
+   for (iti = 0; iti < __inst_mod->flatinum; iti++)
+    {
+     ap = &(wp[2*wlen*iti]);
+     bp = &(ap[wlen]);
+     if (!vval_is0_(&(ap[2]), ndp->szu.xclen - 64) 
+      || !vval_is0_(bp, ndp->szu.xclen))
+      { wr_ndisdel_err(ndp, iti, emsg); err = TRUE; }
+    }
+   if (err) { freeset_is0del(ndp, __inst_mod->flatinum); return(FALSE); }
+
+   /* convert to TIMEBITS by extracting low 64 a/b bits of each */ 
+   /* this frees subtree under ndp but xva constant field can not be freed */
+   __free2_xtree(ndp);
+   __init_xnd(ndp);
+   ndp->optyp = ISNUMBER;
+   ndp->szu.xclen = TIMEBITS;
+   wsiz = 2*__inst_mod->flatinum; 
+   ndp->ru.xvi = __alloc_is_cval(wsiz);
+   wp2 = &(__contab[ndp->ru.xvi]);
+   for (iti = 0; iti < __inst_mod->flatinum; iti++)
+    {
+     ap = &(wp[2*wlen*iti]);
+     bp = &(ap[wlen]);
+     wp2[4*iti] = ap[0]; wp2[4*iti + 1] = ap[1];
+     wp2[4*iti + 2] = bp[0]; wp2[4*iti + 3] = bp[1];
+    }
+   return(TRUE);
+  }
+ /* case 2 between WBITS and TIMEBITS */
+ if (ndp->szu.xclen > WBITS)
+  {
+   for (iti = 0; iti < __inst_mod->flatinum; iti++)
+    {
+     ap = &(wp[4*iti]);
+     bp = &(ap[2]);
+     if (bp[0] != 0L || bp[1] != 0L)
+      { wr_ndisdel_err(ndp, iti, emsg); err = TRUE; }
+    }
+   /* notice on error here even good instances set to 0 */  
+   if (err) { freeset_is0del(ndp, __inst_mod->flatinum); return(FALSE); }
+   /* this uses fact that constants are always stored as 8 byte chunks */
+   ndp->szu.xclen = 64;
+   return(TRUE);
+  }
+ /* finally case is all WBITS */
+ for (iti = 0; iti < __inst_mod->flatinum; iti++)
+  {
+   ap = &(wp[2*iti]); bp = &(ap[1]);
+   if (bp[0] != 0L)
+    {
+     wr_ndisdel_err(ndp, iti, emsg);
+     ap[0] = bp[0] = 0L; 
+     err = TRUE;
+    }
+  }
+ /* here value left unless x/z in which case converted to 0 */ 
+ ndp->szu.xclen = WBITS;
+ return(!err);
+}
+
+/*
+ * upon error free and set delay expr. to WBITS IS delay 0's
+ *
+ * LOOKATME - this does not free previous constant entry
+ */
+static void freeset_is0del(struct expr_t *ndp, int32 insts)
+{
+ register int32 iti;
+ word32 *wp;
+
+ __free2_xtree(ndp);
+ __init_xnd(ndp);
+ ndp->optyp = ISNUMBER;
+ ndp->szu.xclen = WBITS;
+ ndp->ru.xvi = __alloc_is_cval(1*insts);
+ wp = &(__contab[ndp->ru.xvi]);
+ for (iti = 0; iti < insts; iti++) wp[2*iti] = wp[2*iti + 1] = 0L;
+}
+
+/*
+ * write an is need delay form error message
+ */
+static void wr_ndisdel_err(struct expr_t *ndp, int32 iti, char *emsg)
+{
+ char s1[RECLEN];
+
+ __force_base = BDEC;
+ __sgferr(838,
+  "%s value %s not required up to %d bit non x/z delay number (inst. %d)",
+   emsg, __msgnumexpr_tostr(s1, ndp, iti), TIMEBITS, iti);
+ __force_base = BNONE;
+}
+
+/*
+ * check a wires range and array range
+ */
+static void chk_wire_rng(struct net_t *np)
+{
+ int32 vwid, mwid, ival;
+ word32 *wp;
+ struct expr_t *ndp, *ndp2;
+ char s1[RECLEN]; 
+
+ if (np->n_isavec)
+  {
+   /* this must be a non x/z constant that can be a wire range */
+   /* changes to WBIT vectored form */
+   /* never IS form */ 
+   sprintf(s1, "wire or reg first range of %s", np->nsym->synam);
+   if (!__chkndx_expr(np->nu.ct->nx1, s1))
+    {
+bad_wire:
+     np->n_isavec = FALSE;
+     np->nu.ct->nx1 = np->nu.ct->nx2 = NULL;
+     goto chk_arr;
+    }
+   wp = &(__contab[np->nu.ct->nx1->ru.xvi]);
+   ival = (int32) wp[0];
+   if (ival < 0)
+    {
+     __sgferr(902, "%s value %d illegal negative number", s1, ival);
+     goto bad_wire;
+    }
+   
+   sprintf(s1, "wire or reg second range of %s", np->nsym->synam);
+   if (np->nu.ct->nx2 == NULL || !__chkndx_expr(np->nu.ct->nx2, s1))
+    goto bad_wire;
+
+   wp = &(__contab[np->nu.ct->nx2->ru.xvi]);
+   ival = (int32) wp[0];
+   if (ival < 0)
+    {
+     __sgferr(902, "%s value %d illegal negative number", s1, ival);
+     goto bad_wire;
+    }
+
+   /* know net ranges fit in 32 bits or will not get here */
+   vwid = __get_netwide(np);
+   if (vwid > MAXNUMBITS)
+    {
+     __sgferr(774,
+      "wire or reg %s range width %d too wide (%d)", np->nsym->synam, vwid,
+      MAXNUMBITS);
+     np->n_isavec = FALSE;
+     np->nu.ct->nx1 = np->nu.ct->nx2 = NULL;
+     goto chk_arr;
+    }
+   /* DBG remove */
+   if (np->nu.ct->nx1 == NULL || np->nu.ct->nx2 == NULL) 
+    __misc_terr(__FILE__, __LINE__);  
+   /* -- */
+
+   /* for one pound param case, IS form possible but know all same */
+   /* know only one place in source and only pound params used */
+   /* all of what is seen as IS form same so check and fix here */
+   ndp = np->nu.ct->nx1;
+   ndp2 = np->nu.ct->nx2;
+   if (ndp->optyp == ISNUMBER)
+    {
+     chg_rng_isnum_to_num(np, ndp, "first vector range");
+    }
+   if (ndp2->optyp == ISNUMBER)
+    {
+     chg_rng_isnum_to_num(np, ndp2, "second vector range");
+    }
+   if (ndp->optyp != NUMBER)
+    {
+     __sgfterr(329,
+      "wire or reg %s in module %s impossible first vector range expression %s",
+      np->nsym->synam, __inst_mod->msym->synam, __msgexpr_tostr(__xs, ndp));
+    }
+   if (ndp2->optyp != NUMBER)
+    {
+     __sgfterr(329,
+      "wire or reg %s in module %s impossible second vector range expression %s",
+      np->nsym->synam, __inst_mod->msym->synam, __msgexpr_tostr(__xs, ndp2));
+    }
+  }
+ /* inconsistent scalar range */
+ else if (np->nu.ct->nx1 != NULL || np->nu.ct->nx2 != NULL)
+  __misc_terr(__FILE__, __LINE__);
+
+ /* check array */
+chk_arr:
+ if (np->n_isarr)
+  {
+   sprintf(s1, "array first range of %s", np->nsym->synam);
+   if (!__chkndx_expr(np->nu.ct->ax1, s1))
+    {
+bad_arr:
+     np->n_isarr = FALSE;
+     np->nu.ct->ax1 = np->nu.ct->ax2 = NULL;
+     return;
+    }
+   wp = &(__contab[np->nu.ct->ax1->ru.xvi]);
+   ival = (int32) wp[0];
+   if (ival < 0)
+    {
+     __sgferr(902, "%s value %d illegal negative number", s1, ival);
+     goto bad_arr;
+    }
+   sprintf(s1, "array second range of %s", np->nsym->synam);
+   if (np->nu.ct->ax2 == NULL || !__chkndx_expr(np->nu.ct->ax2, s1))
+    goto bad_arr;
+
+   wp = &(__contab[np->nu.ct->ax2->ru.xvi]);
+   ival = (int32) wp[0];
+   if (ival < 0)
+    {
+     __sgferr(902, "%s value %d illegal negative number", s1, ival);
+     goto bad_arr;
+    }
+
+   /* allowing up to 2*24 cells (SJM 11/13/00 - comment was wrong) */
+   mwid = __get_arrwide(np);
+   if (mwid < 0 || mwid > 0x00ffffff)
+    {
+     __sgfwarn(620,
+      "array %s has %d cells - standard only requires maximum of %d",
+      np->nsym->synam, mwid, 0x00ffffff);
+    }
+   /* DBG remove */
+   if (np->nu.ct->ax1 == NULL || np->nu.ct->ax2 == NULL) 
+    __misc_terr(__FILE__, __LINE__);  
+
+   ndp = np->nu.ct->ax1;
+   ndp2 = np->nu.ct->ax2;
+   if (ndp->optyp == ISNUMBER)
+    {
+     chg_rng_isnum_to_num(np, ndp, "first array range");
+    }
+   if (ndp2->optyp == ISNUMBER)
+    {
+     chg_rng_isnum_to_num(np, ndp2, "second array range");
+    }
+   if (ndp->optyp != NUMBER)
+    {
+     __sgfterr(329,
+      "wire or reg %s in module %s impossible first array range expression %s", 
+      np->nsym->synam, __inst_mod->msym->synam, __msgexpr_tostr(__xs, ndp));
+    }
+   if (ndp2->optyp != NUMBER)
+    {
+     __sgfterr(329,
+      "wire or reg %s in module %s impossible second array range expression %s", 
+      np->nsym->synam, __inst_mod->msym->synam, __msgexpr_tostr(__xs, ndp2));
+    }
+   /* --- */
+  }
+}
+
+/*
+ * convert all same value range that is ISNUMBER to simple NUMBER
+ * i.e. change expr type and check
+ *
+ * know first range element checked and good or will not be called
+ */
+static void chg_rng_isnum_to_num(struct net_t *np, struct expr_t *ndp,
+ char *rngstr)
+{
+ register int32 iti; 
+ int32 wlen;
+ word32 *wp, *wp0, *wp1;
+
+ wlen = wlen_(ndp->szu.xclen);
+ wp = &(__contab[ndp->ru.xvi]);
+ wp0 = &(wp[0]);
+ for (iti = 1; iti < __inst_mod->flatinum; iti++)
+  {
+   wp1 = &(wp[2*wlen*iti]);
+   if (memcmp(wp0, wp1, 2*wlen*WRDBYTES) != 0)
+    {
+     __sgferr(902,
+      "wire or reg %s in %s (inst. %d) %s value %s wrong - should be %s - one source instance pound param problem", 
+      np->nsym->synam, __inst_mod->msym->synam, iti, rngstr,
+      __msgnumexpr_tostr(__xs, ndp, 0), __msgnumexpr_tostr(__xs2, ndp, iti));
+    }
+  }
+ /* even if error change to num - i.e. just use first */
+ /* change to number easy, just use first one for all - first xvi right */
+ /* and all other fields right */
+ ndp->optyp = NUMBER;
+ /* DBG remove --- */
+ if (__debug_flg)
+  {
+   __dbg_msg(
+    "++ %s in %s %s set by pound param to %d converted to number - all insts same\n",
+    np->nsym->synam, __inst_mod->msym->synam, rngstr, wp0[0]);
+  } 
+ /* --- */
+}
+
+/*
+ * routine to check a index style 32 bit non x/z expression
+ * for declaration ranges - other routines for now for other things
+ * caller must pass string for error message describing range type
+ */
+extern int32 __chkndx_expr(struct expr_t *ndp, char *emsg)
+{
+ /* must be 0 context - even though result is always 32 bits */
+ __chk_rhsexpr(ndp, 0);
+ /* even if errors, if number at end good returns T else F */
+ if (!__nd_ndxnum(ndp, emsg, TRUE)) return(FALSE);  
+ return(TRUE);
+}
+
+/*
+ * check task regs
+ * must be done before any statement checking
+ */
+static void chk_taskvars(struct task_t *tskp, int32 tregbasi)
+{
+ register int32 syi, ri;
+ register struct sy_t *syp;
+ register struct net_t *rp;
+ struct sy_t **syms;
+ struct symtab_t *sytp;
+ struct net_t *rtab;
+
+ /* if undefined must emit error */
+ syp = tskp->tsksyp;
+ if (!syp->sydecl)
+  {
+   __gferr(776, syp->syfnam_ind, syp->sylin_cnt,
+    "task or function %s not declared", syp->synam);
+   return;
+  }
+ sytp = tskp->tsksymtab;
+ /* this will also set reg ranges */
+ chk_undef_syms(sytp, tskp->tsktyp);
+ /* parameters (including local) checked before defparam processing */
+
+ if (tskp->trnum == 0) return;
+
+ /* then point to right offset in module wide var table */
+ rtab = &(__inst_mod->mnets[tregbasi]);
+
+ /* must now convert all task regs with ranges to constants */
+ /* possible return range of function will be here */
+ for (ri = 0, syi = 0, syms = sytp->stsyms; syi < (int32) sytp->numsyms; syi++)
+  {
+   syp = syms[syi];
+   if (syp->sytyp != SYM_N) continue;
+   rp = syp->el.enp;
+   /* build list of task variables */
+   if (rp->n_isaparam) continue;
+
+   rtab[ri] = *rp;
+   __my_free((char *) rp, sizeof(struct net_t));
+   rp = &(rtab[ri]);
+   syp->el.enp = rp;
+   ri++;
+
+   /* --- DBG
+   if (__debug_flg)
+    {
+     char s1[ECLEN], s2[RECLEN];
+
+     __dbg_msg("--- module %s task %s linking net %s onto list\n",
+      __inst_mod->msym->synam, tskp->tsksyp->synam, rp->nsym->synam); 
+    }
+   --- */
+
+   /* do not need to save these, never called with previous location */
+   __sfnam_ind = rp->nsym->syfnam_ind;
+   __slin_cnt = rp->nsym->sylin_cnt;
+   chk_wire_rng(rp);
+  }
+ /* still need to point to address of task's reg region in mod table */
+ tskp->tsk_regs = rtab; 
+}
+
+/*
+ * PORT WIDTH SETTING AND CHECKING ROUTINES
+ */
+
+/*
+ * set and check module port widths
+ *
+ * will not get here unless all ports good
+ * requires that all I/O port net widths known - param subst. and const.
+ * evaluation completed.
+ */
+extern void __setchk_mpwidths(void)
+{
+ register int32 pi;
+ register struct mod_pin_t *mpp;
+ struct expr_t *mpx;
+ int32 pnum;
+
+ if ((pnum = __inst_mod->mpnum) == 0) return;
+ __expr_rhs_decl = TRUE;
+ for (pi = 0; pi < pnum; pi++)
+  {
+   mpp = &(__inst_mod->mpins[pi]);
+   /* location here must be port header */
+   __sfnam_ind = __inst_mod->msym->syfnam_ind;
+   __slin_cnt = __inst_mod->msym->sylin_cnt;
+
+   /* as a minimum port must be legal expr. */
+   mpx = mpp->mpref;
+
+   if (mpp->mptyp == IO_OUT) __chk_rhsexpr(mpx, mpp->mpwide);
+   else
+    {
+     __chk_lhsexpr(mpx, LHS_DECL);
+     if (mpp->mptyp == IO_BID) __set_expr_onrhs(mpx);
+    }
+
+   /* updates __pr_wid to right width - on error section width assumed 1 */
+   __pr_wid = 0;
+   /* this does more port expr. checking and sets __pr_wid */
+   chk_prtwidth(mpp->mpref, mpp);
+   mpp->mpwide = __pr_wid;
+  }
+ __expr_rhs_decl = FALSE;
+}
+
+/*
+ * set a port width - previously checked before param values known
+ * pr_wid must be set to 0 before this is called
+ * on error uses a subcomponent port width of 1
+ */
+static int32 chk_prtwidth(struct expr_t *ndp, struct mod_pin_t *mpp)
+{
+ struct sy_t *syp;
+ struct net_t *np;
+
+ switch ((byte) ndp->optyp) {
+  case ID:
+   np = ndp->lu.sy->el.enp;
+   __pr_wid += ndp->szu.xclen;
+   break;
+  case LSB:
+   syp = ndp->lu.x->lu.sy;
+   np = syp->el.enp;
+   if (ndp->ru.x->optyp != NUMBER && ndp->ru.x->optyp != ISNUMBER)
+    {
+     __gferr(778, mpp->mpfnam_ind, mpp->mplin_cnt,
+      "module declaration port %s bit select index must be constant",
+      np->nsym->synam);
+    }
+   __pr_wid++;
+   break;
+  case PARTSEL:
+   syp = ndp->lu.x->lu.sy;
+   np = syp->el.enp;
+   __pr_wid += ndp->szu.xclen;
+   break;
+  case LCB:
+   /* notice legal port ref. expr. are always width self determined */
+   {
+    register struct expr_t *ndp2;
+
+    /* notice concatenate syntax already checked */
+    for (ndp2 = ndp->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     {
+      if (!chk_prtwidth(ndp2->lu.x, mpp)) return(FALSE);
+     }
+   }
+   return(TRUE);
+  case OPEMPTY:
+   __pr_wid += 1;
+   return(TRUE);
+  default:
+   __gferr(779, mpp->mpfnam_ind, mpp->mplin_cnt,
+    "%s illegal in module header list of ports", __msgexpr_tostr(__xs, ndp));
+   __pr_wid++;
+   return(FALSE);
+ }
+ /* because of P1364 tran channel channel inout algorithm */ 
+ /* inout ports can not be delayed wires */
+ if (np->iotyp == IO_BID && np->nu.ct->n_dels_u.pdels != NULL)
+  {
+   __sgferr(728,
+    "illegal for inout port %s to have wire delay - incompatible with P1364 tran model",
+    np->nsym->synam);
+  }
+ return(TRUE);
+}
+
+/*
+ * check shorted inouts for current module
+ * notice this must be called only after port widths known
+ */
+extern void __chk_shorted_bids(void)
+{
+ register int32 pi;
+ int32 pnum, has_shorted;
+ struct mod_pin_t *mpp;
+
+ if ((pnum = __inst_mod->mpnum) == 0) return;
+ for (has_shorted = FALSE, pi = 0; pi < pnum; pi++)
+  {
+   mpp = &(__inst_mod->mpins[pi]);
+   /* this uses previously counted number of connected ports */
+   if (!xhas_multconn_wire(mpp->mpref)) continue;
+
+   /* emit inform for shorted that are not inouts */
+   if (mpp->mptyp != IO_BID) emit_nonbid_shortwarn(mpp, mpp->mpref);
+   mpp->mp_jmpered = TRUE;
+   has_shorted = TRUE;
+  }
+ /* also emit informs for inouts */
+ if (has_shorted) emit_shorted_informs(pnum);
+}
+
+/*
+ * emit informs for all shorted ports - ok but good to know about
+ */
+static void emit_shorted_informs(int32 pnum)
+{
+ register int32 pi;
+ register struct expr_t *xp2;
+ struct mod_pin_t *mpp;
+ struct expr_t *xp, *xp3; 
+ struct net_t *np;
+
+ for (pi = 0; pi < pnum; pi++)
+  {
+   mpp = &(__inst_mod->mpins[pi]);
+   /* if previous error will not appear as jumpered */
+   if (!mpp->mp_jmpered) continue;
+   xp = mpp->mpref;
+   switch ((byte) xp->optyp) { 
+    case ID: np = xp->lu.sy->el.enp; break;
+    case LSB: case PARTSEL: np = xp->lu.x->lu.sy->el.enp; break;
+    case LCB:
+     for (xp2 = xp->ru.x; xp2 != NULL; xp2 = xp2->ru.x)
+      { 
+       xp3 = xp2->lu.x;
+       switch((byte) xp3->optyp) {  
+        case ID: np = xp3->lu.sy->el.enp; break;
+        case LSB: case PARTSEL: np = xp3->lu.x->lu.sy->el.enp; break;
+        default: continue;
+       }
+       emit_1net_shorted_informs(mpp, pi, np, pnum);
+      }
+     continue;
+    default: continue;
+   }
+   emit_1net_shorted_informs(mpp, pi, np, pnum);
+  }
+}
+
+/*
+ * emit the shorted port informs for 1 net 
+ */
+static void emit_1net_shorted_informs(struct mod_pin_t *mpp,
+ int32 pi, struct net_t *np, int32 pnum)
+{
+ register int32 pi2;
+ struct mod_pin_t *mpp2;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ /* have jumpered into not in any equiv. class - it is master */
+ for (pi2 = pi + 1; pi2 < pnum; pi2++) 
+  {
+   mpp2 = &(__inst_mod->mpins[pi2]);
+   /* if not jumpered to anything no need to check */
+   if (!mpp2->mp_jmpered) continue;
+   if (!net_in_expr(np, mpp2->mpref)) continue;
+
+   __gfinform(454, mpp2->mpfnam_ind, mpp2->mplin_cnt,
+    "%s %s in %s port %s also referenced in port %s at %s (shorted together)",
+    __to_wtnam(s1, np), np->nsym->synam, __to_ptnam(s2, mpp2->mptyp),
+    __to_mpnam(s3, mpp2->mpsnam), __to_mpnam(__xs2, mpp->mpsnam),
+    __bld_lineloc(__xs, mpp->mpfnam_ind, mpp->mplin_cnt));
+   }
+}
+
+/*
+ * return T if net np is expr xp
+ * return F for non lhs expr.
+ */
+static int32 net_in_expr(struct net_t *np, struct expr_t *xp)
+{
+ register struct expr_t *xp2;
+ struct net_t *np2;
+
+ switch ((byte) xp->optyp) { 
+  case ID:
+   np2 = xp->lu.sy->el.enp;
+   break;
+  case LSB: case PARTSEL:
+   np2 = xp->lu.x->lu.sy->el.enp;
+   break;
+  case LCB:
+   for (xp2 = xp->ru.x; xp2 != NULL; xp2 = xp2->ru.x)
+    { if (net_in_expr(np, xp2->lu.x)) return(TRUE); }
+   return(FALSE);
+  /* if non lhs expr (error elsewhere , just return F */
+  default: return(FALSE);
+ }
+ return(np == np2);
+}
+
+/*
+ * return T if port contains wire that connects to other port
+ * notice only called for ports and not called from interactive
+ * also even though not checked here if inotu shorted must be wire name
+ */
+static int32 xhas_multconn_wire(struct expr_t *ndp)
+{
+ struct expr_t *ndp2;
+ struct net_t *np;
+
+ switch ((byte) ndp->optyp) {
+  case ID:
+   np = ndp->lu.sy->el.enp;
+chk_mult:
+   if (np->nu.ct->num_prtconns == 2) return(TRUE);
+   break;
+  case PARTSEL: case LSB:
+   np = ndp->lu.x->lu.sy->el.enp;
+   goto chk_mult; 
+  case LCB:
+   for (ndp2 = ndp->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+    { if (xhas_multconn_wire(ndp2->lu.x)) return(TRUE); }
+   break;
+  case OPEMPTY: break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(FALSE);
+}
+
+/*
+ * emit warn for shorted together feed thru ports that are not inouts
+ */
+static void emit_nonbid_shortwarn(struct mod_pin_t *mpp,
+ struct expr_t *ndp)
+{
+ struct expr_t *ndp2;
+ struct net_t *np;
+ char s1[RECLEN], s2[RECLEN];
+
+ switch ((byte) ndp->optyp) {
+  case ID:
+   np = ndp->lu.sy->el.enp;
+chk_mult:
+   if (np->iotyp != IO_BID)
+    {  
+     __gfinform(476, mpp->mpfnam_ind, mpp->mplin_cnt,
+      "%s port %s %s %s used in merged or shorted ports - if ranges overlap probably wrong",
+      __to_ptnam(s2, np->iotyp), __to_mpnam(s1, mpp->mpsnam),
+      __to_wtnam(__xs, np), np->nsym->synam);
+    }
+   break;
+  case PARTSEL: case LSB:
+   np = ndp->lu.x->lu.sy->el.enp;
+   goto chk_mult; 
+  case LCB:
+   for (ndp2 = ndp->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+    emit_nonbid_shortwarn(mpp, ndp2->lu.x);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * ROUTINES TO RECONNECT SCALAR GATES/INSTS PIN LISTS
+ */
+
+/*
+ * reconnect and check gates and instances according to LRM rules 
+ */
+extern void __reconn_gia_pins(void)
+{
+ register struct mod_t *mdp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   if (mdp->mgarr != NULL) reconn_1mod_gateterms(mdp);
+   if (mdp->miarr != NULL) reconn_1mod_instports(mdp);
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * reconnect array of gates ports for one module  
+ * new expression put in each expanded bit of gate original free for each term
+ * 
+ * know module has at least one arrayed gates or not called
+ */
+static void reconn_1mod_gateterms(struct mod_t *mdp)
+{
+ register int32 gi, pi, gi2;
+ int32 giawid, bi, wid, r0;
+ word32 av, bv, *wp;
+ struct giarr_t *giap;
+ struct gate_t *gp, *gp2;
+ struct expr_t *xp;
+ struct net_t *np;
+ struct xstk_t *xsp;
+
+ for (gi = 0; gi < mdp->mgnum;)
+  {
+   if ((giap = mdp->mgarr[gi]) == NULL) { gi++; continue; }
+
+   gp = &(mdp->mgates[gi]);
+   giawid = __get_giarr_wide(giap);
+   /* DBG remove -- */
+   if (giap->gia_bi != gi) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   /* for checking each gate has original entire array terms */
+   /* allocate new tab of expr ptrs for each independent of how connected */
+   for (gi2 = giap->gia_bi; gi2 < giap->gia_bi + giawid; gi2++)
+    {
+     gp2 = &(mdp->mgates[gi2]);          
+     gp2->gpins = (struct expr_t **)
+      __my_malloc(gp->gpnum*sizeof(struct expr_t *));
+    }
+
+   /* handle each pin (terminal) in turn */ 
+   for (pi = 0; pi < gp->gpnum; pi++)
+    {
+     xp = giap->giapins[pi];
+     /* notice 0 context in case need to apportion */
+     __chk_rhsexpr(xp, 0);
+
+     /* FIXME - should allow global here? */
+     if (__expr_has_glb(xp)) goto bad_conn_expr;
+
+     if (xp->szu.xclen == 1)
+      {
+       /* exact copy expressions, this can be any expr. */
+       for (gi2 = giap->gia_bi; gi2 < giap->gia_bi + giawid; gi2++)
+        {
+         gp2 = &(mdp->mgates[gi2]);          
+         gp2->gpins[pi] = __copy_expr(xp);
+        }
+      }
+     else if (xp->szu.xclen == giawid)
+      {
+       /* hard apportioning case - know now width 1 and matches */
+       /* only variable, part select, concat, or constant possible */
+       switch ((byte) xp->optyp) {
+        case ID:
+         np = xp->lu.sy->el.enp;
+         if (np->n_isarr)
+          {
+           __gferr(699, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+           "arrayed %s gate %s terminal %d array %s illegal - not selectable",
+            gp->gmsym->synam, giap->gia_base_syp->synam, pi + 1,
+            __msgexpr_tostr(__xs, xp));
+           goto make_unc;
+          } 
+         /* build bsel expression - apportion bits h to l from wire */
+         /* array of gates may be stored either way but first (h) from wire */
+         /* always gets first of array */
+         gi2 = giap->gia_bi;
+         wid = __get_netwide(np);
+         for (bi = wid - 1; gi2 < giap->gia_bi + giawid; gi2++, bi--)
+          {
+           gp2 = &(mdp->mgates[gi2]);          
+           gp2->gpins[pi] = bld_bsel_expr(np, bi);
+          }
+         break;
+        case PARTSEL:
+         /* for part select know internal wire h:l - generating bit selects */
+         /* normalized to it and h bit connects to first, etc */ 
+         wp = &(__contab[xp->ru.x->lu.x->ru.xvi]);
+         r0 = (int32) wp[0];
+
+         gi2 = giap->gia_bi;
+         for (bi = r0; gi2 < giap->gia_bi + giawid; gi2++, bi--)
+          {
+           gp2 = &(mdp->mgates[gi2]);          
+           gp2->gpins[pi] = bld_bsel_expr(xp->lu.sy->el.enp, bi);
+          }
+         break;
+        case LCB:
+         /* easy gate case - peels off 1 bit things from concat */
+         /* concats always h:0 */
+         if (!legal_giarr_conn_concat(xp))
+          {
+           __gferr(699, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+            "arrayed %s gate %s terminal %d concatenate %s illegal - contains non selectable lvalue",
+            gp->gmsym->synam, giap->gia_base_syp->synam, pi + 1,
+            __msgexpr_tostr(__xs, xp));
+           goto make_unc;
+          }
+         conn_1gateterm_concat(mdp, giap, xp, pi);
+         break;
+        case NUMBER:
+         xsp = __eval_xpr(xp);
+
+         /* DBG remove -- */
+         if (xsp->xslen != giawid) __misc_terr(__FILE__, __LINE__);
+         /* --- */
+         /* numbers always h:0 with low bit numbered 0 */
+         bi = xsp->xslen - 1;
+         for (gi2 = giap->gia_bi; gi2 < giap->gia_bi + giawid; gi2++, bi--)
+          {
+           av = rhsbsel_(xsp->ap, bi);
+           bv = rhsbsel_(xsp->bp, bi);
+           gp2 = &(mdp->mgates[gi2]);          
+           gp2->gpins[pi] = __bld_rng_numxpr(av, bv, 1);
+           gp2->gpins[pi]->ibase = BDEC;
+          }
+         __pop_xstk();
+         break;
+        case ISNUMBER:
+         /* must never see this means incorrect splitting somewhere */
+         __misc_terr(__FILE__, __LINE__);
+         break;
+        default:
+          __gferr(699, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+           "arrayed %s gate %s terminal %d expression %s illegal - not var, select, concat or number", 
+          gp->gmsym->synam, giap->gia_base_syp->synam, pi + 1,
+          __msgexpr_tostr(__xs, xp));
+          goto make_unc;
+        } 
+      }
+     else
+      {
+bad_conn_expr:
+       /* error width mis-match */
+       __gferr(698, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+        "arrayed %s gate %s terminal %d connection width %d illegal - must be 1 or %d",
+        gp->gmsym->synam, giap->gia_base_syp->synam, pi + 1, xp->szu.xclen,
+        giawid);
+       /* make each unc. */
+make_unc:
+       for (gi2 = giap->gia_bi; gi2 < giap->gia_bi + giawid; gi2++)
+        {
+         gp2 = &(mdp->mgates[gi2]);          
+         __bld_unc_expr();
+         gp2->gpins[pi] = __root_ndp;
+        }
+      } 
+    }
+   gi += giawid;
+  }
+}
+
+/*
+ * routine to build a constant bit select expression
+ *
+ * passed ndx is h:0 normalized form because later expr. checking will assume
+ * value is what appeared in source, must unnormalize to what is in
+ * source so will get normalized later during expr. check then output 
+ * will reconvert to source - neede so caller can work only with internal h:0 
+ */
+static struct expr_t *bld_bsel_expr(struct net_t *np, int32 ndx)
+{
+ int32 ndx2;
+ struct expr_t *xp, *xpid, *xpndx;
+
+ xpid = __alloc_newxnd();
+ xpid->optyp = ID; 
+ xpid->lu.sy = np->nsym;
+ xpid->szu.xclen = __get_netwide(np);
+
+ ndx2 = __unnormalize_ndx(np, ndx); 
+ xpndx = __bld_rng_numxpr((word32) ndx2, 0L, WBITS);
+ xpndx->ibase = BDEC;
+ if (ndx != ndx2) xpndx->ind_noth0 = TRUE;
+
+ /* root of part select */
+ xp = __alloc_newxnd();
+ xp->optyp = LSB;
+ xp->szu.xclen = 1;
+
+ xp->lu.x = xpid;
+ xp->ru.x = xpndx;
+ return(xp);
+}
+
+/*
+ * connect arrayed gate terms from a concat for one gate term (know 1 bit)
+ *
+ * notice here loop is through gate concat expression - peels off bits 1 by 1
+ * and moved through instances
+ */
+static void conn_1gateterm_concat(struct mod_t *mdp, struct giarr_t *giap,
+ struct expr_t *catxp, int32 pi)
+{
+ register int32 gi2, bi;
+ register struct expr_t *xp2, *xp3;
+ int32 r0, r1, nwid;
+ word32 av, bv;
+ struct gate_t *gp;
+ struct net_t *np;
+ struct xstk_t *xsp;
+
+ gi2 = giap->gia_bi;
+ for (xp2 = catxp->ru.x; xp2 != NULL; xp2 = xp2->ru.x)
+  {
+   xp3 = xp2->lu.x;
+   switch ((byte) xp3->optyp) {
+    case ID:
+     np = xp3->lu.sy->el.enp;
+     nwid = __get_netwide(np);
+     if (np->n_isavec)
+      {
+       for (bi = nwid - 1; bi >= 0; gi2++, bi--)
+        {
+         gp = &(mdp->mgates[gi2]);          
+         gp->gpins[pi] = bld_bsel_expr(np, bi);
+        }
+      }
+     /* SJM 07/08/00 - if scalar in concatenate can't convert ot bsel */
+     else
+      {
+       gp = &(mdp->mgates[gi2]);          
+       gp->gpins[pi] = __copy_expr(xp3);
+       gi2++;
+      }
+     break;
+    case LSB:
+     gp = &(mdp->mgates[gi2]);
+     gp->gpins[pi] = __copy_expr(xp3);
+     gi2++;
+     break;
+    case PARTSEL:
+     /* constants here normalized h:0 and need to apportion in that order */ 
+     r0 = __contab[xp3->ru.x->lu.x->ru.xvi];
+     r1 = __contab[xp3->ru.x->ru.x->ru.xvi];
+     /* SJM 04/13/04 - since psel must get net from left ID of psel */
+     np = xp3->lu.x->lu.sy->el.enp;
+     for (bi = r0; bi >= r1; gi2++, bi--)
+      {
+       gp = &(mdp->mgates[gi2]);          
+       gp->gpins[pi] = bld_bsel_expr(np, bi);
+      }
+     break;
+    case NUMBER:
+     xsp = __eval_xpr(xp3);
+
+     /* numbers always h:0 with low bit numbered 0 */
+     bi = xsp->xslen - 1;
+     for (bi = xsp->xslen - 1; bi >= 0; gi2++, bi--)
+      {
+       av = rhsbsel_(xsp->ap, bi);
+       bv = rhsbsel_(xsp->bp, bi);
+       gp = &(mdp->mgates[gi2]);          
+       gp->gpins[pi] = __bld_rng_numxpr(av, bv, 1);
+       gp->gpins[pi]->ibase = BDEC;
+      }
+     __pop_xstk(); 
+     break;
+    default: __case_terr(__FILE__, __LINE__);  
+   }
+  }
+} 
+
+/*
+ * check concat connected to gate/inst - only IDs, selects, and num 
+ *
+ * nested concatenate illegal (maybe never can see by here)
+ */
+static int32 legal_giarr_conn_concat(struct expr_t *xp)
+{
+ register struct expr_t *xp2;
+ struct net_t *np;
+
+ for (xp2 = xp->ru.x; xp2 != NULL; xp2 = xp2->ru.x)
+  {
+   switch ((byte) xp2->lu.x->optyp) {
+    case ID:
+     np = xp2->lu.x->lu.sy->el.enp;
+     /* array illegal if apportioning because can not be selected from */
+     if (np->n_isarr) return(FALSE);
+     break;
+    case LSB: case PARTSEL: case NUMBER:
+     break;
+    default: return(FALSE);
+   }
+  } 
+ return(TRUE);
+}
+
+/*
+ * reconnect array of instances ports for one module  
+ * new expression put in each expanded bit of gate original free for each term
+ * 
+ * know module has at least arrayed instances or not called
+ */
+static void reconn_1mod_instports(struct mod_t *mdp)
+{
+ register int32 ii, pi, ii2;
+ register struct mod_pin_t *mpp;
+ int32 giawid, bi, nwlen, wid, r0;
+ struct giarr_t *giap;
+ struct mod_t *imdp;
+ struct inst_t *ip, *ip2;
+ struct expr_t *xp, *xp2;
+ struct xstk_t *xsp, *xsp2;
+ struct net_t *np;
+
+ for (ii = 0; ii < mdp->minum;)
+  {
+   if ((giap = mdp->miarr[ii]) == NULL) { ii++; continue; }
+
+   giawid = __get_giarr_wide(giap);
+   ip = &(mdp->minsts[ii]);
+   imdp = ip->imsym->el.emdp;
+
+   /* DBG remove -- */
+   if (giap->gia_bi != ii) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* for checking each inst. has original array inst pins */
+   /* allocate new tab of expr ptrs for each independent of how connected */
+   for (ii2 = giap->gia_bi; ii2 < giap->gia_bi + giawid; ii2++)
+    {
+     ip2 = &(mdp->minsts[ii2]);          
+     /* SJM 10/17/99 - empty pin list possible */
+     if (imdp->mpnum == 0) ip2->ipins = NULL;
+     else
+      {
+       ip2->ipins = (struct expr_t **)
+        __my_malloc(imdp->mpnum*sizeof(struct expr_t *));
+      }
+    }
+
+   /* handle each pin (terminal) in turn */ 
+   for (pi = 0; pi < imdp->mpnum; pi++)
+    {
+     xp = giap->giapins[pi];
+     mpp = &(imdp->mpins[pi]);
+     /* notice 0 context in case need to apportion */
+     __chk_rhsexpr(xp, 0);
+
+     /* FIXME - should allow global here? */
+     if (__expr_has_glb(xp)) goto bad_conn_expr;
+     if (xp->szu.xclen == mpp->mpwide)
+      {
+       /* exact match copy expression, any expr. allowed */
+       for (ii2 = giap->gia_bi; ii2 < giap->gia_bi + giawid; ii2++)
+        {
+         ip2 = &(mdp->minsts[ii2]);          
+         ip2->ipins[pi] = __copy_expr(xp);
+        }
+      }
+     /* port width times array of insts size exactly matches expr size */
+     else if (xp->szu.xclen == giawid*mpp->mpwide)
+      {
+       /* hard apportioning case */
+       /* only variable, part select, or constant possible */
+       switch ((byte) xp->optyp) {
+        case ID:
+         np = xp->lu.sy->el.enp;
+         if (np->n_isarr)
+          {
+           __gferr(699, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+            "arrayed %s instance %s port %d array %s illegal - not selectable",
+            ip->imsym->synam, giap->gia_base_syp->synam, pi + 1,
+            __msgexpr_tostr(__xs, xp));
+           goto make_unc;
+          } 
+         wid = __get_netwide(np);
+ 
+         /* build bsel (for scalar ports) or psel expression */
+         /* 2 cases - port width 1 bit or port width >1 bits */
+         if (mpp->mpwide == 1)
+          {
+           /* build bsel expression - apportion bits h to l from wire */
+           ii2 = giap->gia_bi;
+           for (bi = wid - 1; ii2 < giap->gia_bi + giawid; ii2++, bi--)
+            {
+             ip2 = &(mdp->minsts[ii2]);          
+             ip2->ipins[pi] = bld_bsel_expr(np, bi);
+            }
+          }
+         else
+          {
+           bi = wid - 1;
+           ii2 = giap->gia_bi;
+           for (; ii2 < giap->gia_bi + giawid; ii2++, bi -= mpp->mpwide)
+            {
+             ip2 = &(mdp->minsts[ii2]);          
+             /* build internal h:0 - on output would get unnormalized */
+             ip2->ipins[pi] = bld_psel_expr(np, bi, bi - mpp->mpwide + 1);
+            }
+          } 
+         break; 
+        case PARTSEL:
+         /* values normalized to h:0 wire during expr check */
+         r0 = __contab[xp->ru.x->lu.x->ru.xvi];
+         np = xp->lu.x->lu.sy->el.enp;
+         if (mpp->mpwide == 1)
+          {
+           /* SJM 04/13/04 - core dumped because for loop one too many */
+           /* scalar port */
+           ii2 = giap->gia_bi;
+           bi = r0;
+           for (; ii2 < giap->gia_bi + giawid; ii2++, bi--)
+            {
+             ip2 = &(mdp->minsts[ii2]);          
+             ip2->ipins[pi] = bld_bsel_expr(np, bi);
+            }
+          }
+         else
+          {
+           /* vector port */
+           bi = r0;
+           for (ii2 = giap->gia_bi; ii2 < giap->gia_bi + giawid; ii2++,
+            bi -= mpp->mpwide)
+            {
+             ip2 = &(mdp->minsts[ii2]);          
+             ip2->ipins[pi] = bld_psel_expr(np, bi, bi - mpp->mpwide + 1);
+            }
+          }
+         break;
+        case LCB:
+         /* easy gate case - peels off 1 bit things from concat */
+         /* concats always h:0 */
+         if (!legal_giarr_conn_concat(xp))
+          {
+           __gferr(699, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+            "arrayed %s instance %s port %d concatenate %s illegal - contains non selectable lvalue",
+            ip->imsym->synam, giap->gia_base_syp->synam, pi + 1,
+            __msgexpr_tostr(__xs, xp));
+           goto make_unc;
+          }
+         conn_1instport_concat(mdp, giap, xp, pi, mpp->mpwide);
+         break;
+        case NUMBER:
+         __push_wrkitstk(mdp, 0);
+         xsp = __eval_xpr(xp);
+         __pop_wrkitstk();
+         push_xstk_(xsp2, mpp->mpwide); 
+
+         bi = xsp->xslen - 1;
+         for (ii2 = giap->gia_bi; ii2 < giap->gia_bi + giawid;
+          ii2++, bi -= mpp->mpwide)
+          {
+           /* could improve scalar case by using rhs bsel but this works */
+           __rhspsel(xsp2->ap, xsp->ap, bi, mpp->mpwide);
+           __rhspsel(xsp2->bp, xsp->bp, bi, mpp->mpwide);
+
+           /* must allocate and fill because may be wider than WBITS */
+           xp2 = __alloc_newxnd();
+           xp2->optyp = NUMBER;
+           nwlen = wlen_(mpp->mpwide); 
+           if (mpp->mpwide <= WBITS)
+            {
+             xp2->ru.xvi = __alloc_shareable_cval(xsp2->ap[0], xsp2->ap[1],
+              mpp->mpwide);
+            }
+           else
+            {
+             /* each a and b part of constants fits in integral no. words */
+             xp2->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, nwlen);
+            }
+           xp2->szu.xclen = mpp->mpwide;
+
+           ip2 = &(mdp->minsts[ii2]);          
+           ip2->ipins[pi] = xp2;
+          }
+         __pop_xstk(); 
+         __pop_xstk();
+         break;
+        case ISNUMBER:
+         /* if this is seen bad splitting somewhere */ 
+         __misc_terr(__FILE__, __LINE__);
+         break;
+        default:
+         __gferr(699, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+          "arrayed %s instance %s port %d expression %s illegal - must be var, select, concat, or number", 
+          ip->imsym->synam, giap->gia_base_syp->synam, pi + 1,
+          __msgexpr_tostr(__xs, xp));
+         goto make_unc;
+        } 
+      }
+     else
+      {
+bad_conn_expr:
+       /* error width mis-match */
+       __gferr(698, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+        "arrayed %s instance %s port %d connection width %d illegal - must be %d or %d",
+        ip->imsym->synam, giap->gia_base_syp->synam, pi + 1, xp->szu.xclen,
+        mpp->mpwide, mpp->mpwide*giawid);
+ 
+       /* make each unc. */
+make_unc:
+       for (ii2 = giap->gia_bi; ii2 < giap->gia_bi + giawid; ii2++)
+        {
+         ip2 = &(mdp->minsts[ii2]);          
+         __bld_unc_expr();
+         ip2->ipins[pi] = __root_ndp;
+        }
+      } 
+    }
+   ii += giawid;
+  }
+}
+
+/*
+ * routine to build a constant part select expression
+ *
+ * passed i1/i2 are h:0 normalized form because later expr. check will assume
+ * value is what appeared in source, must actually normalize to what is in
+ * source so will get unnormalized later during expr. check then output 
+ * will reconvert to source - neede so caller can work only with internal h:0 
+ */
+static struct expr_t *bld_psel_expr(struct net_t *np, int32 i1, int32 i2)
+{
+ int32 ndx1, ndx2;
+ struct expr_t *xp, *xpid, *xp1, *xp2, *xpcol;
+
+ xpid = __alloc_newxnd();
+ xpid->optyp = ID; 
+ xpid->szu.xclen = __get_netwide(np);
+ xpid->lu.sy = np->nsym;
+
+ ndx1 = __unnormalize_ndx(np, i1); 
+ xp1 = __bld_rng_numxpr((word32) ndx1, 0L, WBITS);
+ xp1->ibase = BDEC;
+ if (i1 != ndx1) xp1->ind_noth0 = TRUE;
+
+ ndx2 = __unnormalize_ndx(np, i2); 
+ xp2 = __bld_rng_numxpr((word32) ndx2, 0L, WBITS);
+ xp2->ibase = BDEC;
+ if (i2 != ndx2) xp1->ind_noth0 = TRUE;
+
+ /* root of part select */
+ xp = __alloc_newxnd();
+ xp->optyp = PARTSEL;
+ xp->szu.xclen = i1 - i2 + 1;
+ xp->lu.x = xpid;
+ xpcol = __alloc_newxnd();
+ xpcol->optyp = COLON;
+ xp->ru.x = xpcol;
+ xpcol->lu.x = xp1;
+ xpcol->ru.x = xp2;
+ return(xp);
+}
+
+/*
+ * connect arrayed inst port highconns from a concat for one non scalar port
+ *
+ * know width of concat is mpwid*(num insts)
+ * tricky because may need to build new concats when concat exprs overlap
+ * by here know all concatenates converted to one level
+ *
+ * concat width exactly matches width times inst array size (can't fail)
+ * concat components already checked 
+ */
+static void conn_1instport_concat(struct mod_t *mdp, struct giarr_t *giap,
+ struct expr_t *catxp, int32 pi, int32 mpwid)
+{
+ register int32 ii2;
+ register struct exprlst_t *xplp;
+ int32 giawid, gi1, cwidmore;
+ struct exprlst_t *xplphd, *last_xplp;
+ struct expr_t *xp2, *catxp2, *last_catxp;
+ struct inst_t *ip;
+
+ giawid = __get_giarr_wide(giap);
+ gi1 = giap->gia_bi + giawid;
+ /* this copies elements into list - need to leave concat since part of */
+ /* original expr that stays in giap */
+ xplphd = splt_icat_align_xlist(catxp, mpwid);
+ xplp = xplphd;
+ for (ii2 = giap->gia_bi; ii2 < gi1; ii2++)
+  {
+   ip = &(mdp->minsts[ii2]);          
+   /* cat element can never be too wide */
+   /* DBG remove --- */
+   if (xplp->xp->szu.xclen > mpwid) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* case 1: element of concat exactly matches one inst port width */ 
+   if (xplp->xp->szu.xclen == mpwid) 
+    {
+     ip->ipins[pi] = xplp->xp;
+     xplp = xplp->xpnxt;
+     continue;
+    }
+   /* case 2: concatenate combined from elements of array concat needed */
+   catxp2 = __alloc_newxnd();
+   catxp2->optyp = LCB; 
+   catxp2->szu.xclen = mpwid;
+   cwidmore = mpwid;
+   for (last_catxp = NULL;;)
+    {
+     xp2 = __alloc_newxnd();
+     xp2->optyp = CATCOM;
+     if (last_catxp == NULL) catxp2->ru.x = xp2; else last_catxp->ru.x = xp2;
+     last_catxp = xp2;
+
+     /* CAT COM len is distant from high bit to low bit (right end) */ 
+     xp2->szu.xclen = cwidmore;
+     xp2->lu.x = xplp->xp;
+     cwidmore -= xp2->lu.x->szu.xclen;
+     if (cwidmore == 0) break;
+     xplp = xplp->xpnxt;
+     /* DBG remove --- */
+     if (xplp == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+    }
+   ip->ipins[pi] = catxp2;
+   xplp = xplp->xpnxt;
+  }
+ /* DBG remove --- */
+ if (xplp != NULL) __misc_terr(__FILE__, __LINE__); 
+ /* --- */
+ /* need to free concat expr list (but not expressions that are used) */
+ for (xplp = xplphd; xplp != NULL;)
+  {
+   last_xplp = xplp->xpnxt;
+   __my_free((char *) xplp, sizeof(struct exprlst_t));
+   xplp = last_xplp;
+  }
+}
+   
+/*
+ * build expression list with any overlaps eliminated
+ *
+ * when done all expressions copied (so can just conn to insts) and
+ * never overlaps (may need to build concats but never a need to split)
+ */
+static struct exprlst_t *splt_icat_align_xlist(struct expr_t *catxp, int32 mpwid)
+{
+ register struct expr_t *xp2, *xp3;
+ int32 prtbi, cxlen, r1, endlen, overlaplen;
+ word32 *wp;
+ struct exprlst_t *xplphd, *xplp, *xplp_last;
+ struct net_t *np;
+ struct xstk_t *xsp, *xsp2;
+
+ xsp = NULL;
+ xplphd = xplp_last = NULL;
+ /* work one by one thru elements of concatenate */
+ for (prtbi = 0, xp2 = catxp->ru.x; xp2 != NULL; xp2 = xp2->ru.x)
+  {
+   xp3 = xp2->lu.x;
+   cxlen = xp3->szu.xclen;
+   /* case 1: entire expr connects to current instance */
+   if (prtbi + cxlen <= mpwid)   
+    {
+     xplp = __alloc_xprlst();
+     xplp->xp = __copy_expr(xp3);
+     if (xplphd == NULL) xplphd = xplp; else xplp_last->xpnxt = xplp;
+     xplp_last = xplp; 
+     prtbi += cxlen;
+     if (prtbi == mpwid) prtbi = 0;
+     continue;
+    }
+   /* case 2: hard need to split expr because element crosses inst. */
+   /* prtbi + cxlen wider than mpwid */
+   endlen = mpwid - prtbi;
+   overlaplen = cxlen - endlen;
+   /* if number, must compute value for use below */
+   if (xp3->optyp == NUMBER)
+    {
+     xsp = __eval_xpr(xp3);
+    }
+   /* build expr. list element for high bits of expr overlapping inst */
+   xplp = __alloc_xprlst();
+   if (xplphd == NULL) xplphd = xplp; else xplp_last->xpnxt = xplp;
+   xplp_last = xplp; 
+   switch ((byte) xp3->optyp) {
+    case ID:
+     np = xp3->lu.sy->el.enp;
+     r1 = cxlen - 1;
+     /* SJM 07/08/00 - if scalar in concatenate can't convert ot bsel */
+     if (!np->n_isavec) 
+      {
+       xplp->xp = __copy_expr(xp3);
+       break;
+      }
+     goto bld_select; 
+    case PARTSEL:
+     np = xp3->lu.x->lu.sy->el.enp;
+     wp = &(__contab[xp3->ru.x->lu.x->ru.xvi]);
+     r1 = (int32) wp[0];
+
+bld_select:
+     /* split off first part that will then fill to end */
+     if (endlen == 1) xplp->xp = bld_bsel_expr(np, r1);
+     else xplp->xp = bld_psel_expr(np, r1, r1 - endlen + 1);
+     break;
+    case NUMBER:
+     /* make work xsp big enough for both */
+     push_xstk_(xsp2, endlen); 
+     /* split off high part of number for first, new part for overlap */
+     /* 3rd argument is length not low end */
+     __rhspsel(xsp2->ap, xsp->ap, cxlen - 1, endlen);
+     __rhspsel(xsp2->bp, xsp->bp, cxlen - 1, endlen); 
+     xplp->xp = bld_num_expr(xsp2);
+     __pop_xstk();
+     break;
+     /* bit select impossible because always fits */
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   if (overlaplen > mpwid)
+    {
+     /* case 2a: overlap continues for more than one inst */
+     for (;;) 
+      {
+       xplp = __alloc_xprlst();
+       if (xplphd == NULL) xplphd = xplp; else xplp_last->xpnxt = xplp;
+       xplp_last = xplp; 
+       switch ((byte) xp3->optyp) {
+        case ID:
+         np = xp3->lu.sy->el.enp;
+         /* SJM 07/08/00 - if scalar in concatenate can't convert ot bsel */
+         if (!np->n_isavec) 
+          {
+           xplp->xp = __copy_expr(xp3);
+           break;
+          }
+         r1 = overlaplen - 1;
+         goto bld2_selects;
+        case PARTSEL:
+         np = xp3->lu.x->lu.sy->el.enp;
+         /* here need right range end */
+         wp = &(__contab[xp3->ru.x->ru.x->ru.xvi]);
+         r1 = (int32) wp[0] + overlaplen - 1;
+bld2_selects:
+         if (mpwid == 1) xplp->xp = bld_bsel_expr(np, r1);
+         else xplp->xp = bld_psel_expr(np, r1, r1 - mpwid + 1);
+         break;
+        case NUMBER:
+         /* make work xsp big enough for both */
+         push_xstk_(xsp2, mpwid); 
+         __rhspsel(xsp2->ap, xsp->ap, overlaplen - 1, mpwid);
+         __rhspsel(xsp2->bp, xsp->bp, overlaplen - 1, mpwid);
+         /* must allocate and fill because may be wider than WBITS */
+         xplp->xp = bld_num_expr(xsp2);
+         __pop_xstk();
+         break;
+        /* bit select impossible because always fits */
+        default: __case_terr(__FILE__, __LINE__);
+       }
+       overlaplen -= mpwid;
+       /* DBG remove --- */
+       if (overlaplen < 0) __misc_terr(__FILE__, __LINE__);  
+       /* ---*/
+       if (overlaplen == 0) goto nxt_catel;
+       if (overlaplen < mpwid) break;   
+       /* if corrected overlap length equal to or wider than port continue */
+      }
+    }
+   /* final or only end part (if narrower than mpwid) */
+   xplp = __alloc_xprlst();
+   if (xplphd == NULL) xplphd = xplp; else xplp_last->xpnxt = xplp;
+   xplp_last = xplp; 
+   switch ((byte) xp3->optyp) {
+    case ID:
+     np = xp3->lu.sy->el.enp;
+     /* SJM 07/08/00 - if scalar in concatenate can't convert ot bsel */
+     if (!np->n_isavec) 
+      {
+       xplp->xp = __copy_expr(xp3);
+       break;
+      }
+     r1 = overlaplen - 1; 
+     goto bld3_selects; 
+    case PARTSEL:
+     np = xp3->lu.x->lu.sy->el.enp;
+     /* here need right range end */
+     wp = &(__contab[xp3->ru.x->ru.x->ru.xvi]);
+     r1 = (int32) wp[0] + overlaplen - 1;
+bld3_selects:
+     /* split off first part that will then fill to end */
+     if (overlaplen == 1) xplp->xp = bld_bsel_expr(np, r1);
+     else xplp->xp = bld_psel_expr(np, r1, r1 - overlaplen + 1);
+     break;
+    case NUMBER:
+     /* make work xsp big enough for both */
+     push_xstk_(xsp2, overlaplen); 
+     __rhspsel(xsp2->ap, xsp->ap, overlaplen - 1, overlaplen);
+     __rhspsel(xsp2->bp, xsp->bp, overlaplen - 1, overlaplen);
+     xplp->xp = bld_num_expr(xsp2);
+     __pop_xstk();
+     break;
+    /* bit select impossible because always fits */
+    default: __case_terr(__FILE__, __LINE__);
+   }
+nxt_catel:
+   if (xp3->optyp == NUMBER) __pop_xstk();
+  }
+ return(xplphd);
+}
+
+/*
+ * build a new number expression from a expression stack element
+ */
+static struct expr_t *bld_num_expr(struct xstk_t *xsp)
+{
+ int32 nwlen;
+ struct expr_t *xp;
+
+ xp = __alloc_newxnd();
+ xp->optyp = NUMBER;
+ xp->szu.xclen = xsp->xslen;
+ nwlen = wlen_(xsp->xslen); 
+ if (xsp->xslen <= WBITS)
+  {
+   xp->ru.xvi = __alloc_shareable_cval(xsp->ap[0], xsp->ap[1], xsp->xslen);
+  }
+ else
+  {
+   xp->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, nwlen);
+  }
+ return(xp);
+}
+
+/*
+ * ROUTINES TO RESET AS FIXUP MODULE PORT STRENGTHS AFTER PORT EXPANDING 
+ */
+
+/*
+ * set module port strength expression bits
+ *
+ * needed because must check expressions to set widths before apportioning
+ * I/O ports to iconns, but can not propagate strengths until apportioning
+ * done, so now must go back and set expr x_stren bit if module port
+ * exprs contains stren wires, all other expressions checked after stren
+ * propagation so only need to fix up for module ports
+ */
+extern void __reset_modport_strens(void)
+{
+ register int32 pi;
+ register struct mod_t *mdp;
+ register struct mod_pin_t *mpp;
+ int32 pnum;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* SJM 12/26/02 - this was wrong - not marking all port strens so */
+   /* iop gen wasn't working */
+   if ((pnum = mdp->mpnum) == 0) continue;
+
+   for (pi = 0; pi < pnum; pi++)
+    {
+     mpp = &(mdp->mpins[pi]);
+     set_1mpx_stren(mpp->mpref);
+    }
+  }
+}
+
+/*
+ * set expr. strength bits for module port exprs with strength wires
+ *
+ * used recursively on subexprs of ports exprs (not iconn exprs)
+ */
+static void set_1mpx_stren(struct expr_t *mpx)
+{
+ int32 cat_stren;
+ struct net_t *np;
+ struct sy_t *syp;
+
+ switch ((byte) mpx->optyp) {
+  case ID: case GLBREF:
+   np = mpx->lu.sy->el.enp;
+   if (np->n_stren) mpx->x_stren = TRUE;
+   break;
+  case NUMBER: case ISNUMBER: case OPEMPTY: case REALNUM: case ISREALNUM:
+   break;
+  case LSB:
+   syp = mpx->lu.x->lu.sy;
+   np = syp->el.enp;
+   if (np->n_stren) mpx->x_stren = TRUE;
+   set_1mpx_stren(mpx->ru.x);
+   break;
+  case PARTSEL:
+   syp = mpx->lu.x->lu.sy;
+   np = syp->el.enp;
+   if (np->n_stren) mpx->x_stren = TRUE;
+   set_1mpx_stren(mpx->ru.x->lu.x);
+   set_1mpx_stren(mpx->ru.x->ru.x);
+   break;
+  case QUEST:
+   set_1mpx_stren(mpx->lu.x);
+   set_1mpx_stren(mpx->ru.x->ru.x);
+   set_1mpx_stren(mpx->ru.x->lu.x);
+   break;
+  case FCALL: return;
+  case LCB:
+   {
+    register struct expr_t *ndp2;
+    struct expr_t *catxp;
+
+    /* know concatenates never nested by here */
+    for (cat_stren = FALSE, ndp2 = mpx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     {
+      catxp = ndp2->lu.x;
+      set_1mpx_stren(catxp);
+      if (catxp->x_stren) { ndp2->x_stren = TRUE; cat_stren = TRUE; }
+     }
+    if (cat_stren) mpx->x_stren = TRUE;
+   }
+   break;
+  default:
+   if (mpx->lu.x != NULL) set_1mpx_stren(mpx->lu.x);
+   if (mpx->ru.x != NULL) set_1mpx_stren(mpx->ru.x);
+ }
+}
+
+/*
+ * MODULE COMPONENT SEMANTIC CHECKING ROUTINES
+ */
+
+/*
+ * check module - also call procedure checking routines
+ * does the following:
+ *  1) global refs. hanged to ids
+ *  2) constant expr. folded and node widths set
+ *
+ * notice all code called from here requires __inst_mod to be set for
+ * finding size of IS form parmeters that are converted to constants here
+ */
+extern void __chk_mod(void)
+{
+ register struct task_t *tskp;
+
+ /* check inst. conns. and gates */
+ chk_inst_conns();
+ chk_gates();
+ chk_contas();
+
+ /* SJM 09/30/04 - although variable assign initialize decls require */
+ /* constant rhs expr, not checking the expression until here */ 
+ /* because semantics is same as decl followed by initial [var] = [expr]; */
+ chk_varinits();
+ 
+ /* check init/always statements */
+ chk_stmts();
+
+ /* finally check user tasks and function statements */
+ for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+   switch ((byte) tskp->tsktyp) { 
+    case FUNCTION:
+     /* named blocks checked in context */
+     chk_funcdef(tskp);
+     tskp->thas_outs = FALSE;
+     tskp->thas_tskcall = FALSE;
+     break;
+    case TASK:
+     chk_1tsk(tskp);
+     break;
+    /* named block task checked when statement seen */
+    case Begin: case FORK: break;
+    default: __case_terr(__FILE__, __LINE__); 
+   }
+  }
+}
+
+/*
+ * check 1 task
+ * notice this is task definition so cannot be called from iact
+ */
+static void chk_1tsk(struct task_t *tskp)
+{
+ register struct task_pin_t *tpp;
+ int32 ai;
+ struct net_t *np;
+ struct sy_t *syp;
+
+ __cur_tsk = tskp;
+ /* variables checked, chk statements & look for non thread optimizations */
+ for (ai = 1, tpp = tskp->tskpins; tpp != NULL; tpp = tpp->tpnxt, ai++)
+  {
+   np = tpp->tpsy->el.enp;
+   /* SJM 01/14/1999 - arrays illegal formal function arguments */
+   if (np->n_isarr)
+    {
+     syp = tpp->tpsy;
+     __gferr(869, syp->syfnam_ind, syp->sylin_cnt,
+      "task %s definition entire array formal argument %s (pos. %d) illegal - must be simple variable",
+      tskp->tsksyp->synam, syp->synam, ai);
+     continue;
+    }
+
+   /* notice task ports must be regs so no need to set 2nd on lhs */
+   if (tpp->trtyp != IO_IN)
+    {
+     if (np->nrngrep == NX_CT)
+      {
+       if (tpp->trtyp == IO_BID) np->nu.ct->n_onlhs = TRUE;
+       np->nu.ct->n_onrhs = TRUE;
+      }
+     tskp->thas_outs = TRUE;
+    }
+   else if (np->nrngrep == NX_CT) np->nu.ct->n_onlhs = TRUE;
+  }
+ /* notice that task can take any legal variables no argument */
+ /* requirements - this finds any named block no delay cases */
+ __chk_lstofsts(tskp->tskst);
+
+ /* finally do checking to determine if 0 delay or has task call */ 
+ __task_has_delay = FALSE;
+ __task_has_tskcall = FALSE;
+ __nbsti = -1;
+ __chk_nodel_lstofsts(tskp->tskst);
+ __cur_tsk = NULL;
+}
+
+/*
+ * check module instance connections
+ * expression here can be numbers with IS form so need to check
+ * all instances in that case
+ * this frees cell_pin_t since not used after here
+ */
+static void chk_inst_conns(void)
+{
+ register int32 pi, ii;
+ register struct mod_pin_t *mpp;
+ int32 iotyp, sav_enum;
+ int32 pnum, pwid;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+ struct expr_t *pxp;
+ struct srcloc_t *slocp;
+ struct net_t *np;
+
+ __expr_rhs_decl = TRUE;
+ for (ii = 0; ii < __inst_mod->minum; ii++)
+  {
+   ip = &(__inst_mod->minsts[ii]);
+   imdp = ip->imsym->el.emdp;
+   if ((pnum = imdp->mpnum) == 0) continue;
+   slocp = __inst_mod->iploctab[ii];
+
+   for (pi = 0; pi < pnum; pi++)
+    {
+     mpp = &(imdp->mpins[pi]);
+     pxp = ip->ipins[pi];
+     __sfnam_ind = slocp[pi].sl_fnam_ind;
+     __slin_cnt = slocp[pi].sl_lin_cnt;
+
+     /* this should always be at least OPEMPTY by here */
+     /* change to special unc. indicator and check/fix here */
+     /* instance one port missing 'bx for unconnect */
+     /* DBG remove --- */
+     if (pxp == NULL) __misc_sgfterr(__FILE__, __LINE__);
+     /* --- */
+
+     /* module port iconn cannot have real connection */
+     if (pxp->is_real)
+      __sgferr(780,
+       "instance %s port %s (pos. %d) illegally connects to real number",
+       ip->isym->synam, __msgexpr_tostr(__xs, pxp), pi + 1);
+
+     /* cannot be xmr that references down into same inst. */
+     sav_enum = __pv_err_cnt;
+     chk_iconn_downxmr(ip, pxp);
+     if (sav_enum < __pv_err_cnt) continue;
+
+     pwid = mpp->mpwide;
+     /* if first time implicitly declared wire used change to port width */
+     /* if first use if as scalar and later other must still fix here */
+     if (pxp->optyp == ID)
+      {
+       /* SJM 03/15/00 - must catch passing non wire ID as error */
+       if (pxp->lu.sy->sytyp != SYM_N)
+        {
+         __sgferr(789, "instance %s port pos. %d illegally connects to %s %s",
+          ip->isym->synam, pi + 1, __to_sytyp(__xs, pxp->lu.sy->sytyp),
+          __msgexpr_tostr(__xs2, pxp));
+         continue;
+        }
+       np = pxp->lu.sy->el.enp;
+       if (np->nu.ct->n_impldecl && !np->nu.ct->n_rngknown)
+        {
+         /* change to vectored wire with same direction range as port */ 
+         if (pwid > 1)
+          {
+           np->nu.ct->nx1 = __bld_rng_numxpr((word32) (pwid - 1), 0L, WBITS);
+           np->nu.ct->nx2 = __bld_rng_numxpr(0L, 0L, WBITS);
+           np->n_isavec = TRUE;
+           np->nwid = pwid;
+           /* vectored/scalared set to default scalared state at prep time */
+           __sgfinform(472, 
+            "implicitly declared %s %s width changed to %d to match port width",
+            __to_wtnam(__xs, np), np->nsym->synam, pwid);
+          }
+         np->nu.ct->n_rngknown = TRUE;  
+         __chg_rng_direct = TRUE;
+        }
+      }
+
+     iotyp = mpp->mptyp;
+     if (iotyp == IO_IN)
+      {
+       /* fix unc. drive to special type of constant */
+       if (pxp->optyp == OPEMPTY)
+        {
+         pxp->szu.xclen = pwid;
+         /* change node type so will eval. to right value */
+         if (pxp->unc_pull != NO_UNCPULL) pxp->optyp = UNCONNPULL; 
+
+         __sgfinform(473,
+          "instance %s input port %s (pos. %d) width %d unconnected",
+          ip->isym->synam, __to_mpnam(__xs, mpp->mpsnam), pi + 1, pwid);
+
+         continue;
+        }
+       /* notice for IS forms checks each */
+       __chk_rhsexpr(pxp, pwid);
+      }
+     else
+      {
+       /* either output or inout */
+       /* make OPEMPTY not unconn. drive strength form */
+       if (pxp->optyp == OPEMPTY)
+        {
+         pxp->szu.xclen = pwid;
+         if (pxp->x_stren) { pxp->x_stren = FALSE; pxp->ru.xvi = -1; }
+         if (mpp->mptyp == IO_BID && !mpp->mp_jmpered)
+          {
+           __sgfinform(473,
+            "instance %s inout port %s (pos. %d) width %d unconnected",
+            ip->isym->synam, __to_mpnam(__xs, mpp->mpsnam), pi + 1, pwid);
+          }
+         /* already emitted special case inout unc. - not jumpered, etc. */
+         /* 11/06/00 SJM - to match XL emit inform for every unc. port */ 
+         if (mpp->mptyp != IO_BID)
+          {
+           __sgfinform(473,
+            "instance %s output port %s (pos. %d) width %d unconnected",
+            ip->isym->synam, __to_mpnam(__xs, mpp->mpsnam), pi + 1, pwid);
+          }
+         continue;
+        }
+       pxp->szu.xclen = pwid;
+       __chk_lhsexpr(pxp, LHS_DECL);
+       /* inout is also rhs expression */
+       if (iotyp == IO_BID) __set_expr_onrhs(pxp);
+      }
+     /* if error in expr., do not emit size warning */
+     if (sav_enum < __pv_err_cnt) continue;
+
+     /* check port width mismatch */
+     if (pxp->szu.xclen != pwid)
+      {
+       char s2[20], s3[RECLEN];
+
+       __sgfwarn(602,
+        "%s(%s) %s port %s (line %s) width %d mismatch with %s width %d", 
+        ip->isym->synam, ip->imsym->synam, __to_ptnam(s2, mpp->mptyp),  
+        __to_mpnam(s3, mpp->mpsnam), __bld_lineloc(__xs, mpp->mpfnam_ind,
+        mpp->mplin_cnt), pwid, __msgexpr_tostr(__xs2, pxp), pxp->szu.xclen);
+      }
+
+     /* check same wire directions - if either concat do not check */
+     /* know now both mod and inst port exprs checked */
+     chk_iconn_mixeddirrng(ip, mpp, pxp);
+     /* SJM - 10/08/99 - always turn off impl decl change dir since */ 
+     /* if implicit scalar will not go through reverse code */
+     __chg_rng_direct = FALSE;
+    }
+  }
+ __expr_rhs_decl = FALSE;
+}
+
+/*
+ * for inout I/O port expr. must set both rhs bits
+ */
+extern void __set_expr_onrhs(struct expr_t *ndp)  
+{
+ struct net_t *np;
+
+ if (__isleaf(ndp))
+  {
+   if (ndp->optyp == ID || ndp->optyp == GLBREF)
+    {
+     np = ndp->lu.sy->el.enp;
+     if (np->nrngrep == NX_CT)
+      {
+       if (np->iotyp == NON_IO) np->nu.ct->n_onrhs = TRUE;
+      }
+     if (!__expr_rhs_decl) np->n_onprocrhs = TRUE;
+    }
+   return;
+  }
+ if (ndp->lu.x != NULL) __set_expr_onrhs(ndp->lu.x);
+ if (ndp->ru.x != NULL) __set_expr_onrhs(ndp->ru.x);
+}
+
+/*
+ * check for all xmrs in expr. and emit error if xmr into instance
+ * know expr. is instance connection
+ */
+static void chk_iconn_downxmr(struct inst_t *ip, struct expr_t *ndp)
+{
+ register int32 pthi;
+ struct sy_t *syp;
+
+ if (__isleaf(ndp))
+  {
+   if (ndp->optyp == GLBREF)
+    {
+     struct gref_t *grp;
+
+     grp = ndp->ru.grp;
+     if (grp->upwards_rel || grp->gr_gone || grp->gr_err) return;
+     for (pthi = 0; pthi <= grp->last_gri; pthi++)
+      {
+       syp = grp->grcmps[pthi];
+       if (syp == ip->isym)
+        {
+         __sgferr(788,
+          "in module %s: instance %s port list contains hierarchical reference %s into same instance",
+          __inst_mod->msym->synam, ip->isym->synam, grp->gnam);
+        }
+      }
+    }
+   return;
+  }
+ if (ndp->lu.x != NULL) chk_iconn_downxmr(ip, ndp->lu.x);
+ if (ndp->ru.x != NULL) chk_iconn_downxmr(ip, ndp->ru.x);
+}
+
+/*
+ * check for mixed direction range instance 
+ */
+static void chk_iconn_mixeddirrng(struct inst_t *ip,
+ struct mod_pin_t *mpp, struct expr_t *ipxp)
+{
+ int32 one_is_bsel, porthl, iphl, tmp;
+ int32 portr1, portr2, ipr1, ipr2;
+ struct net_t *portnp, *ipnp;
+ char porthls[20], iphls[20];
+
+ /* only check for both psel, id or global, if either bsel, 1 inform */
+ one_is_bsel = FALSE;
+ switch ((byte) mpp->mpref->optyp) { 
+  case ID: case GLBREF: portnp = mpp->mpref->lu.sy->el.enp; break;
+  case PARTSEL:
+get_portsel_np:
+   portnp = mpp->mpref->lu.x->lu.sy->el.enp;
+   break;
+  case LSB:
+   one_is_bsel = TRUE;
+   goto get_portsel_np;
+  default: return;
+ }
+ if (!portnp->n_isavec) return;
+ switch ((byte) ipxp->optyp) { 
+  case ID: case GLBREF: ipnp = ipxp->lu.sy->el.enp; break;
+  case PARTSEL:
+get_ipsel_np:
+   ipnp = ipxp->lu.x->lu.sy->el.enp;
+   break;
+  case LSB:
+   one_is_bsel = TRUE;
+   goto get_ipsel_np;
+  default: return;
+ }
+ if (!ipnp->n_isavec) return;
+ __getwir_range(portnp, &portr1, &portr2);
+ __getwir_range(ipnp, &ipr1, &ipr2);
+
+ /* if either is 1 bit range, no warn/inform */ 
+ if (portr1 == portr2 || ipr1 == ipr2) return;
+
+ /* here if this is implicitly declared from inst. conn. wire, just fix */
+ if (__chg_rng_direct)
+  {
+   /* if port really low high, reverse range */
+   if (portr1 < portr2)
+    {
+     /* only need to reverse con tab pointers */
+     tmp = ipnp->nu.ct->nx1->ru.xvi;
+     ipnp->nu.ct->nx1->ru.xvi = ipnp->nu.ct->nx2->ru.xvi;
+     ipnp->nu.ct->nx2->ru.xvi = tmp;
+    }
+   __chg_rng_direct = FALSE;
+   return;  
+  }
+
+ if (portr1 >= portr2)
+  { porthl = TRUE; strcpy(porthls, "high to low"); }
+ else { porthl = FALSE; strcpy(porthls, "low to high"); }
+ if (ipr1 >= ipr2)
+  { iphl = TRUE; strcpy(iphls, "high to low"); }
+ else { iphl = FALSE; strcpy(iphls, "low to high"); }
+ 
+ if (porthl != iphl)
+  {
+   char s1[2*IDLEN], s2[20];
+
+   sprintf(s1, "%s [%d:%d] %s at %s",
+    __to_ptnam(s2, mpp->mptyp), portr1, portr2, portnp->nsym->synam,
+    __bld_lineloc(__xs, mpp->mpfnam_ind, mpp->mplin_cnt));
+   if (one_is_bsel)
+    {
+     __sgfinform(412,
+      "type %s instance %s range [%d:%d] direction mismatch with %s",
+      ip->imsym->synam, ip->isym->synam, ipr1, ipr2, s1);
+    }
+   else
+    {
+     __sgfwarn(556,
+      "type %s instance %s range [%d:%d] direction mismatch with %s",
+      ip->imsym->synam, ip->isym->synam, ipr1, ipr2, s1);
+    }
+  }
+}
+
+/*
+ * free module port line no.s for one module if not already freed
+ * for split all will share so only one needs to be freed
+ */
+extern void __free_icptab(void)
+{
+ register int32 ii;
+ int32 pnum;
+ struct srcloc_t *iplocs;
+ struct inst_t *ip;
+ struct mod_t *imdp;
+
+ /* only free module from original source list */
+ if (!__inst_mod->msplit && !__inst_mod->mpndsplit) 
+  {
+   for (ii = 0; ii < __inst_mod->minum; ii++)
+    {
+     /* ptr to table of actual src loc records */
+     iplocs = __inst_mod->iploctab[ii];
+
+     ip = &(__inst_mod->minsts[ii]);
+     imdp = ip->imsym->el.emdp;
+     /* number of ports if number for contained inst */
+     if ((pnum = imdp->mpnum) != 0)
+      __my_free((char *) iplocs, pnum*sizeof(struct srcloc_t)); 
+    }
+   if (__inst_mod->minum != 0)
+    {
+     __my_free((char *) __inst_mod->iploctab,
+      __inst_mod->minum*sizeof(struct srcloc_t **));
+    }
+  }
+ __inst_mod->iploctab = NULL;
+}
+
+/*
+ * check gate and continuous assigns
+ * notice at this point continuous assignments still not split off
+ */
+static void chk_gates(void)
+{
+ register int32 gi, pi;
+ register struct gate_t *gp;
+ int32 dnum, nins;
+ struct expr_t *xp;
+ struct net_t *np;
+ struct paramlst_t *dhdr;
+
+ /* check gates first */
+ __expr_rhs_decl = TRUE;
+ for (gi = 0; gi < __inst_mod->mgnum; gi++)
+  {
+   gp = &(__inst_mod->mgates[gi]);
+
+   __sfnam_ind = gp->gsym->syfnam_ind;
+   __slin_cnt = gp->gsym->sylin_cnt;
+   if (gp->g_class != GC_UDP)
+    {
+     /* returns FALSE if special gate (pull?), will then not check ports */
+     /* know output port checked later */
+     if (!chk_1bltingate(gp)) continue;
+     nins = gp->gpnum - 1;
+    }
+   else
+    {
+     /* SJM 07/02/03 - if error here will core dump if keeps checking */ 
+     if (!chk_1udp(gp)) continue;
+     nins = gp->gmsym->el.eudpp->numins;
+    }
+
+   /* returns F on fail, must convert to unc. OPEMPTY */ 
+   if (!chk_gate_source(gp, gp->gpins[0], TRUE, FALSE, &np))
+    { __free_xtree(gp->gpins[0]); set_unc_gateterm(gp, 0); }
+   for (pi = 0; pi < nins; pi++)
+    {
+     /* can tell i/o type from gate order */
+     xp = gp->gpins[pi + 1];
+     __chk_rhsexpr(xp, 1);
+     if (xp->is_real)
+      __sgferr(781, 
+       "gate or udp %s input terminal %s (pos. %d) cannot have real value",
+       gp->gmsym->synam, __msgexpr_tostr(__xs2, xp), pi + 1);
+     /* for implicitly declared must mark as scalar if first use */
+     if (xp->optyp == ID)
+      { 
+       np = xp->lu.sy->el.enp;
+       if (np->nu.ct->n_impldecl && !np->nu.ct->n_rngknown)
+        np->nu.ct->n_rngknown = TRUE;  
+      }
+    }
+   if (gp->g_du.pdels == NULL) continue;
+
+   /* check delay params, sim array built later */
+   if (gp->g_class == GC_UDP)
+    {
+     dhdr = __copy_dellst(gp->g_du.pdels);
+     if ((dnum = __chk_delparams(dhdr, "udp delay", FALSE)) == -1)
+      gp->g_du.pdels = NULL;
+     else if (dnum > 2)
+      {
+       __sgferr(782, "udp has more than 2 delays (%d)", dnum);
+       gp->g_du.pdels = NULL;
+      }
+     __free_dellst(dhdr);
+    }
+   else
+    {
+     dhdr = __copy_dellst(gp->g_du.pdels);
+     if ((dnum = __chk_delparams(dhdr, "built-in gate delay", FALSE)) == -1)
+      gp->g_du.pdels = NULL;
+     else if (gp->g_class == GC_LOGIC)
+      { 
+       if (dnum > 2)
+        {
+         __sgferr(783, "%s logic gate has more than 2 delays (%d)",
+          gp->gmsym->synam, dnum);
+          gp->g_du.pdels = NULL;
+        }
+      }
+     else if (dnum > 3)
+      {
+       __sgferr(775, "%s gate has more than 3 delays (%d)",
+        gp->gmsym->synam, dnum);
+       gp->g_du.pdels = NULL;
+      }
+     __free_dellst(dhdr);
+    }
+  }
+ /* unless looking for declarative, must leave in off state */
+ __expr_rhs_decl = FALSE;
+}
+
+/*
+ * check 1 built in gate (not udps and 1 bit contas still not gates)
+ * notice normal gate just falls through and only terminal list checked
+ * return F to prevent normal 1st only output gate expression checking
+ * if returns F must call expression checking for each port itself
+ *
+ */
+static int32 chk_1bltingate(struct gate_t *gp)
+{
+ int32 pnum;
+ struct primtab_t *ptp;
+
+ pnum = gp->gpnum;
+ ptp = gp->gmsym->el.eprimp;
+ switch ((byte) ptp->gateid) {
+  case G_BUF: case G_NOT:
+   if (pnum == 1) __sgferr(784,
+    "%s gate requires at least 2 terminals", ptp->gatnam);
+   else if (pnum != 2)
+    __sgferr(785, "%s gate with multiple outputs unsupported", ptp->gatnam);
+   break;
+  case G_BUFIF0: case G_BUFIF1: case G_NOTIF0: case G_NOTIF1:
+   if (pnum != 3) gate_errifn(gp, 3);
+   break;
+  case G_RPMOS: case G_RNMOS:
+   /*FALLTHRU */
+  case G_NMOS: case G_PMOS:
+   chk_gate_nostren(gp);
+   if (pnum != 3) gate_errifn(gp, 3);
+   break;
+  case G_RCMOS:
+   /*FALLTHRU */
+  case G_CMOS:
+   chk_gate_nostren(gp);
+   if (pnum != 4) gate_errifn(gp, 4);
+   break;
+  case G_PULLDOWN: case G_PULLUP:
+   chk_pull_gate(gp);
+   /* this inhibits normal checking of ports */
+   return(FALSE);
+  case G_TRAN: case G_RTRAN:
+   chk_tran_gate(gp);
+   return(FALSE);
+  case G_TRANIF0: case G_TRANIF1: case G_RTRANIF0: case G_RTRANIF1:
+   chk_tranif_gate(gp);
+   return(FALSE);
+  default:
+   if (pnum < 2)
+    {
+     __sgferr(786, "%s gate requires at least 2 terminals", gp->gmsym->synam);
+    }
+   else if (pnum < 3)
+    {
+     __sgfwarn(573, "%s gate has only %d terminals - should have at least 3",
+      gp->gmsym->synam, pnum);
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * write a message for a if type gate that needs 3 terminals
+ */
+static void gate_errifn(struct gate_t *gp, int32 n)
+{
+ __sgferr(787, "%s gate does not have required %d terminals",
+  gp->gmsym->synam, n);
+}
+
+/*
+ * emit warning and remove strength on gate that should not have it
+ */
+static void chk_gate_nostren(struct gate_t *gp)
+{
+ if (gp->g_hasst)
+  {
+   __sgfwarn(537, "%s gate cannot have strength", gp->gmsym->synam);
+   gp->g_hasst = FALSE;
+   gp->g_stval = ST_STRVAL; 
+  }
+}
+
+/*
+ * check a tran style gate
+ */
+static void chk_tran_gate(struct gate_t *gp)
+{ 
+ int32 pnum;
+ struct expr_t *px1, *px2;
+ struct net_t *np1, *np2;
+
+ np1 = np2 = NULL;
+ /* first cannot have delay */
+ if (gp->g_du.pdels != NULL)
+  {
+   __sgferr(816, "%s cannot have delay", gp->gmsym->synam);
+   __free_dellst(gp->g_du.pdels);
+   gp->g_du.pdels = NULL;
+  }
+ /* must mark as no del since later expression checking expects no delay */
+ gp->g_delrep = DT_NONE;
+
+ /* any tran can't have strength - signal strength is preserved according */
+ /* to resistive or not mos table */
+ chk_gate_nostren(gp);
+ px1 = px2 = NULL;
+ pnum = gp->gpnum;
+ if (pnum != 2) gate_errifn(gp, 2);
+ if (pnum >= 1) px1 = gp->gpins[0];
+ if (pnum >= 2) px2 = gp->gpins[1];
+ /* for these both terminals must be lhs */ 
+ if (px1 != NULL)
+  {
+   if (!chk_gate_source(gp, px1, TRUE, TRUE, &np1))
+    {
+    __free_xtree(px1);
+     /* this cannot build unc expr since cannot set pull only for inst */
+     set_unc_gateterm(gp, 0);
+    }
+   else chk_1bit_tran(gp, px1, np1, 1);
+  }
+  
+ if (px2 != NULL)
+  {
+   if (!chk_gate_source(gp, px2, TRUE, TRUE, &np2))
+    { __free_xtree(px2); set_unc_gateterm(gp, 1); }
+   else chk_1bit_tran(gp, px2, np2, 2);
+  }
+ __inst_mod->mod_gatetran = TRUE;
+ /* SJM 04/26/01 - if both terminals same, emit warning and mark as gone */
+ chk_tran_terms_same(gp);
+}
+
+/*
+ * check for tran or tranif with both inout terminals same expr
+ * if so emit warning and mark deleted from net list 
+ * return T if deleted
+ */
+static int32 chk_tran_terms_same(struct gate_t *gp)
+{
+ struct expr_t *xp1, *xp2;
+ struct net_t *np1, *np2;
+ int32 i1, i2;
+
+ xp1 = gp->gpins[0]; 
+ xp2 = gp->gpins[1];
+ if (xp1->optyp == ID && xp2->optyp == ID)
+  {
+   np1 = xp1->lu.sy->el.enp;
+   np2 = xp2->lu.sy->el.enp;
+   /* since not xmr, can compare net addrs */
+   if (np1 == np2)
+    {
+     __gfwarn(3117, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+      "%s %s inout terminals (%s) identical - removed because has no effect", 
+      gp->gmsym->synam, gp->gsym->synam, np1->nsym->synam);
+     gp->g_gone = TRUE;
+    }
+   return(TRUE);
+  }
+ if (xp1->optyp == LSB && xp2->optyp == LSB)
+  {
+   np1 = xp1->lu.x->lu.sy->el.enp;
+   np2 = xp2->lu.x->lu.sy->el.enp;
+   /* know same net */
+   if (np1 != np2) return(FALSE);
+
+   if (xp1->ru.x->optyp != NUMBER || xp2->ru.x->optyp != NUMBER)
+    return(FALSE);
+   i1 = __contab[xp1->ru.x->ru.xvi];
+   i2 = __contab[xp2->ru.x->ru.xvi];
+   if (i1 == i2) 
+    {
+     __gfwarn(3117, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+      "%s %s inout terminals (%s[%d]) identical - gate removed because has not effect", 
+      gp->gmsym->synam, gp->gsym->synam, np1->nsym->synam, i1);
+     gp->g_gone = TRUE;
+    }
+  }
+ return(FALSE);
+}
+
+/*
+ * set unc (OPEMPTY) for gate terminal
+ */
+static void set_unc_gateterm(struct gate_t *gp, int32 pi)
+{
+ /* cannot use bld unc expr here since sets pull but that only for */
+ /* for instances */
+ __root_ndp = __alloc_newxnd();
+ __root_ndp->optyp = OPEMPTY;
+ __root_ndp->folded = TRUE;
+ __root_ndp->szu.xclen = 1;
+ gp->gpins[pi] = __root_ndp;
+}
+
+/*
+ * check to make sure tran bidirectional terminal only connect to scalar
+ * nets or bit selects
+ */
+static void chk_1bit_tran(struct gate_t *gp, struct expr_t *px,
+ struct net_t *np, int32 termno)
+{
+ if (px->optyp == OPEMPTY)
+  {
+   __sgfwarn(581, "%s terminal %d unconnected - switch has no effect",
+    gp->gmsym->synam, termno);
+   return;
+  }
+ /* 07/08/00 SJM - because of complexity with switch channal also can't be */
+ /* ID must be select of ID */
+ if (px->optyp == PARTSEL || (px->optyp != LSB && np->n_isavec)
+  || ((px->optyp == GLBREF || px->optyp == ID)
+  && px->lu.sy->el.enp->nwid > 1))
+  { 
+   __sgferr(1237, "%s terminal %d - %s not scalar or scalared bit select",
+    gp->gmsym->synam, termno, __msgexpr_tostr(__xs, px));
+   return;
+  }
+ /* by here any constant converted to empty and caught above */
+ if (np->nu.ct->n_dels_u.pdels != NULL)
+  {
+   __sgferr(1238,
+    "%s terminal %d (%s) - wire %s in tran channel illegally has wire delay",
+    gp->gmsym->synam, termno, __msgexpr_tostr(__xs, px), np->nsym->synam);
+  }
+}
+
+/*
+ * check a tranif style gate 
+ */
+static void chk_tranif_gate(struct gate_t *gp)
+{ 
+ int32 dnum, pnum;
+ struct paramlst_t *dhdr;
+ struct net_t *np1, *np2;
+ struct expr_t *px1, *px2, *px3;
+ 
+ np1 = np2 = NULL;
+ if (gp->g_du.pdels != NULL)
+  {
+   /* can have 0,1 or 2 delays */ 
+   dhdr = __copy_dellst(gp->g_du.pdels);
+   if ((dnum = __chk_delparams(dhdr, "tranif enable delay", TRUE)) == -1)
+    gp->g_du.pdels = NULL; 
+   else if (dnum > 2)
+    {
+     __sgferr(799, "%s gate has more than 2 delays (%d)", gp->gmsym->synam,
+      dnum);
+     gp->g_du.pdels = NULL;
+    }
+   __free_dellst(dhdr);
+  }
+
+ /* any tran can't have strength - signal strength is preserved according */
+ /* to resistive or not mos table */
+ chk_gate_nostren(gp);
+ px1 = px2 = NULL;
+ pnum = gp->gpnum;
+ if (pnum != 3) gate_errifn(gp, 3);
+ if (pnum >= 1) px1 = gp->gpins[0];
+ if (pnum >= 2) px2 = gp->gpins[1];
+ /* for these both terminal must be lhs */ 
+ if (px1 != NULL)
+  {
+   if (!chk_gate_source(gp, px1, TRUE, TRUE, &np1))
+    { __free_xtree(px1); set_unc_gateterm(gp, 0); }
+   else chk_1bit_tran(gp, px1, np1, 1);
+  }
+ if (px2 != NULL)
+  {
+   if (!chk_gate_source(gp, px2, TRUE, TRUE, &np2))
+    { __free_xtree(px2); set_unc_gateterm(gp, 1); }
+   else chk_1bit_tran(gp, px2, np2, 2);
+  }
+ if (pnum < 3) return;
+
+ /* check 3rd control normal input terminal */
+ px3 = gp->gpins[2];
+ __chk_rhsexpr(px3, 1);
+ if (px3->is_real)
+  __sgferr(781, "%s gate input terminal value %s cannot be real",
+   gp->gmsym->synam, __msgexpr_tostr(__xs2, px3));
+ __inst_mod->mod_gatetran = TRUE;
+
+ /* SJM 04/26/01 - if both terminals same, emit warning and mark as gone */
+ chk_tran_terms_same(gp);
+}
+
+/*
+ * check a pull gate - can any any length list of lhs sources
+ * all pull pins are outputs 
+ */
+static void chk_pull_gate(struct gate_t *gp)
+{
+ register int32 i;
+ struct expr_t *xp;
+ struct net_t *np;
+
+ /* first cannot have delay */
+ if (gp->g_du.pdels != NULL)
+  {
+   __sgferr(816, "%s source cannot have delay", gp->gmsym->synam);
+   __free_dellst(gp->g_du.pdels);
+   gp->g_du.pdels = NULL;
+  }
+ /* must mark as no del since later expression checking expects no delay */
+ gp->g_delrep = DT_NONE;
+
+ /* for pull sources, stength defaults to pull not strong */
+ /* LOOKATME - pull gate always has strength so g_hasst not checked */
+ if (!gp->g_hasst) gp->g_stval = 0x2d;
+ else if (gp->g_stval == 0x00)
+  {
+   __sgferr(1151, "%s source highz[01] strength illegal",
+    gp->gmsym->synam);
+  }
+ else if (gp->g_stval == 0x3f)
+  {
+   __sgfwarn(546, "%s source supply[01] strength same as supply declaration",
+    gp->gmsym->synam);
+  }
+
+ /* all ports must be legal lhs expressions except no concat and xmr */
+ /* notice constant bit and part selects ok */
+ for (i = 0; i < (int32) gp->gpnum; i++) 
+  {
+   xp = gp->gpins[i];
+   __chk_lhsexpr(xp, LHS_DECL);
+   if (xp->optyp == LCB)
+    {
+     __sgferr(951, "%s source %s (pos. %d) cannot drive concatenate",
+      gp->gmsym->synam, __msgexpr_tostr(__xs, xp), i + 1);
+     continue;
+    }
+   if (xp->optyp == GLBREF)
+    {
+     __sgferr(959,
+      "%s source cannot drive cross module reference %s (pos. %d)",
+      gp->gmsym->synam, __msgexpr_tostr(__xs, xp), i + 1);
+     continue;
+    }
+   else if (xp->optyp == OPEMPTY)
+    {
+     __sgferr(965,
+      "%s source empty (,,) terminal list element (pos. %d) illegal",
+      gp->gmsym->synam, i + 1); 
+     continue;
+    }
+   /* source must be wire */
+   if (xp->optyp == LSB || xp->optyp == PARTSEL)
+    np = xp->lu.x->lu.sy->el.enp;
+   else np = xp->lu.sy->el.enp;  
+   if (np->ntyp >= NONWIRE_ST)
+    {
+     __sgferr(969,
+      "%s source net %s (pos. %d) type %s illegal - must be wire type",
+      gp->gmsym->synam, np->nsym->synam, i + 1, __to_wtnam(__xs, np));
+     continue;
+    }
+   if (np->ntyp == N_TRIREG)
+    {
+     __sgfinform(443, "%s source on trireg wire %s (pos. %d)",
+      gp->gmsym->synam, np->nsym->synam, i+ 1);
+     continue;
+    }
+   if (np->ntyp == N_SUPPLY0 || np->ntyp == N_SUPPLY1 || np->ntyp == N_TRI0
+    || np->ntyp == N_TRI1)
+    {
+     __sgfwarn(536, "%s source on %s wire %s (pos. %d) has no effect",
+      gp->gmsym->synam, np->nsym->synam, __to_wtnam(__xs, np), i+ 1);
+     continue;
+    }
+  }
+}
+
+/*
+ * check a udp
+ * notice nins here includes output state if non comb.
+ */
+static int32 chk_1udp(struct gate_t *gp)
+{
+ struct udp_t *udpp;
+
+ udpp = gp->gmsym->el.eudpp;
+ udpp->u_used = TRUE;
+ /* numins includes state that does not appear in udp instantiation */
+ if (gp->gpnum - 1 != udpp->numins)
+  {
+   __sgferr(790, "udp %s has wrong number of terminals (%d) should be %d",
+    gp->gmsym->synam, gp->gpnum, udpp->numins + 1);
+   return(FALSE);
+  }
+ /* more checking */
+ return(TRUE);
+}
+
+/*
+ * check a gate output (source) driving terminal more than one
+ */
+static int32 chk_gate_source(struct gate_t *gp, struct expr_t *xp,
+ int32 nd_lhs_chk, int32 nd_1bit, struct net_t **ret_np)
+{
+ int32 rv;
+ struct net_t *np;
+ char s1[RECLEN];
+
+ if (gp->g_class == GC_UDP) strcpy(s1, "udp"); else strcpy(s1, "gate");
+ np = NULL; 
+ *ret_np = NULL;
+ /* real driven by gate output caught also bit select from vectored wire */
+ if (nd_lhs_chk)
+  {
+   rv = __chk_lhsexpr(xp, LHS_DECL);
+   if (!rv) return(FALSE);
+  }
+ switch ((byte) xp->optyp) {
+  case ID: case GLBREF:
+   np = xp->lu.sy->el.enp;
+   if (__get_netwide(np) > 1 && !nd_1bit)
+    {
+     __sgfwarn(538,
+      "%s %s output %s wider than 1 bit - assuming select of low bit", 
+      gp->gmsym->synam, s1, __to_idnam(xp));
+     /* cannot be vectored vector since implied select */
+     __chk_lhsdecl_scalared(xp);
+    }
+   break;
+  case OPEMPTY: break;
+  case ISNUMBER:
+   if (xp->is_real) goto is_real; 
+   /*FALLTHRU */
+  case NUMBER:
+   __sgfwarn(539,
+    "%s %s output drives constant - made unconnected",
+    gp->gmsym->synam, s1);
+   return(FALSE);
+  case REALNUM:
+  case ISREALNUM:
+is_real:
+   __sgferr(793,
+    "%s %s output cannot connect to real number", gp->gmsym->synam, s1); 
+   return(FALSE);
+  case LSB:
+   np = xp->lu.x->lu.sy->el.enp;
+   break;
+  case PARTSEL:
+   /* if part select, must change to bit select with warning */
+   /* done after check psel called - needs normalized indices */
+   if (!nd_1bit)
+    {
+     __sgfwarn(540, "%s %s output drives part select - assign to low bit",
+      gp->gmsym->synam, s1);
+    }
+   np = xp->lu.x->lu.sy->el.enp;
+   break;
+  case LCB:
+   __sgferr(794, "%s %s output terminal cannot be connected to concatenate",
+    gp->gmsym->synam, s1);
+   return(FALSE);
+  default:
+   __sgferr(795, "%s %s output expression %s illegal",
+    gp->gmsym->synam, s1,  __msgexpr_tostr(__xs, xp));
+   return(FALSE);
+  }
+ *ret_np = np;
+ return(TRUE);
+}
+
+/*
+ * check declarative type continuous assignments from one module
+ * know cmsym NULL to get here
+ *
+ * this is point where 1 bit continuous assignments removed and added
+ * as gates of type (token ASSIGN)
+ *
+ * quasi cont. assign checked in statement checking code
+ */
+static void chk_contas(void)
+{
+ register struct conta_t *cap;
+ int32 lhs_gd, dnum, sav_ecnt, cwid, num_gd1bca, cai, num_cas;
+ struct conta_t *last_cap, *cap2, *ca1bit_hd, *last_1bcap, *catab;
+ struct expr_t *lhsx, *rhsx;
+ struct paramlst_t *dhdr;
+
+ last_cap = NULL;
+ ca1bit_hd = NULL;
+ last_1bcap = NULL;
+ __expr_rhs_decl = TRUE;
+ num_cas = 0;
+ for (cap = __inst_mod->mcas, num_gd1bca = 0; cap != NULL;)
+  {
+   __sfnam_ind = cap->casym->syfnam_ind;
+   __slin_cnt = cap->casym->sylin_cnt;
+
+   num_cas++;
+   /* error if cont. assign lhs not a wire */
+   lhsx = cap->lhsx;
+   rhsx = cap->rhsx;
+
+   sav_ecnt = __pv_err_cnt;
+   lhs_gd = __chk_lhsexpr(lhsx, LHS_DECL);
+   /* index error still allow return of T from chk lhs expr */
+   if (__pv_err_cnt > sav_ecnt) lhs_gd = FALSE;
+
+   cwid = lhsx->szu.xclen;
+   __chking_conta = TRUE;
+   __rhs_isgetpat = FALSE;
+   /* notice rhs here may be left as the $getpattern function call */
+   __chk_rhsexpr(rhsx, cwid);
+
+   if (rhsx->is_real || lhsx->is_real)
+    __sgferr(796,
+     "real expression illegal on either side of continuous assign");
+   __chking_conta = FALSE;
+   if (__rhs_isgetpat)
+    {
+     nd_1bit_concat(lhsx);
+     if (cap->ca_du.pdels != NULL)
+      __sgferr(797,
+       "continuous assign with $getpattern on right cannot have delay"); 
+     lhsx->getpatlhs = TRUE;
+     __rhs_isgetpat = FALSE;
+     goto nxt_ca;
+    }
+   if (cap->ca_du.pdels != NULL)
+    {
+     dhdr = __copy_dellst(cap->ca_du.pdels);
+     if ((dnum = __chk_delparams(dhdr, "continuous assignment delay",
+      FALSE)) == -1) cap->ca_du.pdels = NULL;
+     else if (dnum > 3)
+      {
+       __sgferr(798, "continuous assign has more than 3 delays (%d)", dnum);
+       cap->ca_du.pdels = NULL;
+      }
+     /* SJM 09/28/02 - anything but 1v need 4v table so conta del all bits */ 
+     __free_dellst(dhdr);
+    }
+   /* must convert to 1 bit form if needed */
+   if (lhs_gd && lhsx->szu.xclen == 1)
+    {
+     /* link out 1 bit ca onto tmp list */ 
+     cap2 = cap->pbcau.canxt;
+
+     num_gd1bca++;
+     if (last_1bcap == NULL) ca1bit_hd = cap;
+     else last_1bcap->pbcau.canxt = cap;
+     cap->pbcau.canxt = NULL;
+     last_1bcap = cap;
+
+     if (last_cap == NULL) __inst_mod->mcas = cap2;
+     else last_cap->pbcau.canxt = cap2;
+     /* notice last_cap stays same when splicing out */
+     cap = cap2;
+     continue;
+    }
+
+nxt_ca:
+   /* only get here is lhs wider than 1 bit */
+   if (cap->ca_hasst)
+    {
+     if ((cap->ca_stval & 7) == 0 || (cap->ca_stval & 0x38) == 0)
+      __sgferr(1276,
+       "wider than one bit vector continuous assign highz[01] strength unsupported");
+    }
+   last_cap = cap;
+   cap = cap->pbcau.canxt;
+  }
+ __expr_rhs_decl = FALSE;
+ /* next re-allocate 1bit cas on end of mgates array */ 
+ /* since conta already checked can convert and not apply gaet checks */
+ if (num_gd1bca > 0)
+  {
+   cnv_1bcas_into_garr(num_gd1bca, ca1bit_hd); 
+   num_cas -= num_gd1bca;
+  }
+
+ /* final step is to convert conta to array same as m nets conversion */
+ /* from now on (same as with nets) - must index through array to traverse */
+ /* contas */
+ catab = NULL;
+ __inst_mod->mcanum = num_cas;
+ if (__inst_mod->mcanum != 0)
+  {   
+   catab = (struct conta_t *)
+    __my_malloc(__inst_mod->mcanum*sizeof(struct conta_t)); 
+  }
+ for (cai = 0, cap = __inst_mod->mcas; cai < __inst_mod->mcanum; cai++)
+  {
+   cap2 = cap->pbcau.canxt;
+
+   catab[cai] = *cap; 
+   __my_free((char *) cap, sizeof(struct conta_t));
+   catab[cai].pbcau.canxt = NULL;
+
+   cap = cap2;
+  }
+ __inst_mod->mcas = catab; 
+}
+
+/*
+ * convert the separated out 1 bit cas to gates and free cas
+ *
+ * tricky step required to point all symbols for name back to gate which
+ * may (probably will) be moved by re-alloc
+ */
+static void cnv_1bcas_into_garr(int32 n1bcas, struct conta_t *ca1bit_hd) 
+{
+ register int32 gi;
+ struct conta_t *cap, *cap2;
+ int32 osize, nsize;
+ struct gate_t *gp;
+ struct net_t *dum_np;
+
+ dum_np = NULL;
+ /* mark needed because must change back to conta for vpi_ */ 
+ __inst_mod->mod_1bcas  = TRUE;
+
+ /* reallocate mgates to add room at end */
+ osize = __inst_mod->mgnum*sizeof(struct gate_t);
+ nsize = osize + n1bcas*sizeof(struct gate_t);
+ /* common for no gates in design - only 1 bit contas */
+ /* know nsize at least one or will not get here */
+ if (osize == 0) { gp = (struct gate_t *) __my_malloc(nsize); }
+ else 
+  {
+   gp = (struct gate_t *) __my_realloc((char *) __inst_mod->mgates,
+    osize, nsize);
+  }
+ __inst_mod->mgates = gp;
+ /* reset each el egp field */
+ for (gi = 0; gi < __inst_mod->mgnum; gi++)
+  {
+   gp = &(__inst_mod->mgates[gi]);
+   gp->gsym->el.egp = gp;
+  }
+
+ /* notice number is index of one after */
+ gi = __inst_mod->mgnum;
+ __inst_mod->mgnum += n1bcas; 
+ for (cap = ca1bit_hd; cap != NULL; gi++)
+  {
+   gp = &(__inst_mod->mgates[gi]);
+   convert_1bca_togate(gp, cap);
+   
+   /* just move the conta built inst. */ 
+   gp->gsym = cap->casym;
+   gp->gsym->el.egp = gp;
+   gp->gsym->sytyp = SYM_PRIM;
+   if (!chk_gate_source(gp, gp->gpins[0], FALSE, FALSE, &dum_np))
+    {
+     __free_xtree(gp->gpins[0]);
+     set_unc_gateterm(gp, 0);
+    }
+   /* free and link out conta */
+   cap2 = cap->pbcau.canxt;
+   /* ca scheduled event array not yet allocated */
+   __my_free((char *) cap, sizeof(struct conta_t));
+   cap = cap2;
+  }
+}
+
+/*
+ * convert a 1 bit continuous assign to a gate and link on end
+ * of module's gate list - returns F if not converted
+ *
+ * this fills passed gate struct from within mgates
+ * notice this can not return nil
+ * other fields initialized later
+ */
+static struct gate_t *convert_1bca_togate(struct gate_t *gp, 
+ struct conta_t *cap)
+{
+ /* caller sets gsym */
+ gp->gsym = NULL;
+ gp->gmsym = __ca1bit_syp;
+
+ gp->gpnum = 2;
+ gp->g_hasst = cap->ca_hasst;
+ gp->g_stval = cap->ca_stval;
+ gp->g_delrep = cap->ca_delrep;
+ /* assign delay union */
+ gp->g_du = cap->ca_du;
+ gp->schd_tevs = NULL;
+ gp->g_class = GC_LOGIC;
+ gp->g_pdst = FALSE;
+ gp->g_unam = FALSE;
+ gp->g_gone = FALSE;
+ gp->gstate.wp = NULL;
+ gp->gattrs = NULL;
+
+ /* build the special output, temp form */
+ gp->gpins = (struct expr_t **) __my_malloc(2*sizeof(struct expr_t *));
+ gp->gpins[0] = cap->lhsx;
+ gp->gpins[1] = cap->rhsx;
+ /* caller must free and unlink continuous assign */
+ return(gp);
+}
+
+/*
+ * for get pattern continuous assigment must be scalar wire or concat of
+ * scalar wires (lhs of conta assign non wire already caught)
+ */
+static void nd_1bit_concat(struct expr_t *lhsx)
+{
+ register struct expr_t *catndp;
+
+ if (lhsx->optyp == LCB)
+  {
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    chk_getpat_nonscal(catndp->lu.x);
+   return;
+  }
+ __sgferr(800,
+  "$getpattern continous assign lvalue must be concatenate of scalar wires");
+}
+
+/*
+ * error if non scalar net
+ * know this is wire
+ */
+static void chk_getpat_nonscal(struct expr_t *lhsx)
+{
+ struct net_t *np;
+
+ if (lhsx->optyp == GLBREF)
+  { 
+   __sgferr(801,
+    "$getpattern assign lvalue hierarchical path reference %s illegal",
+    __to_idnam(lhsx));
+   return;
+  }
+ if (lhsx->optyp != ID)
+  {
+   __sgferr(802, "$getpattern assign lvalue element %s not a simple wire",
+     __msgexpr_tostr(__xs, lhsx));
+   return;
+  }
+ np = lhsx->lu.sy->el.enp;
+ if (np->n_isavec)
+  __sgferr(966,
+   "$getpattern continous assign lvalue element %s not a scalar",
+   __to_idnam(lhsx));
+ if (np->n_stren)
+  __sgferr(967,
+   "$getpattern continous assign lvalue element %s has strength",
+   __to_idnam(lhsx));
+}
+
+/*
+ * check a user function definition
+ * this must undeclare if error because cannot check call
+ * know function defined at top level of __inst_mod
+ */
+static void chk_funcdef(struct task_t *tskp)
+{
+ int32 saverr_cnt;
+ 
+ __cur_tsk = tskp;
+ saverr_cnt = __pv_err_cnt;
+ /* check definition args */
+ chk_fdef_args(tskp);
+
+ /* SJM 09/28/01 - see if func call other non sys func */
+ __func_has_fcall = FALSE;
+
+ /* first check all statements normally */ 
+ __chk_lstofsts(tskp->tskst);
+ if (__func_has_fcall) tskp->fhas_fcall = TRUE;
+
+ /* check all sub statements for illegal delay controls */
+ /* also sets name_assigned_to if name somewhere on assign lhs */
+ __task_has_delay = FALSE;
+ __task_has_tskcall = FALSE;
+ __name_assigned_to = FALSE;
+ __locfnamsyp = tskp->tskpins->tpsy;
+ __nbsti = -1;
+ __checking_only = FALSE;
+ __chk_nodel_lstofsts(tskp->tskst);
+ __checking_only = TRUE;
+ if (!__name_assigned_to)
+  __gfwarn(647, tskp->tsksyp->syfnam_ind, tskp->tsksyp->sylin_cnt,
+   "no assignment to function name %s in body", tskp->tsksyp->synam);
+ /* must leave name assigned to off, unless checking func. def body */
+ else __name_assigned_to = FALSE;
+ if (__pv_err_cnt != saverr_cnt) tskp->tsksyp->sydecl = FALSE;
+ __cur_tsk = NULL;
+}
+
+/*
+ * check a function def arguments
+ * all ports inputs and 1 required
+ */
+static void chk_fdef_args(struct task_t *tskp)
+{
+ register struct task_pin_t *tpp;
+ int32 ai;
+ struct sy_t *syp;
+ struct net_t *np;
+ char s1[RECLEN];
+
+ /* function definition return value missing */
+ if ((tpp = tskp->tskpins) == NULL)
+  __misc_gfterr(__FILE__, __LINE__, tskp->tsksyp->syfnam_ind,
+   tskp->tsksyp->sylin_cnt);
+ if (tpp->tpsy->sytyp != SYM_N) __arg_terr(__FILE__, __LINE__);  
+ /* assign err replaces unused err, this rhs of func. return value assign */
+ np = tpp->tpsy->el.enp;
+ /* notice not set n_onprocrhs since only needed for wires */ 
+ if (np->nrngrep == NX_CT) np->nu.ct->n_onrhs = TRUE;
+ 
+ if ((tpp = tpp->tpnxt) == NULL)
+  {
+   __gferr(867, tskp->tsksyp->syfnam_ind, tskp->tsksyp->sylin_cnt,
+    "function %s definition requires at least one input argument",
+    tskp->tsksyp->synam);
+   return;
+  }
+ for (ai = 1; tpp != NULL; tpp = tpp->tpnxt, ai++)
+  {
+   if (tpp->trtyp != IO_IN)
+    {
+     syp = tpp->tpsy;
+     __gferr(868, syp->syfnam_ind, syp->sylin_cnt,
+      "function %s argument %s illegal - must be input",
+      __to_ptnam(s1, tpp->trtyp), syp->synam);
+    }
+   if (tpp->tpsy->sytyp != SYM_N) __arg_terr(__FILE__, __LINE__);  
+   np = tpp->tpsy->el.enp;
+   if (np->nrngrep == NX_CT) np->nu.ct->n_onlhs = TRUE;
+   /* SJM 01/14/1999 - arrays illegal formal function arguments */
+   if (np->n_isarr)
+    {
+     syp = tpp->tpsy;
+     __gferr(869, syp->syfnam_ind, syp->sylin_cnt,
+      "function %s definition entire array formal argument %s (pos. %d) illegal - must be simple variable",
+      tskp->tsksyp->synam, syp->synam, ai);
+    }
+  }
+}
+
+/*
+ * check func. def. and task statement list
+ * if func. def. and delay error, else just set flag for optimization
+ */
+extern void __chk_nodel_lstofsts(struct st_t *fhdstp)
+{
+ register struct st_t *stp;
+
+ /* then check for illegal in func def. statements */
+ for (stp = fhdstp; stp != NULL; stp = stp->stnxt) chk_nodel_stmt(stp);
+}
+
+/*
+ * check task body statement list for time movement constructs
+ * for functions emits errors, for rest sets flags
+ * for every named block sets time movement task bits for optimization
+ *
+ * think could allow distant disables and causes and still could optimize
+ * but for now using function rules
+ * assumes normal statement checking already finished
+ * notice always called after statement checking so disables fixed up
+ */
+static void chk_nodel_stmt(struct st_t *stp)
+{
+ char s1[RECLEN];
+
+ switch ((byte) stp->stmttyp) {
+  case S_NULL: case S_STNONE: break;
+  /* legal statements */
+  case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA:
+   /* notice for rhs delay control - wrong delay control caught at dctrl */
+   if (!__checking_only || !__name_assigned_to)
+    {
+     if (lhsexpr_hassym(stp->st.spra.lhsx, __locfnamsyp))
+      __name_assigned_to = TRUE;
+    }
+   break;
+  /* these do not count as assignment to name */ 
+  case S_QCONTA: case S_QCONTDEA:
+   break;
+  case S_IF:
+   __chk_nodel_lstofsts(stp->st.sif.thenst);
+   if (stp->st.sif.elsest != NULL) __chk_nodel_lstofsts(stp->st.sif.elsest);
+   break;
+  case S_CASE:
+   {
+    register struct csitem_t *csip;
+    struct csitem_t *dflt_csip;
+   
+    /* first always default or place holder for default in no st */
+    dflt_csip = stp->st.scs.csitems;
+    for (csip = dflt_csip->csinxt; csip != NULL; csip = csip->csinxt)
+     {
+      __chk_nodel_lstofsts(csip->csist);
+     }
+    if (dflt_csip->csist != NULL) __chk_nodel_lstofsts(dflt_csip->csist);
+   }
+   break;
+  case S_FOREVER:
+  case S_WHILE:
+   __chk_nodel_lstofsts(stp->st.swh.lpst);
+   break;
+  case S_REPEAT:
+   __chk_nodel_lstofsts(stp->st.srpt.repst);
+   break;
+  case S_FOR:
+   {
+    struct for_t *frs;
+
+    frs = stp->st.sfor;
+    chk_nodel_stmt(frs->forassgn);
+    chk_nodel_stmt(frs->forinc);
+    __chk_nodel_lstofsts(frs->forbody);
+   }
+   break;
+  /* illegal statements */
+  case S_TSKCALL:
+   {
+    struct expr_t *tkxp;
+
+    tkxp = stp->st.stkc.tsksyx;
+    /* $stop system tasks requires iact schedule */
+    if (strcmp(tkxp->lu.sy->synam, "$stop") == 0) __iact_must_sched = TRUE;
+    
+    if ((tkxp->optyp == ID || tkxp->optyp == GLBREF)
+     && *(tkxp->lu.sy->synam) != '$')
+     {
+      if (__checking_only) __task_has_tskcall = TRUE;
+      else
+       {
+        __gferr(870, stp->stfnam_ind, stp->stlin_cnt,
+         "user task %s enable illegal in function body", __to_idnam(tkxp));
+       }
+     }
+   }
+   break;
+  /* for these check sub statement even though must have delay */
+  case S_DELCTRL:
+   if (stp->st.sdc->actionst != NULL)
+    __chk_nodel_lstofsts(stp->st.sdc->actionst);
+   goto bad_fdstmt;
+  case S_WAIT:
+   __chk_nodel_lstofsts(stp->st.swait.lpst);
+   goto bad_fdstmt;
+  case S_UNFJ: 
+   { 
+    int32 fji;
+    struct st_t *fjstp;
+    int32 sav_has_tskcall, has_timemove;
+
+    has_timemove = FALSE;
+    sav_has_tskcall = __task_has_tskcall;
+    __task_has_delay = TRUE;
+    __task_has_tskcall = FALSE;
+    for (fji = 0;; fji++)
+     {
+      if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+      __chk_nodel_lstofsts(fjstp);
+      if (__task_has_delay || __task_has_tskcall) has_timemove = TRUE;
+     }
+    if (!has_timemove)
+     {
+      __gfwarn(606, stp->stfnam_ind, stp->stlin_cnt,
+        "unnamed fork-join components probably have no time movement");
+     }
+    if (!__task_has_tskcall) __task_has_tskcall = sav_has_tskcall;
+    /* always has time fork-join always has time move since needs threads */ 
+   }
+   goto bad_fdstmt;
+  /* non blocking procedural assign implies time movement so can not */
+  /* be in function that is execed outside of time */ 
+  case S_NBPROCA:
+  /* these are simple delay statements */
+  case S_CAUSE:
+bad_fdstmt:
+   if (__checking_only) __task_has_delay = TRUE;
+   else
+    {
+     __gferr(870, stp->stfnam_ind, stp->stlin_cnt,
+      "%s illegal in function body", __to_sttyp(s1, stp->stmttyp));
+    }
+   break;
+  /* possibly illegal statements */
+  case S_NAMBLK:
+   /* legal except for fork */
+   {
+    struct task_t *nbtskp;
+    int32 sav_has_delay, sav_has_tskcall;
+
+    sav_has_delay = __task_has_delay;
+    sav_has_tskcall = __task_has_tskcall;
+    __task_has_delay = FALSE;
+    __task_has_tskcall = FALSE;
+    nbtskp = stp->st.snbtsk;
+    __push_nbstk(stp);
+    if (nbtskp->tsktyp == FORK)
+     {
+      int32 fji;
+      int32 has_timemove;
+      struct st_t *stp2;
+      struct st_t *fjstp;
+
+      stp2 = nbtskp->tskst;
+      has_timemove = FALSE;
+      /* named fork-join is task with 1 UNFJ statement */
+      for (fji = 0;; fji++)
+       {
+        if ((fjstp = stp2->st.fj.fjstps[fji]) == NULL) break;
+        __chk_nodel_lstofsts(fjstp);
+        if (__task_has_delay || __task_has_tskcall) has_timemove = TRUE;
+       }
+      if (!has_timemove)
+       {
+        __gfwarn(606, stp->stfnam_ind, stp->stlin_cnt,
+         "named fork-join components probably have no time movement");
+       }
+      if (!__task_has_tskcall) __task_has_tskcall = sav_has_tskcall;
+      goto bad_fdstmt;
+     }
+    __chk_nodel_lstofsts(nbtskp->tskst);
+    if (!__task_has_delay) __task_has_delay = sav_has_delay;
+    if (__task_has_tskcall) nbtskp->thas_tskcall = TRUE;
+    else __task_has_tskcall = sav_has_tskcall;
+    __pop_nbstk();
+   }
+   break;
+  case S_UNBLK:
+   /* must check statements below */
+   {
+    register struct st_t *stp2;
+
+    for (stp2 = stp->st.sbsts; stp2 != NULL; stp2 = stp2->stnxt) 
+     chk_nodel_stmt(stp2);
+   }
+   break;
+  case S_DSABLE:
+   /* this may or may not be a delay */
+   chk_nodel_dsable(stp);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * check a function definition (body) disable 
+ * think possibly here, can still optimize and avoid thread for tasks even
+ * if they disable other tasks - but for now forcing thread.
+ */
+static void chk_nodel_dsable(struct st_t *stp)
+{
+ struct expr_t *dsxp;
+ struct sy_t *syp;
+ int32 dummy;
+
+ /* task disable illegal - named block ok if above in func. body */
+ dsxp = stp->st.sdsable.dsablx;
+ /* assume above */
+ syp = dsxp->lu.sy;
+ if (syp->sytyp == SYM_TSK)
+  {
+   if (__checking_only)
+    {
+     /* if disabling current task still above */
+     if (syp->el.etskp != __cur_tsk) goto set_has_del;
+     return;
+    }
+   __gferr(873, stp->stfnam_ind, stp->stlin_cnt,
+    "task %s disable illegal in function body", __to_idnam(dsxp));
+   return;
+  }
+ /* cannot disable anything outside of function also - qualified name */
+ /* ok if within function */
+ /* cannot disable anything not upward for function */
+ if (dsxp->optyp == GLBREF)
+  { 
+   if (__checking_only) goto set_has_del;
+   __gferr(874, stp->stfnam_ind, stp->stlin_cnt,
+    "disable of cross module reference %s illegal in function", 
+    __to_idnam(dsxp));
+   return;
+  }   
+ /* if called from func., ok to disable function name */
+ if (syp->sytyp == SYM_F)
+  {
+   if (syp->el.etskp != __cur_tsk)
+    {
+     if (__checking_only) goto set_has_del;
+
+     __gferr(866, stp->stfnam_ind, stp->stlin_cnt,
+      "disable of function %s illegal inside other function %s", 
+      __to_idnam(dsxp), __cur_tsk->tsksyp->synam);
+    }
+   return;
+  }
+ /* OK to disable function from within body */
+ if (__nbsti >= 0 && __is_upward_dsable_syp(syp,
+  __nbstk[__nbsti]->st.snbtsk->tsksymtab, &dummy)) return;
+ if (__checking_only) goto set_has_del;
+
+ __gferr(875, stp->stfnam_ind, stp->stlin_cnt,
+  "disable of non enclosing named block %s inside function %s illegal",
+  __msgexpr_tostr(__xs, dsxp), __locfnamsyp->synam);
+ return;
+
+set_has_del:
+ __task_has_delay = TRUE;
+}
+
+/*
+ * return T if lhs expression contains lhs symbol
+ */
+static int32 lhsexpr_hassym(struct expr_t *ndp, struct sy_t *syp)
+{
+ register struct expr_t *ndp2;
+
+ switch ((byte) ndp->optyp) {
+   case ID:
+    if (ndp->lu.sy == syp) return(TRUE);
+    break;
+   case GLBREF: case NUMBER: case REALNUM: break;
+   case LSB: case PARTSEL:
+    if (ndp->lu.x->lu.sy == syp) return(TRUE);
+    break;
+   case LCB:
+    /* know only 1 level of lhs concatenates (at least by here) */
+    for (ndp2 = ndp->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     {
+      /* widths get set after checking */
+      if (ndp2->lu.x->lu.sy == syp) return(TRUE);
+     }
+    break;
+   default: __case_terr(__FILE__, __LINE__);
+  }
+ return(FALSE);
+}
+
+/*
+ * RANGE MANIPULATION ROUTINES
+ */
+
+/*
+ * get width of net - cannot be called unless n_isavec is TRUE 
+ * used when know vector width needed even if array 
+ *
+ * notice always know range is no inst. specific - if defparam in
+ * in range assigned to must really split.
+ */
+extern int32 __get_netwide(struct net_t *np)
+{
+ register int32 i1, i2;
+ int32 wid;
+
+ if (!np->n_isavec) return(1);  
+
+ i1 = i2 = 0;
+ if (np->nrngrep == NX_CT)
+  {
+   i1 = (int32) __contab[np->nu.ct->nx1->ru.xvi];
+   i2 = (int32) __contab[np->nu.ct->nx2->ru.xvi];
+
+   if (i1 == -1 || i2 == -2) __arg_terr(__FILE__, __LINE__);
+   wid = (i1 >= i2) ? (i1 - i2 + 1) : (i2 - i1 + 1);
+   return(wid);
+  }
+ return(np->nwid);
+}
+
+/*
+ * get array width (i.e. width of range or number of elements in memory) 
+ */
+extern int32 __get_arrwide(struct net_t *np)
+{
+ register int32 w1, w2;
+
+ w1 = w2 = 0;
+ switch ((byte) np->nrngrep) {
+  case NX_CT:
+   w1 = (int32) __contab[np->nu.ct->ax1->ru.xvi];
+   w2 = (int32) __contab[np->nu.ct->ax2->ru.xvi];
+   break;
+  case NX_ARR:
+   w1 = np->nu.rngarr->ai1;
+   w2 = np->nu.rngarr->ai2;
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return((w1 >= w2) ? (w1 - w2 + 1) : (w2 - w1 + 1));
+}
+
+/*
+ * get vector range extremes independent of representation 
+ * (for both compile and run times)  
+ * this can only be called for known vector not scalar
+ *
+ * returns false if cannot determine range (unfolded still)
+ * this will return vector width of array
+ * must use bit to determine if vector or not 
+ */
+extern void __getwir_range(struct net_t *np, int32 *xr1, int32 *xr2)
+{
+ register int32 r1, r2;
+
+ r1 = r2 = 0;
+ switch ((byte) np->nrngrep) {
+  case NX_CT:
+   r1 = (int32) __contab[np->nu.ct->nx1->ru.xvi];
+   r2 = (int32) __contab[np->nu.ct->nx2->ru.xvi];
+   break;
+  case NX_ARR: r1 = np->nu.rngarr->ni1; r2 = np->nu.rngarr->ni2; break;
+  case NX_DWIR: r1 = np->nu.rngdwir->ni1; r2 = np->nu.rngdwir->ni2; break;
+  case NX_WIR: r1 = np->nu.rngwir->ni1; r2 = np->nu.rngwir->ni2; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ *xr1 = r1;
+ *xr2 = r2;
+}
+
+/*
+ * run time get array range extremes independent of representation 
+ * must use bit to determine if array or not
+ *
+ * returns false if cannot determine range (unfolded still)
+ * this will return array width of array
+ */
+extern void __getarr_range(struct net_t *np, int32 *mr1, int32 *mr2, int32 *arrwid)
+{
+ register int32 r1, r2;
+
+ r1 = r2 = 0;
+ /* notice fall thru on things with no array range */
+ switch ((byte) np->nrngrep) {
+  case NX_CT:
+   if (np->n_isarr)
+    {
+     r1 = (int32) __contab[np->nu.ct->ax1->ru.xvi];
+     r2 = (int32) __contab[np->nu.ct->ax2->ru.xvi];
+    }
+   break;
+  case NX_ARR: r1 = np->nu.rngarr->ai1; r2 = np->nu.rngarr->ai2; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ *arrwid = (r1 > r2) ? r1 - r2 + 1 : r2 - r1 + 1;
+ *mr1 = r1;
+ *mr2 = r2;
+}
+
+/*
+ * routine to map normalized h:0 form index back to input value
+ * know indi in range and wire type determines if array or wire select
+ */
+extern int32 __unnormalize_ndx(struct net_t *np, int32 indi)
+{
+ int32 r1, r2, obwid;
+
+ if (np->n_isarr) __getarr_range(np, &r1, &r2, &obwid);
+ else if (np->n_isavec) __getwir_range(np, &r1, &r2);
+ else return(indi); 
+ if (r1 >= r2) return(r2 + indi); else return(r2 - indi);
+}
+
+/*
+ * map normalized h:0 constant index to value in source world
+ * already processed to word32 and know in range 
+ *
+ * just like C implied truncating assign to 32 bit value
+ * constants are already normalized during compilation
+ */
+extern int32 __unmap_ndx(int32 biti, int32 ri1, int32 ri2)
+{
+ if (ri1 >= ri2) { if (ri1 != 0) biti -= ri2; }
+ else { if (ri2 != 0) biti = ri2 - biti; }
+ return(biti);
+}
+
+/*
+ * VARIABLE INITIALIZE ASSIGNMENT CHECKING ROUTINES
+ */
+
+/*
+ * check a module's var init rhs exprs
+ */
+static void chk_varinits(void)
+{
+ register struct varinitlst_t *initp;
+
+ initp = __inst_mod->mvarinits;
+ for (; initp != NULL; initp = initp->varinitnxt)
+  {
+   __sfnam_ind = initp->init_syp->syfnam_ind;
+   __slin_cnt = initp->init_syp->sylin_cnt;
+
+   if (!__chk_paramexpr(initp->init_xp, initp->init_syp->el.enp->nwid))
+    {
+     __sgferr(3431,
+      "variable assign to %s initializing expression %s illegal - numbers and parameters only",
+      initp->init_syp->synam, __msgexpr_tostr(__xs, initp->init_xp));
+
+     /* need to still add value of x to prevent further errors */
+     __free2_xtree(initp->init_xp);
+     /* SJM 09/30/04 - LOOKATME - maybe needs to be right width x's */
+     initp->init_xp->szu.xclen = 1;
+     __set_numval(initp->init_xp, ALL1W, ALL1W, 1);
+    }
+  }
+}
+
+/* 
+ * STATEMENT CHECKING ROUTINES
+ */
+
+
+/*
+ * routines to check fix up statements
+ */
+static void chk_stmts(void)
+{
+ register struct ialst_t *ialp;
+
+ for (ialp = __inst_mod->ialst; ialp != NULL; ialp = ialp->ialnxt)
+  {
+   __cur_tsk = NULL;
+   __chk_lstofsts(ialp->iastp);
+   /* also check no del statement lists to set various task/block bits */
+   __task_has_delay = FALSE;
+   __task_has_tskcall = FALSE;
+   __nbsti = -1;
+   __chk_nodel_lstofsts(ialp->iastp);
+  } 
+}
+
+/*
+ * check a statement list
+ */
+extern void __chk_lstofsts(struct st_t *hdstp)
+{
+ register struct st_t *stp;
+
+ /* notice legal empty statement list just does nothing here */
+ for (stp = hdstp; stp != NULL; stp = stp->stnxt) chk_1stmt(stp);
+}
+
+/*
+ * check 1 statement
+ */
+static void chk_1stmt(struct st_t *stp)
+{
+ int32 save_lno, save_fni, cwid, is_regform;
+
+ /* save callers values */
+ save_fni = __sfnam_ind;
+ save_lno = __slin_cnt;
+ __sfnam_ind = stp->stfnam_ind;
+ __slin_cnt = stp->stlin_cnt;
+
+ switch ((byte) stp->stmttyp) {
+  case S_NULL: case S_STNONE: break;
+  /* if delay prefix action part of delay control */
+  case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA: case S_NBPROCA:
+   __chk_lhsexpr(stp->st.spra.lhsx, LHS_PROC);
+   if (stp->st.spra.lhsx->optyp == LCB && stp->st.spra.lhsx->szu.xclen == 1)
+    __sgfwarn(542, "procedural assign lvalue 1 bit concatenate unusual");
+   cwid = stp->st.spra.lhsx->szu.xclen;
+   __chk_rhsexpr(stp->st.spra.rhsx, cwid);
+
+   /* SJM 10/08/04 - for Ver 2001 because WBITS can be 64 - must widen */
+   /* unsized constant (unsiznum bit in expr rec on) to lhs width */
+   if (stp->st.spra.rhsx->optyp == NUMBER && stp->st.spra.rhsx->unsiznum
+    && stp->st.spra.rhsx->szu.xclen < stp->st.spra.lhsx->szu.xclen)
+    {
+     stp->st.spra.rhsx = __widen_unsiz_rhs_assign(stp->st.spra.rhsx,
+      stp->st.spra.lhsx->szu.xclen);
+    }
+   break;
+  case S_IF:
+   __chk_rhsexpr(stp->st.sif.condx, 0);
+   __chk_lstofsts(stp->st.sif.thenst);
+   if (stp->st.sif.elsest != NULL) __chk_lstofsts(stp->st.sif.elsest);
+   break;
+  case S_CASE:
+   chk_case(stp);
+   break;
+  case S_WAIT:
+   /* notice this is level sensitive condition cannot be event expr */
+   /* DBG remove -- */
+   if (stp->st.swait.lpx == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   __chk_rhsexpr(stp->st.swait.lpx, 0);
+   if (__isleaf(stp->st.swait.lpx) && stp->st.swait.lpx->optyp != ID
+    && stp->st.swait.lpx->optyp != GLBREF)
+    __sgfinform(413, "wait expression constant - use loop");
+
+   __chk_lstofsts(stp->st.swait.lpst);
+   break;
+  case S_FOREVER:
+   __chk_lstofsts(stp->st.swh.lpst);
+   break;
+  case S_REPEAT:
+   if (stp->st.srpt.repx != NULL)
+    {
+     __chk_rhsexpr(stp->st.srpt.repx, 0);
+     if (stp->st.srpt.repx->szu.xclen > WBITS)
+      __sgfwarn(543,
+       "truncation of repeat count from %d to 32 bits - high bits ignored",
+       stp->st.srpt.repx->szu.xclen);
+    }
+   else __sgferr(803, "required repeat statement repeat count missing");
+   __chk_lstofsts(stp->st.srpt.repst);
+   break;
+  case S_WHILE:
+   if (stp->st.swh.lpx != NULL)
+    {
+     __chk_rhsexpr(stp->st.swh.lpx, 0);
+     /* SJM 04/05/02 - this warning is wrong - while not truncated - REMOVED */
+     /* --- 
+     if (stp->st.swh.lpx->szu.xclen > WBITS)
+      __sgfwarn(544,
+       "truncation of while expression from %d to 32 bits - high bits ignored",
+       stp->st.swh.lpx->szu.xclen);
+     --- */
+    }
+   else __sgferr(804, "while statement required while expression missing");
+   __chk_lstofsts(stp->st.swh.lpst);
+   break;
+  case S_FOR:
+   {
+    struct for_t *frs;
+
+    /* notice for statement must use temporaries of right width */
+    frs = stp->st.sfor;
+    chk_1stmt(frs->forassgn);
+    if (frs->fortermx != NULL) __chk_rhsexpr(frs->fortermx, 0);
+    chk_1stmt(frs->forinc);
+    __chk_lstofsts(frs->forbody);
+   }
+   break;
+  case S_DELCTRL:
+   chk_dctrl(stp->st.sdc);
+   break;
+  case S_NAMBLK:
+   __chk_lstofsts(stp->st.snbtsk->tskst);
+   break;
+  case S_UNBLK:
+   __chk_lstofsts(stp->st.sbsts);
+   break;
+  case S_UNFJ:
+   {
+    register int32 fji;
+    struct st_t *fjstp;
+
+    /* 1 sub stmt only, for unnamed begin-end will be unnamed block */ 
+    for (fji = 0;; fji++)
+     {
+      if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+      /* SJM 09/24/01 - this can be 2 stmts for for (for assgn then for) */
+      __chk_lstofsts(fjstp);
+     }
+   }
+   break;
+  case S_TSKCALL:
+   __chk_tskenable(stp);
+   break;
+  case S_QCONTA:
+   /* quasi-continuous assign is either proc. assign or force */
+   chk_qclvalue(stp->st.sqca->qclhsx, stp->st.sqca->qcatyp, &is_regform);
+   __set_lhswidth(stp->st.sqca->qclhsx);
+   cwid = stp->st.sqca->qclhsx->szu.xclen;
+   __chk_rhsexpr(stp->st.sqca->qcrhsx, cwid);
+   stp->st.sqca->regform = is_regform;
+
+   /* SJM 10/08/04 - for Ver 2001 because WBITS can be 64 - must widen */
+   /* unsized constant (unsiznum bit in expr rec on) to lhs width */
+   if (stp->st.sqca->qcrhsx->optyp == NUMBER
+    && stp->st.sqca->qcrhsx->unsiznum
+    && stp->st.sqca->qcrhsx->szu.xclen < stp->st.sqca->qclhsx->szu.xclen)
+    {
+     stp->st.sqca->qcrhsx = __widen_unsiz_rhs_assign(stp->st.sqca->qcrhsx,
+      stp->st.sqca->qclhsx->szu.xclen);
+    }
+
+   /* SJM 07/16/03 - illegal if rhs expr. contains lhs being forced lvalue */ 
+   chk_circular_qc_stmt(stp);
+   break;
+  case S_QCONTDEA:
+   /* quasi-continuous deassign is either proc. deassign or release */
+   chk_qclvalue(stp->st.sqcdea.qcdalhs, stp->st.sqcdea.qcdatyp, &is_regform);
+   __set_lhswidth(stp->st.sqcdea.qcdalhs);
+   stp->st.sqcdea.regform = is_regform;
+   break;
+  case S_DSABLE:
+   chk_disable(stp);
+   break;
+  case S_CAUSE:
+   {
+    struct expr_t *ndp;
+    struct sy_t *syp;
+    struct net_t *np;
+
+    ndp = stp->st.scausx;
+    if (ndp->optyp != GLBREF && ndp->optyp != ID)
+     {
+      __sgferr(806, "cause argument %s must be simple event name",
+       __msgexpr_tostr(__xs, ndp));
+      break;
+     }
+    syp = ndp->lu.sy;
+    if (syp->sytyp == SYM_N) np = syp->el.enp; else np = NULL;
+    if (syp->sytyp != SYM_N || np->ntyp != N_EVENT)
+     {
+      if (np == NULL) __to_sytyp(__xs, syp->sytyp);
+      else __to_wtnam(__xs, np);
+      __sgferr(807,
+       "cause right hand side symbol \"%s\" type %s is not an event",
+       __to_idnam(ndp), __xs);
+     }
+    /* cause is lhs assign for event */
+    if (np->nrngrep == NX_CT) np->nu.ct->n_onlhs = TRUE;
+   }
+   break;
+   default: __case_terr(__FILE__, __LINE__);
+  }
+ /* restore callers values */
+ __sfnam_ind = save_fni;
+ __slin_cnt = save_lno;
+}
+
+/*
+ * routine to widen unsized number to lhs context
+ *
+ * know only called for literal numbers - maybe literal from folding
+ * and think folded bit will be on for all but fcalls but not using
+ *
+ * this is special widen with x/z extend in addition to sign extend
+ * but if word32, does not extend the high 1 
+ *
+ * needed from Ver 2001 change because WBITS can now be 64 so for
+ * any of the assigns (proc, cont, func/task input and force/assign)
+ * need to use lhs context to widen unsized number to that size
+ * with sign and x/z extend
+ */
+extern struct expr_t *__widen_unsiz_rhs_assign(struct expr_t *rhsx,
+ int32 lhswid)
+{
+ int32 owlen, bi;
+ word32 *owp;
+ struct xstk_t *xsp;
+
+ owlen = wlen_(rhsx->szu.xclen);
+ push_xstk_(xsp, rhsx->szu.xclen);
+ owp = &(__contab[rhsx->ru.xvi]);
+ memcpy(xsp->ap, owp, 2*owlen*WRDBYTES);
+
+ /* notice not lhs signed because signed does not corss = */
+ if (rhsx->has_sign) __sgn_xtnd_widen(xsp, lhswid);
+ else
+  {
+   /* if x/z - b part high bit on, then widen both a and b parts */
+   bi = get_bofs_(rhsx->szu.xclen - 1);
+   if ((xsp->bp[owlen - 1] & (1 << bi)) != 0) 
+    {
+     /* notice since x/z bit on - can treat as sign extend widen since */
+     /* reduces to x/z widen case */
+     __sgn_xtnd_widen(xsp, lhswid);
+    }
+  }
+ rhsx = bld_num_expr(xsp);
+ __pop_xstk();
+ return(rhsx);
+}
+
+/*
+ * check a case statement
+ *
+ * SJM 05/10/04 - new algorithm turns off sign bit for widening if needed
+ * for * every expression if select expr word32, if select expr signed
+ * then compares are signed if match signed else unsigned
+ */
+static void chk_case(struct st_t *stp)
+{
+ register struct csitem_t *csip;
+ register struct exprlst_t *xplp;
+ int32 xwid, maxselwid, nd_realcnv, nd_unsgn_widen;
+ struct csitem_t *dflt_csip;
+
+ dflt_csip = stp->st.scs.csitems;
+ /* first find maximum selection expression width */
+ csip = dflt_csip->csinxt;
+ for (maxselwid = 0; csip != NULL; csip = csip->csinxt)
+  {
+   /* check each expression in possible list */
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     xwid = __get_rhswidth(xplp->xp);
+     if (xwid > maxselwid) maxselwid = xwid;
+    }
+  }
+ /* including selector itself */
+ xwid = __get_rhswidth(stp->st.scs.csx);
+
+ if (xwid > maxselwid) maxselwid = xwid;
+ stp->st.scs.maxselwid = (word32) maxselwid;
+
+ /* now check expression using max. width context */
+ for (csip = dflt_csip->csinxt; csip != NULL; csip = csip->csinxt)
+  {
+   /* check each expression in possible list */
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     __chk_rhsexpr(xplp->xp, maxselwid);
+    }
+   /* this must be a statement (at least null) */
+   __chk_lstofsts(csip->csist);
+  }
+ __chk_rhsexpr(stp->st.scs.csx, maxselwid);
+
+ if (dflt_csip->csist != NULL) __chk_lstofsts(dflt_csip->csist);
+
+ /* SJM 12/12/03 - because real bit only turned on when rhs expr chk called */ 
+ /* must set the real bits after do all other checking */
+ /* one pass sets the flag if any expr real (select or case item) */
+ csip = dflt_csip->csinxt;
+ nd_unsgn_widen = FALSE;
+ for (nd_realcnv = FALSE; csip != NULL; csip = csip->csinxt)
+  {
+   /* check each expression in possible list */
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     if (xplp->xp->is_real) nd_realcnv = TRUE;
+     if (!xplp->xp->has_sign) nd_unsgn_widen = TRUE;
+    }
+  }
+ if (stp->st.scs.csx->is_real) nd_realcnv = TRUE;
+ if (stp->st.scs.csx->has_sign) nd_unsgn_widen = TRUE;
+
+ if (!nd_realcnv && !nd_unsgn_widen) return;
+
+ for (csip = dflt_csip->csinxt; csip != NULL; csip = csip->csinxt)
+  {
+   /* check each expression in possible list */
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     if (nd_realcnv)
+      {
+       if (!xplp->xp->is_real) xplp->xp->cnvt_to_real = TRUE;
+      }
+     if (nd_unsgn_widen)
+      {
+       if (xplp->xp->has_sign) xplp->xp->unsgn_widen = TRUE;
+      }
+    }
+  }
+ if (nd_realcnv)
+  {
+   if (!stp->st.scs.csx->is_real) stp->st.scs.csx->cnvt_to_real = TRUE;
+  } 
+ if (nd_unsgn_widen)
+  {
+   if (stp->st.scs.csx->has_sign) stp->st.scs.csx->unsgn_widen = TRUE;
+  } 
+}
+
+/*
+ * check a delay control statement
+ */
+static void chk_dctrl(struct delctrl_t *dctp)
+{
+ int32 sav_ecnt;
+ struct paramlst_t *dhdr;
+
+ /* even if error keeep checking - also know list has exactly 1 element */
+ if (dctp->dctyp == DC_EVENT || dctp->dctyp == DC_RHSEVENT)
+  {
+   /* SJM 06/01/04 - if implicit list form "@(*)" no expr to check */
+   if (!dctp->implicit_evxlst)
+    {
+     __chk_evxpr(dctp->dc_du.pdels->plxndp);
+    }
+  }
+ /* pound form normal rhs expression checked here */
+ /* notice delay controls even if numbers scaled at execution time */
+ /* always only and at least 1 value */  
+ else 
+  {
+   dhdr = __copy_dellst(dctp->dc_du.pdels);
+   __chk_delparams(dhdr, "procedural delay control", FALSE);
+   __free_dellst(dhdr);
+  }
+
+ if (dctp->repcntx != NULL)
+  {
+   __chk_rhsexpr(dctp->repcntx, 0);
+
+   if (dctp->repcntx->szu.xclen > WBITS)
+    {
+     __sgfwarn(543,
+      "truncation of right hand side event control repeat count from %d to 32 bits - high bits ignored",
+      dctp->repcntx->szu.xclen);
+    }
+  }
+
+ sav_ecnt = __pv_err_cnt;
+ /* for RHS delay control know is assign, else can be spliced up list */
+ /* algorithm here is bottom up because this may process implicit @* forms */
+ if (dctp->actionst != NULL) __chk_lstofsts(dctp->actionst);
+
+ /* final step (must be done after statement checking) build the */ 
+ /* all rhs form evxpr list */ 
+ if (dctp->implicit_evxlst)
+  {
+   /* if errors in stmts can't build this list - make it empty */
+   if (sav_ecnt > __pv_err_cnt)
+    {
+     __sgfwarn(3134, "implicit @(*) event control action statement has syntax errors - can't build implicit change list");
+     __bld_unc_expr();
+     dctp->dc_du.pdels->plxndp = __root_ndp;
+     return;
+    }
+   if (dctp->actionst == NULL) 
+    {
+     __sgfwarn(3135, "implicit @(*) event control no action statement - no implicit change list");
+     __bld_unc_expr();
+     dctp->dc_du.pdels->plxndp = __root_ndp;
+     return;
+    }
+
+   /* if nothing in list - expr become op empty and no triggers */
+   __impl_evlst_hd = __impl_evlst_tail = NULL; 
+   bld_stlst_evxlst(dctp->actionst);
+   if (__impl_evlst_hd != NULL)
+    {
+     dctp->dc_du.pdels->plxndp = bld_evlst_comma_expr();
+     __impl_evlst_hd = __impl_evlst_tail = NULL; 
+
+     /* SJM 08/03/04 - can't call check here because building normalized */
+     /* to h:0 expressions but check uses actual src read decl ranges */ 
+    }
+  }
+}
+
+/*
+ * bld the list of change ev xpr lists - check for duplicates
+ */
+static void bld_stlst_evxlst(struct st_t *hdstp)
+{
+ register struct st_t *stp;
+
+ /* notice legal empty statement list just does nothing here */
+ for (stp = hdstp; stp != NULL; stp = stp->stnxt)
+  {
+   bld_stmt_evxlst(stp);
+  }
+}
+
+/*
+ * build the evxprlist for the action stmt for one @(*) implicit ev ctrl
+ *
+ * this must be run after the action stmt is checked for syntax errors
+ * this must be run before pass 3 v prp because of for loops
+ */
+static void bld_stmt_evxlst(struct st_t *stp)
+{
+ switch ((byte) stp->stmttyp) {
+  case S_NULL: case S_STNONE: break;
+  case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA: case S_NBPROCA:
+   /* know if lhs IS form bit or array select - will be split */
+   bld_lhs_impl_evxlst(stp->st.spra.lhsx);
+   bld_rhs_impl_evxlst(stp->st.spra.rhsx);
+   break;
+  case S_IF:
+   bld_rhs_impl_evxlst(stp->st.sif.condx);
+   bld_stlst_evxlst(stp->st.sif.thenst);
+   if (stp->st.sif.elsest != NULL) bld_stmt_evxlst(stp->st.sif.elsest);
+   break;
+  case S_CASE:
+   /* case is special case because selection and case item expressions */ 
+   /* need to be added to list */
+   bld_case_evxlst(stp);
+   break;
+  case S_WAIT:
+   bld_stlst_evxlst(stp->st.swait.lpst);
+   break;
+  case S_FOREVER:
+   bld_stlst_evxlst(stp->st.swh.lpst);
+   break;
+  case S_REPEAT:
+   if (stp->st.srpt.repx != NULL)
+    {
+     bld_rhs_impl_evxlst(stp->st.srpt.repx);
+    }
+   bld_stlst_evxlst(stp->st.srpt.repst);
+   break;
+  case S_WHILE:
+   if (stp->st.swh.lpx != NULL)
+    {
+     bld_rhs_impl_evxlst(stp->st.swh.lpx);
+    }
+   bld_stlst_evxlst(stp->st.swh.lpst);
+   break;
+  case S_FOR:
+   {
+    struct for_t *frs;
+
+    /* notice for statement must use temporaries of right width */
+    frs = stp->st.sfor;
+    bld_stmt_evxlst(frs->forassgn);
+    if (frs->fortermx != NULL) bld_rhs_impl_evxlst(frs->fortermx);
+    bld_stmt_evxlst(frs->forinc);
+    bld_stlst_evxlst(frs->forbody);
+   }
+   break;
+  case S_DELCTRL:
+   /* notice if implicit @(*) form event ctrl - implicit expr list */
+   /* already built - but this needs to also add to any containing */
+   /* list is union of all contained implicit dctrl lists */
+   if (stp->st.sdc->actionst != NULL)
+    {
+     bld_stlst_evxlst(stp->st.sdc->actionst);
+    }
+   break;
+  case S_NAMBLK:
+   bld_stlst_evxlst(stp->st.snbtsk->tskst);
+   break;
+  case S_UNBLK:
+   bld_stlst_evxlst(stp->st.sbsts);
+   break;
+  case S_UNFJ:
+   {
+    register int32 fji;
+    struct st_t *fjstp;
+
+    /* 1 sub stmt only, for unnamed begin-end will be unnamed block */ 
+    for (fji = 0;; fji++)
+     {
+      if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+      /* SJM 09/24/01 - this can be 2 stmts for for (for assgn then for) */
+      bld_stlst_evxlst(fjstp);
+     }
+   }
+   break;
+  case S_TSKCALL:
+   /* task enable out ports are lhs exprs (but sel ndx needs to go in list) */
+   /* does nothing for system tasks */
+   bld_tskenable_evxlst(stp);
+   break;
+  case S_QCONTA: case S_QCONTDEA:
+   /* SJM 06/01/04 - LOOKATME - think quasi-cont stmts can't cause triggers */
+   /* because rhs changes outside of proc time */
+   break;
+  case S_DSABLE: case S_CAUSE:
+   /* SJM 06/01/04 - LOOKATME - think cause is lhs expr here */
+   break;
+   default: __case_terr(__FILE__, __LINE__);
+  }
+}
+
+/*
+ * build case stmt evx lst - tricky because both select and case item 
+ * expr must be added
+ */
+static void bld_case_evxlst(struct st_t *stp)
+{
+ register struct csitem_t *csip;
+ register struct exprlst_t *xplp;
+ struct csitem_t *dflt_csip;
+
+ /* first build expr list element for case select */
+ bld_rhs_impl_evxlst(stp->st.scs.csx);
+
+ dflt_csip = stp->st.scs.csitems;
+ csip = dflt_csip->csinxt;
+ for (;csip != NULL; csip = csip->csinxt)
+  {
+   /* then expr list element for each case item expr */
+   /* usually will be constants so none will be added */
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     bld_rhs_impl_evxlst(xplp->xp);
+    }
+  }
+
+ /* now check expression using max. width context */
+ for (csip = dflt_csip->csinxt; csip != NULL; csip = csip->csinxt)
+  {
+   /* check each expression in possible list */
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     bld_rhs_impl_evxlst(xplp->xp);
+    }
+   bld_stlst_evxlst(csip->csist);
+   /* this must be a statement (at least null) */
+  }
+ if (dflt_csip->csist != NULL) bld_stlst_evxlst(dflt_csip->csist);
+}
+
+/*
+ * build task enable stmt evx lst - output ports are lhs exprs here
+ */
+static void bld_tskenable_evxlst(struct st_t *stp)
+{
+ struct expr_t *xp;
+ struct tskcall_t *tkcp;
+ struct sy_t *syp;
+ struct task_t *tskp;
+ struct task_pin_t *tpp;
+
+ tkcp = &(stp->st.stkc);
+ syp = tkcp->tsksyx->lu.sy;
+ /* SJM 06/01/04 - think system task rhs should not go in sensitivity list */
+ if (syp->sytyp == SYM_STSK) return;
+
+ tskp = tkcp->tsksyx->lu.sy->el.etskp;
+ tpp = tskp->tskpins;
+ for (xp = tkcp->targs; xp != NULL; xp = xp->ru.x, tpp = tpp->tpnxt)
+  {
+   /* output port connections are lvalues but must trigger on any indices */
+   if (tpp->trtyp == IO_OUT) bld_lhs_impl_evxlst(xp->lu.x);
+   else bld_rhs_impl_evxlst(xp->lu.x);
+  }
+}
+
+/*
+ * build rhs impl event expr list - all vars, bsel and psels go in list
+ *
+ * SJM 06/01/04 ### ??? FIXME - right to assume not including XMRs
+ */
+static void bld_rhs_impl_evxlst(struct expr_t *rhsx)
+{
+ struct expr_t *evxp;
+ struct exprlst_t *xplp;
+ struct expr_t *ndp2;
+
+ switch ((byte) rhsx->optyp) {
+  case ID:
+   /* DBG remove -- */
+   if (rhsx->lu.sy->el.enp->n_isaparam) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   goto add_expr;
+  case LSB: case PARTSEL:
+add_expr:
+   evxp = __copy_expr(rhsx);
+   if (!xp_in_evxlst(evxp)) 
+    {
+     xplp = (struct exprlst_t *) __my_malloc(sizeof(struct exprlst_t));
+     xplp->xp = evxp;
+     xplp->xpnxt = NULL; 
+     if (__impl_evlst_hd == NULL) __impl_evlst_hd = __impl_evlst_tail = xplp;
+     else { __impl_evlst_tail->xpnxt = xplp; __impl_evlst_tail = xplp; }
+    }
+   break;
+  case GLBREF:
+   /* assuming XMR not in sensitivity list */
+   break;
+  case NUMBER: case ISNUMBER: case OPEMPTY:
+  case REALNUM: case ISREALNUM:
+   break;
+  case QUEST:
+   bld_rhs_impl_evxlst(rhsx->lu.x);
+   bld_rhs_impl_evxlst(rhsx->ru.x->ru.x);
+   bld_rhs_impl_evxlst(rhsx->ru.x->lu.x);
+   break;
+  case FCALL:
+   /* this is func call side */
+   for (ndp2 = rhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+    {
+     bld_rhs_impl_evxlst(ndp2->lu.x);
+    }
+   break; 
+  case LCB:
+   /* know by here concatenates only one level */
+   for (ndp2 = rhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+    {
+     bld_rhs_impl_evxlst(ndp2->lu.x);
+    }
+   break; 
+  default:
+   /* handle unary or binary operators */
+   /* DBG remove -- */
+   if (rhsx->lu.x == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   bld_rhs_impl_evxlst(rhsx->lu.x);
+   if (rhsx->ru.x != NULL) bld_rhs_impl_evxlst(rhsx->ru.x);
+ }
+}
+
+/*
+ * build lhs impl event expr list
+ *
+ * only variable bit select are rhs expr that need to go in list
+ * must handle concats - otherwise only needs to look at bsel/arrsel 
+ *
+ * know all expr checking and folding completed before here
+ */
+static void bld_lhs_impl_evxlst(struct expr_t *lhsx)
+{
+ register struct expr_t *ndp2;
+
+ switch ((byte) lhsx->optyp) {
+  case ID: case GLBREF: case OPEMPTY: break;
+  case LSB:
+   /* only need to add variable selects of bit select or array select */
+   if (lhsx->ru.x->optyp == NUMBER || lhsx->ru.x->optyp == ISNUMBER)
+    break;
+   /* DBG remove -- */
+   if (__is_const_expr(lhsx->ru.x)) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   bld_rhs_impl_evxlst(lhsx->ru.x);
+   break;
+  case PARTSEL:
+   /* know ranges are constant */
+   break;
+  case LCB:
+   /* know lhs concatenates never nested */
+   for (ndp2 = lhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+    {
+     bld_lhs_impl_evxlst(ndp2->lu.x);
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * return T if expr already in the ev xpr list  
+ */
+static int32 xp_in_evxlst(struct expr_t *evxp) 
+{
+ register struct exprlst_t *xplp;
+
+ for (xplp = __impl_evlst_hd; xplp != NULL; xplp = xplp->xpnxt)
+  {
+   /* SJM 06/01/04 - ### ??? LOOKATME - is this expr compare right */ 
+   if (__cmp_xpr(evxp, xplp->xp)) return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * build implicit ev list comma expr from expr list
+ *
+ * notice needs to left associate and edges never appear
+ */
+static struct expr_t *bld_evlst_comma_expr(void)
+{
+ register struct exprlst_t *xplp;
+ struct expr_t *rootndp, *ndp;
+ struct exprlst_t *xplp2;
+ int32 first_time;
+
+ first_time = TRUE;
+ ndp = NULL;
+ rootndp = NULL;
+ for (xplp = __impl_evlst_hd; xplp != NULL; xplp = xplp->xpnxt)
+  {
+   if (first_time)
+    {
+     rootndp = xplp->xp;
+     first_time = FALSE;
+     continue;
+    }
+   ndp = __alloc_newxnd();
+   ndp->optyp = OPEVCOMMAOR;
+   ndp->lu.x = rootndp; 
+   ndp->ru.x = xplp->xp;
+   rootndp = ndp; 
+  }
+ /* DBG remove -- */
+ if (__debug_flg) __dbg_msg(__msgexpr_tostr(__xs, rootndp));
+ /* -- */
+ /* free the expr list but not the contained exprs */
+ for (xplp = __impl_evlst_hd; xplp != NULL;)
+  {
+   xplp2 = xplp->xpnxt;
+   __my_free((char *) xplp, sizeof(struct exprlst_t));
+   xplp = xplp2;
+  }
+ return(rootndp);
+}
+
+/*
+ * STMT CHECKING ROUTINES FOR QC STMTS
+ */
+
+/*
+ * check a quasi continous assign/deassign reg. or force wire or reg
+ * most checks special qc reg concatenate form
+ *
+ * assuming here there are 2 disjoint32 forms - force [normal decl. lhs] or
+ * force [assign style register form] - concatentates cannot mix the 2
+ */
+static void chk_qclvalue(struct expr_t *ndp, word32 qctyp,
+ int32 *is_rgform)
+{
+ register struct expr_t *ndp2;
+ int32 cnt;
+ char s1[RECLEN];
+
+ *is_rgform = TRUE;
+ /* one level concatenates for either reg or wire forms ok */
+ /* for legal concatenate can not mix reg and wire elements */
+ if (ndp->optyp == LCB)
+  {
+   for (cnt = 1, ndp2 = ndp->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x,
+    cnt++)
+    {
+     /* if this is normal declarative (wire only) lhs - must be force */
+     if (!__xhas_reg(ndp2->lu.x))
+      {
+       if (qctyp != FORCE && qctyp != RELEASE)
+        {
+         __sgferr(808,
+           "%s concatenate lvalue (pos. %d) contains wires - use force/release",
+          __to_qctyp(s1, qctyp), cnt);
+         return;
+        }
+       if (cnt == 1) *is_rgform = FALSE;
+       else if (*is_rgform)
+        {
+         __sgferr(1150,
+          "%s concatenate lvalue (pos %d) wire conflicts with reg form",  
+          __to_qctyp(s1, qctyp), cnt);
+         return;
+        }
+       continue;
+      }
+     /* must be reg form */
+     if (!nd_qcreg(ndp2->lu.x))
+      {
+       __sgferr(810,
+        "%s concatenate lvalue (pos %d) not a scalared wire or simple reg",
+        __to_qctyp(s1, qctyp), cnt);
+       return;
+      }
+     if (!*is_rgform)
+      {
+       __sgferr(1150,
+        "%s concatenate lvalue (pos %d) reg conflicts with wire form",
+        __to_qctyp(s1, qctyp), cnt);
+       return;
+      }
+    }
+  }
+ else
+  {
+   /* if this is normal declarative (wire only) lhs - must be force */
+   if (!__xhas_reg(ndp))
+    {
+     if (qctyp != FORCE && qctyp != RELEASE)
+      {
+       __sgferr(808, "%s lvalue contains wires - use force/release",
+        __to_qctyp(s1, qctyp));
+       return;
+      }
+     *is_rgform = FALSE;
+    }
+   else
+    {
+     if (!nd_qcreg(ndp))
+      {
+       __sgferr(810, "%s lvalue not a scalared wire or simple reg",
+        __to_qctyp(s1, qctyp));
+       return; 
+      } 
+    }
+  }
+ /* final step is checking lhs expression */
+ /* know for procedural required simple format already checked for */
+ if (*is_rgform) __chk_lhsexpr(ndp, LHS_PROC);
+ else __chk_lhsexpr(ndp, LHS_DECL);
+
+ /* set used in qc force assign nets - set even if no code gen */
+ set_qc_frcassgn_net(ndp); 
+}
+
+/*
+ * set used in QC stmt bit for all nets on LHS 
+ * always called but does nothing for interactive fixup (pass 2) 
+ */
+static void set_qc_frcassgn_net(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ if (__isleaf(ndp))
+  {
+   if (ndp->optyp == ID || ndp->optyp == GLBREF)
+    {
+     np = ndp->lu.sy->el.enp;
+     if (np->nrngrep != NX_CT) return;
+
+     np->nu.ct->frc_assgn_in_src = TRUE;
+     /* setting mod flag for task to - i.e. no task qc assign/force flag */
+     /* SJM 12/23/02 - only needs to be set during elaboration - if */
+     /* added from PLI not needed */
+     __inst_mod->mhas_frcassgn = TRUE;
+    }
+   return;
+  }
+ if (ndp->lu.x != NULL) set_qc_frcassgn_net(ndp->lu.x);
+ if (ndp->ru.x != NULL) set_qc_frcassgn_net(ndp->ru.x);
+}
+
+/*
+ * return T if expr. is a register
+ * nd reg for id's - this is where node type is unknown
+ * this reg cannot be a real
+ */
+static int32 nd_qcreg(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ if ((ndp->optyp != ID && ndp->optyp != GLBREF) || ndp->lu.sy->sytyp != SYM_N)
+  return(FALSE);
+ np = ndp->lu.sy->el.enp;
+ if (np->n_isaparam) return(FALSE);
+ if (np->ntyp >= NONWIRE_ST && np->ntyp != N_EVENT) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * must check qc assign/force (not deassign/release) for cirular use
+ * of lhs component on rhs 
+ * error if lhs net used on rhs of assign/force
+ *
+ * SJM 07/16/03 new check added since code core dumps with stack overflow
+ * otherwise
+ * LOOKATME - currently pessimistic - different XMR inst or bit still error
+ */
+static void chk_circular_qc_stmt(struct st_t *stp)
+{
+ register struct expr_t *lhsx, *rhsx;
+ int32 qctyp;
+ struct expr_t *catndp, *catelx, *lhsx2;
+ struct net_t *np;
+ char s1[RECLEN];
+
+ lhsx = stp->st.sqca->qclhsx;
+ rhsx = stp->st.sqca->qcrhsx;
+ qctyp =   stp->st.sqca->qcatyp;
+ if (lhsx->optyp == LCB)
+  {
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    {
+     catelx = __get_lvalue_idndp(catndp->lu.x);
+     /* DBG remove -- */
+     if (catelx->optyp != ID && catelx->optyp != GLBREF) 
+      __misc_terr(__FILE__, __LINE__);
+     /* -- */
+     np = catelx->lu.sy->el.enp;
+
+     if (rhs_expr_has_net(rhsx, np))
+      {
+       if (qctyp != FORCE && qctyp != RELEASE)
+        {
+         __sgferr(3409,
+           "net %s in concatenate on both left and right hand sides of QC %s - illegal infinite loop",
+           np->nsym->synam, __to_qctyp(s1, qctyp));
+         return;
+        }
+      }
+    }
+   return;
+  }
+ lhsx2 = __get_lvalue_idndp(lhsx);
+ /* DBG remove -- */
+ if (lhsx2->optyp != ID && lhsx2->optyp != GLBREF) 
+  __misc_terr(__FILE__, __LINE__);
+ /* -- */
+ np = lhsx2->lu.sy->el.enp;
+ if (rhs_expr_has_net(rhsx, np))
+  {
+   __sgferr(3409,
+    "net %s on both left and right hand sides of QC %s - illegal infinite loop",
+    np->nsym->synam, __to_qctyp(s1, qctyp));
+  }
+}
+
+/*
+ * get lvalue (lhs expr that is decomposed form concat) expr
+ * for ID/XMR return expr else return left offspring
+ */
+extern struct expr_t *__get_lvalue_idndp(struct expr_t *lhsx)
+{
+ if (lhsx->optyp == GLBREF || lhsx->optyp == ID) return(lhsx);
+ if (lhsx->optyp == LSB || lhsx->optyp == PARTSEL) return(lhsx->lu.x);
+ __misc_terr(__FILE__, __LINE__);
+ return(NULL);
+}
+
+/*
+ * routine to return T if net contained in rhs expr
+ */
+static int32 rhs_expr_has_net(struct expr_t *rhsx, struct net_t *np)
+{
+ if (__isleaf(rhsx))
+  {
+   if (rhsx->optyp == ID || rhsx->optyp == GLBREF) 
+    {
+     if (rhsx->lu.sy->el.enp == np) return(TRUE);
+    }
+   return(FALSE);
+  }
+ if (rhsx->lu.x != NULL) 
+  { if (rhs_expr_has_net(rhsx->lu.x, np)) return(TRUE); }
+ if (rhsx->ru.x != NULL) 
+  { if (rhs_expr_has_net(rhsx->ru.x, np)) return(TRUE); }
+ return(FALSE); 
+}
+
+/*
+ * check a disable statement
+ * tricky because if non global may need to replace with labl/task sym.
+ */
+static void chk_disable(struct st_t *stp)
+{
+ struct expr_t *dsxp;
+ struct sy_t *syp, *syp2;
+ struct symtab_t *sytp;
+ struct sy_t *upsyp;
+ struct gref_t *grp;
+
+ dsxp = stp->st.sdsable.dsablx;
+ /* case 1: global cannot replace if cannot be disabled */
+ if (dsxp->optyp == GLBREF) syp = dsxp->lu.sy;
+ else if (dsxp->optyp == ID)
+  { 
+   /* case 2: ID - make sure can be disabled and look upward */
+   syp = dsxp->lu.sy;
+   /* if not declared, or not disable try to find above */ 
+   if (!syp->sydecl) goto use_syp;
+
+   if (syp->sytyp != SYM_TSK && syp->sytyp != SYM_F
+    && syp->sytyp != SYM_LB)
+    {
+     /* if ID disable and no current task, error */
+     if (__cur_tsk == NULL) goto use_syp;
+
+     /* work upward to task/func or named block that can be disabled */
+     /* know parent of task is module and of module is nil */
+     /* but only look starting one up since syp already set */
+     sytp = __cur_tsk->tsksymtab->sytpar;
+     for (; sytp != NULL; sytp = sytp->sytpar)
+      {
+       if ((syp2 = __get_sym(syp->synam, sytp)) != NULL)
+        {
+         /* if can be disabled, must change ID expr. symbol */
+         /* but statement still points to same expr. */
+         if (syp2->sytyp == SYM_TSK || syp2->sytyp != SYM_F
+          || syp2->sytyp != SYM_LB)
+          { syp = syp2; dsxp->lu.sy = syp; goto use_syp; }
+        }
+      }
+     /* fall thru and use known wrong syp since no alternative */
+    }
+  }
+ else { syp = NULL; __misc_sgfterr(__FILE__, __LINE__); }
+
+ /* disable object not simple name */
+use_syp:
+ if (!syp->sydecl) return;
+ /* if ID and function know ok, if different func. error catch in nodel chk */ 
+ if (dsxp->optyp == ID && syp->sytyp == SYM_F && __cur_tsk != NULL
+  && __cur_tsk->tsktyp == FUNCTION) return;
+
+ /* if error will still be global ID - else from now on normal symbol */
+ if (syp->sytyp != SYM_TSK && syp->sytyp != SYM_LB)
+  {
+   __sgferr(968, "object \"%s\" type %s cannot be disabled",
+    __to_idnam(dsxp), __to_sytyp(__xs, syp->sytyp));
+  }
+ /* know if local, good since accessible local means not in function */
+ /* or checked in special inside function checking code */
+ if (dsxp->optyp == GLBREF)
+  {
+   grp = dsxp->ru.grp; 
+   /* see if symbol table that target is in */
+   /* think gref target symbol table should be set */
+   if (grp->grsytp == NULL) __misc_sgfterr(__FILE__, __LINE__);
+
+   for (sytp = grp->grsytp; sytp != NULL; sytp = sytp->sytpar)
+    {
+     upsyp = sytp->sypofsyt;
+     if (upsyp->sytyp == SYM_TSK && upsyp->el.etskp->tsktyp == FUNCTION)
+      {
+       __sgferr(805,
+        "disable target \"%s\" type %s cannot be inside function",
+        __to_idnam(dsxp), __to_sytyp(__xs, upsyp->sytyp));
+       return;
+      }
+    }  	
+  }
+} 
diff --git a/src/v_fx3.c b/src/v_fx3.c
new file mode 100644
index 0000000..f9555c7
--- /dev/null
+++ b/src/v_fx3.c
@@ -0,0 +1,6730 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * module that fixes and checks net list after all source read
+ * all defparam and global processing in v_grf
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void try_cnvt_parmsel_toconst(struct expr_t *);
+static void cnvt_paramsel_toconst(struct expr_t *, struct net_t *);
+static void cnvt_nonis_selparm(struct net_t *, struct expr_t *,
+ struct expr_t *);
+static void cnvt_is_bselparm(struct net_t *, struct expr_t *, struct expr_t *);
+static void cnvt_is_arrselparm(struct net_t *, struct expr_t *,
+ struct expr_t *);
+static int32 get_nonis_param_ndx(struct net_t *, struct expr_t *);
+static int32 get_is_param_ndx(struct net_t *, struct expr_t *, int32);
+static void cnvt_nonis_pselparm(struct net_t *, struct expr_t *,
+ struct expr_t *, struct expr_t *);
+static void cnvt_is_pselparm(struct net_t *, struct expr_t *, struct expr_t *,
+ struct expr_t *);
+static void chk_struct_rhsexpr(struct expr_t *, int32);
+static int32 chk_rhs_id(struct expr_t *);
+static void unwind_rhsconcats(struct expr_t *);
+static void remove_0width_catrep_els(struct expr_t *);
+static void set_rhswidth(struct expr_t *, int32);
+static void set2_rhswidth(struct expr_t *, int32);
+static void set_fcall_widths(struct expr_t *, struct task_t *);
+static void set_sysfcall_widths(struct expr_t *);
+static void set_rhs_signed(struct expr_t *);
+static int32 find_xbase(struct expr_t *);
+static void setchk_real_expr(struct expr_t *);
+static void real_setchk_quest(struct expr_t *);
+static void chk_specialop_rhsexpr(struct expr_t *);
+static int32 chk_srcbsel(struct expr_t *, int32);
+static int32 chk_srcpsel(struct expr_t *, int32);
+static void chkspecop_fcall(struct expr_t *);
+static int32 chk_mixedsign_relops(struct expr_t *);
+static void fold_subexpr(struct expr_t *);
+static int32 mark_constnd(register struct expr_t *, int32 *);
+static void fold_const(struct expr_t *);
+static int32 is_signed_decimal(struct expr_t *);
+static void chk_ndfolded_specops(struct expr_t *);
+static int32 chk_inrng_bsel(struct expr_t *);
+static int32 chknorm_range(struct expr_t *, int32, int32, char *, int32);
+static int32 in_range(int32, int32, int32, int32 *);
+static int32 chk_inrng_psel(struct expr_t *);
+static void chk_folded_fargs(struct expr_t *);
+static int32 nd_ndxisnum(struct expr_t *, char *, int32);
+static void chk_sysfargs_syntax(struct expr_t *);
+static void chkbld_pli_func(struct expr_t *, int32);
+static void chk_pli_arglist(register struct expr_t *, int32);
+static int32 tfexpr_isrw(struct expr_t *);
+static int32 lhs_is_decl(struct expr_t *);
+static struct tfrec_t *chkalloc_tfrec(struct expr_t *, int32);
+static struct tfarg_t *alloc_tfarg(register struct expr_t *, int32, int32);
+static void chksf_count_drivers(struct expr_t *, int32);
+static int32 is_1bwire(struct expr_t *);
+static void chksf_getpattern(struct sy_t *, struct expr_t *, int32);
+static void sf_errifn(struct sy_t *, int32);
+static void chksf_q_full(struct expr_t *, int32);
+static void chksf_rand(struct expr_t *, int32, int32);
+static int32 chksyn_lhsexpr(struct expr_t *, int32, int32);
+static void unwind_lhsconcats(struct expr_t *);
+static int32 idnd_var(struct sy_t *);
+static int32 nd_reg(struct expr_t *);
+static int32 xpr_hasfcall(struct expr_t *);
+static int32 xpr_has_nonsys_fcall(struct expr_t *);
+static void chk_edge_expr(struct expr_t *);
+static void chk_systskenable(struct st_t *, struct tskcall_t *);
+static void mark_monit_in_src_nets(struct expr_t *);
+static void chkbld_pli_task(struct st_t *, int32);
+static void st_errif_rng(struct sy_t *, int32, int32, int32);
+static void st_errifn(struct sy_t *, int32, int32);
+static void chkst_dumpvars_enable(struct tskcall_t *, int32);
+static void mark_mod_dvars_under(struct mod_t *, int32);
+static void set_iact_dmpv_all_nd_nchgstore(void);
+static void set_iact_dmpvmod_nd_nchgstore(struct mod_t *);
+static void chkst_readmem(struct sy_t *, int32, struct tskcall_t *);
+static int32 nd_unind_arr(struct expr_t *);
+static void chkst_sreadmem(struct sy_t *, int32, struct tskcall_t *);
+static void chkst_sdfannotate_enable(struct tskcall_t *, int32);
+static int32 chk_undef_specparams(struct symtab_t *);
+static int32 chk_1spcpth(struct spcpth_t *);
+static int32 expr_has_nonpth(struct expr_t *, word32 *);
+static void chk_rep_in_fullpth(struct spcpth_t *);
+static char *pth_tostr(char *, struct spcpth_t *, struct pathel_t *,
+ struct pathel_t *);
+static char *pthel_tostr(char *, struct pathel_t *);
+static int32 pth_overlap(struct pathel_t *, struct pathel_t *);
+static void chk_rep_sdpds(struct spfy_t *);
+static struct xpnd_pthel_t *xpnd_pths(struct spfy_t *, int32 *);
+static void chk_spterm(struct expr_t *, char *, char *, int32);
+static int32 chk_1tchk(struct tchk_t *);
+static void chk_tccond(struct expr_t *, char *, char *);
+static void chk_notifier(struct tchk_t *, char *);
+static struct tchk_t *bld_sup_of_suphld(struct tchk_t *);
+static struct tchk_t *bld_rec_of_recrem(struct tchk_t *);
+static void free_spcpths(struct spcpth_t *);
+static void free_frozen_symtab(struct symtab_t *);
+static void free_spcparms(struct net_t *, int32);
+
+/* extern prototypes (maybe defined in this module) */
+extern char *__my_malloc(int32);
+extern void __my_free(char *, int32);
+extern char *__to_idnam(struct expr_t *);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_sytyp(char *, word32);
+extern char *__to_tcnam(char *, word32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char *__to_opname(word32);
+extern struct expr_t *__copy_expr(struct expr_t *);
+extern struct xstk_t *__eval2_xpr(struct expr_t *);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern char *__msgnumexpr_tostr(char *, struct expr_t *, int32);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern struct paramlst_t *__copy_dellst(struct paramlst_t *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern int32 __isleaf(struct expr_t *);
+extern struct expr_t *__dup_concat(int32, struct expr_t *);
+extern struct expr_t *__find_catend(struct expr_t *);
+extern int32 __nd_ndxnum(struct expr_t *, char *, int32);
+extern void __free2_xtree(struct expr_t *);
+extern void __init_xnd(struct expr_t *);
+extern void __set_numval(struct expr_t *, word32, word32, int32);
+extern int32 __get_netwide(struct net_t *);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern int32 __is_paramconstxpr(struct expr_t *, int32);
+extern void __rhspsel(register word32 *, register word32 *, register int32,
+ register int32);
+extern int32 __get_rhswidth(struct expr_t *);
+extern int32 __get_widthclass(struct expr_t *);
+extern void __narrow_sizchg(register struct xstk_t *, int32);
+extern void __sizchg_widen(register struct xstk_t *, int32);
+extern void __sgn_xtnd_widen(struct xstk_t *, int32);
+extern void __getarr_range(struct net_t *, int32 *, int32 *, int32 *);
+extern void __getwir_range(struct net_t *, int32 *, int32 *);
+extern int32 __cnt_tfargs(register struct expr_t *);
+extern int32 __chk_lhsexpr(struct expr_t *, int32);
+extern void __chkbld_vpi_systf_func(struct expr_t *);
+extern void __pli_func_sizetf(struct expr_t *);
+extern void __set_lhswidth(struct expr_t *);
+extern int32 __nd_wire(struct expr_t *);
+extern int32 __chk_lhsdecl_scalared(struct expr_t *);
+extern void __set_expr_onrhs(struct expr_t *);  
+extern int32 __is_scope_sym(struct sy_t *); 
+extern void __chk_fmt(register struct expr_t *, byte *); 
+extern void __chkbld_vpi_systf_task(struct st_t *);  
+extern void __set_xtab_errval(void);
+extern void __bld_xtree(int32);
+extern void __xtract_wirng(struct expr_t *, struct net_t **, int32 *, int32 *);
+extern void __free_xtree(struct expr_t *);
+extern void __chk_spec_delay(struct expr_t *, char *);
+extern void __free_dellst(struct paramlst_t *);
+extern int32 __chk_numdelay(struct expr_t *, char *);
+extern void __init_tchk(struct tchk_t *, word32);
+extern void __free_tchks(struct tchk_t *);
+extern void __free_xprlst(struct exprlst_t *);
+extern int32 __expr_has_glb(struct expr_t *);
+extern int32 __alloc_is_cval(int32);
+extern int32 __allocfill_cval_new(word32 *, word32 *, int32);
+extern int32 __alloc_shareable_cval(word32, word32, int32);
+extern int32 __alloc_shareable_rlcval(double);
+extern struct expr_t *__widen_unsiz_rhs_assign(struct expr_t *, int);
+
+extern void __pv_warn(int32, char *,...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __gfinform(int32, word32, int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __ia_err(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __misc_sgfterr(char *, int32);
+
+extern struct opinfo_t __opinfo[];
+extern word32 __masktab[];
+
+/*
+ * ROUTINES TO PROCESS AND CHECK RHS EXPRESSIONS
+ */
+
+/*
+ * routine to check a rhs expr.
+ * order must be structural, fold all constant (folds params), and
+ * finally check all embedded selects
+ *
+ * all there is to rhs expression checking
+ */
+extern int32 __chk_rhsexpr(struct expr_t *ndp, int32 csiz)
+{
+ int32 saverr_cnt;
+
+ saverr_cnt = __pv_err_cnt;
+ /* intercept and convert any selects from paramters to num or is num */ 
+ /* this finds all in expr. - returns F if error */ 
+ if (!__isleaf(ndp))
+  {
+   try_cnvt_parmsel_toconst(ndp);
+   if (saverr_cnt != __pv_err_cnt) return(FALSE);
+  }
+
+ /* this can also be called before parameter values (fixed) */
+ /* substitution to real operator done here */
+ chk_struct_rhsexpr(ndp, csiz);
+ /* in case expr. contains declared non wire symbol cannot try to fold */
+ if (saverr_cnt != __pv_err_cnt) return(FALSE);
+
+ /* emit warning for word32 relations comparisons - needed before folding */
+ chk_mixedsign_relops(ndp);
+
+ /* LOOKATME - is here a problem folding analog expressions */
+ /* notice that width know everywhere - so if correct all folding right */
+ /* if error still to be caught, will make reasonable guess for width */
+ fold_subexpr(ndp);
+ /* after folding need checking that requires fold constants */
+ /* for selects and function call arguments */
+ chk_ndfolded_specops(ndp);
+ if (ndp->is_real) ndp->ibase = BDBLE;
+
+ if (saverr_cnt != __pv_err_cnt) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * convert all selects from parameters into constants
+ */
+static void try_cnvt_parmsel_toconst(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ if (__isleaf(ndp)) return;
+ if (ndp->optyp == LSB)
+  {
+   np = ndp->lu.x->lu.sy->el.enp;
+   if (np->n_isaparam && !np->nu.ct->p_specparam)
+    cnvt_paramsel_toconst(ndp, np);
+   else try_cnvt_parmsel_toconst(ndp->ru.x);
+   return;
+  }
+ if (ndp->optyp == PARTSEL)
+  {
+   np = ndp->lu.x->lu.sy->el.enp;
+   if (np->n_isaparam && !np->nu.ct->p_specparam)
+    cnvt_paramsel_toconst(ndp, np);
+   else
+    {
+     try_cnvt_parmsel_toconst(ndp->ru.x->lu.x);
+     try_cnvt_parmsel_toconst(ndp->ru.x->ru.x);
+    }
+   return;
+  }
+
+ if (ndp->lu.x != NULL) 
+  {
+   if (!__isleaf(ndp->lu.x)) try_cnvt_parmsel_toconst(ndp->lu.x); 
+  }
+ if (ndp->ru.x != NULL) 
+  {
+   if (!__isleaf(ndp->ru.x)) try_cnvt_parmsel_toconst(ndp->ru.x); 
+  }
+}
+
+/*
+ * intercept before any checking and convert to number or IS number
+ *
+ * returns F on error - must set width and handle all checking
+ * since no more processing for this rhs expr.
+ * works because nothing under here - changes guts and under of ndp to num.
+ * know current module in cur mod
+ *
+ * LOOKATME - now handle constant selects from parameter arrays
+ */
+static void cnvt_paramsel_toconst(struct expr_t *ndp, struct net_t *np)
+{
+ struct expr_t *ndx1, *ndx2;
+ char selnam[RECLEN], s1[RECLEN];
+
+ /* parameter array index ok for reals, anything else is error */
+ if (np->ntyp == N_REAL && !np->n_isarr)
+  {
+   __sgferr(896, "bit or part select from real parameter %s illegal",
+    np->nsym->synam);
+   return;
+  }
+ if (np->n_isarr && ndp->optyp == PARTSEL)
+  {
+   __sgferr(896, "part select from parameter array %s illegal",
+    np->nsym->synam);
+   return;
+  }
+
+ if (np->n_isarr) strcpy(selnam, "array");
+ else if (np->n_isavec) strcpy(selnam, "bit");
+ else
+  {
+   __sgferr(896, "select from scalar parameter %s illegal", np->nsym->synam);
+   return;
+  }
+ /* step 1: check and convert indices to 32 bit values */
+ if (ndp->optyp == LSB)
+  {
+   /* index must be correct rhs expr. */
+   ndx1 = ndp->ru.x;
+   ndx2 = NULL;
+   if (!__chk_rhsexpr(ndx1, 0)) return;
+   if (ndx1->optyp != NUMBER && ndx1->optyp != ISNUMBER)
+    {
+     /* SJM 11/14/03 - must allow variable bsel from param during sim */
+     if (!np->n_isarr)
+      {
+       return;
+      }
+     else 
+      {
+       __sgferr(926,
+        "parameter %s select %s[%s] index must be constant expression",
+        selnam, np->nsym->synam, __msgexpr_tostr(__xs, ndx1));
+      } 
+     return;
+    }
+   /* convert to either number or is number, 32 bits - maybe x */
+   sprintf(s1, "parameter %s select index", selnam);
+   __nd_ndxnum(ndx1, s1, FALSE);
+  }
+ else if (ndp->optyp == PARTSEL)
+  {
+   ndx1 = ndp->ru.x->lu.x;
+   if (!__chk_rhsexpr(ndx1, 0)) return;
+   __nd_ndxnum(ndx1, "parmeter part select first index",
+    FALSE);
+   ndx2 = ndp->ru.x->ru.x;
+   if (!__chk_rhsexpr(ndx2, 0)) return;
+   __nd_ndxnum(ndx2, "parameter part select second index",
+    FALSE);
+   if (ndx1->optyp != NUMBER && ndx1->optyp != ISNUMBER
+    && ndx2->optyp != NUMBER && ndx2->optyp != ISNUMBER)
+    {
+     __sgferr(926,
+      "parameter %s part select %s both indices must be constant expressions",
+      np->nsym->synam, __msgexpr_tostr(__xs, ndp));
+     return;
+    }
+  }
+ else
+  {
+   __sgferr(822,
+    "bit select from parameter %s index expression non constant",
+    np->nsym->synam);
+   return;
+  }
+ if (ndp->optyp == LSB)
+  {
+   if (ndx1->optyp == NUMBER && np->srep == SR_PNUM)
+    { cnvt_nonis_selparm(np, ndp, ndx1); return; }
+   if (np->n_isarr) cnvt_is_arrselparm(np, ndp, ndx1);
+   else cnvt_is_bselparm(np, ndp, ndx1);
+   return;
+  }
+ /* these return F if out of range or x for either index */
+ if (ndx1->optyp == NUMBER && ndx2->optyp == NUMBER && np->srep == SR_PNUM)
+  cnvt_nonis_pselparm(np, ndp, ndx1, ndx2);
+ else cnvt_is_pselparm(np, ndp, ndx1, ndx2);
+}
+
+/*
+ * convert a parameter non IS bit select to 1 bit constant
+ * or convert parameter array select to value
+ */
+static void cnvt_nonis_selparm(struct net_t *np, struct expr_t *ndp,
+ struct expr_t *ndx)
+{
+ int32 bi, wlen;
+ word32 *wp, av, bv;
+ struct xstk_t *xsp;
+ 
+ bi = get_nonis_param_ndx(np, ndx);
+ if (!np->n_isarr)
+  {
+   if (bi == -1) av = bv = 1L;
+   else
+    {
+     wlen = wlen_(np->nwid);
+     wp = np->nva.wp;
+     av = rhsbsel_(wp, bi);
+     bv = rhsbsel_(&(wp[wlen]), bi); 
+    }
+   __free2_xtree(ndp);
+   __init_xnd(ndp);
+   __set_numval(ndp, av, bv, 1);
+  }
+ else
+  {
+   wlen = wlen_(np->nwid);
+   __free2_xtree(ndp);
+   __init_xnd(ndp);
+   ndp->optyp = NUMBER;
+   ndp->szu.xclen = np->nwid;
+
+   /* parameter arrays never packed */
+   if (bi == -1)
+    {
+     if (np->nwid == WBITS)
+      {
+       ndp->ru.xvi = __alloc_shareable_cval(ALL1W, ALL1W, np->nwid);
+      }
+     else
+      { 
+       push_xstk_(xsp, np->nwid);
+       one_allbits_(xsp->ap, np->nwid);
+       one_allbits_(xsp->bp, np->nwid);
+       ndp->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, wlen);
+       __pop_xstk();
+      }
+    }
+   else
+    {
+     wp = &(np->nva.wp[2*wlen*bi]);
+     if (np->nwid <= WBITS)
+      {
+       ndp->ru.xvi = __alloc_shareable_cval(wp[0], wp[1], np->nwid);
+      }
+     else
+      {
+       ndp->ru.xvi = __allocfill_cval_new(wp, &(wp[wlen]), wlen);
+      }
+    }
+  }
+ ndp->consubxpr = TRUE;
+ ndp->folded = TRUE;
+}
+
+/*
+ * convert a parameter IS bit select to 1 bit constant
+ * know result is an IS constant
+ */
+static void cnvt_is_bselparm(struct net_t *np, struct expr_t *ndp,
+ struct expr_t *ndx)
+{
+ register int32 ii;
+ int32 bi, nbytes, wlen, tmpxvi;
+ word32 *wp, *wp2, av, bv;
+
+ /* bit select will be 1 bit IS constant */
+ nbytes = __inst_mod->flatinum*2*WRDBYTES;  
+
+ /* must not change ndp since still need to access ndx values */
+ /* passes number of words in a part alloc multiplies by 2 for b part too */
+ tmpxvi = __alloc_is_cval(__inst_mod->flatinum);
+ wp = &(__contab[tmpxvi]);
+ memset(wp, 0, nbytes); 
+ 
+ wlen = wlen_(np->nwid);
+ for (ii = 0; ii < __inst_mod->flatinum; ii++) 
+  {  
+   if (ndx->optyp == NUMBER) bi = get_nonis_param_ndx(np, ndx);
+   else if (ndx->optyp == ISNUMBER) bi = get_is_param_ndx(np, ndx, ii); 
+   else { __case_terr(__FILE__, __LINE__); bi = 0; }
+   if (bi == -1) av = bv = 1L;
+   else
+    {
+     wp2 = np->nva.wp;
+     if (np->srep == SR_PISNUM) wp2 = &(wp2[2*wlen*ii]);
+     av = rhsbsel_(wp2, bi);
+     bv = rhsbsel_(&(wp2[wlen]), bi); 
+    }
+   wp[2*ii] = av;
+   wp[2*ii + 1] = bv;
+  }
+
+ /* notice can't free ndp because need to acc ndx (that is contained in it) */
+ __free2_xtree(ndp);
+ __init_xnd(ndp);
+ /* create IS number expr node and then fill it */
+ ndp->optyp = ISNUMBER;
+ ndp->szu.xclen = 1;
+ ndp->ru.xvi = tmpxvi;
+ ndp->consubxpr = TRUE;
+ ndp->consub_is = TRUE;
+ ndp->folded = TRUE;
+}
+
+/*
+ * convert a parameter IS array select to constant
+ * know result is an IS constant
+ */
+static void cnvt_is_arrselparm(struct net_t *np, struct expr_t *ndp,
+ struct expr_t *ndx)
+{
+ register int32 ii;
+ register word32 *wp, *wp2;
+ int32 bi, wsiz, wlen, tmpxvi;
+
+ wlen = wlen_(np->nwid);
+ wsiz = __inst_mod->flatinum*wlen;  
+ /* must not change ndp since still need to access ndx values */
+ tmpxvi = __alloc_is_cval(wsiz);
+ wp = &(__contab[tmpxvi]);
+ memset(wp, 0, 2*WRDBYTES*wsiz); 
+
+ for (ii = 0; ii < __inst_mod->flatinum; ii++) 
+  {  
+   if (ndx->optyp == NUMBER) bi = get_nonis_param_ndx(np, ndx);
+   else if (ndx->optyp == ISNUMBER) bi = get_is_param_ndx(np, ndx, ii); 
+   else { __case_terr(__FILE__, __LINE__); bi = 0; }
+
+   /* array select is 2*wlen value */
+   wp2 = np->nva.wp;
+   if (np->srep == SR_PISNUM) wp2 = &(wp2[2*wlen*ii]);
+   
+   if (bi == -1) 
+    {
+     one_allbits_(&(wp[2*wlen*ii]), np->nwid);
+     one_allbits_(&(wp[2*wlen*ii + wlen]), np->nwid);
+    }
+   else memcpy(&(wp[2*wlen*ii]), wp2, 2*WRDBYTES*wlen);
+  }
+
+ __free2_xtree(ndp);
+ __init_xnd(ndp);
+ ndp->optyp = ISNUMBER;
+ ndp->szu.xclen = np->nwid;
+ ndp->ru.xvi = tmpxvi;
+ ndp->consubxpr = TRUE;
+ ndp->consub_is = TRUE;
+ ndp->folded = TRUE;
+}
+
+/*
+ * access a non IS parameter index expr.
+ * SJM - 08/23/00 - allow rng on params - rng h:0 if no declared range
+ */
+static int32 get_nonis_param_ndx(struct net_t *np, struct expr_t *ndx)
+{
+ register word32 *wp;
+ register int32 bi;
+ int32 ri1, ri2, awid, bi1;
+
+ wp = &(__contab[ndx->ru.xvi]);
+ /* if x/z, warning already emitted but must return -1 */
+ if (wp[1] != 0L) { bi = -1; return(bi); }
+ 
+ /* SJM 09/11/00 - SJM - must check for unnormalized range */
+ if (np->n_isarr) __getarr_range(np, &ri1, &ri2, &awid);
+ else __getwir_range(np, &ri1, &ri2);
+ if (ri1 >= ri2)
+  {
+   if (wp[0] > ri1 || wp[0] < ri2) 
+    {
+bad_rng:
+     __sgfwarn(586,
+      "parameter %s select index %d out of range [%d:%d]",
+      np->nsym->synam, (int32) wp[0], ri1, ri2);
+     bi = -1;
+     return(bi);
+    }
+  }
+ else { if (wp[0] < ri1 || wp[0] > ri2) goto bad_rng; }
+ bi1 = (int32) wp[0];
+ bi = normalize_ndx_(bi1, ri1, ri2);
+ return(bi);
+}
+
+/*
+ * access an IS parameter index expr.
+ * need special routine since no range for parameters
+ * know since index converted to 32 bit IS form before here
+ */
+static int32 get_is_param_ndx(struct net_t *np, struct expr_t *ndx, int32 ii)
+{
+ register int32 bi;
+ register word32 *wp;
+ int32 bi1, ri1, ri2, awid;
+ word32 wval;
+ 
+ wp = &(__contab[ndx->ru.xvi]);
+ /* if x/z, warning already emitted */
+ if (wp[2*ii + 1] != 0L) { bi = -1; return(bi); }
+
+ /* SJM 09/11/00 - SJM - must check for unnormalized range */
+ if (np->n_isarr) __getarr_range(np, &ri1, &ri2, &awid);
+ else __getwir_range(np, &ri1, &ri2);
+ wval = wp[2*ii];
+ if (ri1 >= ri2)
+  {
+   if (wval > ri1 || wval < ri2) 
+    {
+bad_rng:
+     __sgfwarn(586,
+      "parameter %s (instance %s) select index %d out of range [%d:%d]",
+       np->nsym->synam, __msg2_blditree(__xs, __inst_mod->moditps[ii]),
+       wval, ri1, ri2);
+     bi = -1;
+     return(bi);
+    }
+  }
+ else { if (wval < ri1 || wval > ri2) goto bad_rng; }
+ /* good range */
+ bi1 = (int32) wval;
+ bi = normalize_ndx_(bi1, ri1, ri2);
+ return(bi);
+}
+
+/*
+ * convert a parameter non IS part select to psel width constant
+ * constants are stored in minimum 8 byte values
+ */
+static void cnvt_nonis_pselparm(struct net_t *np, struct expr_t *ndp,
+ struct expr_t *ndx1, struct expr_t *ndx2)
+{
+ int32 bi1, bi2, pselwid, wlen;
+ word32 *wp2;
+ struct xstk_t *xsp;
+ 
+ /* parameters always range [(width - 1) to 0] */
+ bi1 = get_nonis_param_ndx(np, ndx1);
+ bi2 = get_nonis_param_ndx(np, ndx2);
+ if (bi1 == -1 || bi2 == -1)
+  {
+   __sgferr(1045,
+    "parameter part select %s (width %d) index(s) x/z, out of range",
+    __msgexpr_tostr(__xs, ndp), np->nwid);
+   return;
+  }
+ if (bi1 < bi2) pselwid = bi2 - bi1 + 1;
+ else pselwid = bi1 - bi2 + 1;
+
+ __free2_xtree(ndp);
+ __init_xnd(ndp);
+ ndp->optyp = NUMBER;
+ ndp->szu.xclen = pselwid;
+ ndp->consubxpr = TRUE;
+ ndp->folded = TRUE;
+
+ /* can't use shareable here becuase need to psel to set value */
+ push_xstk_(xsp, pselwid);
+ wlen = wlen_(np->nwid);
+ wp2 = np->nva.wp; 
+ __rhspsel(xsp->ap, wp2, bi2, pselwid);
+ __rhspsel(xsp->bp, &(wp2[wlen]), bi2, pselwid);
+ ndp->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, wlen_(pselwid));
+ __pop_xstk();
+ return;
+}
+
+/*
+ * convert a parameter IS bit select to 1 bit constant
+ * know result is an IS constant
+ */
+static void cnvt_is_pselparm(struct net_t *np, struct expr_t *ndp,
+ struct expr_t *ndx1, struct expr_t *ndx2)
+{
+ register int32 ii;
+ int32 bi1, bi2, xwlen, wlen, wlen2, err, pselwid, tmp, tmpxvi;
+ word32 *wp, *wp2;
+
+ pselwid = 0;
+ for (err = FALSE, ii =  0; ii < __inst_mod->flatinum; ii++) 
+  {
+   /* parameters always range [(width - 1) to 0] */
+   if (ndx1->optyp == NUMBER) bi1 = get_nonis_param_ndx(np, ndx1);
+   else bi1 = get_is_param_ndx(np, ndx1, ii); 
+   if (ndx2->optyp == NUMBER) bi2 = get_nonis_param_ndx(np, ndx2);
+   else bi2 = get_is_param_ndx(np, ndx2, ii); 
+   if (bi1 == -1 || bi2 == -1)
+    {
+     __sgferr(1045,
+      "parameter part select %s (width %d) (instance %s) index(s) x/z, out of range",
+      __msgexpr_tostr(__xs, ndp), np->nwid, __msg2_blditree(__xs,
+     __inst_mod->moditps[ii]));
+     err = TRUE;
+    }
+   if (bi1 < bi2) tmp = bi2 - bi1 + 1;
+   else tmp = bi1 - bi2 + 1;
+   /* constant is widest in case IS form indices */
+   if (tmp > pselwid) pselwid = tmp;
+  }
+ if (err) return;
+
+ xwlen = __inst_mod->flatinum*wlen_(pselwid);  
+ /* must not change ndp since still need to access ndx values */
+ tmpxvi = __alloc_is_cval(xwlen);
+ wp = &(__contab[tmpxvi]);
+ memset(wp, 0, 2*xwlen*WRDBYTES);
+ 
+ wlen = wlen_(pselwid);
+ wlen2 = wlen_(np->nwid);
+ for (ii =  0; ii < __inst_mod->flatinum; ii++) 
+  {  
+   if (ndx1->optyp == NUMBER) bi1 = get_nonis_param_ndx(np, ndx1);
+   else bi1 = get_is_param_ndx(np, ndx1, ii); 
+   if (ndx2->optyp == NUMBER) bi2 = get_nonis_param_ndx(np, ndx2);
+   else bi2 = get_is_param_ndx(np, ndx2, ii); 
+
+   wp2 = np->nva.wp;
+   if (np->srep == SR_PISNUM) wp2 = &(wp2[2*wlen2*ii]);
+
+   tmp = bi1 - bi2 + 1;
+   /* can part select into section of constant providing starts at 0 */
+   /* tmp can be narrower than psel wid */
+   __rhspsel(&(wp[2*wlen*ii]), wp2, bi2, tmp);
+   __rhspsel(&(wp[2*wlen*ii + wlen]), &(wp2[wlen2]), bi2, tmp);
+  }
+
+ __free2_xtree(ndp);
+ __init_xnd(ndp);
+ ndp->optyp = ISNUMBER;
+ ndp->szu.xclen = pselwid;
+ ndp->ru.xvi = tmpxvi;
+ ndp->consubxpr = TRUE;
+ ndp->consub_is = TRUE;
+ ndp->folded = TRUE;
+ return;
+}
+
+/*
+ * SOURCE (STRUCTURAL) RHS EXPRESSION CHECKING
+ */
+
+/*
+ * check gate/inst array index parameter expression
+ * return F on error (i.e. no constant)
+ *
+ * special case because needed before parameters set to final values
+ * if wider than 32 bits or has x/zs caught after expr. eval
+ */
+extern int32 __chk_giarr_ndx_expr(struct expr_t *ndp)
+{
+ chk_struct_rhsexpr(ndp, 0);
+ /* emit warning for word32 relations comparisons */
+ chk_mixedsign_relops(ndp);
+
+ /* real not allowed */
+ if (__is_paramconstxpr(ndp, FALSE)) return(TRUE);
+ return(TRUE);
+}
+
+/*
+ * check either defparam or specparam rhs expr.
+ * cannot go through chk rhs expr here since some rhs stuff not allowed
+ */
+extern int32 __chk_paramexpr(struct expr_t *ndp, int32 xwid)
+{
+ /* FIXME - need to allow const user function calls in param rhs exprs */
+ /* SJM 03/13/00 - now built-in sys funcs ok - chk later for non const args */
+ if (xpr_has_nonsys_fcall(ndp)) return(FALSE);
+
+ chk_struct_rhsexpr(ndp, xwid);
+ if (ndp->is_real) ndp->ibase = BDBLE;
+ /* emit warning for word32 relations comparisons */
+ chk_mixedsign_relops(ndp);
+
+ if (__is_paramconstxpr(ndp, TRUE)) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * return T if parameter constant expr. - else F (for ID)
+ * if expr. contains anything but numbers and correct type of param return F
+ *
+ * this is for both def params and spec params 
+ * notice for spec param can never be IS form
+ */
+extern int32 __is_paramconstxpr(struct expr_t *ndp, int32 realok)
+{
+ int32 rv1, rv2;
+ struct sy_t *syp;
+ struct net_t *np;
+ struct expr_t *fandp;
+
+ switch ((byte) ndp->optyp) { 
+  case NUMBER: return(TRUE);
+  case REALNUM:
+   if (!realok) return(FALSE);
+   return(TRUE);
+
+  /* can only make ISNUMBER after def/# param assignment */ 
+  case ISNUMBER: case ISREALNUM:
+   __arg_terr(__FILE__, __LINE__);
+   break;
+  case ID:
+   /* previously defined parameter ok */ 
+   syp = ndp->lu.sy;
+   if (!syp->sydecl) return(FALSE);
+   np = syp->el.enp; 
+   if (np->n_isaparam)
+    {
+     /* SJM 02/04/00 - error if parameter used on RHS of specparam */
+     if (__cur_declobj == SPECIFY && !np->nu.ct->p_specparam) return(FALSE);
+     return(TRUE);
+    }
+   return(FALSE);
+  case GLBREF: return(FALSE);
+  /* SJM - 08/22/00 - selects from bit and part selects need to work */ 
+  /* case LSB: case PARTSEL: */
+  /* return(FALSE); */
+  case FCALL:
+   /* getting output width, so have right context elsewhere */
+   /* do not need to get arg. width since call shields */
+   syp = ndp->lu.x->lu.sy;
+   if (syp->sytyp != SYM_SF) return(FALSE);
+   if (syp->el.esyftbp->tftyp != SYSF_BUILTIN) return(FALSE);
+   if (!realok)
+    { if (syp->el.esyftbp->retntyp == N_REAL) return(FALSE); }
+   /* SJM 09/04/01 - for special constant sys funcs must check arg num here */ 
+   /* args must also be constant - first in expr list is return expr */
+   for (fandp = ndp->ru.x; fandp != NULL; fandp = fandp->ru.x)
+    {
+     /* LOOKATME - even if real param not allowed arg to const systf */
+     /* can be real */
+     if (!__is_paramconstxpr(fandp->lu.x, TRUE)) return(FALSE);
+    }
+   return(TRUE);
+ } 
+ rv1 = rv2 = TRUE;
+ if (ndp->lu.x != NULL) rv1 = __is_paramconstxpr(ndp->lu.x, realok);
+ if (ndp->ru.x != NULL) rv2 = __is_paramconstxpr(ndp->ru.x, realok);
+ if (rv1 && rv2) return(TRUE); 
+ return(FALSE);
+}
+
+/*
+ * check a rhs expression for structural correctness
+ *
+ * only needs info available during pass 1
+ * all rhs expressions must be processed through here
+ * needs __sfnam_ind to be set before called
+ *
+ * this checks and changes structural things but does not
+ * do any evaluating or substituting or folding since needed during
+ * source input to determine parameters
+ *
+ * when done all node widths sets, all real operators substituted
+ * and all concatenates 1 level with no repeat forms  
+ * if error that will prevent simulation, emitted here
+ *
+ * not done: part select and bit select normalization and range checking
+ * constant folding, conversion to WBITS values for indices and ranges
+ */
+static void chk_struct_rhsexpr(struct expr_t *ndp, int32 xwid)
+{
+ /* handle all leaves (special fast cases) */
+ switch ((byte) ndp->optyp) {
+  case OPEMPTY: return;
+  case NUMBER: case ISNUMBER: return;
+  case REALNUM: case ISREALNUM:
+   ndp->is_real = TRUE;
+   /* reals always signed */
+   ndp->has_sign = TRUE;
+   __expr_has_real = TRUE;
+   return;
+  case ID: case GLBREF:
+   /* here must set width if possible */
+   if (chk_rhs_id(ndp)) ndp->szu.xclen = __get_netwide(ndp->lu.sy->el.enp);
+   else ndp->szu.xclen = 1;
+   return;
+ }
+ /* must next unwind all concatenates in expr. bottom up */
+ /* result is 1 level only simple concats */
+ unwind_rhsconcats(ndp);
+
+ /* SJM 09/11/03 - because XL/NC support 0 width concat elements, must */
+ /* remove any 0 width one from concat here - if now empty syntax error */ 
+ if (__nd_0width_catel_remove)
+  {
+   remove_0width_catrep_els(ndp);
+   __nd_0width_catel_remove = FALSE;
+  }
+
+ __expr_has_real = FALSE;
+ /* set widths and turn on flag if any reals in expr. */
+ /* also sets is_real for real constants and variables */
+ set_rhswidth(ndp, xwid);
+
+ if (__expr_has_real) setchk_real_expr(ndp);
+
+ /* 10/02/03 - use new 2001 LRM rules to set expr has sign bit */
+ set_rhs_signed(ndp);
+
+ /* check any special (bsel, psel, fcall, etc.) in rhs expr. */
+ /* this leave bit select and part select expressions as is */
+ /* must normalize and convert to WBITS number some where is const. */
+ chk_specialop_rhsexpr(ndp);
+}
+
+/*
+ * check a rhs identifier 
+ * for global checks target
+ */
+static int32 chk_rhs_id(struct expr_t *ndp)
+{
+ struct net_t *np;
+ struct sy_t *syp;
+
+ syp = ndp->lu.sy;
+ /* cross module reference not yet resolved - caller will emit error */
+ if (syp == NULL) return(FALSE);
+
+ if (!syp->sydecl) return(FALSE);
+
+ if (syp->sytyp != SYM_N)
+  {
+  __sgferr(1040, "%s %s illegal in right side expression - must be variable",   
+   __to_sytyp(__xs, syp->sytyp), __to_idnam(ndp));
+   return(FALSE);
+  }
+
+ /* this check for illegal expr. unindexed array and event */
+ /* params and real marking handled here also */
+ np = syp->el.enp;
+ if (np->ntyp == N_EVENT)
+  {
+   __sgferr(893, "event %s illegal in right hand side expression",
+    __to_idnam(ndp));
+   return(FALSE);
+  }
+ if (np->n_isarr)
+  {
+   __sgferr(894,
+    "illegal unindexed array reference of %s in right hand side expression",
+    __to_idnam(ndp));
+   return(FALSE);
+  }
+ /* any rhs wire expr. node must be signed if wire is */
+ if (np->n_signed) ndp->has_sign = TRUE;
+ if (np->n_stren) ndp->x_stren = TRUE;
+ if (np->ntyp == N_REAL)
+  { ndp->is_real = TRUE; ndp->has_sign = TRUE; __expr_has_real = TRUE; }
+ if (np->nrngrep == NX_CT) np->nu.ct->n_onrhs = TRUE;
+ if (!__expr_rhs_decl) np->n_onprocrhs = TRUE;
+ return(TRUE);
+}
+
+/*
+ * check and unwind all rhs concatenates
+ *
+ * this will create any repeat form concatenates it needs to
+ * when done concatenate is one level with catreps removed
+ * concatenate constant folding if implemented must be done after here 
+ *
+ * notice this will unwind concatenates in fcall arguments
+ */
+static void unwind_rhsconcats(struct expr_t *ndp)
+{
+ if (__isleaf(ndp)) return;
+
+ /* DBG ---
+ if (__debug_flg)
+  __dbg_msg("## unwinding concat %s\n", __msgexpr_tostr(__xs, ndp));
+ --- */
+
+ /* concatenate unwinding must be done bottom up */
+ if (ndp->lu.x != NULL)
+  {
+   /* DBG ---
+   if (__debug_flg)
+   __dbg_msg("## left side %s\n", __msgexpr_tostr(__xs, ndp->lu.x));
+   --- */ 
+   unwind_rhsconcats(ndp->lu.x);
+   /* DBG ---
+   if (__debug_flg) __dbg_msg("^^ left up.\n");
+   --- */
+  }
+ if (ndp->ru.x != NULL)
+  {
+   /* DBG ---
+   if (__debug_flg)
+   __dbg_msg("## right side %s\n", __msgexpr_tostr(__xs, ndp->ru.x));
+   --- */
+   unwind_rhsconcats(ndp->ru.x);
+   /* DBG ---
+   if (__debug_flg) __dbg_msg("^^ right up.\n");
+   --- */ 
+  }
+
+ /* node is top of concatenate with all sub concatenates simplified */
+ if (ndp->optyp == LCB)
+  {
+   register struct expr_t *ndp2;
+   struct expr_t *last_ndp2, *end_ndp;
+
+   last_ndp2 = ndp;
+   for (ndp2 = ndp->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+    {
+     struct expr_t *lop;
+
+     lop = ndp2->lu.x;
+     /* notice ,, form illegal in concatentate */
+     switch ((byte) lop->optyp) {
+      case NUMBER: case ISNUMBER:
+       if (lop->unsiznum)
+        __sgferr(897, "unsized number illegal in concatenate");
+       break;
+      case REALNUM: case ISREALNUM:
+       __sgferr(813, "real number illegal in concatenate");
+       break;
+      case LCB:
+       {
+        /* nested concatenate - splice up one level */
+        last_ndp2->ru.x = lop->ru.x;
+        /* find rightmost element - know always there */
+        end_ndp = __find_catend(lop);
+        /* if rightmost up one node will make null */
+        end_ndp->ru.x = ndp2->ru.x;
+        /* end of new chain is new last */
+        last_ndp2 = end_ndp;
+       }
+       continue;
+      case CATREP:
+       {
+        int32 repval;
+        struct expr_t *dupndp;
+        struct xstk_t *xsp;
+
+        if (__chk_paramexpr(lop->lu.x, 0))
+         {
+          xsp = __eval_xpr(lop->lu.x);
+          if (xsp->xslen > WBITS)
+           {
+            if (!vval_is0_(&(xsp->ap[1]), xsp->xslen - WBITS) 
+             || !vval_is0_(&(xsp->bp[1]), xsp->xslen - WBITS)
+             || xsp->bp[0] != 0L) goto bad_rep;
+           }
+          else if (xsp->bp[0] != 0) goto bad_rep;
+          
+          repval = (int32) xsp->ap[0];
+          /* SJM 09/11/03 - also need error for negative */
+          if (repval < 0) goto bad_rep;
+          else if (repval == 0)
+           {
+            __sgfwarn(3109,
+             "concatenate repeat value of 0 causes removal of concatenate");
+           }
+          else if (repval == 1) 
+           __sgfinform(442, "concatenate repeat value of 1 has no effect");
+         }
+        else
+         {
+bad_rep:
+          __sgferr(814,
+           "concatenate repeat value %s not a non negative constant expression",
+           __msgexpr_tostr(__xs, lop->lu.x));
+          repval = 1;
+         }
+
+        __pop_xstk();
+        if (repval == 0)
+         {
+          /* SJM 09/11/03 - contradicts 2001 LRM but 0 width removed */
+          /* from concatenate, but because of possibility of recursive */
+          /* upward removal must insert size 1 and remove later */
+          /* and if remove creates empty concat, then emit syntax error */ 
+          dupndp = __dup_concat(1, lop->ru.x->ru.x);
+          dupndp->folded = TRUE;
+          __nd_0width_catel_remove = TRUE;
+         }
+        else
+         {
+          /* know the rhs thing must be a concatenate */
+          dupndp = __dup_concat(repval, lop->ru.x->ru.x);
+         }
+
+        /* nested concatenate - splice up one level */
+        last_ndp2->ru.x = dupndp;
+        /* find rightmost element - know always there */
+        end_ndp = __find_catend(dupndp);
+
+        /* if rightmost up one node will make null */
+        end_ndp->ru.x = ndp2->ru.x;
+        /* end of new chain is new last */
+        last_ndp2 = end_ndp;
+       }
+       continue;
+      }
+     /* NUMBER or other means move last down tree one */
+     last_ndp2 = ndp2;
+    }
+  }
+}
+
+/*
+ * return TRUE if node is leaf node (id, glbid, number)
+ */
+extern int32 __isleaf(struct expr_t *ndp)
+{
+ switch ((byte) ndp->optyp) {
+  case ID: case GLBREF: case NUMBER: case ISNUMBER:
+  case REALNUM: case ISREALNUM: case OPEMPTY: 
+   return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*
+ * duplicate a single level no embedded CATREP concatenate
+ */
+extern struct expr_t *__dup_concat(int32 repcnt, struct expr_t *catndp)
+{
+ register int32 w;
+ struct expr_t *dupndp, *newndp, *end_ndp;
+
+ /* now build longer chain repeated repval - 1 times */
+ for (newndp = NULL, w = 0; w < repcnt; w++)
+  {
+   /* make one copy */
+   if (w < repcnt - 1) dupndp = __copy_expr(catndp); else dupndp = catndp;
+   if (newndp == NULL) newndp = dupndp;
+   else
+    {
+     end_ndp = __find_catend(dupndp);
+     end_ndp->ru.x = newndp;
+     newndp = dupndp;
+    }
+  }
+ return(newndp);
+}
+
+/*
+ * find the end (rightmost CATCOM) of a one level concatenate chain
+ * expects to be passed LCB concatenate chain header
+ */
+extern struct expr_t *__find_catend(struct expr_t *catndp)
+{
+ register struct expr_t *ndp;
+ struct expr_t *last_ndp;
+
+ for (ndp = catndp, last_ndp = NULL; ndp != NULL; ndp = ndp->ru.x)
+  last_ndp = ndp;
+ return(last_ndp);
+}
+
+/*
+ * go through linearized concat and remove all marked 0 width elements
+ *
+ * if all removed, must emit syntax error and replace now empty concat 
+ * with a 1 bit x concat
+ *
+ * BEWARE - using folded to mark removal so must not fold before here
+ */
+static void remove_0width_catrep_els(struct expr_t *catndp)
+{ 
+ register struct expr_t *com_xp, *com_xp2, *last_com_xp;
+ struct expr_t *rem_com_xp;
+
+ last_com_xp = NULL;
+ rem_com_xp = NULL;
+ com_xp2 = catndp->ru.x; 
+ for (com_xp = catndp; com_xp != NULL;)
+  {
+   if (com_xp->folded)
+    {
+     com_xp2 = com_xp->ru.x;
+
+     if (last_com_xp == NULL) catndp->ru.x = com_xp->ru.x;
+     else { last_com_xp->ru.x = com_xp->ru.x; }
+     if (rem_com_xp == NULL) rem_com_xp = com_xp;
+
+     com_xp = com_xp2;
+    }
+   else
+    {
+     last_com_xp = com_xp;
+     com_xp = com_xp->ru.x;
+    } 
+  }
+ if (catndp->ru.x == NULL)
+  {
+   /* DBG remove -- */
+   if (rem_com_xp == NULL || rem_com_xp->lu.x == NULL)
+    __misc_terr(__FILE__, __LINE__);
+   /* -- */
+
+   __sgferr(3110,
+    "concatenate 0 width repeat removal created illegal empty expression");
+
+   /* SJM 09/11/03 - notice minor memory leak but can't free exprs here */
+   __set_numval(rem_com_xp->lu.x, 1, 1, 1);
+   catndp->ru.x = rem_com_xp;
+  }
+}
+
+/*  
+ * WIDTH SETTING ROUTINES
+ */
+
+/*
+ * set all width values of an expression in a given width context
+ */
+static void set_rhswidth(struct expr_t *rhsx, int32 cwid)
+{
+ int32 cwid2, ibas;
+
+ cwid2 = __get_rhswidth(rhsx);
+ if (cwid > cwid2) cwid2 = cwid;
+ /* if expression wider than context, need expr. max. as context */
+ set2_rhswidth(rhsx, cwid2);
+
+ ibas = find_xbase(rhsx);
+ if (ibas == '?') ibas = BHEX;
+ rhsx->ibase = ibas;
+}
+
+/*
+ * calculate the width of a rhs expression
+ * know width never IS NUMBER form
+ */
+extern int32 __get_rhswidth(struct expr_t *rhsx)
+{
+ int32 wclass, xwid, xwid2, r1, r2, sav_errcnt;
+ struct net_t *np;
+ struct expr_t *psx1, *psx2;
+
+ xwid = 1;
+ switch ((byte) rhsx->optyp) {
+  case ID: case GLBREF:
+   xwid = __get_netwide(rhsx->lu.sy->el.enp);
+   break;
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   xwid = rhsx->szu.xclen;
+   break;
+  case LSB:
+   /* bit select or array reference */
+   np = rhsx->lu.x->lu.sy->el.enp;
+   /* know this is net or will not get here */
+   if (np->n_isarr) return(__get_netwide(np));
+   return(1);
+  case PARTSEL:
+   /* this is tricky since constants not yet folded but since params */
+   /* value known, check (and fold) this sub expression before continuing */
+   psx1 = rhsx->ru.x->lu.x;
+   psx2 = rhsx->ru.x->ru.x;
+   sav_errcnt = __pv_err_cnt;
+   __chk_rhsexpr(psx1, 0);
+   __chk_rhsexpr(psx2, 0);
+   np = rhsx->lu.x->lu.sy->el.enp;
+   /* error caught later, set to 1 for now */
+   if (sav_errcnt != __pv_err_cnt || psx1->optyp != NUMBER
+    || psx2->optyp != NUMBER) xwid = 1;
+   else
+    {
+     r1 = (int32) __contab[psx1->ru.xvi];
+     r2 = (int32) __contab[psx2->ru.xvi];
+     xwid = (r1 > r2) ? (r1 - r2 + 1) : (r2 - r1 + 1);
+    }
+   break;
+  case QUEST:
+   xwid = __get_rhswidth(rhsx->ru.x->ru.x);
+   xwid2 = __get_rhswidth(rhsx->ru.x->lu.x);
+   if (xwid2 > xwid) xwid = xwid2;
+   break;
+  case FCALL:
+   {
+    struct task_t *tskp;
+    struct task_pin_t *tpp;
+    struct sy_t *syp;
+
+    /* getting output width, so have right context elsewhere */
+    /* do not need to get arg. width since call shields */
+    syp = rhsx->lu.x->lu.sy;
+    if (syp->sytyp == SYM_SF)
+     {
+      /* SJM 05/28/04 - $signed and $word32 are special case that return */
+      /* arg width - but need to recursively call get width to determine */
+      if (syp->el.esyftbp->syfnum == STN_SIGNED
+       || syp->el.esyftbp->syfnum == STN_UNSIGNED)
+       {
+        xwid = __get_rhswidth(rhsx->ru.x->lu.x);
+       }
+      else xwid = syp->el.esyftbp->retwid;
+     } 
+    /* error caught later */
+    else if (syp->sytyp == SYM_F)
+     {
+      tskp = syp->el.etskp;
+      tskp->t_used = TRUE;
+      tpp = tskp->tskpins;
+      np = tpp->tpsy->el.enp;
+      xwid = __get_netwide(np);
+     }
+    /* if non fcall, leave as 1 bit */
+   }
+   return(xwid);
+  case LCB:
+   {
+    register struct expr_t *ndp2;
+
+    /* know cat repeats removed by here - component widths set later */
+    for (xwid = 0, ndp2 = rhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     {
+      xwid2 = __get_rhswidth(ndp2->lu.x);
+      xwid += xwid2;
+     }
+   }
+   break;
+  default:
+   /* this is unary or binary op */
+   wclass = __get_widthclass(rhsx);
+   switch ((byte) wclass) {
+    case WIDONE: case WIDENONE: return(1);
+    case WIDMAX:
+     if (rhsx->ru.x == NULL) xwid = 0; else xwid = __get_rhswidth(rhsx->ru.x);
+     if (rhsx->lu.x == NULL) xwid2 = 0; else xwid2 = __get_rhswidth(rhsx->lu.x);
+     if (xwid2 > xwid) xwid = xwid2;
+    break;
+    case WIDLEFT: return(__get_rhswidth(rhsx->lu.x));
+   case WIDSELF: return(__get_rhswidth(rhsx->lu.x));
+    default: __case_terr(__FILE__, __LINE__);
+   }
+ }
+ return(xwid);
+}
+
+/*
+ * get an operator's width class
+ */
+extern int32 __get_widthclass(struct expr_t *rhsx)
+{
+ struct opinfo_t *opip;
+
+ opip = &(__opinfo[rhsx->optyp]);
+ /* unary form of both always reduction => width one */
+ if (opip->opclass == BOTHOP && rhsx->ru.x == NULL)
+  {
+   /* AIV 03/09/05 - minus is only bothop with lhs cnxt size */
+   if (rhsx->optyp != MINUS) return(WIDONE);
+  }
+ return(opip->reswid);
+}
+
+/*
+ * set rhs width - also mark expr. that are real or stren
+ *
+ * SJM 07/16/01 - algorithm here is that operator has correct width that
+ * may be width of assignment lhs context because in expr eval after
+ * pushing operands onto xstk, size changes of xstk are made where needed
+ * according to LRM rules for propagating expression width to interim results
+ */
+static void set2_rhswidth(struct expr_t *rhsx, int32 cwid)
+{
+ int32 wclass, cat_stren, xwid, xwid2, r1, r2;
+ struct expr_t *tndp, *ndx1, *ndx2;
+ struct sy_t *syp;
+ struct net_t *np;
+
+ switch ((byte) rhsx->optyp) {
+  case ID: case GLBREF:
+   np = rhsx->lu.sy->el.enp;
+   /* for real id exprs, expr. is_real bit set in chk id */ 
+   if (np->ntyp == N_REAL)
+    { __expr_has_real = TRUE; rhsx->is_real = TRUE; rhsx->has_sign = TRUE; }
+   if (np->n_stren) rhsx->x_stren = TRUE;
+   rhsx->szu.xclen = __get_netwide(np);
+   return;
+  case NUMBER: case ISNUMBER: case OPEMPTY: return;
+  case REALNUM: case ISREALNUM:
+   /* for real numbers is real bit set in chk id */ 
+   __expr_has_real = TRUE;
+   rhsx->is_real = TRUE;
+   rhsx->has_sign = TRUE;
+   return;
+  case LSB:
+   /* bit select or array reference */
+   syp = rhsx->lu.x->lu.sy;
+   rhsx->lu.x->szu.xclen = __get_netwide(syp->el.enp);
+   set_rhswidth(rhsx->ru.x, 0);
+   np = syp->el.enp;
+   if (np->n_isarr && np->n_isavec) xwid = __get_netwide(np); else xwid = 1;
+   if (np->n_isarr && np->ntyp == N_REAL)
+    {
+     __expr_has_real = TRUE;
+     rhsx->is_real = TRUE;
+     rhsx->has_sign = TRUE;
+    }
+   if (np->n_stren) rhsx->x_stren = TRUE;
+   rhsx->szu.xclen = xwid;
+   return;
+  case PARTSEL:
+   syp = rhsx->lu.x->lu.sy;
+   np = syp->el.enp;
+   if (np->n_stren) rhsx->x_stren = TRUE;
+   rhsx->lu.x->szu.xclen = __get_netwide(np);
+   ndx1 = rhsx->ru.x->lu.x;
+   ndx2 = rhsx->ru.x->ru.x;
+   set_rhswidth(ndx1, 0);
+   set_rhswidth(ndx2, 0);
+   /* SJM 05/22/00 - error for non illegal non numeric psel caught later */
+   /* get rhs width always folds psel indices so if not numeric error */
+   if ((ndx1->optyp == NUMBER || ndx1->optyp == ISNUMBER)
+    && (ndx2->optyp == NUMBER || ndx2->optyp == ISNUMBER))
+    {
+     r1 = (int32) __contab[ndx1->ru.xvi];
+     r2 = (int32) __contab[ndx2->ru.xvi];
+     rhsx->szu.xclen = (r1 >= r2) ? (r1 - r2 + 1) : (r2 - r1 + 1);
+    }
+   /* using 32 bits - error caught later */
+   else rhsx->szu.xclen = WBITS;
+   return;
+  case QUEST:
+   set_rhswidth(rhsx->lu.x, 0);
+   set_rhswidth(rhsx->ru.x->ru.x, cwid);
+   set_rhswidth(rhsx->ru.x->lu.x, cwid);
+
+   tndp = rhsx->ru.x;
+   /* assume right wider */
+   xwid = tndp->lu.x->szu.xclen;
+   if (xwid < tndp->ru.x->szu.xclen) xwid = tndp->ru.x->szu.xclen;
+   rhsx->szu.xclen = xwid;
+   return;
+  case FCALL:
+   {
+    int32 frntyp;
+    struct task_t *tskp;
+    struct task_pin_t *tpp;
+
+    /* notice func. name does not have width but top (rhsx) has ret. width */
+    syp = rhsx->lu.x->lu.sy;
+    tskp = syp->el.etskp;
+    if (syp->sytyp == SYM_SF)
+     {
+      struct sysfunc_t *syfp;
+
+      syfp = syp->el.esyftbp;
+      /* SJM 05/28/04 - $signed and $word32 are special case that return */
+      /* arg width - but need to recursively call get width to determine */
+      if (syp->el.esyftbp->syfnum == STN_SIGNED
+       || syp->el.esyftbp->syfnum == STN_UNSIGNED)
+       {
+        rhsx->szu.xclen = __get_rhswidth(rhsx->ru.x->lu.x);
+       }
+      else
+       {
+        /* for real this must be WBITS */
+        rhsx->szu.xclen = syfp->retwid;
+       }
+      /* notice also sets signed for function */
+      if (syfp->retsigned) rhsx->has_sign = TRUE;
+      frntyp = syfp->retntyp;
+     }
+    else if (syp->sytyp == SYM_F)
+     {
+      tpp = tskp->tskpins;
+      np = tpp->tpsy->el.enp;
+      /* functions cannot return arrays */
+      rhsx->szu.xclen = __get_netwide(np);
+      if (np->n_signed) rhsx->has_sign = TRUE;
+      frntyp = np->ntyp;
+     }
+    /* if call of non function error (caught already) - do nothing */
+    else return;
+
+    if (frntyp == N_REAL)
+     { rhsx->is_real = TRUE; rhsx->has_sign = TRUE; __expr_has_real = TRUE; }
+
+    /* this sets argument widths */
+    /* this is needed and uses right decl. var context for non sys functions */
+    /* because width setting is structural before recursive processing */
+    if (syp->sytyp == SYM_SF) set_sysfcall_widths(rhsx);
+    else set_fcall_widths(rhsx, tskp);
+   }
+   return;
+  case LCB:
+   {
+    register struct expr_t *ndp2;
+    struct expr_t *catxp;
+
+    /* know concatenates never nested by here */
+    /* first set cat self determined component widths */
+    xwid = 0;
+    for (cat_stren = FALSE, ndp2 = rhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     {
+      catxp = ndp2->lu.x;
+      set_rhswidth(catxp, 0);
+      xwid += catxp->szu.xclen;
+      if (catxp->x_stren) { ndp2->x_stren = TRUE; cat_stren = TRUE; }
+     }
+    rhsx->szu.xclen = xwid;
+    if (cat_stren) rhsx->x_stren = TRUE;
+    /* CAT COM op width is dist from high bit of this to low (right) end */
+    for (ndp2 = rhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     {
+      ndp2->szu.xclen = xwid;
+      xwid -= ndp2->lu.x->szu.xclen;
+     }
+    if (xwid != 0) __misc_terr(__FILE__, __LINE__);
+   }
+   return;
+  default:
+   /* this is unary or binary op */
+   wclass = __get_widthclass(rhsx);
+   switch ((byte) wclass) {
+    case WIDONE:
+     /* this is for unaries only except for || and && */
+     rhsx->szu.xclen = 1;
+     /* under width 1 shield new context is max. width of subexpr. */
+     /* case is something like &(a + b + c) where c widest */
+     /* this spreads max. width because of context to all subexpressions */
+     xwid = __get_rhswidth(rhsx->lu.x);
+     set_rhswidth(rhsx->lu.x, xwid);
+     /* notice binaries can be wide one also */
+     if (rhsx->ru.x != NULL)
+      {
+       /* same here */
+       xwid = __get_rhswidth(rhsx->ru.x);
+       set_rhswidth(rhsx->ru.x, xwid);
+      }
+     return;
+    case WIDENONE:
+     /* for binaries that produce one bit result */
+     rhsx->szu.xclen = 1;
+     /* notice not using cwid context under here */
+     xwid = __get_rhswidth(rhsx->lu.x);
+     xwid2 = __get_rhswidth(rhsx->ru.x);
+     if (xwid2 > xwid) xwid = xwid2;
+     if (rhsx->lu.x != NULL) set_rhswidth(rhsx->lu.x, xwid);
+     if (rhsx->ru.x != NULL) set_rhswidth(rhsx->ru.x, xwid);
+     return;
+    case WIDMAX:
+     /* need context here since non shielded binary */
+     r1 = r2 = 0;
+     if (rhsx->ru.x != NULL)
+      {
+       set_rhswidth(rhsx->ru.x, cwid);
+       r1 = rhsx->ru.x->szu.xclen;
+      }
+     if (rhsx->lu.x != NULL)
+      {
+       set_rhswidth(rhsx->lu.x, cwid);
+       r2 = rhsx->lu.x->szu.xclen;
+      }
+     xwid = (r1 < r2) ? r2 : r1;
+select_wid:
+     if (xwid < cwid) xwid = cwid;
+     rhsx->szu.xclen = xwid;
+     return;
+    case WIDLEFT:
+     /* set the non context right width (i.e. shift amount) */
+     set_rhswidth(rhsx->ru.x, 0);
+     set_rhswidth(rhsx->lu.x, cwid);
+     xwid = rhsx->szu.xclen;
+     goto select_wid;
+    case WIDSELF:
+     /* for unary - and ~ - (+ too but does nothing - optimized away) */
+     /* LOOKATME - why getting width and using as context - would 0 work? */
+     xwid = __get_rhswidth(rhsx->lu.x);
+     set_rhswidth(rhsx->lu.x, xwid);
+     /* SJM 07/16/01 - this is wrong - context width need for operator node */
+     /* ??? rhsx->szu.xclen = xwid; */
+     goto select_wid;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+ }
+}
+
+/*
+ * set width for user fcall arguments - context here is argument width
+ * user functions require all arguments
+ * wrong number of arguments caught elsewhere - use what is there
+ */
+static void set_fcall_widths(struct expr_t *fcrhsx,
+ struct task_t *tskp)
+{
+ struct expr_t *fandp;
+ struct task_pin_t *tpp;
+ int32 pwid;
+
+ /* point 1 past extra first argument - not part of source call */
+ tpp = tskp->tskpins->tpnxt;
+ for (fandp = fcrhsx->ru.x; fandp != NULL; fandp = fandp->ru.x)
+  {
+   /* move to next declared argument */
+   if (tpp != NULL) tpp = tpp->tpnxt;
+
+   if (tpp == NULL || tpp->tpsy == NULL) pwid = 0;
+   else pwid = __get_netwide(tpp->tpsy->el.enp);
+
+   /* notice for numbers this can't change width */
+   set_rhswidth(fandp->lu.x, pwid);
+  }
+}
+
+/*
+ * set width for system fcall arguments, no context
+ * at this point since checking done just use expr. that is there
+ */
+static void set_sysfcall_widths(struct expr_t *fcrhsx)
+{
+ struct expr_t *fandp;
+
+ /* 0 argument system functions common */
+ /* notice expressions structure does not have extra 1st return value */
+ for (fandp = fcrhsx->ru.x; fandp != NULL; fandp = fandp->ru.x)
+  set_rhswidth(fandp->lu.x, 0);
+}
+
+
+/*
+ * ROUTINE TO SET EXPR SIGNED USING NEW 2001 RULES
+ */
+
+/*
+ * set all expression nodes has signed flag 
+ */
+static void set_rhs_signed(struct expr_t *rhsx)
+{
+ register struct expr_t *ndp2;
+ int32 wclass;
+ struct net_t *np;
+ struct sy_t *syp;
+ struct task_t *tskp;
+ struct sysfunc_t *syfp;
+ struct task_pin_t *tpp;
+
+ switch ((byte) rhsx->optyp) {
+  case ID: case GLBREF:
+   np = rhsx->lu.sy->el.enp;
+   /* SJM 10/02/03 - for real has sign already set by width setting */
+   /* but doing it here again doesn't hurt */
+   if (np->n_signed) rhsx->has_sign = TRUE;
+   break;
+  case NUMBER: case ISNUMBER: case OPEMPTY:
+  case REALNUM: case ISREALNUM:
+   /* for numbers the signed flag set during source input */
+   break;
+  case LSB:
+   /* bit select or array reference */
+   /* set lhs ID node signedness */ 
+   set_rhs_signed(rhsx->lu.x);
+
+   /* then set select node signedness */
+   syp = rhsx->lu.x->lu.sy;
+   np = syp->el.enp;
+   if (np->n_isarr)
+    {
+     if (np->n_signed) rhsx->has_sign = TRUE; 
+    }
+   else rhsx->has_sign = FALSE;
+
+   /* finally set select range signed */
+   set_rhs_signed(rhsx->ru.x);
+   break;
+  case PARTSEL:
+   /* set lhs ID node signedness */ 
+   set_rhs_signed(rhsx->lu.x);
+   rhsx->has_sign = FALSE;
+   break;
+  case QUEST:
+   set_rhs_signed(rhsx->lu.x);
+
+   set_rhs_signed(rhsx->ru.x->lu.x);
+   set_rhs_signed(rhsx->ru.x->ru.x);
+   if (rhsx->ru.x->lu.x->has_sign && rhsx->ru.x->ru.x->has_sign)
+    {
+     rhsx->has_sign = TRUE;
+    }
+   else
+    {
+     /* SJM 05/21/04 - not both signed - easiest to just make both word32 */
+     rhsx->has_sign = FALSE;
+     rhsx->ru.x->lu.x->has_sign = FALSE;
+     rhsx->ru.x->ru.x->has_sign = FALSE;
+    }
+   break;
+  case FCALL:
+   syp = rhsx->lu.x->lu.sy;
+   tskp = syp->el.etskp;
+   if (syp->sytyp == SYM_SF)
+    {
+     syfp = syp->el.esyftbp;
+     if (syfp->retsigned) rhsx->has_sign = TRUE;
+    }
+   else if (syp->sytyp == SYM_F)
+    {
+     /* SJM 10/02/03 - LOOKATME - old rule was put info in first dummy arg */
+     /* check to see for 2001 LRM is still true */
+
+     tpp = tskp->tskpins;
+     np = tpp->tpsy->el.enp;
+     if (np->n_signed) rhsx->has_sign = TRUE;
+    }
+   /* if call of non function error (caught already) - do nothing */
+   else return;
+
+   /* final step sets signed flag for each argument of function call */
+   for (ndp2 = rhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+    {
+     set_rhs_signed(ndp2->lu.x);
+    }
+   break;
+  case LCB:
+   /* know concatenate result never signed */
+   rhsx->has_sign = FALSE;
+   /* but components can have signed sub-expressions */
+   for (ndp2 = rhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+    {
+     set_rhs_signed(ndp2->lu.x);
+    }
+   break; 
+  default:
+   wclass = __get_widthclass(rhsx);
+   /* this is unary or binary op */
+   switch ((byte) wclass) {
+    case WIDONE:
+     set_rhs_signed(rhsx->lu.x);
+     if (rhsx->ru.x != NULL) set_rhs_signed(rhsx->ru.x);
+     rhsx->has_sign = FALSE;
+     break;
+    case WIDENONE:
+     /* this is for unaries only except for || and && */
+     /* DBG remove */
+     if (rhsx->ru.x == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     set_rhs_signed(rhsx->lu.x);
+     set_rhs_signed(rhsx->ru.x);
+     rhsx->has_sign = FALSE;
+     break;
+    case WIDMAX:
+     /* SJM 04/26/04 - unary minus can be be WID MAX */
+     /* rest of binaries */
+     set_rhs_signed(rhsx->lu.x);
+     if (rhsx->ru.x != NULL)
+      {
+       /* binary case */
+       set_rhs_signed(rhsx->ru.x);
+       if (rhsx->lu.x->has_sign && rhsx->ru.x->has_sign)
+        rhsx->has_sign = TRUE;
+       else rhsx->has_sign = FALSE;
+      }
+     else
+      {
+       /* unary case */
+       if (rhsx->lu.x->has_sign) rhsx->has_sign = TRUE;
+       else rhsx->has_sign = FALSE;
+      }
+     return;
+    case WIDLEFT:
+     /* SHIFT */
+     set_rhs_signed(rhsx->ru.x);
+     /* SJM 10/02/03 - LRM says shift count always word32 */
+     rhsx->ru.x->has_sign = FALSE;
+     set_rhs_signed(rhsx->lu.x);
+     rhsx->has_sign = rhsx->lu.x->has_sign;
+     break;
+    case WIDSELF:
+     /* for unary - and ~ - (+ too but does nothing - optimized away) */
+     set_rhs_signed(rhsx->lu.x);
+     rhsx->has_sign = rhsx->lu.x->has_sign;
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+ }
+}
+
+/*
+ * find a number in an expression with a base and return 
+ * means folded expr. will have base of first component
+ */
+static int32 find_xbase(struct expr_t *ndp)
+{
+ int32 ibas;
+
+ if (ndp->optyp == NUMBER) { ibas = ndp->ibase; return(ibas); }
+ if (__isleaf(ndp)) return((int32) '?');
+ if (ndp->lu.x != NULL)
+  {
+   ibas = find_xbase(ndp->lu.x);
+   if (ibas != '?') return(ibas);
+  }
+ if (ndp->ru.x != NULL)
+  {
+   ibas = find_xbase(ndp->ru.x);
+   if (ibas != '?') return(ibas);
+  }
+ return((int32) '?');
+}
+
+/*
+ * set and check expr is real and check for all real rhs expression 
+ *
+ * only called if know somewhere in expression there is a real 
+ * expressions must be all real but some operators take real args and return
+ * reg (1 bit) - i.e. 1 bit logicals
+ *
+ * this sets IS real and expects IS real bit to already be set for leaf nodes
+ * works bottom up and assumes leaf nodes have IS real set
+ * sets upper nodes and replaces operators
+ */
+static void setchk_real_expr(struct expr_t *xrhs)
+{
+ int32 i, oandnum, wclass;
+ struct opinfo_t *opip;
+ struct expr_t *lx, *rx;
+
+ /* is real bit already set */
+ if (__isleaf(xrhs)) return;
+
+ if (xrhs->optyp == QUEST)
+  {
+   real_setchk_quest(xrhs);
+   return;
+  }
+ if (xrhs->optyp == FCALL)
+  {
+   /* must chk real for all arguments - know fcall is real already set */
+   /* this is a structural entire expr. tree routine so must check reals */
+   /* in arguments even though unrelated and arguments probably contain */ 
+   /* no reals - using check real on these works - does some extra work */
+   /* but subtley needed because probably function is real returning */
+
+   /* if part of relational or boolean subexpression can actually be non */ 
+   /* real returning function */
+   for (rx = xrhs->ru.x; rx != NULL; rx = rx->ru.x) setchk_real_expr(rx->lu.x); 
+   return; 
+  }
+
+ /* special handling of concatenates - by here know 1 level */
+ if (xrhs->optyp == LCB)
+  {
+   for (rx = xrhs->ru.x, i = 1; rx != NULL; rx = rx->ru.x, i++)
+    {
+     setchk_real_expr(rx->lu.x);
+     /* error if any component real - concatenate never real but can be */
+     /* operator to real conditional */
+     if (rx->lu.x->is_real)
+      __sgferr(817, "real expression illegal in concatenate (pos. %d)", i);
+    }
+   return;
+  } 
+
+ oandnum = 0;
+ if ((lx = xrhs->lu.x) != NULL) { setchk_real_expr(lx); oandnum++; }
+ if ((rx = xrhs->ru.x) != NULL) { setchk_real_expr(rx); oandnum++; }
+
+ if (oandnum > 1)
+  {
+   /* binary case */
+   /* case 1: neither, operand is real - node not marked as real */
+   /* this is legal - operator is real not set so if not part of relational */
+   /* or logical error will be caught later */
+   /* example of ok of this: (i < j) || (d1 < d2) */ 
+   if (!lx->is_real && !rx->is_real) return;
+
+   /* case 2: at least one operand is real */
+   opip = &(__opinfo[xrhs->optyp]);
+   if (!opip->realop)
+    {
+     __sgferr(815, "binary operator %s cannot have real operand(s)",
+      __to_opname(xrhs->optyp));
+     return;
+    }
+   /* know legal real binary op */
+   /* notice dependent on real represented with len WBITS using b part */
+   wclass = __get_widthclass(xrhs);
+   if (wclass != WIDENONE && wclass != WIDONE)
+    {
+     /* normal real (allowed subset) operators result is real */
+     xrhs->is_real = TRUE;
+     xrhs->has_sign = TRUE;
+     xrhs->szu.xclen = REALBITS;
+     switch ((byte) xrhs->optyp) {
+      case PLUS: xrhs->optyp = REALPLUS; break;
+      case MINUS: xrhs->optyp = REALMINUS; break;
+      case TIMES: xrhs->optyp = REALTIMES; break;
+      case DIV: xrhs->optyp = REALDIV; break;
+      /* for nest real function calls may already have been converted */ 
+      case REALPLUS: break;
+      case REALMINUS: break;
+      case REALTIMES: break;
+      case REALDIV: break;
+      default: __case_terr(__FILE__, __LINE__);
+     }
+    }
+   else
+    {
+     /* if 1 bit result (comparison or &&/|| result is not real) */
+     switch ((byte) xrhs->optyp) {
+      case RELGT: xrhs->optyp = REALRELGT; break;
+      case RELGE: xrhs->optyp = REALRELGE; break;
+      case RELLT: xrhs->optyp = REALRELLT; break;
+      case RELLE: xrhs->optyp = REALRELLE; break;
+      case RELEQ: xrhs->optyp = REALRELEQ; break;
+      case RELNEQ: xrhs->optyp = REALRELNEQ; break;
+      case BOOLAND: xrhs->optyp = REALBOOLAND; break;
+      case BOOLOR: xrhs->optyp = REALBOOLOR; break;
+      /* for nest real function calls may already have been converted */ 
+      case REALRELGT: break;
+      case REALRELGE: break;
+      case REALRELLT: break;
+      case REALRELLE: break;
+      case REALRELEQ: break;
+      case REALRELNEQ: break;
+      case REALBOOLAND: break;
+      case REALBOOLOR: break;
+      default: __case_terr(__FILE__, __LINE__);
+     }
+    }
+   /* mark either non real for conversion to real */
+   if (!lx->is_real) lx->cnvt_to_real = TRUE; 
+   else if (!rx->is_real) rx->cnvt_to_real = TRUE; 
+   return;
+  }
+
+ /* SJM 10/16/00 - other part of expr. can be real if unary arg not real */
+ /* nothing to do here */
+
+ /* if non real ok, unless under relational err caught higher in expr tree */
+ /* here operand must be real since only one and result real */
+ if (!lx->is_real) return;
+
+ /* unary real case (only unary - and ! legal) */
+ if (xrhs->optyp != MINUS && xrhs->optyp != NOT)
+  {
+   __sgferr(878, "unary operator %s cannot have real operand",
+    __to_opname(xrhs->optyp));
+   return;
+  }
+
+ if (xrhs->optyp == MINUS)
+  {
+   xrhs->optyp = REALMINUS;
+   xrhs->is_real = TRUE;
+   xrhs->has_sign = TRUE; 
+   xrhs->szu.xclen = REALBITS;
+  }
+ /* result is 1 bit but not real - if arg. not real do not change */
+ else if (xrhs->optyp == NOT) xrhs->optyp = REALNOT;
+}
+
+/*
+ * set is real and check real ?:
+ *
+ * LOOKATME - converting : part of ?: to real if one real
+ */
+static void real_setchk_quest(struct expr_t *xrhs)
+{
+ struct expr_t *lx, *rx;
+
+ /* according to lrm - selector can be real (0.0 F else T) */
+ setchk_real_expr(xrhs->lu.x);
+ lx = xrhs->ru.x->lu.x;
+ setchk_real_expr(lx);
+ rx = xrhs->ru.x->ru.x;
+ setchk_real_expr(rx);
+
+ /* must change operators - this is most complicated case */
+ /* know expr. correct and either both or no operators real */ 
+ if (!xrhs->lu.x->is_real)
+  {
+   /* if either : expression real, convert other to real */
+   if (lx->is_real || rx->is_real)
+    {
+     /* notice QUEST top (not QCOL) is changed */
+     xrhs->optyp = REGREALQCOL;
+     xrhs->is_real = TRUE;
+     xrhs->has_sign = TRUE;
+     /* real is WBITS since no x value */ 
+     xrhs->szu.xclen = WBITS;
+     xrhs->ru.x->is_real = TRUE;
+     xrhs->ru.x->has_sign = TRUE;
+     /* QCOL ? is real and has real width */ 
+     xrhs->ru.x->szu.xclen = WBITS;
+     /* set bit so if either non real will get converted */
+     if (!lx->is_real) lx->cnvt_to_real = TRUE; 
+     else if (!rx->is_real) rx->cnvt_to_real = TRUE; 
+    }
+   /* can be non real subexpression of real */   
+   return;
+  }
+ /* know cond. real */
+ if (lx->is_real || rx->is_real)
+  {
+   xrhs->optyp = REALREALQUEST;
+   xrhs->ru.x->is_real = TRUE;
+   xrhs->ru.x->has_sign = TRUE;
+   xrhs->ru.x->szu.xclen = WBITS;
+   xrhs->szu.xclen = WBITS;
+   xrhs->is_real = TRUE;
+   xrhs->has_sign = TRUE;
+   /* set bit so if either non real will get converted */
+   if (!lx->is_real) lx->cnvt_to_real = TRUE; 
+   else if (!rx->is_real) rx->cnvt_to_real = TRUE; 
+   return;
+  }
+ /* notice here nothing marked as real except cond. sub expr */
+ xrhs->optyp = REALREGQUEST;  
+}
+
+/*
+ * recursively check expression special operators - still structural
+ * cannot do anything that requires any folding
+ * also empty illegal here - will have been caught
+ */
+static void chk_specialop_rhsexpr(struct expr_t *ndp)
+{
+ switch ((byte) ndp->optyp) {
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   return;
+  case ID: case GLBREF: chk_rhs_id(ndp); return;
+  case LSB:
+   chk_specialop_rhsexpr(ndp->ru.x);
+   chk_srcbsel(ndp, TRUE);
+   return;
+  case PARTSEL:
+   chk_specialop_rhsexpr(ndp->ru.x->lu.x);
+   chk_specialop_rhsexpr(ndp->ru.x->ru.x);
+   chk_srcpsel(ndp, TRUE);
+   return;
+  case LCB:
+   {
+    register struct expr_t *catndp;
+
+    for (catndp = ndp->ru.x; catndp != NULL; catndp = catndp->ru.x)
+     {
+      chk_specialop_rhsexpr(catndp->lu.x);
+      catndp->has_sign = FALSE;
+     }
+    ndp->has_sign = FALSE;
+   }
+   return;
+  case FCALL: 
+   chkspecop_fcall(ndp);
+   return;
+  case QUEST:
+   chk_specialop_rhsexpr(ndp->lu.x);
+   /* SJM 05/21/04 - these just sets the nd rel sign eval bit */
+   /* signed set elsewhere */
+   chk_specialop_rhsexpr(ndp->ru.x->lu.x);
+   chk_specialop_rhsexpr(ndp->ru.x->ru.x);
+   return;   
+  case REALREGQUEST: case REALREALQUEST: case REGREALQCOL:
+   /* SJM 10/17/99 - now real's allowed in expressions - need to check */
+   chk_specialop_rhsexpr(ndp->lu.x);
+   chk_specialop_rhsexpr(ndp->ru.x->lu.x);
+   chk_specialop_rhsexpr(ndp->ru.x->ru.x);
+   return;
+  case OPEVOR: case OPEVCOMMAOR: case OPPOSEDGE: case OPNEGEDGE:
+   __sgferr(818,
+    "event expression operator %s illegal in right hand side expression",
+    __to_opname(ndp->optyp));
+   return;
+ }
+ /* if real already checked */
+ /* ??? if (ndp->is_real) return; */ 
+
+ /* know ndp some kind of arith operator to fall thru to here */
+ /* know parsing made sure binaries have 2 ops and unaries 1 */
+ if (ndp->lu.x != NULL) chk_specialop_rhsexpr(ndp->lu.x);
+ if (ndp->ru.x != NULL) chk_specialop_rhsexpr(ndp->ru.x);
+ if (ndp->ru.x == NULL && ndp->lu.x == NULL) __arg_terr(__FILE__, __LINE__);
+
+ /* SJM 10/06/03 - now have separate proc to set sign but set rel sign eval */
+ if (ndp->szu.xclen == 1)
+  {
+   /* SJM 05/13/04 - relationals always binary */
+   if (ndp->lu.x != NULL && ndp->ru.x != NULL) 
+    {
+     if (ndp->lu.x->has_sign && ndp->ru.x->has_sign)
+      {
+       /* for reals, always signed and this flag not used */
+       switch ((byte) ndp->optyp) { 
+        case RELGE: case RELGT: case RELLE: case RELLT:
+        case RELNEQ: case RELEQ: case RELCEQ: case RELCNEQ:
+         ndp->rel_ndssign = TRUE;  
+       }
+      }
+    } 
+  }
+}
+
+/*
+ * check a known constant bit select for in range and non-z/x
+ * no lhs/rhs distinction here
+ *
+ * this can be called during source reading - 2nd part checks range
+ * that requires parameters to have fixed values
+ *
+ * return F on error or x/z number - caller decides if error needed
+ * will never get here for event since illegal in rhs or lhs expressions
+ */
+static int32 chk_srcbsel(struct expr_t *ndp, int32 is_rhs)
+{
+ struct expr_t *idndp, *rconx;
+ struct sy_t *syp;
+ struct net_t *np;
+
+ idndp = ndp->lu.x;
+ syp = idndp->lu.sy;
+ rconx = ndp->ru.x;
+ if (syp == NULL) __arg_terr(__FILE__, __LINE__);
+ if (syp->sytyp != SYM_N)
+  {
+   __sgferr(819,
+    "bit select or array index from non wire/reg \"%s\" type %s",
+    __to_idnam(idndp), __to_sytyp(__xs, syp->sytyp));
+   return(FALSE);
+  }
+ np = syp->el.enp;
+ if (!np->n_isavec && !np->n_isarr)
+  {
+   __sgferr(820, "bit select or array index of non memory and non vector %s",
+    __to_idnam(idndp));
+   return(FALSE);
+  }
+ /* selects from real params already removed - LOOKATME ?? */
+ if (np->ntyp == N_REAL && !np->n_isarr)
+  {
+   __sgferr(821, "bit select from real %s illegal", __to_idnam(idndp));
+   return(FALSE);
+  }
+ /* bit and part selects from parameters in normal rhs exprs supported */
+ if (np->n_isarr && (np->ntyp < NONWIRE_ST || np->ntyp == N_EVENT))
+  {
+   __sgferr(823, "array index of %s illegal for %s", __to_idnam(idndp),
+    __to_wtnam(__xs, np));
+   return(FALSE);
+  }
+ if (np->nrngrep == NX_CT)
+  {
+   if (is_rhs)
+    {
+     np->nu.ct->n_onrhs = TRUE;
+     if (!__expr_rhs_decl) np->n_onprocrhs = TRUE;
+    }
+   else
+    {
+     if (np->nu.ct->n_onlhs) np->nu.ct->n_2ndonlhs = TRUE;
+     else np->nu.ct->n_onlhs = TRUE;
+    }   
+  }
+
+ /* can also do real checking now */
+ switch ((byte) rconx->optyp) {
+  case NUMBER: break;
+  case ISNUMBER:
+   if (rconx->is_real) goto bs_real;
+   break;
+  case ISREALNUM:
+bs_real:
+   __sgferr(824,
+    "bit select or array index of %s cannot be real", __to_idnam(idndp));
+   return(FALSE);
+  default:
+   /* for procedural expr. checking done and simplied index expr by here */
+   if (rconx->is_real) goto bs_real; 
+   if (rconx->szu.xclen > WBITS)
+    {
+     __sgfinform(455,
+      "select index variable expression %s wider than %d - high bits ignored",
+      __msgexpr_tostr(__xs, rconx), WBITS);
+    }
+   return(TRUE);
+  }
+ /* but must fold and normalize later */
+ return(TRUE);
+}
+
+/*
+ * check a part select for in range and non-x/z
+ * no lhs/rhs distinction here
+ * part select values non x/z numbers and cannot be variable
+ * returns F on error
+ */
+static int32 chk_srcpsel(struct expr_t *ndp, int32 is_rhs)
+{
+ struct net_t *np;
+ struct expr_t *idndp;
+ struct sy_t *syp;
+
+ idndp = ndp->lu.x; 
+ syp = idndp->lu.sy;
+ if (syp == NULL)
+  {
+   __sgferr(830, "part select from parameter %s illegal", __to_idnam(idndp));
+   return(FALSE);
+  }
+ if (syp->sytyp != SYM_N)
+  {
+   __sgferr(831, "part select from non net or register \"%s\" type %s illegal",
+    __to_idnam(idndp), __to_sytyp(__xs, syp->sytyp));
+   return(FALSE);
+  }
+ np = syp->el.enp;
+ if (!np->n_isavec)
+  {
+   __sgferr(832, "part select of non vector %s illegal", __to_idnam(idndp));
+   return(FALSE);
+  }
+ /* ??? REAL ARRAYS LEGAL
+ if (np->n_isarr)
+  {
+   __sgferr(833, "part select of array %s illegal", __to_idnam(idndp));
+   return(FALSE);
+  }
+ --- */
+ if (np->ntyp == N_REAL)
+  {
+   __sgferr(834, "part select of real %s illegal", __to_idnam(idndp));
+   return(FALSE);
+  }
+ if (np->nrngrep == NX_CT)
+  {
+   if (is_rhs)
+    {
+     np->nu.ct->n_onrhs = TRUE;
+     if (!__expr_rhs_decl) np->n_onprocrhs = TRUE;
+    }
+   else
+    {
+     if (np->nu.ct->n_onlhs) np->nu.ct->n_2ndonlhs = TRUE;
+     else np->nu.ct->n_onlhs = TRUE;
+    }
+  }
+ return(TRUE);
+} 
+
+/*
+ * source (before expr. widths known) structural check of 1 function call
+ * must be call of function with right number of args
+ * argument checking elsewhere
+ */
+static void chkspecop_fcall(struct expr_t *ndp)
+{
+ register struct expr_t *fandp, *andp;
+ struct sy_t *syp;
+ struct expr_t *idndp;
+
+ /* when translating iact stmt, func. call requires scheduled thread */
+ /* since may have break in it */
+ idndp = ndp->lu.x;
+ syp = idndp->lu.sy;
+ if (syp->sytyp != SYM_F && syp->sytyp != SYM_SF)
+  {
+   __sgferr(835, "call of non function %s", __to_idnam(idndp));
+   return;
+  }
+ /* SJM 09/28/01 - set flag so can indicate func has user fcall */
+ if (syp->sytyp == SYM_F)
+  { __iact_must_sched = TRUE; __func_has_fcall = TRUE; }
+ else
+  {
+   /* for system function (maybe PLI) - unindex array legal */
+   for (fandp = ndp->ru.x; fandp != NULL; fandp = fandp->ru.x)
+    {
+     andp = fandp->lu.x;
+     /* only for PLI 2.0 system functions, unindex array legal */ 
+     if (syp->el.esyftbp->syfnum > __last_veriusertf
+      && (andp->optyp == ID || andp->optyp == GLBREF))
+      {
+       if (andp->lu.sy->el.enp->n_isarr) continue;
+      }
+     chk_specialop_rhsexpr(andp);
+    }
+   return;
+  }
+
+ for (fandp = ndp->ru.x; fandp != NULL; fandp = fandp->ru.x)
+  chk_specialop_rhsexpr(fandp->lu.x);
+}
+
+/*
+ * emit warning for word32 relationals
+ * return T if fold word32 so only 1 warning emitted
+ */
+static int32 chk_mixedsign_relops(struct expr_t *ndp)
+{
+ register struct expr_t *xp;
+
+ switch ((byte) ndp->optyp) {
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM:
+  case ID: case GLBREF:
+   break;
+  case LSB:
+   if (chk_mixedsign_relops(ndp->ru.x)) return(TRUE);
+   break;
+  case PARTSEL:
+   if (chk_mixedsign_relops(ndp->ru.x->lu.x)) return(TRUE);
+   if (chk_mixedsign_relops(ndp->ru.x->ru.x)) return(TRUE);
+   break;
+  case LCB:
+   {
+    for (xp = ndp->ru.x; xp != NULL; xp = xp->ru.x)
+     if (chk_mixedsign_relops(xp->lu.x)) return(TRUE);
+   }
+   break;
+  case FCALL: 
+   {
+    /* even if consts in concatenate, entire thing is not */
+    for (xp = ndp->ru.x; xp != NULL; xp = xp->ru.x)
+     if (chk_mixedsign_relops(xp->lu.x)) return(TRUE);
+   }
+   break;
+  default:
+   if (ndp->lu.x != NULL) if (chk_mixedsign_relops(ndp->lu.x)) return(TRUE);
+   if (ndp->ru.x != NULL) if (chk_mixedsign_relops(ndp->ru.x)) return(TRUE);
+   switch ((byte) ndp->optyp) {
+    case RELGE: case RELGT: case RELLE: case RELLT:
+     /* if either but not both or neither signed, emit warning */
+     if (ndp->lu.x->has_sign ^ ndp->ru.x->has_sign)
+      {
+       __sgfinform(440,
+        "relational operator has mixed signed and word32 operands"); 
+       return(TRUE);
+      }
+   }
+ }
+ return(FALSE);
+}
+
+/*
+ * COMPILE TIME CONSTANT FOLDING ROUTINES
+ */
+
+/*
+ * fold any normal rhs expression including specify section
+ * where know only specparams used
+ */
+static void fold_subexpr(struct expr_t *ndp)
+{
+ int32 isform;
+
+ /* notice any opempty will be marked as folded */
+ if (!ndp->folded)
+  {
+   mark_constnd(ndp, &isform);
+   fold_const(ndp);
+   ndp->folded = TRUE;
+  }
+}
+
+/*
+ * mark all constant nodes
+ * if evaluates to constant, root will have consubxpr turned on
+ * all node width's must be set before calling this
+ * any expr. that is ID but really param changed here to constant
+ *
+ * notice ISNUMBER and ISREAL are not foldable and places that need number
+ * must be split ranges or module port header selects, or must be inst by
+ * by inst. (creation of dependent param substituted exprs.) or are
+ * illegal (concatenate repeat counts)
+ *
+ * all selects from parameters (legal in normal but not param define rhs)
+ * converted to number or IS number before here because must set width
+ *
+ * for unary if operand is IS so is result
+ * for binary if either is IS, so is result, no reduction operators
+ */
+static int32 mark_constnd(register struct expr_t *ndp, int32 *has_isform)
+{
+ register struct net_t *np;
+ int32 const_subtree, cat_isform;
+ int32 is1, is2, is3, wlen, nwid, wsiz;
+ double d1;
+ word32 *wp;
+ double *dp;
+ struct xstk_t *xsp;
+
+ *has_isform = FALSE;
+ switch ((byte) ndp->optyp) {
+  case NUMBER: case REALNUM:
+   ndp->consubxpr = TRUE;
+   return(TRUE);
+  case ISNUMBER: case ISREALNUM:
+   ndp->consubxpr = TRUE;
+   ndp->consub_is = TRUE;
+   *has_isform = TRUE;
+   return(TRUE);
+  /* do not mark empty as constant */
+  case OPEMPTY: break;
+  case ID:
+   /* LOOKATME - can this be fcall that is not const */  
+   if (ndp->lu.sy->sytyp != SYM_N) break;
+
+   np = ndp->lu.sy->el.enp;
+cnvt_gref_param:
+   if (!np->n_isaparam) return(FALSE); 
+   else
+    {
+     /* must convert to ID's that are really params to number type  */
+     /* wire converted - must convert expr that points to wire here */
+     /* since parameter can be used more than once, must copy value */
+
+     /* DBG - remove */
+     nwid = __get_netwide(np);
+     if (nwid != ndp->szu.xclen) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     wlen = wlen_(nwid);
+     wsiz = 0;
+     if (np->ntyp != N_REAL)
+      {
+       if (np->srep == SR_PISNUM)
+        {
+         ndp->optyp = ISNUMBER;
+         ndp->consub_is = TRUE;
+         *has_isform = TRUE;
+         wsiz = wlen*__inst_mod->flatinum;
+        }
+       else if (np->srep == SR_PNUM)
+        {
+         ndp->optyp = NUMBER;
+         ndp->consubxpr = TRUE;
+         wsiz = wlen;
+        }
+       else __case_terr(__FILE__, __LINE__);
+
+       if (np->n_signed) ndp->has_sign = TRUE;
+       if (np->nu.ct->pstring) ndp->is_string = TRUE;
+       ndp->ibase = np->nu.ct->pbase;
+
+       if (ndp->optyp == NUMBER && nwid <= WBITS)
+        {
+         wp = np->nva.wp;
+         ndp->ru.xvi = __alloc_shareable_cval(wp[0], wp[1], nwid);
+        }
+       else
+        {
+         /* IS forms can't be shared because are changed after added */
+         if (*has_isform)
+          {
+           ndp->ru.xvi = __alloc_is_cval(wsiz);
+           /* SJM 02/23/05 - IS const alloc no longer also sets the values */ 
+           memcpy(&(__contab[ndp->ru.xvi]), np->nva.wp, 2*wsiz*WRDBYTES);
+          }
+         else
+          {
+           ndp->ru.xvi = __allocfill_cval_new(np->nva.wp, &(np->nva.wp[wsiz]),
+            wsiz);
+          }
+        }
+      }
+     else
+      {
+       /* for real xclen is 32 which produces 8 bytes object (no b part) */
+       /* but need to add to real con tab */ 
+       if (np->srep == SR_PISNUM)
+        {
+         ndp->optyp = ISREALNUM;
+         ndp->consub_is = TRUE;
+         *has_isform = TRUE;
+         /* word size is 1 since reals take 2 words but no b part */
+         ndp->ru.xvi = __allocfill_cval_new(np->nva.wp, &(np->nva.wp[wsiz]),
+          __inst_mod->flatinum);
+
+         /* LOOKATME - does this work ??? */
+         dp = (double *) &(__contab[ndp->ru.xvi]);
+         /* copy from param (aka net) form to constant value table */
+
+         /* copy from param (aka net) form to constant value table */
+         /* SJM 02/20/04 - copy every inst with real size */
+         memcpy(dp, np->nva.dp, sizeof(double)*__inst_mod->flatinum);
+        }
+       else if (np->srep == SR_PNUM)
+        {
+         ndp->optyp = REALNUM;
+         ndp->consubxpr = TRUE;
+         memcpy(&d1, np->nva.wp, sizeof(double));
+         ndp->ru.xvi = __alloc_shareable_rlcval(d1);
+         /* notice because of different byte ordering must cast word32 form */ 
+        }
+       else __case_terr(__FILE__, __LINE__);
+       ndp->is_real = TRUE;
+       ndp->has_sign = TRUE;
+      }
+    } 
+   return(TRUE);
+  case GLBREF: 
+   /* SJM - 04/21/00 - allowing simple form of xmr param ref. */
+   /* can't be IS - non loc - i.e. param that is assigned to */
+   if (ndp->lu.sy->sytyp != SYM_N) break;
+
+   np = ndp->lu.sy->el.enp;
+   if (!np->n_isaparam) break; 
+
+   if (np->srep != SR_PNUM)
+    {
+     __sgferr(3411,
+      "heirarchical reference %s of non local parameter set by defparam or pound param illegal",
+      ndp->ru.grp->gnam);
+
+     ndp->optyp = NUMBER;
+     ndp->consubxpr = TRUE;
+     /* value is same width x */
+     if (np->nwid <= WBITS)
+      {
+       ndp->ru.xvi = __alloc_shareable_cval(ALL1W, ALL1W, WBITS);
+      }
+     else
+      {
+       push_xstk_(xsp, np->nwid); 
+       one_allbits_(xsp->ap, np->nwid);
+       one_allbits_(xsp->bp, np->nwid);
+       ndp->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, wlen_(np->nwid));
+       __pop_xstk();
+      }
+     return(TRUE);
+    }
+   goto cnvt_gref_param;
+  case LSB:
+   /* must fold select expressions separately - but node never a const. */
+   mark_constnd(ndp->ru.x, has_isform);
+   break;
+  case PARTSEL:
+   mark_constnd(ndp->ru.x->lu.x, has_isform);
+   mark_constnd(ndp->ru.x->ru.x, has_isform);
+   break;
+  case FCALL:
+   /* must mark const. args as foldable but not fcall node */
+   {
+    register struct expr_t *fandp;
+
+    /* even if consts in concatenate, entire thing is not */
+    for (fandp = ndp->ru.x; fandp != NULL; fandp = fandp->ru.x)
+     mark_constnd(fandp->lu.x, &is1);
+   }
+   break;
+  case LCB:
+   /* top concatentate left field unused */
+   /* mark top for folding if all components constants */
+   {
+    register struct expr_t *ctndp;
+    int32 canfold;
+
+    cat_isform = FALSE;
+    canfold = TRUE;
+    for (ctndp = ndp->ru.x; ctndp != NULL;)
+     {
+      if (ctndp->optyp == CATCOM)
+       {
+        if (!mark_constnd(ctndp->lu.x, &is1)) canfold = FALSE;
+        else { if (is1) cat_isform = TRUE; }
+        ctndp = ctndp->ru.x;
+       }
+      else
+       {
+        if (!mark_constnd(ctndp, &is1)) canfold = FALSE;
+        else { if (is1) cat_isform = TRUE; }
+        break;
+       }
+     }
+    if (canfold)
+     {
+      ndp->consubxpr = TRUE;
+      if (cat_isform) { ndp->consub_is = TRUE; *has_isform = TRUE; } 
+      return(TRUE);
+     }
+   }
+   break;
+  case QUEST:
+   {
+    int32 m1, m2, m3;
+
+    /* only mark if all 3 constants - but really only need selector const */
+    m1 = mark_constnd(ndp->lu.x, &is1);
+    m2 = mark_constnd(ndp->ru.x->ru.x, &is2);
+    m3 = mark_constnd(ndp->ru.x->lu.x, &is3);
+    /* for now only folding if all 3 expressions constants */
+    if (m1 && m2 && m3)
+     {
+      ndp->consubxpr = TRUE;
+      /* if any IS then entire expression must eval to IS because selects */
+      /* can differ - SJM 10/17/99 */
+      if (is1 || is2 || is3 ) { ndp->consub_is = TRUE; *has_isform = TRUE; }
+      return(TRUE);
+     }
+   }
+   break;
+  case CATREP:
+   /* know left must be a constant */
+   mark_constnd(ndp->ru.x, &is1);
+   /* cat repeat value not simple number */
+   if (is1) __misc_terr(__FILE__, __LINE__);
+   break;
+  default:
+   /* know op. node to get here */
+   is2 = FALSE;
+   const_subtree = mark_constnd(ndp->lu.x, &is1);
+   if (ndp->ru.x != NULL && !mark_constnd(ndp->ru.x, &is2))
+    const_subtree = FALSE;
+   ndp->consubxpr = (const_subtree) ? TRUE : FALSE;
+   /* SJM 10/17/99 - must set has isform to propagate up tree */
+   if (is1 || is2) { ndp->consub_is = TRUE; *has_isform = TRUE; } 
+   return(const_subtree);
+  }
+ /* return for normal non constant case */
+ ndp->consubxpr = FALSE;
+ return(FALSE);
+}
+
+/*
+ * eval all constant subnodes in tree - constant reduces to number node
+ *
+ * requires expr. node widths to be set before here
+ * also __sfnam_ind must be set
+ *
+ * bit or part selects from parameters in rhs expressions are legal consts
+ * but such selects cannot be used in param rhs defining expressions
+ */
+static void fold_const(struct expr_t *ndp)
+{
+ register int32 iti;
+ int32 wlen, xreal, base, xwi, sav_xclen, xsign;
+ word32 *wp; 
+ double *dp, d1;
+ struct xstk_t *xsp;
+
+ wp = NULL;
+ /* leaves already folded unless parameter */
+ if (__isleaf(ndp))
+  {
+   if (ndp->optyp != ID) return;
+   if (idnd_var(ndp->lu.sy)) return;
+  }
+ xsp = NULL;
+ ndp->folded = TRUE;
+ /* know sub expr. evaluates to constant */
+ if (ndp->consubxpr)
+  {
+   /* --- DBG */
+   if (__debug_flg)
+    __dbg_msg("## folding constant expression %s\n",
+     __msgexpr_tostr(__xs, ndp));
+   /* --- */
+   wlen = wlen_(ndp->szu.xclen);
+   if (ndp->is_real) { xreal = TRUE; base = BDBLE; }
+   else
+    {
+     xreal = FALSE;
+     if (is_signed_decimal(ndp)) base = BDEC; else base = BHEX; 
+    }
+ 
+
+   /* case: foldable expression that does not contain or result in IS form */
+   /* notice do not need current itree place here - will crash if problem */
+   if (!ndp->consub_is)
+    {
+     xsp = __eval_xpr(ndp);
+
+is_1inst:
+     /* for constants at least need to change width of expression */ 
+     /* SJM 09/29/03 - change to handle sign extension and separate types */
+     if (xsp->xslen > ndp->szu.xclen) __narrow_sizchg(xsp, ndp->szu.xclen);
+     else if (xsp->xslen < ndp->szu.xclen)
+      {
+       if (ndp->has_sign) __sgn_xtnd_widen(xsp, ndp->szu.xclen);
+       else __sizchg_widen(xsp, ndp->szu.xclen);
+      }
+
+     /* AIV 09/29/04 - need to save the sign for a folded expr */
+     xsign = ndp->has_sign; 
+     __free2_xtree(ndp);
+     __init_xnd(ndp);
+     ndp->szu.xclen = xsp->xslen;
+     ndp->has_sign = xsign; 
+
+     /* if real know value will be real - no need for conversion */
+     if (xreal)
+      {
+       memcpy(&d1, xsp->ap, sizeof(double)); 
+       ndp->ru.xvi = __alloc_shareable_rlcval(d1);
+       ndp->optyp = REALNUM;
+       ndp->is_real = TRUE;
+       ndp->has_sign = TRUE;
+       ndp->ibase = BDBLE;
+      }
+     else
+      {
+       /* anything value set here must be (becomes) sized number */
+       if (ndp->szu.xclen <= WBITS)
+        {
+         ndp->ru.xvi = __alloc_shareable_cval(xsp->ap[0], xsp->bp[0], 
+          ndp->szu.xclen);
+        } 
+       else
+        {
+         ndp->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, wlen);
+        }
+       /* must set standard after folded expr. node flags */
+       ndp->optyp = NUMBER;
+       if (base == BDEC) { ndp->ibase = BDEC; ndp->has_sign = TRUE; }
+      }
+     __pop_xstk();
+     ndp->consubxpr = TRUE;
+     ndp->folded = TRUE;
+    
+     /* --- DBG --
+     if (__debug_flg)
+      __dbg_msg("## result is %s\n", __msgnumexpr_tostr(__xs, ndp, 0));
+     --- */
+     return;
+    }
+   /* for IS form only indication of real is is_real flag - and expr. and */
+   /* replaced constant will have same value */ 
+   if (xreal) xwi = __alloc_is_cval(__inst_mod->flatinum);
+   else
+    {
+     xwi = __alloc_is_cval(wlen*__inst_mod->flatinum);
+     wp = &(__contab[xwi]);
+    }
+   sav_xclen = ndp->szu.xclen;
+
+   for (iti = 0; iti < __inst_mod->flatinum; iti++)
+    {
+     __inst_ptr->itinum = iti; 
+     __inum = iti;
+     /* 1 value per instance number */
+     xsp = __eval_xpr(ndp);
+
+     /* know if expr real all instances will eval to real */
+     if (xreal)
+      {
+       memcpy(&d1, xsp->ap, sizeof(double)); 
+       dp = (double *) &(__contab[xwi + __inum]);
+       *dp = d1;
+      }
+     else
+      {
+       /* SJM 09/29/03 - change to handle sign extension and separate types */
+       if (xsp->xslen > ndp->szu.xclen) __narrow_sizchg(xsp, ndp->szu.xclen);
+       else if (xsp->xslen < ndp->szu.xclen)
+        {
+         if (ndp->has_sign) __sgn_xtnd_widen(xsp, ndp->szu.xclen);
+         else __sizchg_widen(xsp, ndp->szu.xclen);
+        }
+
+       memcpy(&(wp[2*wlen*__inum]), xsp->ap, 2*WRDBYTES*wlen);
+      }
+
+     /* this may no longer be IS form if only 1 inst - xstk popped at 1 inst */
+     /* FIXME is this case possible - if so, memory leak */
+     if (__inst_mod->flatinum == 1) { __pop_itstk(); goto is_1inst; }
+     __pop_xstk();
+    }
+
+   __free2_xtree(ndp);
+   __init_xnd(ndp);
+   /* notice this eliminates width - so must be set from saved */
+   ndp->szu.xclen = sav_xclen;
+   ndp->ru.xvi = xwi;
+   if (xreal) ndp->optyp = ISREALNUM; else ndp->optyp = ISNUMBER;
+   ndp->consubxpr = TRUE;
+   ndp->consub_is = TRUE;
+   ndp->folded = TRUE;
+
+   if (__debug_flg)
+    {
+     for (iti = 0; iti < __inst_mod->flatinum; iti++)
+      {
+       __force_base = BDEC;
+       __dbg_msg("## IS form result for inst. no. %d is %s (width %d)\n", iti,
+        __msgnumexpr_tostr(__xs, ndp, iti), ndp->szu.xclen);
+       __force_base = BNONE;
+      }
+    }
+   __inst_ptr->itinum = 0;
+   __inum = 0;
+   return;
+  }
+
+ /* must fold select expressions separately */
+ /* but work is done in above part of this routine */ 
+ switch ((byte) ndp->optyp) {
+  case LSB:
+   fold_const(ndp->ru.x);
+   return;
+  case PARTSEL:
+   fold_const(ndp->ru.x->lu.x);
+   fold_const(ndp->ru.x->ru.x);
+   return;
+  case QUEST:
+  /* SJM 04/26/04 - must also catch real ?: cases and check leaves only */ 
+  case REALREALQUEST:
+  case REALREGQUEST:
+  case REGREALQCOL:
+   /* will not get here if all 3 constants - could fold if cond. const */
+   /* if all 3 constants will not get here */
+   fold_const(ndp->lu.x);
+   fold_const(ndp->ru.x->lu.x);
+   fold_const(ndp->ru.x->ru.x);
+   return;
+  case FCALL:
+   {
+    register struct expr_t *fandp;
+
+    /* notice width already set for these arguments */
+    for (fandp = ndp->ru.x; fandp != NULL; fandp = fandp->ru.x)
+     {
+      if (__debug_flg)
+       __dbg_msg("## folding fcall argument expression %s\n",
+        __msgexpr_tostr(__xs, fandp->lu.x));
+      fold_const(fandp->lu.x);
+     }
+    }
+   return;
+  case LCB:
+   /* for folding elements of concatenate when not all constants */
+   {
+    register struct expr_t *ctndp;
+
+    for (ctndp = ndp->ru.x; ctndp != NULL; ctndp = ctndp->ru.x)
+     {
+      /* --- DBG
+      if (__debug_flg && ctndp->lu.x->optyp != ID)
+       {
+        __dbg_msg("## folding non all constant concatenate expression %s\n",
+  __msgexpr_tostr(__xs, ctndp->lu.x));
+       }
+      --- */
+      fold_const(ctndp->lu.x);
+     }
+    /* now know all components are numbers */
+   }
+   break;
+  case CATREP:
+   /* concatenate repeat form expansion error */
+   __misc_sgfterr(__FILE__, __LINE__);
+   break;
+  default:
+   /* may be subexpressions of normal bin. or un. that can be folded */
+   /* pass global context down - operators may change */
+   /* know this is not leaf node */
+   if (ndp->ru.x != NULL) fold_const(ndp->ru.x);
+   if (ndp->lu.x != NULL) fold_const(ndp->lu.x);
+ }
+}
+
+/*
+ * check if constant signed decimal expression
+ */
+static int32 is_signed_decimal(struct expr_t *xp)
+{
+ switch ((byte) xp->optyp) { 
+  case MINUS: case PLUS: case TIMES: case DIV: case MOD:
+   if (xp->lu.x != NULL) if (!is_signed_decimal(xp->lu.x)) return(FALSE);
+   if (xp->ru.x != NULL) return(is_signed_decimal(xp->ru.x));
+   return(TRUE);
+  case NUMBER: case ISNUMBER: 
+   if (xp->szu.xclen == 1 || xp->szu.xclen > WBITS || xp->ibase != BDEC
+    || !xp->has_sign) return(FALSE);
+   break;
+  default: return(FALSE); 
+ }
+ return(TRUE);
+}
+
+/*
+ * ROUTINES TO CHECK AND NORMALIZE SELECT CONSTANT EXPRESIONS
+ */
+
+/*
+ * check any psel or bsel constant index for in range and also
+ * normalize
+ */
+static void chk_ndfolded_specops(struct expr_t *ndp)
+{
+ switch ((byte) ndp->optyp) {
+  /* error for these already caught */
+  case ID: case GLBREF: case NUMBER: case ISNUMBER:
+  case REALNUM: case ISREALNUM: case OPEMPTY: 
+   break;
+  case LSB:
+   /* know real number error already caught */
+   /* but only call if constant - caller must check for required constant */
+   if (ndp->ru.x->optyp == NUMBER || ndp->ru.x->optyp == ISNUMBER)
+    chk_inrng_bsel(ndp);
+   /* can have embedded selects */
+   else chk_ndfolded_specops(ndp->ru.x);
+   break;
+  case PARTSEL:
+   /* here - know selects must be numbers by here */
+   chk_inrng_psel(ndp);
+   break;
+  case FCALL:
+   /* this handles embedded special things like selects */
+   chk_folded_fargs(ndp);
+   break;
+  default:
+   if (ndp->lu.x != NULL) chk_ndfolded_specops(ndp->lu.x);
+   if (ndp->ru.x != NULL) chk_ndfolded_specops(ndp->ru.x);
+ }
+}
+
+/*
+ * check a constant bit select for in range - if non constant must
+ * check at run time and this routine not called
+ * know index expression already checked and folded
+ * return F on error
+ *
+ * 2nd part of bit select checking - requires pass 2 all parameter
+ * substitution and splitting done
+ */
+static int32 chk_inrng_bsel(struct expr_t *ndp)
+{
+ int32 err;
+ int32 ri1, ri2, obwid;
+ struct expr_t *idndp, *rconx;
+ struct net_t *np;
+ char s1[RECLEN];
+ 
+ idndp = ndp->lu.x;
+ np = idndp->lu.sy->el.enp;
+ rconx = ndp->ru.x;
+
+ /* even if not number will be converted to 32 bit x */
+ /* register bit select of x ok, means make it x on rhs and all x's on lhs */
+ err = FALSE;
+
+ ri1 = ri2 = -1;
+ if (np->n_isarr) __getarr_range(np, &ri1, &ri2, &obwid);
+ else if (np->n_isavec) __getwir_range(np, &ri1, &ri2);
+ else __arg_terr(__FILE__, __LINE__);
+
+ /* case 1: reg/real that can be array */
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   /* case 1b: array */ 
+   if (np->n_isarr)
+    {
+     sprintf(s1, "array index of %s", np->nsym->synam);     
+     if (!chknorm_range(rconx, ri1, ri2, s1, FALSE)) err = TRUE;
+    }
+   /* 2b: reg */
+   else
+    {
+     sprintf(s1, "register bit select of %s", np->nsym->synam);     
+     if (!__nd_ndxnum(rconx, s1, FALSE)) err = TRUE;
+     else if (!chknorm_range(rconx, ri1, ri2, s1, FALSE))
+      err = TRUE;
+    }
+  }
+ /* case 2: wire */
+ else
+  {
+   sprintf(s1, "wire bit select of %s", np->nsym->synam);     
+   /* declarative either side select index must be non x/z */ 
+   if (!__nd_ndxnum(rconx, s1, TRUE)) err = TRUE;
+   /* if out of range, changed to end */
+   else if (!chknorm_range(rconx, ri1, ri2, s1, FALSE)) err = TRUE;
+  }
+ return(!err);
+}
+
+/*
+ * check and emit error for out of range condition
+ * also normalize if no error
+ *
+ * for all selects - string of type passed
+ * know value number or is number or will not be passed
+ */
+static int32 chknorm_range(struct expr_t *rconx, int32 ri1, int32 ri2,
+ char *emsg, int32 emit_err)
+{
+ register int32 iti, iti2;
+ int32 err, indval, newindval, errindval, alloc_new_con;
+ word32 *wp, *wp2;
+
+ if (rconx->optyp == NUMBER)
+  {
+   /* err/warn already emitted for this case */
+   if (__contab[rconx->ru.xvi + 1] != 0) return(FALSE);
+  
+   indval = (int32) __contab[rconx->ru.xvi];
+   /* ---
+   if (__debug_flg) 
+    __dbg_msg("$$$ in range check of %d in [%d:%d] - line %d\n",
+     indval, ri1, ri2, __slin_cnt);
+   --- */
+   if (!in_range(indval, ri1, ri2, &errindval))
+    {
+     if (emit_err)
+      __sgferr(836, "%s %d out of range [%d:%d] - end used", emsg, indval,
+       ri1, ri2);
+     else __sgfwarn(547, "%s %d out of range [%d:%d] - end used", emsg,
+      indval, ri1, ri2);
+     
+     indval = errindval;
+     rconx->ru.xvi = __alloc_shareable_cval((word32) indval, 0, WBITS);
+    }
+   /* normalize */
+   newindval = normalize_ndx_(indval, ri1, ri2);
+   if (newindval != indval)
+    {
+     rconx->ru.xvi = __alloc_shareable_cval((word32) newindval, 0, WBITS);
+     rconx->ind_noth0 = TRUE;
+    }
+   return(TRUE);
+  }
+ err = FALSE;
+ alloc_new_con = FALSE;
+ wp = &(__contab[rconx->ru.xvi]);
+ wp2 = NULL;
+ for (iti = 0; iti < __inst_mod->flatinum; iti++)
+  {
+   /* must normal any that are good */
+   if (wp[2*iti + 1] != 0L) continue; 
+   indval = (int32) wp[2*iti];
+   if (!in_range(indval, ri1, ri2, &errindval))
+    {
+     if (emit_err)
+      __sgferr(837, "%s %d out of range [%d:%d] (inst. %d)", emsg,
+       indval, ri1, ri2, iti);
+     else __sgfwarn(548, "%s %d out of range [%d:%d] (inst %d)", emsg,
+      indval, ri1, ri2, iti);
+     if (!alloc_new_con)
+      { 
+       /* allocate new and copy up to current */
+       rconx->ru.xvi = __alloc_is_cval(__inst_mod->flatinum);
+       wp2 = &(__contab[rconx->ru.xvi]);
+       alloc_new_con = TRUE;
+       for (iti2 = 0; iti2 < iti; iti2++)
+        {
+         wp2[2*iti2] = wp[2*iti2];
+         wp2[2*iti2 + 1] = wp[iti2 + 1]; 
+        }
+      }
+
+     wp2[2*iti] = indval = errindval;
+     /* SJM 12/22/03 - on error use end of range but b part must be set to 0 */
+     wp2[2*iti + 1] = 0;
+     err = TRUE;
+    }
+   /* know range are always non is form numbers - will have split if needed */
+   /* normalize */
+   newindval = normalize_ndx_(indval, ri1, ri2);
+   /* notice if any not h:0 form all will be */
+   if (alloc_new_con)
+    {
+     /* once any changed all must be copied */
+     wp2[2*iti] = newindval;
+     wp2[2*iti + 1] = 0;
+     /* SJM 12/22/03 - if out of rng caused alloc new this may chg h:0 */
+     if (newindval != indval) rconx->ind_noth0 = TRUE;
+    }
+   else if (newindval != indval)
+    {
+     /* allocate new and copy up to current */
+     rconx->ru.xvi = __alloc_is_cval(__inst_mod->flatinum);
+     wp2 = &(__contab[rconx->ru.xvi]);
+     alloc_new_con = TRUE;
+     for (iti2 = 0; iti2 < iti; iti2++)
+      {
+       wp2[2*iti2] = wp[2*iti2];
+       wp2[2*iti2 + 1] = wp[iti2 + 1]; 
+      }
+     /* SJM 12/22/03 - must fill and set only when allocating new */ 
+     /* this was wrongly out of loop so if same, wp2 was nil */
+     wp2[2*iti] = newindval;
+     wp2[2*iti + 1] = 0;
+     rconx->ind_noth0 = TRUE;
+    }
+  }
+ return(!err);
+}
+
+/*
+ * return T if value av between v1a and v2a
+ * if F, sets newv1a and newv2a to new extrema
+ */
+static int32 in_range(int32 ai, int32 v1a, int32 v2a, int32 *newai)
+{
+ /* case 1 low to high */
+ if (v1a < v2a)
+  {
+   if (ai < v1a) { *newai = v1a; return(FALSE); }
+   if (ai > v2a) { *newai = v2a; return(FALSE); }
+   return(TRUE);
+  }
+ /* case 2 - normal high to low */
+ if (ai > v1a) { *newai = v1a; return(FALSE); }
+ if (ai < v2a) { *newai = v2a; return(FALSE); }
+ return(TRUE);
+}
+
+/*
+ * check a part select for in range - must always be constant
+ * know index expression already checked and folded
+ * but need to convert to WBITS 
+ *
+ * 2nd part of bit select checking - requires pass 2 all parameter
+ * substitution and splitting done
+ */
+static int32 chk_inrng_psel(struct expr_t *ndp)
+{
+ int32 err, ri1, ri2, pseli1, pseli2;
+ struct expr_t *idndp, *rcon1, *rcon2;
+ struct net_t *np;
+ char s1[RECLEN];
+ 
+ idndp = ndp->lu.x;
+ np = idndp->lu.sy->el.enp;
+ rcon1 = ndp->ru.x->lu.x;
+ rcon2 = ndp->ru.x->ru.x;
+
+ /* even if not number will be converted to 32 bit x */
+ /* always error for part select range x/z - what does x in range mean */
+ err = FALSE;
+ sprintf(s1, "1st part select index of %s", np->nsym->synam);
+ if (!__nd_ndxnum(rcon1, s1, TRUE)) err = TRUE;
+ sprintf(s1, "2nd part select index of %s", np->nsym->synam);
+ if (!__nd_ndxnum(rcon2, s1, TRUE)) err = TRUE;
+
+ /* parts selects of arrays not in language */
+ __getwir_range(np, &ri1, &ri2);
+ /* check psel direction and wire direction same */
+ /* if errror (x/z for example) in range, cannot check direction */
+ if (!err)
+  {
+   pseli1 = (int32) __contab[rcon1->ru.xvi];
+   pseli2 = (int32) __contab[rcon2->ru.xvi];
+   if ((ri1 < ri2 && pseli1 > pseli2) || (ri1 > ri2 && pseli1 < pseli2))
+    {
+      __sgferr(879,
+       "part select %s range direction conflicts with net %s[%d:%d]",
+       __msgexpr_tostr(__xs, ndp), __to_idnam(ndp->lu.x), ri1, ri2);
+      err = TRUE;
+    }
+  }
+ /* even if error - try to check and normalize - ignores any x's */
+ sprintf(s1, "1st part select index of %s", np->nsym->synam);
+ if (!chknorm_range(rcon1, ri1, ri2, s1, FALSE))
+  err = TRUE;
+ sprintf(s1, "2nd part select index of %s", np->nsym->synam);
+ if (!chknorm_range(rcon2, ri1, ri2, s1, FALSE))
+  err = TRUE;
+ /* since will change out of range to top - need to reset widths */
+ /* if no change will be same */
+ pseli1 = (int32) __contab[rcon1->ru.xvi];
+ pseli2 = (int32) __contab[rcon2->ru.xvi];
+ ndp->szu.xclen = pseli1 - pseli2 + 1;  
+ return(!err);
+}
+
+/*
+ * check function call arguments after folding
+ * mainly for checking the various special system function arguments 
+ * but also check actual and formal argument number
+ */
+static void chk_folded_fargs(struct expr_t *ndp)
+{
+ register struct expr_t *fandp;
+ register struct task_pin_t *tpp;
+ int32 pwid;
+ struct sy_t *syp;
+ struct expr_t *idndp;
+ struct task_t *tskp;
+
+ idndp = ndp->lu.x;
+ syp = idndp->lu.sy;
+
+ /* SJM 10/08/04 - LOOKATME - think never need new ver 2001 x/z widening? */
+ /* this checks system function arguments */
+ if (syp->sytyp == SYM_SF) { chk_sysfargs_syntax(ndp); return; }
+
+ /* can have embedded fcalls and selects - check before arg no. match */
+ /* notice checking these even for undeclared function */
+ for (fandp = ndp->ru.x; fandp != NULL; fandp = fandp->ru.x) 
+  chk_ndfolded_specops(fandp->lu.x);
+
+ /* if funcdef error, will not be declard and also cannot check params */
+ /* but undeclared error already emitted */
+ if (!syp->sydecl) return;
+
+ /* final check is formal and actual number must match for user functions */ 
+ /* for now allowing conversions of any arg real or reg to any other */
+ /* in apl sense - yes, semantics allows assignments in both directions */
+
+ tskp = syp->el.etskp;
+ /* first pin is dummy return type */
+ tpp = tskp->tskpins->tpnxt;
+ /* point 1 past extra first argument - not part of source call */
+ fandp = ndp->ru.x;
+ for (; tpp != NULL; tpp = tpp->tpnxt, fandp = fandp->ru.x)
+  {
+   /* move to next actual argument */
+   if (fandp == NULL)
+    {
+     __sgferr(840,
+      "function %s called with too few arguments", __to_idnam(idndp));
+     return;
+    }
+
+   /* notice x/z widening does not effect num arg checking */
+
+
+   /* nwid field not set yet */
+   pwid = __get_netwide(tpp->tpsy->el.enp);
+   /* SJM 10/08/04 - for Ver 2001 because WBITS can be 64 - must widen */
+   /* unsized constant (unsiznum bit in expr rec on) to lhs width */
+   /* folded bit not set for these but will be folded to number */
+
+   if (fandp->lu.x->optyp == NUMBER && fandp->lu.x->unsiznum
+    && fandp->lu.x->szu.xclen < pwid)
+    {
+     fandp->lu.x = __widen_unsiz_rhs_assign(fandp->lu.x, pwid);
+    }
+  }
+ if (fandp != NULL)
+  __sgferr(841, "function %s called with too many arguments",
+   __to_idnam(idndp));
+}
+
+/*
+ * ROUTINE TO CHECK AND CONVERT NUMBERS THAT MUST BE INDEXES
+ */
+
+/*
+ * convert a number (non real) to 32 bit non x/z constant
+ * if possible - else error or warn - return F on error
+ *
+ * called after structural checking and constant folding
+ * always converts but returns FALSE if losing something
+ * and make value WBIT wide x and emits error 
+ * for indices and ranges - can never be real and no scaling
+ *
+ * must be called with itree loc (inst and mod set)
+ */
+extern int32 __nd_ndxnum(struct expr_t *ndp, char *emsg, int32 emit_err)
+{
+ int32 wlen, err;
+ word32 *ap, *bp;
+ word32 av, bv;
+
+ switch ((byte) ndp->optyp) {
+  case ISNUMBER: return(nd_ndxisnum(ndp, emsg, emit_err));
+  case NUMBER:
+   wlen = wlen_(ndp->szu.xclen);
+   ap = &(__contab[ndp->ru.xvi]);
+   bp = &(ap[wlen]);
+   if (ndp->szu.xclen > WBITS)
+    {
+     /* here always free-alloc to work constant */
+     __free2_xtree(ndp);
+     __init_xnd(ndp);
+     ndp->optyp = NUMBER;
+     ndp->szu.xclen = WBITS;
+
+
+     if (!vval_is0_(&(ap[1]), ndp->szu.xclen - WBITS)
+      || !vval_is0_(bp, ndp->szu.xclen))
+      { 
+       av = bv = ALL1W; 
+       __force_base = BDEC;
+       __msgexpr_tostr(__xs, ndp);
+       __force_base = BNONE;
+       err = TRUE;
+      } 
+     else { av = ap[0]; bv = 0L; err = FALSE; }
+     /* know this is WBITS */
+     ndp->ru.xvi = __alloc_shareable_cval(av, bv, WBITS);
+
+     if (err) goto wr_err;
+     return(TRUE);
+    }
+   ndp->szu.xclen = WBITS;
+   if (bp[0] == 0L) return(TRUE);
+   __force_base = BDEC;
+   __msgexpr_tostr(__xs, ndp);
+   __force_base = BNONE;
+   ndp->ru.xvi = __alloc_shareable_cval(ALL1W, ALL1W, WBITS);
+   goto wr_err;
+ } 
+ /* SJM 05/22/00 - need to save expr for error message before cnv to x */
+ __force_base = BDEC;
+ __msgexpr_tostr(__xs, ndp);
+ __force_base = BNONE;
+
+ /* normal expr - must convert to x */
+ __free2_xtree(ndp);
+ __init_xnd(ndp);
+ ndp->optyp = NUMBER;
+ ndp->szu.xclen = WBITS;
+ ndp->ru.xvi = __alloc_shareable_cval(ALL1W, ALL1W, WBITS);
+
+wr_err:
+ if (emit_err) 
+  __sgferr(902, "%s value %s not required %d bit non x/z number",
+   emsg, __xs, WBITS);
+ else __sgfwarn(582, "%s value %s not required %d bit non x/z number",
+  emsg, __xs, WBITS);
+ return(FALSE);
+}
+
+/*
+ * need an index form number that fits in 32 or 64 for delays bits
+ * know type is ISNUMBER or will not be called
+ * return F on error (not good)
+ *
+ * always converts but returns FALSE if losing something
+ * and make value WBIT x
+ * assumes itree loc pushed
+ */
+static int32 nd_ndxisnum(struct expr_t *ndp, char *emsg, int32 emit_err)
+{
+ register int32 iti;
+ int32 good, wlen;
+ word32 *wp, *wp2, *ap, *bp;
+ 
+ /* first do the checking */
+ good = TRUE;
+ wlen = wlen_(ndp->szu.xclen);
+ wp = &(__contab[ndp->ru.xvi]);
+
+ for (iti = 0; iti < __inst_mod->flatinum; iti++)
+  {
+   ap = &(wp[2*wlen*iti]);
+   bp = &(ap[wlen]);
+   if (ndp->szu.xclen > WBITS)
+    {
+     if (!vval_is0_(&(ap[1]), ndp->szu.xclen - WBITS) 
+      || !vval_is0_(bp, ndp->szu.xclen)) goto x_err;
+     continue;
+    }
+   if (bp[0] == 0L) continue;
+
+x_err:
+   __cur_sofs = 0;
+   __force_base = BDEC;
+   __msgnumexpr_tostr(__xs, ndp, iti);
+   __force_base = BNONE;
+   if (emit_err) 
+    __sgferr(902, "%s value %s not required %d bit non x/z number (inst. %d)",
+     emsg, __xs, WBITS, iti);
+   else
+    __sgfwarn(582, "%s value %s not required %d bit non x/z number (inst. %d)",
+     emsg, __xs, WBITS, iti);
+   good = FALSE;
+   ndp->ru.xvi = __alloc_shareable_cval(ALL1W, ALL1W, WBITS);
+  }
+ /* next convert if needed */
+ if (ndp->szu.xclen > WBITS)
+  {
+   /* must access old expression constant value before freeing */
+   wp = &(__contab[ndp->ru.xvi]);
+
+   __free2_xtree(ndp);
+   __init_xnd(ndp);
+   ndp->optyp = ISNUMBER;
+   ndp->szu.xclen = WBITS;
+   /* arg is words */
+   ndp->ru.xvi = __alloc_is_cval(__inst_mod->flatinum);
+   wp2 = &(__contab[ndp->ru.xvi]);
+
+   for (iti = 0; iti < __inst_mod->flatinum; iti++)
+    {
+     ap = &(wp[2*wlen*iti]);
+     bp = &(ap[wlen]);
+     wp2[2*iti] = ap[0];
+     wp2[2*iti + 1] = bp[0];
+    }
+  }
+ else ndp->szu.xclen = WBITS;
+ return(good);
+}
+
+/*
+ * SYSTEM FUNCTION ARGUMENT CHECKING ROUTINES
+ */
+
+/*
+ * check system functions call according to specific task argument
+ * requirements not needed for user funcs, type mismatches just fixed
+ * with copy there
+ *
+ * this routine must call chk rhsexpr for every argument
+ * except know global and param substitution done
+ * ndp is expr. node (i.e. left node is func name and right is args)  
+ *
+ * here few special sys func. arg lists cause net to not be deleteable
+ * but not called for all non special
+ */
+static void chk_sysfargs_syntax(struct expr_t *ndp)
+{
+ register struct expr_t *fandp;
+ int32 anum, special_syntax;
+ struct sy_t *syp;
+ struct sysfunc_t *syfp;
+ struct expr_t *fax;
+ struct net_t *np;
+
+ syp = ndp->lu.x->lu.sy;
+ syfp = syp->el.esyftbp;
+ anum = __cnt_tfargs(ndp->ru.x);
+
+ /* special check for 1 arg. */ 
+ if (anum == 1 && ndp->ru.x->lu.x->optyp == OPEMPTY)
+  {
+   __sgfwarn(633,
+    "system function call: %s(); has one empty argument - for no arguments omit the ()",
+    syp->synam);
+  }
+
+ special_syntax = FALSE;
+ switch (syfp->syfnum) {
+  /* functions that require special handling */
+  case STN_ITOR:
+   if (anum != 1) { sf_errifn(syp, 1); break; }
+   fax = ndp->ru.x->lu.x;
+   /* 32 bit width dependendent */
+   /* this should probably allow 64 bit integers */
+   __chk_rhsexpr(fax, WBITS);
+   if (fax->szu.xclen > WBITS || fax->is_real)
+    __sgferr(859,
+     "%s system function call argument %s not required width %d integer or reg",
+     syp->synam, __msgexpr_tostr(__xs, fax), WBITS);
+   special_syntax = TRUE;
+   break;
+  case STN_BITSTOREAL:
+   if (anum != 1) { sf_errifn(syp, 1); break; }
+   fax = ndp->ru.x->lu.x;
+   /* must set arg. rhs expression width using 64 bit context */
+   /* just overwrites one that is there */
+   __chk_rhsexpr(fax, REALBITS);
+   /* 64 bit width dependendent */
+   if (fax->szu.xclen != 64 || fax->is_real)
+    __sgfwarn(634,
+     "%s system function call argument %s should be 64 bit wide non real",
+     syp->synam, __msgexpr_tostr(__xs, fax));
+   special_syntax = TRUE;
+   break;
+  case STN_RTOI:
+  case STN_REALTOBITS:
+   if (anum != 1) { sf_errifn(syp, 1); break; } 
+   fax = ndp->ru.x->lu.x;
+   __chk_rhsexpr(fax, 0);
+   if (!fax->is_real)
+    __sgferr(843,
+     "%s system function call argument %s is not required real expression",
+     syp->synam, __msgexpr_tostr(__xs, fax));
+   special_syntax = TRUE;
+   break;
+  case STN_SIGNED:
+   if (anum != 1) { sf_errifn(syp, 1); break; } 
+   fax = ndp->ru.x->lu.x;
+   /* no context for this special case sys func that does nothing */
+   /* and whose return value width is same as arg width */
+   __chk_rhsexpr(fax, 0);
+   if (fax->has_sign)
+    __sgfinform(3007,
+     "argment %s to new 2001 $signed system task already signed",
+     __msgexpr_tostr(__xs, fax));
+   special_syntax = TRUE;
+   break;
+  case STN_UNSIGNED:
+   if (anum != 1) { sf_errifn(syp, 1); break; } 
+   fax = ndp->ru.x->lu.x;
+   /* no context for this special case sys func that does nothing */
+   /* and whose return value width is same as arg width */
+   __chk_rhsexpr(fax, 0);
+   if (!fax->has_sign)
+    __sgfinform(3007,
+     "argment %s to new 2001 $word32 system task already unsigned",
+     __msgexpr_tostr(__xs, fax));
+   special_syntax = TRUE;
+   break;
+  case STN_COUNT_DRIVERS:
+   chksf_count_drivers(ndp, anum);
+   special_syntax = TRUE;
+   break;
+  case STN_GETPATTERN:
+   __rhs_isgetpat = TRUE;
+   chksf_getpattern(syp, ndp, anum);
+   special_syntax = TRUE;
+   break;
+  case STN_SCALE:
+   /* this takes one module value (cannot be expr.) that should be time */
+   special_syntax = TRUE;
+   if (anum != 1) { sf_errifn(syp, 1); break; }
+   fax = ndp->ru.x->lu.x;
+   if (fax->optyp != GLBREF)
+    {
+     __sgferr(844, 
+      "$scale system function argument %s must be cross module hierarchical reference",
+      __msgexpr_tostr(__xs, fax));
+     break;
+    }
+   syp = fax->lu.sy;
+   if (syp->sytyp == SYM_M || syp->sytyp == SYM_I)
+    __arg_terr(__FILE__, __LINE__);
+   np = syp->el.enp;
+   if (__get_netwide(np) > TIMEBITS)  
+    __sgfwarn(637,
+     "$scale argument %s value wider than %d bits - will be truncated",
+     fax->ru.grp->gnam, TIMEBITS); 
+   break;
+  case STN_Q_FULL:
+   chksf_q_full(ndp, anum);
+   special_syntax = TRUE;
+   break;
+  case STN_RANDOM:
+   /* various dist. of random number generators - all params ins, ret. int32 */
+   chksf_rand(ndp, 1, anum);
+   special_syntax = TRUE;
+   break;
+  case STN_DIST_CHI_SQUARE:
+  case STN_DIST_EXPONENTIAL:
+  case STN_DIST_POISSON:
+  case STN_DIST_T:
+   chksf_rand(ndp, 2, anum);
+   special_syntax = TRUE;
+   break;
+  case STN_DIST_UNIFORM:
+  case STN_DIST_NORMAL:
+  case STN_DIST_ERLANG:
+   chksf_rand(ndp, 3, anum);
+   special_syntax = TRUE;
+   break;
+
+  /* functions that must not have any arguments */
+  case STN_REALTIME: case STN_STIME: case STN_TIME:
+  case STN_STICKSTIME: case STN_TICKSTIME:
+  case STN_RESET_COUNT: case STN_RESET_VALUE:
+   if (anum != 0)
+    {
+     /* needs to be warning and throw away arguments */
+     __sgferr(846,
+      "%s system function has %d arguments but no arguments allowed",
+      syp->synam, anum);
+     ndp->ru.x = NULL;
+    }
+   break;
+
+  /* functions that take exactly one argument */
+  case STN_FOPEN:
+   /* AIV 09/08/03 - changed now can take one or 2 args */
+   /* $fopen([filename]) (mcd form) or $fopen([filename], [open type str]) */
+   if (anum !=1 && anum !=2)        
+    {
+     __sgferr(851,
+     "%s system function illegal number of arguments (%d) - 1 or 2 legal",
+     syp->synam, anum);
+    }
+   break; 
+  /* AIV 09/08/03 - new fileio system functions */
+  case STN_FGETC: case STN_FTELL: case STN_REWIND:
+   /* code = $fgetc([fd]), code = $ftell([fd]), code = $rewind([fd]) */
+   if (anum != 1) sf_errifn(syp, 1);
+   break;
+  case STN_UNGETC:
+   /* code = $ungetc([char], [fd]) - [fd] has high bit on */ 
+   if (anum != 2) sf_errifn(syp, 2);
+   break;
+  case STN_FSEEK:
+   /* code = $fseek([fd], [offset], [operation]) - [fd] has high bit on */ 
+   /* $fseek([fd], [offset], [operation]) */
+   if (anum != 3) sf_errifn(syp, 3);
+   break; 
+  case STN_FGETS:
+   /* code = $fgets([proc lhs], [fd]) */ 
+   /* this inhibits normal rhs checking of args */ 
+   special_syntax = TRUE;
+   if (anum != 2) { sf_errifn(syp, 2); break; }
+   fax = ndp->ru.x;
+   __chk_lhsexpr(fax->lu.x, LHS_PROC); 
+   fax = fax->ru.x;
+   __chk_rhsexpr(fax->lu.x, 32);
+   break;
+  case STN_FERROR:
+   /* [user errno] = $ferror([fd], [proc lhs]) */ 
+   /* this inhibits normal rhs checking of args */ 
+   if (anum != 2) { sf_errifn(syp, 3); return; }
+   fax = ndp->ru.x;
+   __chk_rhsexpr(fax->lu.x, 32);
+   fax = fax->ru.x;
+   __chk_lhsexpr(fax->lu.x, LHS_PROC); 
+   special_syntax = TRUE;
+   break;
+  case STN_FSCANF: case STN_SSCANF:
+   /* $fscanf([fd], ...) or $sscanf([proc lhs], ...) */
+   if (anum < 3)
+    {
+     __sgferr(851, "%s system function does not have required three arguments",
+      syp->synam);
+     return;
+    }
+   fax = ndp->ru.x;
+   /* width self determined */
+   __chk_rhsexpr(fax->lu.x, 0);
+   fax = fax->ru.x;
+   fax = fax->ru.x;
+   /* width self determined */
+   __chk_rhsexpr(fax->lu.x, 0);
+   for (fandp = fax->ru.x; fandp != NULL; fandp = fandp->ru.x)
+    {
+     __chk_lhsexpr(fandp->lu.x, LHS_PROC);
+    }
+   special_syntax = TRUE;
+   break;
+  case STN_FREAD:
+   /* for reg: code = $fgets([proc lhs], [fd]) - size from [proc lhs] size */ 
+   /* for mem $fgets(mem, [fd], {[start], [count] optional}) */
+   if (anum < 2 || anum > 4)        
+    {
+     __sgferr(851,
+      "%s system function illegal number of arguments (%d) - 2, 3, or 4 legal",
+      syp->synam, anum);
+    }
+   fax = ndp->ru.x;
+   /* if first arg is memory and not indexed ok */
+   if (fax->lu.x->optyp == ID || fax->lu.x->optyp == GLBREF)
+    {
+     if (fax->lu.x->lu.sy->el.enp->n_isarr) goto first_arg_ok;
+    }
+   __chk_lhsexpr(fax->lu.x, LHS_PROC);
+first_arg_ok:
+   /* check rest of args as normal rhs */
+   for (fandp = fax->ru.x; fandp != NULL; fandp = fandp->ru.x)
+    {
+     fax = fandp->lu.x;
+     /* next 3 are 32 bits numbers and optional */ 
+     __chk_rhsexpr(fax, WBITS);
+    }
+   special_syntax = TRUE;
+   break;
+  case STN_TESTPLUSARGS:
+   if (anum != 1) sf_errifn(syp, 1);
+   break;
+  case STN_SCANPLUSARGS:  
+   if (anum != 2) sf_errifn(syp, 2);
+   fandp = ndp->ru.x; 
+   if (anum >= 1) { fax = fandp->lu.x; __chk_rhsexpr(fax, 0); }
+   if (anum >= 2)
+    { fandp = fandp->ru.x; fax = fandp->lu.x; __chk_lhsexpr(fax, LHS_PROC); }
+   special_syntax = TRUE;
+   break;
+  /* SJM 03/09/00 - added built-in math functins and can be used with */
+  /* constant args in parameter expressions */
+  case STN_COS: case STN_SIN: case STN_TAN: case STN_ACOS: case STN_ASIN:
+  case STN_ATAN: case STN_COSH: case STN_SINH: case STN_TANH:
+  case STN_INT: case STN_SGN:
+  case STN_LN: case STN_LOG10: case STN_ABS: case STN_SQRT: case STN_EXP:
+  case STN_HSQRT: case STN_HLOG: case STN_HLOG10:
+  case STN_ATANH: case STN_ACOSH: case STN_ASINH:
+   if (anum != 1) sf_errifn(syp, 1);
+   break;
+  case STN_POW: case STN_MIN: case STN_MAX:
+  case STN_HPOW: case STN_HPWR: case STN_HSIGN: case STN_HDB:
+  case STN_HYPOT: case STN_ATAN2:
+   if (anum != 2) sf_errifn(syp, 2);
+   break;
+  default: 
+   if (syfp->syfnum >= BASE_VERIUSERTFS && (int32) syfp->syfnum <= __last_systf)
+    {
+     /* chk and bld user tf_ or systf vpi_ pli function or real function */
+     chkbld_pli_func(ndp, (int32) syfp->syfnum);
+     return;
+    }
+   /* fall through on built-in system function */
+  }
+ if (special_syntax) return;
+
+ /* if this is not executed width not check for wrong array/event usage */
+ /* or bit/part select problems */
+ /* this checks all of argument as rhs expr. - prev. chk rhsexpr stopped */
+ /* when hit system function */
+ for (fandp = ndp->ru.x; fandp != NULL; fandp = fandp->ru.x)
+  {
+   fax = fandp->lu.x;
+   __chk_rhsexpr(fax, 0);
+  }
+}
+
+/*
+ * check build tf rec for pli function
+ *
+ * this is passed top of fcall expr. node
+ * know this is called with __cur task and __cur mod set
+ * do everything but call user checktf even if errors
+ * will probably crash here if user pointers bad
+ */
+static void chkbld_pli_func(struct expr_t *fcallx, int32 sfnum)
+{
+ int32 sav_errcnt, anum;
+ struct tfrec_t *tfrp;
+
+ sav_errcnt = __pv_err_cnt;
+
+ /* also check syntax of argument list */
+ /* this sets tf_rw flags */
+ if (fcallx->ru.x != NULL)
+  { chk_pli_arglist(fcallx->ru.x, sfnum); anum = __cnt_tfargs(fcallx->ru.x); }
+ else anum = 0;
+
+ /* need separate routine for vpi_ systfs compiletf and maybe sizetf */
+ if (sfnum > __last_veriusertf)
+  {
+   __chkbld_vpi_systf_func(fcallx);
+   return;
+  }
+
+ /* allocate the tf aux d.s. and link on to func. name expr unused len fld */
+ /* every call of tf_ system function needs d.s. chges (pvc flags etc) */
+ tfrp = chkalloc_tfrec(fcallx->ru.x, anum);
+ tfrp->tf_func = TRUE;
+ /* need both direction links */
+ tfrp->tfu.callx = fcallx;
+ fcallx->lu.x->szu.xfrec = tfrp;
+ if (__tfrec_hdr == NULL) __tfrec_hdr = __tfrec_end = tfrp;
+ else { __tfrec_end->tfrnxt = tfrp; __tfrec_end = tfrp; }
+
+ /* cannot call tf routines if errors */
+ if (__pv_err_cnt != sav_errcnt) return;
+
+ /* call the sizetf - this sets the func. return width in tf rec */
+ /* must he called or cannot check rhs exprs */
+ __pli_func_sizetf(fcallx);
+}
+
+/*
+ * check PLI _tf and vpi_ systf routine argument syntax  
+ * notice build aux. d.s. and call checktf routine during prep for tf_
+ */
+static void chk_pli_arglist(register struct expr_t *argxp, int32 stfnum)
+{
+ int32 lhstyp;
+ struct expr_t *xp;
+ struct sy_t *syp;
+ 
+ /* right offspring is first argument */
+ for (; argxp != NULL; argxp = argxp->ru.x)
+  {
+   xp = argxp->lu.x;
+   /* XMR task and inst scope arguments legal and are not checked */
+   /* PLI deals with argument */
+   /* if expr. can't contain scope object - i.e. this is special form */
+   if (xp->optyp == GLBREF)
+    {
+     syp = xp->lu.sy; 
+     /* LOOKATME - why are top level modules SYM M not SYM I? */
+     if (syp->sytyp == SYM_M) continue; 
+
+     if (syp->sytyp == SYM_I || syp->sytyp == SYM_TSK
+      || syp->sytyp == SYM_LB) continue;  
+
+     /* function scope object illegal - will be converted to fcall */
+     /* DBG remove --- */
+     if (syp->sytyp == SYM_F) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     /* fall through normal XMR */
+    }
+
+   /* for vpi_ system tasks or functions, entire array legal */
+   if (stfnum > __last_veriusertf)
+    {
+     if ((xp->optyp == ID || xp->optyp == GLBREF) && xp->lu.sy->sytyp == SYM_N
+      && xp->lu.sy->el.enp->n_isarr) continue;
+    }
+   /* can be assigned to must be treated as lhs expr */
+   if (tfexpr_isrw(xp))
+    {
+     if (lhs_is_decl(xp)) lhstyp = LHS_DECL; else lhstyp = LHS_PROC;
+     __chk_lhsexpr(xp, lhstyp);
+     xp->tf_isrw = TRUE;
+    }
+   else __chk_rhsexpr(xp, 0);
+  }
+}
+
+/*
+ * for user tf (task or func.) args - set tf_isrw if expr can be assigned to
+ * concatenates are legal Verilog but not PLI tf_ lvalues
+ */
+static int32 tfexpr_isrw(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ /* only simplify/check bit and part select expressions (not lvals) */
+ switch ((byte) ndp->optyp) {
+  case ID: case GLBREF:
+   /* notice even for global lu.x actual symbol set */
+   if (ndp->lu.sy->sytyp != SYM_N) return(FALSE);
+   np = ndp->lu.sy->el.enp;
+   /* possible for unexpanded parameters here */ 
+   if (np->n_isaparam) return(FALSE);
+   return(TRUE);
+  /* this include array index */
+  case LSB: case PARTSEL: return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*
+ * return T if lhs rw expr. is declarative else F is procedural 
+ */
+static int32 lhs_is_decl(struct expr_t *xp)
+{
+ struct net_t *np;
+
+ if (xp->optyp == LSB || xp->optyp == PARTSEL)
+  np = xp->lu.x->lu.sy->el.enp; 
+ else np = xp->lu.sy->el.enp;
+ if (np->ntyp >= NONWIRE_ST) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * alloc and initialize a tf_ auxialiary record
+ * always set 0th arg. (for tf_ func only) to nil here
+ */
+static struct tfrec_t *chkalloc_tfrec(struct expr_t *argxp,
+ int32 anum)
+{ 
+ register int32 i;
+ int32 insts;
+ struct tfrec_t *tfrp;
+
+ if (__inst_mod == NULL) insts = 1;
+ else insts = __inst_mod->flatinum;
+ tfrp = (struct tfrec_t *) __my_malloc(sizeof(struct tfrec_t)); 
+ tfrp->tf_func = FALSE;
+ tfrp->fretreal = FALSE;
+ tfrp->tffnam_ind = __sfnam_ind;
+ tfrp->tflin_cnt = __slin_cnt;
+ tfrp->tfu.callx = NULL;
+ /* this is number - 1 since 0th is unused for task ret. val for func. */ 
+ tfrp->tfanump1 = anum + 1;
+ tfrp->fretsiz = -1;
+ tfrp->tf_inmdp = __inst_mod;
+ tfrp->tf_intskp = __cur_tsk;
+ tfrp->tfargs = alloc_tfarg(argxp, anum + 1, insts);
+
+ tfrp->asynchon = (byte *) __my_malloc(insts); 
+ memset(tfrp->asynchon, 0, insts);
+ /* some save area for user between calls but rather pointless */
+ tfrp->savwrkarea = (char **) __my_malloc(insts*sizeof(char *));
+ tfrp->pvcdcep = (struct dceauxlst_t **)
+  __my_malloc(insts*sizeof(struct dceauxlst_t *));
+ tfrp->sync_tevp = (i_tev_ndx *) __my_malloc(insts*sizeof(i_tev_ndx)); 
+ tfrp->rosync_tevp = (i_tev_ndx *) __my_malloc(insts*sizeof(i_tev_ndx)); 
+ tfrp->setd_telst = (struct tevlst_t **) 
+  __my_malloc(insts*sizeof(struct tevlst_t *));
+ for (i = 0; i < insts; i++)
+  {
+   tfrp->savwrkarea[i] = NULL;
+   tfrp->pvcdcep[i] = NULL;
+   tfrp->sync_tevp[i] = -1;
+   tfrp->rosync_tevp[i] = -1;
+   tfrp->setd_telst[i] = NULL;
+  }
+ tfrp->tfrnxt = NULL;
+ return(tfrp);
+}
+
+/*
+ * allocate and initialize the tf argument record array
+ * notice this is an array not an array of ptrs to the records
+ */
+static struct tfarg_t *alloc_tfarg(register struct expr_t *argxp,
+ int32 anump1, int32 insts)
+{
+ register int32 i, pi;
+ register struct expr_t *xp;
+ struct tfarg_t *tfatab, *tfap;
+ 
+ /* notice if no args still will allocate 1 even if tf_ task */
+ tfatab = (struct tfarg_t *) __my_malloc(anump1*sizeof(struct tfarg_t));
+ tfap = &(tfatab[0]); 
+ tfap->arg.awp = NULL; 
+ tfap->old_pvc_flgs = NULL;
+ tfap->sav_pvc_flgs = NULL;
+ tfap->sav_xinfos = NULL;
+ tfap->tfdrv_wp.wp = NULL;
+
+ for (pi = 1; argxp != NULL; argxp = argxp->ru.x, pi++)
+  {
+   tfap = &(tfatab[pi]);
+   xp = argxp->lu.x;
+   tfap->arg.axp = xp;
+   tfap->old_pvc_flgs = (byte *) __my_malloc(insts); 
+   memset(tfap->old_pvc_flgs, 0, insts);
+   tfap->sav_pvc_flgs = (byte *) __my_malloc(insts); 
+   memset(tfap->sav_pvc_flgs, 0, insts);
+   tfap->dputp_tedlst = (struct dltevlst_t **)
+    __my_malloc(insts*sizeof(struct dltevlst_t *));
+   for (i = 0; i < insts; i++) tfap->dputp_tedlst[i] = NULL;
+   tfap->sav_xinfos = (char **) __my_malloc(insts*sizeof(char *));
+   for (i = 0; i < insts; i++) tfap->sav_xinfos[i] = NULL;
+
+   if (xp->tf_isrw)
+    {
+     if (xp->optyp == ID || xp->optyp == GLBREF) 
+      tfap->anp = xp->lu.sy->el.enp;
+     else if (xp->optyp == LSB || xp->optyp == PARTSEL)
+      tfap->anp = xp->lu.x->lu.sy->el.enp;
+     else __case_terr(__FILE__, __LINE__);
+     tfap->tfdrv_wp.bp = NULL;
+     /* only have node infos if expr. rw */
+    }
+   /* SJM 04/20/00 - must allo set drive to nil if not rw */
+   else { tfap->anp = NULL; tfap->tfdrv_wp.bp = NULL; }
+  }
+ return(tfatab);
+}
+
+/*
+ * count no. of function arguments
+ */
+extern int32 __cnt_tfargs(register struct expr_t *argndp)
+{
+ int32 anum;
+
+ for (anum = 0; argndp != NULL; argndp = argndp->ru.x) anum++;
+ return(anum);
+}
+
+/*
+ * check count drivers system function arguments (lhs)
+ */
+static void chksf_count_drivers(struct expr_t *ndp, int32 anum)
+{
+ register struct expr_t *fandp;
+
+ if (anum > 6 || anum < 1)
+  {
+   __sgferr(847,
+    "$countdrivers system function call must have from 1 to 6 arguments - has %d",
+    anum);
+   return;
+  }
+
+ /* first argument must be good declarative lhs and 1 bit form */ 
+ fandp = ndp->ru.x;
+ __chk_lhsexpr(fandp->lu.x, LHS_DECL);
+ if (!is_1bwire(fandp->lu.x))
+  {
+   __sgferr(903,
+    "$count_drivers system function first argument %s not scalar or constant bit select",
+     __msgexpr_tostr(__xs, fandp->lu.x));
+  }
+
+ /* rest of arguments must be procedural lhs since output params */
+ /* ,, common and legal lhs - these do not effect gate eater must be reg */
+ for (fandp = fandp->ru.x; fandp != NULL; fandp = fandp->ru.x)
+  __chk_lhsexpr(fandp->lu.x, LHS_PROC);
+}
+
+/*
+ * return T if expression is a scalar wire or a bit select of scalared wire
+ * also if bit select index x 
+ */
+static int32 is_1bwire(struct expr_t *ndp)
+{
+ int32 rv;
+ struct net_t *np;
+ struct expr_t *idndp;
+ struct xstk_t *xsp;
+
+ if (ndp->optyp == LSB)
+  {
+   idndp = ndp->lu.x; 
+   if (ndp->ru.x->optyp != NUMBER && ndp->ru.x->optyp != ISNUMBER)
+    return(FALSE); 
+   np = idndp->lu.sy->el.enp;
+   if (np->nrngrep == NX_CT)
+    {
+     if ((__no_expand && np->nu.ct->n_spltstate != SPLT_SCAL)
+      || np->nu.ct->n_spltstate == SPLT_VECT) return(FALSE);
+    }
+   else if (!np->vec_scalared) return(FALSE);
+
+   xsp = __eval_xpr(ndp->ru.x);
+   /* if out of range or constant x index still error here */
+   if (!vval_is0_(xsp->bp, xsp->xslen)) rv = FALSE; else rv = TRUE; 
+   __pop_xstk();
+   return(rv);
+  }
+ else
+  {
+   np = ndp->lu.sy->el.enp;
+   if (ndp->optyp != ID && ndp->optyp != GLBREF) return(FALSE);
+   np = ndp->lu.sy->el.enp;
+  }
+ if (np->ntyp >= NONWIRE_ST) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * check getpattern system function arguments - checks very limited usage
+ */
+static void chksf_getpattern(struct sy_t *syp, struct expr_t *ndp,
+ int32 anum)
+{
+ struct net_t *np;
+ struct expr_t *fax;
+
+ if (anum != 1)
+  {
+   sf_errifn(syp, 1);
+   if (anum > 1) ndp->ru.x->ru.x = NULL;
+   else return;
+  }
+ if (!__chking_conta)
+  __sgferr(849,
+   "$getpattern system function call not on right hand side of continuous assignment");
+ fax = ndp->ru.x->lu.x;
+ if (fax->optyp == LSB)
+  {
+   np = fax->lu.x->lu.sy->el.enp;
+   if (np->n_isarr)
+    {
+     /* getpattern result is same width as arg. */
+     /* must make sure constant folding done */
+     __chk_rhsexpr(fax, 0);
+     if (fax->ru.x->optyp != ID) goto gpat_err;
+     ndp->szu.xclen = fax->lu.x->szu.xclen;
+     return;
+    }
+  }
+gpat_err:
+ __sgferr(850,
+  "argument to $getpattern system function not variable indexed array");
+}
+
+/*
+ * system function wrong number of arguments error
+ */
+static void sf_errifn(struct sy_t *syp, int32 expn)
+{
+ __sgferr(851, "system function %s call does not have required %d arguments",
+  syp->synam, expn);
+}
+
+/*
+ * check the $q_full system function
+ * if final argument not needed can be left out
+ */
+static void chksf_q_full( struct expr_t *ndp, int32 anum)
+{
+ struct expr_t *fax;
+
+ /* but for now making it an error */
+ if (anum > 2 || anum < 1)
+  __sgferr(847,
+   "$q_full system function must have either 1 or 2 arguments not %d", anum);
+
+ fax = ndp->ru.x;
+ /* context here must be WBITS and also must change width during exec */
+ __chk_rhsexpr(fax->lu.x, WBITS);
+ if (anum == 2) { fax = fax->ru.x; __chk_lhsexpr(fax->lu.x, LHS_PROC); }
+}
+
+/*
+ * check a random number generator type system function
+ *
+ * know first argument if present is always seed lvalue
+ */
+static void chksf_rand(struct expr_t *ndp, int32 maxanum, int32 anum)
+{
+ struct sy_t *syp;
+ struct expr_t *fax;
+
+ syp = ndp->lu.x->lu.sy;
+ if (anum > maxanum)
+  {
+   __sgferr(847,
+    "%s system function must have less than %d arguments - has %d",
+    syp->synam, maxanum + 1, anum);
+   return;
+  }
+ if (anum == 0) return;
+ fax = ndp->ru.x;
+ if (fax->lu.x->optyp != OPEMPTY)
+  {
+   /* seed argument can be any procedural lhs including ,, - OPEMPTY */ 
+   __chk_lhsexpr(fax->lu.x, LHS_PROC);
+   if (fax->lu.x->szu.xclen != WBITS) 
+    __sgferr(877, "%s system function first argument %s must be 32 bits",
+    syp->synam, __msgexpr_tostr(__xs, fax->lu.x));
+  }
+ /* check from 2nd on - must be rvalue not lvalue */
+ for (fax = fax->ru.x; fax != NULL; fax = fax->ru.x)
+  __chk_rhsexpr(fax->lu.x, 0);
+}
+
+/*
+ * PASS 2 LHS EXPRESSION CHECKING ROUTINES
+ */
+
+/*
+ * check a lhs expression
+ * needs __sfnam_ind to be set before called
+ * convention is to mark all ID and GLBIDs that are lhs expr and top
+ * expr. as lhs expr.
+ */
+extern int32 __chk_lhsexpr(struct expr_t *ndp, int32 lhstyp)
+{
+ if (ndp->optyp == LCB)
+  {
+   unwind_lhsconcats(ndp);
+  }
+ if (!chksyn_lhsexpr(ndp, TRUE, lhstyp)) return(FALSE);
+ /* even if error try to set */
+ __set_lhswidth(ndp);
+ ndp->x_islhs = TRUE; 
+ return(TRUE);  
+}
+
+/*
+ * check syntax of lhs lvalue expression
+ * also marks lhs expression nodes and wires
+ * needs __sfnam_ind to be set before called
+ * return FALSE on error
+ */
+static int32 chksyn_lhsexpr(struct expr_t *ndp, int32 is_top, int32 lhstyp)
+{
+ struct expr_t *erndp;
+ struct net_t *np;
+ struct sy_t *syp;
+
+ /* only simplify/check bit and part select expressions (not lvals) */
+ switch ((byte) ndp->optyp) {
+  case ID: case GLBREF:
+   syp = ndp->lu.sy;
+   if (syp->sytyp != SYM_N)
+    { 
+     __sgferr(1046, "symbol %s of type %s illegal left hand side value",
+      syp->synam, __to_sytyp(__xs, syp->sytyp));
+     return(FALSE);
+    }
+
+   ndp->szu.xclen = __get_netwide(syp->el.enp);
+   ndp->x_islhs = TRUE; 
+   erndp = ndp;
+
+   /* unindexed array illegal on lhs */
+   np = syp->el.enp;
+   if (np->n_isarr) 
+    {
+     __sgferr(1046, "entire (unindexed) array %s illegal left hand side value",
+      np->nsym->synam);
+     return(FALSE);
+    }
+
+chk_id:
+   np = syp->el.enp;
+   if (np->n_isaparam)
+    {
+     __sgferr(854, "assignment to parameter illegal");
+     return(FALSE);
+    }
+   if (np->nrngrep == NX_CT)
+    {
+     if (np->nu.ct->n_onlhs) np->nu.ct->n_2ndonlhs = TRUE; 
+     else np->nu.ct->n_onlhs = TRUE;
+    }
+
+   if (np->ntyp == N_REAL) { ndp->is_real = TRUE; ndp->has_sign = TRUE; }
+   if (lhstyp == LHS_DECL)
+    {
+     if (np->n_stren) ndp->x_stren = TRUE;
+     return(__nd_wire(erndp));
+    }
+   else return(nd_reg(erndp));
+  case LSB:
+   erndp = ndp->lu.x;
+   syp = erndp->lu.sy;
+   /* this does not need to be a constant */
+   /* lhs decl. bit selects must be constants see lrm 5-1, 12-16 (rule 2) */
+   if (lhstyp == LHS_DECL)
+    {
+     /* this must convert to bit index constant (maybe IS form) */
+     if (!chk_srcbsel(ndp, FALSE)) return(FALSE);
+     if (!__chk_rhsexpr(ndp->ru.x, 0)) return(FALSE);
+     chk_inrng_bsel(ndp);
+     /* even if error, check decl. scalared */
+     if (!__chk_lhsdecl_scalared(erndp)) return(FALSE);
+    }
+   /* procedural lhs can be non constant */
+   else
+    {
+     if (!chk_srcbsel(ndp, FALSE)) return(FALSE);
+     if (!__chk_rhsexpr(ndp->ru.x, 0)) return(FALSE);
+     /* here either constant or expr. ok */
+     if (ndp->ru.x->optyp == NUMBER || ndp->ru.x->optyp == ISNUMBER)
+      {
+       /* for procedural number lhs warn if out of range but gets assigned */
+       if (!chk_inrng_bsel(ndp)) return(FALSE);
+      }
+    }
+   goto chk_id;
+  case PARTSEL:
+   syp = ndp->lu.x->lu.sy;
+   erndp = ndp->lu.x;
+   if (!chk_srcpsel(ndp, FALSE)) return(FALSE);
+   if (!__chk_rhsexpr(ndp->ru.x->lu.x, 0)) return(FALSE);
+   if (!__chk_rhsexpr(ndp->ru.x->ru.x, 0)) return(FALSE);
+   if (!chk_inrng_psel(ndp)) return(FALSE);
+   if (lhstyp == LHS_DECL)
+    {
+     if (!__chk_lhsdecl_scalared(erndp)) return(FALSE);
+    }
+   goto chk_id;
+  case LCB:
+   /* DBG remove */
+   if (!is_top) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* notice legal lhs concatenates element width self determined */
+   {
+    register struct expr_t *ndp2;
+    int32 errind, has_stren, i;
+
+    errind = TRUE;
+    has_stren = FALSE;
+    for (ndp2 = ndp->ru.x, i = 1; ndp2 != NULL; ndp2 = ndp2->ru.x, i++)
+     {
+      /* widths get set after checking */
+      if (!chksyn_lhsexpr(ndp2->lu.x, FALSE, lhstyp)) errind = FALSE;
+      /* notice, setting lhs st for all components and also top */
+      /* if has stren know will be wire */
+      if (ndp2->lu.x->x_stren) { ndp2->x_stren = TRUE; has_stren = TRUE; }
+      if (ndp2->lu.x->is_real)
+       {
+        __sgferr(900,
+         "real variable illegal in lvalue concatenate (pos. %d)", i);
+       }
+     }
+    if (has_stren) ndp->x_stren = TRUE;
+    return(errind);
+   }
+  case CATREP:
+   __sgferr(856, "lvalue concatenate repeat form illegal");
+   break;
+  /* if empty form already checked to have appeared in legal place */
+  case OPEMPTY: return(TRUE);
+  case NUMBER:
+    /* number is wrong so needs to fall through */
+  default:
+   __sgferr(857, "expression %s is illegal lvalue element",
+    __msgexpr_tostr(__xs, ndp));
+ }
+ return(FALSE);
+}
+
+/*
+ * check and unwind lhs concatenates
+ *
+ * repeat form concats and numbers illegal on lhs
+ * when done concatenate is one level and checked
+ *
+ * notice this will unwind concatenates in fcall arguments
+ */
+static void unwind_lhsconcats(struct expr_t *ndp)
+{
+ if (__isleaf(ndp)) return;
+
+ /* DBG ---
+ if (__debug_flg)
+  __dbg_msg("## unwinding lhs concat %s\n", __msgexpr_tostr(__xs, ndp));
+ --- */
+
+ /* concatenate unwinding must be done bottom up */
+ if (ndp->lu.x != NULL)
+  {
+   /* DBG ---
+   if (__debug_flg)
+   __dbg_msg("## left side %s\n", __msgexpr_tostr(__xs, ndp->lu.x));
+   --- */ 
+   unwind_lhsconcats(ndp->lu.x);
+   /* DBG ---
+   if (__debug_flg) __dbg_msg("^^ left up.\n");
+   --- */
+  }
+ if (ndp->ru.x != NULL)
+  {
+   /* DBG ---
+   if (__debug_flg)
+   __dbg_msg("## right side %s\n", __msgexpr_tostr(__xs, ndp->ru.x));
+   --- */
+   unwind_lhsconcats(ndp->ru.x);
+   /* DBG ---
+   if (__debug_flg) __dbg_msg("^^ right up.\n");
+   --- */ 
+  }
+
+ /* node is top of concatenate with all sub concatenates simplified */
+ if (ndp->optyp == LCB)
+  {
+   register struct expr_t *ndp2;
+   struct expr_t *last_ndp2, *end_ndp;
+
+   last_ndp2 = ndp;
+   for (ndp2 = ndp->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+    {
+     struct expr_t *lop;
+
+     lop = ndp2->lu.x;
+     /* notice ,, form illegal in concatentate */
+     switch ((byte) lop->optyp) {
+      /* constants illegal but caught later */
+      case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM:
+       break;
+      case LCB:
+       {
+        /* nested concatenate - splice up one level */
+        last_ndp2->ru.x = lop->ru.x;
+        /* find rightmost element - know always there */
+        end_ndp = __find_catend(lop);
+
+        /* DBG LINT remove -- */
+        if (end_ndp == NULL) __misc_terr(__FILE__, __LINE__);
+        /* -- */
+
+        /* if rightmost up one node will make null */
+        end_ndp->ru.x = ndp2->ru.x;
+        /* end of new chain is new last */
+        last_ndp2 = end_ndp;
+       }
+       continue;
+      case CATREP:
+       /* error caught later */
+       continue;
+      }
+     /* NUMBER or other means move last down tree one */
+     last_ndp2 = ndp2;
+    }
+  }
+}
+
+/*
+ * check a declarative lhs bit or part select to make sure scalared
+ *
+ * notice wire name on conta lhs does not require scalared vector
+ * unless bit or part select
+ *
+ * if this is a reg (error caught later) surpress this error
+ */
+extern int32 __chk_lhsdecl_scalared(struct expr_t *idndp)
+{
+ struct net_t *np;
+
+ np = idndp->lu.sy->el.enp;
+ if (np->ntyp >= NONWIRE_ST) return(TRUE);
+
+ /* if no autoexpand, must explicitly declare as scalared or error */
+ /* if autoexpand (the default),  error if explicitly declared vectored */ 
+ /* check only possible for non interact - should never happen in interact */
+ if (np->nrngrep == NX_CT)
+  {
+   if ((__no_expand && np->nu.ct->n_spltstate != SPLT_SCAL)
+    || np->nu.ct->n_spltstate == SPLT_VECT)
+    {
+     __sgferr(860, "vectored %s %s illegal in declarative lvalue",
+      __to_wtnam(__xs, np), __to_idnam(idndp));
+     return(FALSE);
+   }
+  }
+ return(TRUE);
+}
+
+/*
+ * return T if is a variable - i.e. any SYM_N that is not a parameter
+ * know object is an id
+ */
+static int32 idnd_var(struct sy_t *syp)
+{
+ struct net_t *np;
+
+ if (syp->sytyp != SYM_N) return(FALSE);
+ np = syp->el.enp;
+ if (!np->n_isaparam) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * for declarative code, lhs must be a wire
+ * this catches declarative lhs reals
+ * needs __sfnam_ind to be set before called
+ */
+extern int32 __nd_wire(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ np = ndp->lu.sy->el.enp;
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   __sgferr(861, "declarative lvalue or port sink %s %s must be a wire",
+    __to_wtnam(__xs, np), __to_idnam(ndp));
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * return T if expression contains any register
+ *
+ * needed for force/release since if has reg, must be quasi-continuous assign
+ * reg form else normal lhs
+ * notice this must handle un converted globals since chk expressions
+ * routine that replaces the global not yet called at this point
+ */
+extern int32 __xhas_reg(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ switch ((byte) ndp->optyp) {
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   break;
+  case ID: case GLBREF:
+   np = ndp->lu.sy->el.enp;
+   if (np->ntyp >= NONWIRE_ST) return(TRUE);
+   break;
+  default:
+   if (ndp->lu.x != NULL) if (__xhas_reg(ndp->lu.x)) return(TRUE);
+   if (ndp->ru.x != NULL) if (__xhas_reg(ndp->ru.x)) return(TRUE);
+   break;
+ }
+ return(FALSE);
+}
+
+/*
+ * for procedural code, lhs must be a reg
+ * know node is an id
+ * needs __sfnam_ind to be set before called
+ */
+static int32 nd_reg(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ np = ndp->lu.sy->el.enp;
+ if (np->ntyp < NONWIRE_ST || np->ntyp == N_EVENT)
+  {
+   __sgferr(862, "procedural lvalue %s %s is not a reg",
+    __to_wtnam(__xs, np), __to_idnam(ndp));
+   return(FALSE);
+  }
+ if (np->n_isaparam)
+  {
+   __sgferr(863,
+    "defparam %s use as register variable not supported", __to_idnam(ndp));
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * compute the lhs width
+ * know called in only 1 place after global substituted
+ */
+extern void __set_lhswidth(struct expr_t *lhsx)
+{
+ int32 r1, r2, xwid;
+ struct net_t *np;
+ struct sy_t *syp;
+
+ switch ((byte) lhsx->optyp) {
+  case ID: case GLBREF:
+   lhsx->szu.xclen = __get_netwide(lhsx->lu.sy->el.enp);
+   break;
+  /* width of empty is 0 that matches anything */
+  case OPEMPTY: break;
+  case LSB:
+   syp = lhsx->lu.x->lu.sy;
+   lhsx->lu.x->szu.xclen = __get_netwide(syp->el.enp);
+   /* this is bit select or array index */
+   np = syp->el.enp;
+   if (np->n_isarr && np->n_isavec) xwid = __get_netwide(np); else xwid = 1;
+   lhsx->szu.xclen = xwid;
+   break;
+  case PARTSEL:
+   syp = lhsx->lu.x->lu.sy;
+   lhsx->lu.x->szu.xclen = __get_netwide(syp->el.enp);
+   np = syp->el.enp;
+   /* know these values always fit in 32 bits and never IS form */
+   r1 = (int32) __contab[lhsx->ru.x->lu.x->ru.xvi];
+   r2 = (int32) __contab[lhsx->ru.x->ru.x->ru.xvi];
+   lhsx->szu.xclen = (r1 > r2) ? r1 - r2 + 1 : r2 - r1 + 1;
+   break;
+  case LCB:
+   {
+    register struct expr_t *ndp2;
+
+    /* know lhs concatenates never nested */
+    for (xwid = 0, ndp2 = lhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     {
+      __set_lhswidth(ndp2->lu.x);
+      xwid += ndp2->lu.x->szu.xclen;
+     }
+    lhsx->szu.xclen = xwid;
+    /* CAT COM op width is dist from high bit of this to low (right) end */
+    for (ndp2 = lhsx->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+     {
+      ndp2->szu.xclen = xwid;
+      xwid -= ndp2->lu.x->szu.xclen;
+     }
+    if (xwid != 0) __misc_terr(__FILE__, __LINE__);
+    break;
+   }
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * check an event expression
+ * real numbers not allowed in event expressions
+ */
+extern void __chk_evxpr(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ switch ((byte) ndp->optyp) {
+  /* any simple ID good - event versus variable change known from var type */
+  case ID: case GLBREF:
+   np = ndp->lu.sy->el.enp;
+   if (np->ntyp == N_EVENT)
+    {
+     ndp->szu.xclen = 1;
+     if (np->nrngrep == NX_CT) np->nu.ct->n_onrhs = TRUE;
+     break;
+    }
+   /* any wire used in an event control is accessed as on rhs */
+   if (np->nrngrep == NX_CT) np->nu.ct->n_onrhs = TRUE;
+   goto chk_expr;
+  case OPEVOR: case OPEVCOMMAOR:
+   __chk_evxpr(ndp->lu.x);
+   __chk_evxpr(ndp->ru.x);
+   break;
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM:
+   /* SJM 05/22/00 - per XL, real ev exprs (non edge) legal - just chg op */
+is_num:
+    __sgfwarn(551, "event expression constant - event cannot occur"); 
+   break;
+  case OPPOSEDGE: case OPNEGEDGE:
+   chk_edge_expr(ndp); 
+   break;
+  default: 
+   /* change of any rhs expressions */
+chk_expr:
+   __chk_rhsexpr(ndp, 0);
+   if (ndp->optyp == NUMBER) goto is_num;
+   /* SJM 05/22/00 - per XL, real ev exprs (non edge) legal - just chg op */
+   if (xpr_hasfcall(ndp))
+    __sgfinform(414, "event expression %s has function call that can have side effects",
+     __msgexpr_tostr(__xs, ndp));
+ }
+}
+
+/*
+ * return T if expression has a function call
+ */
+static int32 xpr_hasfcall(struct expr_t *ndp)
+{
+ if (ndp->optyp == FCALL) return(TRUE);
+ if (__isleaf(ndp)) return(FALSE);
+ if (ndp->lu.x != NULL) { if (xpr_hasfcall(ndp->lu.x)) return(TRUE); }
+ if (ndp->ru.x != NULL) { if (xpr_hasfcall(ndp->ru.x)) return(TRUE); }
+ return(FALSE);
+}
+
+/*
+ * return T if expression has a user function call
+ * built-in $ starting system functions legal
+ *
+ */
+static int32 xpr_has_nonsys_fcall(struct expr_t *ndp)
+{
+ int32 anum;
+ struct sy_t *syp; 
+ struct sysfunc_t *syfp;
+
+ if (ndp->optyp == FCALL)
+  {
+   syp = ndp->lu.x->lu.sy;
+   if (syp->sytyp != SYM_SF) return(TRUE);
+
+   syfp = syp->el.esyftbp;
+   if (syfp->tftyp != SYSF_BUILTIN) return(TRUE);
+   anum = __cnt_tfargs(ndp->ru.x);
+
+   /* SJM 09/04/01 - must check arg num here since can't fold - also */
+   /* exec assumes right no. of args without check */
+   /* only some built-in system functions allowed in const exprs */
+   switch (syfp->syfnum) {
+    case STN_ITOR: case STN_BITSTOREAL: case STN_RTOI: case STN_REALTOBITS:
+    case STN_SIGNED: case STN_UNSIGNED:
+    case STN_COS: case STN_SIN: case STN_TAN: case STN_ACOS: case STN_ASIN:
+    case STN_ATAN: case STN_COSH: case STN_SINH: case STN_TANH:
+    case STN_ATANH: case STN_ACOSH: case STN_ASINH:
+    case STN_INT: case STN_SGN:
+    case STN_LN: case STN_LOG10: case STN_ABS: case STN_SQRT: case STN_EXP:
+    case STN_HSQRT: case STN_HLOG: case STN_HLOG10:
+     if (anum != 1) { sf_errifn(syp, 1); return(TRUE); }
+     break;
+
+    case STN_POW: case STN_MIN: case STN_MAX:
+    /* hspice special too */
+    case STN_HPOW: case STN_HPWR: case STN_HSIGN: case STN_HDB:
+    case STN_HYPOT: case STN_ATAN2:
+     if (anum != 2) { sf_errifn(syp, 2); return(TRUE); }
+     break;
+    default:
+     /* illegal built-in system function in constant expression */ 
+     return(TRUE);
+   }
+   /* fall thru - because must check args */
+  }
+ if (__isleaf(ndp)) return(FALSE);
+
+ if (ndp->lu.x != NULL) { if (xpr_has_nonsys_fcall(ndp->lu.x)) return(TRUE); }
+ if (ndp->ru.x != NULL) { if (xpr_has_nonsys_fcall(ndp->ru.x)) return(TRUE); }
+ return(FALSE);
+}
+
+/*
+ * any expression legal here but warning if wider than 1 bit (use low bit)
+ * LRM requires using low bit for any wider than 1 bit
+ *
+ * allowing any expression including array index - have separate expr
+ * old value and eval to filter for anything but scalared variable and
+ * constant bit select of scalared
+ */
+static void chk_edge_expr(struct expr_t *endp)
+{
+ struct expr_t *ndp;
+
+ ndp = endp->lu.x;
+ /* this will catch any event variable */
+ __chk_rhsexpr(ndp, 0);
+ /* SJM 05/22/00 - real edge expressions still illegal */
+ if (ndp->is_real)
+  {
+   __sgferr(864, "edge event control expression %s cannot be real",
+    __msgexpr_tostr(__xs, endp));
+   return;
+  }
+ if (ndp->szu.xclen != 1)
+  {
+   __sgfwarn(677,
+    "edge control %s expression width %d wider than 1 bit - low bit used",
+    __msgexpr_tostr(__xs, endp), ndp->szu.xclen);
+  }
+}
+
+/*
+ * PASS 2 (AFTER ALL SOURCE READ) FUNCTION AND TASK CHECKING ROUTINES
+ */
+
+/*
+ * check a task enable statement
+ */
+extern void __chk_tskenable(struct st_t *stp)
+{
+ register struct expr_t *xp;
+ register struct task_pin_t *tpp;
+ int32 pwid, pi;
+ struct task_t *tskp;
+ struct sy_t *syp;
+ struct expr_t *tkxp;
+ struct tskcall_t *tkcp;
+
+ tkcp = &(stp->st.stkc);
+ /* cannot check number of widths (assuming 0 context of system tasks) */
+ tkxp = tkcp->tsksyx;
+ if (tkxp->optyp == ID && *(tkxp->lu.sy->synam) == '$')
+  {
+   /* system task args do not have type or width - take what is there */
+   chk_systskenable(stp, tkcp);
+   return;
+  }
+
+ /* task call symbol missing or not declared as task */
+ if (tkxp == NULL || (tkxp->optyp != GLBREF && tkxp->optyp != ID)
+  || (syp = tkxp->lu.sy) == NULL) __misc_sgfterr(__FILE__, __LINE__);
+
+ /* if error will be left as global ID */
+ syp = tkcp->tsksyx->lu.sy;
+ tskp = syp->el.etskp;
+ tpp = tskp->tskpins;
+ pi = 1;
+ for (xp = tkcp->targs; xp != NULL; xp = xp->ru.x, tpp = tpp->tpnxt, pi++)
+  {
+   if (tpp == NULL)
+    {
+     __sgferr(871, "task %s enable has more arguments (%d) than declaration",
+      __to_idnam(tkcp->tsksyx), pi);
+     return;
+    }
+   /* decl. argumen cannot be global - declared symbol */
+   pwid = __get_netwide(tpp->tpsy->el.enp);
+   /* but expression is normal either right or left sides */
+   if (tpp->trtyp == IO_IN)
+    {
+     __chk_rhsexpr(xp->lu.x, pwid);
+
+     /* SJM 10/08/04 - for Ver 2001 because WBITS can be 64 - must widen */
+     /* unsized constant (unsiznum bit in expr rec on) to lhs width */
+     if (xp->lu.x->optyp == NUMBER && xp->lu.x->unsiznum
+      && xp->lu.x->szu.xclen < pwid)
+      {
+       xp->lu.x = __widen_unsiz_rhs_assign(xp->lu.x, pwid);
+      }
+    }
+   else
+    {
+     __chk_lhsexpr(xp->lu.x, LHS_PROC);
+     if (tpp->trtyp == IO_BID) __set_expr_onrhs(xp->lu.x);
+    }
+   /* no inform for bit width changes (they are common) */
+   /* but inform for arg. real and value non real or opposite */
+   if (tpp->tpsy->el.enp->ntyp == N_REAL && !(xp->lu.x->is_real))
+    {
+     __sgfinform(485,
+      "task %s argument pos. %d declared real - non real expression %s converted",
+      __to_idnam(tkcp->tsksyx), pi,  __msgexpr_tostr(__xs, xp->lu.x));
+    }
+   else if (tpp->tpsy->el.enp->ntyp != N_REAL && xp->lu.x->is_real)
+    {
+     __sgfinform(485,
+      "task %s argument pos. %d declared non real - real expression %s converted",
+      __to_idnam(tkcp->tsksyx), pi,  __msgexpr_tostr(__xs, xp->lu.x));
+    }
+  }
+ if (tpp != NULL)
+  __sgferr(872, "task %s enable has fewer arguments than declaration",
+   __to_idnam(tkcp->tsksyx));
+ tskp->t_used = TRUE;
+}
+
+/*
+ * check a system task enable
+ *
+ * notice there is no task structure and symbol in special symbol table
+ * any number with any type argument list just passed on
+ */
+static void chk_systskenable(struct st_t *stp, struct tskcall_t *tkcp)
+{
+ register struct expr_t *xp;
+ int32 anum, special_syntax, is_disp_typ, is_monit_typ, nbytes, ii;
+ struct sy_t *syp;
+ struct expr_t *tkxp, *sav_xp;
+ struct systsk_t *stbp;
+ struct expr_t *ndp;
+ struct sy_t *tsyp;
+ byte *monit_argtyps;
+
+ tkxp = tkcp->tsksyx;
+ syp = tkxp->lu.sy;
+ stbp = syp->el.esytbp;
+
+ /* system task number inconsistent */
+ if (stbp->stsknum == 0) __misc_sgfterr(__FILE__, __LINE__);
+
+ special_syntax = FALSE;
+ /* notice for system tasks no special first arg. return type */
+ /* assume start checking expressions with 1st arg. */
+ xp = tkcp->targs;
+ anum = __cnt_tfargs(tkcp->targs);
+ is_disp_typ = FALSE;
+ is_monit_typ = FALSE;
+ if (anum == 1 && xp->lu.x->optyp == OPEMPTY)
+  {
+   __sgfwarn(633,
+    "system task enable: %s(); has one empty argument - for no arguments omit the ()",
+    syp->synam);
+  }
+
+ /* dumpvars is special case because xmr's may not resolve to wire */
+ /* if pli system task supercedes normal, will never see its task number */ 
+ switch (stbp->stsknum) {
+  case STN_FFLUSH:
+   /* $fflush([optional op]) - op can be missing, then all, [mcd] or [fd] */
+   if (anum != 0 && anum !=1)
+    {
+     __sgferr(851,
+      "%s system task illegal number of arguments (%d) - 0 or 1 legal",
+      syp->synam, anum);
+    } 
+   break;
+  case STN_SWRITE: case STN_SWRITEB: case STN_SWRITEH: case STN_SWRITEO:
+   is_disp_typ = TRUE;
+   if (anum < 2)
+    {
+     __sgferr(882,
+      "%s system task required output reg and one argument missing",
+      syp->synam);
+     return;
+    }
+   ndp = xp->lu.x;
+   /* SJM 05/17/04 - LOOKATME this can be any width string - why 32? */
+   __chk_lhsexpr(ndp, 32);
+   /* move to 2nd argument */
+   xp = xp->ru.x;
+   break;
+  case STN_SFORMAT:
+   is_disp_typ = TRUE;
+   if (anum < 2)
+    {
+     __sgferr(882,
+      "%s system task required output reg and format argument(s) missing",
+      syp->synam);
+     special_syntax = TRUE;
+     break;
+    }
+   ndp = xp->lu.x;
+   /* width self determined for lhs string written into */
+   __chk_lhsexpr(ndp, 0);
+   /* move to 2nd format argument */
+   xp = xp->ru.x;
+   /* again width self determined */
+   __chk_rhsexpr(xp->lu.x, 0);
+
+   /* if format arg is literal string - can check format */
+   if (xp->lu.x->is_string) is_disp_typ = TRUE;
+   else special_syntax = TRUE;
+
+   xp = xp->ru.x;
+   /* if variable fmt, can only check the rhs fmt args */ 
+   if (special_syntax)
+    {
+     for (sav_xp = xp; xp != NULL; xp = xp->ru.x)
+      {
+       __chk_rhsexpr(xp->lu.x, 0);
+      }
+    }
+   break;
+  /* task requires special argument processing */
+  case STN_DUMPVARS:
+   chkst_dumpvars_enable(tkcp, anum);
+
+   /* SJM 01/27/03 - error if compiled sim and try to call dumpvars */
+   /* from interactive mode because need source preprocessing */ 
+   if (__iact_state && __optimized_sim)
+    {
+     __sgferr(876, 
+      "%s system task call from interactive debugger illegal - move to module ssource or run without -O",
+      syp->synam);
+     /* error will inhibit interactive execution but need rest of checking */
+    }
+   special_syntax = TRUE;
+   break;
+  case STN_READMEMB: case STN_READMEMH:
+   chkst_readmem(syp, anum, tkcp);
+   special_syntax = TRUE;
+   break;
+  case STN_SREADMEMB: case STN_SREADMEMH:
+   chkst_sreadmem(syp, anum, tkcp);
+   special_syntax = TRUE;
+   break;
+  case STN_TIMEFORMAT:
+   /* set how %t displayed and sets interactive time unit interpretation */
+   /* (units, precision, suffix, minimum width) */
+   if (anum < 1 || anum > 4) st_errif_rng(syp, 1, 4, anum);
+   if (!__des_has_timescales)
+    {
+     __sgfwarn(626,
+      "%s system task ignored - design does not use timescales", syp->synam);
+    }
+   /* args are just string or numeric expressions - from interp. in Ver */
+   break;
+  case STN_PRINTTIMESCALE:
+   /* this takes hierarchical xmr as name */
+   if (anum > 1) st_errif_rng(syp, 0, 1, anum);
+   /* 0 args - means use $scope() set module */
+   if (anum == 1)
+    {
+     /* notice must not check as rhs expr since requires variables */
+     ndp = xp->lu.x;
+     /* this must always be xmr - already resolved */ 
+     if (ndp->optyp != GLBREF || (ndp->lu.sy->sytyp != SYM_I
+      && ndp->lu.sy->sytyp != SYM_M))
+      {
+       __sgferr(876, 
+        "%s system task argument %s is not required module instance reference",
+        syp->synam, __msgexpr_tostr(__xs, ndp));
+      }
+     special_syntax = TRUE;
+    }
+   break;
+  case STN_SCOPE:
+   /* list can have 0 arguments but scope must have exactly one */  
+   if (anum != 1) { st_errifn(syp, 1, anum); break; } 
+   goto args_ok;
+  case STN_LIST:
+   /* this takes hierarchical xmr as name */
+   if (anum > 1) st_errif_rng(syp, 0, 1, anum);
+   /* no argument means use current scope for list */
+   if (anum == 0) break;
+args_ok:
+   ndp = xp->lu.x;
+   /* any 1 component scope reference will still be global here */
+   if (ndp->optyp != GLBREF)
+    {
+     if (ndp->optyp != ID) goto bad_scope;
+     tsyp = ndp->lu.sy;
+     /* local task/func/lb scope is legal - will not be seen as global */
+     if (tsyp->sytyp == SYM_F || tsyp->sytyp == SYM_LB
+     || tsyp->sytyp == SYM_TSK) { special_syntax = TRUE; break; }
+     goto bad_scope;
+    }
+   else tsyp = ndp->lu.sy;
+   /* know this is global - maybe 1 component */
+   /* need error if try to $scope into udp or built in primitive */
+   if (tsyp->sytyp == SYM_UDP || tsyp->sytyp == SYM_PRIM)
+    {
+     __sgferr(880, "%s system task argument %s %s illegal", syp->synam,
+      __to_sytyp(__xs, syp->sytyp), syp->synam);
+     special_syntax = TRUE;
+     break;
+    }
+   /* only scope required here */
+   if (!__is_scope_sym(tsyp))
+    {
+bad_scope:
+     __sgferr(881,
+      "%s system task argument %s is not required scope identifier",
+      syp->synam, __msgexpr_tostr(__xs, ndp));
+     }
+   special_syntax = TRUE;
+   break;
+  case STN_SHOWVARIABLES:
+   /* for now just treating same as showvars - ignoring control argument */
+   if (anum < 1)
+    {
+     __sgferr(883, "%s system task required first control argument missing",
+      syp->synam);
+     break;
+    }
+   /* move to 2nd argument */
+   xp = xp->ru.x;
+   /*FALLTHRU */
+  case STN_SHOWVARS:
+   /* any number of args ok - but can be var,glb,bsel or psel only */ 
+   for (; xp != NULL; xp = xp->ru.x)
+    {
+     ndp = xp->lu.x;
+     __chk_rhsexpr(ndp, 0);
+     switch ((byte) ndp->optyp) {
+      case ID: case GLBREF: case LSB: case PARTSEL: break;
+      default:
+       __sgferr(917,
+        "%s system task argument %s: variable, global or select required",
+        syp->synam, __msgexpr_tostr(__xs, ndp));
+     }
+    }
+   special_syntax = TRUE;
+   break;
+  /* tasks that cannot have any arguments */
+  case STN_MONITORON: case STN_MONITOROFF: case STN_DUMPON: case STN_DUMPOFF:
+  case STN_DUMPALL: case STN_DUMPFLUSH:
+  case STN_NOKEY: case STN_NOLOG: case STN_CLEARTRACE:
+  case STN_SHOWALLINSTANCES: case STN_SETTRACE: case STN_SHOWEXPANDEDNETS:
+  case STN_HISTORY: case STN_MEMUSE: case STN_FLUSHLOG:
+  case STN_SETEVTRACE: case STN_CLEAREVTRACE:
+  case STN_SETDEBUG: case STN_CLEARDEBUG:
+  case STN_RESET:
+   if (anum > 3) st_errif_rng(syp, 0, 3, anum);
+   /* any arguments just evaluated for 32 bit values - sign bit may have */
+   /* significance */ 
+   break;
+
+  /* tasks that can have 0 or 1 arguments */
+  /* notice these can appear in source - since just change files */
+  case STN_KEY: case STN_LOG: case STN_INPUT:
+  case STN_FINISH: case STN_STOP: case STN_SHOWSCOPES:
+  case STN_SNAPSHOT: case STN_TRACEFILE: case STN_SYSTEM:
+  case STN_DUMPFILE:
+   if (anum > 1) st_errif_rng(syp, 0, 1, anum);
+   break;
+  /* tasks that require exactly 1 expr. type arg. (file name?) */
+  case STN_DUMPLIMIT: case STN_SAVE: case STN_RESTART: case STN_INCSAVE:
+  case STN_FCLOSE:
+   if (anum != 1) st_errifn(syp, 1, anum);
+   break;
+  /* tasks that take a multichannel descriptor followed by anything */
+  case STN_FMONITOR: case STN_FMONITORB: case STN_FMONITORH:
+  case STN_FMONITORO:
+   is_monit_typ = TRUE;
+   /*FALLTHRU*/ 
+  case STN_FDISPLAY: case STN_FDISPLAYB: case STN_FDISPLAYH:
+  case STN_FDISPLAYO:
+  case STN_FWRITE: case STN_FWRITEB: case STN_FWRITEH: case STN_FWRITEO:
+  case STN_FSTROBE: case STN_FSTROBEB: case STN_FSTROBEH: case STN_FSTROBEO:
+   is_disp_typ = TRUE;
+   if (anum < 1)
+    {
+     __sgferr(882,
+      "%s system task required file descriptor or MCD first argument missing",
+      syp->synam);
+     return;
+    }
+   ndp = xp->lu.x;
+   __chk_rhsexpr(ndp, 32);
+   if (ndp->szu.xclen != 32)
+    {
+     __sgfwarn(612,
+      "file descriptor or MCD first argument has size %d should be 32",
+      ndp->szu.xclen);
+    }
+   /* move to 2nd argument */
+   xp = xp->ru.x;
+   break;
+  /* tasks that take any number of numeric arguments - checked later */
+  case STN_SUPWARNS:
+  case STN_ALLOWWARNS:
+   /* could check constant arguments here */
+   break;
+  /* task that take any number of unchecked arguments */
+  case STN_MONITOR: case STN_MONITORB: case STN_MONITORH: case STN_MONITORO:
+   is_monit_typ = TRUE;
+   /*FALLTHRU*/ 
+  case STN_DISPLAY: case STN_DISPLAYB: case STN_DISPLAYH: case STN_DISPLAYO:
+  case STN_WRITE: case STN_WRITEB: case STN_WRITEH: case STN_WRITEO:
+  case STN_STROBE: case STN_STROBEB: case STN_STROBEH: case STN_STROBEO:
+   is_disp_typ = TRUE;
+   break;
+  /* any number of reg/wire variables */
+  /* all have four required arguments, last inout */
+  case STN_Q_ADD:
+  case STN_Q_INITIALIZE:
+   /* LOOKATME - LRM says 4th arg. is required - but now old Gateway doc. */
+   /* but maybe operator empty is arg (i.e. , required? */
+   if (anum != 4) st_errifn(syp, 4, anum);
+   /* first arg. is input int32 identifying the Q */
+   if (anum >= 1) __chk_rhsexpr(xp->lu.x, 0);
+   /* 2nd arg. is q_type for initialize and job_id (user num.) for add */
+   if (anum >= 2) { xp = xp->ru.x; __chk_rhsexpr(xp->lu.x, 0); }
+   /* 3rd arg is max q len for initialize and 2nd user num for add */
+   if (anum >= 3) { xp = xp->ru.x; __chk_rhsexpr(xp->lu.x, 0); }
+   /* 4th arg is output operation status value */
+   if (anum >= 4) { xp = xp->ru.x; __chk_lhsexpr(xp->lu.x, LHS_PROC); }
+   special_syntax = TRUE;
+   break;
+  case STN_Q_REMOVE:
+   if (anum != 4) st_errifn(syp, 4, anum);
+   /* first arg. is input int32 identifying the Q */
+   if (anum >= 1) __chk_rhsexpr(xp->lu.x, 0);
+   /* 2nd arg. is output job_id (user num. put in by add call) */
+   if (anum >= 2) { xp = xp->ru.x; __chk_lhsexpr(xp->lu.x, LHS_PROC); }
+   /* 3rd arg. is output inform_id (2nd user num. put in by add call) */
+   if (anum >= 3) { xp = xp->ru.x; __chk_lhsexpr(xp->lu.x, LHS_PROC); }
+   /* 4th arg is output operation status (completion value) value */
+   if (anum >= 4) { xp = xp->ru.x; __chk_lhsexpr(xp->lu.x, LHS_PROC); }
+   special_syntax = TRUE;
+   break;
+  case STN_Q_EXAM:
+   if (anum != 4) st_errifn(syp, 4, anum);
+   /* first arg. is input int32 identifying the Q */
+   if (anum >= 1) __chk_rhsexpr(xp->lu.x, 0);
+   /* 2nd arg. is input q_stat_code that selects information to return */
+   if (anum >= 2) { xp = xp->ru.x; __chk_rhsexpr(xp->lu.x, 0); }
+   /* 3rd arg. is output status value */
+   if (anum >= 3) { xp = xp->ru.x; __chk_lhsexpr(xp->lu.x, LHS_PROC); }
+   /* 4th arg is output operation status (completion code) value */
+   if (anum >= 4) { xp = xp->ru.x; __chk_lhsexpr(xp->lu.x, LHS_PROC); }
+   special_syntax = TRUE;
+   break;
+  case STN_SDF_ANNOTATE:
+   chkst_sdfannotate_enable(tkcp, anum);
+   special_syntax = TRUE;
+   break;
+
+  case STN_GRREMOTE:
+  case STN_PSWAVES:
+  case STN_GRSYNCHON:
+  case STN_GRREGS:
+  case STN_GRWAVES:
+  case STN_FREEZEWAVES:
+  case STN_DEFINEGROUPWAVES:
+   __sgfwarn(553,
+    "group waves task %s not supported- executed as null statement",
+    syp->synam);
+   return; 
+
+  default:
+   /* check pli tf user task enable and build tf rec */
+   if (stbp->stsknum >= BASE_VERIUSERTFS
+    && (int32) stbp->stsknum <= __last_systf)
+    {
+     /* tf_ checktf called during prep after aux record built */
+     /* for both tf_ and vpi_ systf */
+     chkbld_pli_task(stp, (int32) stbp->stsknum);
+     return;
+    }
+ }
+ if (special_syntax) return;
+
+ /* fall through to normal anything legal - notice 0 (none) expr. context */
+ for (sav_xp = xp; xp != NULL; xp = xp->ru.x)
+  {
+   ndp = xp->lu.x;
+   __chk_rhsexpr(ndp, 0);
+   /* if special syntax called if needed in that routine */
+   /* width in bytes where bit sizes rounded up to next word32 */
+   /* SJM 07/24/00 - no nu.ct when elaborated from iact state */
+   if (is_monit_typ && !__iact_state)
+    {
+     mark_monit_in_src_nets(ndp);
+    }
+  }
+ if (is_monit_typ)
+  {
+   /* must allocate 1 byte even if no args */
+   nbytes = (anum != 0) ? anum : 1; 
+   /* monit type implies display type */
+   monit_argtyps = (byte *) __my_malloc(nbytes);
+   memset(monit_argtyps, 0, nbytes);
+   __chk_fmt(sav_xp, monit_argtyps);
+   /* will never get here for PLI task func that shares trec field */ 
+   if (tkcp->tkcaux.mauxp == NULL)
+    {
+     tkcp->tkcaux.mauxp = (struct monaux_t *)
+      __my_malloc(sizeof(struct monaux_t));
+     tkcp->tkcaux.mauxp->dces_blt = FALSE;
+     tkcp->tkcaux.mauxp->argisvtab = NULL;
+     tkcp->tkcaux.mauxp->mon_dcehdr = (struct dceauxlst_t **)
+      __my_malloc(__inst_mod->flatinum*sizeof(struct dceauxlst_t *));
+     for (ii = 0; ii < __inst_mod->flatinum; ii++) 
+      tkcp->tkcaux.mauxp->mon_dcehdr[ii] = NULL;
+    }
+   tkcp->tkcaux.mauxp->argisvtab = monit_argtyps;
+   return;
+  }
+ if (is_disp_typ) __chk_fmt(sav_xp, (byte *) NULL);
+}
+
+/*
+ * for optimizer, mark monit arg nets as having monit in src 
+ *
+ * BEWARE - must not call this during iact elaboration but called
+ * even for interpreter now
+ */
+static void mark_monit_in_src_nets(struct expr_t *xp)
+{
+ struct net_t *np;
+
+ if (__isleaf(xp))
+  {
+   /* SJM 03/22/02 - XMR monits in source must also be marked */
+   if ((xp->optyp == ID || xp->optyp == GLBREF) && xp->lu.sy->sytyp == SYM_N)
+    {
+     np = xp->lu.sy->el.enp; 
+     if (!np->n_isaparam) np->nu.ct->monit_in_src = TRUE;
+    }
+   return;
+  }
+ if (xp->lu.x != NULL) mark_monit_in_src_nets(xp->lu.x);
+ if (xp->ru.x != NULL) mark_monit_in_src_nets(xp->ru.x);
+}
+
+/*
+ * return T if symbol can be scope 
+ */
+extern int32 __is_scope_sym(struct sy_t *syp) 
+{
+ switch ((byte) syp->sytyp) { 
+  case SYM_I: case SYM_M: case SYM_LB: case SYM_TSK: case SYM_F: return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*
+ * check and build vpi_ tf rec for pli task
+ */
+static void chkbld_pli_task(struct st_t *stp, int32 tfnum)
+{
+ int32 anum;
+ struct tskcall_t *tkcp;
+ struct tfrec_t *tfrp;
+
+ tkcp = &(stp->st.stkc);
+ /* this sets tf_rw flags for args */
+ if (tkcp->targs != NULL)
+  { chk_pli_arglist(tkcp->targs, tfnum); anum = __cnt_tfargs(tkcp->targs); }
+ else anum = 0;
+
+ /* need separate routine for vpi_ systfs compiletf and checking */ 
+ if (tfnum > __last_veriusertf)
+  {
+   __chkbld_vpi_systf_task(stp);
+   return;
+  }
+
+ /* allocate the tf rec and link on to func. name expr unused len fld */
+ tfrp = chkalloc_tfrec(tkcp->targs, anum);
+ tfrp->tf_func = FALSE;
+ /* link together both directions */
+ tfrp->tfu.tfstp = stp;
+ tkcp->tkcaux.trec = tfrp;
+
+ if (__tfrec_hdr == NULL) __tfrec_hdr = __tfrec_end = tfrp;
+ else { __tfrec_end->tfrnxt = tfrp; __tfrec_end = tfrp; }
+}
+
+/*
+ * system task number of arguments outside of legal range error
+ */
+static void st_errif_rng(struct sy_t *syp, int32 expl, int32 exph, int32 anum)
+{
+ __sgferr(884, "%s system task must have from %d to %d arguments - has %d",
+  syp->synam, expl, exph, anum);
+}
+
+/*
+ * system task number of arguments not required number
+ */
+static void st_errifn(struct sy_t *syp, int32 expn, int32 anum)
+{
+ if (expn == 0)
+  __sgferr(885, "%s system task cannot have any arguments - has %d",
+   syp->synam, anum);
+ else __sgferr(886, "%s system task %d argument(s) required - has %d",
+  syp->synam, expn, anum);
+}
+
+/*
+ * check the $dumpvars system task enable - needs special processing
+ * 1st arg. if present must be num. rhs expr. and rest must be vars.
+ * does the following:
+ *  1. make sure 1st expr. evaluates to rhs value
+ *  2. must be simple scope or wire 
+ * case of wire and top mod. conflicts handled in global substitution  
+ *
+ * SJM 07/15/00 - now 3. mark all all mod and one net dumpvars in src
+ */
+static void chkst_dumpvars_enable(struct tskcall_t *tkcp, int32 anum)
+{
+ register struct expr_t *alxp;
+ int32 levels;
+ word32 *wp;
+ double *dp;
+ struct expr_t *dpthndp, *xp;
+ struct gref_t *grp;
+ struct net_t *np;
+ struct sy_t *syp;
+ struct mod_t *mdp;
+
+ alxp = tkcp->targs;
+ /* special case of dump all variables in design */
+ if (anum == 0)
+  {
+   /* SJM 07/15/00 - dumpvars with no args is dumpv all in src */
+   __dv_allform_insrc = TRUE;
+   /* must adjust so all net stores use chg form to trigger dumpvaring */
+   if (__iact_state) set_iact_dmpv_all_nd_nchgstore();
+   return;
+  }
+
+ dpthndp = alxp->lu.x;
+ __chk_rhsexpr(dpthndp, 0);
+ if (dpthndp->optyp == OPEMPTY)
+  __sgferr(918, "$dumpvars first argument () or (, empty form illegal");
+
+ /* SJM 08/08/03 - was not handling first level argument right */
+ /* also must be constant expression or can't mark underneath levels */
+ /* argument list form, know first is level */
+ /* must be number by here since will be folded if possible */ 
+
+ /* NOTICE - works for -O vm gen even for non numeric expr since */
+ /* just causes dmpv change forms to be emitted for all under */
+ if (dpthndp->optyp == NUMBER)
+  {
+   wp = &(__contab[dpthndp->ru.xvi]);
+   if (!vval_is0_(wp, dpthndp->szu.xclen)) goto non_const_expr;
+   levels = (int32) wp[0];
+  }
+ else if (dpthndp->optyp == REALNUM)
+  {
+   dp = (double *) __contab[dpthndp->ru.xvi];
+   levels = (int32) *dp;
+   if (levels < 0.0) goto non_const_expr;
+  }
+ else
+  {
+non_const_expr:
+   /* if non constant expr set levels to 0 and do all underneath */
+   levels = 0;
+  }
+
+ for (alxp = alxp->ru.x; alxp != NULL; alxp = alxp->ru.x)
+  {
+   /* case 1 - identifier - must be wire */
+   xp = alxp->lu.x;
+   switch ((byte) xp->optyp) {
+    case ID:
+     np = xp->lu.sy->el.enp;
+     if (np->n_isarr)
+      {
+is_arr:
+       __sgfwarn(541,
+        "$dumpvars argument variable %s cannot be array - ignored",
+        __to_idnam(xp)); 
+       break;
+      }
+     np->nu.ct->dmpv_in_src = TRUE;
+
+     /* SJM 08/08/03 - for dumpvars sys task called from iact code */
+     /* must set nd chg store form because only this net changed */
+     if (__iact_state)
+      {
+       np->dmpv_in_src = TRUE;
+       np->nchg_nd_chgstore = TRUE;
+      }
+     break;
+    case GLBREF:
+     grp = xp->ru.grp;
+     syp = grp->targsyp; 
+     if (syp->sytyp == SYM_N)
+      {
+       np = syp->el.enp;
+       if (np->n_isarr) goto is_arr;
+       np->nu.ct->dmpv_in_src = TRUE;
+
+       /* SJM 08/08/03 - for dumpvars sys task called from iact code */
+       /* must set nd chg store form because only this net changed */
+       if (__iact_state)
+        {
+         np->dmpv_in_src = TRUE;
+         np->nchg_nd_chgstore = TRUE;
+        }
+       break;
+      }
+     /* also cannot be udp or primitive - have no vars */
+     /* here module is for top level modules (inst. name the same here) */
+     if (syp->sytyp != SYM_I && syp->sytyp != SYM_M)
+      {
+       __sgferr(887,
+        "$dumpvars scope form argument %s %s illegal - instance required",
+ __to_sytyp(__xs, syp->sytyp), syp->synam);
+       goto make_op_err;
+      }
+     /* distance under 1 is nothing under and 0 and is all under */
+     /* SJM 08/08/03 - notice must mark wires for all insts of mod */ 
+     /* even though only some under depending on where $dumpvars is */
+     /* called from during sim */
+     if (syp->sytyp == SYM_I) mdp = syp->el.eip->imsym->el.emdp;
+     else mdp = syp->el.emdp;
+
+     if (levels == 1)
+      {
+       if (!mdp->mod_dvars_in_src)
+        {
+         mdp->mod_dvars_in_src = TRUE;
+         /* can't be called from iact if vm compiler on */
+         if (__iact_state) set_iact_dmpvmod_nd_nchgstore(mdp);
+        }
+      } 
+     else mark_mod_dvars_under(mdp, levels);
+     break;
+    case OPEMPTY: 
+     __sgferr(889, "$dumpvars argument cannot be empty (,,) form");
+     goto make_op_err;
+    default:
+     __sgferr(888, "$dumpvars argument %s must be variable or scope path",
+      __msgexpr_tostr(__xs, xp));
+make_op_err:
+     __set_xtab_errval();
+     __bld_xtree(0);
+     alxp->lu.x = __root_ndp;
+   }
+   /* notice by here, if parameter will be substituted to number */
+  }
+}
+
+/*
+ * mark all module instances up to level under as dumpvars
+ * levels of 0 implies all
+ */
+static void mark_mod_dvars_under(struct mod_t *mdp, int32 levels)
+{
+ register int32 ii; 
+ register struct inst_t *down_ip;
+ if (!mdp->mod_dvars_in_src)
+  {
+   mdp->mod_dvars_in_src = TRUE;
+   /* SJM 08/08/03 - must turn on assign chg processing for nets in mod */
+   if (__iact_state) set_iact_dmpvmod_nd_nchgstore(mdp);
+  }
+ if (levels == 1) return; 
+
+ for (ii = 0; ii < mdp->minum; ii++)
+  { 
+   down_ip = &(mdp->minsts[ii]);
+   mark_mod_dvars_under(down_ip->imsym->el.emdp,
+    (levels != 0) ? levels - 1 : 0);
+  }
+}
+  
+
+/*
+ * for all dumpvars from called from interactive need to turn on all
+ * nd chg store bits in all modules or else dumpvars records will not happen
+ *
+ * SJM 08/08/03 - this fixes bug that caused iact dumpvars not to work
+ */
+static void set_iact_dmpv_all_nd_nchgstore(void)
+{
+ register struct mod_t *mdp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   set_iact_dmpvmod_nd_nchgstore(mdp);
+  }
+}
+
+/*
+ * set all nchg need chg store bits if dumpvars called from interactive
+ * with module form
+ *
+ * this is same as nd nchg nchg nd chgstore adjustment when iact dces added
+ * but the nchgaction bits will be set up right when iact dumpv stsk execed
+ *
+ * SJM - 08/08/03 - this is needed to make dumpvars from interactive code work
+ * LOOKATME - maybe should not allow $dumpvars calls from iact mode
+ */
+static void set_iact_dmpvmod_nd_nchgstore(struct mod_t *mdp)
+{
+ register int32 ni;
+ register struct net_t *np;
+ register struct task_t *tskp;
+
+ for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+  {
+   /* can never dumpvar arrays */
+   if (!np->n_isarr)
+    {
+     np->dmpv_in_src = TRUE;
+     np->nchg_nd_chgstore = TRUE;
+    }
+  }
+ for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+   for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+    {
+     if (!np->n_isarr)
+      {
+       np->dmpv_in_src = TRUE;
+       np->nchg_nd_chgstore = TRUE;
+      }
+    }
+  }
+}
+
+/*
+ * check $readmemb or $readmemh arguments
+ */
+static void chkst_readmem(struct sy_t *syp, int32 anum,
+ struct tskcall_t *tkcp)
+{
+ struct expr_t *alxp, *ndp;
+
+ /* allow any expr that evaluates to string (i.e. treated as string) here */
+ if (anum > 4 || anum < 2)
+  {
+   __sgferr(884,
+    "%s system task has %d arguments not from 2 to 4", syp->synam, anum);
+   /* leave since correct number will not be needed */
+   return;
+  }
+ alxp = tkcp->targs;
+ ndp = alxp->lu.x;
+ __chk_rhsexpr(ndp, 0);
+
+ alxp = alxp->ru.x;
+ ndp = alxp->lu.x;
+ if (!nd_unind_arr(ndp))
+  {
+   __sgferr(891,
+    "%s system task second argument %s must be an unindexed memory name",
+    syp->synam, __msgexpr_tostr(__xs, ndp));
+   return;
+  }
+ if (anum > 2) { alxp = alxp->ru.x; __chk_rhsexpr(alxp->lu.x, 0); }
+ if (anum > 3) { alxp = alxp->ru.x; __chk_rhsexpr(alxp->lu.x, 0); }
+}
+
+/*
+ * return if expression is an unindexed array
+ */
+static int32 nd_unind_arr(struct expr_t *ndp)
+{
+ struct net_t *np;
+
+ if (ndp->optyp != ID && ndp->optyp != GLBREF) return(FALSE);
+ np = ndp->lu.sy->el.enp;
+ /* notice (s)readmem assigns to memory so it is lhs indirectly here */
+ if (np->nrngrep == NX_CT) np->nu.ct->n_onlhs = TRUE;
+ if (np->ntyp < NONWIRE_ST || np->ntyp == N_EVENT) return(FALSE);
+ if (!np->n_isarr) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * check $sreadmemb or $sreadmemh arguments
+ */
+static void chkst_sreadmem(struct sy_t *syp, int32 anum,
+ struct tskcall_t *tkcp)
+{
+ register struct expr_t *alxp;
+
+ if (anum < 4)
+  {
+   __sgferr(884, "%s system task has %d arguments but at least 4 required",
+    syp->synam, anum);
+   /* leave since correct number will not be needed */
+   return;
+  }
+ alxp = tkcp->targs;
+ if (!nd_unind_arr(alxp->lu.x))
+  {
+   __sgferr(895,
+    "%s system task first argument %s must be an unindexed memory name",
+    syp->synam, __msgexpr_tostr(__xs, alxp->lu.x));
+   return;
+  }
+ alxp = alxp->ru.x;
+ __chk_rhsexpr(alxp->lu.x, 0);
+ alxp = alxp->ru.x;
+ __chk_rhsexpr(alxp->lu.x, 0);
+ /* all remaiing only needs to eval (forced) to string need not be literal */
+ for (alxp = alxp->ru.x; alxp != NULL; alxp = alxp->ru.x)
+  __chk_rhsexpr(alxp->lu.x, 0);
+} 
+ 
+/*
+ * check $sdf_annotate system tsk arguments 
+ */
+static void chkst_sdfannotate_enable(struct tskcall_t *tkcp, int32 anum)
+{
+ register struct expr_t *alxp;
+ register int32 argi;
+ struct expr_t *ndp;
+
+ if (anum < 1 || anum > 7)
+  {
+   __sgferr(884,
+    "$sdf_annotate system task must have from 1 to 7 arguments - has %d",
+    anum);
+   return;
+  }
+ alxp = tkcp->targs;
+
+ ndp = alxp->lu.x;
+ /* allowing string expressions following other places in language */
+ __chk_rhsexpr(ndp, 0);
+ if (ndp->optyp == OPEMPTY)
+  {
+   __sgferr(918,
+    "$sdf_annotate required first file name argument empty (, form illegal");
+   return;
+  }
+ if (__iact_state)
+  {
+   __ia_err(1495,
+    "$sdf_annotate system task call illegal as interactive command - must be added to source");
+   return;
+  }
+ __has_sdfann_calls = TRUE;
+ /* only first file name arg required */
+ if (anum <= 1) return;
+
+ /* this must always be xmr instance scope reference - already resolved */ 
+ alxp = alxp->ru.x;
+ ndp = alxp->lu.x;
+ /* because this must be scope - can not use chk rhs expr for this arg */
+ /* scope reference can be empty ,, form */
+ if (ndp->optyp != OPEMPTY)
+  {
+   if (ndp->optyp != GLBREF || (ndp->lu.sy->sytyp != SYM_I
+    && ndp->lu.sy->sytyp != SYM_M))
+    {
+     __sgferr(876, 
+     "$sdf_annotate second argument %s illegal - must be module instance scope",
+      __msgexpr_tostr(__xs, ndp));
+     return;
+    }
+  }
+ for (alxp = alxp->ru.x, argi = 3; alxp != NULL; alxp = alxp->ru.x, argi++)
+  {
+   ndp = alxp->lu.x;
+   __chk_rhsexpr(ndp, 0);
+   if (ndp->optyp == OPEMPTY) continue;
+
+   switch (argi) {
+    case 3:
+     __sgfwarn(664, 
+      "$sdf_annotate third config_file argument %s ignored - not in SDF standard",
+      __msgexpr_tostr(__xs, ndp));
+     break;
+    /* SJM 07/08/01 - now supporting separate SDF log file */
+    case 4: break;
+    /* MTM to over-ride command line option supported */
+    case 5: break;
+    case 6:
+      __sgfwarn(664, 
+       "$sdf_annotate sixth scale factors argument %s ignored - not in SDF standard",
+       __msgexpr_tostr(__xs, ndp));
+      break;
+     case 7:
+      __sgfwarn(664, 
+       "$sdf_annotate seventh scale type argument %s ignored - not in SDF standard",
+       __msgexpr_tostr(__xs, ndp));
+      break;
+     default: __case_terr(__FILE__, __LINE__);
+   }
+  }
+}
+
+/*
+ * ROUTINES TO FIX UP AND CHECK SPECIFY SECTION
+ */
+
+/*
+ * check specparams
+ */
+extern void __chkfix_spfy(void)
+{ 
+ register struct spcpth_t *pthp;
+ register struct tchk_t *tcp;
+ int32 spec_empty, saveobj;
+ struct spfy_t *spfp;
+ struct tchk_t *suptcp, *rectcp;
+
+ saveobj = __cur_declobj;
+ __cur_declobj = SPECIFY;
+ spec_empty = TRUE;
+ spfp = __inst_mod->mspfy;
+ /* make sure all specparams that were used are defined */
+ /* unless all specparam values defined cannot check specify section */
+ /* or determine specparam values */
+ if (spfp->spfsyms->numsyms != 0)
+  {
+   spec_empty = FALSE;
+   if (!chk_undef_specparams(spfp->spfsyms)) goto done;
+  } 
+
+ /* if top level module has paths - emit warning and ignore */
+ if (__inst_mod->minstnum == 0)
+  { 
+   if (spfp->spcpths != NULL)  
+    {
+     __pv_warn(679, 
+      "specify paths in top level module %s ignored - should be in library",
+      __inst_mod->msym->synam);
+
+     spec_empty = FALSE;
+     free_spcpths(spfp->spcpths);
+     spfp->spcpths = NULL;
+    }
+  }
+ else 
+  {
+   /* check pin to pin delays */
+   for (pthp = spfp->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+    {
+     spec_empty = FALSE;
+     if (!chk_1spcpth(pthp)) { pthp->pth_gone = TRUE; continue; }
+     if (pthp->pthtyp == PTH_FULL) chk_rep_in_fullpth(pthp);
+    }
+   /* use all module paths to check for sdpds multiple same paths withs conds */
+   chk_rep_sdpds(spfp);
+  }
+
+ /* check timing checks */
+ for (tcp = spfp->tchks; tcp != NULL; tcp = tcp->tchknxt)
+  {
+   /* if marked gone because of error, do not split setuphold */
+   spec_empty = FALSE;
+   if (!chk_1tchk(tcp)) tcp->tc_gone = TRUE;
+   else
+    {
+     if (tcp->tchktyp == TCHK_SETUPHOLD)
+      {
+       suptcp = bld_sup_of_suphld(tcp); 
+       /* insert after current and move pointer so not checked */
+       suptcp->tchknxt = tcp->tchknxt;
+       tcp->tchknxt = suptcp;
+       tcp = tcp->tchknxt;
+      }
+     else if (tcp->tchktyp == TCHK_RECREM)
+      {
+       rectcp = bld_rec_of_recrem(tcp); 
+       /* insert after current and move pointer so not checked */
+       rectcp->tchknxt = tcp->tchknxt;
+       tcp->tchknxt = rectcp;
+       tcp = tcp->tchknxt;
+      } 
+    } 
+  }
+done:
+ if (spec_empty)
+  __pv_warn(559, 
+   "module %s specify section has no delay paths or timing checks",
+   __inst_mod->msym->synam);
+ __cur_declobj = saveobj;
+}
+
+/*
+ * check for undefined but used specparams
+ *
+ * if a variable is used in a delay expr. or tchk limit or specparam rhs
+ * it is assumed to be an undeclared specparam - this makes sure it appears
+ * in a specparam statement 
+ */
+static int32 chk_undef_specparams(struct symtab_t *sytp)
+{
+ register int32 syi;
+ int32 good;
+ struct sy_t *syp;
+
+ __wrkstab = sytp->stsyms;
+ for (good = TRUE, syi = 0; syi < (int32) sytp->numsyms; syi++)
+  {
+   syp = __wrkstab[syi];
+   if (!syp->sydecl)
+    {
+     __gferr(777, syp->syfnam_ind, syp->sylin_cnt,
+      "specparam or path element %s not defined or not wire", syp->synam); 
+     good = FALSE;
+    }
+  }
+ return(good);
+}
+
+/*
+ * check 1 specify path
+ * converts from expression to path else simple wire or select 
+ * will return F if error and path marked as gone
+ *
+ * any edge check at source input - will be correct by here or previous error
+ * check cond. expr. here than can be any rhs expression
+ * eval code handles selecting low bit if needed
+ */
+static int32 chk_1spcpth(struct spcpth_t *pthp) 
+{
+ register struct exprlst_t *pxlp;
+ register int32 pei;
+ int32 num_peinels, num_peoutels, pi1, pi2, dnum, sav_errcnt;
+ word32 badoptyp;
+ struct exprlst_t *pxins, *pxouts, *pxlp2;
+ struct net_t *np;
+ struct pathel_t *pep;
+ struct expr_t *cndx;
+ struct paramlst_t *pmp, *dhdr;
+ char s1[RECLEN];
+
+ sav_errcnt = __pv_err_cnt;
+ __sfnam_ind = pthp->pthsym->syfnam_ind;
+ __slin_cnt = pthp->pthsym->sylin_cnt;
+
+ /* first check input and output path expr. lists */
+ pxlp = (struct exprlst_t *) pthp->peins;
+ /* do not bother free error stuff here - if non I/O will need to support */
+ for (num_peinels = 0; pxlp != NULL; pxlp = pxlp->xpnxt, num_peinels++)
+  {
+   if (num_peinels == 0 && pxlp->xpnxt == NULL) strcpy(s1, "");
+   else sprintf(s1, " terminal %d", num_peinels + 1); 
+   chk_spterm(pxlp->xp, s1, "path input", IO_IN);
+  }
+ pxlp = (struct exprlst_t *) pthp->peouts;
+ for (num_peoutels = 0; pxlp != NULL; pxlp = pxlp->xpnxt, num_peoutels++)
+  {
+   if (num_peoutels == 0 && pxlp->xpnxt == NULL) strcpy(s1, "");
+   else sprintf(s1, " terminal %d", num_peoutels + 1); 
+   chk_spterm(pxlp->xp, s1, "path output", IO_OUT);
+  }
+ if (sav_errcnt != __pv_err_cnt) goto chk_pdels;
+ /* paths must always have 1 element to get here */
+ if (num_peinels < 1 || num_peoutels < 1) __misc_terr(__FILE__, __LINE__);
+
+ /* error for || paths to have lists - but continue checking */
+ if (pthp->pthtyp == PTH_PAR && (num_peinels > 1 || num_peoutels > 1))
+  {
+   __sgferr(1085,
+    "parallel (=>) path illegally has multiple sources (%d) and/or destinations (%d)",
+    num_peinels, num_peoutels);
+  }
+
+ /* convert to pathel form and mark wires that are specify srcs and dsts */
+ pxins = (struct exprlst_t *) pthp->peins;
+ pxouts = (struct exprlst_t *) pthp->peouts;
+ /* must build the path tables and mark path source and dest. wires */
+ pthp->peins = (struct pathel_t *)
+  __my_malloc(num_peinels*sizeof(struct pathel_t));
+ pthp->last_pein = num_peinels - 1;
+ for (pei = 0, pxlp = pxins; pei < num_peinels; pei++)
+  {
+   pxlp2 = pxlp->xpnxt;
+   __xtract_wirng(pxlp->xp, &np, &pi1, &pi2);
+   pep = &(pthp->peins[pei]);
+   pep->penp = np;
+   pep->pthi1 = pi1;
+   pep->pthi2 = pi2;
+   np->n_isapthsrc = TRUE;
+   __free_xtree(pxlp->xp); 
+   __my_free((char *) pxlp, sizeof(struct exprlst_t)); 
+   pxlp = pxlp2;
+  }
+ pthp->peouts = (struct pathel_t *)
+  __my_malloc(num_peoutels*sizeof(struct pathel_t));
+ pthp->last_peout = num_peoutels - 1;
+ for (pei = 0, pxlp = pxouts; pei < num_peoutels; pei++)
+  {
+   pxlp2 = pxlp->xpnxt;
+   __xtract_wirng(pxlp->xp, &np, &pi1, &pi2);
+   np->n_isapthdst = TRUE;
+   pep = &(pthp->peouts[pei]);
+   pep->penp = np;
+   pep->pthi1 = pi1;
+   pep->pthi2 = pi2;
+   __free_xtree(pxlp->xp); 
+   __my_free((char *) pxlp, sizeof(struct exprlst_t)); 
+   pxlp = pxlp2;
+  }
+ /* mark form of path expressions changed to range form */
+ pthp->pth_as_xprs = FALSE;
+
+chk_pdels:
+ /* first check cond. expr if present */
+ if ((cndx = pthp->pthcondx) != NULL)
+  {
+   __chk_rhsexpr(cndx, 0);
+   /* normal expression except no xmr's and only path condition operators */
+   if (__expr_has_glb(cndx))
+    {
+     __sgferr(1022,
+      "global hierarchical reference illegal in state dependent path condition %s",
+      __msgexpr_tostr(__xs, cndx));
+    }
+   if (expr_has_nonpth(cndx, &badoptyp))
+    {
+     __sgferr(1022,
+      "state dependent path condition (%s) illegal operator(s) [one bad: %s]",
+      __msgexpr_tostr(__xs, cndx), __to_opname(badoptyp));
+    }
+  }
+ /* if ifnone, must be simple module path */
+ if (pthp->pth_ifnone)
+  {
+   if (pthp->pthcondx != NULL || pthp->pthedge != NOEDGE)
+    {
+     __sgferr(1012, "ifnone path illegal - has edge or is state dependent");
+    }
+  }
+
+ /* next check and substitute numeric values for expressions */
+ /* changed to sim form during prep */
+ dhdr = __copy_dellst(pthp->pth_du.pdels);
+ for (dnum = 0, pmp = dhdr; pmp != NULL; pmp = pmp->pmlnxt)
+  {
+   sprintf(s1, "path delay (element %d)", dnum + 1);
+   __chk_spec_delay(pmp->plxndp, s1);
+   dnum++;
+  }
+ __free_dellst(dhdr);
+ if (dnum == 1 || dnum == 2 || dnum == 3 || dnum == 6 || dnum == 12) 
+  {
+   if (sav_errcnt != __pv_err_cnt) return(FALSE);
+   return(TRUE);
+  }
+ __sgferr(791, "path delay illegal number of delays %d", dnum);
+ return(FALSE);
+}
+
+/*
+ * return T if expression has any illegal path cond. expr. operators
+ * uses value from op info table
+ */
+static int32 expr_has_nonpth(struct expr_t *cndx, word32 *badop)
+{
+ struct opinfo_t *opip;
+
+ *badop = UNDEF;
+ if (__isleaf(cndx)) return(FALSE);
+ opip = &(__opinfo[cndx->optyp]);
+ if (!opip->pthexpop)
+  {
+   *badop = cndx->optyp;
+   return(TRUE);
+  }
+
+ if (cndx->lu.x != NULL)
+  {
+   if (expr_has_nonpth(cndx->lu.x, badop)) return(TRUE);
+  }  
+ if (cndx->ru.x != NULL)
+  {
+   if (expr_has_nonpth(cndx->ru.x, badop)) return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * check all paths to make sure no same paths withing full (*>) list
+ *
+ * because duplicate entries for same sdpds need different conditions
+ * error for repeated path in one statement
+ *
+ * only called for full *> paths
+ */
+static void chk_rep_in_fullpth(struct spcpth_t *pthp)
+{
+ register int32 pei, pei2;
+ struct pathel_t *pep1, *pep2;
+ char s1[RECLEN], s2[RECLEN];
+
+ /* first check for repeated ins - because full will be repeated */
+ for (pei = 0; pei <= pthp->last_pein; pei++)
+  {
+   pep1 = &(pthp->peins[pei]);
+   for (pei2 = pei + 1; pei2 <= pthp->last_pein; pei2++)
+    {
+     pep2 = &(pthp->peins[pei2]);
+     if (pep1->penp != pep2->penp) continue; 
+     /* exactly same path repeated */
+     if (pep1->pthi1 == pep2->pthi1 && pep1->pthi2 == pep2->pthi2)
+      {
+       __gferr(1059,  pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+        "full path input element %s repeated in one path", 
+        pthel_tostr(s1, pep1));
+       continue;
+      }
+     /* overlapped path repeated */ 
+     if (pth_overlap(pep1, pep2))
+      {
+       __gferr(1079,  pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+        "path path input element %s overlaps %s in one path",
+        pthel_tostr(s1, pep1), pthel_tostr(s2, pep2));
+      } 
+     }
+   }
+ /* next check for repeated outs - because full will be repeated */
+ for (pei = 0; pei <= pthp->last_peout; pei++)
+  {
+   pep1 = &(pthp->peins[pei]);
+   for (pei2 = pei + 1; pei2 <= pthp->last_pein; pei2++)
+    {
+     pep2 = &(pthp->peouts[pei2]);
+     if (pep1->penp != pep2->penp) continue; 
+     /* exactly same path repeated */
+     if (pep1->pthi1 == pep2->pthi1 && pep1->pthi2 == pep2->pthi2)
+      {
+       __gferr(1059, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+        "full path output element %s repeated in one path", 
+        pthel_tostr(s1, pep1));
+       pthp->pth_gone = TRUE;
+       continue;
+      }
+     /* overlapped path elements error */
+     if (pth_overlap(pep1, pep2))
+      {
+       __gferr(1079,  pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+        "path output element %s overlaps %s in one path",
+        pthel_tostr(s1, pep1), pthel_tostr(s2, pep2));
+       pthp->pth_gone = TRUE;
+      }
+    }
+  }
+}
+
+/*
+ * convert a simple (non list form) path to a string
+ */
+static char *pth_tostr(char *s, struct spcpth_t *pthp,
+ struct pathel_t *pep1, struct pathel_t *pep2)
+{
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (pthp->pthtyp == PTH_FULL) strcpy(s1, "*>"); else strcpy(s1, "=>");
+ sprintf(s, "(%s %s %s)", pthel_tostr(s2, pep1), s1, pthel_tostr(s3, pep2));
+ return(s);
+}
+
+/*
+ * convert path element to string
+ */
+static char *pthel_tostr(char *s, struct pathel_t *pep)
+{
+ if (pep->pthi1 == -1) strcpy(s, pep->penp->nsym->synam);
+ else if (pep->pthi1 == pep->pthi2) sprintf(s, "%s[%d]",
+  pep->penp->nsym->synam, pep->pthi1);
+ else sprintf(s, "%s[%d:%d]", pep->penp->nsym->synam, pep->pthi1, pep->pthi2);
+ return(s);
+}
+
+/*
+ * return T if 2 path elements overlap - know not called if identical
+ */
+static int32 pth_overlap( struct pathel_t *pep1, struct pathel_t *pep2)
+{
+ int32 i1, i2, o1, o2;
+
+ if (pep1->pthi1 >= pep1->pthi2) { i1 = pep1->pthi1; i2 = pep1->pthi2; }
+ else { i1 = pep1->pthi2; i2 = pep1->pthi1; }
+ if (pep2->pthi1 >= pep2->pthi2) { o1 = pep2->pthi1; o2 = pep2->pthi2; }
+ else { o1 = pep2->pthi2; o2 = pep2->pthi1; }
+ if (i2 > o1 || o2 > i1) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * check repeated sdpd paths
+ */
+static void chk_rep_sdpds(struct spfy_t *spfp)
+{
+ register struct xpnd_pthel_t *xpthp, *xpthp2;
+ int32 numxpths, last_xpi, xpi, has_ifnone;
+ struct xpnd_pthel_t *xpth_hdr, **xpth_equivs;
+ struct spcpth_t *pthp, *pthp2;
+ struct pathel_t *pep1s, *pep1e, *pep2s, *pep2e;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+ 
+ /* for paths that are gone, expanded elements not added */
+ /* if none expanded, done */
+ if ((xpth_hdr = xpnd_pths(spfp, &numxpths)) == NULL) return;
+
+ /* since as big as entire list know big enough */
+ xpth_equivs = (struct xpnd_pthel_t **)
+  __my_malloc(numxpths*sizeof(struct xpnd_pthel_t *));
+
+ for (xpthp = xpth_hdr; xpthp != NULL; xpthp = xpthp->xpthnxt)
+  {
+   if (xpthp->in_equiv_set) continue;
+   xpth_equivs[0] = xpthp; 
+   /* since processing done, makr as in equiv. class (maybe size 1) */ 
+   xpthp->in_equiv_set = TRUE;
+   last_xpi = 0;
+   pthp = xpthp->pthp;
+   pep1s = &(pthp->peins[xpthp->peii]);
+   pep1e = &(pthp->peouts[xpthp->peoi]);
+   for (xpthp2 = xpthp->xpthnxt; xpthp2 != NULL; xpthp2 = xpthp2->xpthnxt)
+    {
+     if (xpthp2->in_equiv_set) continue;
+
+     pthp2 = xpthp2->pthp;
+     pep2s = &(pthp2->peins[xpthp2->peii]);
+     pep2e = &(pthp2->peouts[xpthp2->peoi]);
+
+     /* if both src or both dest nets differ, eliminate */
+     if (pep1s->penp != pep2s->penp || pep1e->penp != pep2e->penp) continue;
+     
+     /* range must be exact match */
+     if (pep1s->pthi1 == pep2s->pthi1 && pep1s->pthi2 == pep2s->pthi2
+      && pep1e->pthi1 == pep2e->pthi1 && pep1e->pthi2 == pep2e->pthi2)
+      { 
+       xpth_equivs[++last_xpi] = xpthp2; 
+       xpthp2->in_equiv_set = TRUE;
+       continue;
+      }
+
+     /* probably same paths but not coded the same way - error */ 
+     /* notice some source bit(s) to two different dest bit(s) ok */
+     if (pth_overlap(pep1s, pep2s) && pth_overlap(pep1e, pep2e))
+      {
+       __gferr(1118, pthp2->pthsym->syfnam_ind, pthp2->pthsym->sylin_cnt,
+        "path %s and path %s at %s overlap - multiple sdpds must have identical ranges",
+        pth_tostr(s1, pthp2, pep2s, pep2e), pth_tostr(s2, pthp, pep1s, pep1e), 
+        __bld_lineloc(s3, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt));
+       /* mark so will test for other overlap equivalences */ 
+       xpthp2->in_equiv_set = TRUE;
+      }
+    }
+   /* check equivalence class (even if only one element) */
+   if (last_xpi == 0)
+    {
+     pthp2 = xpth_equivs[0]->pthp;
+     if (pthp2->pth_ifnone)
+      {
+       pthp2->pth_ifnone = FALSE;
+       __gfinform(482, pthp2->pthsym->syfnam_ind, pthp2->pthsym->sylin_cnt,
+        "path has ifnone condition but no other sdpds for path - made simple");
+      }
+     continue;
+    }
+   /* real multiple path - only check makes sure either has cond or edge */
+   /* LOOKATME - will not work if same expressions but can not check this */
+   for (has_ifnone = FALSE, xpi = 0; xpi <= last_xpi; xpi++)
+    {
+     xpthp2 = xpth_equivs[xpi];
+     pthp2 = xpthp2->pthp;
+     /* if none must be simple - already check */
+     if (pthp2->pth_ifnone)
+      {
+       if (has_ifnone)
+        {
+         __gferr(1125, pthp2->pthsym->syfnam_ind, pthp2->pthsym->sylin_cnt,
+          "more than one ifnone path in sdpd same path group illegal");
+        }
+       else has_ifnone = TRUE;
+       continue;
+      }
+     /* other in same path sdpd group must be non simple */
+     if (pthp2->pthcondx == NULL && pthp2->pthedge == NOEDGE)
+      {
+       __gferr(1126, pthp2->pthsym->syfnam_ind, pthp2->pthsym->sylin_cnt,
+        "path in sdpd same path group illegally simple - needs edge or conditon");
+      }
+    }
+  }
+
+ /* free the expanded path list */
+ __my_free((char *) xpth_equivs, numxpths*sizeof(struct xpnd_pthel_t *));
+ for (xpthp = xpth_hdr; xpthp != NULL;)
+  {
+   xpthp2 = xpthp->xpthnxt;
+   __my_free((char *) xpthp, sizeof(struct xpnd_pthel_t));
+   xpthp = xpthp2;
+  } 
+}
+
+/*
+ * expand paths into list of simple (non list form) elements
+ */
+static struct xpnd_pthel_t *xpnd_pths(struct spfy_t *spfp,
+ int32 *numxpths)
+{
+ register int32 pii, poi;
+ int32 numxps;
+ struct spcpth_t *pthp;
+ struct xpnd_pthel_t *xpth_hdr, *xpth_end, *xpthp; 
+
+ xpth_hdr = xpth_end = NULL;
+ numxps = 0;
+ for (pthp = spfp->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+  {
+   if (pthp->pth_gone) continue;
+
+   if (pthp->pthtyp == PTH_PAR)
+    {
+     xpthp = (struct xpnd_pthel_t *) __my_malloc(sizeof(struct xpnd_pthel_t));
+     xpthp->in_equiv_set = FALSE;
+     xpthp->pthp = pthp;
+     xpthp->peii = xpthp->peoi = 0;
+     xpthp->xpthnxt = NULL;
+     if (xpth_hdr == NULL) xpth_hdr = xpth_end = xpthp;
+     else { xpth_end->xpthnxt = xpthp; xpth_end = xpthp; } 
+     numxps++; 
+     continue;
+    }
+   /* harder full path case */
+   for (pii = 0; pii <= pthp->last_pein; pii++)
+    {
+     for (poi = 0; poi <= pthp->last_peout; poi++)
+      {
+       xpthp = (struct xpnd_pthel_t *) __my_malloc(sizeof(struct xpnd_pthel_t));
+       xpthp->in_equiv_set = FALSE;
+       xpthp->pthp = pthp;
+       xpthp->peii =pii; 
+       xpthp->peoi = poi;
+       xpthp->xpthnxt = NULL;
+       if (xpth_hdr == NULL) xpth_hdr = xpth_end = xpthp;
+       else { xpth_end->xpthnxt = xpthp; xpth_end = xpthp; } 
+       numxps++; 
+      }
+    }
+  }
+ *numxpths = numxps;
+ return(xpth_hdr);
+}
+
+/*
+ * check a specify section delay value
+ */
+extern void __chk_spec_delay(struct expr_t *ndp, char *emsg)
+{
+ /* first must be expr. of numbers and parameters only */
+ if (!__chk_paramexpr(ndp, 0))
+  {
+   __sgferr(898, "%s must be specify constant expression", emsg);
+   return;
+  }
+ /* then must fold */
+ fold_subexpr(ndp);
+ /* finally check to make sure number delay - prep code scales */
+ __chk_numdelay(ndp, emsg);
+ ndp->ibase = BDEC;
+}
+
+/*
+ * check specify terminal (path or timing check)
+ * do not remove since will not get to prep. code
+ */
+static void chk_spterm(struct expr_t *spxp, char *spos, char *snam,
+ int32 iodir)
+{
+ struct net_t *np;
+ struct expr_t *xp, *xp2;
+
+ /* if even path destination (could be rhs reg), here must be lhs wire */
+ if (spxp->optyp == LCB)
+  {
+   __sgferr(914, "%s%s concatenate illegal", snam, spos);
+   return;
+  }
+ if (spxp->optyp == GLBREF)
+  {
+   __sgferr(899, "%s%s hierarchical reference illegal", snam, spos); 
+   return;
+  }
+ /* exactly 3 things legal, port wire, bsel of port wire, psel of port wire */ 
+ switch (spxp->optyp) {
+  case ID: 
+   np = spxp->lu.sy->el.enp;
+
+chk_iodir:
+   /* timing check terminal can be any wire */
+   if (iodir == NON_IO)
+    {
+     if (np->ntyp >= NONWIRE_ST)
+      {
+       __sgferr(901, "%s%s terminal %s %s must be a wire",
+        snam, spos, __to_wtnam(__xs, np), np->nsym->synam);
+      }
+     return;
+    }
+
+   /* check to make sure terminal is port */
+   if (np->iotyp == NON_IO)
+    {
+     __sgferr(905, "%s%s %s %s must be a module I/O port",
+      snam, spos, __to_wtnam(__xs, np), np->nsym->synam);
+     return;
+    }
+   if (iodir == IO_IN)
+    {
+     if (np->iotyp != IO_IN && np->iotyp != IO_BID)
+      {
+       __sgferr(906, "%s%s port %s must be input or inout", snam, spos,
+        np->nsym->synam); 
+       return;
+      }
+    }
+   else
+    {
+     if (np->iotyp != IO_OUT && np->iotyp != IO_BID)
+      {
+       __sgferr(907, "%s%s port %s must be output or inout", snam, spos,
+        np->nsym->synam); 
+       return;
+      }
+    }
+   break;
+  case LSB:
+   np = spxp->lu.x->lu.sy->el.enp;
+   xp = spxp->ru.x;
+   /* index must only contain specparams and numbers */
+   if (!__chk_paramexpr(xp, 0)) return;
+   /* next must fold it */
+   fold_subexpr(xp);
+   /* result must be number (no IS form) or error */
+   if (xp->optyp != NUMBER)
+    {
+     __sgferr(908,
+      "%s%s port bit select %s must contain only numbers and specparams",
+      snam, spos, __msgexpr_tostr(__xs, spxp));
+    }
+   /* finally check and normalize bit select */
+   chk_inrng_bsel(spxp);
+   goto chk_iodir;
+  case PARTSEL:
+   np = spxp->lu.x->lu.sy->el.enp;
+   xp = spxp->ru.x->lu.x;
+   xp2 = spxp->ru.x->ru.x;
+   /* index must only contain specparams and numbers */
+   if (!__chk_paramexpr(xp, 0) || !__chk_paramexpr(xp2, 0)) return;
+   /* next must fold it */
+   fold_subexpr(xp);
+   fold_subexpr(xp2);
+   /* result must be number (no IS form) or error */
+   if (xp->optyp != NUMBER || xp2->optyp != NUMBER)
+    {
+     __sgferr(904,
+      "%s%s port part select %s must contain only numbers and specparams",
+      snam, spos, __msgexpr_tostr(__xs, spxp));
+    }
+   /* finally check and normalize bit select */
+   chk_inrng_psel(spxp);
+   goto chk_iodir;
+  default:
+   __sgferr(915, "%s%s illegal expression %s", snam, spos,
+     __msgexpr_tostr(__xs, spxp));
+ } 
+}
+
+/*
+ * check 1 specify timing check
+ *
+ * notice only checking here - width/period event duplicated in prep code
+ * limit evaluation routines must be recalled if specparams changed
+ * any edges read and checking during source input but cond checked here
+ */
+static int32 chk_1tchk(struct tchk_t *tcp)
+{
+ int32 sav_errcnt;
+ struct paramlst_t *dhdr;
+ char s1[RECLEN], s2[RECLEN];
+
+ __sfnam_ind = tcp->tcsym->syfnam_ind;
+ __slin_cnt = tcp->tcsym->sylin_cnt;
+
+ sav_errcnt = __pv_err_cnt;
+ sprintf(s1, " %s timing check", __to_tcnam(s2, tcp->tchktyp)); 
+ switch ((byte) tcp->tchktyp) { 
+  case TCHK_SETUP: case TCHK_HOLD: case TCHK_SKEW: case TCHK_SETUPHOLD:
+  case TCHK_RECOVERY: case TCHK_REMOVAL: case TCHK_RECREM:
+   /* SJM 01/16/04 - $removal has reversed terms to $recovery as setup/hold */
+   chk_spterm(tcp->startxp, "first event", s1, NON_IO);
+   if (tcp->startcondx != NULL) chk_tccond(tcp->startcondx, "first", s1);
+   chk_spterm(tcp->chkxp, "second event", s1, NON_IO);
+   if (tcp->chkcondx != NULL) chk_tccond(tcp->chkcondx, "second", s1);
+   chk_notifier(tcp, s1);
+
+   /* this will find errors and if errors convert to 0 */
+   /* notice leave 1st (setup) limit even though not used for hold part */ 
+   dhdr = __copy_dellst(tcp->tclim_du.pdels);
+   __chk_spec_delay(dhdr->plxndp, "timing check limit");
+   __free_dellst(dhdr);
+
+   /* this is hold half limit but kept in original not added setup */
+   if (tcp->tchktyp == TCHK_SETUPHOLD)
+    {
+     dhdr = __copy_dellst(tcp->tclim2_du.pdels);
+     __chk_spec_delay(dhdr->plxndp, "setuphold second (hold) limit");
+     __free_dellst(dhdr);
+    }
+   /* this is removal half limit but kept in original not added recovery */
+   else if (tcp->tchktyp == TCHK_SETUPHOLD)
+    {
+     dhdr = __copy_dellst(tcp->tclim2_du.pdels);
+     __chk_spec_delay(dhdr->plxndp, "recrem second (removal) limit");
+     __free_dellst(dhdr);
+    }
+   break;
+  case TCHK_WIDTH: case TCHK_PERIOD:
+   /* one event, 2 limits for width but 2nd threshold is optional */  
+   chk_spterm(tcp->startxp, "first edge", s1, NON_IO);
+   if (tcp->startcondx != NULL) chk_tccond(tcp->startcondx, "first edge", s1);
+   chk_notifier(tcp, s1);
+   /* check delay expr. */
+   dhdr = __copy_dellst(tcp->tclim_du.pdels);
+   __chk_spec_delay(dhdr->plxndp, "timing check limit");
+   __free_dellst(dhdr);
+
+   if (tcp->tchktyp == TCHK_WIDTH)
+    {
+     dhdr = __copy_dellst(tcp->tclim2_du.pdels);
+     __chk_spec_delay(dhdr->plxndp, "width second limit");
+     __free_dellst(dhdr);
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ /* if any errors, return fail (F) */ 
+ if (sav_errcnt != __pv_err_cnt) return(FALSE); 
+ return(TRUE);
+}
+
+/*
+ * check the option condition
+ * notice this is procedural rhs
+ */
+static void chk_tccond(struct expr_t *cndx, char *spos, char *snam)
+{
+ struct net_t *np;
+
+ /* this expr. needs to be one bit but width self determined */
+ __chk_rhsexpr(cndx, 0);
+ switch ((byte) cndx->optyp) {
+  case ID:
+   np = cndx->lu.sy->el.enp;
+chk_1bit:
+   /* notice - wires ok here - just gets evaluated */
+   if (np->n_isarr)
+    {
+     __sgferr(909, "%s %s &&& condition array %s illegal", spos, snam,
+      np->nsym->synam); 
+     return;
+    }
+   if (cndx->szu.xclen > 1)
+    {
+     __sgfwarn(613,
+      "%s %s &&& condition expression %s wider than 1 bit - low bit used",
+      spos, snam, __msgexpr_tostr(__xs, cndx));
+    }
+   return;
+  case BITNOT: 
+   if (cndx->lu.x->optyp != ID)
+    __sgferr(910,
+     "%s %s &&& condition ~ (bit not) operand too complicated (must be identifier)",
+     spos, snam);
+   np = cndx->lu.x->lu.sy->el.enp;
+   goto chk_1bit;
+  case RELCEQ:
+  case RELCNEQ:
+  case RELEQ: 
+  case RELNEQ:
+   if (cndx->lu.x->optyp != ID)
+    {
+     __sgferr(912,
+      "%s %s &&& condition left operand too complicated (must be identifier)",
+      spos, snam);
+     return; 
+    }
+   np = cndx->lu.x->lu.sy->el.enp;
+   if (cndx->ru.x->optyp != NUMBER || cndx->ru.x->szu.xclen > WBITS)
+    {
+bad_const:
+     __sgferr(911,
+      "%s %s &&& condition right operand must be a scalar constant",
+      spos, snam);
+     goto chk_1bit;
+    }
+   if (cndx->ru.x->szu.xclen != 1)
+    {
+     word32 av, bv;
+     word32 *wp;
+
+     wp = &(__contab[cndx->ru.x->ru.xvi]);
+     av = wp[0];
+     bv = wp[1];
+     if ((av != 0L && av != 1L) || (bv != 0L && bv != 1L)) goto bad_const;  
+     cndx->ru.x->szu.xclen = 1;
+    }
+   goto chk_1bit;
+  default:
+   __sgferr(913,
+    "%s %s &&& condition expression must be one operator scalar expression",
+    spos, snam);
+ }
+}
+
+/*
+ * check a notifier - must be register
+ * this also changed coded symbol to wire or NULL
+ */
+static void chk_notifier(struct tchk_t *tcp, char *snam)
+{
+ struct sy_t *syp;
+
+ if (tcp->ntfy_np == NULL) return;
+ syp = (struct sy_t *) tcp->ntfy_np;
+ if (syp->sytyp != SYM_N || syp->el.enp->ntyp != N_REG
+  || syp->el.enp->n_isavec)
+  {
+   __sgferr(916,
+    "%s notify symbol %s is not a scalar register", snam, syp->synam);
+   tcp->ntfy_np = NULL;
+   return;
+  }
+ tcp->ntfy_np = syp->el.enp;
+}
+
+/*
+ * build setuphold new setup timing check
+ *
+ * setuphold contains hold half (ref. and data event orders match), 
+ * setup has reversed but uses 1st delay from hold referenced thru lim
+ */
+static struct tchk_t *bld_sup_of_suphld(struct tchk_t *otcp)
+{
+ struct tchk_t *ntcp;
+
+ ntcp = (struct tchk_t *) __my_malloc(sizeof(struct tchk_t));
+ __init_tchk(ntcp, TCHK_SETUP);
+ ntcp->tc_supofsuphld = TRUE;
+ /* notice the 2 halves share symbol and handled specially in mod copy */
+ ntcp->tcsym = otcp->tcsym;
+ /* reverse edges */
+ ntcp->startedge = otcp->chkedge;
+ ntcp->chkedge = otcp->startedge;
+
+ /* copy start reference event expr. from check */
+ if (otcp->startxp != NULL) ntcp->chkxp = __copy_expr(otcp->startxp);
+ if (otcp->startcondx != NULL)
+  ntcp->chkcondx = __copy_expr(otcp->startcondx);
+
+ /* copy start reference event expr. from check */
+ if (otcp->chkxp != NULL) ntcp->startxp = __copy_expr(otcp->chkxp);
+ if (otcp->chkcondx != NULL)
+  ntcp->startcondx = __copy_expr(otcp->chkcondx);
+ /* point first delay to master hold and get delay (1st) from there */
+ ntcp->tclim_du.pdels = (struct paramlst_t *) otcp;
+
+ /* notice this is intra module so can just copy - becomes net */
+ ntcp->ntfy_np = otcp->ntfy_np;
+ return(ntcp);
+}
+
+/*
+ * build recrems new recovery timing check
+ * SJM - 01/16/04 added to support new 2001 LRM $recrem
+ *
+ * recrem contains removal half (ref. and data event orders match), 
+ * recovery has reversed but uses 1st delay from removal referenced thru lim
+ */
+static struct tchk_t *bld_rec_of_recrem(struct tchk_t *otcp)
+{
+ struct tchk_t *ntcp;
+
+ ntcp = (struct tchk_t *) __my_malloc(sizeof(struct tchk_t));
+ __init_tchk(ntcp, TCHK_RECOVERY);
+ ntcp->tc_recofrecrem = TRUE;
+ /* notice the 2 halves share symbol and handled specially in mod copy */
+ ntcp->tcsym = otcp->tcsym;
+ /* reverse edges */
+ ntcp->startedge = otcp->chkedge;
+ ntcp->chkedge = otcp->startedge;
+
+ /* copy start reference event expr. from check */
+ if (otcp->startxp != NULL) ntcp->chkxp = __copy_expr(otcp->startxp);
+ if (otcp->startcondx != NULL)
+  ntcp->chkcondx = __copy_expr(otcp->startcondx);
+
+ /* copy start reference event expr. from check */
+ if (otcp->chkxp != NULL) ntcp->startxp = __copy_expr(otcp->chkxp);
+ if (otcp->chkcondx != NULL)
+  ntcp->startcondx = __copy_expr(otcp->chkcondx);
+ /* point first delay to master hold and get delay (1st) from there */
+ ntcp->tclim_du.pdels = (struct paramlst_t *) otcp;
+
+ /* notice this is intra module so can just copy - becomes net */
+ ntcp->ntfy_np = otcp->ntfy_np;
+ return(ntcp);
+}
+
+/*
+ * emit unused informs for all parameters and specparams
+ */
+extern void __emit_param_informs(void)
+{
+ register int32 pi;
+ register struct net_t *np;
+ register struct task_t *tskp;
+ 
+ for (pi = 0; pi < __inst_mod->mprmnum; pi++)
+  {
+   np = &(__inst_mod->mprms[pi]);
+   if (!np->n_isaparam || np->nu.ct->n_onrhs) continue; 
+
+   __gfinform(451, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+    "in %s: parameter %s unused", __inst_mod->msym->synam, np->nsym->synam);
+  }
+
+
+ for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  { 
+   for (pi = 0; pi < tskp->tprmnum; pi++)
+    {
+     np = &(tskp->tsk_prms[pi]);
+     if (!np->n_isaparam || np->nu.ct->n_onrhs) continue; 
+
+     __gfinform(451, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+      "in %s.%s: parameter %s unused", __inst_mod->msym->synam,
+      tskp->tsksyp->synam, np->nsym->synam);
+    }
+  }
+
+ if (__no_specify || __inst_mod->mspfy == NULL) return; 
+ for (pi = 0; pi < __inst_mod->mspfy->sprmnum; pi++)
+  {
+   np = &(__inst_mod->mspfy->msprms[pi]);
+   /* DBG remove --- */
+   if (!np->n_isaparam) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   if (np->nu.ct->n_onrhs) continue; 
+
+   __gfinform(452, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+    "in %s: specparam %s unused", __inst_mod->msym->synam, np->nsym->synam);
+  }
+}
+
+/*
+ * free specify
+ * this can only be called be prep of specify section called
+ */
+extern void __free_specify(struct mod_t *mdp)
+{
+ struct spfy_t *spfp;
+
+ spfp = mdp->mspfy;
+ if (spfp->spfsyms != NULL) free_frozen_symtab(spfp->spfsyms);
+ if (spfp->spcpths != NULL) free_spcpths(spfp->spcpths);
+ if (spfp->tchks != NULL) __free_tchks(spfp->tchks);
+ if (spfp->msprms != NULL) free_spcparms(spfp->msprms, spfp->sprmnum);
+}
+
+/*
+ * free specify section paths
+ */
+static void free_spcpths(struct spcpth_t *pthp)
+{
+ register int32 pi;
+ struct pathel_t *pep;
+ struct spcpth_t *pthp2;
+
+ for (; pthp != NULL;)
+  {
+   pthp2 = pthp->spcpthnxt;
+   /* normal case free as fixup to path elements */
+   if (!pthp->pth_as_xprs)
+    {
+     /* first mark all path source and destination wires as non paths */ 
+     for (pi = 0; pi <= pthp->last_pein; pi++)
+      { pep = &(pthp->peins[pi]); pep->penp->n_isapthsrc = FALSE; }
+     for (pi = 0; pi <= pthp->last_peout; pi++)
+      { pep = &(pthp->peouts[pi]); pep->penp->n_isapthdst = FALSE; }
+
+     /* next delete the path range arrays */
+     if (pthp->last_pein >= 0) __my_free((char *) pthp->peins,
+      (pthp->last_pein + 1)*sizeof(struct pathel_t)); 
+     if (pthp->last_peout >= 0) __my_free((char *) pthp->peouts,
+      (pthp->last_peout + 1)*sizeof(struct pathel_t)); 
+    }
+   else
+    {
+     /* freeing before fixup must free expr. list */
+     __free_xprlst((struct exprlst_t *) pthp->peins);
+     __free_xprlst((struct exprlst_t *) pthp->peouts);
+    }
+   /* free does nothing if nil */
+   __free_dellst(pthp->pth_du.pdels);
+   __free_xtree(pthp->datasrcx);
+   __free_xtree(pthp->pthcondx);
+
+   __my_free((char *) pthp, sizeof(struct spcpth_t)); 
+   pthp = pthp2;
+  }
+}
+
+/*
+ * free timing checks
+ */
+extern void __free_tchks(struct tchk_t *tcp)
+{
+ struct tchk_t *tcp2;
+
+ for (; tcp != NULL;) 
+  {
+   tcp2 = tcp->tchknxt;
+   /* notice freeing null expr. is ok, does nothing */
+   /* and for setup of setuphold and recovery of recrem these are copied */
+   __free_xtree(tcp->startxp);
+   __free_xtree(tcp->startcondx);
+   __free_xtree(tcp->chkxp);
+   __free_xtree(tcp->chkcondx);
+   /* but delays shared (not copied) with hold of setup hold - can't free */
+   if (!tcp->tc_supofsuphld && !tcp->tc_recofrecrem)
+    {
+     __free_dellst(tcp->tclim_du.pdels);
+     __free_dellst(tcp->tclim2_du.pdels);
+    }
+   /* must not free symbol for ntfy_np */
+   __my_free((char *) tcp, sizeof(struct tchk_t)); 
+   tcp = tcp2;
+  }
+}
+
+/*
+ * free specify parameters - passing spec param (net) table
+ */
+static void free_spcparms(struct net_t *nptab, int32 pnum)
+{
+ register int32 pi;
+ struct net_t *np;
+ struct ncomp_t *ncomp;
+
+ /* first free insides */ 
+ for (pi = 0; pi < pnum; pi++) 
+  {
+   np = &(nptab[pi]);
+   /* nothing inside net but comp union to free (at fixup time) */
+   ncomp = np->nu.ct;
+   /* just free the expressions since if arg. nil does nothing */
+   __free_xtree(ncomp->nx1);
+   __free_xtree(ncomp->nx2);
+   __free_xtree(ncomp->ax1);
+   __free_xtree(ncomp->ax2);
+   /* will free the ncomp in blocks later */
+   /* SJM 03/29/99 - no list - only one value (maybe min:nom:max) */
+   __free_xtree(ncomp->n_dels_u.d1x);
+  }
+ /* then free entire block */
+ __my_free((char *) nptab, pnum*sizeof(struct net_t));
+}
+
+/*
+ * free 1 frozen symbol table
+ */
+static void free_frozen_symtab(struct symtab_t *sytp)
+{
+ register int32 syi;
+ struct sy_t *syp;  
+
+ /* may be dummy symbol table */
+ if (sytp->numsyms == 0) return;
+
+ if (sytp->stsyms == NULL) __misc_terr(__FILE__, __LINE__);
+ for (syi = 0; syi < (int32) sytp->numsyms; syi++)
+  {
+   /* frozen form is array of ptrs to symbols */
+   syp = sytp->stsyms[syi]; 
+   /* notice must leave symbol names even though not accessible */
+   __my_free((char *) syp, sizeof(struct sy_t)); 
+  }
+ __my_free((char *) sytp->stsyms,
+  (int32) (sytp->numsyms*sizeof(struct sy_t *)));
+ __my_free((char *) sytp, sizeof(struct symtab_t));
+}
diff --git a/src/v_ms.c b/src/v_ms.c
new file mode 100644
index 0000000..acdb4c2
--- /dev/null
+++ b/src/v_ms.c
@@ -0,0 +1,7263 @@
+/* Copyright (c) 1986-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * miscellaneous routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pwd.h> 
+
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <time.h>
+#include <setjmp.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+/* REMOVEME - no longer supporting SunOS - maybe needed for hpux? */
+#if defined(__sparc) && !defined(__SVR4)  
+extern int32 tolower(int32);
+extern ungetc(int32 c, FILE *);
+extern long time (long *);
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static char *expand_arg_macro(struct sy_t *, int32 *);
+static void process_macdef(void);
+static void dmp_macdef_exptab(char *, struct macexp_t *);
+static void process_macundef(void);
+static char *bld_macdef_arglist(int32 *);
+static char *remchk_macdef_coms(char *);
+static struct macexp_t *bld_mac_expandtab(char *, char *, int32);
+static int32 find_mac_formal_arg(char *);
+static void free_macexplst(register struct macexp_t *);
+static void do_argmacdefine(char *, struct macexp_t *, int32);
+static int32 cskip_ifdef_section(FILE *, int32);
+static int32 my_getc(FILE *);
+static int32 rd_comment(FILE *);
+static int32 skipto_attr_end(FILE *); 
+static void rd_attribute(FILE *);
+static int32 vgetstr(FILE *);
+static void str_tovval(void);
+static void unget2_vtok(int32);
+static int32 rd_num(FILE *, int32);
+static void rem_lead_0chars(char *);
+static int32 voverwhite(FILE *, register int32);
+static int32 chlen_to_bitlen(int32, int32);
+static void chg_abwrklen(int32);
+static void to_dec(int32 *);
+static void wide_strtoverdec(int32);
+static void to_bin(int32);
+static void to_oct(int32);
+static void to_hex(int32);
+static int32 vnum_toowide(word32 *, int32);
+static int32 nibblexz(word32, word32, int32);
+static int32 octdigxz(word32 *, word32 *, int32);
+static void widen_val(word32 *, int32, int32, word32);
+static char *prt2_vtok(int32);
+static int32 get_vkeywrd(register char *);
+static int32 set_syncto_tokclass(byte);
+static int32 set_specitem_class(void);
+static int32 set_udpsyncto(byte);
+static int32 get_cfgkeywrd(char *);
+static int32 get_cmdcomment(FILE *);
+static void one_rot(struct tnode_t *, struct tnode_t *, struct tnode_t *);
+static void two_rot(struct tnode_t *, struct tnode_t *, struct tnode_t *);
+static struct tnode_t *alloc_tnode(struct symtab_t *);
+static char *__to_nppsubtyp(char *, word32);
+static char *decompnum_to_str(char *, char *, int32, int32);
+static char *nfbig_alloc(int32);
+static char *tilde_expand(char *, int32 *);
+static char *pv_stralloc2(char *);
+static int32 try_chg_tononesc(void);
+static int32 ch_tobits(word32 *, word32 *, int32);
+static int32 ch_toocts(word32 *, word32 *, int32);
+static int32 ch_tohexs(word32 *, word32 *, int32);
+
+/* extern prototypes (maybe defined in this module) */
+extern void __get_vtok(void);
+extern int32 __chk_beg_line(int32);
+extern void __collect_line(void);
+extern void __skipover_line(void);
+extern void __do_macdefine(char *, char *);
+extern int32 __bqline_emptytail(register char *);
+extern void __do_include(void);
+extern int32 __rd_ialine(void);
+extern int32 __get1_vtok(FILE *);
+extern void __vstr_to_vval(word32 *, char *, int32);
+extern struct xstk_t *__cstr_to_vval(char *);
+extern void __unget_vtok(void);
+extern int32 __to_base(int32);
+extern int32 __is_vdigit(int32, int32);
+extern void __to_dhboval(int32, int32);
+extern char *__prt_vtok(void);
+extern char *__to_opname(word32);
+extern char *__get_vkeynam(char *, int32);
+extern int32 __vskipto_modend(int32);
+extern int32 __vskipto2_modend(int32, int32);
+extern int32 __vskipto3_modend(int32, int32, int32);
+extern int32 __vskipto_any(int32);
+extern int32 __vskipto2_any(int32, int32);
+extern int32 __vskipto3_any(int32, int32, int32);
+extern int32 __vskipto4_any(int32, int32, int32, int32);
+extern int32 __spec_vskipto_any(int32);
+extern int32 __spec_vskipto2_any(int32, int32);
+extern int32 __spec_vskipto3_any(int32, int32, int32);
+extern int32 __udp_vskipto_any(int32);
+extern int32 __udp_vskipto2_any(int32, int32);
+extern int32 __udp_vskipto3_any(int32, int32, int32);
+extern int32 __get_cmdtok(FILE *);
+extern struct sy_t *__get_sym_env(char *);
+extern struct sy_t *__find_sym(char *);
+extern struct sy_t *__decl_sym(char *, struct symtab_t *);
+extern void __add_sym(char *, struct tnode_t *);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern struct tnode_t *__vtfind(char *, struct symtab_t *);
+extern struct sy_t *__zget_sym(char *, struct sy_t **, word32);
+extern struct symtab_t *__alloc_symtab(int32);
+extern int32 __ip_indsrch(char *);
+extern char *__to_idnam(struct expr_t *);
+extern char *__to_mpnam(char *, char *);
+extern int32 __fr_wtnam(int32);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_wtnam2(char *, word32);
+extern char *__to_ptnam(char *, word32);
+extern char *__to_splt_nam(char *, int32);
+extern word32 __fr_stren_nam(int32);
+extern char *__to_stren_nam(char *, int32, int32);
+extern char *__to_stval_nam(char *, word32);
+extern char *__to1_stren_nam(char *, int32, int32);
+extern int32 __is_capstren(int32);
+extern int32 __fr_cap_size(int32);
+extern word32 __to_cap_size(int32);
+extern char *__to_sytyp(char *, word32);
+extern char *__to_tsktyp(char *, word32);
+extern char *__to_sttyp(char *, word32);
+extern char *__to_qctyp(char *, word32);
+extern char *__to_tetyp(char *, word32);
+extern char *__to_npptyp(char *, struct net_pin_t *);
+extern char *__to_deltypnam(char *, word32);
+extern char *__to_tcnam(char *, word32);
+extern int32 __fr_tcnam(char *);
+extern char *__to_gonam(char *, struct gate_t *, word32);
+extern char *__to_ginam(char *, struct gate_t *, word32, int32);
+extern char *__to_vnam(char *, word32, word32);
+extern char *__to_vvstnam(char *, word32);
+extern char *__to_vvnam(char *, word32);
+extern char *__to_uvvnam(char *, word32);
+extern char __to_baselet(int32);
+extern char *__to_timunitnam(char *, word32);
+extern char *__to_edgenam(char *, word32);
+extern char *__to_dcenam(char *, word32);
+extern char *__pv_stralloc(char *);
+extern char *__my_malloc(int32);
+extern void __my_free(char *, int32);
+extern char *__my_realloc(char *, int32, int32);
+extern void __my_fclose(FILE *);
+extern void __my_rewind(FILE *);
+extern int32 __tilde_open(char *, int32);
+extern FILE *__tilde_fopen(char *, char *);
+extern FILE *__my_fopen(char *, char *);
+extern int32 __tilde_creat(char *);
+extern int32 __my_creat(char *);
+extern char *__schop(char *, char *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern void __init_sy(struct sy_t *);
+
+extern void __crit_msg(char *, ...);
+extern void __sysfatal_msg(char *, ...);
+extern void __cv_msg(char *, ...);
+extern void __cvsim_msg(char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __misc_terr(char *, int32);
+extern void __misc_fterr(char *, int32);
+extern void __misc_gfterr(char *, int32, word32, int32);
+extern void __misc_sgfterr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __arg_terr(char *, int32);
+extern void __pv_terr(int32, char *, ...);
+extern void __fterr(int32, char *, ...);
+extern void __sgfterr(int32, char *, ...);
+extern void __gfterr(int32, word32, int32, char *, ...);
+extern void __pv_err(int32, char *, ...);
+extern void __pv_ferr(int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __ia_err(int32, char *, ...);
+extern void __via_err(int32, char *, va_list, va_list);
+extern void __pv_warn(int32, char *, ...);
+extern void __pv_fwarn(int32, char *, ...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __gfwarn(int32, word32, int32, char *, ...);
+extern void __ia_warn(int32, char *, ...);
+extern void __via_warn(int32, char *, va_list, va_list);
+extern void __inform(int32, char *, ...);
+extern void __finform(int32, char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __gfinform(int32, word32, int32, char *, ...);
+extern int32 __em_suppr(int32);
+extern void __my_fprintf(FILE *, char *, ...);
+extern void __my_vfprintf(FILE *, char *, va_list, va_list);
+extern void __vpi_error_trycall(void);
+extern void __cberror_fill_einfo(int32, int32, char *, char *, int32);
+
+extern int32 __pop_vifstk(void);
+extern int32 __open_sfil(void);
+extern void __push_vinfil(void);
+extern void __grow_infils(int32);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern double __my_strtod(char *, char **, int32 *);
+extern word32 __my_strtoul(char *, char **, int *);
+extern int32 __trim1_0val(word32 *, int32);
+extern void __lmult(register word32 *, register word32 *, register word32 *, int32);
+extern void __ladd(word32 *, word32 *, word32 *, int32);
+extern void __lhsbsel(register word32 *, register int32, word32);
+extern void __lhspsel(register word32 *, register int32, register word32 *, register int32);
+extern void __rhspsel(register word32 *, register word32 *, register int32, register int32);
+extern void __my_exit(int32, int32);
+extern char *__to_timstr(char *, word64 *);
+extern int32 __notokenize_skiplines(char *);
+extern char *__to_dispst_str(char *, word32);
+
+
+extern struct opinfo_t __opinfo[];
+extern byte __stren_map_tab[];
+extern word32 __masktab[];
+
+/* system stuff */
+extern int32 errno;
+
+/* jmp buf defined in v_dbg */
+extern jmp_buf __iact_jmpbuf;
+extern char __pv_ctab[];
+
+/*
+ * ROUTINES THE INTERFACE TO GET TOKEN ROUTINES
+ */
+
+/*
+ * get a Verilog token (outer routine for macro handling)
+ *
+ * routine sets globals __toktyp and __token and may set other for numbers
+ * (modified from yylex in "The Unix Programming Environment" p. 337)
+ *
+ * BEWARE - need to be careful here because for efficiency using global 
+ * strings ok to use __xs but not call prt2_vtok more than once in error
+ */
+extern void __get_vtok(void)
+{
+ int32 ttyp, ifdtyp, len, savlin_cnt;
+ struct sy_t *syp, *tmpsyp;
+ char *chp;
+
+ /* assume no attribute prefix */
+ __attr_prefix = FALSE; 
+ if (__lasttoktyp != UNDEF)
+  {
+   __toktyp = __lasttoktyp;
+   strcpy(__token, __lasttoken);
+   __lasttoktyp = UNDEF;
+   /* SJM 10/16/00 - must save and restore state of pending attr prefix */
+   /* seen when token is pushed back - happens for endmodule then read of */
+   /* module to check for EOF */
+   __attr_prefix = __last_attr_prefix;
+
+   /* extremely rare number push back case */
+   if (__toktyp == NUMBER)
+    {
+     word32 wlen; 
+
+     __itokbase = __lastitokbase;
+     __itoksized = __lastitoksized;
+     __itoksizdflt = __lastitoksizdflt;
+     __itok_signed = __lastitok_signed;
+     __itoklen = __lastitoklen;
+
+     /* used malloc to save const value, now need to restore and free */
+     wlen = wlen_(__itoklen);
+     memcpy(__acwrk, __lastacwrk, wlen*WRDBYTES);
+     __my_free((char *) __lastacwrk, wlen*WRDBYTES);
+     memcpy(__bcwrk, __lastbcwrk, wlen*WRDBYTES);
+     __my_free((char *) __lastbcwrk, wlen*WRDBYTES);
+     __lastacwrk = __lastbcwrk = NULL;
+    }
+   else if (__toktyp == REALNUM)
+    {
+     __itokbase = __lastitokbase;
+     __itoksized = __lastitoksized;
+     __itoksizdflt = __lastitoksizdflt;
+     __itok_signed = __lastitok_signed;
+     __itoklen = __lastitoklen;
+     __itok_realval = __lastitok_realval;
+    }
+   return;
+  }
+
+vtagain:
+ /* file will be NULL when reading from macro text */
+ switch ((byte) (ttyp = __get1_vtok(__in_s))) {
+  case TEOF:
+   /* first try to pop some sort of outer nested thing */
+   if (__pop_vifstk())
+    {
+     /* SJM 06/22/00 - for 2 stage 2 tok num - ready to read 2nd tok of num */ 
+     if (__macro_sep_width)
+      {
+       __maybe_2tok_sized_num = TRUE;
+       __macro_sep_width = FALSE;
+      }
+     goto vtagain;
+    }
+   /* next try to replace just finished 0th element with new input file */
+   if (__cur_infi + 1 > __last_inf || __iact_state)
+    { __toktyp = TEOF; return; }
+   __cur_infi++; 
+   if (!__open_sfil()) { __toktyp = TEOF; return; }
+   /* know first token of file flag now on */
+   goto vtagain;
+  case CDIR_DEFINE:
+   /* on return - know all of line read */
+   process_macdef();
+   goto vtagain;
+  case CDIR_UNDEF:
+   process_macundef();
+   goto vtagain;
+  case CDIR_INCLUDE:
+   if (__iact_state)
+    {
+illegal_iact_dir:
+     __ia_err(1401, "%s compiler directive illegal in interactive commands",
+      prt2_vtok(ttyp));
+     __skipover_line();
+     goto vtagain;
+    }
+   /* on return all of line read - trims tail of line for file name */ 
+   if (!__chk_beg_line(CDIR_INCLUDE)) goto vtagain;
+   /* collect line into mac wr kstrafter first skips white space to token */
+   __collect_line();
+   __do_include();
+   goto vtagain;
+  case CDIR_IFDEF: case CDIR_IFNDEF: 
+   if (__iact_state) goto illegal_iact_dir;
+   ifdtyp = ttyp;
+   if (!__chk_beg_line(ifdtyp)) goto vtagain;
+   /* see if token `defined */
+   savlin_cnt = __lin_cnt;
+   if ((ttyp = __get1_vtok(__in_s)) != ID)
+    {
+     /* BEWARE */
+     /* must use get vkeynam for compile directive (know only 2 possible) */
+     /* because prt2_vtok uses fixed storage */
+     __pv_ferr(923, "%s not followed by text macro name - %s read",
+      __get_vkeynam(__xs, ifdtyp), prt2_vtok(ttyp));
+     goto skip_rest;
+    }
+   if (*__token == '`')
+    {
+     __pv_fwarn(570,
+      "%s text macro name %s should not begin with ` - dropped",
+      __get_vkeynam(__xs, ifdtyp), __token);
+     strcpy(__xs, __token);
+     goto skip_rest;
+    } 
+   else { strcpy(&(__xs[1]), __token); __xs[0] = '`'; }
+   if (savlin_cnt != __lin_cnt)
+    {
+     __pv_ferr(921, "%s text macro name must be on same line",
+      __get_vkeynam(__xs, ifdtyp));
+     unget2_vtok(ttyp);
+     /* to get here know moved to next line */
+     goto vtagain;
+    }
+   __in_ifdef_level++;
+   /* notice for macro with args. here still just use name */
+   tmpsyp = __get_sym(__xs, __pv_defsyms);
+
+   /* undeclare when macro undefed because no way to remove from symtab */
+   if (tmpsyp != NULL && !tmpsyp->sydecl) tmpsyp = NULL;
+
+   /* `ifndef reverses sense of `ifdef - following C preprocessor */
+   if ((ifdtyp == CDIR_IFDEF && tmpsyp == NULL)
+    || (ifdtyp == CDIR_IFNDEF && tmpsyp != NULL))
+    {
+     /* case 1: `ifdef symbol not defined (i.e. if fails) */
+     if (cskip_ifdef_section(__in_s, ifdtyp) == CDIR_ENDIF)
+      {
+       /* if this is `endif just skipped `ifdef (or `ifndef) so continue */
+       /* if else enter look for else state */
+       __in_ifdef_level--;
+      }
+     /* `else or `endif read and processed when get to here */ 
+     /* know if end with `else, will be ready to include `else lines */
+     /* if this is `endif get an actual token */
+     goto vtagain;
+    }
+   /* case 2: symbol defined - continue getting tokens to `else or endif` */
+skip_rest:
+   /* must always skip over rest of line */
+   __skipover_line();
+   goto vtagain;
+  case CDIR_ELSE:
+   if (__iact_state) goto illegal_iact_dir;
+   if (!__chk_beg_line(CDIR_ELSE)) goto vtagain;
+   /* know ifdef was true - this is end and need to skip */
+   if (__in_ifdef_level == 0)
+    {
+     __pv_ferr(924, "`else read but no previous matching initial `ifdef");
+     goto skip_rest;
+    }
+   /* if skip to another else, this will emit error and continue */
+   /* know can only return with `endif */
+   cskip_ifdef_section(__in_s, CDIR_ELSE);
+   __in_ifdef_level--;
+   /* this will have consumed `endif line */ 
+   goto vtagain;
+  case CDIR_ENDIF:
+   if (__iact_state) goto illegal_iact_dir;
+   if (!__chk_beg_line(CDIR_ENDIF)) goto vtagain;
+   __skipover_line();
+   /* think this can never happen */
+   if (__in_ifdef_level == 0)
+    {
+     __pv_ferr(925, "`endif read but no previous matching initial `ifdef");
+     goto vtagain;      
+    }
+   __in_ifdef_level--;
+   /* else just up one nested ifdef level */
+   goto vtagain;
+  /* SJM 09/18/99 - these need to be supported inside modules */
+  case CDIR_ENDPROTECT:
+  case CDIR_ENDPROTECTED:
+  case CDIR_PROTECT:
+  case CDIR_PROTECTED:
+   __pv_fwarn(619, "directive %s unimplemented", prt2_vtok(ttyp));
+   __skipover_line();
+   goto vtagain;
+  /* notice time scale can only appear outside modules*/
+  case ID:
+   /* user redefinition of compiler directive overwrites keyword */
+   if (*__token == '$') goto ret_id;
+
+   if (*__token == '`')
+    {
+     if ((syp = __get_sym(__token, __pv_defsyms)) == NULL || !syp->sydecl)
+      {
+       __pv_fwarn(654,
+        "text macro %s undefined or possibly compiler directive for other tool - ignored",
+        __token);
+       goto vtagain;
+      }
+     if (!syp->sy_argsmac)
+      { 
+       chp = syp->el.edfchp;
+       /* `define macros can be empty from +define+ command arg */
+       if (strcmp(chp, "") == 0) goto vtagain;
+       len = -1;  
+      } 
+     else 
+      {
+       int32 sav_first_num_eol;
+
+       /* save first tok state, if `xx expands to compiler dir. must be 1st */
+       /* 2 stage num eol in get 1 vtok sets first of line */ 
+       if (__first_linetok) sav_first_num_eol = TRUE;
+       else sav_first_num_eol = FALSE;
+
+       /* expand into malloced storage setting length to len */
+       /* this may unget TEOF token */
+       chp = expand_arg_macro(syp, &len);
+       __first_num_eol = sav_first_num_eol;
+       if (chp == NULL) goto vtagain;
+      }
+     /* if currently reading file, must preserve line count */
+     if (__visp->vi_s != NULL) __visp->vilin_cnt = __lin_cnt;
+     /* push string on top of read stack */
+     __push_vinfil();
+     __visp->vichp = __visp->vichp_beg = chp;
+     __visp->vichplen = len;
+     __in_s = NULL;
+     /* DBG remove --- */
+     if (__debug_flg)
+      __dbg_msg("macro %s value [%s]\n", syp->synam, chp);
+     /* --- */
+     goto vtagain;
+    }
+ret_id:
+   __file_just_op = FALSE;
+   __toktyp = ID;
+   break;
+  default:
+   /* if this is not directive, must indicate not at start of file */
+   if (ttyp < CDIR_TOKEN_START || ttyp > CDIR_TOKEN_END)
+    __file_just_op = FALSE;
+   __toktyp = ttyp;
+   break;
+  }
+ /* SJM 06/22/00 - using 2 state 2 token number - finished by here */ 
+ __maybe_2tok_sized_num = FALSE;
+ /* DBG remove --
+ if (__debug_flg)
+  {
+   if (__toktyp == ID) __dbg_msg("++ returning token %s [%d]\n", __token,
+    __toktyp);
+   else __dbg_msg("++ returning token %s [%d]\n", __prt_vtok(), __toktyp);
+  }
+ --- */
+}
+
+/* macro for adding char and growing mac wrk str */
+#define addto_macwrkstr_(c) \
+ do { \
+  int32 osize; \
+  if (++len >= __macwrklen - 1) \
+   { \
+    osize = __macwrklen; \
+    __macwrklen += IDLEN; \
+    __macwrkstr = __my_realloc(__macwrkstr, osize, __macwrklen); \
+    chp = &(__macwrkstr[len - 1]); \
+   } \
+  *chp++ = (c); \
+ } while (0)
+
+/*
+ * expand a macro with arguments 
+ *
+ * collects , (...) list which may have syntax errors into mac work string
+ * list cannot cross macro or include but can contain white space
+ * build array of args that are malloced using __macwrkstr
+ * processing within argument () special char not token scanning  
+ * reads ending ) then stops reading 
+ *
+ * notice sections of text with unmatched ) or , are illegal since
+ * in Verilog \ escapes an identifier
+ */
+static char *expand_arg_macro(struct sy_t *syp, int32 *explen)
+{
+ register int32 c;
+ register char *chp, *chp2;
+ int32 ttyp, par_cnt, setb_cnt, setb_err, last_argno, last_i, len;
+ struct amac_t *amacp;
+ struct macexp_t *mxp;
+ struct macarg_t *macap, *macap2, *maca_hdr, *maca_end, **mactab;
+
+ *explen = -1;
+ if ((ttyp = __get1_vtok(__in_s)) != LPAR)
+  {
+   __pv_ferr(1270, "%s macro argument list ( expected - %s read",
+    syp->synam, prt2_vtok(ttyp));
+   unget2_vtok(ttyp);
+   return(NULL);
+  } 
+ /* get each argument first into mac wrk str then alloc */
+ /* argument is string before next non nested , or ) */
+ macap = maca_end = maca_hdr = NULL;
+ for (c = -1, last_argno = 0;; last_argno++)
+  {
+   setb_err = FALSE;
+   par_cnt = setb_cnt = 0;
+   for (chp = __macwrkstr, len = 0;;)
+    {
+     c = my_getc(__in_s);
+     switch (c) {   
+      case EOF:
+eof_err:
+       __pv_ferr(1295,
+        "%s macro argument no. %d **EOF** read before argument ending , or )",
+        syp->synam, last_argno); 
+       /* must put back eof */
+       my_ungetc_(c, __in_s);
+       /* allow memory leak on syntax eof error */ 
+       return(NULL);
+      case '(': par_cnt++; break;
+      case ')': 
+       /* if this is extra ) must end - error if in concat */
+       if (par_cnt == 0)
+        {
+         if (setb_cnt > 0)
+          __pv_ferr(1296,
+          "%s macro argument no. %d list ending ) found but concatenate not ended",
+          syp->synam, last_argno); 
+         goto arg_end;
+        }
+       par_cnt--;
+       break;
+      case '{': setb_cnt++; break;
+      case '}': 
+       if (setb_cnt == 0 && !setb_err)
+        {
+         __pv_ferr(1297,
+          "%s macro argument no. %d list nested concatenate illegal - too many }s",
+          syp->synam, last_argno); 
+         setb_err = TRUE;
+        }
+       else setb_cnt--;
+       break;
+      case ',': 
+       if (par_cnt == 0 && setb_cnt == 0) goto arg_end; 
+       break;
+      /* copy all chars in quoted string - vgetstr used later to scan */ 
+      case '"':
+       addto_macwrkstr_(c);
+       for (;;) 
+        {
+         c = my_getc(__in_s);
+         /* must not end on escaped " */
+         if (c == '\\') { addto_macwrkstr_(c); c = my_getc(__in_s); }  
+         else if (c == '"') break;
+
+         if (c == EOF) goto eof_err;  
+         /* here collect embedded new line, error later */
+         if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
+         addto_macwrkstr_(c);
+        }
+       break;
+      /* copy from escape through white space since maybe esc. id */ 
+      /* no escaping inside escaped ID */
+      case '\\': 
+       addto_macwrkstr_(c);
+       for (;;) 
+        {
+         c = my_getc(__in_s);
+         if (c == EOF) goto eof_err;
+         if (vis_white_(c)) break;
+         addto_macwrkstr_(c);
+        }
+       break;
+     }
+     if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
+     addto_macwrkstr_(c);
+    }
+arg_end:
+   *chp = '\0';
+   macap = (struct macarg_t *) __my_malloc(sizeof(struct macarg_t));
+   macap->macargnam = __pv_stralloc(__macwrkstr);
+   macap->macargnxt = NULL;
+   if (maca_end == NULL) maca_hdr = maca_end = macap;
+   else maca_end->macargnxt = macap;
+   maca_end = macap;
+   if (c == ')') break;
+  }
+ /* convert argument list to table for look up from sym mac exp. tab */
+ mactab = (struct macarg_t **)
+  __my_malloc((last_argno + 1)*sizeof(struct macarg_t *)); 
+ for (last_i = -1, macap = maca_hdr; macap != NULL; macap = macap->macargnxt)
+  mactab[++last_i] = macap;
+ /* DBG remove */
+ if (last_i != last_argno) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ amacp = syp->el.eamacp;
+ if (last_i + 1 != amacp->num_formal_args)
+  { 
+   __pv_ferr(1298,
+    "%s macro requires %d formal arguments - %d present", syp->synam,
+    amacp->num_formal_args, last_i + 1);
+   chp2 = NULL;
+   goto done;
+  }
+ /* do the expansion */
+ chp = __macwrkstr;
+ for (len = 0, mxp = amacp->amxp; mxp != NULL; mxp = mxp->macexpnxt)
+  {
+   /* copy into chp the leading string */
+   for (chp2 = mxp->leading_str; *chp2 != '\0'; chp2++)
+    addto_macwrkstr_(*chp2);
+   /* copy the actual argument, -1 for none (trailing part) */
+   if (mxp->ins_argno != -1)
+    {
+     for (chp2 = mactab[mxp->ins_argno]->macargnam; *chp2 != '\0'; chp2++)
+      addto_macwrkstr_(*chp2);
+    } 
+  }
+ *chp = '\0';
+ chp2 = __my_malloc(len + 1);
+ strcpy(chp2, __macwrkstr);
+ *explen = len;
+
+ /* final step - free actual arg list */
+done:
+ for (macap = maca_hdr; macap != NULL;)
+  {
+   macap2 = macap->macargnxt;  
+   __my_free((char *) macap->macargnam, strlen(macap->macargnam) + 1); 
+   __my_free((char *) macap, sizeof(struct macarg_t));
+   macap = macap2;
+  }
+ maca_hdr = NULL;
+ __my_free((char *) mactab, (last_argno + 1)*sizeof(struct macarg_t *)); 
+ return(chp2);
+}
+
+/*
+ * process one `define macro define
+ * know `define read and consumes entire line
+ * notice macro name must be in symbol table with `
+ */
+static void process_macdef(void)
+{
+ int32 ttyp, has_err, savlin_cnt, nargs, c, space_before_lpar;
+ char *mactxt_chp, dnam[IDLEN];
+ struct macexp_t *mxp;
+
+ if (!__chk_beg_line(CDIR_DEFINE)) return;
+ savlin_cnt = __lin_cnt;
+ has_err = FALSE;
+ if ((ttyp = __get1_vtok(__in_s)) != ID)
+  {
+   __pv_ferr(922, "`define not followed by text macro identifier - %s read",
+    prt2_vtok(ttyp));
+   has_err = TRUE;
+  }
+ /* need to use get token that does not know about line breaks */
+ if (__lin_cnt != savlin_cnt)
+  {
+   __pv_ferr(929, "`define text macro identifier name must be on same line");
+   unget2_vtok(ttyp);
+   return;
+  }
+ if (!has_err && __token[0] == '`')  
+  {
+   __pv_ferr(1291,
+    "`define text macro identifier name %s cannot begin with `", __token);
+   has_err = TRUE; 
+  }
+ if (!has_err) { strcpy(dnam, "`"); strcat(dnam, __token); }
+ /* always collect entire line (with possible escaped nl) into mac wrk str */
+  
+ c = my_getc(__in_s); 
+ /* if white space collect will skip anyway - no need to unget */
+ if (vis_nonnl_white_(c)) space_before_lpar = TRUE;
+ else
+  {
+   space_before_lpar = FALSE;
+   my_ungetc_(c, __in_s);
+  }
+ __collect_line();
+
+ /* if problem with definition but saw `define return after line read */
+ if (has_err) return;
+
+ if (get_vkeywrd(dnam) != ID)
+  {
+   __pv_ferr(1293,
+    "macro name %s conflicts with predefined directive - redefinition illegal",
+    dnam);
+   return;
+  }
+
+ /* if has argument build list and return start of body in mac wrk str */ 
+ /* returns nil if error (it emits the message) */
+ /* SJM - 01/31/00 - now for arg macros ( must be next char (no intervening white space) */   
+ /*                  otherwise ( treated as grouping param */
+ if (!space_before_lpar && __macwrkstr[0] == '(')
+  { 
+   /* build the global formal argument list and skip over it */
+   if ((mactxt_chp = bld_macdef_arglist(&nargs)) == NULL) return;
+
+   /* remove all comments macro and replace multiple white space with 1 sp */
+   /* also remove trailing white space */
+   /* this replaces value in mac wrk str - will always be no longer */
+   if ((mactxt_chp = remchk_macdef_coms(mactxt_chp)) == NULL) return;
+
+   /* if expands to empty (could be some white space) make one space */ 
+   if ((mxp = bld_mac_expandtab(dnam, mactxt_chp, nargs)) == NULL)
+    { strcpy(__macwrkstr, " "); goto do_nonarg; }
+   do_argmacdefine(dnam, mxp, nargs);
+   if (__debug_flg) dmp_macdef_exptab(dnam, mxp);
+  }
+ else
+  {
+do_nonarg:
+   /* SJM - 01/31/00 - continue to support old escaped scheme */
+   if (__macwrkstr[0] == '\\' && __macwrkstr[1] == '(')
+    mactxt_chp = &(__macwrkstr[1]);
+   else mactxt_chp = __macwrkstr;
+   if ((mactxt_chp = remchk_macdef_coms(mactxt_chp)) == NULL) return;
+   __do_macdefine(dnam, mactxt_chp);
+   if (__debug_flg) 
+    __dbg_msg("+++ text macro %s defined with value [%s]\n", dnam,
+     mactxt_chp);
+  }
+}
+
+/*
+ * dump the arg. macro expansion table for debugging
+ */
+static void dmp_macdef_exptab(char *dnam, struct macexp_t *mxp)
+{
+ int32 argno;
+
+ __dbg_msg("+++ arg text macro %s defined - expands from:\n", dnam);
+ for (argno = 1; mxp != NULL; mxp = mxp->macexpnxt, argno++)
+  {
+   __dbg_msg("    arg. %d: prefix [%s] insert actual %d\n", 
+    argno, mxp->leading_str, mxp->ins_argno);
+  }
+ __dbg_msg("+++ end of formal args +++\n");
+}
+
+/*
+ * undefine a macro
+ */
+static void process_macundef(void)
+{
+ int32 ttyp, has_err, savlin_cnt;
+ struct sy_t *syp;
+ char dnam[IDLEN];
+
+ if (!__chk_beg_line(CDIR_UNDEF)) return;
+ savlin_cnt = __lin_cnt;
+ has_err = FALSE;
+ if ((ttyp = __get1_vtok(__in_s)) != ID)
+  {
+   __pv_ferr(922, "`undef required text macro identifier missing - %s read",
+    prt2_vtok(ttyp));
+   has_err = TRUE;
+  }
+ /* need to use get token that does not know about line breaks */
+ if (__lin_cnt != savlin_cnt)
+  {
+   __pv_ferr(929, "`undef text macro identifier name must be on same line");
+   unget2_vtok(ttyp);
+   return;
+  }
+ if (!has_err && __token[0] == '`')  
+  {
+   __pv_ferr(1291,
+    "`undef text macro identifier name %s cannot begin with `", __token);
+   has_err = TRUE; 
+  }
+ if (!has_err) { strcpy(dnam, "`"); strcat(dnam, __token); }
+ __skipover_line();
+ if (has_err) return;
+
+ if (get_vkeywrd(dnam) != ID)
+  {
+   __pv_ferr(1293,
+    "`undef of macro name %s illegal - cannot `undef predefined directive",
+    dnam);
+   return;
+  }
+
+ if ((syp = __get_sym(dnam, __pv_defsyms)) == NULL || !syp->sydecl)
+  {
+   __pv_fwarn(655, "`undef of %s does nothing - macro not defined", dnam);
+   return;
+  }
+ if (syp->sy_argsmac)
+  {
+   free_macexplst(syp->el.eamacp->amxp);
+   __my_free((char *) syp->el.eamacp, sizeof(struct amac_t));
+   syp->sy_argsmac = FALSE;
+  }
+ else __my_free(syp->el.edfchp, strlen(syp->el.edfchp) + 1);
+ syp->el.edfchp = __pv_stralloc("");
+ syp->sydecl = FALSE;
+}
+
+/*
+ * return F and emit error if not at beginning of line
+ * tricky case if first token file_just_op - this is really first token
+ * in line but flag will be off - check for case and if found must turn
+ * off file just open - if this check not called will get turned off
+ * normally.
+ *
+ * problem here is caused by Verilog semantics that treat compiler directives
+ * as having \n as token but in normal code not a token
+ */
+extern int32 __chk_beg_line(int32 cdtyp)
+{
+ /* ---
+ if (__iact_state)
+  { 
+   __ia_err(1401,
+    "compiler directives illegal in interactive commands - %s read",
+    __get_vkeynam(__xs, cdtyp));
+   return(FALSE); 
+  }
+ --- */
+ if (!__first_linetok) 
+  {
+   if (__file_just_op) { __file_just_op = FALSE; return(TRUE); }
+   else __pv_ferr(928, "compiler directive %s must be first token on line",
+    __get_vkeynam(__xs, cdtyp));
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * collect a line into mac wrk str first skip over all leading white space
+ * notice white space inside line kept and line can be arbitrarily long
+ * with possible escaped new lines 
+ * 
+ * this sets length of used part of macro line
+ * this can be arbitrarily long for mulitple line macros
+ */
+extern void __collect_line(void)
+{
+ register int32 c;
+ register char *chp;
+ int32 len;
+
+ for (;;) { c = my_getc(__in_s); if (!vis_nonnl_white_(c)) break; }
+ if (c == '\n' || c == EOF)
+  {
+   *__macwrkstr = '\0';
+   my_ungetc_(c, __in_s);
+   return;
+  } 
+ for (chp = __macwrkstr, len = 0;;)
+  {
+   /* \\n is line continuation and must become ' ' in macro string line */
+   /* anything else added is part of escaped id */
+   if (c == '\\') 
+    {
+     if ((c = my_getc(__in_s)) == '\n') { c = ' '; __lin_cnt++; }
+     else { my_ungetc_(c, __in_s); c = '\\'; }
+    }
+   addto_macwrkstr_(c);
+   c = my_getc(__in_s);
+   if (c == '\n' || c == EOF) { my_ungetc_(c, __in_s); break; }
+  }
+ /* notice trailing new line or eof removed */
+ *chp = '\0';
+ __mac_line_len = len;
+}
+
+/*
+ * skip over characters to a new line (skip ending or error stuff)
+ * know current char never new line
+ * this also skips over \\[newline]
+ *
+ * not counted as part of total source lines since skipped from ` conds
+ */ 
+extern void __skipover_line(void)
+{
+ register int32 c;
+
+ for (;;)
+  {
+   if ((c = my_getc(__in_s)) == '\n' || c == EOF) break;
+   if (c == '\\')
+    {
+     /* \\n is just white space not end of line but \\EOF is still eof */
+     if ((c = my_getc(__in_s)) == EOF) break;
+     /* not counting continuation lines in total */
+     if (c == '\n') __lin_cnt++;
+    }
+  }
+ if (c != EOF) { my_ungetc_(c, __in_s); };
+}
+
+/*
+ * read a line into passed string
+ */
+extern int32 __my_getlin(register char *lp)
+{
+ register int32 c, len;
+
+ for (len = 0;;)
+  {
+   c = my_getc(__in_s);
+   if (++len >= IDLEN)
+    {
+     __pv_ferr(2889, "`language section line too long (%d) - truncated",
+      IDLEN - 1);
+    }
+   else *lp++ = c; 
+   if (c == '\n' || c == EOF) break;
+  }
+ *lp = '\0';
+ return(c);
+}
+
+/*
+ * build the formal arg list and skip over 
+ * passed with mac wrk str pointing to leading ( 
+ * returns ptr to one after ending ) or nil if error 
+ *
+ * FIXME make table larger so can be 8 bit clean 
+ */
+static char *bld_macdef_arglist(int32 *nargs)
+{
+ register char *chp;
+ char *chp2, *chp3;
+ int32 argno, arglen, toolong;
+ struct macarg_t *marp, *macarg_end;
+ char argnam[IDLEN];
+ 
+ *nargs = 0;
+ chp = &(__macwrkstr[1]);
+ __macarg_hdr = NULL;
+ macarg_end = NULL;
+ for (argno = 1;; argno++)
+  {
+   toolong = FALSE;
+   /* skip white space before arg */
+   while (vis_nonnl_white_(*chp)) chp++;
+   /* format argument can start with _ but not ` or $ */
+   /* digit can be in id but not start it */
+   if (__pv_ctab[(*chp & 0x7f)] != 0 || isdigit(*chp) || *chp == '$')
+    {
+     __pv_ferr(1292,
+      "text macro formal argument %d identifier expected - %c read - if non argument macro, add ' ' before (",
+      argno, *chp);
+     /* on error just do not define macro */
+     return(NULL);
+    }
+   arglen = 1;
+   chp2 = chp++;
+   chp3 = NULL;
+   /* collect the chars in the formal name */  
+   while(__pv_ctab[(*chp & 0x7f)] == 0)
+    {
+     if (++arglen >= IDLEN - 1)
+      {
+       if (!toolong)
+        {
+         __pv_ferr(944, 
+          "text macro formal argument has too many characters (%d)",
+          IDLEN - 1);
+         toolong = TRUE;
+         /* end is 1 past end where \0 will go */
+         chp3 = chp;
+        }
+      }
+     chp++;
+    }
+   if (chp3 == NULL) chp3 = chp; 
+   strncpy(argnam, chp2, chp3 - chp2);
+   argnam[chp3 - chp2] = '\0'; 
+   marp = (struct macarg_t *) __my_malloc(sizeof(struct macarg_t));
+   marp->macargnam = __pv_stralloc(argnam);
+   marp->macargnxt = NULL;
+   if (macarg_end == NULL) __macarg_hdr = macarg_end = marp; 
+   else macarg_end->macargnxt = marp;
+   macarg_end = marp;
+   /* maybe skip white space */ 
+   while (vis_nonnl_white_(*chp)) chp++;
+   if (*chp == ')') break;
+   if (*chp == ',') { chp++; continue; } 
+   /* wrong separator */
+   __pv_ferr(1294,
+    "text macro formal argument %d not followed by , or ) - char %c read",
+    argno, *chp);
+   return(NULL);
+  }
+ chp++;
+ /* notice something like "`define aa(a,b) )()(" is legal, err later */
+ *nargs = argno;
+ return(chp);
+}
+
+/*
+ * remove any comments from macro body copy then build macwrkstr
+ * error and return F if / * comment or string not completed
+ *
+ * only here for macro def. bodies, // \[escaped nl] is removed comment
+ * / * can span escaped new lines - and always left as escaped in output
+ * mchp must always point into mac wrk str
+ *
+ * this copies into temp and then puts back in macro string
+ */
+static char *remchk_macdef_coms(char *mchp)
+{
+ register char *chp, *nchp;
+ int32 llen, first_time;
+ char *newwrkstr, *start_mchp;
+
+ /* macro text starts with non white */
+ while(vis_nonnl_white_(*mchp)) mchp++;
+ start_mchp = mchp;
+
+ /* region to allocate does not include possible args */
+ llen = __mac_line_len - (mchp - __macwrkstr);  
+ /* will never be wider but may be same length */
+ newwrkstr = __my_malloc(llen + 1);
+ 
+ for (first_time = TRUE, chp = mchp, nchp = newwrkstr; *chp != '\0';)
+  {
+   /* replace string of white space with one space */
+   if (vis_nonnl_white_(*chp))
+    {
+     if (!first_time) *nchp++ = ' ';
+     chp++;
+     while(vis_nonnl_white_(*chp)) chp++;
+    }
+   first_time = FALSE;
+
+   switch (*chp) {
+    case '/':
+     /* handle comments - no quoted strings in comments */ 
+     chp++;
+     /* remove // comment - can go to end of area (real nl or esc. nl) */
+     if (*chp == '/') 
+      { 
+       chp++;
+       while (*chp != '\0')   
+        {
+         /* both of these better be removed by collect line */
+         if (*chp == '\n' || *chp == EOF) __misc_terr(__FILE__, __LINE__);
+         chp++;
+        }
+       /* now skipped to end of // comment */
+       *nchp = '\0';
+       goto at_end;
+      }
+     /* remove / * comment - error if hit end of string */ 
+     if (*chp == '*') 
+      {
+       chp++;
+       while (*chp != '*')
+        {
+         if (*chp == '\n' || *chp == EOF) __misc_terr(__FILE__, __LINE__);
+         if (*chp == '\0')
+          {
+           __pv_ferr(930, 
+            "*/ in `define macro line without initial /* comment start");
+           __my_free(newwrkstr, llen + 1);
+           return(NULL);
+          }
+         if (*chp == '/' && chp[1] == '*')
+          {
+           __pv_fwarn(622, "nested /* in macro body /* style comment");
+          }
+         /* skip any escaped chars - can not end comment */ 
+         if (*chp == '\\') { chp++; chp++; }
+         chp++;
+        }
+       chp++;
+       if (*chp == '/') { *nchp++ = ' '; chp++; continue; }
+       break;
+      }
+     /* simple / so must keep in line */
+     *nchp++ = '/';
+     break;
+    /* must copy any non white space escape and char */
+    case '\\':
+     /* escaped nl becomes space */
+     if (chp[1] == '\n') { chp++; chp++; *nchp++ = ' '; break; }
+     *nchp++ = *chp++;
+     if (*chp == '\0')
+      {
+       __pv_ferr(931,
+        "`define macro line ends with \\ - following escaped char required");
+       return(NULL);
+      }
+     /* must copy any escaped char as is - cannot have any meaning */
+     *nchp++ = *chp++; 
+     break; 
+    case '\0': goto at_end; 
+    case '"':
+     *nchp++ = *chp++;
+     while (*chp != '"')
+      {
+       if (*chp == '\\') *nchp++ = *chp++;
+       if (*chp == '\0')
+        {
+         __pv_ferr(932,
+          "`define macro contains unterminated string - not defined"); 
+         return(NULL);
+        }
+       *nchp++ = *chp++;
+      }
+     /* exit and copy " */     
+   }
+   *nchp++ = *chp++;
+  }
+at_end:
+ /* remove trailing white space */
+ for (;;)
+  { 
+   if (nchp == newwrkstr) break;
+   nchp--; 
+   if (!vis_white_(*nchp)) { nchp++; break; }
+  }
+ *nchp = '\0';
+
+ /* DBG remove --- */ 
+ if (nchp - newwrkstr > llen) __misc_terr(__FILE__, __LINE__); 
+ /* --- */  
+ strcpy(mchp, newwrkstr);
+ __mac_line_len = (mchp - __macwrkstr) + (nchp - newwrkstr);
+ __my_free(newwrkstr, llen + 1);
+ return(start_mchp);
+}
+
+/*
+ * process an argument macro definition 
+ * know mac arg hdr global point to formal argument list
+ *
+ * know working out of collected line so new line impossible
+ * expand arguments anywhere but within strings 
+ * know all comments changed to 1 space and multiple white space to 1 space
+ * also know all quoted strings completed
+ * LOOKATME - is it true this cannot fail
+ */
+static struct macexp_t *bld_mac_expandtab(char *dnam, char *dval, int32 nargs)
+{
+ register char *chp;
+ register int32 andx;
+ register struct macarg_t *marp;
+ byte *argutab;
+ struct macexp_t *mxp, *mxp_hdr, *mxp_end;
+ char *startchp, *startid, idnam[IDLEN];
+
+ argutab = (byte *) __my_malloc(nargs);
+ memset(argutab, 0, nargs);
+ mxp_hdr = mxp_end = NULL;
+ startchp = dval;
+ for (chp = dval; *chp != '\0';)
+  {
+   /* skip leading white space */ 
+   while (vis_nonnl_white_(*chp)) chp++; 
+
+   /* always skip quoted strings */
+   if (*chp == '"')
+    {
+     chp++;
+     /* must not match escaped quote */
+     while (*chp != '"')
+      {
+       if (*chp == '\0')
+        {  
+         __pv_ferr(932,
+          "macro %s value contains unterminated string - macro undefined",
+          dnam); 
+         return(NULL);
+        }
+       if (*chp == '\\') chp++;
+       chp++;
+      }
+     chp++;
+     continue;
+    }
+   /* if identifier or keyword remove and build record, else just skip */ 
+   if (__pv_ctab[(*chp & 0x7f)] == 0 && (!isdigit(*chp) || *chp == '`'))
+    {
+     startid = chp;
+     chp++;  
+     while(__pv_ctab[(*chp & 0x7f)] == 0) chp++;
+     /* see if this is formal argument */
+     strncpy(idnam, startid, chp - startid);
+     idnam[chp - startid] = '\0';
+     /* if does not match left in literal copy part and at next char */
+     if ((andx = find_mac_formal_arg(idnam)) == -1) continue;
+     argutab[andx] = 1;
+     /* this is formal */
+     mxp = (struct macexp_t *) __my_malloc(sizeof(struct macexp_t)); 
+     mxp->leading_str = __my_malloc(startid - startchp + 1);
+     strncpy(mxp->leading_str, startchp, startid - startchp);
+     mxp->leading_str[startid - startchp] = '\0';
+     mxp->leadlen = startid - startchp;
+     mxp->ins_argno = andx;
+     mxp->macexpnxt = NULL;
+     if (mxp_end == NULL) mxp_hdr = mxp_end = mxp;
+     else mxp_end->macexpnxt = mxp;
+     mxp_end = mxp;
+     /* reset fill to one after ID */ 
+     startchp = chp;
+     continue;
+    }
+   chp++;
+  }
+ for (andx = 0, marp = __macarg_hdr; andx < nargs; andx++,
+  marp = marp->macargnxt)
+  {
+   if (argutab[andx] == 0)
+    {
+     __pv_fwarn(640,
+      "%s macro definition formal argument %s (no. %d) not used in macro body", 
+      dnam, marp->macargnam, andx);
+    }
+  }
+ __my_free((char *) argutab, nargs);
+ argutab = NULL;
+
+ /* unless value is empty include trailing chars */
+ /* if totally empty value, make it one space */ 
+ if (chp == startchp && mxp_end == NULL)
+  {
+   __pv_fwarn(638, "argument macro %s expands to nothing - use `undef", dnam);
+   return(NULL);
+  }
+ if (chp == startchp) return(mxp_hdr); 
+
+ /* add the ending prefix with no argument to expand in */
+ mxp = (struct macexp_t *) __my_malloc(sizeof(struct macexp_t)); 
+ mxp->leading_str = __my_malloc(chp - startchp + 1);
+ strncpy(mxp->leading_str, startchp, chp - startchp);
+ mxp->leading_str[chp - startchp] = '\0';
+ mxp->ins_argno = -1;
+ mxp->macexpnxt = NULL;
+ if (mxp_end == NULL) mxp_hdr = mxp_end = mxp;
+ else mxp_end->macexpnxt = mxp;
+ return(mxp_hdr);
+}
+
+/*
+ * search an formal argument list to match a legal ID name
+ * returns nil if not found
+ */
+static int32 find_mac_formal_arg(char *argnam)
+{
+ register int32 anum;
+ register struct macarg_t *marp;
+
+ anum = 0;
+ for (marp = __macarg_hdr; marp != NULL; marp = marp->macargnxt, anum++)
+  { if (strcmp(marp->macargnam, argnam) == 0) return(anum); }
+ return(-1);
+}
+
+/*
+ * define a text macro named dnam with value dval
+ * this looks up in symbol table and stores "" ok and used for `ifdef 
+ * dval here is really rest of line that may be ""
+ */
+extern void __do_macdefine(char *dnam, char *dval)
+{
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+
+ tnp = __vtfind(dnam, __pv_defsyms);
+ /* now add the symbol */
+ if (__sym_is_new)
+  {
+   /* allocate symbol and fill symbol */
+   __add_sym(dnam, tnp);
+   __pv_defsyms->numsyms++;
+   syp = tnp->ndp;
+   syp->sytyp = SYM_DEF;
+   syp->sydecl = TRUE;
+  }
+ else
+  {
+   syp = tnp->ndp;
+   /* if `define follows undef just define - no message */
+   if (syp->sydecl)
+    {
+     if (syp->sy_argsmac)
+      {
+       __finform(415,
+        "textmacro name %s redefined - previous but not new had args", dnam);
+        free_macexplst(syp->el.eamacp->amxp);
+       __my_free((char *) syp->el.eamacp, sizeof(struct amac_t));
+       syp->sy_argsmac = FALSE;
+      }
+     else
+      {
+       __finform(415,
+        "textmacro name %s redefined - neither has arguments", dnam);
+       __my_free(syp->el.edfchp, strlen(syp->el.edfchp) + 1);
+      }
+    }
+   /* if was undefined now defined */
+   syp->sydecl = TRUE;
+  }
+ syp->el.edfchp = __pv_stralloc(dval);
+}
+
+/*
+ * free an args macro expand list 
+ */
+static void free_macexplst(register struct macexp_t *mxp)
+{
+ register struct macexp_t *mxp2;
+
+ for (; mxp != NULL;)
+  {
+   mxp2 = mxp->macexpnxt;
+   __my_free(mxp->leading_str, mxp->leadlen + 1);
+   __my_free((char *) mxp, sizeof(struct macexp_t));
+   mxp = mxp2;
+  }
+}
+
+/*
+ * define a text macro with arguments named dnam with value dval
+ * and macro subsitution list macp
+ *
+ * this looks up in symbol table and stores "" ok and used for `ifdef 
+ * dval here is really rest of line that may be ""
+ * illegal conflicts with predefined compiler directives caught before here
+ */
+static void do_argmacdefine(char *dnam, struct macexp_t *mxp, int32 nformal_args)
+{
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+
+ tnp = __vtfind(dnam, __pv_defsyms);
+ /* now add the symbol */
+ if (__sym_is_new)
+  {
+   /* allocate symbol and fill symbol */
+   __add_sym(dnam, tnp);
+   __pv_defsyms->numsyms++;
+   syp = tnp->ndp;
+   syp->sytyp = SYM_DEF;
+   syp->sy_argsmac = TRUE;
+   syp->sydecl = TRUE;
+   syp->el.eamacp = (struct amac_t *) __my_malloc(sizeof(struct amac_t));
+  }
+ else
+  {
+   syp = tnp->ndp;
+   if (syp->sydecl)
+    {
+     if (syp->sy_argsmac)
+      {
+       __finform(415,
+        "textmacro name %s redefined - previous and new have args",
+        dnam);
+       free_macexplst(syp->el.eamacp->amxp);
+      }
+     else
+      {
+       __finform(415,
+        "textmacro name %s redefined - only new has args", dnam);
+       __my_free(syp->el.edfchp, strlen(syp->el.edfchp) + 1);
+       syp->el.eamacp = (struct amac_t *) __my_malloc(sizeof(struct amac_t));
+      }
+    }
+   syp->sydecl = TRUE;
+  }
+ syp->el.eamacp->amxp = mxp; 
+ syp->el.eamacp->num_formal_args = nformal_args;
+ syp->sy_argsmac = TRUE;
+}
+
+/*
+ * return F if remainder of line contains anything but comment
+ * know all white space has been removed before call
+ * if / * comment but be completed on line
+ * return T if good
+ */
+extern int32 __bqline_emptytail(register char *cp)
+{
+ for (; *cp != '\0'; cp++)
+  {
+   switch (*cp) {
+    case '/':
+     cp++;
+     if (*cp == '/') return(TRUE);
+     if (*cp == '*') 
+      {
+       /* in / *  comment */ 
+       for (cp++;; cp++)
+        {
+         if (*cp == '\0') return(FALSE);
+         if (*cp == '*')
+          {
+           cp++;
+           if (*cp == '/') goto nxt_white;
+           cp--;
+           continue;
+          }
+        }
+      }
+     continue;
+    case '\\': cp++; continue;
+    default: return(FALSE);
+   }
+nxt_white:;
+  }
+ return(TRUE);
+}
+
+/*
+ * do the new `include directive - entire line consumed
+ * must be called with file name (starting ") in token
+ */
+extern void __do_include(void)
+{
+ register int32 idi;
+ register char *cp;
+ int32 inflen, plen, space;
+ FILE *f;
+ struct incloc_t *ilp;
+ char *chp, incfnam[RECLEN], incpth[RECLEN];
+ struct sy_t *syp;
+
+ cp = __macwrkstr;
+ /* AIV 06/27/05 -  handle the special `include `FILE case */
+ if (*cp == '`')
+  {
+   /* strip the white space at the end of the line */
+   plen = strlen(cp) - 1;
+   space = FALSE;
+   for (idi = plen; idi >= 0; idi--) 
+    {
+     if (cp[idi] == ' ') 
+      {
+       space = TRUE;
+       cp[idi] = '\0';
+      }
+     else if (space) break;
+    }
+    /* find `define variable to ge the file name */
+   if ((syp = __get_sym(cp, __pv_defsyms)) == NULL || !syp->sydecl)
+    {
+     __pv_fwarn(937,
+      "`include name - text macro %s undefined or possibly compiler directive for other tool - ignored", cp);
+     return;
+    }
+  /* set the file name pointer */
+  cp = syp->el.edfchp;
+ }
+ chp = cp;
+ if (*chp != '"')
+  {
+bad_fnam:
+   __pv_ferr(937,
+    "`include name not surrounded by double quotation marks");
+   return;
+  } 
+ /* fill token to ending " - white space in file names ok */
+ for (chp++;; chp++)
+  { 
+   if (*chp == '\0') goto bad_fnam;
+   if (*chp == '"') break; 
+  } 
+ /* replace ending quotes with \0 */
+ *chp = '\0';
+ /* cp now points file name skipping the first char (") */
+ /* know not longer than 1024 because that is Verilog line length */
+ strcpy(incfnam, &(cp[1]));
+
+ if ((f = __tilde_fopen(incfnam, "r")) == NULL)
+  {
+   /* if file absolute, do not search incdir list */
+   /* AIV 09/15/04 - ./[name] form is relative not absolute */
+   if (incfnam[0] == '/' || incfnam[0] == '~') goto nonrel_notfnd; 
+
+   if (__last_incdir >= 0)
+    {
+     inflen = strlen(incfnam);
+     for (idi = 0; idi <= __last_incdir; idi++) 
+      {
+       plen = strlen(__incdirs[idi]) + inflen + 1;
+       if (plen >= RECLEN)
+        {
+         chp = __my_malloc(plen);
+         strcpy(chp, __incdirs[idi]); 
+         strcat(chp, incfnam);
+         __pv_fwarn(571,
+          "`include file +incdir+ path name %s too long (%d) - ignored", chp,
+           RECLEN); 
+         __my_free(chp, plen);
+         continue;
+        }
+       strcpy(incpth, __incdirs[idi]);
+       strcat(incpth, incfnam); 
+       /* DBG remove --
+       __cv_msg("*** attempting to open include path %s\n", chp);
+       --- */
+       if ((f = __tilde_fopen(incpth, "r")) != NULL)
+        { strcpy(incfnam, incpth); goto found_path; }
+      }
+     __pv_ferr(933,
+      "unable to open `include file %s - not found in any +incdir+", incfnam);
+     return;
+    }
+nonrel_notfnd:
+   __pv_ferr(933, "unable to open `include file %s", incfnam);
+   return;
+  }
+
+found_path:
+ /* add include file to file list for error messages */
+ /* __last_inf still used to find last non lib. input file */
+ /* this dies if >64k */
+ /* idea here is that initial build entire list of input then library files */
+ /* while process arguments - when reading includes put on end of file list */
+ /* so that contents can be read by debugger */
+ if (++__last_lbf >= __siz_in_fils) __grow_infils(__last_lbf);
+ __in_fils[__last_lbf] = __pv_stralloc(incfnam);
+
+ /* have good include file, add to include location list */
+ ilp = (struct incloc_t *) __my_malloc(sizeof(struct incloc_t));
+ /* link on end */
+ if (__inclst_hdr == NULL) __inclst_hdr = __inclst_end = ilp;  
+ else __inclst_end->inclocnxt = ilp;
+ ilp->inc_fnind = __last_lbf;
+ ilp->incfrom_fnind = __cur_fnam_ind;
+ ilp->incfrom_lcnt = __lin_cnt;
+ ilp->inclocnxt = NULL;
+
+ /* save current __lin_cnt before pushing */
+ if (__visp->vi_s != NULL) __visp->vilin_cnt = __lin_cnt;
+ /* push new file on tos */
+ __push_vinfil();
+ /* notice push sets __visp */
+ __visp->vifnam_ind = __last_lbf;
+ __visp->vi_s = __in_s = f;
+ __cur_fnam = __in_fils[__visp->vifnam_ind];
+ __cur_fnam_ind = __visp->vifnam_ind;
+ __lin_cnt = 1;
+ if (__lib_verbose || __verbose)
+  {
+   if (__doing_langdir)
+    {
+     __cv_msg("  Reading `included `language non Verilog file \"%s\"\n",
+      __cur_fnam);
+    }
+   else __cv_msg("  Compiling `included source file \"%s\"\n", __cur_fnam);
+  }
+ __file_just_op = TRUE;
+}
+
+/*
+ * skip to matching level else for `ifdef that is F
+ * this reads ending `endif or `else and it line
+ * returns -1 on not found error
+ *
+ * fortuntately never need to back up
+ * this has a bug that needs to be documented - in sections that are
+ * skipped only looks for match level `else or `endif - once starts skipping
+ * a down level `ifdef does not catch extra `else's  
+ * notice this routines only uses local variables
+ *
+ * FIXME - looks like if `end never found in infinite loop?
+ */
+static int32 cskip_ifdef_section(FILE *f, int32 begtok)
+{
+ int32 level, ttyp2, sav_lin_cnt;
+ int32 savfnam_ind;
+
+ /* ifdef must be on line by itself - anything treated as comment */
+ __skipover_line();
+ /* save the line count */
+ savfnam_ind = __cur_fnam_ind;
+ sav_lin_cnt = __lin_cnt;
+ /* SJM 12/04/00 - need flag when skipping for ifdef section to */
+ /* not emit rd num warnings since parameter substitution not right */
+ __ifdef_skipping = TRUE;
+ /* know reading stars after directive line */
+ for (level = 0;;)
+  {
+   switch ((byte) (ttyp2 = __get1_vtok(f))) {
+    case TEOF:
+     /* if finished include or macro expansion just continue reading tokens */
+     if (__pop_vifstk()) continue;
+
+     /* next try to replace just finished 0th element with new input file */
+     /* notice these can cross file boundaries - real eof is all files */
+     /* exhausted */
+     if (__cur_infi < __last_inf)
+      {
+       __cur_infi++;
+       if (__open_sfil()) continue;
+      }
+     /* for interactive can never get here since checking line begin fails */
+     /* notice control here always ends with fata error */
+     if (begtok == CDIR_IFDEF || begtok == CDIR_IFNDEF)
+      {
+       __pv_terr(313,
+        "`ifdef/`ifndef line %s - no matching `else or `endif before **EOF**",
+        __bld_lineloc(__xs, (word32) savfnam_ind, sav_lin_cnt));  
+      }
+     else
+      {
+       __pv_terr(313, "`else line %s - no matching `endif before **EOF**",
+        __bld_lineloc(__xs, (word32) savfnam_ind, sav_lin_cnt));  
+      }
+     continue;
+    case CDIR_IFDEF: case CDIR_IFNDEF: 
+     /* notice will not see if not 1st token of line */ 
+     if (__chk_beg_line(ttyp2)) level++;
+     __skipover_line();
+     continue;
+    case CDIR_ENDIF:
+     if (!__chk_beg_line(CDIR_ENDIF)) break;
+     __skipover_line();
+     /* SJM 12/04/00 - when done skipping now need to turn off flag */
+     /* flag needed because macros now alloed for number width */ 
+     if (level == 0)
+      { __ifdef_skipping = FALSE; return(CDIR_ENDIF); }
+     level--;
+     continue;
+    case CDIR_ELSE:
+     if (!__chk_beg_line(CDIR_ELSE)) break;
+     __skipover_line();
+     if (level == 0)
+      {
+       if (begtok == CDIR_ELSE)
+        {
+         __pv_ferr(1011,
+          "`else line %s - followed by same nesting level `else",
+          __bld_lineloc(__xs, (word32) savfnam_ind, sav_lin_cnt));  
+         /* keep looking for `endif */
+         continue;
+        }
+       __ifdef_skipping = FALSE;
+       return(CDIR_ELSE);
+      }
+     continue;
+    case CDIR_LANG:
+     /* here because can not tokenize included foreign language */ 
+     savfnam_ind = __cur_fnam_ind;
+     sav_lin_cnt = __lin_cnt;
+     if (__notokenize_skiplines("`endlanguage") == TEOF)
+      {
+       __pv_terr(328,
+        "skipped `language at %s in `ifdef/`ifndef no matching `endlanguage before **EOF**",
+       __bld_lineloc(__xs, (word32) savfnam_ind, sav_lin_cnt));  
+      }
+     break;
+    case CDIR_TIMESCALE:
+     /* SJM 12/02/99 - these require special scanning so can't just skip */
+     /* must read line and ignore it - know always first on line */
+     __skipover_line();
+     continue; 
+   }
+  }
+ /*UNREACHABLE*/
+ __ifdef_skipping = FALSE;
+ return(-1);
+}
+
+/*
+ * INTERACTIVE ENVIRONMENT GET TOKEN ROUTINES
+ */
+
+/*
+ * read an interactive line - must handle \[new line] escapes which
+ * are left in and treated as white space
+ *
+ * __iahwrkline grows but must start out at least IDLEN + 1 characters lone
+ * this returns TEOF on at eof and nothing in line (or error?)
+ * return TOK_NONE on good
+ *
+ * caller must handle key file and parsing tokenization of read line
+ * (command) and any adding to history list
+ * ending new line is removed
+ */
+extern int32 __rd_ialine(void)
+{
+ int32 len, totlen, osize, intr_num;
+ char *chp;
+ FILE *f;
+
+rd_again:
+ __iahwrkline[0] = '\0';
+ if (__cmd_s != NULL) { f = __cmd_s; __lin_cnt++; } else f = stdin;
+ if (feof(f)) return(TEOF);
+
+ for (totlen = 0;;)
+  {
+   /* will not return NULL if any chars read */
+   chp = &(__iahwrkline[totlen]);
+   /* when iact debugger run from pipe, under FlexLM may be interrupted */
+   /* and need to restart */
+   intr_num = 0;
+again2:  
+   clearerr(f);
+   if (fgets(chp, IDLEN + 1, f) == NULL)
+    {
+     if (++intr_num >= 512)
+      {
+       __ia_err(1450,
+        "interactive input call interrupted %d consecutive times - assuming EOF",
+        intr_num); 
+       break;
+      }
+     if (!feof(f) && errno == EINTR) goto again2;
+     if (feof(f) && errno == EINTR)
+      {
+       __ia_warn(1603,
+        "interactive input call interrupted (but EOF also seen?) - trying again");
+       goto again2;
+      }
+     if (ferror(f))
+      {
+       __ia_err(1460,
+        "interactive input call failed because: [%s] - assuming EOF", 
+        strerror(errno));
+      }
+     break;
+    }
+   if (__pending_enter_iact && __iact_reason == IAER_CTRLC)
+    {
+     __pending_enter_iact = FALSE;
+     __iact_reason = IAER_UNKN;
+     
+     if (__cmd_s == NULL) goto rd_again; 
+     /* ^c (interrupt signal) during $input interrupts and closes file */
+     __ia_err(1457,
+      "interactive $input file processing terminated by interrupt (^c)");
+     totlen = 0;
+     __iahwrkline[0] = '\0';
+     return(TEOF);
+    }
+
+   len = strlen(chp);
+   if (len >= IDLEN) 
+    {
+     __ia_err(1402, "interactive line too long (%d) - truncated", IDLEN - 1);
+     chp[IDLEN - 1] = '\0';  
+     break;
+    }
+   totlen += len;
+   /* know last char. always new line for fgets  - see if escaped */
+   if (chp[len - 2] != '\\') break;
+   /* if escaped keep reading but first see if need to grow work line */
+   if (totlen >= __iahwrklen - IDLEN - 4)  
+    {
+     osize = __iahwrklen;
+     __iahwrklen += IDLEN + 4;
+     __iahwrkline = __my_realloc(__iahwrkline, osize, __iahwrklen);
+    }
+   /* if (f != NULL) __lin_cnt++; */
+  }
+ if (totlen == 0) return(TEOF);
+ /* FIXME - lot file output only ?? */
+ if (__echo_iactcmds_tolog && __log_s != NULL)
+  __my_fprintf(__log_s, "%s", __iahwrkline);
+
+ /* final step change final unescaped new line to blank */ 
+ /* if not blank error such as omitted ; previous token not seen */
+ __iahwrkline[totlen - 1] = ' '; 
+ return(TOK_NONE);
+} 
+
+/*
+ * ACTUAL TOKENIZATION CODE
+ */
+
+/*
+ * ascii character table for processing end of ID tokens
+ * 0: continue - legal ID char (letter, digit, _, $)
+ * 1: end and don't back up (white space)
+ * 2: end and back up (operators plus special back quote)
+ * 3: inc lin_cnt and end - only new line
+ * 4: illegal ID char
+ *
+ * notice special handling of . - if 1st char after comma or white space,
+ * then dot part of .[name](port) for else . legal in ID, but can not
+ * be 1st char of id
+ * 0x24 is $ and 0x5f is _ both are legal starting and in IDs (value 0)
+ */
+char __pv_ctab[128] = {
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 3, 4, 1, 1, 4, 4, /* ^i,\n,\f,\r */
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ /* need to handle " */
+ 1, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* sp,!,%,#,(,),*,',+,-,.,/ */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, /* digits, :,;,<,=,>,? */
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @, cap letters */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, /* letters `,[,\\,],^, */
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* `, letters */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2  /* letters, {, |, },~,EOF */
+};
+
+/*
+ * get a Verilog token
+ * (modified from yylex in "The Unix Programming Environment" p. 337)
+ */
+extern int32 __get1_vtok(FILE *f)
+{
+ register int32 c, ctval;
+ register char *cp;
+ int32 c1, len, toolong;
+ int32 t1typ;
+
+again:
+ /* not first line token since always push back new line except number */
+ /* ending line required scan to make sure not ' */
+ if (__first_num_eol) { __first_linetok = TRUE; __first_num_eol = FALSE; }
+ else __first_linetok = FALSE;
+
+again3:
+ do { ctval = __pv_ctab[(c = my_getc(f)) & 0x7f]; } while (ctval == 1);
+ if (c == '\n')
+  {
+again2:
+   __lin_cnt++;
+   __total_rd_lines++;
+   do { ctval = __pv_ctab[(c = my_getc(f)) & 0x7f]; } while (ctval == 1);
+   if (c == '\n') goto again2; 
+   __first_linetok = TRUE;
+  }
+ switch (c) {
+  case ';': return(SEMI);
+  case ',': return(COMMA);
+  case ':': return(COLON);
+  case '#': return(SHARP);
+  case '(':
+   if ((c1 = my_getc(f)) != '*') { my_ungetc_(c1, f); return(LPAR); }
+
+   /* SJM 06/01/04 - for new @(*) form can't be attr - need to check */
+   /* spaces possible because something like @(`star ) is possible */
+   if (__canbe_impl_evctrl) { my_ungetc_(c1, f); return(LPAR); }
+
+   /* collect attribute into global string */
+   rd_attribute(f);
+   goto again;
+  case ')': return(RPAR);
+  case '[': return(LSB);
+  case ']': return(RSB);
+  case '{': return(LCB);
+  case '}': return(RCB);
+  /* notice dot can not start real number in Verilog - digit or sign only */
+  case '.': return(DOT);
+  case '?': return(QUEST);
+  case '@': return(AT);
+  case '=':
+   if ((c1 = my_getc(f)) != '=')
+    {
+     if (c1 == '>') return(PPTHCON);
+     my_ungetc_(c1, f);
+     return(EQ);
+    }
+   if ((c1 = my_getc(f)) != '=') { my_ungetc_(c1, f); return(RELEQ); }
+   return(RELCEQ);
+  case '\'':
+   return(rd_num(f, c));
+  case '+': return(PLUS);
+  case '-':
+   if ((c1 = my_getc(f)) != '>') { my_ungetc_(c1, f); return(MINUS); }
+   return(CAUSE);
+
+  case '0': case '1': case '2': case '3': case '4': case '5':
+  case '6': case '7': case '8': case '9':
+   return(rd_num(f, c));
+  case '*':
+   if ((c1 = my_getc(f)) != '>') { my_ungetc_(c1, f); return(TIMES); }
+   return(FPTHCON);
+  /* notice no C assignment op operators */
+  case '/':
+   if ((t1typ = rd_comment(f)) == UNDEF) goto again;
+   if (t1typ == TEOF) return(TEOF);
+   return(DIV);
+  case '%': return(MOD);
+  case '~':
+   /* notice ~& and ~| parse as 2 that must be unaries */
+   /* a ~| b is meaningless - since ~ is unary only */
+   /* but ~^ is alternative form of xnor (^~) */
+   if ((c1 = my_getc(f)) == '^') return(REDXNOR);
+   my_ungetc_(c1, f);
+   return(BITNOT);
+  case '&':
+   if ((c1 = my_getc(f)) != '&') { my_ungetc_(c1, f); return(BITREDAND); }
+   if ((c1 = my_getc(f)) != '&') { my_ungetc_(c1, f); return(BOOLAND); }
+   return(TCHKEVAND);
+  case '|':
+   if ((c1 = my_getc(f)) != '|') { my_ungetc_(c1, f); return(BITREDOR); }
+   return(BOOLOR);
+  /* also ^~ 2 unaries or bitwise xor of unary bit wise not */
+  case '^':
+   /* notice ^~ is not bit wise xor of bit wise negated unary result */
+   /* but special built in operator */
+   if ((c1 = my_getc(f)) == '~') return(REDXNOR);
+   my_ungetc_(c1, f);
+   return(BITREDXOR);
+  case '!':
+   if ((c1 = my_getc(f)) != '=') { my_ungetc_(c1, f); return(NOT); }
+   if ((c1 = my_getc(f)) != '=') { my_ungetc_(c1, f); return(RELNEQ); }
+   return(RELCNEQ);
+  case '>':
+   if ((c1 = my_getc(f)) == '=') return(RELGE);
+   else if (c1 == '>')
+    {
+     /* SJM 10/01/03 - add >>> arithmetic right shift */
+     if ((c1 = my_getc(f)) == '>') return(ASHIFTR);
+     my_ungetc_(c1, f);
+     return(SHIFTR);
+    }
+   my_ungetc_(c1, f);
+   return(RELGT);
+  case '<':
+   if ((c1 = my_getc(f)) == '=') return(RELLE);
+   else if (c1 == '<')
+    {
+     /* SJM 10/01/03 - add <<< arithmetic left shift */
+     if ((c1 = my_getc(f)) == '<') return(ASHIFTL);
+     my_ungetc_(c1, f);
+     return(SHIFTL);
+    }
+   my_ungetc_(c1, f);
+   return(RELLT);
+  case '\\':
+   /* escaped new line is white space and inc line counter */
+   /* removed from macro bodies */
+   if ((c1 = my_getc(f)) == '\n')
+    { __lin_cnt++; __total_rd_lines++; goto again3; } 
+   else { my_ungetc_(c1, f); }
+
+   /* handle escaped ID */
+   for (toolong = FALSE, len = 0, cp = __token;;)
+    {
+     /* should never happen since max. line is same as IDLEN */
+     if (++len >= IDCHARS - 1)
+      {
+       if (!toolong)
+        {
+         __pv_ferr(942,
+          "Verilog escaped identifier too many characters (%d)", IDCHARS - 2);
+          toolong = TRUE;
+        }
+      }
+     else *cp++ = c;
+
+     if ((c = my_getc(f)) == EOF) return(TEOF);
+     /* 3 is new line, 1 end and don't back up (white space) */
+     if ((ctval = __pv_ctab[c & 0x7f]) == 3) { my_ungetc_(c, f); break; }
+     if (ctval == 1) break;
+    }
+   /* lrm says trailing white space not part of escaped ID */
+   /* but must store space at end or name will not be output right */
+   *cp++ = ' '; 
+   *cp = '\0';
+   /* according to P1364 must store escaped that is legal as non escaped */ 
+   /* but can not escape keyword */
+   if (!try_chg_tononesc()) return(UNDEF);
+   return(ID);
+  case '"': return(vgetstr(f));
+  case EOF: return(TEOF);
+ }
+ /* here know digits eliminated so only letters, $, and _ have ct val 0 */
+ if (ctval != 0 && c != '`')
+  {
+   __pv_ferr(943, "identifier starts with illegal char '%c' (%x)", c & 0xff,
+    c & 0xff);
+   goto again;
+  }
+ /* try to recognize some kind of id - only */
+ for (toolong = FALSE, cp = __token, len = 0;;)
+  {
+   if (++len >= IDCHARS)
+    {
+     if (!toolong)
+      {
+       __pv_ferr(944, 
+        "Verilog identifier has too many characters (%d)", IDCHARS - 1);
+       toolong = TRUE;
+      }
+    }
+   else *cp++ = c;
+
+   c = my_getc(f);
+   if (__pv_ctab[c & 0x7f] == 0) continue;
+
+   /* must not process \n (3) until next time through */
+   /* or lin_cnt wrong for errors */
+   /* punctuation token end - unget it */
+   /* must always put back char after token since even if white space */
+   /* a .b .c is not xmr - even though think lrm says it is */
+   /* unget causes any error to be caught later */
+   my_ungetc_(c, f);
+   goto end_id;
+  }
+end_id:
+ *cp = '\0';
+ /* only keywords ($ system tasks are not keywords) can be in keyword table */
+ t1typ = get_vkeywrd(__token);
+ return(t1typ);
+}
+
+/*
+ * get character routine that can read from macro
+ */
+static int32 my_getc(FILE *f)
+{
+ register int32 c;
+
+again:
+ if (f == NULL)
+  {
+   c = *__visp->vichp;
+   /* for get ch from line form, must never move past \0 */
+   if (c == '\0') return(EOF);
+   (__visp->vichp)++;
+  }
+ else c = getc(f);
+
+ if ((__pv_ctab[c & 0x7f] == 4 || c > 127) && !__rding_comment && c != EOF)
+  {
+   __finform(416, "illegal non printable character (%x) ignored", c & 0xff);
+   goto again;
+  }
+ return(c);
+}
+
+/*
+ * get a comment
+ */
+static int32 rd_comment(FILE *f)
+{
+ register int32 c;
+ int32 c2;
+
+ /* // to EOL comment */
+ if ((c2 = my_getc(f)) == '/')
+  {
+   __rding_comment = TRUE;
+   while ((c = my_getc(f)) != '\n') if (c == EOF) return(TEOF);
+   __rding_comment = FALSE;
+   my_ungetc_(c, f);
+   return(UNDEF);
+  }
+ /* slash-star comments don't nest */
+ if (c2 == '*')
+  {
+more_comment:
+   __rding_comment = TRUE;
+   while ((c = my_getc(f)) != '*')
+    {
+     /* error if / * comments nested */
+     if (c == '/')
+      {
+       if ((c2 = my_getc(f)) == '*')
+        {
+         __pv_fwarn(622, "nested /* in /* style comment");
+         continue;
+        }
+       c = c2;
+      }
+     if (c == EOF)
+      {
+       if (__iact_state)
+        __pv_ferr(960,
+        "interactive /* comment cannot extend across multiple lines - */ added");
+       __rding_comment = FALSE;
+       return(TEOF);
+      }
+     if (c == '\n') { __lin_cnt++; __total_rd_lines++; } 
+    }
+got_star:
+   if ((c = my_getc(f)) == '/')
+    {
+     __rding_comment = FALSE;
+     return(UNDEF);
+    }
+   if (c == '*') goto got_star;
+   if (c == '\n') { __lin_cnt++; __total_rd_lines++; } 
+   goto more_comment;
+  }
+ /* not a comment so treat as name token */
+ /* notice c2 here must be most recent because above if never falls through */
+ my_ungetc_(c2, f);
+ return(DIV);
+}
+
+/* macro for adding char and growing attr wrk str */
+#define addto_attrwrkstr_(c) \
+ do { \
+  int32 osize; \
+  if (++len >= __attrwrklen - 1) \
+   { \
+    osize = __attrwrklen; \
+    __attrwrklen += IDLEN; \
+    __attrwrkstr = __my_realloc(__attrwrkstr, osize, __attrwrklen); \
+    chp = &(__attrwrkstr[len - 1]); \
+   } \
+  *chp++ = (c); \
+ } while (0)
+
+/*
+ * read an attribute char by char into a saved line
+ *
+ * know (* read and reading ending ) of *) 
+ * collected into attr wrk str - parsed later
+ *
+ * error if comments in attribute section
+ * since parsed in separate parser subroutine `ifdefs must be self contained
+ *
+ * LOOKATME - adding ; at end - not clear from grammar if required
+ *            assuming not for now
+ */
+static void rd_attribute(FILE *f)
+{
+ register char *chp;
+ int32 c, c2, len, wrk_fnam_ind, wrk_lin_cnt;
+
+ wrk_fnam_ind = __cur_fnam_ind;
+ wrk_lin_cnt = __lin_cnt;
+
+ for (chp = __attrwrkstr, len = 0;;)
+  {
+   c = my_getc(f);
+   if (c == EOF)
+    {
+hit_eof:
+     my_ungetc_(c, f);
+     __pv_ferr(940, "end of file read inside attribute_instance (* ... *)");
+     return; 
+    }
+   switch (c) { 
+    case '\\': 
+     /* escaped can't end or comment */ 
+     addto_attrwrkstr_(c);
+     c = my_getc(__in_s);
+     if (c == EOF) goto hit_eof;
+     if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
+     addto_attrwrkstr_(c);
+     continue;
+    case '"':
+     /* collect string to un-escaped " */
+     addto_attrwrkstr_(c);
+     for (;;)
+      {
+       if ((c = my_getc(f)) == EOF) goto hit_eof;
+       if (c == '\\')
+        {
+         /* always also both escape and char after */
+         addto_attrwrkstr_(c);
+         c = my_getc(__in_s);
+         if (c == EOF) goto hit_eof;
+         if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
+         addto_attrwrkstr_(c);
+         continue;
+        }
+       if (c == '"') { addto_attrwrkstr_(c); break; }
+       if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
+       if (c == '\n' || c == '\r')
+        {
+         __pv_ferr(945,
+          "string inside attribute_instance (* .. *) can not cross line boundary - must escape new line");
+         if ((c = skipto_attr_end(f)) == EOF) goto hit_eof;
+         return;
+        }
+       /* non speical char in string , just collect */ 
+       addto_attrwrkstr_(c);
+      }
+     continue;
+    case '/': 
+     addto_attrwrkstr_(c);
+     c = my_getc(f);
+     if (c == '/' || c == '*')
+      {
+       __pv_ferr(3402,
+        "/%c comment inside attribute_instance (* ... *) illegal - must be moved outside", c);
+       if ((c = skipto_attr_end(f)) == EOF) goto hit_eof;
+       return;
+      }
+     my_ungetc_(c, f);
+     continue;
+    case '(':
+     /* know starting (* read before proc called, this is ( inside */
+     addto_attrwrkstr_(c);
+     c = my_getc(f);
+     if (c == '*')
+      {
+       __pv_ferr(3403,
+        "atttribute start sequence (* illegal inside attribute_instance");
+      }
+     /* still include it */
+     my_ungetc_(c, f);
+     continue;
+    case '*':
+     /* do not include leading (* or ending *) */  
+     c2 = my_getc(f);
+     if (c2 == ')') goto done; 
+     addto_attrwrkstr_(c);
+     my_ungetc_(c2, f);
+     continue;
+    default:
+     addto_attrwrkstr_(c);
+   }
+  }
+done:
+ /* LOOKATME is semi required? */
+ chp--;
+ if (*chp != ';')
+  {
+   chp++;
+   addto_attrwrkstr_(';');
+  }
+ else chp++;
+ *chp = '\0'; 
+
+ /* length does not include added \0 */
+ __attr_line_len = len;
+ 
+ if (__attr_prefix)
+  {
+   __pv_ferr(3401,
+    "more than one attribute_instance in row - using last at %s instead of first at %s",
+    __bld_lineloc(__xs, (word32) wrk_fnam_ind, wrk_lin_cnt),
+    __bld_lineloc(__xs2, (word32) __attr_fnam_ind, __attr_lin_cnt));
+  }
+ __attr_fnam_ind = wrk_fnam_ind;
+ __attr_lin_cnt = wrk_lin_cnt;
+ __attr_prefix = TRUE;
+ /* DBG remove -- */
+ if (__debug_flg)
+  {
+   __dbg_msg("&&& at %s attribute_instance string [%s])\n",
+    __bld_lineloc(__xs, (word32) __attr_fnam_ind, __attr_lin_cnt),
+    __attrwrkstr);
+  }
+ /* --- */
+}
+
+/*
+ * skip to attribute ending *)
+ */
+static int32 skipto_attr_end(FILE *f) 
+{
+ register int32 c;
+
+ __attr_fnam_ind = 0;
+ __attr_lin_cnt = 0;
+ for (;;)
+  {
+   if ((c = my_getc(f)) == EOF) return(EOF);
+   switch (c) {
+    case '\\':
+     if ((c = my_getc(f)) == EOF) return(EOF);
+     continue;
+    case '"':
+     for (;;)
+      {
+       if ((c = my_getc(f)) == EOF) return(EOF);
+       if (c == '\\')
+        {
+         if ((c = my_getc(f)) == EOF) return(EOF);
+         continue;
+        }
+       if (c == '"') break;
+      }
+     continue;
+    case '*':
+     c = my_getc(f); 
+     if (c == ')') goto done;
+   } 
+   /* non special keep reading */
+  }
+done:
+ return(c); 
+}
+
+/*
+ * read a string token - Verilog string are wide numbers
+ * notice %% must be left here as 2 characters - processed by display
+ * also value collected in token is not a 0 terminated c string (no \0) 
+ */
+static int32 vgetstr(FILE *f)
+{
+ register char *cp;
+ int32 c, c1, len, toolong, nsize;
+
+ /* return string - should save length - Ver. strings not \0 terminated */
+ if ((c = my_getc(f)) == '"')
+  {
+   /* "" is special case of 8 bit 0 */
+   *__strtoken = '\0';
+   len = 1;
+   goto done;
+  }
+ for (toolong = FALSE, len = 0, cp = __strtoken;;)
+  {
+   switch (c) { 
+    case '\n': case '\r':
+     __pv_ferr(945,
+      "string cannot cross line boundary (new line must be escaped)");
+     goto done;
+    case '\\':
+     c1 = my_getc(f);
+     switch (c1) {
+      case 't': c = '\t'; break;
+      case 'n': c = '\n'; break;
+      case '\\': c = '\\'; break;
+      case '"': c = '"'; break;
+      case '0': case '1': case '2': case '3': case '4': case '5':
+      case '6': case '7':
+       /* c is escaped char value (octal) */
+       c = c1 - '0';
+       /* this always reads one past and puts back - read always pushed back */
+       c1 = my_getc(f);
+       if (isdigit(c1) && c1 != '8' && c1 != '9')
+        {
+         c = (c << 3) + c1 - '0';
+         c1 = my_getc(f);
+         if (isdigit(c1) && c1 != '8' && c1 != '9') c = (c << 3) + c1 - '0';
+         else my_ungetc_(c1, f);
+        }
+       else my_ungetc_(c1, f);
+       break;
+      default:
+       /* skip escape and use next char as is */
+       __pv_fwarn(555, "string \\ escaped character '%c' (%x) same as '%c'",
+        c1 & 0x7f, c1 & 0x7f, c1 & 0x7f);
+       c = c1;
+     }
+     break;
+    case '"': goto done;
+   }
+   /* should never happen since max. line is same as IDLEN - nd " room */
+   /* SJM 03/20/00 - now allow up to 1M length strings */
+   if (++len >= __numtok_wid)
+    {
+     if (len >= MAXNUMBITS) 
+      {
+       if (!toolong)
+        {
+         __pv_ferr(946, "string token has too many characters (%d)",
+   MAXNUMBITS - 1);
+         toolong = TRUE;
+       }
+      }
+     else
+      {
+       /* LOOKATME - SJM 03/20/00 - doubling may be too fast growth */
+       nsize = 2*__strtok_wid;
+       __numtoken = __my_realloc(__numtoken, __strtok_wid, nsize);
+       __strtok_wid = nsize;
+       *cp++ = c;
+      }
+    }
+   else *cp++ = c;
+
+   if ((c = my_getc(f)) == EOF)
+    {
+     if (__iact_state)
+      __pv_ferr(947, "interactive string terminator missing");
+     else __pv_ferr(947, "end of file read inside string");
+     strcpy(__strtoken, "");
+     len = 1;
+     goto done;
+    }
+   /* if (__debug_flg) __dbg_msg("&&& vgetstr read %c (%x)\n", c , c); */
+  }
+
+done:
+ /* except for expr. node string bit - this is now normal val. bit pattern */
+ /* assuming 8 bit bytes - on serious error len can be 0 */
+ if ((__itoklen = 8*len) == 0) __itoklen = 1;
+ /* string are actually sized token - must work in concatenates */
+ __itoksized = TRUE;
+ /* puts string into ac wrk and bc wrk - may adjust size */
+ str_tovval();
+ /* if (__debug_flg) __dbg_msg("&&& vgstrread [%s]\n", __strtoken); */
+ /* notice even though converted to value - can print input from __token */
+ return(LITSTR);
+}
+
+/*
+ * need to convert form escaped ID to normal if escaped (after \\ is legal)
+ * notice although '$' is a class 0 and can go in IDs, it can not start ID
+ */
+static int32 try_chg_tononesc(void) 
+{
+ register char *chp;
+ register int32 len, ctval;
+ char s1[IDLEN];
+
+ chp = __token;
+ /* move past escape */
+ chp++;  
+ for (len = 0; *chp != '\0'; chp++)
+  {
+   if ((ctval = __pv_ctab[*chp & 0x7f]) != 0)
+    {
+     if (ctval == 1 || ctval == 3)
+      {
+       /* if next is end of ID \0, then found legal non escaped */
+       if (chp[1] == '\0')
+        {
+         if (strcmp(__token, "\\ ") == 0)
+          {
+           __pv_ferr(942,
+     "Verilog escaped identifier empty - at least one non white space character required");
+           return(FALSE);
+          }
+
+         strcpy(s1, &(__token[1])); 
+         /* remove the ending white space char */
+         s1[len] = '\0';  
+         strcpy(__token, s1);
+         return(TRUE);
+        }
+      }  
+     return(TRUE);
+    }
+   /* first is one after escape this is present at entry */
+   /* SJM - 05/26/99 - fixed bug where \222 were getting un-escaped */
+   if (len == 0)
+    {
+     if (*chp == '$' || isdigit(*chp)) return(TRUE);
+     /* SJM-09/18/00- FIXME must not unescape or - need to handle as keywrd */
+     if (strcmp(chp, "or ") == 0) return(TRUE);
+    }
+   len++;
+  }
+ return(TRUE);
+}
+
+/*
+ * convert ascii user input string into ac wrk and bc wrk 
+ *
+ * notice __ac wrk and __bc wrk not necessarily contiguous
+ */
+static void str_tovval(void)
+{
+ register int32 wlen;
+
+ wlen = wlen_(__itoklen);
+ if (wlen > __abwrkwlen || (__abwrkwlen > DFLTIOWORDS && wlen <= DFLTIOWORDS))
+  chg_abwrklen(wlen);
+ zero_allbits_(__bcwrk, __itoklen);
+ __vstr_to_vval(__acwrk, __strtoken, __itoklen);
+}
+
+/*
+ * convert Verilog literal style string to a Verilog numeric value
+ * notice Verilog has built in 8 bit chars
+ * know ap wide enough and all bits zeroed before called here
+ * notice this has built in dependency on 32 bit words  
+ */
+extern void __vstr_to_vval(word32 *ap, char *s, int32 bitlen)
+{
+ register int32 i;
+ register int32 bi;
+ int32 slen;
+
+ slen = bitlen/8;
+ /* fill val from low char (right str) to high char (const left to right) */
+ for (i = slen - 1, bi = 0; i >= 0; i--)
+  {
+   if (bi == 0) *ap = (word32) s[i];
+   else *ap |= (((word32) s[i]) << bi);
+   if (bi == 24) { bi = 0; ap++; } else bi += 8;
+  }
+}
+
+/*
+ * convert c style string to Verilog value
+ * this pushes new v value onto stack
+ */
+extern struct xstk_t *__cstr_to_vval(char *s)
+{
+ int32 blen, slen;
+ struct xstk_t *xsp;
+
+ slen = strlen(s);
+ blen = 8*slen;
+ push_xstk_(xsp, blen);
+ zero_allbits_(xsp->ap, blen);
+ zero_allbits_(xsp->bp, blen);
+ __vstr_to_vval(xsp->ap, s, blen);
+ return(xsp);
+} 
+
+/*
+ * push back for internal use by unget routines where get1_vtok value
+ * must be pushed back
+ */
+static void unget2_vtok(int32 ttyp)
+{
+ int32 save_ttyp;
+
+ save_ttyp = __toktyp;
+ __toktyp = ttyp;
+ __unget_vtok();
+ __toktyp = save_ttyp;
+}
+
+/*
+ * push back an already read token operator or keyword token
+ */
+extern void __unget_vtok(void)
+{
+ __lasttoktyp = __toktyp;
+ strcpy(__lasttoken, __token);
+ /* SJM 10/16/00 - save any pending attribte - because does not really read */
+ /* token the actual attr string and other vars will be right and preserved */
+ __last_attr_prefix = __attr_prefix;
+
+ /* extremely rare number push back case */
+ if (__toktyp == NUMBER) 
+  {
+   int32 wlen;
+
+   __lastitokbase = __itokbase;
+   __lastitoksized = __itoksized;
+   __lastitoksizdflt = __itoksizdflt;
+   __lastitok_signed = __itok_signed;
+   __lastitoklen = __itoklen;
+    
+   /* must malloc to save in rare pushed back case */
+   /* SJM 03/20/00 - no unget of num token since already in a/b wrk as val */
+   wlen = wlen_(__itoklen);
+   __lastacwrk = (word32 *) __my_malloc(wlen*WRDBYTES);
+   __lastbcwrk = (word32 *) __my_malloc(wlen*WRDBYTES);
+   memcpy(__lastacwrk, __acwrk, wlen*WRDBYTES);
+   memcpy(__lastbcwrk, __bcwrk, wlen*WRDBYTES);
+   return;
+  }
+ if (__toktyp == REALNUM) 
+  {
+   __lastitokbase = __itokbase;
+   __lastitoksized = __itoksized;
+   __lastitoksizdflt = __itoksizdflt;
+   __lastitok_signed = __itok_signed;
+   __lastitoklen = __itoklen;
+   __lastitok_realval = __itok_realval;
+  }
+}
+
+/*
+ * read a verilog style number
+ * know first char digit or ' and reads number end char
+ * width if present left in nwidtoken and value in token
+ *
+ * notice that maximun number can be IDLEN - 1 digits must leave
+ * since other sizes like max. no. of const. bits set to prevent possibility
+ * of overflow
+ *
+ * notice '_' in number are just ignored and not added to token, is this ok
+ */
+static int32 rd_num(FILE *f, int32 c1)
+{
+ register char *chp;
+ register int32 c;
+ int32 len, toolong, isreal, errnum, blen, nsize;
+ word32 v;
+ double d1;
+ char *endp;
+ /* SJM 03/20 - FIXME - for now limiting dec unsized to 16k digits */
+ char nwidtoken[4*IDLEN];
+
+ __itokbase = BDEC;
+ __itoksized = FALSE;
+ __itoksizdflt = FALSE;
+ __itok_signed = FALSE;
+ __itoklen = WBITS;
+ strcpy(nwidtoken, "");
+
+ /* read the possible decimal size value or unsized unbased number */
+ isreal = FALSE;
+ len = 0;
+ if ((c = c1) != '\'')
+  {
+   /* 06/22/00 - SJM - only 2 token number case if `[base][num] */ 
+   __maybe_2tok_sized_num = FALSE;
+   /* collect value */
+   for (toolong = FALSE, chp = nwidtoken, len = 0;;)
+    {
+     while (c == '_') c = my_getc(f);
+     switch (c) {
+      case '0': case '1': case '2': case '3': case '4': case '5':
+      case '6': case '7': case '8': case '9': break;
+      /* - and + here */
+      case 'e': case 'E': isreal = TRUE; break; 
+      case '.': isreal = TRUE; break;
+      case '-': case '+':
+       /* + and minus after exponent legal else end of number */
+       /* this can never cause a number to be real */
+       if (*(chp - 1) == 'e' || *(chp - 1) == 'E') break;
+       goto end_unsiz;
+      default: goto end_unsiz;
+     }
+    if (++len >= 4*IDLEN)
+     {
+      if (!toolong)
+       {
+        __pv_ferr(948,
+         "Verilog size prefix or unsized number too many characters (%d)",
+         4*IDLEN);
+        toolong = TRUE;
+       }
+     }
+    else *chp++ = c;
+    c = my_getc(f);
+   }
+end_unsiz:
+  *chp = '\0';
+
+  /* know c is not a digit - punctuation ok */
+  if (__pv_ctab[c & 0x7f] == 0)
+   {
+    /* numbers can end with letter in udp tables */
+    if (__letendnum_state) goto ok_letend;
+    __pv_ferr(949,
+     "unsized number terminated with illegal char '%c' (%x)", c & 0xff,
+     c & 0xff);
+    goto ok_letend;
+   }
+  /* this skips across new line */ 
+  c = voverwhite(f, c);
+  if (c == EOF) __macro_sep_width = TRUE;
+ }
+
+ /* know either c is char after unsized number or quote for Ver number */
+ok_letend:
+ if (c != '\'')
+  {
+   /* 06/22/00 - SJM - only 2 token number case if `[base][num] */ 
+   __maybe_2tok_sized_num = FALSE;
+
+   /* char after white space starts next token */
+   /* this is case where next token is special first token on line */
+   my_ungetc_(c, f);
+   /* SJM - 03/20/00 - here just increase to size needed */
+   if (len >= __numtok_wid) 
+    {
+     /* 06/26/00 - increase size with realloc but unsized not too wide */
+     __numtoken = __my_realloc(__numtoken, __numtok_wid, __numtok_wid
+      + RECLEN);
+     __numtok_wid = len + RECLEN;
+    }
+   strcpy(__numtoken, nwidtoken);
+   strcpy(nwidtoken, "");
+
+   /* remove leading 0's  but if first char is . put 1 back */
+   if (!__letendnum_state) rem_lead_0chars(__numtoken);
+   /* allowing any legal c real here - but maybe should not allow dot not */
+   /* surrounded by digits */
+   if (isreal)
+    {
+     d1 = __my_strtod(__numtoken, &endp, &errnum);   
+     if (errnum != 0 || *endp != '\0')
+      __pv_ferr(950, "illegal real number %s", __numtoken);
+     /* notice some compilers crash if doubles not 8 byte aligned ? */
+     /* therefore need special routine for doubles */
+     __itok_realval = d1;
+     __itoklen = REALBITS;
+     __itokbase = BDBLE;
+     __macro_sep_width = FALSE;
+     return(REALNUM);
+    }
+   /* SJM 10/02/03 - string of dec digits no '[base] is signed decimal */
+   __itok_signed = TRUE;
+   /* handle numbers that fit in 10 chars as special case */
+   if (strlen(__numtoken) < 10) 
+    {
+     v = __my_strtoul(__numtoken, &endp, &errnum);
+     if (errnum != 0 || *endp != '\0') __misc_terr(__FILE__, __LINE__); 
+     __acwrk[0] = v;
+     __bcwrk[0] = 0L;
+     if (__macro_sep_width) __macro_sav_nwid = (int32) v; 
+     return(NUMBER);
+    }
+   /* for implied WBITS number convert and truncate */
+   goto do_convert;
+  }
+
+ /* know c is ' */
+ /* know token read after this is not first token on line because */
+ /* number becuase size number ' is on next line */
+ /* know '[base] form is unsized and word32 but'[Ss][base] is signed */
+
+ /* AIV 07/09/04 - special case to handle:  8'h`DEFINE */
+ /* if `define macro contains a 'base it is illegal */
+ if (__macbs_flag)
+  {
+   __pv_ferr(3418,
+    "number with '[base] macro expansion %s contains extra '[base]", __token);
+   /* AIV 07/12/04 - not sure what happens with error resync here */ 
+   return(UNDEF);
+  }
+
+ /* if this is too wide will be caught later - this sets [size]' size */
+ if (strcmp(nwidtoken, "") != 0)
+  {
+   blen = __my_strtoul(nwidtoken, &endp, &errnum);
+   if (errnum != 0 || *endp != '\0')
+    {
+     __pv_ferr(952, "number size %s format bad", nwidtoken);
+     __itoklen = WBITS;
+    }
+   else __itoklen = blen;
+
+   /* saying 0'[base]... is legal and becomes WBITS */
+   if (__itoklen == 0)
+    {
+     __pv_fwarn(557, "INTERNAL - zero number size changed to %d", WBITS);
+     __itoklen = WBITS;
+    }
+   __itoksized = TRUE;
+  }
+ else
+  {
+   /* 06/22/00 - SJM - this is 2nd part of sized num */
+   if (__maybe_2tok_sized_num)
+    {
+     /* flags turned off later */
+     __itoklen = __macro_sav_nwid;
+     __itoksized = TRUE;
+    }
+   else __itoksizdflt = TRUE;
+  }
+
+ /* '[base][number] is unsized 32 bits */
+ if (__itoklen > MAXNUMBITS)
+  {
+   __pv_ferr(953, "number size too large (%d)", MAXNUMBITS);
+   __itoklen = WBITS;
+   __itoksized = FALSE;
+  }
+
+ /* SJM 10/01/03 - add code that get the optional base signed char */ 
+ /* and set signed flag for use when expression token constructed */
+ c = my_getc(f); 
+ if (c == 's' || c == 'S')
+  {
+   __itok_signed = TRUE;
+   c = my_getc(f); 
+  }
+
+ if ((__itokbase = __to_base(c)) == -1)
+  {
+   __pv_ferr(954,
+    "illegal Verilog number base %c - for compiler directive use back quote(`)", c);
+   my_ungetc_(c, f);
+   __macro_sep_width = FALSE;
+   return(UNDEF);
+  }
+ c = my_getc(f);
+ c = voverwhite(f, c);
+ /* AIV 07/09/04 - special case to handle:  8'h`DEFINE */
+ if (c == '`')
+  {
+   int32 stok;
+   my_ungetc_(c, f);
+   /* save the base */
+   stok = __itokbase;
+   /* set the flag to make sure macro doesn't contain a base */
+   __macbs_flag = TRUE;
+   /* AIV 07/12/04 - need recursive call but can't read another number */ 
+   __get_vtok();
+   __macbs_flag = FALSE;
+   __itokbase = stok;
+   goto do_convert;
+  }
+
+ /* know c is 1st character of sized number */
+ toolong = FALSE;
+ for (chp = __numtoken, len = 0;;)
+  {
+   while (c == '_') c = my_getc(f);
+   c1 = __is_vdigit(c, __itokbase);
+   if (c1 == -1) break;
+   if (c1 == -2)
+    {
+     __pv_ferr(955, "digit %c illegal for base '%c", c,
+      __to_baselet(__itokbase));
+     c = c1 = '0';
+    }
+   /* using maximum length of Verilog line as 1024 (really ID len. max) */
+   if (++len >= __numtok_wid)
+    {
+     if (len >= MAXNUMBITS) 
+      {
+       if (!toolong)
+        {
+         __pv_ferr(956,
+          "Verilog sized number too many characters (%d)", MAXNUMBITS);
+         toolong = TRUE;
+        }
+      }
+     else
+      {
+       /* LOOKATME - SJM 03/20/00 - doubling may be too fast growth */
+       nsize = 2*__numtok_wid;
+       __numtoken = __my_realloc(__numtoken, __numtok_wid, nsize);
+       __numtok_wid = nsize;
+       *chp++ = c1;
+      }
+    }
+   else *chp++ = c1;
+   c = my_getc(f);
+  }
+ *chp = '\0';
+
+ if (strcmp(__numtoken, "") == 0)
+  {
+   __pv_ferr(957, "sized number value part empty");
+   strcpy(__numtoken, "0");
+  }
+
+ if (__pv_ctab[c & 0x7f] == 0)
+  __pv_ferr(958, "sized number terminated with illegal char '%c' (%x)",
+  c % 0xff, c & 0xff);
+ my_ungetc_(c, f);
+ /* finally do the conversion - know sizedness set and length in itok len */
+ /* length never 0 */
+
+ /* notice this can never generate error */
+ /* wide numbers truncated in here - do all non real numbers here */
+do_convert:
+ /* this sets number bit length and allocates number if needed */
+ __macro_sep_width = FALSE;
+ __to_dhboval(__itokbase, TRUE);
+ return(NUMBER);
+}
+
+/*
+ * remove leading 0 characters from numer string in token
+ * this works in place
+ */
+static void rem_lead_0chars(char *s)
+{
+ register int32 i, j;
+ int32 slen;
+
+ /* first set index to first non 0 char */
+ for (i = 0; ; i++)
+  {
+   /* number all zero convert to 1 0 */
+   if (s[i] == '\0') { s[0] = '0'; s[1] = '\0'; return; }
+   if (s[i] != '0') break;
+  }
+ if (i == 0) return;
+ /* if leading is . then must add 1 leading 0 - know at least 0. at start */
+ if (s[i] == '.') i--;  
+
+ /* copy to remove all leading 0's */
+ slen = strlen(s);
+ for (j = 0; j < slen - i; j++) s[j] = s[i + j]; 
+ s[slen - i] = '\0';
+}
+
+/*
+ * skip over white space and return char just after
+ * expects current character to be in c - no skip if current not white space
+ */
+static int32 voverwhite(FILE *f, register int32 c)
+{
+ int32 ct;
+
+ for (;; c = my_getc(f))
+  {
+   /* notice anthing escaped is not white space */
+   if ((ct = __pv_ctab[c & 0x7f]) == 1) continue;
+   if (ct == 3)
+    { __lin_cnt++; __total_rd_lines++; __first_num_eol = TRUE; continue; }
+   break;
+  }
+ return(c);
+}
+
+/*
+ * convert a character to a Verilog number base
+ */
+extern int32 __to_base(int32 c)
+{
+ switch (c) {
+  case 'b': case 'B': return(BBIN);
+  case 'o': case 'O': return(BOCT);
+  case 'd': case 'D': return(BDEC);
+  case 'h': case 'H': return(BHEX);
+ }
+ return(-1);
+}
+
+/*
+ * return TRUE if character can appear in Verilog number
+ * return value if digit, -1 for non digit or -2 for out of range digit 
+ * (ends number)
+ */
+extern int32 __is_vdigit(int32 c, int32 base)
+{
+ switch (c) {
+  case 'x': case 'X': return('x');
+  case '?': case 'z': case 'Z': return('z');
+ }
+ if (!isxdigit(c)) return(-1);
+ switch (base) {
+  case BBIN:
+   if (c != '0' && c != '1') return(-2);
+   break;
+  case BOCT:
+   if (c < '0' || c > '7') return(-2);
+   break;
+  case BDEC:
+   if (!isdigit(c)) return(-2);
+   break;
+  case BHEX:
+   if (c >= 'A' && c <= 'F') return(tolower(c));
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(c);
+}
+
+/*
+ * ROUTINES TO CONVERT TO AB VALUE FROM SCANNED TOKEN
+ */
+
+/*
+ * convert a scanned input number token to a h, b, or o value
+ * this routines x/z extends from highest used digit if needed
+ * warning if too many digits and truncates
+ * this routine fills __ac wrk and __bc wrk, if needed will widen
+ *
+ * this is also used by tf_ string to value conversion routines 
+ * sets values in __numtoken, __itoklen, __itok_signed
+ */
+extern void __to_dhboval(int32 base, int32 emit_warn)
+{
+ register int32 chlen, wlen, srcwlen, ubits;
+ int32 srcblen;
+ word32 aival, bival;
+ char s1[RECLEN];
+
+ chlen = strlen(__numtoken);
+ /* must allow enough room in work string to convert number */
+ /* even if much wider than itoklen - just at least wide estimate here */
+ srcblen = chlen_to_bitlen(chlen, base);
+ if (srcblen < __itoklen) srcblen = __itoklen; 
+
+ /* SJM 10/02/03 now wide decimal or numbers with s/S base part signed */ 
+ /* therefore itok is int32 global not accessed here */
+
+ wlen = wlen_(srcblen);
+ /* if need to widen or wider than default, change allocated length */
+ /* notice left until maybe changed next time used */
+ if (wlen > __abwrkwlen || (__abwrkwlen > DFLTIOWORDS && wlen <= DFLTIOWORDS))
+  chg_abwrklen(wlen);
+
+ /* now know __ac wrk and __bc wrk wide enough */
+ memset(__acwrk, 0, wlen*WRDBYTES);
+ memset(__bcwrk, 0, wlen*WRDBYTES);
+
+ /* convert number in token into work constant values */
+ /* notice previous guess of src blen, made exact here */
+ switch (base) {
+  /* notice must trucate/widen after conversion here */
+  case BDEC: to_dec(&srcblen); strcpy(s1, "decimal"); break;
+  case BBIN: to_bin(chlen); strcpy(s1, "binary"); srcblen = chlen; break;
+  case BOCT: to_oct(chlen); strcpy(s1, "octal"); srcblen = 3*chlen; break;
+  case BHEX: to_hex(chlen); strcpy(s1, "hex"); srcblen = 4*chlen; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+
+ /* words and occupied bits of number represented by chars */
+ /* check case of number of character wider - maybe too wide number */
+ /* __itoklen is number of bits that word32 must be stored in */
+ /* srcblen is number of bits in source input number */
+ if (srcblen > __itoklen)
+  {
+   srcwlen = wlen_(srcblen);
+   if (vnum_toowide(__acwrk, srcblen) || vnum_toowide(__bcwrk, srcblen))
+    {
+     /* no warning for [3-1]'h[zx] or [2-1]'o[zx] in high position */
+     /* notice for hex, must be in same word32 to have not too wide nibble */
+     if (base == BHEX)
+      {
+       if (srcblen - __itoklen < 4 && wlen == srcwlen
+ && nibblexz(__acwrk[wlen - 1], __bcwrk[wlen - 1], srcblen))
+        goto do_mask;
+      }
+     else if (base == BOCT)
+      {
+       if (srcblen - __itoklen < 3 && octdigxz(__acwrk, __bcwrk, srcblen))
+        goto do_mask; 
+      }
+     /* SJM 12/04/00 - no warn if skipping over ifdef because will not */
+     /* parse `macro_width_name h [number] right */
+     if (emit_warn && !__ifdef_skipping)
+      { 
+       if (__run_state == SS_SIM)
+        __pv_warn(558, "redundant digit(s) in tf_strput number %s",
+         decompnum_to_str(s1, __numtoken, base, __itoklen));
+       else __pv_fwarn(558, "redundant digit(s) in number %s",
+        decompnum_to_str(s1, __numtoken, base, __itoklen));
+      }
+    }
+   /* if values 0 or vnum not too wide, no warn but still must mask */
+
+   /* must truncate the values to __itoklen */
+   /* this leave high words as is but since unused - if used will be zeroed */
+   /* before use */
+do_mask:
+   ubits = ubits_(__itoklen);
+   __acwrk[wlen - 1] &= __masktab[ubits];
+   __bcwrk[wlen - 1] &= __masktab[ubits];
+  }
+ else if (srcblen < __itoklen)
+  {
+   /* case where widening needed */
+   if (__numtoken[0] == 'z' || __numtoken[0] == 'Z')
+    { aival = 0L; bival = 1L; }
+   else if (__numtoken[0] == 'x' || __numtoken[0] == 'X')
+    { aival = 1L; bival = 1L; }
+   else { aival = 0L; bival = 0L; }
+
+   widen_val(__acwrk, __itoklen, srcblen, aival);
+   widen_val(__bcwrk, __itoklen, srcblen, bival);
+  }
+}
+
+/*
+ * computer number of bits + 1 needed to store number in base of chlen
+ * worst case - could contain '_' place holders
+ */
+static int32 chlen_to_bitlen(int32 chlen, int32 base)
+{
+ int32 bitlen;
+ double d1;
+
+ switch (base) {
+  case BDEC:
+   /* here must make sure bit enough if rounding error */
+   /* actual conversion will compute exact bit length */
+   d1 = ((double) chlen)/LG2_DIV_LG10 + WBITS;
+   bitlen = (int32) d1;
+   break;
+  case BBIN: bitlen = chlen; break;
+  case BOCT: bitlen = 3*chlen; break;
+  case BHEX: bitlen = 4*chlen; break;
+  default: __case_terr(__FILE__, __LINE__); return(0);
+ }
+ return(bitlen);
+}
+
+/*
+ * change __ac wrk (and bc) work area length from blen if needed
+ * only gets here if either blen (__itoklen) or abwork len wider than default
+ * notice __ac wrk and __bc wrk not necessary contiguous
+ */
+static void chg_abwrklen(int32 wlen)
+{
+ int32 olen, nlen;
+
+ olen = WRDBYTES*__abwrkwlen;
+ if (wlen <= DFLTIOWORDS) __abwrkwlen = DFLTIOWORDS; else __abwrkwlen = wlen;
+ nlen = WRDBYTES*__abwrkwlen;
+ __acwrk = (word32 *) __my_realloc((char *) __acwrk, olen, nlen);
+ __bcwrk = (word32 *) __my_realloc((char *) __bcwrk, olen, nlen);
+}
+
+/*
+ * convert a number scanned token to a decimal value
+ * know number initialized to 0 of itoklen width
+ * LOOKATME - could maybe speed up by using scanf if fits in one word?
+ */
+static void to_dec(int32 *blen) 
+{
+ /* know __ac wrk and __bc wrk set to 0 before this is called */
+ if (strchr(__numtoken, 'z') != NULL)
+  { one_allbits_(__bcwrk, __itoklen); *blen = __itoklen; return; }
+ else if (strchr(__numtoken, 'x') != NULL)
+  {
+   /* 1 decimal digit will be at least this wide */
+   one_allbits_(__acwrk, __itoklen);
+   one_allbits_(__bcwrk, __itoklen);
+   *blen = __itoklen;
+   return;
+  }
+ /* do the conversion */
+ wide_strtoverdec(*blen);
+ /* finally, find real convert decimal number bit width by trimming */
+ *blen = __trim1_0val(__acwrk, *blen); 
+}
+
+/*
+ * convert a string in __numtoken into a decimal number in acwrk that is known
+ * to be wide enough (blen width)
+ * know all digits in token are legal decimal digits
+ */
+static void wide_strtoverdec(int32 blen)
+{
+ register char *chp;
+ word32 *reg10, *newdig, *acc;
+ int32 wlen;
+ struct xstk_t *xsp;
+
+ wlen = wlen_(blen);
+ push_xstk_(xsp, blen);
+ /* build the constant 10 */
+ reg10 = xsp->ap;
+ memset(reg10, 0, wlen*WRDBYTES);
+ reg10[0] = 10;
+ /* and use b part to hold new digit to add */
+ newdig = xsp->bp;
+ memset(newdig, 0, wlen*WRDBYTES);
+ push_xstk_(xsp, blen);
+ acc = xsp->ap;
+ memset(acc, 0, wlen*WRDBYTES);
+
+ chp = __numtoken;
+ __acwrk[0] = *chp - '0'; 
+ /* notice start with high (left) digit */ 
+ for (chp++; *chp != '\0'; chp++) 
+  {
+   /* 10 times current value plus new digit */
+   __lmult(acc, __acwrk, reg10, blen);
+   newdig[0] = *chp - '0';
+   __ladd(acc, acc, newdig, blen); 
+   /* notice the accumulator must be copied into ac wrk since lmult res */
+   /* must be different value than u and v */
+   memcpy(__acwrk, acc, wlen*WRDBYTES);
+  } 
+ /* value now in acwrk */
+ __pop_xstk();
+ __pop_xstk();
+}
+
+/*
+ * convert a number scanned token to binary in work string (acwrk and bcwrk)
+ * input in token and token length set
+ * know will fit and correct
+ * notice caller know to have zerod __ac wrk and __bc wrk
+ */
+static void to_bin(int32 slen)
+{
+ register int32 i;
+ word32 a, b;
+ int32 bi;
+
+ /* fill val from low char (rght str) to high char (const left to rght) */
+ for (i = slen - 1, bi = 0; i >= 0; i--, bi++)
+  {
+   ch_tobits(&a, &b, __numtoken[i]);
+   __lhsbsel(__acwrk, bi, a);
+   __lhsbsel(__bcwrk, bi, b);
+  }
+}
+
+/*
+ * convert binary plus z-x character to bit
+ */
+static int32 ch_tobits(word32 *ap, word32 *bp, int32 ch)
+{
+ *ap = *bp = 0L;
+ switch (ch) {
+  case 'z': case 'Z': *bp = 1L; break;
+  case 'x': case 'X': *ap = 1L; *bp = 1L; break;
+  case '0': break;
+  case '1': *ap = 1L; break;
+  default: return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * convert a number scanned token to octal in work string (acwrk and bcwrk)
+ * input in token and token length set
+ * know will fit and __ac wrk and __bc wrk zeroed 
+ */
+static void to_oct(int32 slen)
+{
+ register int32 i, bi;
+ word32 a, b;
+
+ /* fill val from low char (rght str) to high char (const left to rght) */
+ for (i = slen - 1, bi = 0; i >= 0; i--, bi += 3)
+  {
+   ch_toocts(&a, &b, __numtoken[i]);
+   /* cant use literal shifts and mask because some octs split on boundary */
+   __lhspsel(__acwrk, bi, &a, 3);
+   __lhspsel(__bcwrk, bi, &b, 3);
+  }
+}
+
+/*
+ * convert octal digit plus z-x character to bit
+ */
+static int32 ch_toocts(word32 *ap, word32 *bp, int32 ch)
+{
+ *ap = *bp = 0L;
+ switch (ch) {
+  case 'z': case 'Z': *bp = 0x7L; break;
+  case 'x': case 'X': *ap = 0x7L; *bp = 0x7L; break;
+  default:
+   if (ch < '0' || ch > '7') return(FALSE);
+   *ap = (word32) ((ch - '0') & 0x7L);
+  }
+ return(TRUE);
+}
+
+/*
+ * convert number scanned token to hex in work string (__ac wrk and __bc wrk)
+ * input in token and itoklen set
+ * know will fit and know acwrk and bcwrk already zeroed
+ * sets tokval or tokptr if > WBITS
+ */
+static void to_hex(int32 slen)
+{
+ register int32 i, bi;
+ register word32 *ap, *bp;
+ word32 a, b;
+
+ /* fill val from low char (right str) to high char (const left to right) */
+ ap = __acwrk;
+ bp = __bcwrk;
+ for (i = slen - 1, bi = 0; i >= 0; i--)
+  {
+   /* know already checked for out of range before here */
+   ch_tohexs(&a, &b, __numtoken[i]);
+   if (bi == 0) { *ap = a; *bp = b; bi += 4; continue; }
+   *ap |= a << bi;
+   *bp |= b << bi;
+   if (bi == 28) { bi = 0; ap++; bp++; } else bi += 4;
+  }
+}
+
+/*
+ * convert hex digit plus x and z to bit pattern
+ */
+static int32 ch_tohexs(word32 *ap, word32 *bp, int32 ch)
+{
+ *ap = *bp = 0L;
+ switch (ch) {
+  case 'z': case 'Z': *bp = 0xfL; break;
+  case 'x': case 'X': *ap = 0xfL; *bp = 0xfL; break;
+  default:
+   if (ch >= '0' && ch <= '9')
+    {
+     *ap = (word32) ((ch - '0') & 0xfL);
+     break;
+    }
+   if (isupper(ch)) ch = tolower(ch);
+   if (ch >= 'a' && ch <= 'f')
+    {
+     *ap = (word32) ((10 + ch - 'a') & 0xfL);
+     break;
+    }
+   /* should have already been caught */
+   /* illegal 'h radix digit */
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * return T if source input number at wp of length srcblen wider
+ * than __itoklen - if all high bits 0 returns F (not too wide)
+ *
+ * only called if srcblen > __itoklen
+ * if too wide only because x or z hex or oct digit returns T here
+ * but change to not too wide later
+ */
+static int32 vnum_toowide(word32 *wp, int32 srcblen)
+{
+ register int32 i;
+ int32 srcwlen, storwlen, storubits;
+
+ srcwlen = wlen_(srcblen);
+ storwlen = wlen_(__itoklen);
+ storubits = ubits_(__itoklen);
+ /* if high bits of high word32 from storage token length, too wide */
+ if ((wp[storwlen - 1] & ~__masktab[storubits]) != 0L) return(TRUE);
+ for (i = storwlen; i < srcwlen; i++) if (wp[i] != 0L) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * return T if high unused bits of high 4 bit nibble x or z
+ * know shubits is aligned on 4 bit boundary and both in same word
+ * know if all high bits 0 won't get here
+ */
+static int32 nibblexz(word32 aw, word32 bw, int32 srcblen)
+{
+ int32 itokubits;
+ word32 tmp;
+
+ /* know __itoklen has at least 1 high bit unused or will not get here */
+ itokubits = ubits_(__itoklen);
+ bw >>= itokubits;
+ aw >>= itokubits;
+ switch (srcblen - __itoklen) {
+  case 1:
+   /* notice this will shift so 1 extra bit is in low position not 8 pos. */
+   if ((bw & 1L) == 0L) return(FALSE);
+   break;
+  case 2:
+   /* if 2, b part bits are not 11 or a part 01 or 10 then not ok nibble */
+   if ((bw & 3L) != 3L || ((tmp = aw & 3L) == 01L || tmp == 02L))
+    return(FALSE);
+   break;
+  case 3:
+   /* if 3 extra, b part bits 111 and a part not 000 or 111, not ok nibble */
+   if ((bw & 7L) != 7L || ((tmp = aw & 7L) != 7L && tmp != 0L))
+    return(FALSE);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(TRUE);
+}
+
+/*
+ * return T if high unused bits of high 3 bit nibble x or z
+ */
+static int32 octdigxz(word32 *ap, word32 *bp, int32 srcblen)
+{
+ word32 tmp, aw, bw;
+
+ /* part select needed to isolate bits, oct can overlap word32 boundary */
+ __rhspsel(&bw, bp, __itoklen - 1, 3);
+ switch (srcblen - __itoklen) {
+  case 1:
+   if ((bw & 4L) != 0L) return(FALSE); break;
+  case 2:
+   if ((bw & 6L) != 6L) return(FALSE);
+   __rhspsel(&aw, ap, __itoklen - 1, 3);
+   /* for 2 bits must both be x aw=11? or z aw=00? */
+   /* not a high x/z if 010 or 100 after masking */
+   if ((tmp = aw & 6L) == 2L || tmp == 4L) return(FALSE);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(TRUE);
+}
+
+/*
+ * widen a shorter value into a longer value in place (either a or b)
+ * highval determines kind of ext. (0 = 0, 1 = 1)
+ * do not know what is in higher values
+ * know valwp wide enough
+ */
+static void widen_val(word32 *vwp, int32 lngblen, int32 shblen, word32 highval)
+{
+ register int32 i;
+ register word32 *wp;
+ word32 mask;
+ int32 shwlen, shubits, lngwlen, lngubits;
+
+ shwlen = wlen_(shblen);
+ shubits = ubits_(shblen);
+ lngwlen = wlen_(lngblen);
+ lngubits = ubits_(lngblen);
+ /* first extend unused part of old short high word32 */
+ if (shubits != 0)
+  {
+   mask = __masktab[shubits];
+   vwp[shwlen - 1] &= mask;
+   if (highval == 1L) vwp[shwlen - 1] |= ~mask;
+  }
+ /* done if widen up to max of WBITS or words same length */
+ if (lngwlen == 1 || lngwlen == shwlen) goto done;
+
+ /* next set all higher words to highval */
+ if (highval == 0L) memset(&(vwp[shwlen]), 0, WRDBYTES*(lngwlen - shwlen));
+ else
+  {
+   /* notice if incing wp cannot use indexed later */ 
+   for (i = shwlen, wp = &(vwp[shwlen]); i < lngwlen; i++) *wp++ = ALL1W;
+  }
+
+done:
+ /* finally zero unused portion of high word32 */
+ vwp[lngwlen - 1] &= __masktab[lngubits];
+}
+
+/*
+ * MISC. TOKEN HANDLING ROUTINES
+ */
+
+/*
+ * version of print vtoken where value is not in global _toktyp  
+ * for use inside get token routines
+ */ 
+static char *prt2_vtok(int32 ttyp)
+{
+ int32 save_ttyp;
+ char *chp; 
+
+ save_ttyp = __toktyp;
+ __toktyp = ttyp;
+ chp = __prt_vtok();
+ __toktyp = save_ttyp;
+ return(chp);
+}
+
+/*
+ * print a token for error messages - indicate token is a keyword for msg
+ *
+ */
+extern char *__prt_kywrd_vtok(void)
+{
+ char s1[RECLEN];
+
+ if (get_vkeywrd(__token) != ID)
+  {
+   /* know pv varnam always has enough room for keyword */
+   sprintf(s1, "Verilog keyword: %s",  __prt_vtok());
+   strcpy(__pv_varnam, s1);
+   return(__pv_varnam);
+  }
+ return(__prt_vtok());
+}
+
+/*
+ * print the value of a token
+ * only for current token (i.e. moves punct./op. to token)
+ * i.e. typ cannot be old
+ */
+extern char *__prt_vtok(void)
+{
+ /* notice this must not change current val. of token */
+ if (__toktyp >= BKEYS)
+  { __get_vkeynam(__pv_varnam, __toktyp); return(__pv_varnam); }
+
+ switch ((byte) __toktyp) {
+  case TEOF:
+   if (__run_state == SS_SIM && __cmd_s == NULL) strcpy(__token, "**EOL**");  
+   else strcpy(__token, "**EOF**");
+   break;
+  case ID: return(__token);
+  case NUMBER: return(__numtoken);
+  case REALNUM: sprintf(__token, "%#g",  __itok_realval); break;
+  case LITSTR: return(__strtoken);
+  case SEMI: strcpy(__token, ";"); break;
+  case COMMA: strcpy(__token, ","); break;
+  case COLON: strcpy(__token, ":"); break;
+  case SHARP: strcpy(__token, "#"); break;
+  case LPAR: strcpy(__token, "("); break;
+  case RPAR: strcpy(__token, ")"); break;
+  case LSB: strcpy(__token, "["); break;
+  case RSB: strcpy(__token, "]"); break;
+  case LCB: strcpy(__token, "{"); break;
+  case RCB: strcpy(__token, "}"); break;
+  case DOT: strcpy(__token, "."); break;
+  case QUEST: strcpy(__token, "?"); break;
+  case AT: strcpy(__token, "@"); break;
+  case CAUSE: strcpy(__token, "->"); break;
+  case PLUS: strcpy(__token, "+"); break; 
+  case MINUS: strcpy(__token, "-"); break;
+  case TIMES: strcpy(__token, "*"); break;
+  case DIV: strcpy(__token, "/"); break;
+  case MOD: strcpy(__token, "%"); break;
+  case BITNOT: strcpy(__token, "~"); break;
+  case BITREDAND: strcpy(__token, "&"); break;
+  case BITREDOR: strcpy(__token, "|"); break;
+  case BITREDXOR: strcpy(__token, "^"); break;
+  /* notice ~ ^ are 2 unary operators */
+  case REDXNOR: strcpy(__token, "^~"); break;
+  case RELGE: strcpy(__token, ">="); break;
+  case RELGT: strcpy(__token, ">"); break;
+  case RELLE: strcpy(__token, "<="); break;
+  case RELLT: strcpy(__token, "<"); break;
+  case RELCEQ: strcpy(__token, "==="); break;
+  case RELEQ: strcpy(__token, "=="); break;
+  case RELCNEQ: strcpy(__token, "!=="); break;
+  case RELNEQ: strcpy(__token, "!="); break;
+  case BOOLAND: strcpy(__token, "&&"); break;
+  case BOOLOR: strcpy(__token, "||"); break;
+  case NOT: strcpy(__token, "!"); break;
+  case SHIFTL: strcpy(__token, "<<"); break;
+  case ASHIFTL: strcpy(__token, "<<<"); break;
+  case SHIFTR: strcpy(__token, ">>"); break;
+  case ASHIFTR: strcpy(__token, ">>>"); break;
+  case EQ: strcpy(__token, "="); break;
+  case FPTHCON: strcpy(__token, "*>"); break;
+  case PPTHCON: strcpy(__token, "=>"); break;
+  case TCHKEVAND: strcpy(__token, "&&&"); break;
+  case UNDEF: strcpy(__token, "**NONE**"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(__token);
+}
+
+/*
+ * convert a punct./operator token to a name
+ * only for current token (i.e. moves punct./op. to token)
+ * non expression token removed when tree built but included here
+ * result 
+ */
+extern char *__to_opname(word32 otyp)
+{
+ /* token number %d illegal in expression */
+ if (otyp > TEOF) __misc_fterr(__FILE__, __LINE__);
+ return(__opinfo[otyp].opnam);
+}
+
+/* note! - must be kept in alphabetical order */
+/* keyword types (already know token is a name) */
+/* making as many things as possible Verilog since they are reserved */
+struct vkeywds_t {
+ char *vknam;
+ int32 vknum;
+};
+
+static struct vkeywds_t vkeywds[] = {
+ { "`accelerate", CDIR_ACCEL },
+ { "`autoexpand_vectornets", CDIR_AEXPVECNETS },
+ { "`celldefine", CDIR_CELLDEF },
+ { "`default_decay_time", CDIR_DFLTDECAYTIME },
+ { "`default_nettype", CDIR_DFLNTYP },
+ { "`default_trireg_strength", CDIR_DFLTTRIREGSTREN },
+ { "`define", CDIR_DEFINE },
+ { "`delay_mode_distributed", CDIR_DELMODEDIST },
+ { "`delay_mode_path", CDIR_DELMODEPATH },
+ { "`delay_mode_unit", CDIR_DELMODEUNIT },
+ { "`delay_mode_zero", CDIR_DELMODEZERO },
+ { "`else", CDIR_ELSE },
+ { "`endcelldefine", CDIR_ECELLDEF },
+ { "`endif", CDIR_ENDIF },
+ { "`endprotect", CDIR_ENDPROTECT },
+ { "`endprotected", CDIR_ENDPROTECTED },
+ { "`expand_vectornets", CDIR_XPNDVNETS },
+ { "`ifdef", CDIR_IFDEF },
+ { "`ifndef", CDIR_IFNDEF },
+ { "`include", CDIR_INCLUDE },
+ { "`language", CDIR_LANG },
+ { "`noaccelerate", CDIR_NOACCEL },
+ { "`noexpand_vectornets", CDIR_NOXPNDVNETS },
+ { "`noremove_gatenames", CDIR_NOREMGATENAMES },
+ { "`noremove_netnames", CDIR_NOREMNETNAMES },
+ { "`nounconnected_drive", CDIR_NOUNCONNDRIVE },
+ { "`protect", CDIR_PROTECT },
+ { "`protected", CDIR_PROTECTED },
+ { "`remove_gatenames", CDIR_REMGATESNAMES },
+ { "`remove_netnames", CDIR_REMNETNAMES },
+ { "`resetall", CDIR_RESETALL },
+ { "`timescale", CDIR_TIMESCALE },
+ { "`unconnected_drive", CDIR_UNCONNDRIVE },
+ { "`undef", CDIR_UNDEF },
+
+ { "always", ALWAYS },
+ { "assign", ASSIGN },
+ { "begin", Begin },
+ { "case", CASE },
+ { "casex", CASEX },
+ { "casez", CASEZ },
+ { "deassign", DEASSIGN },
+ { "default", DEFAULT },
+ { "defparam", DEFPARAM },
+ { "disable", DISABLE },
+ { "edge", EDGE },
+ { "else", ELSE },
+ { "end", END },
+ { "endcase", ENDCASE },
+ { "endfunction", ENDFUNCTION },
+ { "endgenerate", ENDGENERATE },
+ { "endmodule", ENDMODULE },
+ { "endprimitive", ENDPRIMITIVE },
+ { "endspecify", ENDSPECIFY },
+ { "endtable", ENDTABLE },
+ { "endtask", ENDTASK },
+ { "event", EVENT },
+ { "for", FOR },
+ { "force", FORCE },
+ { "forever", FOREVER },
+ { "fork", FORK },
+ { "function", FUNCTION },
+ { "generate", GENERATE },
+ { "highz0", HIGHZ0 },
+ { "highz1", HIGHZ1 },
+ { "if", IF },
+ { "ifnone", IFNONE }, 
+ { "initial", INITial },
+ { "inout", INOUT },
+ { "input", INPUT },
+ /* not int32 */
+ { "integer", INTEGER },
+ { "join", JOIN },
+ { "large", LARGE },
+ { "macromodule", MACROMODULE },
+ { "medium", MEDIUM },
+ { "module", MODULE },
+ { "negedge", NEGEDGE },
+ { "output", OUTPUT },
+ { "parameter", PARAMETER },
+ { "posedge", POSEDGE },
+ { "primitive", PRIMITIVE },
+ { "pull0", PULL0 },
+ { "pull1", PULL1 },
+ { "real", REAL },
+ { "realtime", REALTIME },
+ { "reg", REG },
+ { "release", RELEASE },
+ { "repeat", REPEAT },
+ { "scalared", SCALARED },
+ { "signed", SIGNED },
+ { "small", SMALL },
+ { "specify", SPECIFY },
+ { "specparam", SPECPARAM },
+ { "strength", Strength },
+ { "strong0", STRONG0 },
+ { "strong1", STRONG1 },
+ { "supply0", SUPPLY0 },
+ { "supply1", SUPPLY1 },
+ { "table", TABLE },
+ { "task", TASK },
+ { "time", TIME },
+ { "tri", TRI },
+ { "tri0", TRI0 },
+ { "tri1", TRI1 },
+ { "triand", TRIAND },
+ { "trior", TRIOR },
+ { "trireg", TRIREG },
+ { "vectored", VECTORED },
+ { "wait", WAIT },
+ { "wand", WAND },
+ { "weak0", WEAK0 },
+ { "weak1", WEAK1 },
+ { "while", WHILE },
+ { "wire", WIRE },
+ { "wor", WOR }
+};
+#define NVKEYWDS (sizeof(vkeywds) / sizeof(struct vkeywds_t))
+
+/*
+ * determine type of keyword or ident
+ * binary search because the table is so big
+ */
+static int32 get_vkeywrd(register char *tstr)
+{
+ int32 l, h;
+ register int32 m, cv;
+
+ l = 0; h = NVKEYWDS - 1;
+ for (;;)
+  {
+   m = (l + h)/2;
+   if ((cv = strcmp(vkeywds[m].vknam, tstr)) == 0) return(vkeywds[m].vknum);
+   if (cv < 0) l = m + 1; else h = m - 1;
+   if (h < l) break;
+  }
+ return(ID);
+}
+
+/*
+ * determine keyword name from number
+ * must use linear search since not sorted
+ */
+extern char *__get_vkeynam(char *s, int32 knum)
+{
+ register int32 vi;
+
+ for (vi = 0; vi < NVKEYWDS; vi++)
+  {
+   if (vkeywds[vi].vknum == knum)
+   {
+    strcpy(s, vkeywds[vi].vknam);
+    return(s);
+   }
+  }
+ strcpy(s, "--none--");
+ return(s);
+}
+
+/*
+ * ROUTINES FOR RESYNCING AFTER ERROR
+ */
+
+/*
+ * skip to symbol - if not found only end module/primitive ends
+ * rest of module not checked
+ * return T if found targ1 else F
+ */
+extern int32 __vskipto_modend(int32 targ1)
+{
+ int32 sav_letendnum;
+
+ /* SJM 11/30/04 - save and restore edge illegal num errors when skip mod */
+ sav_letendnum = __letendnum_state;
+ __letendnum_state = TRUE;
+ for (;;)
+  {
+   if (__toktyp == targ1)
+    {
+     __letendnum_state = sav_letendnum;
+     return(TRUE);
+    }
+   switch ((byte) __toktyp) {
+    case ENDMODULE: case ENDPRIMITIVE:
+     goto done;
+    case PRIMITIVE: case MODULE: case MACROMODULE:
+     __unget_vtok(); goto done;
+   }
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
+   __get_vtok();
+  }
+done:
+ __letendnum_state = sav_letendnum;
+ return(FALSE);
+}
+
+/*
+ * skip to 2 symbols - if not found only end module/primitive ends
+ * rest of module not checked
+ * return T if found targ1 else F
+ */
+extern int32 __vskipto2_modend(int32 targ1, int32 targ2)
+{
+ int32 sav_letendnum;
+
+ /* SJM 11/30/04 - save and restore edge illegal num errors when skip mod */
+ sav_letendnum = __letendnum_state;
+ __letendnum_state = TRUE;
+ for (;;)
+  {
+   if (__toktyp == targ1 || __toktyp == targ2)
+    {
+     __letendnum_state = sav_letendnum;
+     return(TRUE);
+    }
+   switch ((byte) __toktyp) {
+    case ENDMODULE: case ENDPRIMITIVE:
+     goto done;
+    case PRIMITIVE: case MODULE: case MACROMODULE:
+    __unget_vtok();
+    goto done;
+   }
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
+   __get_vtok();
+  }
+done:
+ __letendnum_state = sav_letendnum;
+ return(FALSE);
+}
+
+/*
+ * skip to 3 symbols - if not found only end module/primitive ends
+ * est of module not checked
+ * return T if found targ1 else F
+ */
+extern int32 __vskipto3_modend(int32 targ1, int32 targ2, int32 targ3)
+{
+ int32 sav_letendnum;
+
+ /* SJM 11/30/04 - save and restore edge illegal num errors when skip mod */
+ sav_letendnum = __letendnum_state;
+ __letendnum_state = TRUE;
+ for (;;)
+  {
+   if (__toktyp == targ1 || __toktyp == targ2 || __toktyp == targ3)
+    {
+     __letendnum_state = sav_letendnum;
+     return(TRUE);
+    }
+   switch ((byte) __toktyp) {
+    case ENDMODULE: case ENDPRIMITIVE:
+     goto done;
+    case PRIMITIVE: case MODULE: case MACROMODULE:
+     __unget_vtok();
+     goto done;
+   }
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
+   __get_vtok();
+  }
+done:
+ __letendnum_state = sav_letendnum;
+ return(FALSE);
+}
+
+/*
+ * skip to any start of stmt/item symbol
+ * general sync algorithm.
+ *
+ * if finds specific thing, return T
+ * else sets syncto_class and return F
+ *
+ * possibilities are:
+ *   SYNC_FLEVEL - file level mod/prim
+ *   SYNC_MODLEVEL - module level declaration or item
+ *   SYNC_STMT - start of statement
+ *   SYNC_TARG - target found and return T
+ */
+extern int32 __vskipto_any(int32 targ1)
+{
+ /* for interactive just give up on any error - but must skip to end of line */
+ if (__iact_state) longjmp(__iact_jmpbuf, 1);
+
+ for (;;)
+  {
+   if (__toktyp == targ1) { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_syncto_tokclass((byte) __toktyp)) break;
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to statement token %s",
+     prt2_vtok(targ1));
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+extern int32 __vskipto2_any(int32 targ1, int32 targ2)
+{
+ if (__iact_state) longjmp(__iact_jmpbuf, 1);
+ for (;;)
+  {
+   if (__toktyp == targ1 || __toktyp == targ2)
+    { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_syncto_tokclass((byte) __toktyp)) break;
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to statement token %s",
+     prt2_vtok(targ1));
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+extern int32 __vskipto3_any(int32 targ1, int32 targ2, int32 targ3)
+{
+ if (__iact_state) longjmp(__iact_jmpbuf, 1);
+ for (;;)
+  {
+   if (__toktyp == targ1 || __toktyp == targ2 || __toktyp == targ3)
+    { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_syncto_tokclass((byte) __toktyp)) break;
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to statement token %s",
+     prt2_vtok(targ1));
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+extern int32 __vskipto4_any(int32 targ1, int32 targ2, int32 targ3, int32 targ4)
+{
+ if (__iact_state) longjmp(__iact_jmpbuf, 1);
+ for (;;)
+  {
+   if (__toktyp == targ1 || __toktyp == targ2 || __toktyp == targ3
+    || __toktyp == targ4)
+    { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_syncto_tokclass((byte) __toktyp)) break;
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to statement token %s",
+     prt2_vtok(targ1));
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+/*
+ * skip to end of list of port port decl element
+ *
+ * special case because resyncs at port name keyword ID 
+ * notice can't be used for new list of parameters form
+ */
+extern int32 __vskipto_lofp_end()
+{
+ /* only for list of ports decl so can't be invoked from iact state */ 
+ if (__iact_state) __misc_terr(__FILE__, __LINE__);
+
+ for (;;)
+  {
+   /* semi can end because end of list ) always followed by ; */
+   if (__toktyp == INPUT || __toktyp == OUTPUT || __toktyp == INOUT
+    || __toktyp == RPAR || __toktyp == SEMI)
+    { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_syncto_tokclass((byte) __toktyp)) break;
+   if (__toktyp == TEOF)
+    __fterr(315,
+     "unexpected EOF while skipping over list of port declaration");
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+/*
+ * skip to end of list of port port decl element from inside port name comma
+ * list
+ *
+ * special case because resyncs at port name keyword ID 
+ * notice can't be used for new list of parameters form
+ */
+extern int32 __vskipto2_lofp_end()
+{
+ /* only for list of ports decl so can't be invoked from iact state */ 
+ if (__iact_state) __misc_terr(__FILE__, __LINE__);
+
+ for (;;)
+  {
+   /* semi can end because end of list ) always followed by ; */
+   if (__toktyp == INPUT || __toktyp == OUTPUT || __toktyp == INOUT
+    || __toktyp == RPAR || __toktyp == SEMI || __toktyp == COMMA)
+    { __syncto_class = SYNC_TARG; return(TRUE); }
+
+   if (set_syncto_tokclass((byte) __toktyp)) break;
+
+   if (__toktyp == TEOF)
+    __fterr(315,
+     "unexpected EOF while skipping over list of port declaration");
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+/*
+ * set __token class - return T if not a sync to
+ */
+static int32 set_syncto_tokclass(byte ttyp) 
+{
+ switch (ttyp) {
+  /* file level item */
+  case ENDMODULE: case ENDPRIMITIVE:
+   __syncto_class = SYNC_FLEVEL;
+   break;
+  case PRIMITIVE: case MODULE: case MACROMODULE:
+   __unget_vtok();
+   __syncto_class = SYNC_FLEVEL;
+   break;
+  /* module item end - must assume next things is good item */
+  /* because [id] [type](inst) is common */
+  case ENDFUNCTION: case ENDTASK: case ENDSPECIFY:
+   __syncto_class = SYNC_MODLEVEL;
+   break;
+  case INITial: case ALWAYS:
+  case DEFPARAM: case SPECIFY: case TASK: case FUNCTION: 
+  case PARAMETER: case ASSIGN:
+  case INPUT: case OUTPUT: case INOUT:
+  case WIRE: case TRI: case TRI0: case TRI1: case TRIAND: 
+  case TRIOR: case TRIREG: case WAND: case WOR: case SUPPLY0:
+  case SUPPLY1: case REG: case INTEGER: case TIME: case REAL: case REALTIME:
+  case EVENT:
+   __unget_vtok();
+   __syncto_class = SYNC_MODLEVEL;
+   break;
+  /* stmt begin things - sync so next get tok will be stmt start */
+  /* these are likely module item previous ends and assume so */
+  /* but could be part of wrong list of stmts */
+  /* SJM 01/14/1999 - moved else from statement start case to stmt end */
+  /* LOOKATME - is there a problem with this? */
+  case END: case JOIN: case ENDCASE: case ELSE:
+   __syncto_class = SYNC_STMT;
+   break;
+  case SHARP: case AT:
+  case IF: case IFNONE: case CASE: case CASEX: case CASEZ:
+  case Begin: case FORK: case CAUSE:
+  case FOREVER: case REPEAT: case WHILE: case FOR: case WAIT:
+  case DISABLE: case FORCE: case RELEASE:
+   __unget_vtok();
+   __syncto_class = SYNC_STMT;
+   break;
+  default: return(FALSE);
+ } 
+ return(TRUE);
+}
+
+/*
+ * for specify normal skip to any except also specify item level
+ */
+extern int32 __spec_vskipto_any(int32 targ1)
+{
+ for (;;)
+  {
+   if (__toktyp == targ1) { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_syncto_tokclass((byte) __toktyp))
+    { 
+     if (__toktyp == IF) __syncto_class = SYNC_SPECITEM;
+     break;
+    }
+   if (set_specitem_class()) break;
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to statement token %s",
+     prt2_vtok(targ1));
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+extern int32 __spec_vskipto2_any(int32 targ1, int32 targ2)
+{
+ for (;;)
+  {
+   if (__toktyp == targ1 || __toktyp == targ2)
+    { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_syncto_tokclass((byte) __toktyp))
+    { 
+     if (__toktyp == IF) __syncto_class = SYNC_SPECITEM;
+     break;
+    }
+   if (set_specitem_class()) break;
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to statement token %s",
+     prt2_vtok(targ1));
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+extern int32 __spec_vskipto3_any(int32 targ1, int32 targ2, int32 targ3)
+{
+ for (;;)
+  {
+   if (__toktyp == targ1 || __toktyp == targ2 || __toktyp == targ3)
+    { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_syncto_tokclass((byte) __toktyp))
+    { 
+     if (__toktyp == IF) __syncto_class = SYNC_SPECITEM;
+     break;
+    }
+   if (set_specitem_class()) break;
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to statement token %s",
+     prt2_vtok(targ1));
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+/*
+ * set specify level for token that can begin specify section
+ * returns T if found sync to place
+ * this needs to access global toktyp and token 
+ * notice - cannot sync to most common ( for path start
+ */
+static int32 set_specitem_class(void)
+{
+ if (__toktyp == ID && *__token == '$')
+  {
+   if (__fr_tcnam(__token) != -1)
+    {
+     __unget_vtok();
+     __syncto_class = SYNC_SPECITEM;
+     return(TRUE);
+    } 
+  }
+ return(FALSE);
+}
+
+/*
+ * skip to udp symbol
+ */
+/*
+ * skip to udp symbol - 
+ * return T if found targ1 else F
+ */
+extern int32 __udp_vskipto_any(int32 targ1)
+{
+ for (;;)
+  {
+   if (__toktyp == targ1) { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_udpsyncto((byte) __toktyp)) break;
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+extern int32 __udp_vskipto2_any(int32 targ1, int32 targ2)
+{
+ for (;;)
+  {
+   if (__toktyp == targ1 || __toktyp == targ2)
+    { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_udpsyncto((byte) __toktyp)) break;
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+extern int32 __udp_vskipto3_any(int32 targ1, int32 targ2, int32 targ3)
+{
+ for (;;)
+  {
+   if (__toktyp == targ1 || __toktyp == targ2 || __toktyp == targ3)
+    { __syncto_class = SYNC_TARG; return(TRUE); }
+   if (set_udpsyncto((byte) __toktyp)) break;
+   if (__toktyp == TEOF)
+    __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
+   __get_vtok();
+  }
+ return(FALSE);
+}
+
+/*
+ * set udp token class - return T if token not a sync to
+ */
+static int32 set_udpsyncto(byte ttyp) 
+{
+ switch (ttyp) {
+  /* file level item */
+  case ENDMODULE: case ENDPRIMITIVE:
+   __syncto_class = SYNC_FLEVEL;
+   break;
+  case PRIMITIVE: case MODULE: case MACROMODULE:
+   __unget_vtok();
+   __syncto_class = SYNC_FLEVEL;
+   break;
+ case INPUT: case OUTPUT: case REG: case TABLE:
+   __unget_vtok();
+   __syncto_class = SYNC_UDPLEVEL;
+   break;
+  default: return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ *  LIB. INPUT ROUTINES
+ *  BEWARE - must open file, use all, close file before using other get func.
+ */
+
+/*
+ * ascii character table for processing ID tokens
+ * 0 - continue, 1 - end and don't back up, 2 - end and back up
+ * notice here any non white space contiguous chars good since can be path
+ */
+static char __lbctab[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 1, 0, 0,  /* ^i,\n,\f \r */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* sp */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2   /* eof */
+};
+
+/*
+ * get a -f file option token - only white space and semi separation
+ * (modified from yylex in "The Unix Programming Environment" p. 337)
+ * notice no push back token here
+ * also handles normal / * and // comments
+ */
+extern int32 __get_cmdtok(FILE *f)
+{
+ /* the char must be an int32 for machine independence */
+ register int32 c;
+ register char *cp;
+ int32 namlen;
+
+again:
+ while ((c = getc(f)) == ' ' || c == '\t' || c == '\f' || c == '\r') ;
+ /* SJM 12/06/03 - only new line needs line cnt inc and pushed back */
+ if (c == '\n') { __lin_cnt++; goto again; }
+
+ /* // or / * comments legal */
+ if (c == '/') if (get_cmdcomment(f)) goto again;
+
+ /* get here by falling through case */
+ for (cp = __token, namlen = 0;;)
+  {
+   if (++namlen >= IDCHARS - 1)
+    __pv_ferr(919,
+     "command option token too long (%d) - ignored", IDCHARS - 1);
+
+   *cp++ = c;
+   if ((c = getc(f)) == EOF) return(TEOF);
+   switch (__lbctab[c & 0x7f]) {
+    case 0: continue;         /* normal in ID char */
+    case 1: goto end_nam;     /* white space token end - swallow it */
+    /* or lin_cnt wrong for errors */
+    case 2: ungetc(c, f); goto end_nam; /* non white space end token */
+   }
+  }
+end_nam:
+ *cp = '\0';
+ /* does not need canonical token since not related to output */
+ /* Verilog world options are case sensitive */
+ return(ID);
+}
+
+/*
+ * ascii character table for processing config tokens
+ * 0 - continue, 1 - end and don't back up, 2 - end and back up
+ * notice here any non white space contiguous chars good since can be path
+ */
+static char cfgctab[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 1, 0, 0,  /* ^i,\n,\f \r */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,  /* sp, , */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,  /* ; */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2   /* eof */
+};
+
+/*
+ * get a cfg -L or default map.lib file token 
+ * (modified from yylex in "The Unix Programming Environment" p. 337)
+ * AIV 10/30/03 - added for new 2001 cfg feature
+ *
+ * notice no push back token here and tok typ glb not set
+ * also handles normal / * and // comments
+ *
+ * allowing ' and " quotes and back slash escaping of quotes in quoted
+ * strings but not allowing embedded new lines in tokens
+ * 
+ * complicated because need warnings and must handle quoting and
+ * escaping but only within quoted names 
+ */
+extern int32 __get_cfgtok(FILE *f)
+{
+ /* the char must be an int32 for machine independence */
+ register int32 c;
+ register char *cp;
+ int32 namlen, ttyp, qchar;
+
+again:
+ while ((c = getc(f)) == ' ' || c == '\t' || c == '\f' || c == '\r') ;
+ /* SJM 12/06/03 - only new line needs line cnt inc and pushed back */
+ if (c == '\n') { __lin_cnt++; goto again; }
+ /* AIV since push back ; if ';' */
+ if (c == ';') return(CFG_SEMI);
+ if (c == ',') return(CFG_COMMA);
+ /* // or / * comments legal */
+ if (c == '/') if (get_cmdcomment(f)) goto again;
+
+ if (c == '\'' || c == '"')
+  {
+   qchar = c;
+   c = getc(f);
+   /* get here by falling through case */
+   for (cp = __token, namlen = 0;;)
+    {
+     if (++namlen >= IDCHARS - 1)
+      {
+       __pv_ferr(919,
+        "config file token (path?) too long (%d) - rest discarded",
+        IDCHARS - 1);
+       for (;;)
+        {
+         if (c == '\\') { c = getc(f); continue; }
+         if (c == qchar) break;
+         if (c == EOF) return(CFG_EOF);
+         c = getc(f);
+        }
+       *cp = '\0';
+       return(CFG_ID);
+      }
+     /* escaped chars legal but only in quoted strings */
+     if (c == '\\')
+      {
+       c = getc(f);
+       if (c == EOF) return(CFG_EOF);
+       *cp++ = c;
+      }
+     else
+      {
+       /* ending quote not part of ID and can't be key word32 */
+       if (c == qchar)
+        {
+         if (strcmp(__token, "") == 0)
+          {
+           __pv_fwarn(3125, "quoted map library token empty string");
+          }
+         break;
+        }
+      } 
+     if (c == '\n')
+      {
+       if (strcmp(__token, "") == 0)
+        {
+         __pv_fwarn(3126,
+          "quoted map library token contains embedded new line");
+        }
+      }
+     *cp++ = c;
+     c = getc(f);
+    }
+   *cp = '\0';
+   return(CFG_ID);
+  }
+
+ /* get here by falling through case */
+ for (cp = __token, namlen = 0;;)
+  {
+   if (++namlen >= IDCHARS - 1)
+    __pv_ferr(919,
+     "config file token (path?) too long (%d) - rest discarded", IDCHARS - 1);
+
+   *cp++ = c;
+   if ((c = getc(f)) == EOF) { __toktyp = CFG_EOF; return(CFG_EOF); }
+   switch (cfgctab[c & 0x7f]) {
+    case 0: continue;         /* normal in ID char */
+    case 1: goto end_nam;     /* white space token end - swallow it */
+    case 2: ungetc(c, f); goto end_nam; /* non white space end token */
+   }
+  }
+end_nam:
+ *cp = '\0';
+ ttyp = get_cfgkeywrd(__token);
+ return(ttyp);
+}
+
+/*
+ * look up a cfg file ID and convert to a keyword NUMBER
+ *
+ * notice keyword numbers disjoint32 from and overlap Verilog keywords 
+ * FIXME - should use binary search
+ */
+static int32 get_cfgkeywrd(char *tstr)
+{
+ if (strcmp(tstr, "library") == 0) return(CFG_LIBRARY);
+ if (strcmp(tstr, "config") == 0) return(CFG_CFG);
+ if (strcmp(tstr, "design") == 0) return(CFG_DESIGN);
+ if (strcmp(tstr, "liblist") == 0) return(CFG_LIBLIST);
+ if (strcmp(tstr, "instance") == 0) return(CFG_INSTANCE);
+ if (strcmp(tstr, "cell") == 0) return(CFG_CELL);
+ if (strcmp(tstr, "use") == 0) return(CFG_USE);
+ if (strcmp(tstr, "endconfig") == 0) return(CFG_ENDCFG);
+ if (strcmp(tstr, "default") == 0) return(CFG_DEFAULT);
+ return(CFG_ID);
+}
+
+/*
+ * convert cfg toktyp number to name
+ */
+extern char *__to_cfgtoknam(char *s, int32 ttyp)
+{ 
+ switch (ttyp) {
+  case CFG_UNKNOWN: strcpy(s, "??CFG-UNKNOWN??"); break;
+  case CFG_ID: strcpy(s, __token); break;
+  case CFG_COMMA: strcpy(s, ","); break;
+  case CFG_SEMI: strcpy(s, ";"); break;
+  case CFG_EOF: strcpy(s, "**CFG EOF**"); break;
+  case CFG_LIBRARY: strcpy(s, "library"); break;
+  case CFG_CFG: strcpy(s, "config"); break;
+  case CFG_INCLUDE: strcpy(s, "include"); break;
+  case CFG_DESIGN: strcpy(s, "design"); break;
+  case CFG_LIBLIST: strcpy(s, "liblist"); break;
+  case CFG_INSTANCE: strcpy(s, "instance"); break;
+  case CFG_CELL: strcpy(s, "cell"); break;
+  case CFG_USE: strcpy(s, "use"); break;
+  case CFG_ENDCFG: strcpy(s, "endconfig"); break; 
+  case CFG_DEFAULT: strcpy(s, "default"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * get a comment
+ */
+static int32 get_cmdcomment(FILE *f)
+{
+ register int32 c;
+ int32 c2;
+
+ /* // to EOL comment */
+ if ((c2 = getc(f)) == '/')
+  {
+   while ((c = getc(f)) != '\n') if (c == EOF) { ungetc(c, f); return(TRUE); }
+   ungetc(c, f);
+   return(TRUE);
+  }
+ /* slash-star comments don't nest */
+ if (c2 == '*')
+  {
+more_comment:
+   while ((c = getc(f)) != '*')
+    {
+     if (c == EOF) { ungetc(c, f); return(TRUE); }
+     if (c == '\n') __lin_cnt++;
+     if (c == '/')
+      {
+       if ((c2 = getc(f)) == '*')
+        {
+         __pv_fwarn(622, "nested /* in /* style -f argument file comment");
+         continue;
+        }
+       c = c2;
+      }
+    }
+
+got_star:
+   if ((c = getc(f)) == '/') return(TRUE);
+   if (c == '*') goto got_star;
+   if (c == '\n') __lin_cnt++;
+   goto more_comment;
+  }
+ /* / not followed by / or * so put back and return SLASH token */
+ ungetc(c2, f);
+ return(FALSE);
+}
+
+/*
+ * SYMBOL TABLE ROUTINES
+ */
+
+/*
+ * locate a currently accessible symbol - for non path qualified names
+ * use __find_sym if needs to be addded when not found
+ * notice this works for frozen symbol tables since get sym determines type
+ *
+ * LOOKATME - could make variable routine if if in this inner loop to slow
+ */
+extern struct sy_t *__get_sym_env(char *nam)
+{
+ int32 sti;
+ struct sy_t *syp;
+ struct symtab_t *sytp;
+
+ /* LOOKATME - special convenience variable symbol table could go here */
+ if (!__iact_state)
+  {
+   for (sti = __top_sti; sti >= 0; sti--)
+    {
+     sytp = __venviron[sti];
+     if ((syp = __get_sym(nam, sytp)) != NULL) return(syp);
+    }
+   return(NULL);
+  }
+
+ if (__scope_tskp == NULL)
+  __last_iasytp = __scope_ptr->itip->imsym->el.emdp->msymtab;
+ else __last_iasytp = __scope_tskp->tsksymtab;
+ /* know parent of task is top level module instance and of module is nil */
+ for (; __last_iasytp != NULL; __last_iasytp = __last_iasytp->sytpar)
+  { if ((syp = __get_sym(nam, __last_iasytp)) != NULL) return(syp); }
+ return(NULL);
+}
+
+/*
+ * find a symbol (will add SYM_UNKN symbol if needed)
+ * if needs to be implicit wire decl. caller must add and set net
+ */
+extern struct sy_t *__find_sym(char *nam)
+{
+ register int32 sti;
+ struct sy_t *syp;
+ struct tnode_t *tnp;
+ struct symtab_t *sytp;
+
+ /* top module level is lowest in task/function symbol table stack */
+ for (sti = __top_sti; sti >= 0; sti--)
+  {
+   sytp = __venviron[sti];
+   if ((syp = __get_sym(nam, sytp)) != NULL)
+    { __sym_is_new = FALSE; return(syp); }
+  }
+ sytp = __venviron[__top_sti];
+ tnp = __vtfind(nam, sytp);
+ /* know symbol will be new */
+ /* allocate symbol and fill symbol */
+ __add_sym(nam, tnp);
+ (__venviron[__top_sti]->numsyms)++;
+ syp = tnp->ndp;
+ return(syp);
+}
+
+/*
+ * declare a symbol - caller determines where declared
+ *
+ * this is used to add sym to symbol table - sydecl not set
+ * when real source declaration (maybe implicit) sydecl set
+ */
+extern struct sy_t *__decl_sym(char *nam, struct symtab_t *sytp)
+{
+ struct sy_t *syp;
+ struct tnode_t *tnp;
+
+ if ((syp = __get_sym(nam, sytp)) != NULL)
+  { __sym_is_new = FALSE; return(syp); }
+ tnp = __vtfind(nam, sytp);
+ /* allocate symbol and fill symbol */
+ __add_sym(nam, tnp);
+ (sytp->numsyms)++;
+ return(tnp->ndp);
+}
+
+/*
+ * add a symbol, caller must fill and set type
+ * expects symbol tree node to be inserted in avl tree and passed here
+ * symbol always added to symbol table on top of module/task nesting stack
+ */
+extern void __add_sym(char *snam, struct tnode_t *tnp)
+{
+ struct sy_t *syp;
+
+ syp = (struct sy_t *) __my_malloc(sizeof(struct sy_t));
+ tnp->ndp = syp;
+ __init_sy(syp);
+ syp->synam = pv_stralloc2(snam);
+}
+
+/*
+ * allocate a string from a big block
+ * this must allocate the 1 char null string for `define as flag
+ */
+static char *pv_stralloc2(char *s)
+{
+ char *cp;
+ int32 slen;
+
+ if (*s == '\0') slen = 1; else slen = strlen(s) + 1;
+ cp = nfbig_alloc(slen);
+ __memstr_use += slen;
+ /* this just copies '\0' for "" case */
+ strcpy(cp, s);
+ return(cp);
+}
+
+/*
+ * initialize a symbol
+ * requires set current file and line number
+ */
+extern void __init_sy(struct sy_t *syp)
+{
+ syp->synam = NULL;
+ syp->sytyp = SYM_UNKN;
+ /* notice all symbols add during input phase */
+ syp->sydecl = FALSE;
+ syp->syundefmod = FALSE;
+ syp->sy_impldecl = FALSE;
+ syp->sy_argsmac = FALSE;
+ syp->sy_giabase = FALSE;
+ syp->el.enp = NULL;
+ syp->syfnam_ind = __cur_fnam_ind;
+ syp->sylin_cnt = __lin_cnt;
+ syp->spltsy = NULL;
+}
+
+/*
+ * BALANCED TREE ACCESS ROUTINES NETS
+ * MUST GO HERE BECAUSE GLOBALS USE FIND_NET MECHANISM
+ */
+
+/*
+ * search one symbol table and if found return sym node
+ * call __vtfind if need to add if not found
+ */
+extern struct sy_t *__get_sym(char *nam, struct symtab_t *sytp)
+{
+ struct tnode_t *cur;
+ int32 cv;
+
+ /* interactive bld node accesses frozen symbol table */
+ if (sytp->stsyms != NULL)
+  return(__zget_sym(nam, sytp->stsyms, sytp->numsyms));
+
+ /* FIXME - SJM - 09/16/99 when copied n_head may be non nil for empty tab */
+ if (sytp->n_head == NULL || sytp->numsyms == 0) return(NULL);
+ for (cur = sytp->n_head;;)
+  {
+   if ((cv = strcmp(nam, cur->ndp->synam)) == 0) return(cur->ndp);
+   if ((cur = (cv < 0) ? cur->lp : cur->rp) == NULL) break;
+  }
+ return(NULL);
+}
+
+/*
+ * special vpi/sdf version of get sym that fails for g/i array base name
+ *
+ * LOOKATME - change this if allowing vpi_ access to arrays of gates/insts
+ */
+extern struct sy_t *__get_nongia_sym(char *nam, struct symtab_t *sytp)
+{
+ struct sy_t *syp;
+
+ if ((syp = __get_sym(nam, sytp)) == NULL) return(NULL);
+ if (syp->sy_giabase) return(NULL);
+ return(syp);
+}
+
+/*
+ * find an entry in symbol node tree and add if needed
+ * expects caller to connect in sy_t and fill it
+ */
+extern struct tnode_t *__vtfind(char *nam, struct symtab_t *sytp)
+{
+ register struct tnode_t *cur, *down;
+ struct tnode_t *balpt_par, *bal_pt, *vtnew, *bal_down;
+ int32 cv;
+
+ /* DBG remove --
+ if (sytp->stsyms != NULL) __misc_terr(__FILE__, __LINE__);
+  --- */
+
+ vtnew = NULL;
+ if (sytp->n_head == NULL)
+  { sytp->n_head = alloc_tnode(sytp); return(sytp->n_head); }
+ for (balpt_par = NULL, bal_pt = cur = sytp->n_head;;)
+  {
+   if ((cv = strcmp(nam, cur->ndp->synam)) == 0)
+    { __sym_is_new = FALSE; return(cur); }
+
+   if (cv < 0) { cur->via_dir = BLEFT; down = cur->lp; }
+   else { cur->via_dir = BRIGHT; down = cur->rp; }
+   if (down == NULL)
+    {
+     down = alloc_tnode(sytp);
+     if (cur->via_dir == BLEFT) cur->lp = down; else cur->rp = down;
+     vtnew = down;
+     break;
+    }
+   if (down->bal != BEVEN) { balpt_par = cur; bal_pt = down; }
+   cur = down;
+  }
+
+ /* bal down is one below balance point */
+ if (bal_pt->via_dir == BLEFT) bal_down = bal_pt->lp;
+ else bal_down = bal_pt->rp;
+ /* know all nodes from bal_pt down to but not including new had balance 0 */
+ /* adjust up to but not including balance of new */
+ for (cur = bal_down; cur != vtnew;)
+  {
+   cur->bal = cur->via_dir;
+   if (cur->via_dir == BLEFT) cur = cur->lp; else cur = cur->rp;
+  }
+ /* since only unbalanced by 1 put off doing anything */
+ if (bal_pt->bal == BEVEN) { bal_pt->bal = bal_pt->via_dir; return(vtnew); }
+
+ /* tree got more balanced */
+ /* check for bal and even dir opposite or both even */
+ if ((bal_pt->bal == BEVEN && bal_pt->via_dir == BEVEN)
+  || (bal_pt->bal == BLEFT && bal_pt->via_dir == BRIGHT)
+  || (bal_pt->bal == BRIGHT && bal_pt->via_dir == BLEFT))
+  {
+   bal_pt->bal = BEVEN;
+   return(vtnew);
+  }
+
+ __tmp_head = sytp->n_head;
+ /* these routines may update global __tmp_head */
+ /* tree more out of balance - needs rebalancing */
+ if (bal_down->bal == bal_pt->via_dir) one_rot(bal_pt, bal_down, balpt_par);
+ else two_rot(bal_pt, bal_down, balpt_par);
+ sytp->n_head = __tmp_head;
+
+ return(vtnew);
+}
+
+/*
+ * single rotation
+ */
+static void one_rot(struct tnode_t *bal_pt, struct tnode_t *bal_down, 
+ struct tnode_t *balpt_par)
+{
+ if (bal_pt->via_dir == BLEFT)
+  {
+   bal_pt->lp = bal_down->rp;
+   bal_down->rp = bal_pt;
+  }
+ else
+  {
+   bal_pt->rp = bal_down->lp;
+   bal_down->lp = bal_pt;
+  }
+ bal_pt->bal = bal_down->bal = BEVEN;
+
+ if (balpt_par == NULL) __tmp_head = bal_down;
+ else if (balpt_par->via_dir == BLEFT) balpt_par->lp = bal_down;
+ else balpt_par->rp = bal_down;
+}
+
+/*
+ * double rotation
+ */
+static void two_rot(struct tnode_t *bal_pt, struct tnode_t *bal_down,
+ struct tnode_t *balpt_par)
+{
+ struct tnode_t *tmp;
+
+ if (bal_pt->via_dir == BLEFT)
+  {
+   tmp = bal_down->rp;
+   bal_down->rp = tmp->lp;
+   tmp->lp = bal_down;
+   bal_pt->lp = tmp->rp;
+   tmp->rp = bal_pt;
+  }
+ else
+  {
+   tmp = bal_down->lp;
+   bal_down->lp = tmp->rp;
+   tmp->rp = bal_down;
+   bal_pt->rp = tmp->lp;
+   tmp->lp = bal_pt;
+  }
+
+ /* update the balances */
+ if (tmp->bal == BEVEN) bal_pt->bal = bal_down->bal = BEVEN;
+ else if (tmp->bal == bal_pt->via_dir)
+  {
+   if (bal_pt->via_dir == BRIGHT) bal_pt->bal = BLEFT;
+   else if (bal_pt->via_dir == BLEFT) bal_pt->bal = BRIGHT;
+   else bal_pt->bal = BEVEN;
+   bal_down->bal = BEVEN;
+  }
+ else { bal_pt->bal = BEVEN; bal_down->bal = bal_pt->via_dir; }
+ tmp->bal = BEVEN;
+
+ /* point node above balance point to new high node */
+ if (balpt_par == NULL) __tmp_head = tmp;
+ else if (balpt_par->via_dir == BLEFT) balpt_par->lp = tmp;
+ else balpt_par->rp = tmp;
+}
+
+/*
+ * allocate a node
+ */
+static struct tnode_t *alloc_tnode(struct symtab_t *sytp)
+{
+ struct tnode_t *tnp;
+ register struct tnblk_t *tnbp; 
+
+ if (!sytp->freezes)
+  tnp = (struct tnode_t *) __my_malloc(sizeof(struct tnode_t));
+ else
+  {
+   if (__tnblk_nxti == -1)
+    {
+     tnbp = (struct tnblk_t *) __my_malloc(sizeof(struct tnblk_t));
+     tnbp->tnblks = (struct tnode_t *) __my_malloc(BIG_ALLOC_SIZE);
+     tnbp->tnblknxt = __hdr_tnblks;
+     __hdr_tnblks = tnbp;
+     __tnblk_nxti = 0;
+    }
+   tnp = (struct tnode_t *) &(__hdr_tnblks->tnblks[__tnblk_nxti]);
+   if (++__tnblk_nxti > ((BIG_ALLOC_SIZE/sizeof(struct tnode_t)) - 1))
+     __tnblk_nxti = -1;
+  }
+
+ tnp->lp = tnp->rp = NULL;
+ tnp->bal = BEVEN;
+ tnp->via_dir = BEVEN;
+ __sym_is_new = TRUE;
+ tnp->ndp = NULL;
+ return(tnp);
+}
+
+/*
+ * find a symbol in the current scope
+ */
+
+/*
+ * get a symbol in frozen table - notice nsyms is num. not last
+ */
+extern struct sy_t *__zget_sym(char *nam, struct sy_t **syms, word32 nsyms)
+{
+ register int32 l, h;
+ register int32 m, cv;
+
+ if (nsyms == 0) return(NULL);
+ l = 0; h = nsyms - 1;
+ for (;;)
+  {
+   m = (l + h)/2;
+   if ((cv = strcmp(syms[m]->synam, nam)) == 0) return(syms[m]);
+   if (cv < 0) l = m + 1; else h = m - 1;
+   if (h < l) break;
+  }
+ return(NULL);
+}
+
+/*
+ * allocate a new empty symbol table
+ */
+extern struct symtab_t *__alloc_symtab(int32 freezes)
+{
+ struct symtab_t *sytp;
+
+ sytp = (struct symtab_t *) __my_malloc(sizeof(struct symtab_t));
+ sytp->n_head = NULL;
+ sytp->stsyms = NULL;
+ sytp->sytpar = NULL;
+ sytp->sytsib = NULL;
+ sytp->sytofs = NULL;
+ sytp->sypofsyt = NULL;
+ sytp->numsyms = 0;
+ sytp->freezes = freezes;
+ return(sytp);
+}
+
+/*
+ * MISC. REPRESENTATION CHANGE RROUTINES
+ */
+
+/*
+ * routine to find index in ip table and it roots of top level module 
+ *
+ * here __top_ipind is sorted array of indexes into top_iptab which
+ * is || to __it_roots
+ */
+extern int32 __ip_indsrch(char *nam)
+{
+ int32 l, h;
+ register int32 m, cv;
+
+ if (__numtopm == 0) return(-1);
+ l = 0; h = __numtopm - 1;
+ for (;;)
+  {
+   m = (l + h)/2;
+   if ((cv = strcmp(__top_itab[__top_ipind[m]]->imsym->synam, nam)) == 0)
+    return(__top_ipind[m]);
+   if (cv < 0) l = m + 1; else h = m - 1;
+   if (h < l) break;
+  }
+ return(-1);
+}
+
+/*
+ * convert an identifier to either global or id name
+ */
+extern char *__to_idnam(struct expr_t *xp)
+{
+ char *chp; 
+
+ if (xp->optyp == ID)
+  {
+   if (xp->locqualnam) return(xp->ru.qnchp); else return(xp->lu.sy->synam);
+  }
+ else if (xp->optyp == GLBREF) chp = xp->ru.grp->gnam;
+ else { chp = NULL;  __case_terr(__FILE__, __LINE__); }
+ return(chp);
+}
+
+/*
+ * convert port name to string - maybe unnamed (chp nil) 
+ */
+extern char *__to_mpnam(char *s, char *chp)
+{
+ if (chp == NULL) strcpy(s, "*unnamed*"); else strcpy(s, chp);
+ return(s);
+}
+
+
+/*
+ * convert from a wire type token number to its wtyp value (-1 if no match)
+ */
+extern int32 __fr_wtnam(int32 ttyp)
+{
+ int32 wtyp;
+
+ switch ((byte) ttyp) {
+  case WIRE: wtyp = N_WIRE; break;
+  case TRI: wtyp = N_TRI; break;
+  case TRI0: wtyp = N_TRI0; break;
+  case TRI1: wtyp = N_TRI1; break;
+  case TRIOR: wtyp = N_TRIOR; break;
+  case TRIAND: wtyp = N_TRIAND; break;
+  case TRIREG: wtyp = N_TRIREG; break;
+  case WAND: wtyp = N_WA; break;
+  case WOR: wtyp = N_WO; break;
+  /* notice pulls never explicitly declared */ 
+  case SUPPLY0: wtyp = N_SUPPLY0; break;
+  case SUPPLY1: wtyp = N_SUPPLY1; break;
+  case REG: wtyp = N_REG; break;
+  case TIME: wtyp = N_TIME; break;
+  case INTEGER: wtyp = N_INT; break;
+  case REAL: case REALTIME: wtyp = N_REAL; break;
+  case EVENT: wtyp = N_EVENT; break;
+  default: wtyp = -1; break;
+ }
+ return(wtyp);
+}
+
+/*
+ * convert a net to its wire type 
+ */
+extern char *__to_wtnam(char *s, struct net_t *np)
+{
+ return(__to_wtnam2(s, np->ntyp));
+}
+
+/*
+ * convert a wire type value into a output name (2nd variant constant wtyp)
+ * not for I/O port types
+ */
+extern char *__to_wtnam2(char *s, word32 typ)
+{
+ switch ((byte) typ) {
+  case N_WIRE: strcpy(s, "wire"); break;
+  case N_TRI: strcpy(s, "tri"); break;
+  case N_TRI0: strcpy(s, "tri0"); break;
+  case N_TRI1: strcpy(s, "tri1"); break;
+  case N_TRIOR: strcpy(s, "wor"); break;
+  case N_TRIAND: strcpy(s, "wand"); break;
+  case N_TRIREG: strcpy(s, "trireg"); break;
+  case N_WA: strcpy(s, "wand"); break;
+  case N_WO: strcpy(s, "wor"); break;
+  case N_SUPPLY0: strcpy(s, "supply0"); break;
+  case N_SUPPLY1: strcpy(s, "supply1"); break;
+  /* these need special syntax for declaration */
+  case N_REG: strcpy(s, "reg"); break;
+  case N_TIME: strcpy(s, "time"); break;
+  case N_INT: strcpy(s, "integer"); break;
+  case N_REAL: strcpy(s, "real"); break;
+  case N_EVENT: strcpy(s, "event"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * convert an i/o port type to a name (use lower case for these)
+ */
+extern char *__to_ptnam(char *s, word32 ptyp)
+{
+ switch ((byte) ptyp) {
+  case IO_IN: strcpy(s, "input"); break;
+  case IO_OUT: strcpy(s, "output"); break;
+  case IO_BID: strcpy(s, "inout"); break;
+  case IO_UNKN: strcpy(s, "-unknown-"); break;
+  case NON_IO: strcpy(s, "-non-io-"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * convert a wire splitting type to scalared/vectored state
+ */
+extern char *__to_splt_nam(char *s, int32 sptyp)
+{
+ if (sptyp == SPLT_SCAL) strcpy(s, "scalared");
+ else if (sptyp == SPLT_VECT) strcpy(s, "vectored");
+ else { __case_terr(__FILE__, __LINE__);  strcpy(s,""); }
+ return(s);
+}
+
+/*
+ * convert from a token type number to a strength symbolic constant
+ * return NO_STREN on not a strength - checking must be elsewhere
+ */
+extern word32 __fr_stren_nam(int32 ttyp)
+{
+ switch ((byte) ttyp) {
+  case HIGHZ0: case HIGHZ1: return(ST_HIGHZ);
+  case SMALL: return(ST_SMALL);
+  case MEDIUM: return(ST_MEDIUM);
+  case WEAK0: case WEAK1: return(ST_WEAK);
+  case LARGE: return(ST_LARGE);
+  case PULL0: case PULL1: return(ST_PULL);
+  case STRONG0: case STRONG1: return(ST_STRONG);
+  case SUPPLY0: case SUPPLY1: return(ST_SUPPLY);
+ }
+ return(NO_STREN);
+}
+
+/*
+ * convert a strength pair to a name
+ * use this to write cap strength
+ */
+extern char *__to_stren_nam(char *s, int32 stren1, int32 stren2)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ if (__is_capstren(stren1))
+  sprintf(s, "(%s)", __to1_stren_nam(s1, stren1, 2));
+ else sprintf(s, "(%s, %s)", __to1_stren_nam(s1, stren1, 0),
+  __to1_stren_nam(s2, stren2, 1));
+ return(s);
+}
+
+/*
+ * convert a stval coded strength name
+ * not for cap. strength
+ * and notice value coded in 6 bits (i.e. no value in low 2 bits
+ */
+extern char *__to_stval_nam(char *s, word32 stval)
+{
+ int32 st0, st1;
+ char s1[RECLEN], s2[RECLEN];
+
+ st0 = (int32) (stval >> 3) & 7;
+ st1 = (int32) (stval) & 7;
+ sprintf(s, "(%s, %s)", __to1_stren_nam(s1, st0, 0),
+  __to1_stren_nam(s2, st1, 1));
+ return(s);
+}
+
+/*
+ * convert from a strength type and 0/1 value to a strength name
+ * this is source driving strength - not net strength value
+ */
+extern char *__to1_stren_nam(char *s, int32 st, int32 st01dir)
+{
+ switch ((byte) st) {
+  case ST_HIGHZ: strcpy(s, "highz"); break;
+  case ST_SMALL: strcpy(s, "small"); return(s);
+  case ST_MEDIUM: strcpy(s, "medium"); return(s);
+  case ST_WEAK: strcpy(s, "weak"); break;
+  case ST_LARGE: strcpy(s, "large"); return(s);
+  case ST_PULL: strcpy(s, "pull"); break;
+  case ST_STRONG: strcpy(s, "strong"); break;
+  case ST_SUPPLY: strcpy(s, "supply"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ if (st01dir == 0) strcat(s, "0");
+ else if (st01dir == 1) strcat(s, "1");
+ return(s);
+}
+
+/*
+ * return T if strength value is cap. strength
+ */
+extern int32 __is_capstren(int32 st)
+{
+ switch ((byte) st) {
+  case ST_SMALL: case ST_MEDIUM: case ST_LARGE: return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*
+ * convert from a capacitor size constant to a capacitor strength 
+ */
+extern int32 __fr_cap_size(int32 capsiz)
+{
+ int32 st;
+
+ switch ((byte) capsiz) {
+  case CAP_NONE: st = ST_STRONG; break;
+  case CAP_SMALL: st = ST_SMALL; break;
+  case CAP_MED: st = ST_MEDIUM; break;
+  case CAP_LARGE: st = ST_LARGE; break;
+  default: st = ST_STRONG; __case_terr(__FILE__, __LINE__);
+ }
+ return(st);
+}
+
+/*
+ * convert to a capacitor size constant from a capacitor strength 
+ * must catch non cap size strength input before here
+ */
+extern word32 __to_cap_size(int32 st)
+{
+ int32 capsiz;
+
+ switch ((byte) st) {
+  case ST_STRONG: capsiz = CAP_NONE; break;
+  case ST_SMALL: capsiz = CAP_SMALL; break;
+  case ST_MEDIUM: capsiz = CAP_MED; break;
+  case ST_LARGE: capsiz = CAP_LARGE; break;
+  default: capsiz = CAP_NONE; __case_terr(__FILE__, __LINE__);
+ }
+ return(capsiz);
+}
+
+/*
+ * build a $display style 2 char strength string
+ */
+extern char *__to_dispst_str(char *s, word32 st)
+{
+ switch ((byte) st) {
+  case ST_HIGHZ: strcpy(s, "Hi"); break;
+  case ST_SMALL: strcpy(s, "Sm"); break;
+  case ST_MEDIUM: strcpy(s, "Me"); break;
+  case ST_WEAK: strcpy(s, "We"); break;
+  case ST_LARGE: strcpy(s, "La"); break;
+  case ST_PULL: strcpy(s, "Pu"); break;
+  case ST_STRONG: strcpy(s, "St"); break;
+  case ST_SUPPLY: strcpy(s, "Su"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * build a symbol class name
+ */
+extern char *__to_sytyp(char *s, word32 styp)
+{
+ switch ((byte) styp) {
+  case SYM_UNKN: strcpy(s, "--unknown--"); break;
+  case SYM_I: strcpy(s, "instance"); break;
+  case SYM_M: strcpy(s, "module"); break;
+  case SYM_PRIM: strcpy(s, "primitive"); break;
+  case SYM_UDP: strcpy(s, "udp define"); break;
+  case SYM_N: strcpy(s, "variable"); break;
+  case SYM_TSK: strcpy(s, "task"); break;
+  case SYM_STSK: strcpy(s, "systask"); break;
+  case SYM_LB: strcpy(s, "named block"); break;
+  case SYM_F: strcpy(s, "function"); break;
+  case SYM_SF: strcpy(s, "sysfunction"); break;
+  case SYM_DEF: strcpy(s, "preprocessor `define"); break;
+  case SYM_CA: strcpy(s, "continuous assign"); break; 
+  case SYM_PTH: strcpy(s, "delay path"); break;
+  case SYM_TCHK: strcpy(s, "timing check"); break; 
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * build a task type name - tskt is token number
+ */
+extern char *__to_tsktyp(char *s, word32 tskt)
+{
+ switch ((byte) tskt) {
+  case Begin: strcpy(s, "named begin"); break;
+  case FORK: strcpy(s, "named fork"); break;
+  case FUNCTION: strcpy(s, "function"); break;
+  case TASK: strcpy(s, "task"); break;
+ }
+ return(s);
+}
+
+/*
+ * build a statement type name
+ */
+extern char *__to_sttyp(char *s, word32 sttyp)
+{
+ switch ((byte) sttyp) {
+  case S_NULL: strcpy(s, "empty"); break;
+  case S_STNONE: strcpy(s, "empty block"); break;
+  case S_PROCA: strcpy(s, "proc. assign"); break;
+  case S_FORASSGN: strcpy(s, "for initial assign"); break;
+  case S_NBPROCA: strcpy(s, "non-blocking proc. assign"); break;
+  case S_RHSDEPROCA: strcpy(s, "proc. assign (rhs delay/event)"); break;
+  case S_IF: strcpy(s, "if"); break;
+  case S_CASE: strcpy(s, "case/casex/casez"); break;
+  case S_FOREVER: strcpy(s, "forever"); break;
+  case S_REPEAT: strcpy(s, "repeat"); break;
+  case S_WHILE: strcpy(s, "while"); break;
+  case S_WAIT: strcpy(s, "wait"); break;
+  case S_FOR : strcpy(s, "for loop"); break;
+  case S_DELCTRL: strcpy(s, "delay control"); break;
+  case S_NAMBLK : strcpy(s, "named block"); break;
+  case S_UNBLK : strcpy(s, "unnamed block"); break;
+  case S_UNFJ: strcpy(s, "parallel block"); break;
+  case S_TSKCALL: strcpy(s, "task enable"); break;
+  case S_QCONTA: strcpy(s, "quasi-continuous assign"); break;
+  case S_QCONTDEA: strcpy(s, "quasi-continous deassign"); break;
+  case S_CAUSE: strcpy(s, "cause"); break;
+  case S_DSABLE: strcpy(s, "disable"); break;
+  case S_REPSETUP: strcpy(s, "**added loop setup"); break;
+  case S_REPDCSETUP: strcpy(s, "**added repeat event control setup"); break;
+  case S_GOTO: strcpy(s, "**added goto"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * build the quasi-continue statement type name 
+ */
+extern char *__to_qctyp(char *s, word32 qctyp)
+{
+ switch ((byte) qctyp) {
+  case FORCE: strcpy(s, "force"); break;
+  case RELEASE: strcpy(s, "release"); break;
+  case ASSIGN: strcpy(s, "assign"); break;
+  case DEASSIGN: strcpy(s, "deassign"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * build an event type name
+ */
+extern char *__to_tetyp(char *s, word32 tetyp) 
+{
+ switch ((byte) tetyp) {
+  case TE_THRD: strcpy(s, "procedural"); break;
+  case TE_G: strcpy(s, "gate assign"); break;
+  case TE_CA: strcpy(s, "conta assign"); break;
+  case TE_WIRE: strcpy(s, "wire delay"); break;
+  case TE_BIDPATH: strcpy(s, "inout path dest."); break;
+  case TE_MIPD_NCHG: strcpy(s, "MIPD change"); break;
+  case TE_NBPA: strcpy(s, "NB assign"); break;
+  case TE_TFSETDEL: strcpy(s, "tf_ set delay"); break;
+  case TE_SYNC: strcpy(s, "tf_ #0 synchronize"); break;
+  case TE_TFPUTPDEL: strcpy(s, "tf_ delayed strputp"); break;
+  case TE_VPIPUTVDEL: strcpy(s, "vpi_ put value"); break;
+  case TE_VPIDRVDEL: strcpy(s, "vpi_ add drv. chg."); break;
+  case TE_VPICBDEL: strcpy(s, "vpi_ delay cb"); break;
+  case TE_UNKN: 
+   /*FALLTHRU */
+  default:
+   strcpy(s, "**UNKNOWN**");
+   /* __case_terr(__FILE__, __LINE__); */
+ }
+ return(s);
+}
+
+/*
+ * build a net-pin connection/action type
+ */
+extern char *__to_npptyp(char *s, struct net_pin_t *npp) 
+{
+ char s1[RECLEN];
+
+ switch ((byte) npp->npntyp) {
+  case NP_ICONN: strcpy(s, "instance port"); break;
+  case NP_PB_ICONN: strcpy(s, "instance per bit port"); break;
+  case NP_MDPRT: strcpy(s, "module port"); break;
+  case NP_PB_MDPRT: strcpy(s, "module per bit port"); break;
+  case NP_MIPD_NCHG: strcpy(s, "MIPD input/inout port"); break;
+  case NP_CONTA:
+   if (npp->elnpp.ecap->ca_pb_sim) strcpy(s, "per bit cont. assign lvalue"); 
+   else strcpy(s, "cont. assign lvalue"); break;
+   break;
+  case NP_TFRWARG: strcpy(s, "tf_ PLI rw arg wire driver"); break;
+  case NP_VPIPUTV: strcpy(s, "vpi_put_value wire driver"); break;
+  case NP_GATE: strcpy(s, "gate terminal"); break;
+  case NP_TRANIF: strcpy(s, "tranif enable"); break;
+  case NP_TCHG:
+   sprintf(s, "bit change(%s)", __to_nppsubtyp(s1, npp->chgsubtyp));
+   break;
+  case NP_PULL: strcpy(s, "pull driver"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * build the net change subtype name 
+ */
+static char *__to_nppsubtyp(char *s, word32 subtyp)
+{
+ switch ((byte) subtyp) {
+  case NPCHG_TCSTART: strcpy(s, "tchk start ref."); break;
+  case NPCHG_TCCHK: strcpy(s, "tchk data end"); break;
+  case NPCHG_PTHSRC: strcpy(s, "path source"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * build a delay type name string
+ */
+extern char *__to_deltypnam(char *s, word32 dtyp)
+{
+ switch ((byte) dtyp) {
+   case DT_NONE: strcpy(s, "?none?"); break; 
+   case DT_1V: strcpy(s, "one"); break;
+   case DT_IS1V: case DT_IS1V1: case DT_IS1V2:
+    strcpy(s, "one instance specific");
+    break;
+   case DT_4V: strcpy(s, "(r, f, toz)"); break;
+   case DT_IS4V: case DT_IS4V1: case DT_IS4V2:
+    strcpy(s, "(r, f, toz) instance specific");
+    break;
+   case DT_16V: strcpy(s, "path 2,3,6,12 value"); break;
+   case DT_IS16V: case DT_IS16V1: case DT_IS16V2:
+     strcpy(s, "path 2,3,6,12 value instance specific");
+     break;
+   case DT_1X: strcpy(s, "one non constant"); break;
+   case DT_4X: strcpy(s, "(r, f, toz) non constant"); break;
+   case DT_PTHDST: strcpy(s, "internal path descriptor non"); break;
+   case DT_CMPLST: strcpy(s, "translation time expression list"); break;
+   default: __case_terr(__FILE__, __LINE__);
+  }
+ return(s);
+}
+
+/*
+ * convert timing check type to name
+ */
+extern char *__to_tcnam(char *s, word32 tctyp) 
+{
+ switch ((byte) tctyp) {
+  case TCHK_SETUP: strcpy(s, "$setup"); break;
+  case TCHK_HOLD: strcpy(s, "$hold"); break;
+  case TCHK_WIDTH: strcpy(s, "$width"); break;
+  case TCHK_PERIOD: strcpy(s, "$period"); break;
+  case TCHK_SKEW: strcpy(s, "$skew"); break;
+  case TCHK_RECOVERY: strcpy(s, "$recovery"); break;
+  case TCHK_SETUPHOLD: strcpy(s, "$setuphold"); break;
+  case TCHK_NOCHANGE: strcpy(s, "$nochange"); break;
+  /* SJM 12/15/03 - new 2001 timing checks - if used not read with warn */
+  case TCHK_FULLSKEW: strcpy(s, "$fullskew"); break;
+  case TCHK_REMOVAL: strcpy(s, "$removal"); break;
+  case TCHK_RECREM: strcpy(s, "$recrem"); break;
+  case TCHK_TIMESKEW: strcpy(s, "$timeskew"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * convert timing check name to type number - returns -1 if not found
+ * expected the leading $ 
+ */
+extern int32 __fr_tcnam(char *tcnam)
+{
+ if (*tcnam != '$') return(-1);
+ switch (tcnam[1]) {
+  case 'f':
+   if (strcmp(&(tcnam[2]), "ullskew") == 0) return(TCHK_FULLSKEW);
+   break;
+  case 'h': if (strcmp(&(tcnam[2]), "old") == 0) return(TCHK_HOLD); break;
+  case 'n':
+   if (strcmp(&(tcnam[2]), "ochange") == 0) return(TCHK_NOCHANGE); break;
+  case 'p': if (strcmp(&(tcnam[2]), "eriod") == 0) return(TCHK_PERIOD); break;
+  case 'r':
+   /* SJM - 11/21/03 - must also recognize recrem */
+   if (strcmp(&(tcnam[2]), "ecovery") == 0) return(TCHK_RECOVERY);
+   if (strcmp(&(tcnam[2]), "ecrem") == 0) return(TCHK_RECREM);
+   if (strcmp(&(tcnam[2]), "emoval") == 0) return(TCHK_REMOVAL);
+   break;
+  case 's':
+   if (tcnam[2] == 'k')
+    { if (strcmp(&(tcnam[3]), "ew") == 0) return(TCHK_SKEW); break; } 
+   else if (strcmp(&(tcnam[2]), "etuphold") == 0) return(TCHK_SETUPHOLD);
+   else if (strcmp(&(tcnam[2]), "etup") == 0) return(TCHK_SETUP);
+   break;
+  case 't':
+   if (strcmp(&(tcnam[2]), "imeskew") == 0) return(TCHK_TIMESKEW);
+   break;
+  case 'w': if (strcmp(&(tcnam[2]), "idth") == 0) return(TCHK_WIDTH); break;
+ }
+ return(-1);
+}
+
+/*
+ * output a number that is decomposed from input token but not yet converted
+ * to value for errors during input number processing
+ */
+static char *decompnum_to_str(char *s, char *digs, int32 base, int32 width)
+{
+ sprintf(s, "%d'%c%s", width, __to_baselet(base), digs);
+ return(s);
+}
+
+/*
+ * convert gate output value to printable
+ * tricky because depending on gate class and stval may or may not need stren
+ */
+extern char *__to_gonam(char *s, struct gate_t *gp, word32 v)
+{
+ switch ((byte) gp->g_class) { 
+  case GC_LOGIC: case GC_UDP:
+   if (gp->g_hasst)
+    {
+     if (v != 2) v |= (gp->g_stval << 2);
+     __to_vvstnam(s, (word32) __stren_map_tab[v]);
+    }
+   else __to_vvnam(s, (word32) v); 
+   break;
+  case GC_TRANIF:
+   /* here gate "output" is conducting state */
+   if (v == 0) strcpy(s, "*OFF*");
+   else if (v == 1) strcpy(s, "*ON*"); 
+   else if (v == 3) strcpy(s, "*UNKNOWN*");
+   else __misc_terr(__FILE__, __LINE__);
+   break;
+  case GC_TRAN: case GC_PULL:
+   __case_terr(__FILE__, __LINE__); strcpy(s, ""); 
+  /* mos and bufif outputs always strength */
+  default: __to_vvstnam(s, (word32) v);
+ } 
+ return(s);
+}
+
+/*
+ * convert gate value to printable
+ * tricky because depending on gate class and stval may or may not need stren
+ */
+extern char *__to_ginam(char *s, struct gate_t *gp, word32 v, int32 i)
+{
+ switch ((byte) gp->g_class) { 
+  /* bufif inputs non stength even though drives strength */
+  /* tranif 3rd input non strength and value not just on/off */ 
+  case GC_LOGIC: case GC_UDP: case GC_BUFIF: case GC_TRANIF:
+   __to_vvnam(s, (word32) v);
+   break;
+  /* mos input 1 strength (added if needed) but control input non stren */
+  case GC_MOS: case GC_CMOS: 
+   /* only 1st mos or cmos input has strength not control(s) */
+   if (i == 1) __to_vvstnam(s, (word32) v); else __to_vvnam(s, (word32) v);
+   break;
+  /* tran and pull cannot use this routine */
+  default: __case_terr(__FILE__, __LINE__);
+ } 
+ return(s);
+}
+
+/*
+ * convert net value to printable
+ */
+extern char *__to_vnam(char *s, word32 is_stren, word32 v)
+{
+ if (is_stren) __to_vvstnam(s, (word32) v); else __to_vvnam(s, (word32) v);
+ return(s);
+}
+
+/*
+ * convert a strength value to a 3 letter name string
+ * know always 3 characters
+ *
+ * SJM 08/16/01 - BEWARE this routine must not be changed because it is
+ * only way debug switch determines if mistake in table or algorithm
+ * has caused one of the illegal 129 stren values to be created 
+ * algorithms do something slightly and undectably wrong if this happens
+ */
+extern char *__to_vvstnam(char *s, word32 stval)
+{
+ word32 st0, st1;
+ byte val;
+ char ch;
+
+ /* decode stren byte */
+ val = (byte) stval & 3;
+ st0 = (stval >> 5) & 7;
+ st1 = (stval >> 2) & 7;
+
+ switch (val) {
+  case 0: ch = '0'; break;
+  case 1: ch = '1'; break;
+  case 2:
+   /* real HiZ */ 
+   if (st0 != 0 || st1 != 0)__misc_terr(__FILE__, __LINE__);
+   strcpy(s, "HiZ");
+   return(s);
+  case 3:
+   /* this should be Z not X */
+   if (st0 == 0 && st1 == 0) __misc_terr(__FILE__, __LINE__); 
+
+   /* z with hiz 0 strength component is H */
+   if (st0 == 0) { __to_dispst_str(s, st1); s[2] = 'H'; s[3] = '\0'; }
+   /* z with hiz 1 strength component is L */
+   else if (st1 == 0) { __to_dispst_str(s, st0); s[2] = 'L'; s[3] = '\0'; }
+   else { ch = 'X'; break; } 
+   return(s);
+  default: __case_terr(__FILE__, __LINE__); return(NULL);
+ }
+
+ /* finally known case strength is range with value */
+ /* notice strength letters always 2 chars */
+ if (st0 == st1)
+  {
+   /* DBG remove --- */
+   /* for normal value strength cannot both be 0 */  
+   if (st0 == 0) __misc_terr(__FILE__, __LINE__); 
+   /* --- */
+   __to_dispst_str(s, st0);
+   s[2] = ch;
+  }
+ else { s[0] = '0' + st0; s[1] = '0' + st1; s[2] = ch; }
+ s[3] = '\0';
+ return(s);
+}
+
+/*
+ * convert a 2 bit number to its verilog value name
+ */
+extern char *__to_vvnam(char *s, word32 v)
+{
+ switch ((byte) v) {
+  case 0: strcpy(s, "0"); break;
+  case 1: strcpy(s, "1"); break;
+  case 2: strcpy(s, "z"); break;
+  case 3: default: strcpy(s, "x"); break;
+ }
+ return(s);
+}
+
+/* same but for udp 3-values */
+extern char *__to_uvvnam(char *s, word32 v)
+{
+ switch ((byte) v) {
+  case 0: strcpy(s, "0"); break;
+  case 1: strcpy(s, "1"); break;
+  default: strcpy(s, "x"); break;
+ }
+ return(s);
+}
+
+/*
+ * convert base code to letter
+ */
+extern char __to_baselet(int32 bcod)
+{
+ char ch;
+
+ switch ((byte) bcod) {
+  case BBIN: ch = 'b'; break;
+  case BHEX: ch = 'h'; break;
+  case BOCT: ch = 'o'; break;
+  case BDEC: ch = 'd'; break;
+  default: ch = '?'; __case_terr(__FILE__, __LINE__);
+ }
+ return(ch);
+}
+
+/*
+ * convert time unit string (0-15) code to time unit name  
+ */
+extern char *__to_timunitnam(char *s, word32 unit)
+{
+ switch ((byte) unit) {
+  case 0: strcpy(s, "1 s"); break; 
+  case 1: strcpy(s, "100 ms"); break;
+  case 2: strcpy(s, "10 ms"); break;
+  case 3: strcpy(s, "1 ms"); break;
+  case 4: strcpy(s, "100 us"); break;
+  case 5: strcpy(s, "10 us"); break;
+  case 6: strcpy(s, "1 us"); break;
+  case 7: strcpy(s, "100 ns"); break;
+  case 8: strcpy(s, "10 ns"); break;
+  case 9: strcpy(s, "1 ns"); break;
+  case 10: strcpy(s, "100 ps"); break;
+  case 11: strcpy(s, "10 ps"); break;
+  case 12: strcpy(s, "1 ps"); break;
+  case 13: strcpy(s, "100 fs"); break;
+  case 14: strcpy(s, "10 fs"); break;
+  case 15: strcpy(s, "1 fs"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * convert an edge bit byte into an edge name string
+ * if posedge or negedge use name else use [...] form
+ */
+extern char *__to_edgenam(char *s, word32 eval)
+{
+ int32 first_time;
+ byte ebyte;
+ 
+ switch ((ebyte = (byte) eval)) {
+  case E_POSEDGE: strcpy(s, "posedge"); break; 
+  case E_NEGEDGE: strcpy(s, "negedge"); break; 
+  case NOEDGE: strcpy(s, ""); break;
+  default:
+   strcpy(s, "edge[");
+   first_time = TRUE;
+   if ((ebyte & EDGE01) != 0)
+    {
+     if (first_time) first_time = FALSE; else strcat(s, ", ");
+     strcat(s, "01");
+    }
+   if ((ebyte & EDGE10) != 0)
+    { 
+     if (first_time) first_time = FALSE; else strcat(s, ", ");
+     strcat(s, "10");
+    }
+   if ((ebyte & EDGE0X) != 0)
+    {
+     if (first_time) first_time = FALSE; else strcat(s, ", ");
+     strcat(s, "0x");
+    }
+   if ((ebyte & EDGEX1) != 0)
+    {
+     if (first_time) first_time = FALSE; else strcat(s, ", ");
+     strcat(s, "x1");
+    }
+   if ((ebyte & EDGE1X) != 0)
+    {
+     if (first_time) first_time = FALSE; else strcat(s, ", ");
+     strcat(s, "1x");
+    }
+   if ((ebyte & EDGEX0) != 0)
+    {
+     if (first_time) first_time = FALSE; else strcat(s, ", ");
+     strcat(s, "x0");
+    }
+   strcat(s, "]");
+  }
+ return(s);
+}
+
+/*
+ * convert an delay control type to a name
+ */
+extern char *__to_dcenam(char *s, word32 dctyp)
+{
+ switch ((byte) dctyp) {
+  case DC_NONE: strcpy(s, "**NONE?**"); break; 
+  case DC_EVENT: strcpy(s,"event"); break;
+  case DC_DELAY: strcpy(s, "delay"); break;
+  case DC_RHSEVENT:strcpy(s,"rhs event"); break; 
+  case DC_RHSDELAY:strcpy(s, "rhs delay"); break;
+  case DC_WAITEVENT: strcpy(s,"wait event"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(s);
+}
+
+/*
+ * SPECIAL MEMORY ALLOCATION ROUTINES
+ * USES OWN STRUCT AND CONSTANTS BELOW
+ */
+
+/*
+ * allocate a string for use during elaboration - adds the ending \0
+ * this must allocate the 1 char null string for `define as flag
+ */
+extern char *__pv_stralloc(char *s)
+{
+ char *cp;
+ int32 slen;
+
+ if (*s == '\0') slen = 1; else slen = strlen(s) + 1;
+ cp = __my_malloc(slen);
+ __memstr_use += slen;
+ /* this just copies '\0' for "" case */
+ strcpy(cp, s);
+ return(cp);
+}
+
+/*
+ * memory allocator for non freed memory
+ * and allocate small piece from a large allocated block
+ * aligns on 4 byte boundaries for VAX and 68000 too
+ * notice this is 32 bit word32 dependent
+ *
+ * could save space in pc by allocating only on bytes but would need always
+ * at least 4 bytes - no since now using free by size header table
+ */
+static char *nfbig_alloc(int32 size)
+{
+ char *cp;
+ int32 rem, real_size;
+
+ if ((rem = size % 4) != 0) real_size = size + 4 - rem;
+ else real_size = size;
+
+ if ((__start_sp + real_size + 4) >= __end_sp)
+  {
+   __start_sp = __my_malloc(BIG_ALLOC_SIZE); 
+   __end_sp = __start_sp + BIG_ALLOC_SIZE - 16;
+  }
+ cp = __start_sp;
+ __start_sp += real_size;
+ return(cp);
+}
+
+/*
+ * call to malloc that dies if no memory available
+ * these are normal OS memory allocation with error terminaton
+ */
+extern char *__my_malloc(int32 size)
+{
+ char *cp;
+
+ /* DBG remove --- */
+ if (size <= 0) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+
+ if ((cp = (char *) malloc((word32) size)) == NULL)
+  {
+   __sysfatal_msg(
+   "**fatal err[1]: No more memory - at file %s line %d allocated %ld bytes\n",
+    __cur_fnam, __lin_cnt, __mem_use);
+   __my_exit(4, TRUE);
+  }
+ __mem_use += size;
+ __mem_allocated += size;
+ /* DBG remove ---
+ if (__debug_flg) __dbg_msg("my_malloc - allocated %d bytes - use %ld\n",
+   size, __mem_use);
+ --- */
+ return(cp);
+}
+
+/*
+ * call to free 
+ */
+extern void __my_free(char *mp, int32 size)
+{
+ /* DBG remove --- */
+ if (size <= 0) return;
+ /* --- */
+ free(mp);
+ __mem_use -= size;
+ __mem_freed += size;
+ /* DBG remove ---
+ if (__debug_flg) __dbg_msg("freeing %d bytes - memuse now %ld\n", size,
+  __mem_use);
+ --- */
+}
+
+/*
+ * interface to system realloc()
+ * can only call with malloced mp or cannot realloc
+ */
+extern char *__my_realloc(char *mp, int32 osize, int32 nsize)
+{
+ char *cp;
+
+ if ((cp = (char *) realloc(mp, (word32) nsize)) == NULL)
+  {
+   __sysfatal_msg(
+    "**fatal err[1]: realloc failed - allocated %ld bytes\n", __mem_use);
+   __my_exit(4, TRUE);
+  }
+ /* DBG remove ---
+ if (__debug_flg)
+  __dbg_msg("realloc: freeing %d byte and allocating %d bytes\n",
+   osize, nsize);
+ --- */
+ __mem_use -= osize;
+ __mem_use += nsize;
+ return(cp);
+}
+
+/*
+ *  INTERFACE TO OS ROUTINES
+ */
+
+/*
+ * version of fclose that ends with fatal error if cannot close 
+ * some unixes do not return anything on fclose failure
+ */
+extern void __my_fclose(FILE *f)
+{
+ if (f == NULL) __misc_terr(__FILE__, __LINE__);
+ if (fclose(f) == EOF)
+  {
+   __crit_msg("**fatal err[1]: OS fclose failed: %s\n", strerror(errno));
+   __my_exit(5, TRUE);
+  }
+}
+
+
+/*
+ * version of fd close that ends with fatal error if cannot close 
+ * some unixes do not return anything on close failure
+ */
+extern void __my_close(int32 fd)
+{
+ if (fd == -1) __misc_terr(__FILE__, __LINE__);
+ if (close(fd) == -1)
+  {
+   __crit_msg("**fatal err[1]: OS fclose failed: %s\n", strerror(errno));
+   __my_exit(5, TRUE);
+  }
+}
+
+/*
+ * interface to system rewind routine
+ */
+extern void __my_rewind(FILE *f)
+{
+ if (fseek(f, 0L, 0) == -1)
+  {
+   __crit_msg("**fatal err[1]: OS rewind failed: %s\n", strerror(errno));
+   __my_exit(5, TRUE);
+  }
+}
+
+/*
+ * version of unbuffered open that performs tilde expansion
+ * FIXME - should allow ~[dir] form and look at some network directory
+ * and allow ~ anywhere in path name
+ */
+extern int32 __tilde_open(char *pthnam, int32 opmask)
+{
+ int32 newlen;
+ char *chp;
+ int32 fd;
+
+ if (*pthnam != '~') return(open(pthnam, opmask)); 
+ if ((chp = tilde_expand(pthnam, &newlen)) == NULL) return(-1);
+ fd = open(chp, opmask);
+ __my_free(chp, newlen);
+ return(fd);
+}
+
+/*
+ * open with expand of leading tilde in file name using home
+ */
+extern FILE *__tilde_fopen(char *pthnam, char *opmod)
+{
+ int32 newlen;
+ char *chp;
+ FILE *f;
+
+ if (*pthnam != '~') return(__my_fopen(pthnam, opmod)); 
+ if ((chp = tilde_expand(pthnam, &newlen)) == NULL) return(NULL);
+ f = __my_fopen(chp, opmod);
+ __my_free(chp, newlen);
+ return(f);
+}
+
+/*
+ * perform prefix tilde expansion
+ * only called if path starts with tilde
+ * notice for now silently returns 
+ *
+ * LOOKATME could allow /~/ component anywhere in path name for net addrs? 
+ */
+static char *tilde_expand(char *pthnam, int32 *newlen)
+{
+ char *chp, *chp2;
+ int32 hlen, plen;
+ char usernam[RECLEN];
+
+ /* first ~/ form */
+ if (pthnam[1] == '/') { chp2 = __pv_homedir; goto bld_expanded; }
+
+ /* ~[user] form - look up if possible */
+ if ((chp = strchr(pthnam, '/')) == NULL) return(NULL);
+ strncpy(usernam, &(pthnam[1]), chp - pthnam - 1);
+ usernam[chp - pthnam - 1] = '\0';
+ /* pathname now has / prefix but ~[name] removed */
+ pthnam = chp - 1;
+
+ /* if do not know system, assume vanilla non networked BSD unix */
+ {
+  struct passwd *pwp;
+
+  if ((pwp = getpwnam(usernam)) == NULL) return(NULL);
+  chp2 = pwp->pw_dir;
+ }
+ goto bld_expanded;
+
+bld_expanded:
+ /* know home dir does not have ending / and . if HOMEDIR not set */
+ hlen = strlen(chp2);
+ plen = strlen(pthnam);
+ *newlen = hlen - 1 + plen + 1;
+ chp = __my_malloc(*newlen);
+ strcpy(chp, chp2);
+ strcpy(&(chp[hlen]), &(pthnam[1]));
+ return(chp);
+}
+
+/*
+ * unbuffered creat for writing with expand leading tilde in file name using 
+ */
+extern int32 __tilde_creat(char *pthnam)
+{
+ int32 newlen;
+ char *chp;
+ int32 fd;
+
+ if (*pthnam != '~') return(__my_creat(pthnam)); 
+ if ((chp = tilde_expand(pthnam, &newlen)) == NULL) return(-1);
+ fd = __my_creat(chp);
+ __my_free(chp, newlen);
+ return(fd);
+}
+
+/*
+ * version of open that returns NULL when directory opened
+ * unix allows opening directories for reading
+ */
+extern FILE *__my_fopen(char *fnam, char *opmod)
+{
+ FILE *f;
+ struct stat sbuf;
+
+ if ((f = fopen(fnam, opmod)) == NULL) return(NULL);
+ if (fstat(fileno(f), &sbuf) == -1)
+  {
+   __crit_msg("**fatal err[1]: OS file stat operation failed: %s\n",
+    strerror(errno));
+   __my_exit(5, TRUE);
+  }
+ /* anything but directory is ok */
+ if ((S_IFDIR & sbuf.st_mode) == 0) return(f);
+
+ /* ---
+ __inform(417, "open failed because %s is directory or special file", fnam);
+ --- */
+ __my_fclose(f);
+ return(NULL);
+}
+
+/*
+ * version of non buffered creat that returns -1 when directory opened
+ * unix allows opening directories for reading
+ */
+extern int32 __my_creat(char *fnam)
+{
+ int32 fd;
+ struct stat sbuf;
+
+ if ((fd = creat(fnam, 0666)) == -1) return(-1);
+ if (fstat(fd, &sbuf) == -1)
+  {
+   __crit_msg("**fatal err[1]: OS file stat operation failed: %s\n",
+    strerror(errno));
+   __my_exit(5, TRUE);
+  }
+ /* anything but directory is ok */
+ if ((S_IFDIR & sbuf.st_mode) == 0) return(fd);
+
+ /* ---
+ __inform(417, "open failed because %s is directory or special file", fnam);
+ --- */
+ close(fd);
+ return(-1);
+}
+
+/*
+ * routine to truncate (chop) a string for output 
+ * one constant per run value for ID string chopped length
+ * notice this always copies
+ */
+extern char *__schop(char *s1, char *s2)
+{
+ int32 slen, sendi;
+
+ slen = strlen(s2);
+ if (slen < (sendi = MSGTRUNCLEN - 4)) strcpy(s1, s2);
+ else { strncpy(s1, s2, sendi); strcpy(&s1[sendi], "..."); }
+ return(s1);
+}
+
+/*
+ * build a **<file>(<line. no.) reference
+ * this chops file name so know will fit
+ * s must be RECLEN wide
+ */
+extern char *__bld_lineloc(char *s, word32 fnind, int32 fnlcnt)
+{
+ char s1[RECLEN];
+
+ sprintf(s, "**%s(%d)", __schop(s1, __in_fils[fnind]), fnlcnt);
+ return(s);
+}
+
+/*
+ * MESSAGE ROUTINES
+ */
+
+/*
+ * intellectual property (IP) message unsuppressable except by special simctrlb
+ * IP messages suppression also stops log
+ */
+/*VARARGS*/
+extern void __ip_msg(char *s, ...)
+{
+ va_list va, va2;
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va, s);
+ va_start(va2, s);
+ vfprintf(stdout, s, va);
+ if (__log_s != NULL) vfprintf(__log_s, s, va2);
+ va_end(va);
+ va_end(va2);
+}
+
+/*
+ * intellectual property (IP) message 
+ *
+ * suppressable before customer1 cb if -q flag
+ * IP messages suppression also stops log
+ */
+/*VARARGS*/
+extern void __ip2_msg(char *s, ...)
+{
+ va_list va, va2;
+
+ if (__quiet_msgs) return;
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va, s);
+ va_start(va2, s);
+ vfprintf(stdout, s, va);
+ if (__log_s != NULL) vfprintf(__log_s, s, va2);
+ va_end(va);
+ va_end(va2);
+}
+
+/*
+ * critical Copyright, licensing, OS failure, malloc failure etc. 
+ * never suppressed 
+ */
+/*VARARGS*/
+extern void __crit_msg(char *s, ...)
+{
+ va_list va, va2;
+
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va, s);
+ va_start(va2, s);
+ vfprintf(stdout, s, va);
+ if (__log_s != NULL) vfprintf(__log_s, s, va2);
+ va_end(va);
+ va_end(va2);
+}
+
+/*
+ * never suppressed special OS failure (can't call malloc or os calls)
+ * vendor 1 must detect -4 (inverse of vpi vpiSystem error level)
+ * BEWARE - this can't call system or malloc
+ */
+/*VARARGS*/
+extern void __sysfatal_msg(char *s, ...)
+{
+ va_list va, va2;
+
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va, s);
+ va_start(va2, s);
+ vfprintf(stdout, s, va);
+ if (__log_s != NULL) vfprintf(__log_s, s, va2);
+ va_end(va);
+ va_end(va2);
+}
+
+/*
+ * all normal (supressable with -q) messages 
+ * Cver progress, -d, status options
+ */
+/*VARARGS*/
+extern void __cv_msg(char *s, ...)
+{
+ va_list va, va2;
+
+ if (__quiet_msgs) return;
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va, s);
+ va_start(va2, s);
+ vfprintf(stdout, s, va);
+ if (__log_s != NULL) vfprintf(__log_s, s, va2);
+ va_end(va);
+ va_end(va2);
+}
+
+/*
+ * cver simulation output messages (from system tasks such as $showvars)
+ * version 1 to both stdout and log file
+ *
+ * also all debugger output since interchangeable with system tasks
+ * never suppressed 
+ */
+/*VARARGS*/
+extern void __cvsim_msg(char *s, ...)
+{
+ va_list va, va2;
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va, s);
+ va_start(va2, s);
+ vfprintf(stdout, s, va);
+ if (__log_s != NULL) vfprintf(__log_s, s, va2);
+ va_end(va);
+ va_end(va2);
+}
+
+/*
+ * cver simulation output messages - * version 2 to just stdout
+ */
+/*VARARGS*/
+extern void __cvsim2_msg(char *s, ...)
+{
+ va_list va;
+
+ va_start(va, s);
+ vfprintf(stdout, s, va);
+ va_end(va);
+}
+
+/*
+ * cver simulation output messages
+ * version 3 only to log file
+ *
+ * from system tasks such as $showvars and debugger output
+ * never suppressed and log file not suppresable
+ */
+/*VARARGS*/
+extern void __cvsim3_msg(char *s, ...)
+{
+ va_list va;
+
+ va_start(va, s);
+ if (__log_s != NULL) vfprintf(__log_s, s, va);
+ va_end(va);
+}
+
+/*
+ * debugger (not debugger output) messages - not callback stopable
+ * goes to both stdout and log file
+ */
+/*VARARGS*/
+extern void __dbg_msg(char *s, ...)
+{
+ va_list va;
+ va_list va2;
+
+ va_start(va, s);
+ va_start(va2, s);
+ __my_vfprintf(stdout, s, va, va2);
+ va_end(va2);
+ va_end(va);
+}
+
+/*
+ * trace message printf - to trace file unless stdout (the default)
+ * LOOATME - maybe should default trace file to verilog.trace
+ */
+/*VARARGS*/
+extern void __tr_msg(char *s, ...)
+{
+ va_list va, va2;
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va, s);
+ va_start(va2, s);
+ vfprintf(__tr_s, s, va);
+ if (__tr_s == stdout && __log_s != NULL) vfprintf(__log_s, s, va2);
+ va_end(va);
+ va_end(va2);
+}
+
+/*
+ * ERROR MESSAGE ROUTINES
+ */
+
+/*
+ * miscellaneous (most) internal fatal errors 
+ */
+extern void __misc_terr(char *fnam, int32 lno)
+{
+ /* SJM DBG REMOVE - malloc_chain_check(1); */
+ if (lno == -1039)
+  {
+   __pv_terr(304,
+     "cver.lic file or single job lock invalid or removed - run licprobe -lockcheck");
+  }
+ __pv_terr(303,
+  "MISC INTERNAL - source line **%s(%d) - maybe at **%s(%d) or **%s(%d)",
+  fnam, lno, __cur_fnam, __lin_cnt, __in_fils[__sfnam_ind], __slin_cnt);
+}
+
+/*
+ * file miscellaneous (most) internal fatal errors (input file place known) 
+ */
+extern void __misc_fterr(char *fnam, int32 lno)
+{
+ __fterr(303, "MISC INTERNAL - source line **%s(%d)", fnam, lno);
+}
+
+/*
+ * global analysis phase internal error - object provides line number
+ */
+extern void __misc_gfterr(char *fnam, int32 lno, word32 gfnam_ind,
+ int32 gflin_cnt)
+{
+ __gfterr(303, gfnam_ind, gflin_cnt,
+  "MISC INTERNAL - source line **%s(%d)", fnam, lno);
+}
+
+/*
+ * non execution statement type error __sfnam_ind contains location
+ */
+extern void __misc_sgfterr(char *fnam, int32 lno)
+{
+ __gfterr(303, __sfnam_ind, __slin_cnt,
+  "MISC INTERNAL - source lint **%s(%d)", fnam, lno);
+}
+
+/*
+ * simple case fatal error - can always find with debugger
+ */
+extern void __case_terr(char *fnam, int32 lno)
+{
+ __pv_terr(324,
+  "CASE INTERNAL - source line **%s(%d) - maybe at **%s(%d) or **%s(%d)",
+  fnam, lno, __cur_fnam, __lin_cnt, __in_fils[__sfnam_ind], __slin_cnt);
+}
+
+/*
+ * simple argument passed to routine internal error
+ */
+extern void __arg_terr(char *fnam, int32 lno)
+{
+ __pv_terr(322,
+  "ARG INTERNAL - source line **%s(%d) - maybe at **%s(%d) or **%s(%d)",
+  fnam, lno, __cur_fnam, __lin_cnt, __in_fils[__sfnam_ind], __slin_cnt);
+}
+
+/*
+ * error with fatal termination
+ * arg s is a format specification string for sprintf
+ *
+ * notice error messages longer than 4k bytes will cause crash
+ * caller of error routines must make sure no more than 4 ID called
+ */
+extern void __pv_terr(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**FATAL ERROR** [%d] ", id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(FATAL, id_num, vpichp, "[NONE]", 0);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_ontrol used to suppress emsg, used up so turned off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; __my_exit(1, TRUE); }
+  }
+ __my_fprintf(stdout, "**FATAL ERROR** [%d] ", id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+ __my_exit(1, TRUE);
+}
+
+/*
+ * vpi error with fatal termination and no error cb try call
+ * arg s is a format specification string for sprintf
+ *
+ * notice error messages longer than 4k bytes will cause crash
+ * caller of error routines must make sure no more than 4 ID called
+ */
+extern void __pv_vpi_terr(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**FATAL ERROR** [%d] ", id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __my_free(vpichp, slen);
+   /* if vpi_ontrol used to suppress emsg, used up so turned off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; __my_exit(1, TRUE); }
+  }
+ __my_fprintf(stdout, "**FATAL ERROR** [%d] ", id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+ __my_exit(1, TRUE);
+}
+
+/*
+ * note ferr forms all take a variable prefix for acc_ and tf_ and debugger
+ */
+
+/*VARARGS*/
+extern void __fterr(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**%s(%d) FATAL ERROR** [%d] ", __cur_fnam,
+    __lin_cnt, id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(FATAL, id_num, vpichp, __cur_fnam, __lin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turned off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; __my_exit(2, TRUE); }
+  }
+
+ __my_fprintf(stdout, "**%s(%d) FATAL ERROR** [%d] ", __cur_fnam,
+  __lin_cnt, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+ __my_exit(2, TRUE);
+}
+
+/*VARARGS*/
+extern void __sgfterr(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+ char s1[RECLEN], s2[RECLEN];
+
+ if (__run_state == SS_SIM) 
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+ else strcpy(s1, "");
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**%s(%d) FATAL ERROR**%s [%d] ", __in_fils[__sfnam_ind],
+    __slin_cnt, s1, id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(FATAL, id_num, vpichp, __in_fils[__sfnam_ind],
+    __slin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turned off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; __my_exit(2, TRUE); }
+  }
+
+ __my_fprintf(stdout, "**%s(%d) FATAL ERROR**%s [%d] ",
+  __in_fils[__sfnam_ind], __slin_cnt, s1, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+ __my_exit(2, TRUE);
+}
+
+/*VARARGS*/
+extern void __gfterr(int32 id_num, word32 gfnam_ind, int32 gflin_cnt,
+ char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+ char s1[RECLEN], s2[RECLEN];
+
+ if (__run_state == SS_SIM) 
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+ else strcpy(s1, "");
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**%s(%d) FATAL ERROR**%s [%d] ",
+    __in_fils[gfnam_ind], gflin_cnt, s1, id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(FATAL, id_num, vpichp, __in_fils[gfnam_ind],
+    gflin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turned off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; __my_exit(2, TRUE); }
+  }
+
+ __my_fprintf(stdout, "**%s(%d) FATAL ERROR**%s [%d] ",
+  __in_fils[gfnam_ind], gflin_cnt, s1, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+ __my_exit(2, TRUE);
+}
+
+/*
+ * serious but non-fatal error
+ */
+/*VARARGS*/
+extern void __pv_err(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+ __pv_err_cnt++;
+ if (!__no_errs)
+  {
+   if (__vpierr_cb_active && !__iact_state)
+    {
+     /* reset in case user called sim control operation from wrong place */
+     __errorcb_suppress_msg = FALSE;
+
+     sprintf(vpis1, "** ERROR** [%d] ", id_num);
+     va_start(va, s);
+     vsprintf(vpis2, s, va);
+     va_end(va);
+   
+     slen = strlen(vpis1) + strlen(vpis2) + 1;
+     vpichp = __my_malloc(slen);
+     strcpy(vpichp, vpis1);
+     strcat(vpichp, vpis2);
+
+     __cberror_fill_einfo(ERROR, id_num, vpichp, "[NONE]", 0);
+     __vpi_error_trycall();
+
+     __my_free(vpichp, slen);
+     /* if vpi_control used to suppress emsg, used up so turn off here */ 
+     if (__errorcb_suppress_msg)
+      { __errorcb_suppress_msg = FALSE; return; }
+    }
+   __my_fprintf(stdout, "** ERROR** [%d] ", id_num);
+
+   /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+   va_start(va2, s);
+   va_start(va3, s);
+   __my_vfprintf(stdout, s, va2, va3);
+   va_end(va2);
+   va_end(va3);
+
+   my_putc_('\n', stdout);
+  }
+ if (__run_state == SS_SIM) 
+ if ((__run_state == SS_COMP || __run_state == SS_LOAD) 
+  && __max_errors != 0 && __pv_err_cnt > __max_errors)
+  __pv_terr(id_num, "maximum error count exceeded");
+}
+
+/*VARARGS*/
+extern void __pv_ferr(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+ __pv_err_cnt++;
+ if (__iact_state)
+  {
+   /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+   va_start(va, s);
+   va_start(va2, s);
+   __via_err(id_num, s, va, va2);
+   va_end(va);
+   va_end(va2);
+   return;
+  } 
+
+ if (!__no_errs)
+  {
+   if (__vpierr_cb_active)
+    {
+     /* reset in case user called sim control operation from wrong place */
+     __errorcb_suppress_msg = FALSE;
+
+     sprintf(vpis1, "**%s(%d) ERROR** [%d] ", __cur_fnam, __lin_cnt, id_num);
+     va_start(va, s);
+     vsprintf(vpis2, s, va);
+     va_end(va);
+   
+     slen = strlen(vpis1) + strlen(vpis2) + 1;
+     vpichp = __my_malloc(slen);
+     strcpy(vpichp, vpis1);
+     strcat(vpichp, vpis2);
+
+     __cberror_fill_einfo(ERROR, id_num, vpichp, __cur_fnam, __lin_cnt);
+     __vpi_error_trycall();
+
+     __my_free(vpichp, slen);
+     /* if vpi_control used to suppress emsg, used up so turn off here */ 
+     if (__errorcb_suppress_msg)
+      { __errorcb_suppress_msg = FALSE; return; }
+    }
+   __my_fprintf(stdout, "**%s(%d) ERROR** [%d] ", __cur_fnam, __lin_cnt,
+    id_num);
+
+   /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+   va_start(va2, s);
+   va_start(va3, s);
+   __my_vfprintf(stdout, s, va2, va3);
+   va_end(va2);
+   va_end(va3);
+   my_putc_('\n', stdout);
+  }
+ if ((__run_state == SS_COMP || __run_state == SS_LOAD) 
+  && __max_errors != 0 && __pv_err_cnt > __max_errors)
+  __pv_terr(id_num, "maximum error count exceeded");
+}
+
+/*VARARGS*/
+extern void __sgferr(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+ char s1[RECLEN], s2[RECLEN];
+
+ __pv_err_cnt++;
+ if (!__no_errs)
+  {
+   if (__run_state == SS_SIM)
+    sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+   else strcpy(s1, "");
+
+   if (__vpierr_cb_active && !__iact_state)
+    {
+     /* reset in case user called sim control operation from wrong place */
+     __errorcb_suppress_msg = FALSE;
+
+     sprintf(vpis1, "**%s(%d) ERROR**%s [%d] ", __in_fils[__sfnam_ind],
+      __slin_cnt, s1, id_num);
+     va_start(va, s);
+     vsprintf(vpis2, s, va);
+     va_end(va);
+   
+     slen = strlen(vpis1) + strlen(vpis2) + 1;
+     vpichp = __my_malloc(slen);
+     strcpy(vpichp, vpis1);
+     strcat(vpichp, vpis2);
+
+     __cberror_fill_einfo(ERROR, id_num, vpichp, __in_fils[__sfnam_ind],
+      __slin_cnt);
+     __vpi_error_trycall();
+
+     __my_free(vpichp, slen);
+     /* if vpi_control used to suppress emsg, used up so turn off here */ 
+     if (__errorcb_suppress_msg)
+      { __errorcb_suppress_msg = FALSE; return; }
+    }
+
+   __my_fprintf(stdout, "**%s(%d) ERROR**%s [%d] ", __in_fils[__sfnam_ind],
+    __slin_cnt, s1, id_num);
+
+   /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+   va_start(va2, s);
+   va_start(va3, s);
+   __my_vfprintf(stdout, s, va2, va3);
+   va_end(va2);
+   va_end(va3);
+   my_putc_('\n', stdout);
+  }
+ if ((__run_state == SS_COMP || __run_state == SS_LOAD) 
+  && __max_errors != 0 && __pv_err_cnt > __max_errors)
+  __pv_terr(id_num, "maximum error count exceeded");
+}
+
+/*VARARGS*/
+extern void __gferr(int32 id_num, word32 gfnam_ind, int32 gflin_cnt,
+ char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+ char s1[RECLEN], s2[RECLEN];
+
+ __pv_err_cnt++;
+ if (!__no_errs)
+  {
+   if (__run_state == SS_SIM)
+    sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+   else strcpy(s1, "");
+
+   if (__vpierr_cb_active && !__iact_state)
+    {
+     /* reset in case user called sim control operation from wrong place */
+     __errorcb_suppress_msg = FALSE;
+
+     sprintf(vpis1, "**%s(%d) ERROR**%s [%d] ", __in_fils[gfnam_ind],
+      gflin_cnt, s1, id_num);
+    
+     va_start(va, s);
+     vsprintf(vpis2, s, va);
+     va_end(va);
+   
+     slen = strlen(vpis1) + strlen(vpis2) + 1;
+     vpichp = __my_malloc(slen);
+     strcpy(vpichp, vpis1);
+     strcat(vpichp, vpis2);
+
+     __cberror_fill_einfo(ERROR, id_num, vpichp, __in_fils[gfnam_ind],
+      gflin_cnt);
+     __vpi_error_trycall();
+
+     __my_free(vpichp, slen);
+     /* if vpi_control used to suppress emsg, used up so turn off here */ 
+     if (__errorcb_suppress_msg)
+      { __errorcb_suppress_msg = FALSE; return; }
+    }
+
+   __my_fprintf(stdout, "**%s(%d) ERROR**%s [%d] ", __in_fils[gfnam_ind],
+    gflin_cnt, s1, id_num);
+
+   /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+   va_start(va2, s);
+   va_start(va3, s);
+   __my_vfprintf(stdout, s, va2, va3);
+   va_end(va2);
+   va_end(va3);
+   my_putc_('\n', stdout);
+  } 
+ if ((__run_state == SS_COMP || __run_state == SS_LOAD) 
+  && __max_errors != 0 && __pv_err_cnt > __max_errors)
+  __pv_terr(id_num, "maximum error count exceeded");
+}
+
+/*
+ * interactive command error
+ * this output still goes to log file 
+ * notice this routine does not increment err number
+ */
+/*VARARGS*/
+extern void __ia_err(int32 id_num, char *s, ...)
+{
+ va_list va, va2;
+
+ /* can suppress any interactive error */
+ if (__em_suppr(id_num)) return;
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va, s);
+ va_start(va2, s);
+ __via_err(id_num, s, va, va2);
+ va_end(va);
+ va_end(va2);
+} 
+
+/*VARARGS*/
+extern void __via_err(int32 id_num, char *s, va_list args, va_list args2)
+{
+ if (__cmd_s == NULL) __my_fprintf(stdout, "--CMD ERROR** [%d] ", id_num);
+ else __my_fprintf(stdout, "--%s(%d) CMD ERROR** [%d] ", __cmd_fnam,
+  __lin_cnt, id_num);
+ __my_vfprintf(stdout, s, args, args2);
+ my_putc_('\n', stdout);
+}
+
+/*VARARGS*/
+extern void __pv_warn(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+ __pv_warn_cnt++;
+ if (__no_warns || __em_suppr(id_num)) return;
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1,"** WARN** [%d] ", id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(WARN, id_num, vpichp, "[NONE]", 0);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+  }
+
+ __my_fprintf(stdout,"** WARN** [%d] ", id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+}
+
+/*VARARGS*/
+extern void __pv_fwarn(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+ __pv_warn_cnt++;
+ if (__no_warns || __em_suppr(id_num)) { va_end(va); return; }
+
+ if (__iact_state)
+  {
+   /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+   va_start(va, s);
+   va_start(va2, s);
+   __via_err(id_num, s, va, va2);
+   va_end(va);
+   va_end(va2);
+   return;
+  } 
+
+ if (__vpierr_cb_active)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**%s(%d) WARN** [%d] ", __cur_fnam, __lin_cnt, id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(WARN, id_num, vpichp, __cur_fnam, __lin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+  }
+
+ __my_fprintf(stdout, "**%s(%d) WARN** [%d] ", __cur_fnam, __lin_cnt, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+}
+
+/*VARARGS*/
+extern void __sgfwarn(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+ char s1[RECLEN], s2[RECLEN];
+
+ __pv_warn_cnt++;
+ if (__no_warns || __em_suppr(id_num)) return;
+
+ if (__run_state == SS_SIM)
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+ else strcpy(s1, "");
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**%s(%d) WARN**%s [%d] ", __in_fils[__sfnam_ind],
+    __slin_cnt, s1, id_num);
+
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(WARN, id_num, vpichp, __in_fils[__sfnam_ind],
+    __slin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+  }
+
+ __my_fprintf(stdout, "**%s(%d) WARN**%s [%d] ", __in_fils[__sfnam_ind],
+  __slin_cnt, s1, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+}
+
+/*VARARGS*/
+extern void __gfwarn(int32 id_num, word32 gfnam_ind, int32 gflin_cnt,
+ char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+ char s1[RECLEN], s2[RECLEN];
+
+ __pv_warn_cnt++;
+ if (__no_warns || __em_suppr(id_num)) return;
+
+ if (__run_state == SS_SIM)
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+ else strcpy(s1, "");
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "**%s(%d) WARN**%s [%d] ", __in_fils[gfnam_ind],
+    gflin_cnt, s1, id_num);
+
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(WARN, id_num, vpichp, __in_fils[gfnam_ind],
+    gflin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+  }
+
+ __my_fprintf(stdout, "**%s(%d) WARN**%s [%d] ", __in_fils[gfnam_ind],
+  gflin_cnt, s1, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+}
+
+/*
+ * interactive command warning
+ * this output still goes to log file 
+ * notice this routine does not increment warn number
+ */
+/*VARARGS*/
+extern void __ia_warn(int32 id_num, char *s, ...)
+{
+ va_list va, va2;
+
+ if (id_num >= 1700) __arg_terr(__FILE__, __LINE__);
+ /* can suppress any interactive error */
+ if (__em_suppr(id_num)) return;
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va, s);
+ va_start(va2, s);
+ __via_warn(id_num, s, va, va2);
+ va_end(va);
+ va_end(va2);
+} 
+
+/*VARARGS*/
+extern void __via_warn(int32 id_num, char *s, va_list args, va_list args2)
+{
+ if (__cmd_s == NULL) __my_fprintf(stdout, "--CMD WARN** [%d] ", id_num);
+ else __my_fprintf(stdout, "--%s(%d) CMD WARN** [%d] ", __cmd_fnam,
+  __lin_cnt, id_num);
+ __my_vfprintf(stdout, s, args, args2);
+ my_putc_('\n', stdout);
+}
+
+/*VARARGS*/
+extern void __inform(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+ __inform_cnt++;
+ if (__no_informs || __em_suppr(id_num)) return;
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "--INFORM: [%d] ", id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(INFORM, id_num, vpichp, "[NONE]", 0);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+  }
+
+ __my_fprintf(stdout, "--INFORM: [%d] ", id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+}
+
+/*VARARGS*/
+extern void __finform(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+
+ __inform_cnt++;
+ if (__no_informs || __em_suppr(id_num)) return;
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "--%s(%d) INFORM-- [%d] ", __cur_fnam, __lin_cnt, id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(INFORM, id_num, vpichp, __cur_fnam, __lin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+  }
+
+ __my_fprintf(stdout, "--%s(%d) INFORM-- [%d] ", __cur_fnam,
+  __lin_cnt, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+}
+
+/*VARARGS*/
+extern void __sgfinform(int32 id_num, char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+ char s1[RECLEN], s2[RECLEN];
+
+ __inform_cnt++;
+ if (__no_informs || __em_suppr(id_num)) return;
+
+ if (__run_state == SS_SIM)
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+ else strcpy(s1, "");
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "--%s(%d) INFORM--%s [%d] ", __in_fils[__sfnam_ind],
+    __slin_cnt, s1, id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(INFORM, id_num, vpichp, __in_fils[__sfnam_ind],
+    __slin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+  }
+
+ __my_fprintf(stdout, "--%s(%d) INFORM--%s [%d] ", __in_fils[__sfnam_ind],
+  __slin_cnt, s1, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+}
+
+/*VARARGS*/
+extern void __gfinform(int32 id_num, word32 gfnam_ind, int32 gflin_cnt,
+ char *s, ...)
+{
+ va_list va, va2, va3;
+ int32 slen;
+ char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp; 
+ char s1[RECLEN], s2[RECLEN];
+
+ __inform_cnt++;
+ if (__no_informs || __em_suppr(id_num)) return;
+
+ if (__run_state == SS_SIM)
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
+ else strcpy(s1, "");
+
+ if (__vpierr_cb_active && !__iact_state)
+  {
+   /* reset in case user called sim control operation from wrong place */
+   __errorcb_suppress_msg = FALSE;
+
+   sprintf(vpis1, "--%s(%d) INFORM--%s [%d] ", __in_fils[gfnam_ind],
+    gflin_cnt, s1, id_num);
+   va_start(va, s);
+   vsprintf(vpis2, s, va);
+   va_end(va);
+   
+   slen = strlen(vpis1) + strlen(vpis2) + 1;
+   vpichp = __my_malloc(slen);
+   strcpy(vpichp, vpis1);
+   strcat(vpichp, vpis2);
+
+   __cberror_fill_einfo(INFORM, id_num, vpichp, __in_fils[gfnam_ind],
+    gflin_cnt);
+   __vpi_error_trycall();
+
+   __my_free(vpichp, slen);
+   /* if vpi_control used to suppress emsg, used up so turn off here */ 
+   if (__errorcb_suppress_msg)
+    { __errorcb_suppress_msg = FALSE; return; }
+  }
+
+ __my_fprintf(stdout, "--%s(%d) INFORM--%s [%d] ", __in_fils[gfnam_ind],
+  gflin_cnt, s1, id_num);
+
+ /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
+ va_start(va2, s);
+ va_start(va3, s);
+ __my_vfprintf(stdout, s, va2, va3);
+ va_end(va2);
+ va_end(va3);
+ my_putc_('\n', stdout);
+}
+
+/*
+ * return T if this message marked to be suppressed
+ * if warnings off all suppressed
+ */
+extern int32 __em_suppr(int32 id)
+{
+ word32 w;
+ int32 bi, wi;
+
+ bi = id % WBITS;
+ wi = id / WBITS;
+ w = __wsupptab[wi];
+ if ((w & (1L << bi)) != 0) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * my fprintf - normal fprintf except if f is stdout then also to log file
+ *
+ * SJM 10/13/99 - ansii std says varargs not usable after vprintf called
+ */
+/*VARARGS*/
+extern void __my_fprintf(FILE *f, char *s, ...)
+{
+ va_list va, va2;
+
+ va_start(va, s);
+ va_start(va2, s);
+ vfprintf(f, s, va);
+ if (f == stdout && __log_s != NULL) vfprintf(__log_s, s, va2);
+ va_end(va);
+ va_end(va2);
+}
+
+/*
+ * version of my fprintf when caller passed variable arg list 
+ *
+ * SJM 10/13/99 - ansii std says varargs not usable after vprintf called
+ */
+extern void __my_vfprintf(FILE *f, char *s, va_list args, va_list args2)
+{
+ vfprintf(f, s, args);
+ if (f == stdout && __log_s != NULL) vfprintf(__log_s, s, args2);  
+}
diff --git a/src/v_prp.c b/src/v_prp.c
new file mode 100644
index 0000000..fab6dbb
--- /dev/null
+++ b/src/v_prp.c
@@ -0,0 +1,4803 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * Verilog simulation preparation routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+#include "vpi_user.h"
+
+/* local prototypes */
+static void rem_inc_dupes(void);
+static void prep_udps(void);
+static void prep1_udp(struct udp_t *);
+static void prep_comb_udptab(struct udp_t *);
+static void xpnd_1wcard(int32, word32);
+static void init_utab(word32 *, int32);
+static void chg_unfilled_tox(word32 *, int32);
+static void bld_wcardtab(register char *, word32, word32);
+static word32 bld_uinitndx(char *, word32, int32);
+static void setchk_uval(word32);
+static char *bld_udploc(char *, word32, word32, word32);
+static char *udploc_to_line(char *, char *);
+static void dmp_comb_udptab(struct udp_t *);
+static void dmp_udp3v_tab(word32 *, word32);
+static char *bld3vndx_str(char *, word32, word32);
+static void dmp_udp2b_tab(word32 *, word32);
+static int32 udmp_impossible_value(word32, word32);
+static char *bldndx_str(char *, word32, word32);
+static void dmp_edge_udptab(struct udp_t *);
+static void dmp_udp3v_etab(word32 *, word32, int32, int32);
+static void dmp_udp2b_etab(word32 *, word32, int32, int32);
+static void prep_edge_udptab(struct udp_t *);
+static void xpnd_edge_wcard(word32, int32, int32, word32);
+static void free_udp_lines(struct udp_t *);
+static void change_all_rngreps(void);
+static void set_optim_nflds(struct net_t *);
+static void free_ncablks(void);
+static void emit_varunused_informs(struct net_t *, struct task_t *);
+static void rt_change_rngrep(struct net_t *);
+static void bld_gstate(void);
+static void alloc_gstate(struct gate_t *, int32);
+static word32 cmp_udpind(word32, word32);
+static void prep_conta_dels(void);
+static int32 rhs_cat_separable(struct expr_t *);
+static int32 rhs_modpin_separable(struct expr_t *);
+static void bld_pbsep_input_mpps(void);
+static void bld_pbsep_output_mpps(void);
+static int32 output_pb_separable(void);
+static void bld_pb_mpps(struct mod_pin_t *);
+static void bld_pb_contas(void);
+static struct pbexpr_t *bld_pb_expr_map(struct expr_t *, int32);
+static void init_pbexpr_el(struct pbexpr_t *);
+static struct expr_t *bld_1sep_pbit_expr(struct pbexpr_t *, int32);
+static struct expr_t *cnvt_to_bsel_expr(struct expr_t *, int32);
+static void bld_nplist(void);
+static void bld_lhsexpr_npins(struct expr_t *, int32);
+static void bld2_lhsexpr_npins(struct expr_t *, int32);
+static void bld_rhsexpr_npins(struct expr_t *, int32);
+static void conn_rtxmr_npin(struct net_t *, int32, int32, int32, int32,
+ struct gref_t *, int32, char *);
+static void conn_xmr_npin(struct net_t *, int32, int32, int32, int32,
+ struct gref_t *, int32, char *);
+static struct net_pin_t *conn2_npin(struct net_t *, int32, int32, int32,
+ int32);
+static void set_chgsubfld(struct net_pin_t *, int32, char *);
+static void add_netdel_pnp(struct net_t *, struct paramlst_t *);
+static void init_pnp(struct parmnet_pin_t *);
+static void addto_parmnplst(struct expr_t *, struct parmnet_pin_t *);
+static void add_gatedel_pnp(struct gate_t *, struct paramlst_t *);
+static void add_contadel_pnp(struct conta_t *, struct paramlst_t *);
+static void free_1parm_pnps(struct net_t *);
+static void realloc_npplist_to_tab(void);  
+static void realloc_1net_npplist(struct net_t *);
+static int32 cnt_npps(struct net_pin_t *);
+static int32 cnt_dces(struct dcevnt_t *);
+static void eat_gates(void);
+static int32 has_muststay_npp(register struct net_pin_t *);
+static void mark_muststay_wires(struct expr_t *);
+static void eat_nets(int32);
+static void rem_del_npps(void);
+static void remove_all_npps(struct net_t *);
+static void bld1vec_fifo(struct net_t *);
+static void update_vec_fifo(struct net_t *, word32 *, int32 *, int32 *,
+ int32 *);
+static int32 wire_implied_driver(struct net_t *);
+static void eat_cells(int32 *);
+static int32 conn_expr_gone(struct expr_t *);
+static void mark_maybe_gone_nets(struct expr_t *);
+static void getbit_fifo(struct net_t *, int32, int32 *, int32 *);
+
+/* extern prototypes (maybe defined in this module) */
+extern void __prep_sim(void);
+extern void __set_init_gstate(struct gate_t *, int32, int32);
+extern void __set_init_udpstate(struct gate_t *, int32, int32);
+extern void __conn_npin(struct net_t *, int32, int32, int32, int32,
+ struct gref_t *, int32, char *);
+extern struct net_pin_t *__alloc_npin(int32, int32, int32);
+extern struct npaux_t *__alloc_npaux(void);
+extern void __add_dctldel_pnp(struct st_t *);
+extern void __add_tchkdel_pnp(struct tchk_t *, int32);
+extern void __add_pathdel_pnp(struct spcpth_t *);
+extern void __free_design_pnps(void);
+extern int32 __get_acc_class(struct gate_t *);
+extern int32 __add_gate_pnd0del(struct gate_t *, struct mod_t *, char *);
+extern int32 __add_conta_pnd0del(struct conta_t *, struct mod_t *, char *);
+
+extern void __prep_xmrs(void);
+extern void __alloc_nchgaction_storage(void);
+extern void __alloc_sim_storage(void);
+extern void __bld_bidandtran_graph(void);
+extern void __setchk_all_fifo(void);
+extern void __prep_exprs_and_ports(void);
+extern void __prep_contas(void);
+extern void __prep_stmts(void);
+extern void __set_nchgaction_bits(void);
+extern void __set_optimtab_bits(void);
+extern void __set_mpp_assign_routines(void);
+extern void __set_pb_mpp_assign_routines(void);
+extern void __set_mpp_aoff_routines(void);
+extern void __dmpmod_nplst(struct mod_t *, int32);
+extern void __do_decompile(void);
+extern void __prep_specify(void);
+extern void __show_allvars(void);
+extern char *__my_malloc(int32);
+extern void __my_free(char *, int32);
+extern char *__to_uvvnam(char *, word32);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_ptnam(char *, word32);
+extern void __prep_delay(struct gate_t *, struct paramlst_t *, int32, int32,
+ char *, int32, struct sy_t *, int32);
+extern void __free_xtree(struct expr_t *);
+extern void __init_vec_var(register word32 *, int32, int32, int32, word32,
+ word32);
+extern char *__to_mpnam(char *, char *);
+extern int32 __isleaf(struct expr_t *);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern void __free_dellst(struct paramlst_t *);
+extern void __free_del(union del_u, word32, int32);
+extern void __bld_pb_fifo(struct net_t *, int32 *, int32 *, int32 *, int32);
+extern int32 __gate_is_acc(struct gate_t *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern void __allocinit_perival(union pck_u *, int32, int32, int32);
+extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
+extern void __rem_0path_dels(void);
+extern int32 __chk_0del(word32, union del_u, struct mod_t *);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern struct expr_t *__copy_expr(struct expr_t *);
+extern int32 __cnt_cat_size(struct expr_t *);
+extern struct expr_t *__alloc_newxnd(void);
+extern struct expr_t *__bld_rng_numxpr(word32, word32, int32);
+extern int32 __get_const_bselndx(register struct expr_t *);
+extern void __getwir_range(struct net_t *, int32 *, int32 *);
+
+extern void __cv_msg(char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __pv_ferr(int32, char *, ...);
+extern void __gfinform(int32, word32, int32, char *, ...);
+extern void __gfwarn(int32, word32, int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+
+extern void __vpi_err(int32, int32, char *, ...);
+
+extern word32 __masktab[];
+
+/*
+ * SIMULATION PREPARATION ROUTINES
+ */
+
+/*
+ * prepare for simulation
+ */
+extern void __prep_sim(void)
+{
+ register struct mod_t *mdp; 
+ int32 sav_declobj;
+
+ /* because checking delay expressions need object type global set */
+ sav_declobj = __cur_declobj;
+ __cur_declobj = MODULE;
+
+ /* done reading source files - remove all duplicates from inc dbg list */
+ if (__inclst_hdr != NULL) rem_inc_dupes();
+
+ /* build per type udp tables - 1st since can free lots of storage */
+ prep_udps();
+
+ /* first change all wire ranges to constant form - need to build np list */
+ change_all_rngreps();
+
+ /* allocate and fill xmr table - used when building np list */
+ __prep_xmrs();
+
+ /* SJM 09/18/02 - build the per bit decomposed ports and iconns */
+ bld_pbsep_input_mpps();
+ bld_pbsep_output_mpps();
+ bld_pb_contas();
+
+ /* build the various net pin lists */
+ bld_nplist();
+
+ /* if errors building np list can't check further */
+ if (__pv_err_cnt != 0) return;
+
+ /* SJM 05/03/05 - now always allocate nchg action byte table separately */
+ __alloc_nchgaction_storage();
+
+ /* allocate storage for wire and regs (variables) and gate states */
+ __alloc_sim_storage();
+
+ bld_gstate();
+ prep_conta_dels();
+
+ /* build inout tran and tran channel connection graphs */
+ __bld_bidandtran_graph();
+
+ /* SJM 12/19/04 - after tran chans built, tran npps removed so can convert */
+ /* npp list to a table - but still set npnxt since add/rem during sim */ 
+ realloc_npplist_to_tab();  
+
+ if (__gateeater_on) eat_gates();
+
+ /* mark each wire that has multi fan in for any bit */
+ __setchk_all_fifo();
+
+ /* allocate inout port memory and mark expr. fi>1 */
+ __prep_exprs_and_ports();
+
+ /* special preparation for contas (alloc drive values) and check getpats */
+ __prep_contas();
+
+ /* modify statements where needed */
+ /* this also needs sim storage to be allocated */
+ __prep_stmts();
+
+ /* new first step toward compiler optimization routines (this for ports) */ 
+ if (__accelerate)
+  {
+   __set_mpp_assign_routines();
+   __set_pb_mpp_assign_routines();
+  }
+ else __set_mpp_aoff_routines();
+
+ /* SJM 07/19/02 - need to prep specify to add tchk and path loads */
+ /* before setting nchg action bits */
+
+ /* all modules processed, object now only specify */
+ __cur_declobj = SPECIFY;
+ __prep_specify();
+ /* interactive must run in module declare object for expr. */
+ __cur_declobj = sav_declobj;
+
+ /* SJM 08/08/03 - order was wrong, this is needed before setting chg bits */
+ /* LOOKATME - only setting optim fields for dmpvars so far */
+ __set_optimtab_bits();
+
+ /* SJM 05/05/05 - since using new nchgbtab for per inst nchg bytes */
+ /* must always initialize the nchg action bits here */
+ /* notice all event control dces added by here */
+ __set_nchgaction_bits();
+
+ if (__debug_flg)
+  {
+   for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+    __dmpmod_nplst(mdp, FALSE); 
+  }
+ if (__debug_flg && __decompile) __do_decompile();
+
+ if (__debug_flg) __show_allvars();
+}
+
+/*
+ * ROUTINES TO PREPARE SOURCE FOR DEBUGGER CAN BE DONE ANY TIME
+ */
+
+/*
+ * remove all duplicated (exactly same name) include files 
+ */
+static void rem_inc_dupes(void)
+{
+ register struct incloc_t *ilp, *ilp2, *last_ilp2, *ilp3;
+
+ for (ilp = __inclst_hdr; ilp != NULL; ilp = ilp->inclocnxt) 
+  {
+   last_ilp2 = ilp;
+   for (ilp2 = ilp->inclocnxt; ilp2 != NULL;)
+    {
+     ilp3 = ilp2->inclocnxt;
+     /* notice if same file included with different path ref. just left */
+     if (strcmp(__in_fils[ilp->inc_fnind], __in_fils[ilp2->inc_fnind]) == 0)
+      {
+       /* if same leave first and link out next and keep looking */
+       last_ilp2->inclocnxt = ilp2->inclocnxt;
+       __my_free((char *) ilp2, sizeof(struct incloc_t));
+      }
+     else last_ilp2 = ilp2;
+     ilp2 = ilp3;
+    }
+  }
+}
+
+/*
+ * ROUTINES TO BUILD UDP STATE CHANGE TABLES
+ */
+
+/*
+ * prepare all udp types - i.e. build the tables
+ */
+static void prep_udps(void)
+{
+ register struct udp_t *udpp;
+ struct udp_t *udpp2, *last_udpp;
+ long sav_mem_use;
+
+ sav_mem_use = __mem_use;
+ for (last_udpp = NULL, udpp = __udphead; udpp != NULL;)
+  {
+   udpp2 = udpp->udpnxt;
+   if (udpp->u_used)
+    {
+     __mem_use = sav_mem_use;
+     prep1_udp(udpp);
+     __mem_udpuse += __mem_use - sav_mem_use;
+     __mem_use = sav_mem_use; 
+
+     /* cannot free lines since dumping source for debug after prep DBG */
+     /* free_udp_lines(udpp); */
+     last_udpp = udpp;
+    }
+   else
+    {
+     free_udp_lines(udpp);
+     __my_free((char *) udpp, sizeof(struct udp_t));
+     if (last_udpp == NULL) __udphead = udpp2;
+     else last_udpp->udpnxt = udpp2;  
+     /* do not change last_udpp here */ 
+    }
+   udpp = udpp2;
+  }
+}
+
+/*
+ * prepare one udp
+ */
+static void prep1_udp(struct udp_t *udpp)
+{
+ /* either combinatorial (no state) or level */
+ if (udpp->utyp != U_EDGE)
+  {
+   udpp->utab = (struct udptab_t *) __my_malloc(sizeof(struct udptab_t));
+   udpp->utab->eudptabs = NULL;
+   prep_comb_udptab(udpp);
+   /* array of pointers to tables is of size [number of edge tables-1] */
+   udpp->utab->ludptab = __cur_utab;
+   /* DBG remove --
+   if (__debug_flg) dmp_comb_udptab(udpp);
+   --- */
+   return;
+  }
+ /* build the edge table - for now always build even if no level entries */
+ prep_edge_udptab(udpp);
+ /* -- DBG remove
+ if (__debug_flg) dmp_edge_udptab(udpp);
+ --- */
+}
+
+/* table of combinatorial table output sizes in bits (2 per entry) */
+/* constant must be <= 7 since 7 inputs is 4k bytes per table */
+static int32 combtabsiz[] = { 0, 8, 32, 128, 512, 2048, 8192, 32768 };
+
+/* table of slower encoding scheme sizes in bits (standard <= 10 ins) */
+static int32 comb2tabsiz[] = { 0, 6, 18, 54, 162, 486, 1458, 4374, 13122,
+ 39366, 118098, 354294, 1062882, 3188646, 9565938, 28697814 };
+
+/*
+ * build the combinatorial table
+ * also needed for sequential udps where levels override edges
+ * use 2 bit per input form for up to 6 inputs
+ *
+ * notice output can not be wild card since would means 1 input combination
+ * to multiple outputs
+ */
+static void prep_comb_udptab(struct udp_t *udpp)
+{
+ register struct utline_t *utlp;
+ word32 nstates;
+ int32 blen, bytsiz;
+ word32 ndx;
+ char out_ch;
+
+ /* for comb. errors must indicate no edge */
+ __cur_ueipnum = NO_VAL;
+ __cur_utabsel = NO_VAL;
+ /* udp number of states includes output for sequentials */
+ nstates = udpp->numstates;
+ /* set size of table */
+ if (udpp->u_wide) blen = comb2tabsiz[nstates];
+ else blen = combtabsiz[nstates];
+ /* notice Verilog assumes 8 bit bytes */
+ /* SJM 05/19/01 - since fill using word32 ptr need to round to wrd bytes */
+ bytsiz = WRDBYTES*wlen_(blen);
+ /* RELEASE remove --
+ if (__debug_flg)
+  __dbg_msg("## comb (part?) udp %s - %u states with table size %d bytes\n",
+   udpp->usym->synam, nstates, bytsiz); 
+ --- */
+ __cur_utab = (word32 *) __my_malloc(bytsiz);
+ /* initialize to unfilled (3) - maps table x (2) to real 3 as last step */
+ init_utab(__cur_utab, blen);
+ __cur_udp = udpp;
+
+ for (utlp = udpp->utlines; utlp != NULL; utlp = utlp->utlnxt)
+  {
+   /* if this is edge line, goes in edge not combinatorial table */
+   if (utlp->uledinum != NO_VAL) continue;
+
+   __sfnam_ind = utlp->utlfnam_ind;
+   __slin_cnt = utlp->utlin_cnt;
+
+   /* next output state can be wildcard */
+   if (utlp->ulhas_wcard) bld_wcardtab(utlp->tline, nstates, nstates + 1);
+
+   /* build 2 bit form for narrow or signature for wide */
+   /* wildcards here always make 0 contribution */  
+   ndx = bld_uinitndx(utlp->tline, nstates, -1);
+
+   /* out ch gets the output value (as char here) */
+   out_ch = utlp->tline[udpp->numstates];
+   /* if output - (no change form) must set output (__cur_uoval) during */
+   /* wild card expansion */  
+   if (out_ch == '-') __cur_unochange = TRUE;
+   else
+    {
+     /* else can set it immediately */
+     __cur_unochange = FALSE;
+     /* must be for checking so will match x */
+     __cur_uoval = (word32) ((out_ch == '0') ? 0 : ((out_ch == '1') ? 1 : 2));  
+    }
+   /* this sets 1st to each and recursives call self to expand others */
+   if (utlp->ulhas_wcard) xpnd_1wcard(0, ndx);
+   /* if no wildcards, even if '-' output, will be 0/1/x (3 since out) */
+   /* this sets current output value */
+   else setchk_uval(ndx);
+  }
+ /* finally for all locations left unitialized changed to udp x (2) */
+ chg_unfilled_tox(__cur_utab, blen);
+}
+
+extern word32 __pow3tab[];
+
+/*
+ * recursively expand 1 wild card
+ * if wildcard, must be used to set all o states (even 1st)
+ * notice recursion depends on fact that passed ndx is by value
+ */
+static void xpnd_1wcard(int32 wci, word32 ndx)
+{
+ int32 wcvi, wchval, i;
+ word32 ndx2;
+ 
+ wchval = (__wcardtab[wci].wcchar == '?') ? 2 : 1;
+ i = __wcardtab[wci].wcinum;
+ /* notice need to go through for 0 since table value not yet set */
+ for (wcvi = 0; wcvi <= wchval; wcvi++)
+  {
+   if (!__cur_udp->u_wide)
+    {
+     /* know i input 2 bits will always be 0 */
+     if (wcvi == 0) ndx2 = ndx;
+     else
+      { 
+       /* needed because even though now sticking 2 in as x output */
+       /* index must be 3 which will be the value after table prepared */
+       /* for non wide table entry */
+       if (wcvi == 2) wcvi = 3;
+       ndx2 = ndx | (word32) (wcvi << (2*i));
+      }
+    }
+   else
+    { 
+     /* know here contribution from i, is 0 in ndx */
+     if (wcvi != 0) ndx2 = ndx + wcvi*__pow3tab[i];
+     else ndx2 = ndx;
+     /* know if this is true, will always be rightmost wild card */
+     if (i == __cur_udp->numstates - 1) __cur_upstate = (word32) wcvi;
+     if (ndx2 >= __pow3tab[__cur_udp->numstates])
+      __misc_terr(__FILE__, __LINE__);
+    }
+   /* - (no change) output handled in level value setting */
+   if (wci == __last_wci) setchk_uval(ndx2);
+   else xpnd_1wcard(wci + 1, ndx2);
+  }
+}
+
+/*
+ * init a udp table to 3 (not set) - later change 2 (x for now) to x (3)
+ * notice udp 2 is unused not z (no z in udp world) 
+ * inputs always just 3 for normal rep, 2 add value for signature
+ *
+ * when done here all 2's changed to 3's (real x's stored in output gstate)
+ * radix form uses 3's in vector but changed to 2 in signature update
+ * notice any unused in high word32 just set to unfilled
+ */
+static void init_utab(word32 *taddr, int32 blen)
+{
+ register int32 i;
+ register word32 *wp;
+ int32 wlen;
+
+ wlen = wlen_(blen);
+ /* initialize to real x's - during table building x's are 2 that are then */
+ /* changed to 3's where needed */
+ /* since most of table is x's can check and change to x much faster */
+ for (wp = taddr, i = 0; i < wlen; i++) wp[i] = ALL1W;
+ wp[wlen - 1] &= __masktab[ubits_(blen)];
+}
+
+/*
+ * convert 1 unfilled (defaults to x) from unfill 2 to x (3)
+ */
+static void chg_unfilled_tox(word32 *taddr, int32 blen)
+{
+ register word32 tmp;
+ register int32 wi, bi;
+ int32 wlen, ubits;
+
+ wlen = wlen_(blen);
+ for (wi = 0; wi < wlen - 1; wi++) 
+  {
+   /* if all bits already literally set to x's continue */
+   if ((tmp = taddr[wi]) == ALL1W) continue;
+
+   /* must change 2 (tmp. udp table build x) to 3 - real x */
+   for (bi = 0; bi < WBITS; bi += 2)
+    {
+     if (((tmp >> bi) & 0x3L) == 2L)
+      tmp |= (3L << bi);
+    }
+   taddr[wi] = tmp;
+  }
+ /* if by accident high word32 full and already all x's - done */
+ if ((tmp = taddr[wlen - 1]) == ALL1W) return; 
+
+ /* high word32 needs special handling */
+ if ((ubits = ubits_(blen)) == 0) ubits = WBITS;
+ for (bi = 0; bi < ubits; bi += 2) 
+  {
+   if (((tmp >> bi) & 0x3L) == 2L) tmp |= (3L << bi);
+  }
+ taddr[wlen - 1] = tmp;
+}
+
+/*
+ * build wild card table from input line
+ * for each wild card table contains input no. and wild card char
+ *
+ * even if edge (\?\?) form (really *) do not include in wild card table
+ * for combinatorial table pass one past last input
+ */
+static void bld_wcardtab(register char *chp, word32 nstates, word32 einum)
+{
+ register word32 i;
+ struct wcard_t *wcp;
+
+ for (__last_wci = -1, i = 0; i < nstates; i++, chp++)
+  {
+   if (i == einum) continue;
+
+   if (*chp == 'b' || *chp == '?')
+    {
+     wcp = &(__wcardtab[++__last_wci]);
+     wcp->wcinum = i;
+     wcp->wcchar = *chp;
+    }
+  }
+}
+
+/*
+ * build the initial udp table index - 
+ * either 2 bit per input with x as 3 or signature with x as 2 contribution
+ */
+static word32 bld_uinitndx(char *tlp, word32 nstates, int32 einum)
+{
+ register word32 i;
+ register char *chp;
+ word32 ndx;
+
+ /* ? (01x) and b (01) are only that later require loops */
+ ndx = 0;
+ /* build initial state vector and set rep table start */
+ /* wild cards 0 for now */
+ /* notice cannot build incrementally, pins in initial signature backward*/ 
+ for (i = 0, chp = tlp; i < nstates; i++, chp++)
+  {
+   /* for edge tab, if wildcard table select do not include, added in xpnd */
+   if (i == (int32) einum) continue;
+   switch (*chp) {
+    /* make edge wildcards 0 here also - r/f just (01) and (10) by here */
+    case '0': case 'b': case '?': case '*': case 'n': case 'p':
+     if (__cur_udp->u_wide) __cur_upstate = 0L;
+     break;
+    case '1':
+     if (__cur_udp->u_wide) { ndx += __pow3tab[i]; __cur_upstate = 1L; }
+     else { ndx &= ~(3L << (2*i)); ndx |= (1L << (2*i)); }
+     break;
+    /* explicit x is always 2 here for normal udp (later changed to 3) */
+    case 'x':
+     if (__cur_udp->u_wide) { ndx += 2*__pow3tab[i]; __cur_upstate = 2L; }
+     else ndx |= (3L << (2*i));
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+  }
+ return(ndx);
+}
+
+/*
+ * set and check if already set a normal non signature udp table entry
+ * this is only place in udp preparation code that udp tables indexed
+ * this is passed input state in 2 bit form with x == 2
+ * uninitialized is 3 here that statys as real x (3) before exec
+ * set to x is 2 here that is changed to 3, real x  
+ */
+static void setchk_uval(word32 init_ndx)
+{
+ register word32 tw, tw2;
+ word32 ndx;
+ int32 wi, bi;
+ char s1[RECLEN], s2[RECLEN];
+
+ /* by here init_ndx is correct for this wildcard */ 
+ if (__cur_udp->u_wide) ndx = init_ndx;
+ else ndx = init_ndx & (int32) __masktab[2*__cur_udp->numstates];
+
+ /* set 2: get old value */
+ wi = get_wofs_(2*ndx);
+ bi = get_bofs_(2*ndx);
+ /* notice for edge cur utab set to right table from edge pair */
+ tw = __cur_utab[wi];
+ tw2 = (tw >> bi) & 3L;
+
+ /* step 2a: if - output form get output */
+ /* if output is '-' use last input that is state */
+ /* if not '-' form, know __cur_uoval not set */
+ if (__cur_unochange)
+  {
+   /* notice this can only happen for udp's with state */
+   if (__cur_udp->u_wide) __cur_uoval = __cur_upstate;
+   else
+    {
+     __cur_uoval = (init_ndx >> (2*(__cur_udp->numins))) & 0x3L;
+     /* must be 2 so if table set (old value == 2) will get warn if 2 */
+     if (__cur_uoval == 3L) __cur_uoval = 2L;
+    }
+  }
+ /* step3: if table value already set - check it */
+ if (tw2 != 3L)
+  {
+   if (__cur_uoval == tw2)
+    {
+     /* do not know previous line - could save but complicated */
+    __sgfinform(462, "udp %s selector %s repeated", __cur_udp->usym->synam,
+      bld_udploc(s1, ndx, __cur_uoval, __cur_udp->numstates));
+     goto done;
+    }
+  __sgferr(970, "udp %s selector %s conflicts with previous %s",
+   __cur_udp->usym->synam, bld_udploc(s1, ndx, __cur_uoval,
+   __cur_udp->numstates), bld_udploc(s2, ndx, tw2, __cur_udp->numstates));
+   /* fall thru here, even though error, use latest */
+  }
+ 
+ /* step4: change output to new value, here x must be represented as 2 */
+ /* that gets changed later */
+ __cur_utab[wi] = (tw & ~(3L << bi)) | (__cur_uoval << bi);
+
+done:;
+ /* --- RELEASE ---
+ if (__debug_flg)
+  { 
+   __dbg_msg("+++ udp set: %s, val=%x, bi=%d, wi=%d\n", 
+    bld_udploc(s1, ndx, __cur_uoval, __cur_udp->numstates),
+    __cur_utab[wi], bi, wi);
+   __dbg_msg("+++ udp set: %s\n", bld_udploc(s1, ndx, __cur_uoval,
+    __cur_udp->numstates));
+  }
+ --- */
+}
+
+/*
+ * build a udp location entry - for error messages
+ * notice for wide signature form index must be wp[1] actual table index
+ */
+static char *bld_udploc(char *s, word32 ndx, word32 val, word32 nstates)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ if (__cur_udp->u_wide) bld3vndx_str(s1, ndx, nstates);
+ else bldndx_str(s1, ndx, nstates);
+ udploc_to_line(s2, s1);
+
+ sprintf(s, "%s : %s", s2, __to_uvvnam(s1, (word32) val));
+ return(s);
+}
+
+/*
+ * convert a simple edge char array to edge line 
+ */
+static char *udploc_to_line(char *s, char *line)
+{
+ register int32 i;
+ int32 slen;
+ char *chp, *lchp;
+
+ /* first add edge */
+ if (__cur_ueipnum != NO_VAL)
+  {
+   lchp = line;
+   chp = s;
+   for (i = 0; *lchp != '\0'; i++)
+    {
+     if (i == __cur_ueipnum)
+      {
+       *chp++ = '('; 
+       *chp++ = (__cur_utabsel == 0) ? '0': (__cur_utabsel == 1) ? '1' : 'x'; 
+       *chp++ = *lchp++;
+       *chp++ = ')';   
+      }
+     else *chp++ = *lchp++;     
+    }
+   *chp = '\0';
+  }
+ else strcpy(s, line);
+ /* then add : if has state */
+ if (__cur_udp->numins != __cur_udp->numstates)
+  {
+   slen = strlen(s);
+   s[slen + 1] = '\0';
+   s[slen] = s[slen - 1];
+   s[slen - 1] = ':';
+  }
+ return(s);
+}
+
+/*
+ * dump a non edge udp table only 6 states or less
+ */
+static void dmp_comb_udptab(struct udp_t *udpp)
+{
+ word32 *utabp;
+ word32 nstates;
+
+ utabp = udpp->utab->ludptab;
+ nstates = udpp->numstates;
+ if (nstates > 6) return;
+
+ __dbg_msg(".. dumping combinatorial udp %s with %d states\n",
+  udpp->usym->synam, nstates);
+ if (udpp->u_wide) dmp_udp3v_tab(utabp, nstates);
+ else dmp_udp2b_tab(utabp, nstates);
+ __dbg_msg("... end dump\n");
+}
+
+/*
+ * dump a non superposition 2b per element form udp table
+ * input is array of words and number of inputs 
+ * need more sophisticated version
+ */
+static void dmp_udp3v_tab(word32 *tabp, word32 nstates) 
+{
+ register word32 i;
+ int32 bi, wi;
+ word32 val, ndx;
+ char s1[RECLEN], s2[RECLEN];
+
+ ndx = 0;
+ for (i = 0, bi = 0; i < __pow3tab[nstates]; i++) 
+  { 
+   ndx = i;
+   wi = get_wofs_(2*ndx);
+   bi = get_bofs_(2*ndx); 
+   val = (tabp[wi] >> bi) & 0x3L;
+   /* RELEASE ---
+   __dbg_msg("%s: %s, val=%lx, bi=%d, wi=%d\n", bld3vndx_str(s1, ndx,
+    nstates), __to_uvvnam(s2, val), tabp[wi], bi, wi);
+   --- */
+   __dbg_msg("%s: %s\n", bld3vndx_str(s1, ndx, nstates),
+    __to_uvvnam(s2, val));
+  }
+}
+
+/*
+ * build the input string with high value (rightmost on left)
+ */
+static char *bld3vndx_str(char *s, word32 ndx, word32 nstates)
+{
+ register word32 i;
+ word32 val;
+ char s1[10];
+
+ for (i = 0; i < nstates; i++)
+  { val = ndx % 3; ndx /= 3; __to_uvvnam(s1, val); s[i] = s1[0]; }
+ s[i] = '\0';
+ return(s);
+}
+
+/*
+ * dump a non superposition 2b per element form udp table
+ * input is array of words and number of inputs 
+ */
+static void dmp_udp2b_tab(word32 *tabp, word32 nstates)
+{
+ register word32 i;
+ int32 bi, wi;
+ word32 val, ndx;
+ char s1[RECLEN], s2[RECLEN];
+
+ ndx = 0;
+ for (i = 0; i < (1 << (2*nstates)); i++)
+  { 
+   ndx = (word32) i;
+   /* for narrow case, z's in signature but never used */
+   if (udmp_impossible_value(ndx, nstates)) continue;
+
+   wi = get_wofs_(2*ndx);
+   bi = get_bofs_(2*ndx); 
+   val = (tabp[wi] >> bi) & 0x3L;
+   /* --- RELEASE
+   if (__debug_flg)
+    { 
+     __dbg_msg("%s: %s, val=%lx, bi=%d, wi=%d\n", bldndx_str(s1, ndx,
+      nstates), __to_uvvnam(s2, val), tabp[wi], bi, wi);
+    }
+   -- */
+   __dbg_msg("%s: %s\n", bldndx_str(s1, ndx, nstates),
+    __to_uvvnam(s2, val));
+  }
+}
+
+/*
+ * return T if somewhere there is a 2 bit 10 pattern in word
+ * since for narrow know 10 index never used just 00, 01, 11
+ */
+static int32 udmp_impossible_value(word32 ndx, word32 nstates)
+{
+ register word32 i;
+
+ for (i = 0; i < nstates; i++)
+  { if (((ndx >> (2*i)) & 3L) == 2L) return(TRUE); }
+ return(FALSE);
+}
+
+/*
+ * build the input string with high value (rightmost on left)
+ */
+static char *bldndx_str(char *s, word32 ndx, word32 nstates)
+{
+ register word32 i;
+ word32 val;
+ char vs1[10];
+
+ for (i = 0; i < nstates; i++)
+  { val = (ndx >> (2*i)) & 3L; __to_uvvnam(vs1, val); s[i] = vs1[0]; }
+ s[i] = '\0';
+ return(s);
+}
+
+/*
+ * dump an combinatorial udp table if not more than 5 inputs
+ */
+static void dmp_edge_udptab(struct udp_t *udpp)
+{
+ word32 *utabp;
+ int32 nins, i, v;
+
+ nins = udpp->numins;
+ if (nins > 5) return;
+
+ __dbg_msg(".. dumping edge udp %s with %d inputs\n", udpp->usym->synam,
+  nins);
+ __dbg_msg(" - combinatorial table:\n");
+ dmp_comb_udptab(udpp);
+
+ __dbg_msg(" - edge tables:\n");
+ /* notice, edge udp always sequential and no edge for state input */
+ for (i = 0; i < nins; i++)  
+  {
+   for (v = 0; v < 3; v++)
+    {
+     __dbg_msg(
+      "--> input no. %d changed from %c\n", i, ((v > 1) ? 'x': '0' + v ));
+     utabp = udpp->utab->eudptabs[3*i + v];
+     if (udpp->u_wide) dmp_udp3v_etab(utabp, udpp->numstates, i, v);
+     else dmp_udp2b_etab(utabp, udpp->numstates, i, v);
+    }
+  }
+ __dbg_msg("... end dump\n");
+}
+
+/*
+ * dump a superposition form edge udp table
+ * input is array of words and number of inputs 
+ * leave out lines where edge input and edge new value are same
+ * know eipnum never state value
+ */
+static void dmp_udp3v_etab(word32 *tabp, word32 nstates, int32 eipnum,
+ int32 e1val) 
+{
+ register word32 i;
+ int32 bi, wi, ndxev;
+ word32 val, ndx;
+ char s1[RECLEN], s2[RECLEN];
+
+ ndx = 0;
+ for (i = 0, bi = 0; i < __pow3tab[nstates]; i++) 
+  { 
+   ndx = i;
+   bld3vndx_str(s1, ndx, nstates),
+   ndxev = (s1[eipnum] == 'x') ? 2 : (s1[eipnum] - '0'); 
+   if (e1val == ndxev) continue;
+
+   wi = get_wofs_(2*ndx);
+   bi = get_bofs_(2*ndx); 
+   val = (tabp[wi] >> bi) & 0x3L;
+   /* --- RELEASE remove
+   __dbg_msg("%s: %s, val=%lx, bi=%d, wi=%d\n", s1, __to_uvvnam(s2, val),
+    tabp[wi], bi, wi);
+   --- */
+   __dbg_msg("%s: %s\n", s1, __to_uvvnam(s2, val));
+  }
+}
+
+/*
+ * dump a non superposition 2b per element form udp table
+ * input is array of words and number of inputs 
+  * notice for 11 states size will be 1 million lines
+ */
+static void dmp_udp2b_etab(word32 *tabp, word32 nstates, int32 eipnum,
+ int32 e1val) 
+{
+ register word32 i;
+ int32 bi, wi, ndxev;
+ word32 val, ndx;
+ char s1[RECLEN], s2[RECLEN];
+
+ ndx = 0L;
+ for (i = 0; i < (1 << (2*nstates)); i++)
+  { 
+   ndx = (word32) i;
+   /* for narrow case, z's in signature but never used */
+   if (udmp_impossible_value(ndx, nstates)) continue;
+
+   bldndx_str(s1, ndx, nstates);
+   ndxev = (s1[eipnum] == 'x') ? 2 : (s1[eipnum] - '0'); 
+   if (e1val == ndxev) continue;
+
+   wi = get_wofs_(2*ndx);
+   bi = get_bofs_(2*ndx); 
+   val = (tabp[wi] >> bi) & 0x3L;
+   /* RELEASE remove --- 
+   __dbg_msg("%s: %s, val=%lx, bi=%d, wi=%d\n", s1, __to_uvvnam(s2, val),
+    tabp[wi], bi, wi);
+   --- */
+   __dbg_msg("%s: %s\n", s1, __to_uvvnam(s2, val));
+  }
+}
+
+/*
+ * allocate the edge index and all the edge tables and set values from lines
+ * know level table already filled and edge tables pointer array allocated
+ */
+static void prep_edge_udptab(struct udp_t *udpp)
+{
+ register int32 i;
+ register struct utline_t *utlp;
+ int32 nins, eutabels, blen, bytsiz, tabi, e1val, e2val;
+ word32 nstates;
+ word32 ustate;
+ char ech, out_ch, ech2;
+
+ nstates = udpp->numstates;
+ nins = udpp->numins;
+ /* these are size for 1 table in bits */
+ if (udpp->u_wide) blen = comb2tabsiz[nstates];
+ else blen = combtabsiz[nstates];
+ /* SJM 05/19/01 - since fill using word32 ptr need to round to wrd bytes */
+ bytsiz = WRDBYTES*wlen_(blen);
+
+ /* idea is that old input value selects table, new is index in table */
+ /* 1 input 3 table 0,1,x, 2 inputs 6, 3 for 1st and 3 for 2nd, ... */  
+ /* state input cannot have edge */
+ eutabels = 3*nins;
+ /* -- RELEASE remove
+ if (__debug_flg)
+  __dbg_msg("## edge udp %s - %d inputs %d tables of size %d bytes\n",
+   udpp->usym->synam, nins, eutabels, bytsiz); 
+ -- */
+
+ /* number of separate tables is 1 per 3*[non state ins (ins-1)] + 1 */
+ /* 3 is possible values and extra 1 is for level lines without edges */
+ udpp->utab = (struct udptab_t *) __my_malloc(sizeof(struct udptab_t));
+ udpp->utab->ludptab = NULL;
+ udpp->utab->eudptabs = (word32 **) __my_malloc(eutabels*4);
+ /* build the level tab - for now always build even if no level entries */
+ prep_comb_udptab(udpp);
+ udpp->utab->ludptab = __cur_utab;
+
+ /* initialize all edge tables to */
+ for (i = 0; i < eutabels; i++)
+  {
+   __cur_utab = (word32 *) __my_malloc(bytsiz);
+   init_utab(__cur_utab, blen);
+   udpp->utab->eudptabs[i] = __cur_utab;
+  }
+
+ for (utlp = udpp->utlines; utlp != NULL; utlp = utlp->utlnxt)
+  {
+   __cur_utlp = utlp;
+   /* if no edge, already used to set level table output */
+   if (utlp->uledinum == NO_VAL) continue;
+
+   __slin_cnt = utlp->utlin_cnt;
+   __sfnam_ind = utlp->utlfnam_ind;
+
+   /* notice 1 possible edge wild card not in wild card table */
+   /* but state can be wild card */
+   /* never add in edge 2nd value here, added in xpnd or const. case */
+   if (utlp->ulhas_wcard) bld_wcardtab(utlp->tline, nstates, utlp->uledinum);
+
+   /* sets any wild cards including edge 1st values will be 00 */
+   /* gets converted if wide form */
+   ustate = bld_uinitndx(utlp->tline, nstates, (int32) utlp->uledinum);
+
+   /* use the previuos state - if wildcard just */
+   if ((out_ch = utlp->tline[nstates]) == '-') __cur_unochange = TRUE;
+   else
+    { 
+     /* if no '-' current output value fixed for all iterations */
+     __cur_unochange = FALSE;
+     /* must be 2 so if output set will match x */
+     __cur_uoval = (out_ch == '0') ? 0 : ((out_ch == '1') ? 1 : 2);
+    }
+   /* for edge wild cards, both values same so can use first tab index */
+   switch ((byte) utlp->utabsel) {
+    case '*':
+do_star:
+     xpnd_edge_wcard(ustate, 0, 1, utlp->uledinum);
+     xpnd_edge_wcard(ustate, 0, 2, utlp->uledinum);
+     xpnd_edge_wcard(ustate, 1, 0, utlp->uledinum);
+     xpnd_edge_wcard(ustate, 1, 2, utlp->uledinum);
+     xpnd_edge_wcard(ustate, 2, 0, utlp->uledinum);
+     xpnd_edge_wcard(ustate, 2, 1, utlp->uledinum);
+     break;
+    case 'p':
+     /* potential rising edge */
+     xpnd_edge_wcard(ustate, 0, 1, utlp->uledinum);
+     xpnd_edge_wcard(ustate, 0, 2, utlp->uledinum);
+     xpnd_edge_wcard(ustate, 2, 1, utlp->uledinum);
+     break;
+    case 'n':
+     /* potential falling edge */
+     xpnd_edge_wcard(ustate, 1, 0, utlp->uledinum);
+     xpnd_edge_wcard(ustate, 1, 2, utlp->uledinum);
+     xpnd_edge_wcard(ustate, 2, 0, utlp->uledinum);
+     break;
+    case '?':
+     ech2 = utlp->tline[utlp->uledinum];
+     /* notice (..) form can be value or b or ? but not edge abbreviation */
+     /* also notice for edge only wildcard is possible '-' */
+     switch (ech2) {
+      case '?':
+       /* (\?\?) is same as * */
+       goto do_star;
+      case 'b':
+       /* (?b) */
+       xpnd_edge_wcard(ustate, 1, 0, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 2, 0, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 0, 1, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 2, 1, utlp->uledinum);
+       break;
+      case '0':
+       /* (?0) */
+       xpnd_edge_wcard(ustate, 1, 0, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 2, 0, utlp->uledinum);
+       break;
+      case '1':
+       /* (?1) */
+       xpnd_edge_wcard(ustate, 0, 1, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 2, 1, utlp->uledinum);
+       break;
+      case 'x':  
+       /* (?x) */
+       xpnd_edge_wcard(ustate, 0, 2, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 1, 2, utlp->uledinum);
+       break;
+      default: __case_terr(__FILE__, __LINE__);
+     }
+     break;
+    case 'b': 
+     ech2 = utlp->tline[utlp->uledinum];
+     switch (ech2) {
+      case '?':
+       /* (b?) */
+       xpnd_edge_wcard(ustate, 0, 1, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 0, 2, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 1, 0, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 1, 2, utlp->uledinum);
+       break;
+      case 'b':
+       /* (bb) */
+       xpnd_edge_wcard(ustate, 0, 1, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 1, 0, utlp->uledinum);
+       break;
+      case '0':
+       /* (b0) */
+       xpnd_edge_wcard(ustate, 1, 0, utlp->uledinum);
+       break;
+      case '1':
+       /* (b1) */
+       xpnd_edge_wcard(ustate, 0, 0, utlp->uledinum);
+       break;
+      case 'x':
+       /* (bx) */
+       xpnd_edge_wcard(ustate, 0, 2, utlp->uledinum);
+       xpnd_edge_wcard(ustate, 1, 2, utlp->uledinum);
+       break;
+      default: __case_terr(__FILE__, __LINE__);
+     }
+     break;
+    case '0': case '1': case 'x':
+     /* notice ech is case index for output tab too */
+     ech = (char) utlp->utabsel;
+     /* may have ([01x][?b]) style wild card form  */
+     ech2 = utlp->tline[utlp->uledinum];
+     if (ech2 == '?')
+      {
+       switch (ech) {
+        case '0':
+         xpnd_edge_wcard(ustate, 0, 1, utlp->uledinum);
+         xpnd_edge_wcard(ustate, 0, 2, utlp->uledinum);
+         break;
+        case '1':
+         xpnd_edge_wcard(ustate, 1, 0, utlp->uledinum);
+         xpnd_edge_wcard(ustate, 1, 2, utlp->uledinum);
+         break;
+        case 'x':
+         xpnd_edge_wcard(ustate, 2, 0, utlp->uledinum);
+         xpnd_edge_wcard(ustate, 2, 1, utlp->uledinum);
+         break;
+        default: __case_terr(__FILE__, __LINE__); 	   
+       }
+       break;
+      }
+     if (ech2 == 'b')
+      {
+       switch (ech) {
+        case '0': xpnd_edge_wcard(ustate, 0, 1, utlp->uledinum); break;
+        case '1': xpnd_edge_wcard(ustate, 1, 0, utlp->uledinum); break;
+        case 'x':
+         xpnd_edge_wcard(ustate, 2, 0, utlp->uledinum);
+         xpnd_edge_wcard(ustate, 2, 1, utlp->uledinum);
+         break;
+        default: __case_terr(__FILE__, __LINE__);
+       }
+       break;
+      }
+
+     e1val = (ech == '0') ? 0 : ((ech == '1') ? 1 : 2);
+     tabi = 3*utlp->uledinum + e1val;
+
+     /* non edge wild card case - must add in 2nd edge part of state */
+     /* know contribution before here 0 */
+     e2val = (ech2 == '0') ? 0 : ((ech2 == '1') ? 1 : 2);
+     if (udpp->u_wide) ustate += (e2val*__pow3tab[utlp->uledinum]); 
+     else ustate |= (e2val << (2*utlp->uledinum));
+
+     /* RELEASE remove --- 
+     if (__debug_flg)
+      __dbg_msg(
+       "=== non wildcard input edge (%c%c) with from value %d - table %d\n",
+       utlp->uledinum, ech, ech2, tabi);
+     --- */
+     /* once current table corresponding to edge is set, just like level */
+     __cur_utab = udpp->utab->eudptabs[tabi];
+     if (!utlp->ulhas_wcard) setchk_uval(ustate);
+     else xpnd_1wcard(0, ustate);
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+  }
+ /* final step is conversion of x (set x) to 3 real x */ 
+ for (i = 0; i < eutabels; i++)
+  {
+   __cur_utab = udpp->utab->eudptabs[i];
+   chg_unfilled_tox(__cur_utab, blen);
+  }
+}
+
+/*
+ * process edge wildcard entry - passed fixed edge generated from iteration
+ * e1 val selects table and e2 val is table value (changed to)  
+ */
+static void xpnd_edge_wcard(word32 ustate, int32 e1val, int32 e2val,
+ word32 einpnum)
+{
+ int32 tabi;
+
+ /* first select the table */
+ tabi = 3*einpnum + e1val;
+ /* --- RELEASE remove 
+ if (__debug_flg)
+  __dbg_msg("=== expand wildcard input edge %d from value %d - table %d\n",
+   einpnum, e1val, tabi);
+ --- */
+ /* once current table corresponding to edge is set, just like level */
+ __cur_utab = __cur_udp->utab->eudptabs[tabi];
+
+ /* must set ustate input no. einpnum to ech2 value - know 0 on input */
+ /* know this can never be last previous state input or will not get here */
+ /* ustate is 2 bit per element form */
+ /* ustate is table index so for narrow form must be 3 */
+ if (__cur_udp->u_wide) ustate += e2val*__pow3tab[einpnum];
+ else
+  {
+   /* ustate is index which for narrow must be 3 - value is 2 */
+   if (e2val == 2) e2val = 3;
+   ustate |= (((word32) e2val) << (2*einpnum));
+  }
+
+ /* need some global to be set for errors */
+ __cur_ueipnum = einpnum;
+ __cur_utabsel = e1val;
+
+ /* ulhas_wcard is only level wildcard */
+ if (!__cur_utlp->ulhas_wcard) setchk_uval(ustate);
+ else xpnd_1wcard(0, ustate);
+}
+
+/*
+ * free udp lines
+ * only called for uninstantiated udps since size small and needed for PLI
+ */
+static void free_udp_lines(struct udp_t *udpp)
+{
+ register struct utline_t *utlp;
+ struct utline_t *utlp2;
+
+ for (utlp = udpp->utlines; utlp != NULL;)
+  {
+   utlp2 = utlp->utlnxt;
+   /* notice this is not 0 terminated string */
+   __my_free(utlp->tline, (int32) utlp->ullen);
+   __my_free((char *) utlp, sizeof(struct utline_t));
+   utlp = utlp2;
+  }
+ udpp->utlines = NULL;
+}
+
+/*
+ * ROUTINES TO CHANGE ALL WIRE RANGE REPS 
+ */
+
+/*
+ * change representation and allocate sim net struct for every net range
+ * must do unused var. checking before change range rep since uses ncomp
+ * range form bits
+ *
+ * BEWARE - for normal nets allocating nu.ct to large chunk area because
+ * freeing too slow - but here for params (also specparams) since cannot
+ * distinguish must copy since now can be annotated too
+ */
+static void change_all_rngreps(void)
+{
+ register int32 ni;
+ register struct net_t *np;
+ register struct ncomp_t *oncomp, *nncomp;
+ struct mod_t *mdp;
+ int32 pi, sav_declobj;
+ struct task_t *tskp;
+
+ sav_declobj = __cur_declobj;
+ __cur_declobj = MODULE;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   __cur_declobj = MODULE;
+
+   if (__inst_mod->mnnum != 0) 
+    {
+     for (ni = 0, np = &(__inst_mod->mnets[0]); ni < __inst_mod->mnnum;
+      ni++, np++)
+      {
+//SJM FIXME - why both { {
+        {
+         /* expect inout ports to be set but not used or used but not set */
+         if (np->iotyp != IO_BID)
+          emit_varunused_informs(np, (struct task_t *) NULL);
+        }
+       set_optim_nflds(np);
+       rt_change_rngrep(np); 
+      }
+    } 
+   /* copy ncomp that are still needed for delay annotation */
+   /* needed because ncomps allocated and freed in blocks */
+   for (pi = 0; pi < __inst_mod->mprmnum; pi++)  
+    {
+     np = &(__inst_mod->mprms[pi]);
+     oncomp = np->nu.ct;
+     nncomp = (struct ncomp_t *) __my_malloc(sizeof(struct ncomp_t));
+     /* expressions not freed and copied will point to right ones */ 
+     memcpy(nncomp, oncomp, sizeof(struct ncomp_t));
+     np->nu.ct = nncomp;
+    }
+
+   __cur_declobj = TASK; 
+   for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if (tskp->trnum == 0) continue;
+
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       emit_varunused_informs(np, tskp);
+
+       set_optim_nflds(np);
+       rt_change_rngrep(np); 
+      }
+     /* copy ncomp that are still needed for delay annotation */
+     /* needed because ncomps allocated and freed in blocks */
+     for (pi = 0; pi < tskp->tprmnum; pi++)  
+      {
+       np = &(tskp->tsk_prms[pi]);
+       oncomp = np->nu.ct;
+       nncomp = (struct ncomp_t *) __my_malloc(sizeof(struct ncomp_t));
+       /* expressions not freed and copied will point to right ones */ 
+       memcpy(nncomp, oncomp, sizeof(struct ncomp_t ));
+       np->nu.ct = nncomp;
+      }
+    }
+   if (__inst_mod->mspfy != NULL)
+    {
+     __cur_declobj = SPECIFY;
+     for (pi = 0; pi < __inst_mod->mspfy->sprmnum; pi++)  
+      {
+       np = &(__inst_mod->mspfy->msprms[pi]);
+       oncomp = np->nu.ct;
+       nncomp = (struct ncomp_t *) __my_malloc(sizeof(struct ncomp_t));
+       /* expressions not freed and copied will point to right ones */ 
+       memcpy(nncomp, oncomp, sizeof(struct ncomp_t ));
+       np->nu.ct = nncomp;
+      }
+    }
+   __pop_wrkitstk();
+  }
+
+ __cur_declobj = sav_declobj;
+ free_ncablks();
+}
+
+/*
+ * copy fields form ncomp into run time net fields
+ *
+ * LOOAKTME - think no longer need 2 step setting of optim fields
+ */
+static void set_optim_nflds(struct net_t *np)
+{
+ np->frc_assgn_allocated = FALSE;
+ np->dmpv_in_src = FALSE;
+ np->monit_in_src = FALSE;
+ np->n_onrhs = FALSE;
+ np->n_onlhs = FALSE;
+ 
+ if (np->nu.ct->frc_assgn_in_src) np->frc_assgn_allocated = TRUE;
+ if (np->nu.ct->dmpv_in_src) np->dmpv_in_src = TRUE;
+ if (np->nu.ct->monit_in_src) np->monit_in_src = TRUE;
+ if (np->nu.ct->n_onrhs) np->n_onrhs = TRUE;
+ if (np->nu.ct->n_onlhs) np->n_onlhs = TRUE;
+}
+
+
+/*
+ * routine to free all allocated ncmp blks when no longed used at all
+ *
+ * this frees all ncomps but param comp previously copied because needed
+ * for delay annotation
+ */
+static void free_ncablks(void)
+{
+ register struct ncablk_t *ncabp, *ncabp2;
+
+ /* free all ncomp ablks since ncomp form now gone */
+ for (ncabp = __hdr_ncablks; ncabp != NULL;)
+  {
+   ncabp2 = ncabp->ncablknxt;
+   __my_free((char *) ncabp->ancmps, BIG_ALLOC_SIZE);
+   __my_free((char *) ncabp, sizeof(struct ncablk_t));
+   ncabp = ncabp2;
+  }
+}
+
+/*
+ * emit any unused inform
+ * notice this is called just before change to non comp representation
+ */
+static void emit_varunused_informs(struct net_t *np, struct task_t *tskp)
+{
+ struct ncomp_t *ncmp;
+ int32 infnum;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[RECLEN];
+
+ ncmp = np->nu.ct;
+ if (ncmp->n_onrhs && ncmp->n_onlhs) return;
+
+ if (tskp != NULL)
+  {
+   switch ((byte) tskp->tsktyp) {
+    case Begin: strcpy(s2, "in begin block"); break;
+    case FORK: strcpy(s2, "in fork block"); break;
+    case FUNCTION: strcpy(s2, "in function"); break;
+    case TASK: strcpy(s2, "in task"); break;
+    default: __case_terr(__FILE__, __LINE__);   
+   }
+   sprintf(s1, "%s %s in %s", s2, tskp->tsksyp->synam,
+    __inst_mod->msym->synam);
+  }
+ else sprintf(s1, "in module %s", __inst_mod->msym->synam);
+ 
+ if (np->n_isarr) strcpy(s2, "array"); else __to_wtnam(s2, np);
+
+ if (np->ntyp == N_EVENT)
+  {
+   if (!ncmp->n_onrhs && !ncmp->n_onlhs)
+    { strcpy(s3, "unused"); infnum = 436; }
+   else if (!ncmp->n_onrhs && ncmp->n_onlhs)
+    { strcpy(s3, "caused but used in no event control"); infnum = 437; }
+   else { strcpy(s3, "used in event control but not caused"); infnum = 438; }
+  }
+ else
+  {
+   if (!ncmp->n_onrhs && !ncmp->n_onlhs) { strcpy(s3, "unused");
+    infnum = 436; }
+   else if (!ncmp->n_onrhs && ncmp->n_onlhs)
+    { strcpy(s3, "set but not accessed"); infnum = 437; }
+   else { strcpy(s3, "accessed but not set"); infnum = 438; }
+  } 
+
+ /* if completely unreferenced normal inform */
+ if (np->iotyp == NON_IO || infnum == 436)
+  {
+   __gfinform(infnum, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+    "%s: %s %s %s", s1, s2, np->nsym->synam, s3);
+  } 
+ else
+  {
+   if (infnum == 437) infnum = 467;
+   else if (infnum == 438) infnum = 468;
+   else __case_terr(__FILE__, __LINE__);
+
+   __gfinform(infnum, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+    "%s: %s %s %s %s", s1, __to_ptnam(s4, np->iotyp), s2, np->nsym->synam,
+    s3);
+  }
+}
+
+/*
+ * change auxiliary nx from compile to run time (numbers) form
+ * only for wires (and regs)
+ *
+ * notice this is place nwid set
+ * also after here ncomps gone
+ */
+static void rt_change_rngrep(struct net_t *np)
+{
+ register int32 bi;
+ int32 nni1, nni2, nai1, nai2, bits;
+ struct ncomp_t *ncmp;
+ struct rngarr_t *rap;
+ struct rngdwir_t *rdwp;
+ struct gate_t gwrk;
+ struct rngwir_t *rwp;
+
+ /* in XL parameters can be regs at run time */
+ /* not legal in standard so must catch before here */
+ /* DBG remove --- */
+ if (np->n_isaparam || np->nrngrep != NX_CT)
+  __arg_terr(__FILE__, __LINE__);
+ /* -- */
+
+ ncmp = np->nu.ct;
+
+
+ /* know this is number since range */
+ if (np->n_isavec)
+  {
+   nni1 = (int32) __contab[ncmp->nx1->ru.xvi];
+   nni2 = (int32) __contab[ncmp->nx2->ru.xvi];
+
+   if (nni1 == -1 || nni2 == -2) __arg_terr(__FILE__, __LINE__);
+   np->nwid = ((nni1 >= nni2) ? (nni1 - nni2 + 1) : (nni2 - nni1 + 1));
+   /* need to handle options that set default splitting state */
+   switch (ncmp->n_spltstate) {
+    case SPLT_DFLT:
+     np->vec_scalared = (__no_expand) ? FALSE : TRUE;
+     break;
+    case SPLT_SCAL: np->vec_scalared = TRUE; break;
+    case SPLT_VECT: np->vec_scalared = FALSE; break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+  }
+ /* scalar wire has vec scalared off since 1 bit treated as entity */
+ else { np->vec_scalared = FALSE; np->nwid = 1; nni1 = nni2 = 0; }
+
+ /* registers and arrays always vectored (non split into bits) */  
+ if (np->ntyp >= NONWIRE_ST) np->vec_scalared = FALSE;
+ else
+  {
+   if (np->n_stren && np->n_isavec && !np->vec_scalared)
+    {
+     __gferr(982, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+      "non scalar strength wire %s cannot be vectored", np->nsym->synam);
+    }
+  }
+
+ if (np->n_isarr)
+  {
+   nai1 = (int32) __contab[ncmp->ax1->ru.xvi];
+   nai2 = (int32) __contab[ncmp->ax2->ru.xvi];
+
+   rap = (struct rngarr_t *) __my_malloc(sizeof(struct rngarr_t));
+   rap->ni1 = nni1;
+   rap->ni2 = nni2;
+   rap->ai1 = nai1;
+   rap->ai2 = nai2;
+   np->nu.rngarr = rap;
+   np->nrngrep = NX_ARR;
+  }
+ else if (ncmp->n_dels_u.pdels != NULL || np->n_isapthdst)
+  {
+   /* path dest. can not have delays */
+   /* if has delay and path dest., turn off dst. to cause later error */
+   if (ncmp->n_dels_u.pdels != NULL)
+    { if (np->n_isapthdst) np->n_isapthdst = FALSE; }
+
+   rdwp = (struct rngdwir_t *) __my_malloc(sizeof(struct rngdwir_t));
+   rdwp->ni1 = nni1;
+   rdwp->ni2 = nni2;
+
+   if (!np->n_isapthdst)
+    {
+     /* add any defparams (or spec but impossible) to param np list */
+     add_netdel_pnp(np, np->nu.ct->n_dels_u.pdels);
+     /* preprocess wire delays into indexable array or value */
+     __prep_delay(&gwrk, np->nu.ct->n_dels_u.pdels, FALSE,
+      (np->ntyp == N_TRIREG), "path delay", TRUE, np->nsym, FALSE); 
+
+     if (__nd_neg_del_warn)
+      {
+       __gferr(971, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+        "wire %s delay negative (0 used)", np->nsym->synam);
+       __nd_neg_del_warn = FALSE;
+      } 
+
+     rdwp->n_delrep = gwrk.g_delrep;
+     /* is union assign portable */
+     rdwp->n_du = gwrk.g_du;
+    }
+   /* this is allocated and filled later */
+   else { rdwp->n_delrep = DT_PTHDST; rdwp->n_du.pb_pthdst = NULL; }
+
+   /* must allocate the per bit pending scheduled value */
+   bits = __inst_mod->flatinum*np->nwid;
+   rdwp->wschd_pbtevs = (i_tev_ndx *) __my_malloc(bits*sizeof(i_tev_ndx));
+   for (bi = 0; bi < bits; bi++) rdwp->wschd_pbtevs[bi] = -1;
+   np->nu.rngdwir = rdwp;
+   np->nrngrep = NX_DWIR;
+  }
+ else
+  {
+   /* finally any other wire */
+   if (np->n_isavec) 
+    {
+     rwp = (struct rngwir_t *) __my_malloc(sizeof(struct rngwir_t));
+     rwp->ni1 = nni1;
+     rwp->ni2 = nni2;
+     np->nu.rngwir = rwp;
+     np->nrngrep = NX_WIR;
+    }
+   else { np->nu.rngwir = NULL; np->nrngrep = NX_SCALWIR; }
+  }
+ /* just free the expressions since if arg. nil does nothing */
+ __free_xtree(ncmp->nx1);
+ __free_xtree(ncmp->nx2);
+ __free_xtree(ncmp->ax1);
+ __free_xtree(ncmp->ax2);
+} 
+
+/*
+ * ROUTINES TO ALLOCATE AND INITIALIZE GATE INTERNAL STATE
+ */
+
+/*
+ * 
+ * build the schedule array and gate state value for each gate
+ * also prepares delays
+ */
+static void bld_gstate(void)
+{
+ register int32 gi;
+ struct mod_t *mdp;
+ struct gate_t *gp;
+
+ /* for each module in design */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   for (gi = 0; gi < mdp->mgnum; gi++)
+    {
+     gp = &(mdp->mgates[gi]);
+
+     /* pull gate (really source) has no state or scheduled events */
+     /* no state for trans */ 
+     if (gp->g_class == GC_PULL || gp->g_class == GC_TRAN) continue;
+
+     /* if output unc. (OPEMPTY), changes are not seen (do not propagate) */
+     if (gp->g_class != GC_TRANIF && gp->gpins[0]->optyp == OPEMPTY)
+      continue;
+
+     if (gp->g_du.pdels == NULL)
+      { gp->g_du.d1v = NULL; gp->g_delrep = DT_NONE; }
+     else
+      {
+       add_gatedel_pnp(gp, gp->g_du.pdels);
+       __prep_delay(gp, gp->g_du.pdels, FALSE, FALSE, "primitive delay",
+        FALSE, gp->gsym, FALSE);
+       if (__nd_neg_del_warn)
+        {
+         __gferr(972, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+          "gate %s delay negative (0 used)", gp->gsym->synam);
+         __nd_neg_del_warn = FALSE;
+        } 
+      }
+     /* remove #0 if special option on - annotation may put back */ 
+     if (__rm_gate_pnd0s)
+      {
+       if (__chk_0del(gp->g_delrep, gp->g_du, mdp) == DBAD_0) 
+        {
+         __num_rem_gate_pnd0s++; 
+         __num_flat_rem_gate_pnd0s += mdp->flatinum;
+         __free_del(gp->g_du, gp->g_delrep, mdp->flatinum);
+         gp->g_du.d1v = NULL;
+         gp->g_delrep = DT_NONE;
+        }
+      }
+     /* only gates have gstate, eval. for conta (can be func. on rhs) */
+     alloc_gstate(gp, mdp->flatinum);
+    }
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * allocate per instance gstate or usate and intialize to x
+ */
+static void alloc_gstate(struct gate_t *gp, int32 insts)
+{
+ register int32 gsi;
+ int32 nbytes;
+
+ /* first allocate and NULL per instantiating module schedule event ptrs */
+ /* only allocate inertial schedule array if has delay (includes #0) */
+ if (gp->g_delrep != DT_NONE)
+  {
+   nbytes = insts*sizeof(i_tev_ndx); 
+   gp->schd_tevs = (i_tev_ndx *) __my_malloc(nbytes);
+   for (gsi = 0; gsi < insts; gsi++) gp->schd_tevs[gsi] = -1;
+  }
+ 
+ /* no state for continuous assign */
+ if (gp->g_class != GC_UDP) __set_init_gstate(gp, insts, TRUE);
+ else __set_init_udpstate(gp, insts, TRUE);
+}
+
+/* SJM 12/16/99 - notices packing only into words does not change this */
+/* mask table for <= 16 bit wide pck elements (1,z,x) - 0 just all 0's */
+/* 0 width impossible and never used for scalar */ 
+/* SJM 07/15/00- only for gates since variables no longer packed */
+word32 __pack_imaskx[17] = {
+ 0L, 0x3L, 0xfL, 0x3fL, 0xffL, 0x03ff, 0x0fffL, 0x3fffL, 0xffffL,
+ 0x3ffffL, 0xfffffL, 0x3fffffL, 0xffffffL, 0x3ffffffL, 0xfffffffL,
+ 0x3fffffffL, ALL1W
+};
+
+/* what is this value of 16 bit should 1 not 8 1's ? */
+word32 __pack_imask1[17] = {
+ 0L, 0x1L, 0x3L, 0x07L, 0x0fL, 0x001fL, 0x003fL, 0x007fL, 0x00ffL,
+ 0x01ffL, 0x03ffL, 0x07ffL, 0x0fffL, 0x1fffL, 0x03fffL, 0x7fffL, 0xffffL
+};
+
+word32 __pack_imaskz[17] = {
+ 0L, 0x2L, 0xcL, 0x38L, 0xf0L, 0x03e0L, 0x0fc0L ,0x3f80L, 0xff00L,
+ 0x3fe00L, 0xffc00L, 0x3ff800L, 0xfff000L, 0x3ffe000L, 0xfffc000L,
+ 0x3fff8000L, 0xffff0000L
+};
+
+/*
+ * set initial state for builtin gate
+ * 
+ * LOOKATME - SJM 12/19/99 maybe should also only pck into word32 here but
+ * wastes lotsof storage for 4 state gates
+ */
+extern void __set_init_gstate(struct gate_t *gp, int32 insts, int32 nd_alloc)
+{
+ register int32 i;
+ register word32 *wp;
+ register hword *hwp;
+ register byte *bp;
+ int32 pnum, wlen;
+ word32 maska;
+
+ switch ((byte) gp->g_class) {
+  case GC_LOGIC:
+   pnum = gp->gpnum;
+   if (pnum > 16)
+    {
+     wlen = wlen_(pnum);
+     if (nd_alloc)
+      gp->gstate.wp = (word32 *) __my_malloc(2*WRDBYTES*insts*wlen);
+     __init_vec_var(gp->gstate.wp, insts, wlen, pnum, ALL1W, ALL1W);
+     break;
+    }
+   /* case 1, fits in 8 bits */
+   maska = __pack_imaskx[pnum];
+   if (pnum <= 4) 
+    {
+     if (nd_alloc) gp->gstate.bp = (byte *) __my_malloc(insts);
+     bp = gp->gstate.bp;
+     for (i = 0; i < insts; i++) bp[i] = (byte) maska;
+    }
+   else if (pnum <= 8)
+    {     
+     if (nd_alloc) gp->gstate.hwp = (hword *) __my_malloc(2*insts);
+     hwp = gp->gstate.hwp;
+     for (i = 0; i < insts; i++) hwp[i] = (hword) maska;
+    }
+   else 
+    {
+     if (nd_alloc) gp->gstate.wp = (word32 *) __my_malloc(WRDBYTES*insts);
+     wp = gp->gstate.wp;
+     for (i = 0; i < insts; i++) wp[i] = maska;
+    }
+   break;
+  case GC_BUFIF:
+   if (nd_alloc) gp->gstate.hwp = (hword *) __my_malloc(2*insts); 
+   /* this starts by driving given strength x (if no expl. <st1:st0>= x) */
+   hwp = gp->gstate.hwp;
+   for (i = 0; i < insts; i++) hwp[i] = (hword) (0x3f | (gp->g_stval << 6));
+   break;
+  case GC_MOS:
+   if (nd_alloc) gp->gstate.wp = (word32 *) __my_malloc(WRDBYTES*insts);
+   wp = gp->gstate.wp;
+   /* pattern here in highz in, control x, and high z out */
+   for (i = 0; i < insts; i++) wp[i] = 0x00020302L;
+   break;
+  case GC_CMOS:
+   if (nd_alloc) gp->gstate.wp = (word32 *) __my_malloc(WRDBYTES*insts);
+   /* pattern here in highz in, controls both x, and high z out */
+   wp = gp->gstate.wp;
+   for (i = 0; i < insts; i++) wp[i] = 0x02030302L;
+   return;
+  case GC_TRANIF:
+   /* tranif states are 2 bit - 1 conducting, 0 no conducting, 3 unknown */
+   /* notice for delay case, schedule in tev */
+   wlen = wlen_(2*insts);
+   if (nd_alloc) gp->gstate.wp = (word32 *) __my_malloc(WRDBYTES*wlen);
+   wp = gp->gstate.wp;
+   /* start with tranif gates in unknown conducting state */
+   for (i = 0; i < wlen; i++) wp[i] = 0xffffffffL;
+   wp[wlen - 1] &= __masktab[ubits_(2*insts)];
+   return;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * set initial state for udp
+ * for udps >6 also need 1 word32 per inst. for current table index value
+ *
+ * notice value is stored as x (3) - but indexing uses 2 for nins > 6
+ * conversions from normal 4 value to 3 value made when indexing
+ *
+ * ustate values are stored as n 2 bit scalars not separate a and b parts
+ * since no need for reduction word32 evaluation operations
+ */
+extern void __set_init_udpstate(struct gate_t *gp, int32 insts,
+ int32 nd_alloc)
+{
+ register int32 gsi;
+ register word32 *wp;
+ register hword *hwp;
+ int32 nins;
+ word32 iwval, indval;
+ struct udp_t *udpp;
+
+ udpp = gp->gmsym->el.eudpp;
+ /* notice nins is total number of input pins: (state not included) */
+ nins = udpp->numins;
+ /* assume initial value x - notice inputs plus 1 output no pending  */
+ iwval = __masktab[2*nins + 2];
+ /* initialize to x here - if initial value assign instead of normal eval */ 
+ if (udpp->u_wide)
+  {
+   /* 2 words for each superposition form udp */
+   if (nd_alloc) gp->gstate.wp = (word32 *) __my_malloc(2*WRDBYTES*insts);
+   wp = gp->gstate.wp;
+   for (gsi = 0; gsi < insts; gsi++)
+    {
+     wp[2*gsi] = iwval;
+     indval = cmp_udpind(iwval, udpp->numstates);
+     wp[2*gsi + 1] = indval;
+     /* --- RELEASE remove 
+     if (__debug_flg)
+      __dbg_msg("++ wide udp init (inst %d): w0=%lx, w1=%lx\n",
+       gsi, wp[2*gsi], wp[2*gsi + 1]);
+     --- */
+    }
+  }
+ else
+  {
+   /* also store signature form udp in half word32 - 2 bit udp pointless */
+   if (nd_alloc) gp->gstate.hwp = (hword *) __my_malloc(2*insts);
+   hwp = gp->gstate.hwp;
+   /* -- RELEASE remove
+   if (__debug_flg)
+    __dbg_msg("-- narrow udp init: initial state h=%x\n", (hword) iwval); 
+   -- */
+   for (gsi = 0; gsi < insts; gsi++) hwp[gsi] = (hword) iwval;
+  }
+}
+
+/*
+ * eval input state (including possible previous state) to get table index
+ * for initialization only since normally must use transition to select tab
+ *
+ * assuming here that 30 bit and 2 bit shifts take same time
+ */
+static word32 cmp_udpind(word32 ustate, word32 nstates)
+{
+ register word32 ui;
+
+ word32 ind;
+ word32 ival;
+
+ /* know ustate has proper initialized state */
+ /* notice here need to use state that may have been initialized */ 
+ for (ind = 0, ui = 0; ui < nstates; ui++)
+  {
+   ival = (ustate >> ui) & 3L; 
+   /* input x converted to udp x (2) to index - z is x and left as is */
+   if (ival == 3) ival = 2;
+   ind += ival*__pow3tab[ui];
+  } 
+ return(ind);
+}
+/*
+ * prep conta delays
+ *
+ * SJM 09/28/02 - even for rhs concat PB separated, delay in master
+ */
+static void prep_conta_dels(void)
+{
+ register struct mod_t *mdp;
+ register struct conta_t *cap;
+ int32 cai;
+ struct gate_t gwrk;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   for (cap = &(mdp->mcas[0]), cai = 0; cai < mdp->mcanum; cai++, cap++)
+    {
+     /* 1 bit lhs conta delays like gate delays - 3rd arg determines */
+     if (cap->ca_du.pdels == NULL)
+      { cap->ca_du.d1v = NULL; cap->ca_delrep = DT_NONE; }
+     else
+      {
+       add_contadel_pnp(cap, cap->ca_du.pdels);
+       __prep_delay(&gwrk, cap->ca_du.pdels, FALSE, FALSE,
+        "continuous assignment delay", FALSE, cap->casym, FALSE);
+       if (__nd_neg_del_warn)
+        {
+         __gferr(973, cap->casym->syfnam_ind, cap->casym->sylin_cnt,
+          "continuous assign delay negative (0 used)");
+         __nd_neg_del_warn = FALSE;
+        } 
+       cap->ca_du = gwrk.g_du;
+       cap->ca_delrep = gwrk.g_delrep;
+       /* SJM 09/28/02 - now set ca 4v del during fixup */ 
+      }
+    }
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * ROUTINES TO BUILD PER BIT INPUT PORT ICONN PINS, MOD PORTS, and CONCATS
+ */
+
+/*
+ * bld the separated per bit iconn rhs net pins for one iconn
+ *
+ * notice building one PB for every down mod port bit - if highconn inst
+ * conn wider nothing to change if and mod port wider unc. no value
+ * since pb not used for initialization
+ */
+static void bld_pbsep_input_mpps(void)
+{
+ register int32 pi, bi;
+ register struct mod_t *mdp;
+ int32 ii, pi2, numpins, ptyp;
+ struct mod_t *imdp;
+ struct mod_pin_t *mpp;
+ struct inst_t *ip;
+ struct expr_t *xp, *xp2;
+ struct pbexpr_t *pbexpr;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   /* first process all instances in module */
+   for (ii = 0; ii < mdp->minum; ii++)
+    {
+     ip = &(mdp->minsts[ii]);
+     imdp = ip->imsym->el.emdp;
+     if ((numpins = imdp->mpnum) == 0) continue;
+
+     for (pi = 0; pi < numpins; pi++)
+      {
+       mpp = &(imdp->mpins[pi]);
+       xp = ip->ipins[pi];
+       ptyp = mpp->mptyp;
+       if (ptyp != IO_IN) continue; 
+       /* notice decl lhs always separable but no separate unless hconn cat */
+       if (!rhs_cat_separable(xp)) continue;
+
+       if (ip->pb_ipins_tab == NULL)
+        {
+         ip->pb_ipins_tab = (struct expr_t ***)
+          __my_malloc(numpins*sizeof(struct expr_t **));
+         for (pi2 = 0; pi2 < numpins; pi2++) ip->pb_ipins_tab[pi2] = NULL;
+        }
+       /* all bits filled below */
+       ip->pb_ipins_tab[pi] = (struct expr_t **)
+        __my_malloc(mpp->mpwide*sizeof(struct expr_t *));
+       
+       pbexpr = bld_pb_expr_map(xp, mpp->mpwide);
+       for (bi = 0; bi < mpp->mpwide; bi++)
+        {
+         /* for unc. (lhs wider) builds the constant rhs 0/z */
+         xp2 = bld_1sep_pbit_expr(&(pbexpr[bi]), xp->x_stren);
+         ip->pb_ipins_tab[pi][bi] = xp2;
+        }
+       __my_free((char *) pbexpr, numpins*sizeof(struct pbexpr_t));
+
+       /* T means at least one highconn iconn is per bit concat */
+       mpp->has_scalar_mpps = TRUE;
+      }
+    }
+   __pop_wrkitstk();
+  }
+
+ /* always build separated per bit mpps if any hconn separable concat */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   numpins = mdp->mpnum;
+   for (pi = 0; pi < numpins; pi++)
+    {
+     mpp = &(mdp->mpins[pi]);
+     ptyp = mpp->mptyp;
+     if (ptyp != IO_IN) continue; 
+     if (!mpp->has_scalar_mpps) continue;
+     bld_pb_mpps(mpp);
+    }
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * bld the separated per bit output mod port lhs net pins for one iconn
+ *
+ * this is symmetric case to bld per bit separable mpps and and iconn 
+ * pb ipins tabs for output but here as long as all highconns for port
+ * can be separated into bits will separate if any low conn or high concats
+ *
+ * can only build PB records for output ports if all iconn widths exactly
+ * same as mod port width
+ */
+static void bld_pbsep_output_mpps(void)
+{
+ register int32 pi, bi;
+ register struct mod_t *mdp;
+ int32 ii, pi2, numpins, ptyp;
+ struct mod_t *imdp;
+ struct mod_pin_t *mpp;
+ struct inst_t *ip;
+ struct expr_t *xp, *xp2;
+ struct pbexpr_t *pbexpr;
+
+ if (!output_pb_separable()) return;
+
+ /* first bld per bit ipins tab for output port lhs separable highconns */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   /* process all instances in module */
+   for (ii = 0; ii < mdp->minum; ii++)
+    {
+     ip = &(mdp->minsts[ii]);
+     imdp = ip->imsym->el.emdp;
+     if ((numpins = imdp->mpnum) == 0) continue;
+
+     for (pi = 0; pi < numpins; pi++)
+      {
+       mpp = &(imdp->mpins[pi]);
+       ptyp = mpp->mptyp;
+       if (ptyp != IO_OUT) continue; 
+       if (!mpp->has_scalar_mpps) continue;
+       xp = ip->ipins[pi];
+
+       if (ip->pb_ipins_tab == NULL)
+        {
+         ip->pb_ipins_tab = (struct expr_t ***)
+          __my_malloc(numpins*sizeof(struct expr_t **));
+         for (pi2 = 0; pi2 < numpins; pi2++) ip->pb_ipins_tab[pi2] = NULL;
+        }
+       /* all bits filled below - know lhs iconn and rhs mpp same width */
+       ip->pb_ipins_tab[pi] = (struct expr_t **)
+        __my_malloc(mpp->mpwide*sizeof(struct expr_t *));
+       
+       pbexpr = bld_pb_expr_map(xp, mpp->mpwide);
+       for (bi = 0; bi < mpp->mpwide; bi++)
+        {
+         xp2 = bld_1sep_pbit_expr(&(pbexpr[bi]), xp->x_stren);
+         ip->pb_ipins_tab[pi][bi] = xp2;
+        }
+       __my_free((char *) pbexpr, numpins*sizeof(struct pbexpr_t));
+      }
+    }
+   __pop_wrkitstk();
+  }
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   numpins = mdp->mpnum;
+   for (pi = 0; pi < numpins; pi++)
+    {
+     mpp = &(mdp->mpins[pi]);
+     ptyp = mpp->mptyp;
+     if (ptyp != IO_IN) continue; 
+     if (!mpp->has_scalar_mpps) continue;
+     bld_pb_mpps(mpp);
+    }
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * mark each mod output port that can be and gains from separate into PB form
+ * return T if some ports can be separated into PB form
+ * 
+ * separable only if more than half total highconn inst connections separble
+ * and concats not too narrow only counted
+ */
+static int32 output_pb_separable(void)
+{
+ register int32 pi, ii;
+ register struct mod_t *mdp;
+ register struct mod_pin_t *mpp;
+ int32 numpins, nels, num_cat_insts, not_pbsep, some_pbsep;
+ struct itree_t *down_itp;
+ struct expr_t *up_lhsx;
+
+ /* first go through and make sure all high conns can be separated into pb */ 
+ some_pbsep = FALSE;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* SJM 11/19/02 - if top level mod, never separable since no highconn */
+   if (mdp->minstnum == 0) continue;
+
+   if ((numpins = mdp->mpnum) == 0) continue;
+   __push_wrkitstk(mdp, 0);
+   for (pi = 0; pi < numpins; pi++)
+    {
+     mpp = &(mdp->mpins[pi]);
+     if (mpp->mptyp != IO_OUT) continue;
+
+
+     /* if down rhs lowconn mod port not separable, can't PB separate any */
+     if (!rhs_modpin_separable(mpp->mpref)) continue;
+   
+     num_cat_insts = 0; 
+     not_pbsep = FALSE;
+     for (ii = 0; ii < mdp->flatinum; ii++) 
+      {
+       down_itp = mdp->moditps[ii];
+       /* LOOKATME - is nil here possible? */
+       up_lhsx = down_itp->itip->ipins[pi];
+       if (up_lhsx->optyp != LCB) continue;
+
+       /* if any width differences, can't separate */
+       /* LOOKATME - is this really required? */
+       if (mpp->mpref->szu.xclen != up_lhsx->szu.xclen)  
+        { not_pbsep = TRUE; break; }
+
+       nels = __cnt_cat_size(up_lhsx);
+       /* only gain from separate if 4 or more els and wider than 4 bits */
+       /* LOOKATME - if many wide per bit maybe not better */
+       if (nels < 4 || up_lhsx->szu.xclen < 4) continue;
+       num_cat_insts++;
+      }
+     if (num_cat_insts/2 < mdp->flatinum) not_pbsep = TRUE;
+     if (!not_pbsep)
+      {
+       some_pbsep = TRUE;
+       mpp->has_scalar_mpps = TRUE;
+      }
+    }
+   __pop_wrkitstk();
+  }
+ return(some_pbsep);
+}
+
+/*
+ * build per bit mpps for simulation 
+ */
+static void bld_pb_mpps(struct mod_pin_t *mpp)
+{
+ register int32 bi;
+ register struct mod_pin_t *mpp2;
+ struct expr_t *xp;
+ struct pbexpr_t *pbexpr;
+
+ xp = mpp->mpref;
+ pbexpr = bld_pb_expr_map(xp, mpp->mpwide);
+ mpp->pbmpps = (struct mod_pin_t *)
+  __my_malloc(mpp->mpwide*sizeof(struct mod_pin_t));
+ for (bi = 0; bi < mpp->mpwide; bi++)
+  {
+   /* fields except for per bit same */
+   mpp->pbmpps[bi] = *mpp;
+   mpp2 = &(mpp->pbmpps[bi]);
+   /* since expr copied for ID/XMR part, stren and other bits set right */
+   xp = bld_1sep_pbit_expr(&(pbexpr[bi]), mpp2->mpref->x_stren);
+   mpp2->mpref = xp;
+   mpp2->mpwide = 1;
+   mpp2->pbmpps = NULL;
+   mpp2->has_scalar_mpps = FALSE;
+  }
+ __my_free((char *) pbexpr, mpp->mpwide*sizeof(struct pbexpr_t));
+}
+
+/*
+ * bld the separated per bit rhs concat - stored in non pb concat 
+ */
+static void bld_pb_contas(void)
+{
+ register int32 bi;
+ register struct mod_t *mdp;
+ int32 cawid, cai;
+ struct conta_t *cap, *pbcap;
+ struct expr_t *lhsx, *xp2, *xp3;
+ struct pbexpr_t *rhs_pbexpr, *lhs_pbexpr;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   for (cap = &(mdp->mcas[0]), cai = 0; cai < mdp->mcanum; cai++, cap++)
+    {
+     /* if not concat expr, should not separate so this returns F */
+     if (!rhs_cat_separable(cap->rhsx)) continue;
+
+     /* SJM 09/28/02 - now always use per bit for rhs concat */
+     /* fi>1 works and may allow per bit driver load and 4v delay works */
+     /* because evaluates all bits of rhs during sim */
+     lhsx = cap->lhsx;
+     cawid = lhsx->szu.xclen;
+     cap->ca_pb_sim = TRUE;
+     cap->pbcau.pbcaps = (struct conta_t *)
+      __my_malloc(cawid*sizeof(struct conta_t));
+     for (bi = 0; bi < cawid; bi++)
+      {
+       cap->pbcau.pbcaps[bi] = *cap;
+       pbcap = &(cap->pbcau.pbcaps[bi]);
+       /* SJM 08/28/02 - sym and delays in mast not per bit */
+       pbcap->casym = NULL;
+       pbcap->ca_du.pdels = NULL;
+       pbcap->ca_pb_sim = FALSE;
+       pbcap->ca_pb_el = TRUE;
+       pbcap->pbcau.mast_cap = cap;
+      }
+
+     rhs_pbexpr = bld_pb_expr_map(cap->rhsx, cawid);
+     lhs_pbexpr = bld_pb_expr_map(lhsx, cawid);
+     for (bi = 0; bi < cawid; bi++)
+      {
+       pbcap = &(cap->pbcau.pbcaps[bi]);
+       /* if lhs too narrow, 0/z determened by whether lhs stren */
+       xp2 = bld_1sep_pbit_expr(&(rhs_pbexpr[bi]), lhsx->x_stren);
+       pbcap->rhsx = xp2;
+
+       xp3 = bld_1sep_pbit_expr(&(lhs_pbexpr[bi]), lhsx->x_stren);
+       pbcap->lhsx = xp3;
+       if (cap->lhsx->x_multfi) pbcap->lhsx->x_multfi = TRUE;
+      }
+     __my_free((char *) rhs_pbexpr, cawid*sizeof(struct pbexpr_t));
+     __my_free((char *) lhs_pbexpr, cawid*sizeof(struct pbexpr_t));
+    }
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * return T if separable into per bit rhs concat 
+ * now called with any expr 
+ *
+ * all elements must be simple
+ * think width self determined exps legal in cats but can't per bit separate
+ */
+static int32 rhs_cat_separable(struct expr_t *rhsx)
+{
+ register struct expr_t *catndp;
+ struct net_t *np;
+
+ if (rhsx->optyp != LCB) return(FALSE);
+ /* if only one element in rhs concat - no optimize */
+ if (rhsx->ru.x->ru.x == NULL) return(FALSE);
+
+ for (catndp = rhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+  {
+   switch (catndp->lu.x->optyp) {
+    case ID: case GLBREF:
+     np = catndp->lu.x->lu.sy->el.enp;
+     if (!np->vec_scalared) return(FALSE);
+     break;
+    case PARTSEL:
+     np = catndp->lu.x->lu.x->lu.sy->el.enp;
+     if (!np->vec_scalared) return(FALSE);
+     break; 
+    case LSB:
+     /* SJM 12/17/02 - old vectored keyword also prevents pb separation */ 
+     np = catndp->lu.x->lu.x->lu.sy->el.enp;
+     if (np->n_isarr || !np->vec_scalared)
+      return(FALSE);
+     break;
+    case NUMBER: 
+     break;
+    default: return(FALSE);
+   }
+  }
+ return(TRUE);
+}
+
+/*
+ * return T if rhs mod pin separable (can be cat or not)
+ */
+static int32 rhs_modpin_separable(struct expr_t *rhsx)
+{
+ struct expr_t *catndp;
+
+ /* 1 bit ports never separable */
+ switch (rhsx->optyp) {
+  case ID: case GLBREF:
+   /* evan regs always separable */
+   break;
+  case PARTSEL:
+   break; 
+  case LSB:
+   /* bsel not separable if array select */
+   if (rhsx->lu.x->lu.sy->el.enp->n_isarr) return(FALSE);
+   break;
+  case NUMBER: 
+   break;
+  case LCB:  
+   for (catndp = rhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    {
+     if (!rhs_modpin_separable(catndp->lu.x)) return(FALSE);
+    }
+  default: return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * decompose expr into per bit expr record 
+ */
+static struct pbexpr_t *bld_pb_expr_map(struct expr_t *xp, int32 xwid)
+{
+ register int32 bi, bi2;
+ register struct expr_t *catndp;
+ int32 nels, xi, xofs, biti, bitj, wi, wlen;
+ word32 av, bv;
+ struct expr_t **xtab, *cur_xp, *idndp;
+ struct pbexpr_t *pbexpr, *pbxp;
+ struct net_t *np;
+
+ /* make sure both rhs and lhs in low to high order tables */
+ /* needed because for concat, first in list is high order part */
+ if (xp->optyp == LCB)
+  {
+   nels = __cnt_cat_size(xp);
+   xtab = (struct expr_t **) __my_malloc(nels*sizeof(struct expr_t *));
+   xi = nels - 1;
+   /* fill expr tab in reverse order */
+   catndp = xp->ru.x;
+   for (; catndp != NULL; catndp = catndp->ru.x, xi--)
+    { xtab[xi] = catndp->lu.x; }
+  }
+ else
+  {
+   xtab = (struct expr_t **) __my_malloc(sizeof(struct expr_t *));
+   xtab[0] = xp;
+   nels = 1;
+  }
+
+ /* size determined by lhs expr */
+ pbexpr = (struct pbexpr_t *) __my_malloc(xwid*sizeof(struct pbexpr_t));
+ for (bi = 0; bi < xwid; bi++) init_pbexpr_el(&(pbexpr[bi]));
+ 
+ /* first fill lhs, then another loop to fill rhs matching */
+ /* process one lhs expr element every time through */
+ for (xofs = 0, xi = 0; xi < nels; xi++)
+  {
+   cur_xp = xtab[xi];
+   pbxp = &(pbexpr[xofs]);
+   /* fill lhs */
+   switch ((byte) cur_xp->optyp) {
+    case GLBREF: case ID:
+     idndp = cur_xp; 
+     np = idndp->lu.sy->el.enp;
+     /* scalar */
+     /* lhs bi is offset in object, -1 is entire object such as out of rng */
+     if (!np->n_isavec)
+      {
+       pbxp = &(pbexpr[xofs]);
+       pbxp->xp = idndp;
+       pbxp->bi = -1;
+       /* SJM 05/25/05 - need gt-eq since must stop at xwid not 1 past */
+       if (++xofs >= xwid) goto done;
+       break;
+      }
+     /* vector */
+     for (bi2 = 0; bi2 < np->nwid; bi2++) 
+      {
+       pbxp = &(pbexpr[xofs]);
+       pbxp->xp = idndp;
+       /* this is offset in expr */
+       pbxp->bi = bi2;
+       if (++xofs >= xwid) goto done;
+      }        
+     break;
+    case LSB:
+     idndp = cur_xp->lu.x; 
+     np = idndp->lu.sy->el.enp;
+     pbxp->xp = cur_xp;
+     /* DBG remove */
+     if (np->n_isarr) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     /* SJM 09/03/02 - IS number legal since scalar decl assigns allow it */  
+     if (cur_xp->ru.x->optyp == ISNUMBER) biti = -2;
+     else biti = __get_const_bselndx(cur_xp);
+     /* LOOKATME - think out of rng for const index not possible */ 
+     if (biti == -1) pbxp->ndx_outofrng = TRUE;
+     /* offset is offset in ID/XMR object */
+     pbxp->bi = biti; 
+     if (++xofs >= xwid) goto done;
+     break;
+    case PARTSEL:
+     idndp = cur_xp->lu.x; 
+     np = idndp->lu.sy->el.enp;
+     /* know part select never IS */
+     biti = __contab[cur_xp->ru.x->lu.x->ru.xvi];
+     bitj = __contab[cur_xp->ru.x->ru.x->ru.xvi];
+     for (bi2 = bitj; bi2 <= biti; bi2++)
+      {
+       pbxp = &(pbexpr[xofs]);
+       pbxp->xp = idndp;
+       /* this is offset in expr */
+       pbxp->bi = bi2;
+       /* this is offset from low end of concat element */
+       if (++xofs >= xwid) goto done;
+      } 
+     break;
+    case NUMBER:
+     /* LOOKATME - could include ISNUMBER here if always has inst context */
+     for (bi = 0; bi < cur_xp->szu.xclen; bi++)
+      {
+       pbxp = &(pbexpr[xofs]);
+       pbxp->xp = cur_xp; 
+       pbxp->rhs_const = TRUE;
+       /* this is offset in expr */
+       pbxp->bi = -1;
+       wlen = wlen_(cur_xp->szu.xclen);
+       wi = get_wofs_(bi);
+       bi2 = get_bofs_(bi);
+       av = (__contab[cur_xp->ru.xvi + wi] >> bi) & 1;
+       bv = (__contab[cur_xp->ru.xvi + wlen + wi] >> bi) & 1;
+       pbxp->aval = av;
+       pbxp->bval = bv;
+       /* SJM 05/25/05 - if out of lhs - remaining rhs unused so ignore */
+       if (++xofs >= xwid) goto done; 
+      } 
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   } 
+  }
+ /* if still more lhs elements - rhs too narrow - this is bit by bit */
+ for (; xofs < xwid; xofs++)
+  {
+   pbxp = &(pbexpr[xofs]);
+   /* for extra lhs, need z assign if stren else 0 assign */
+   pbxp->no_rhs_expr = TRUE;
+   /* LOOKATME - just leaving rhs fields empty for now */
+  }
+
+done:
+ if (xtab != NULL) __my_free((char *) xtab, nels*sizeof(struct expr_t *));
+ return(pbexpr);
+} 
+
+/*
+ * initialize decomposed into per bit expr 1 bit table entry 
+ */
+static void init_pbexpr_el(struct pbexpr_t *pbxp)
+{
+ pbxp->ndx_outofrng = FALSE;
+ pbxp->rhs_const = FALSE;
+ pbxp->no_rhs_expr = FALSE;
+ pbxp->xp = NULL;
+ pbxp->bi = -1;
+ /* initialize to x */
+ pbxp->aval = 1;
+ pbxp->bval = 1;
+}
+
+/*
+ * fill separated per bit assign expr pair table
+ */
+static struct expr_t *bld_1sep_pbit_expr(struct pbexpr_t *pbxp,
+ int32 is_stren)
+{
+ struct expr_t *xp;
+
+ /* some special cases */
+ if (pbxp->ndx_outofrng)
+  {
+   xp = __bld_rng_numxpr(1, 1, 1);
+   xp->ibase = BHEX;
+   return(xp); 
+  }
+ if (pbxp->no_rhs_expr)
+  {
+   if (is_stren)
+    {
+     xp = __bld_rng_numxpr(0, 0, 1);
+     xp->ibase = BDEC;
+    }
+   else
+    {
+     /* SJM 06/27/05 - rhs widening - always widen with 0's */
+     xp = __bld_rng_numxpr(0, 0, 1);
+     xp->ibase = BHEX;
+    }
+   return(xp); 
+  }
+
+ /* lhs bsel or ID/XMR scalar - copy the expr  */ 
+ if (pbxp->xp->optyp == LSB ||
+  ((pbxp->xp->optyp == ID || pbxp->xp->optyp == GLBREF)
+  && !pbxp->xp->lu.sy->el.enp->n_isavec))
+  { xp = __copy_expr(pbxp->xp); }
+ /* rhs number - can never be IS number */
+ else if (pbxp->xp->optyp == NUMBER)
+  {
+   xp = __bld_rng_numxpr(pbxp->aval, pbxp->bval, 1);
+   xp->ibase = BDEC;
+  }
+ /* ID/XMR vector or psel, build bsel expr */
+ else xp = cnvt_to_bsel_expr(pbxp->xp, pbxp->bi);
+ return(xp);
+}
+
+/*
+ * convert id or psel to constant bsel
+ * passed index must be normalized to h:0 form
+ *
+ * LOOKATME - for bsel just copying expression - ignoring various IS
+ * and out of range conditions - could get rid of flags
+ */
+static struct expr_t *cnvt_to_bsel_expr(struct expr_t *xp, int32 i1)
+{
+ int32 ri1, ri2;
+ struct expr_t *new_xp, *new_xp2, *idndp, *selxp;
+ struct net_t *np;
+
+ if (xp->optyp == PARTSEL) idndp = xp->lu.x; else idndp = xp;
+ new_xp = __copy_expr(idndp);
+ np = idndp->lu.sy->el.enp;
+
+ /* root expr of bit select */
+ new_xp2 = __alloc_newxnd();
+ new_xp2->optyp = LSB;
+ new_xp2->szu.xclen = 1;
+ new_xp2->lu.x = new_xp;
+ selxp = __bld_rng_numxpr((word32) i1, 0L, WBITS);
+ selxp->ibase = BDEC;
+ 
+ __getwir_range(np, &ri1, &ri2); 
+ if (ri2 != 0 || ri1 < ri2) selxp->ind_noth0 = TRUE;
+ new_xp2->ru.x = selxp;
+ return(new_xp2);
+}
+
+/*
+ * compute number of elements in concat (passed LSB expr node)
+ */
+extern int32 __cnt_cat_size(struct expr_t *xp)
+{
+ register struct expr_t *catndp;
+ int32 nels;
+
+ for (nels = 0, catndp = xp->ru.x; catndp != NULL; catndp = catndp->ru.x)
+  nels++;
+ return(nels);
+}
+
+/*
+ * ROUTINES TO BUILD SYMETRIC NET PIN LIST
+ */
+
+/*
+ * build the net pin list and gate state and set port expr. storarge ptrs.
+ *
+ * this will automatically include xmr's
+ * net ranges must have been changed from NX_CT
+ * also short circuits expression node id's to point to storage
+ *
+ * know will not see def or spec params since frozed before here
+ * and different code for special param np lists disjoint
+ */
+static void bld_nplist(void)
+{
+ register int32 pi, pbi, cai;
+ register struct mod_pin_t *mpp;
+ int32 ii, gi, ptyp, pnum;
+ struct inst_t *ip;
+ struct mod_t *mdp, *imdp;
+ struct gate_t *gp;
+ struct conta_t *cap, *pb_cap;
+ struct expr_t *xp, *pb_xp;
+ struct tfrec_t *tfrp; 
+ struct tfarg_t *tfap;
+ struct mod_pin_t *pb_mpp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   /* first process all instances in module */
+   for (ii = 0; ii < mdp->minum; ii++)
+    {
+     __cur_npii = ii;
+     ip = &(mdp->minsts[ii]);
+     imdp = ip->imsym->el.emdp;
+     if ((pnum = imdp->mpnum) == 0) continue;
+
+     for (pi = 0; pi < pnum; pi++)
+      {
+       mpp = &(imdp->mpins[pi]);
+       xp = ip->ipins[pi];
+       ptyp = mpp->mptyp;
+
+       __cur_npnum = pi;
+       __cur_pbi = -1;
+       /* inst. input port rhs is driver that propagates down into module */
+       if (ptyp == IO_IN)
+        { 
+         /* SJM 09/18/02 - scalarize if separable concat hconn */
+         if (mpp->has_scalar_mpps && rhs_cat_separable(xp))
+          {
+           /* lhs width is mpp width since input port down assign */
+           for (pbi = 0; pbi < mpp->mpwide; pbi++)
+            {
+             pb_xp = ip->pb_ipins_tab[pi][pbi];
+             __cur_pbi = pbi;
+             bld_rhsexpr_npins(pb_xp, NP_PB_ICONN);
+            }
+          }
+         else bld_rhsexpr_npins(xp, NP_ICONN);
+        }
+
+       /* inst output port lhs is load propagated up from down module */
+       /* whether in load or driver list determines interpretation */
+       else if (ptyp == IO_OUT)
+        {
+         if (mpp->has_scalar_mpps)
+          {
+           for (pbi = 0; pbi < mpp->mpwide; pbi++)
+            {
+             pb_xp = ip->pb_ipins_tab[pi][pbi];
+             __cur_pbi = pbi;
+             bld_lhsexpr_npins(pb_xp, NP_PB_ICONN);
+            }
+          }
+         else bld_lhsexpr_npins(xp, NP_ICONN);
+        }
+       /* SJM 08/23/00 - for empty port IO type unknown and no npins */
+       else if (ptyp == IO_UNKN) ;
+       else
+        {
+         /* SJM - 08/25/00 - now allowing concat inouts */ 
+         /* FIXME - SJM - 08/27/00 - still but when concat on both sides */
+         if (xp->optyp == LCB && mpp->mpref->optyp == LCB)  
+          {
+           __gferr(711, ip->isym->syfnam_ind, ip->isym->sylin_cnt,
+            "instance %s of type %s inout port %s (pos. %d) concatenate on both sides unsupported",
+            ip->isym->synam, ip->imsym->synam, __to_mpnam(__xs, mpp->mpsnam),
+            pi + 1);
+          }
+         else bld_lhsexpr_npins(xp, NP_BIDICONN);
+	}
+      }
+    }
+
+   /* next gates including udps */
+   /* need for rhs select for lhs concat never possible for gates */
+   __cur_pbi = -1;
+   __cur_lhscati1 = __cur_lhscati2 = -1;
+   for (gi = 0; gi < mdp->mgnum; gi++)
+    {
+     gp = &(mdp->mgates[gi]);
+     __cur_npgp = gp;
+     switch ((byte) gp->g_class) {
+      case GC_PULL:
+       /* one gate all drivers can have multiple pins */
+       for (pi = 0; pi < (int32) gp->gpnum; pi++)
+        {
+         xp = gp->gpins[pi];
+         __cur_npnum = pi;
+         bld_lhsexpr_npins(xp, NP_PULL);
+        }
+       continue;
+      /* trans in separate switch channels, drvs needed here for building */
+      /* and to store tran graph edge, but removed from ndrvs */ 
+      case GC_TRAN: 
+       /* SJM 04/26/01 - if both terminals same, no effect - omit from nl */ 
+       if (gp->g_gone) continue;
+
+       /* build for directional tran to first lhs port */
+       /* first driver for forward to port 0 lhs tran */
+bld_tran_ports:
+       __cur_npnum = 0;
+       xp = gp->gpins[0];
+       if (xp->optyp != OPEMPTY) bld_lhsexpr_npins(xp, NP_TRAN);
+       /* then driver for backwards port 1 lhs tran */
+       __cur_npnum = 1;
+       xp = gp->gpins[1];
+       if (xp->optyp != OPEMPTY) bld_lhsexpr_npins(xp, NP_TRAN);
+       continue;
+      case GC_TRANIF:
+       /* SJM 04/26/01 - if both terminals same, no effect - omit from nl */ 
+       if (gp->g_gone) continue;
+
+       /* build rhs load for 3rd port enable input */
+       /* 3rd input port is only a load - never assigned to */
+       __cur_npnum = 2;
+       bld_rhsexpr_npins(gp->gpins[2], NP_TRANIF);
+       goto bld_tran_ports;
+      default:
+       /* if output unc. (OPEMPTY), chges are not seen (do not propagate) */
+       if (gp->gpins[0]->optyp == OPEMPTY) continue;
+       __cur_npnum = 0;
+       bld_lhsexpr_npins(gp->gpins[0], NP_GATE);
+       /* notice pnum is only input pins */
+       for (pi = 1; pi < (int32) gp->gpnum; pi++)
+        {
+         xp = gp->gpins[pi];
+         __cur_npnum = pi;
+         bld_rhsexpr_npins(xp, NP_GATE);
+        }
+     }
+    }
+   __cur_npnum = 0;
+   for (cap = &(mdp->mcas[0]), cai = 0; cai < mdp->mcanum; cai++, cap++)
+    {
+     if (cap->ca_pb_sim)
+      { 
+       /* for rhs cat without 4v delay, simulator as per bit */ 
+       for (pbi = 0; pbi < cap->lhsx->szu.xclen; pbi++)
+        {
+         pb_cap = &(cap->pbcau.pbcaps[pbi]);
+        /* notice for PB cap still need actual cap - will index during sim */
+         __cur_npcap = cap;
+         __cur_pbi = pbi;
+         bld_lhsexpr_npins(pb_cap->lhsx, NP_CONTA);
+         bld_rhsexpr_npins(pb_cap->rhsx, NP_CONTA);
+        }
+      }
+     else
+      {
+       __cur_npcap = cap;
+       __cur_pbi = -1;
+       /* for conta expression determines width */
+       bld_lhsexpr_npins(cap->lhsx, NP_CONTA);
+       bld_rhsexpr_npins(cap->rhsx, NP_CONTA);
+      }
+    }
+
+   /* SJM - 04/30/99 - no longer removing ports but still no npps */
+   /* for top level modules that have ports still - no npps */
+   if (mdp->minstnum == 0) goto nxt_mod;
+
+   /* module ports */
+   pnum = mdp->mpnum;
+   for (pi = 0; pi < pnum; pi++)
+    {
+     mpp = &(mdp->mpins[pi]);
+     xp = mpp->mpref;
+     ptyp = mpp->mptyp;
+     __cur_npmdp = mdp;
+     __cur_npnum = pi;
+     __cur_pbi = -1;
+
+     /* module inputs are lvalues (opposite cells) */
+     if (ptyp == IO_IN)
+      {
+       /* SJM 09/18/02 - scalarize if any concat hconn */
+       /* LOOKATME ??? - what if some high conns not pb seperable concats? */ 
+       /* since only for inputs only drivers here, think for non sep */
+       /* does not hurt to use per bit drivers */
+       if (mpp->has_scalar_mpps)
+        {
+         /* lhs width is mpp width since input port down assign */
+         for (pbi = 0; pbi < mpp->mpwide; pbi++)
+          {
+           pb_mpp = &(mpp->pbmpps[pbi]);
+           pb_xp = pb_mpp->mpref;
+           __cur_pbi = pbi;
+           bld_lhsexpr_npins(pb_xp, NP_PB_MDPRT);
+          }
+        }
+       else bld_lhsexpr_npins(xp, NP_MDPRT);
+      }
+     else if (ptyp == IO_OUT)
+      {
+       if (mpp->has_scalar_mpps)
+        {
+         for (pbi = 0; pbi < mpp->mpwide; pbi++)
+          {
+           pb_mpp = &(mpp->pbmpps[pbi]);
+           pb_xp = pb_mpp->mpref;
+           __cur_pbi = pbi;
+           bld_rhsexpr_npins(pb_xp, NP_PB_MDPRT);
+          }
+        }
+       else bld_rhsexpr_npins(xp, NP_MDPRT);
+      }
+     /* inouts have no loads or drivers since tran channel eval instead */
+     /* but for PLI nlds and ndrvs set but never used for simulation */
+     else if (ptyp == IO_BID)
+      {
+       /* SJM - 08/25/00 - now allowing concat connected inout port defs */ 
+       bld_lhsexpr_npins(xp, NP_BIDMDPRT);
+      }
+     /* SJM 08/23/00 - for empty port IO type unknown and no npins */
+     else if (ptyp == IO_UNKN) ;
+     else __case_terr(__FILE__, __LINE__);
+    }
+nxt_mod:
+   __pop_wrkitstk();
+  }
+
+ /* keeping one module wide tf rec list */
+ __cur_pbi = -1;
+ for (tfrp = __tfrec_hdr; tfrp != NULL; tfrp = tfrp->tfrnxt)
+  { 
+   for (pi = 1; pi < tfrp->tfanump1; pi++)
+    {
+     tfap = &(tfrp->tfargs[pi]);
+     xp = tfap->arg.axp; 
+     if (!xp->tf_isrw) continue;
+
+     /* DBG remove --- */
+     if (tfap->anp == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+
+     if (tfap->anp->ntyp >= NONWIRE_ST) continue; 
+     __cur_nptfrp = tfrp; 
+     __cur_npnum = pi;
+     bld_lhsexpr_npins(xp, NP_TFRWARG);
+    } 
+  } 
+}
+
+/*
+ * build net_pin elements for wire only (lhs) output or inout port
+ * or gate or conta output port
+ * know bit/part select not declared with vectored attribute or prev. error
+ * know concatenates must be exactly 1 level 
+ *
+ * this also sets has delay bit in top level noded if any element has delay
+ */
+static void bld_lhsexpr_npins(struct expr_t *xp, int32 npctyp)
+{
+ __cur_lhscati1 = __cur_lhscati2 = -1;
+ __lhsxpr_has_ndel = FALSE;
+ bld2_lhsexpr_npins(xp, npctyp);
+ if (__lhsxpr_has_ndel) xp->lhsx_ndel = TRUE;
+}
+
+/*
+ * notice lhs xmr's automatically work on lhs no cross module propagation
+ * either assign to wires where gref info used to find storage and propagate
+ * in target inst. or eval. drivers using target inst. where needed
+ * propagation after assignment in cur. itp of destination is wire by wire
+ */
+static void bld2_lhsexpr_npins(struct expr_t *xp, int32 npctyp)
+{
+ int32 biti, bitj;
+ struct expr_t *idndp;
+ struct net_t *np;
+ struct expr_t *catxp;
+ struct gref_t *grp;
+
+ grp = NULL;
+ switch ((byte) xp->optyp) {
+  /* this can happen for unc. */
+  case GLBREF:
+   idndp = xp;
+   np = xp->lu.sy->el.enp;
+   grp = idndp->ru.grp;
+   if (np->nrngrep == NX_DWIR) __lhsxpr_has_ndel = TRUE;
+   __conn_npin(np, -1, -1, TRUE, npctyp, grp, NPCHG_NONE, (char *) NULL);
+   break;
+  case ID:
+   np = xp->lu.sy->el.enp;
+   if (np->nrngrep == NX_DWIR) __lhsxpr_has_ndel = TRUE;
+   /* by here anything that must be scalared has been or error */
+   __conn_npin(np, -1, -1, TRUE, npctyp, grp, NPCHG_NONE, (char *) NULL);
+   break;
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   return;
+  case LSB:
+   idndp = xp->lu.x;
+   np = idndp->lu.sy->el.enp;
+   if (np->nrngrep == NX_DWIR) __lhsxpr_has_ndel = TRUE;
+   /* know will be constant or will not be on decl. lhs */
+   /* DBG remove --- */ 
+   if (!np->vec_scalared) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   if (idndp->optyp == GLBREF) grp = idndp->ru.grp;
+   if (xp->ru.x->optyp == ISNUMBER)
+    {
+     /* SJM 10/12/04 - IS const must be contab ndx since contab realloced */
+     __isform_bi_xvi = xp->ru.x->ru.xvi;
+     __conn_npin(np, -2, 0, TRUE, npctyp, grp, NPCHG_NONE, (char *) NULL);
+    }
+   else
+    {
+     biti = (int32 ) __contab[xp->ru.x->ru.xvi];
+     __conn_npin(np, biti, biti, TRUE, npctyp, grp, NPCHG_NONE,
+      (char *) NULL);
+    }
+   break;
+  case PARTSEL:
+   idndp = xp->lu.x;
+   np = idndp->lu.sy->el.enp;
+
+   /* DBG remove --- */ 
+   if (!np->vec_scalared) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   if (idndp->optyp == GLBREF) grp = idndp->ru.grp;
+
+   /* for path dest. this is on */
+   if (np->nrngrep == NX_DWIR) __lhsxpr_has_ndel = TRUE;
+   /* array stored from 0 to size even though bits go high to 0 */
+   /* never IS form */
+   biti = (int32) (__contab[xp->ru.x->lu.x->ru.xvi]);
+   bitj = (int32) (__contab[xp->ru.x->ru.x->ru.xvi]);
+
+   __conn_npin(np, biti, bitj, TRUE, npctyp, grp, NPCHG_NONE, (char *) NULL);
+   break;
+  case LCB:
+   for (catxp = xp->ru.x; catxp != NULL; catxp = catxp->ru.x)
+    {
+     /* catxp length is distance from high bit to rhs end (0) */
+     __cur_lhscati1 = catxp->szu.xclen - 1;
+     __cur_lhscati2 = __cur_lhscati1 - catxp->lu.x->szu.xclen + 1;
+     bld2_lhsexpr_npins(catxp->lu.x, npctyp);
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * build net_pin elements for rhs reg or wire
+ * these are things that when wire changes (is assigned to) are traced to
+ * propagate change by evaluating rhs these are in
+ *
+ * idea here is too build as normal, then add special itp stuff if needed
+ * for any global needed because when wire changes in target (eval itp),
+ * must propagate cross module to place used
+ */
+static void bld_rhsexpr_npins(struct expr_t *xp, int32 npctyp)
+{
+ int32 biti, bitj;
+ struct net_t *np;
+ struct expr_t *idndp, *selxp;
+ struct gref_t *grp;
+
+ grp = NULL;
+ switch ((byte) xp->optyp) {
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: return;
+  case OPEMPTY:
+   /* could handle `unconndrive by adding some kind of driver here ? */
+   return; 
+  case GLBREF:
+   idndp = xp;
+   np = xp->lu.sy->el.enp;
+   grp = idndp->ru.grp;
+   __conn_npin(np, -1, -1, FALSE, npctyp, grp, NPCHG_NONE, (char *) NULL);
+   break;
+  case ID:
+   np = xp->lu.sy->el.enp;
+   __conn_npin(np, -1, -1, FALSE, npctyp, grp, NPCHG_NONE, (char *) NULL);
+   break;
+  case LSB:
+   idndp = xp->lu.x;
+   np = idndp->lu.sy->el.enp;
+   if (idndp->optyp == GLBREF) grp = idndp->ru.grp;
+   selxp = xp->ru.x;
+   /* for registers or arrays, never split, change must always propagate */
+   /* this means no per array cell tab, if any cell changes, reevaluate */
+   /* if reg (not wire) or vectored and not arr, any chg causes propagation */ 
+   if (!np->vec_scalared && !np->n_isarr)
+    {
+     /* if this constant just does nothing */
+     bld_rhsexpr_npins(selxp, npctyp);
+     __conn_npin(np, -1, -1, FALSE, npctyp, grp, NPCHG_NONE, (char *) NULL);
+    }
+   else if (selxp->optyp == NUMBER)
+    {
+     biti = (int32) (__contab[selxp->ru.xvi]);
+     __conn_npin(np, biti, biti, FALSE, npctyp, grp, NPCHG_NONE,
+      (char *) NULL);
+    }
+   else if (selxp->optyp == ISNUMBER)
+    {
+     /* SJM 10/12/04 - IS const must be contab ndx since contab realloced */
+     __isform_bi_xvi = selxp->ru.xvi;
+     __conn_npin(np, -2, 0, FALSE, npctyp, grp, NPCHG_NONE, (char *) NULL);
+    }
+   else
+    {
+     __conn_npin(np, -1, -1, FALSE, npctyp, grp, NPCHG_NONE, (char *) NULL);
+     bld_rhsexpr_npins(selxp, npctyp);
+    }
+   break;
+  case PARTSEL:
+   idndp = xp->lu.x;
+   np = idndp->lu.sy->el.enp;
+   if (idndp->optyp == GLBREF) grp = idndp->ru.grp;
+   /* for part select of reg - still need to match all bits */
+   /* know here both range will be constants */
+   if (!np->vec_scalared)
+    __conn_npin(np, -1, -1, FALSE, npctyp, grp, NPCHG_NONE, (char *) NULL);
+   else
+    {
+     /* array stored from 0 to size even though bits go high to 0 */
+     selxp = xp->ru.x;
+     /* never IS form */
+     biti = (int32) (__contab[selxp->lu.x->ru.xvi]);
+     bitj = (int32) (__contab[selxp->ru.x->ru.xvi]);
+     __conn_npin(np, biti, bitj, FALSE, npctyp, grp, NPCHG_NONE,
+      (char *) NULL);
+    }
+   break;
+  case FCALL:
+   {
+    register struct expr_t *fax;
+
+    /* if any args of system or user functions change, monitor triggers */
+    for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+     bld_rhsexpr_npins(fax->lu.x, npctyp);
+   }
+   return;
+  case LCB:
+   {
+    register struct expr_t *catxp;
+
+    for (catxp = xp->ru.x; catxp != NULL; catxp = catxp->ru.x)
+     bld_rhsexpr_npins(catxp->lu.x, npctyp);
+   }
+   return;
+  default:
+   if (xp->lu.x != NULL) bld_rhsexpr_npins(xp->lu.x, npctyp);
+   if (xp->ru.x != NULL) bld_rhsexpr_npins(xp->ru.x, npctyp);
+   return;
+ }
+}
+
+/*
+ * scheme for various types of xmr npps
+ *
+ * not xmr (0)          - simple no bits set, no move to ref, no filter
+ * xmr (not root)   (1) - xmrtyp, npu gref, no filter 
+ * any rooted xmr   (2) - xmrtyp/1inst, npu filtitp to ref, npaux npdownitp 
+ */
+
+/*
+ * routine to build 1 net pin connection per static location 
+ *
+ * LOOKATME - here do matching to find identical static tree upward inst_t
+ * path but have static tree so maybe could traverse to not need to match?
+ */
+extern void __conn_npin(struct net_t *np, int32 ni1, int32 ni2, int32 islhs,
+ int32 npctyp, struct gref_t *grp, int32 chgtyp, char *chgp)
+{
+ struct net_pin_t *npp;
+
+ /* case: non xmr */ 
+ if (grp == NULL)
+  {
+   npp = conn2_npin(np, ni1, ni2, islhs, npctyp);
+   if (chgtyp != NPCHG_NONE) set_chgsubfld(npp, chgtyp, chgp);
+   return;
+  }
+ /* case 2: rooted xmr */
+ if (grp->is_rooted)
+  conn_rtxmr_npin(np, ni1, ni2, islhs, npctyp, grp, chgtyp, chgp);
+ /* case 3: non rooted xmr */ 
+ else conn_xmr_npin(np, ni1, ni2, islhs, npctyp, grp, chgtyp, chgp);
+}
+
+/*
+ * connect any rooted xmr net pin
+ *
+ * idea here is that there will be one npp for each module containing
+ * reference the one driver or load (rooted xmr) drivers or is a load
+ * of all instances
+ *
+ * for rooted:
+ *  when wire changes must match npauxp npdownitp inst or not load or driver
+ *  to move from target (wire that changes) to ref. one loc. is npdownitp
+ */
+static void conn_rtxmr_npin(struct net_t *np, int32 ni1, int32 ni2,
+ int32 islhs, int32 npctyp, struct gref_t *grp, int32 chgtyp, char *chgp)
+{
+ register int32 ii;
+ struct net_pin_t *npp; 
+ struct itree_t *targitp;
+
+ targitp = grp->targu.targitp;
+ /* here npp is not instance specific */ 
+ for (ii = 0; ii < grp->gin_mdp->flatinum; ii++)
+  {
+   npp = conn2_npin(np, ni1, ni2, islhs, npctyp);
+   if (chgtyp != NPCHG_NONE) set_chgsubfld(npp, chgtyp, chgp);  
+   if (npp->npaux == NULL) npp->npaux = __alloc_npaux();
+   /* this is place npp referenced from */
+   npp->npaux->npdownitp = (struct itree_t *) grp->gin_mdp->moditps[ii];
+
+   /* for rooted, target (place wire in) must be the one changed wire in */
+   /* itree location - need to filter */
+   npp->npaux->npu.filtitp = targitp;
+
+   npp->np_xmrtyp = XNP_RTXMR;
+   npp->npproctyp = NP_PROC_FILT;
+  }
+}
+
+/*
+ * connect an xmr that is not rooted
+ * for upwards or downwards relative search using normal routines
+ * no filtering since one npp where all refs have different target
+ */
+static void conn_xmr_npin(struct net_t *np, int32 ni1, int32 ni2, int32 islhs,
+ int32 npctyp, struct gref_t *grp, int32 chgtyp, char *chgp)
+{
+ struct net_pin_t *npp;
+
+ npp = conn2_npin(np, ni1, ni2, islhs, npctyp);
+ if (chgtyp != NPCHG_NONE) set_chgsubfld(npp, chgtyp, chgp);  
+ if (npp->npaux == NULL) npp->npaux = __alloc_npaux();
+ /* use gref to move from target (npp on wire/inst) to ref. */
+ npp->npaux->npu.npgrp = grp;
+ if (grp->upwards_rel) npp->np_xmrtyp = XNP_UPXMR;
+ else npp->np_xmrtyp = XNP_DOWNXMR;
+ npp->npproctyp = NP_PROC_GREF;
+}
+
+/*
+ * connect a range of net bits
+ * not for register output or trigger net pin list building
+ * all allocation and connecting of net pins done through here
+ *
+ * the xmr fields must be set by caller if needed
+ */
+static struct net_pin_t *conn2_npin(struct net_t *np, int32 ni1, int32 ni2,
+ int32 islhs, int32 npctyp)
+{
+ struct net_pin_t *npp;
+ 
+ /* if load of vectored vector - always just mark change of entire wire */ 
+ if (!islhs && !np->n_isarr && np->n_isavec && !np->vec_scalared)
+  ni1 = ni2 = -1; 
+
+ npp = __alloc_npin(npctyp, ni1, ni2);
+ /* notice 32 bit dependent since assumes ptr and int32 both 4 bytes */
+ /* also __isform_bi xvi is contab index so can just use it */
+ if (ni1 == -2)
+  npp->npaux->nbi2.xvi = __isform_bi_xvi;
+
+ /* link on front */
+ if (islhs)
+  {
+   if (__cur_lhscati1 != -1)
+    {
+     if (npp->npaux == NULL) npp->npaux = __alloc_npaux();
+     npp->npaux->lcbi1 = __cur_lhscati1;
+     npp->npaux->lcbi2 = __cur_lhscati2;
+    }
+   npp->npnxt = np->ndrvs;
+   np->ndrvs = npp;
+  }
+ else
+  {
+   /* never insert mipd nchg using this routine */
+   /* DBG remove -- */
+   if (npp->npntyp == NP_MIPD_NCHG) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   /* SJM 07/10/01 - MIPD load must always be first on list */
+   /* SJM 07/24/01 - logic was wrong - now if front mipd nchg insert after */
+   if (np->nlds != NULL && np->nlds->npntyp == NP_MIPD_NCHG)
+    { npp->npnxt = np->nlds->npnxt; np->nlds->npnxt = npp; }
+   else { npp->npnxt = np->nlds; np->nlds = npp; }
+  }
+ /* DBG remove ---
+ if (__debug_flg)
+  {
+   struct npaux_t *npauxp;
+
+   __dbg_msg(".. mod %s adding net %s pin type %d to front",
+    __inst_mod->msym->synam, np->nsym->synam, npp->npntyp);
+   if ((npauxp = npp->npaux) != NULL && npauxp->lcbi1 != -1)
+    __dbg_msg("([%d:%d])\n", npauxp->lcbi1, npauxp->lcbi2);
+   else __dbg_msg("\n");
+  }
+ --- */
+ /* just put on front */
+ return(npp);
+}
+
+/*
+ * allocate a net pin element 
+ * net pin form converted to table for all net pins in current module
+ *
+ * notice [i1:i2] are corrected to h:0 form by here
+ * also notice some globals such as obnum (port) must be set before calling
+ */
+extern struct net_pin_t *__alloc_npin(int32 nptyp, int32 i1, int32 i2)
+{
+ struct net_pin_t *npp;
+ struct primtab_t *ptp;
+
+ npp = (struct net_pin_t *) __my_malloc(sizeof(struct net_pin_t));
+ npp->npntyp = (word32) nptyp;
+ npp->npproctyp = NP_PROC_INMOD;
+ /* value explicitly set if needed */
+ npp->chgsubtyp = 0; 
+ 
+ npp->np_xmrtyp = XNP_LOC;
+ npp->pullval = 0;
+ /* assume more common load */
+ npp->obnum = __cur_npnum;
+ npp->pbi = -1;
+ npp->npaux = NULL;
+ switch ((byte) nptyp) {
+  case NP_ICONN: case NP_BIDICONN:
+   npp->elnpp.eii = __cur_npii;
+   break;
+  case NP_PB_ICONN:
+   npp->elnpp.eii = __cur_npii;
+   npp->pbi = __cur_pbi;
+   break;
+  case NP_GATE: case NP_TRAN: case NP_TRANIF:
+   npp->elnpp.egp = __cur_npgp;
+   break;
+  case NP_CONTA:
+   npp->elnpp.ecap = __cur_npcap;
+   npp->pbi = __cur_pbi;
+   break;
+  case NP_MDPRT: case NP_BIDMDPRT:
+   npp->elnpp.emdp = __cur_npmdp;
+   break;
+  case NP_PB_MDPRT:
+   npp->elnpp.emdp = __cur_npmdp;
+   npp->pbi = __cur_pbi;
+   break;
+  /* set later */
+  case NP_TCHG: npp->elnpp.etchgp = NULL; break;
+  case NP_PULL:
+   npp->elnpp.egp = __cur_npgp;
+   ptp = __cur_npgp->gmsym->el.eprimp; 
+   npp->pullval = (ptp->gateid == G_PULLUP) ? 1 : 0; 
+   break;
+  case NP_TFRWARG:
+   npp->elnpp.etfrp = __cur_nptfrp; 
+   npp->obnum = __cur_npnum;
+   break;
+  case NP_VPIPUTV:
+   npp->elnpp.enp = __cur_npnp;
+   /* caller sets to index number of this driver */
+   npp->obnum = 0;
+   break;
+  case NP_MIPD_NCHG: 
+   npp->elnpp.enp = __cur_npnp;
+   npp->obnum = 0;
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ npp->npnxt = NULL;
+
+ if (i1 != -1)
+  {
+   npp->npaux = __alloc_npaux();
+   npp->npaux->nbi1 = i1;
+   npp->npaux->nbi2.i = i2;
+  }
+ return(npp);
+}
+
+/*
+ * allocate and initialize the aux. net pin record
+ */
+extern struct npaux_t *__alloc_npaux(void)
+{
+ struct npaux_t *npauxp;
+
+ npauxp = (struct npaux_t *) __my_malloc(sizeof(struct npaux_t));
+ npauxp->nbi1 = -1;
+ npauxp->nbi2.i = -1;
+ npauxp->npu.npgrp = NULL;
+ npauxp->npdownitp = NULL;
+ npauxp->lcbi1 = npauxp->lcbi2 = -1;
+ return(npauxp);
+}
+
+/*
+ * set change subtype fields for a npp
+ */
+static void set_chgsubfld(struct net_pin_t *npp, int32 chgtyp, char *chgp) 
+{
+ npp->chgsubtyp = chgtyp;
+ switch (chgtyp) {
+  case NPCHG_TCSTART: npp->elnpp.etchgp = (struct tchg_t *) chgp; break;
+  case NPCHG_TCCHK: npp->elnpp.echktchgp = (struct chktchg_t *) chgp; break;
+  case NPCHG_PTHSRC: npp->elnpp.etchgp = (struct tchg_t *) chgp; break;
+  default: __case_terr(__FILE__, __LINE__); 
+ }
+}
+
+/*
+ * ROUTINES TO BUILD DEFPARAM AND SPECPARAM CONTAINING EXPR LIST
+ */
+
+/*
+ * add delay list parameters to param parm nplst for a net
+ */
+static void add_netdel_pnp(struct net_t *np, struct paramlst_t *pdels)
+{
+ register struct paramlst_t *pmp;
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct expr_t *dxp;
+ struct parmnet_pin_t tmpl_pnp;
+
+ init_pnp(&tmpl_pnp);
+ tmpl_pnp.pnptyp = PNP_NETDEL;
+ /* object delay for */ 
+ tmpl_pnp.elpnp.enp = np;
+ /* not copied but moved from previous pdels whose field is overwritten */
+ tmpl_pnp.pnplp = pdels;
+
+ sav_fnam_ind = __sfnam_ind;
+ sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) np->nsym->syfnam_ind;
+ __slin_cnt = np->nsym->sylin_cnt;
+
+ /* only free first one */
+ __nd_parmpnp_free = TRUE;
+ for (pmp = pdels; pmp != NULL; pmp = pmp->pmlnxt)
+  { dxp = pmp->plxndp; addto_parmnplst(dxp, &tmpl_pnp); }
+
+ __sfnam_ind = sav_fnam_ind;
+ __slin_cnt = sav_slin_cnt;
+}
+
+/*
+ * initialize a param net pin elemnt 
+ */
+static void init_pnp(struct parmnet_pin_t *pnp)
+{
+ pnp->pnp_free = FALSE;
+ pnp->elpnp.enp = NULL;
+ pnp->pnplp = NULL;
+ pnp->pnpnxt = NULL;
+}
+
+/*
+ * build a param nplst element from a param in an expression
+ */
+static void addto_parmnplst(struct expr_t *xp,
+ struct parmnet_pin_t *tmplate_pnp)
+{
+ struct net_t *np;
+ struct parmnet_pin_t *pnp;
+
+ if (__isleaf(xp))
+  {
+   if (xp->optyp == GLBREF)
+    {
+     np = xp->lu.sy->el.enp;
+      __sgfinform(457, 
+       "hierarchical parameter %s used in delay expression can not be annotated to",
+       __msgexpr_tostr(__xs, xp));
+     return;
+    }
+   if (xp->optyp != ID || xp->lu.sy->sytyp != SYM_N) return;
+
+   np = xp->lu.sy->el.enp;
+   if (!np->n_isaparam) return;
+
+   pnp = (struct parmnet_pin_t *) __my_malloc(sizeof(struct parmnet_pin_t));   
+   *pnp = *tmplate_pnp; 
+   if (__nd_parmpnp_free)
+    { pnp->pnp_free = TRUE; __nd_parmpnp_free = FALSE; }
+   else pnp->pnp_free = FALSE;
+   /* reverse order, put on front */
+   if (np->nlds == NULL) np->nlds = (struct net_pin_t *) pnp;
+   else
+    {
+     pnp->pnpnxt = (struct parmnet_pin_t *) np->nlds; 
+     np->nlds = (struct net_pin_t *) pnp;
+    }
+   return;
+  }
+ if (xp->lu.x != NULL) addto_parmnplst(xp->lu.x, tmplate_pnp);
+ if (xp->ru.x != NULL) addto_parmnplst(xp->ru.x, tmplate_pnp);
+}
+
+/*
+ * add delay list parameters to param parm nplst for a gate
+ */
+static void add_gatedel_pnp(struct gate_t *gp, struct paramlst_t *pdels)
+{
+ register struct paramlst_t *pmp;
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct expr_t *dxp;
+ struct parmnet_pin_t tmpl_pnp;
+
+ init_pnp(&tmpl_pnp);
+ tmpl_pnp.pnptyp = PNP_GATEDEL;
+ /* object delay for */ 
+ tmpl_pnp.elpnp.egp = gp;
+ /* not copied but moved from previous pdels whose field is overwritten */
+ tmpl_pnp.pnplp = pdels;
+
+ sav_fnam_ind = __sfnam_ind;
+ sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) gp->gsym->syfnam_ind;
+ __slin_cnt = gp->gsym->sylin_cnt;
+
+ /* only free first use - all other uses point to same parm npp */
+ __nd_parmpnp_free = TRUE;
+ for (pmp = pdels; pmp != NULL; pmp = pmp->pmlnxt)
+  { dxp = pmp->plxndp; addto_parmnplst(dxp, &tmpl_pnp); }
+
+ __sfnam_ind = sav_fnam_ind;
+ __slin_cnt = sav_slin_cnt;
+}
+
+/*
+ * add delay list parameters to param parm nplst for a conta
+ */
+static void add_contadel_pnp(struct conta_t *cap, struct paramlst_t *pdels)
+{
+ register struct paramlst_t *pmp;
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct expr_t *dxp;
+ struct parmnet_pin_t tmpl_pnp;
+
+ init_pnp(&tmpl_pnp);
+ tmpl_pnp.pnptyp = PNP_CONTADEL;
+ /* object delay for */ 
+ tmpl_pnp.elpnp.ecap = cap;
+ /* not copied but moved from previous pdels whose field is overwritten */
+ tmpl_pnp.pnplp = pdels;
+
+ sav_fnam_ind = __sfnam_ind;
+ sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) cap->casym->syfnam_ind;
+ __slin_cnt = cap->casym->sylin_cnt;
+
+ /* only free first one */
+ __nd_parmpnp_free = TRUE;
+ for (pmp = pdels; pmp != NULL; pmp = pmp->pmlnxt)
+  { dxp = pmp->plxndp; addto_parmnplst(dxp, &tmpl_pnp); }
+
+ __sfnam_ind = sav_fnam_ind;
+ __slin_cnt = sav_slin_cnt;
+}
+
+/*
+ * add delay list parameters to param parm nplst for a procedural delay ctrl
+ *
+ * know will only be one delay
+ */
+extern void __add_dctldel_pnp(struct st_t *stp)
+{
+ register struct paramlst_t *pmp;
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct delctrl_t *dctp;
+ struct paramlst_t *pdels;
+ struct expr_t *dxp;
+ struct parmnet_pin_t tmpl_pnp;
+
+ init_pnp(&tmpl_pnp);
+ tmpl_pnp.pnptyp = PNP_PROCDCTRL;
+ /* object delay for */ 
+ dctp = stp->st.sdc;
+ tmpl_pnp.elpnp.edctp = dctp;
+ pdels = dctp->dc_du.pdels;
+ /* not copied but moved from previous pdels whose field is overwritten */
+ tmpl_pnp.pnplp = pdels;
+
+ sav_fnam_ind = __sfnam_ind;
+ sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) stp->stfnam_ind;
+ __slin_cnt = stp->stlin_cnt;
+
+ /* only free first one */
+ __nd_parmpnp_free = TRUE;
+ /* DBG remove -- */
+ if (pdels->pmlnxt != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ for (pmp = pdels; pmp != NULL; pmp = pmp->pmlnxt)
+  { dxp = pmp->plxndp; addto_parmnplst(dxp, &tmpl_pnp); }
+
+ __sfnam_ind = sav_fnam_ind;
+ __slin_cnt = sav_slin_cnt;
+}
+
+/*
+ * add delay list parameters to param parm nplst for a timing check
+ *
+ * know will only be one delay
+ */
+extern void __add_tchkdel_pnp(struct tchk_t *tcp, int32 is_1st)
+{
+ register struct paramlst_t *pmp;
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct paramlst_t *pdels;
+ struct expr_t *dxp;
+ struct parmnet_pin_t tmpl_pnp;
+
+ init_pnp(&tmpl_pnp);
+ tmpl_pnp.elpnp.etcp = tcp;
+ if (is_1st)
+  { tmpl_pnp.pnptyp = PNP_TCHKP1; pdels = tcp->tclim_du.pdels; }
+ else { tmpl_pnp.pnptyp = PNP_TCHKP2; pdels = tcp->tclim2_du.pdels; }
+ /* not copied but moved from previous pdels whose field is overwritten */
+ tmpl_pnp.pnplp = pdels;
+
+ sav_fnam_ind = __sfnam_ind;
+ sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) tcp->tcsym->syfnam_ind;
+ __slin_cnt = tcp->tcsym->sylin_cnt;
+
+ /* only free first one */
+ __nd_parmpnp_free = TRUE;
+ /* DBG remove -- */
+ if (pdels->pmlnxt != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ for (pmp = pdels; pmp != NULL; pmp = pmp->pmlnxt)
+  { dxp = pmp->plxndp; addto_parmnplst(dxp, &tmpl_pnp); }
+
+ __sfnam_ind = sav_fnam_ind;
+ __slin_cnt = sav_slin_cnt;
+}
+
+/*
+ * add delay list parameters to param parm nplst for a timing check
+ */
+extern void __add_pathdel_pnp(struct spcpth_t *pthp)
+{
+ register struct paramlst_t *pmp;
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct paramlst_t *pdels;
+ struct expr_t *dxp;
+ struct parmnet_pin_t tmpl_pnp;
+
+ init_pnp(&tmpl_pnp);
+ tmpl_pnp.elpnp.epthp = pthp;
+ tmpl_pnp.pnptyp = PNP_PATHDEL;
+ pdels = pthp->pth_du.pdels;
+ /* not copied but moved from previous pdels whose field is overwritten */
+ tmpl_pnp.pnplp = pdels;
+
+ sav_fnam_ind = __sfnam_ind;
+ sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) pthp->pthsym->syfnam_ind;
+ __slin_cnt = pthp->pthsym->sylin_cnt;
+
+ /* only free first one */
+ __nd_parmpnp_free = TRUE;
+ for (pmp = pdels; pmp != NULL; pmp = pmp->pmlnxt)
+  { dxp = pmp->plxndp; addto_parmnplst(dxp, &tmpl_pnp); }
+
+ __sfnam_ind = sav_fnam_ind;
+ __slin_cnt = sav_slin_cnt;
+}
+
+/*
+ * free all parm net pin in design
+ *
+ * after this is called information required to annotate delays from
+ * params (labels) gone
+ */
+extern void __free_design_pnps(void)
+{
+ register int32 ni;
+ register struct net_t *prmp;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   if (__inst_mod->mprmnum != 0) 
+    {
+     for (ni = 0, prmp = &(__inst_mod->mprms[0]); ni < __inst_mod->mprmnum;
+      ni++, prmp++)
+      {
+       /* DBG remove -- */
+       if (!prmp->n_isaparam) __misc_terr(__FILE__, __LINE__);
+       /* --- */
+        
+       if (prmp->nlds == NULL) continue;
+       free_1parm_pnps(prmp); 
+      }
+    }
+   for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if (tskp->tprmnum == 0) continue;
+     prmp = &(tskp->tsk_prms[0]);
+     for (ni = 0; ni < tskp->tprmnum; ni++, prmp++)
+      {
+       if (!prmp->n_isaparam) continue;
+       if (prmp->nlds == NULL) continue;
+       free_1parm_pnps(prmp); 
+      }
+    }
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * free the pnp parm net list for one parameter
+ *
+ * called after SDF and vpi_ cbEndOfCompile call back since from then
+ * on assign to parameters in delay expressions (by vpi_, SDF annotate done)
+ * has no effect since delays elaborated (or frozen)
+ */
+static void free_1parm_pnps(struct net_t *prmp)
+{
+ register struct parmnet_pin_t *pnp, *pnp2;
+
+ for (pnp = (struct parmnet_pin_t *) prmp->nlds; pnp != NULL;)
+  {
+   pnp2 = pnp->pnpnxt;   
+   if (pnp->pnp_free) __free_dellst(pnp->pnplp);
+   __my_free((char *) pnp, sizeof(struct parmnet_pin_t));
+   pnp = pnp2;
+  }
+}
+
+/*
+ * ROUTINES TO CONVERT KNOWN AT COMPILE TIME NPPS TO TABLE (ARRAY)
+ */
+
+/*
+ * re allocate npp list into indexable table
+ *
+ * only for the in src (non bid/tran npps that are in tran channels
+ * edges so removed) - keep as linked list since during sim will add
+ * and remove - table allows generation of .s that does not change
+ * from malloc differences - MIPD and vpi added npps can't be accessed
+ * by index
+ *
+ * since bid tran npps pointed to by edges, can't realloc to table
+ * but know that all tran channel npps (BID and TRAN) removed so
+ * list can be converted to indexable table but only for in src npps
+ */
+static void realloc_npplist_to_tab(void)  
+{
+ register struct mod_t *mdp;
+ register struct net_t *np;
+ int32 ni;
+ struct task_t *tskp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+    {
+     realloc_1net_npplist(np);
+    }
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       realloc_1net_npplist(np);
+      }
+    }
+  }
+}
+
+/*
+ * realloc npp list into table (only for npps and dces in src) 
+ *
+ * nothing points at dce and the tran channel edges that point to npps
+ * linked out by here
+ *
+ * fields pointed to from npps and dces can just be copied
+ */
+static void realloc_1net_npplist(struct net_t *np)
+{
+ register int32 i;
+ int32 num_dces, num_npps;
+ struct dcevnt_t *dcetab, *dcep, *dcep2;
+ struct net_pin_t *npptab, *npp, *npp2;
+
+ if (np->dcelst != NULL) 
+  {
+   num_dces = cnt_dces(np->dcelst);
+   dcetab = (struct dcevnt_t *) __my_malloc(num_dces*sizeof(struct dcevnt_t)); 
+   for (i = 0, dcep = np->dcelst; i < num_dces; i++)
+    {
+     dcep2 = dcep->dcenxt;
+
+     dcetab[i] = *dcep;
+     if (i > 0) dcetab[i - 1].dcenxt = &(dcetab[i]);
+
+     __my_free((char *) dcep, sizeof(struct dcevnt_t));
+     dcep = dcep2;
+    }
+   /* last one's nil, copied right */ 
+   np->dcelst = dcetab;
+  }
+ if (np->nlds != NULL)
+  {
+   num_npps = cnt_npps(np->nlds);
+   npptab = (struct net_pin_t *)
+    __my_malloc(num_npps*sizeof(struct net_pin_t)); 
+   for (i = 0, npp = np->nlds; i < num_npps; i++)
+    {
+     npp2 = npp->npnxt;
+
+     npptab[i] = *npp;
+     if (i > 0) npptab[i - 1].npnxt = &(npptab[i]);
+
+     __my_free((char *) npp, sizeof(struct net_pin_t));
+     npp = npp2;
+    }
+   /* last one's nil, copied right */ 
+   np->nlds = npptab;
+  }
+ if (np->ndrvs != NULL)
+  {
+   num_npps = cnt_npps(np->ndrvs);
+   npptab = (struct net_pin_t *)
+    __my_malloc(num_npps*sizeof(struct net_pin_t)); 
+   for (i = 0, npp = np->ndrvs; i < num_npps; i++)
+    {
+     npp2 = npp->npnxt;
+
+     npptab[i] = *npp;
+     if (i > 0) npptab[i - 1].npnxt = &(npptab[i]);
+
+     __my_free((char *) npp, sizeof(struct net_pin_t));
+     npp = npp2;
+    }
+   /* last one's nil, copied right */ 
+   np->ndrvs = npptab;
+  }
+}
+
+/*
+ * count number of npps
+ */
+static int32 cnt_npps(struct net_pin_t *npp)
+{
+ int32 num_npps;
+
+ for (num_npps = 0; npp != NULL; npp = npp->npnxt) num_npps++;
+ return(num_npps);
+}
+
+/*
+ * count number of dces
+ */
+static int32 cnt_dces(struct dcevnt_t *dcep)
+{
+ int32 num_dces;
+
+ for (num_dces = 0; dcep != NULL; dcep = dcep->dcenxt) num_dces++;
+ return(num_dces);
+}
+
+/*
+ * ROUTINES TO IMPLEMENT GATE EATER
+ */
+
+/*
+ * remove all gates and nets that are not driver or drive nothing
+ *
+ * if wire connects to I/O port never removed
+ * if instance source or destination of xmr never removed 
+ * 
+ * this uses n_ispthsrc flag since deletable wires never I/O ports
+ * also only I/O ports can be deleted so since I/O ports not deletable
+ * will never see here 
+ * this builds nqc_u (nu2) for keepping track of fan-in/fan-out but always
+ * freed when done
+ */
+static void eat_gates(void)
+{
+ register struct net_t *np;
+ register int32 pi, ni;
+ register struct tfrec_t *tfrp;
+ int32 some_eaten, first_time, wlen;
+ word32 *wp;
+ struct mod_t *mdp;
+ struct tfarg_t *tfap;
+
+ /* first mark all wires in design that are undeletable */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mnnum == 0) continue;
+
+   __push_wrkitstk(mdp, 0);
+   /* this sets n_mark for all nets not candidates for deletion */
+   for (ni = 0, np = &(__inst_mod->mnets[0]); ni < __inst_mod->mnnum;
+    ni++, np++)
+    {
+     np->n_mark = FALSE;
+
+     /* cannot delete i/o ports or arrays and must be wire to delete */
+     /* temporary n_mark indicates not deletable */
+     /* never delete wire in tran channel really has drivers and loads */
+
+     if (np->ntyp >= NONWIRE_ST || np->iotyp != NON_IO || np->ntraux != NULL)
+      { np->n_mark = TRUE; continue; }
+
+     /* if only drivers or loads but has must stay npp's cannot delete */
+     /* cannot delete if xmr or IS form */
+     if (np->ndrvs != NULL && has_muststay_npp(np->ndrvs))
+      { np->n_mark = TRUE; continue; }
+     if (np->nlds != NULL && has_muststay_npp(np->nlds))
+      { np->n_mark = TRUE; continue; }
+    }
+   __pop_wrkitstk();
+  }
+ /* also mark all wires that connect to tf_ args - list is design wide */
+ /* even if only used in rhs connection */
+ for (tfrp = __tfrec_hdr; tfrp != NULL; tfrp = tfrp->tfrnxt)
+  {
+   for (pi = 1; pi < tfrp->tfanump1; pi++)
+    {
+     tfap = &(tfrp->tfargs[pi]);
+     mark_muststay_wires(tfap->arg.axp);
+    }
+  }
+
+ /* next do deleting module by module */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   some_eaten = TRUE;
+   first_time = TRUE;
+   while (some_eaten)
+    {
+     /* notice only deleted cells can allow new net deletions */
+     eat_nets(first_time);
+     first_time = FALSE;
+     eat_cells(&some_eaten);
+    } 
+   /* this module done free any qcval fields */
+   /* if any qc forms, will be rebuilt and used for different purpose */
+   if (__inst_mod->mnnum != 0)
+    {
+     for (ni = 0, np = &(__inst_mod->mnets[0]); ni < __inst_mod->mnnum;
+      ni++, np++)
+      {
+       /* turn mark off */
+       np->n_mark = FALSE;
+       if (np->nu2.wp != NULL)
+        {
+         wlen = 2*wlen_(np->nwid);
+         wp = np->nu2.wp;
+         __my_free((char *) wp, wlen*WRDBYTES);
+         np->nu2.wp = NULL;
+        }
+      }
+    }
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * return T if has some kind of net pin that cannot be deleted
+ * 1) if IS form undeletable 
+ * 2) if net pin is xmr then net it is on cannot be deleted
+ *
+ * also) if has I/O port connection, but should never see here
+ */
+static int32 has_muststay_npp(register struct net_pin_t *npp)
+{
+ struct npaux_t *npauxp;
+
+ for (; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->np_xmrtyp != XNP_LOC) return(TRUE);
+   if ((npauxp = npp->npaux) != NULL && npauxp->nbi1 == -2) return(TRUE); 
+   /* --- DBG remove */
+   if (npp->npntyp == NP_MDPRT || npp->npntyp == NP_PB_MDPRT)
+    __misc_terr(__FILE__, __LINE__);
+  }
+ return(FALSE);
+}
+
+/*
+ * mark wires that must remain uneaten because connect to tf_ arg
+ */
+static void mark_muststay_wires(struct expr_t *xp)
+{
+ struct net_t *np;
+
+ if (__isleaf(xp))
+  {
+   if (xp->optyp == ID || xp->optyp == GLBREF)
+    {
+     np = xp->lu.sy->el.enp;
+     if (np->ntyp < NONWIRE_ST) np->n_mark = TRUE;
+    }
+   return;
+  }
+ if (xp->lu.x != NULL) mark_muststay_wires(xp->lu.x);
+ if (xp->ru.x != NULL) mark_muststay_wires(xp->ru.x);
+}
+
+/*
+ * remove net and npp's for unc. bits 
+ * know only nets marked n_ispthsrc (tmp. flag) 
+ * tri0/tri1 implied driver nets always have fi = 1
+ * 
+ */
+static void eat_nets(int32 first_time)
+{
+ register int32 ni, wi;
+ register struct net_t *np;
+ int32 nfi, nfo, impl_drv, wlen;
+ word32 *wpfi, *wpfo; 
+
+ if (__inst_mod->mnnum == 0) return;
+ if (!first_time) rem_del_npps();
+ for (ni = 0, np = &(__inst_mod->mnets[0]); ni < __inst_mod->mnnum; ni++, np++)
+  {
+   if (np->n_mark || np->n_gone) continue;
+
+   impl_drv = wire_implied_driver(np);
+   /* assume has fi and fan out */
+   nfi = nfo = 1;
+   if (!np->n_isavec)
+    {
+     /* any type of driver including tri0/1 implied prevents deletion */
+     /* wire used in any rhs (i.e. procedural) has loads even if no wire */
+     /* loads that require event propagation */  
+     if (np->nlds == NULL && !np->n_onprocrhs) nfo = 0;
+     if (np->ndrvs == NULL && !impl_drv) nfi = 0; 
+     if (nfo != 0 && nfi != 0) continue;
+
+do_delete:
+     if (nfo == 0 && nfi == 0)
+      __gfinform(447, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+       "net %s in %s disconnected: no drivers, no loads and no procedural connections",
+       np->nsym->synam, __inst_mod->msym->synam);
+     else if (nfi == 0)
+      __gfinform(447, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+       "net %s in %s disconnected: no drivers", np->nsym->synam,
+       __inst_mod->msym->synam);
+     else 
+      __gfinform(447, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+       "net %s in %s disconnected: no loads and no procedural connections",
+       np->nsym->synam, __inst_mod->msym->synam);
+del_done:
+     np->n_gone = TRUE;
+     remove_all_npps(np);
+     __flnets_removable += __inst_mod->flatinum;
+     __nets_removable++;
+     continue; 
+    }
+   /* if vector no loads (or proc rhs conns) or drivers can just delete */
+   if (np->nlds == NULL && !np->n_onprocrhs) nfo = 0;
+   if (np->ndrvs == NULL && !impl_drv) nfi = 0;
+   if (nfi == 0 || nfo == 0)
+    {
+     /* in case last npp removed, mark processed */
+     /* here know non i/o that can be deleted is never path source so use */
+     /* as temporary need to delete this time flag */
+     np->n_isapthsrc = FALSE;
+     goto do_delete; 
+    }
+
+   /* if npp list changed or not yet built, must build */ 
+   if ((wpfi = np->nu2.wp) == NULL || np->n_isapthsrc)
+    {
+     bld1vec_fifo(np);
+     np->n_isapthsrc = FALSE;
+     /* make sure wpfi set from nu2 wp union member */
+     wpfi = (word32 *) np->nu2.wp;
+    }
+
+   /* if at least one driver and used on rhs cannot delete */
+   /* but still need per bit fifo vec since if gate connecting bit */
+   /* has no fi and no fo even though has proc. connection gate del. gate */
+   if (np->ndrvs != NULL && np->n_onprocrhs) goto nxt_net;
+
+   /* must check bit by bit - possible for some bits have fi others fo */  
+   wlen = wlen_(np->nwid);
+   wpfo = &(wpfi[wlen]);
+   for (wi = 0; wi < wlen; wi++)
+    {
+     /* if even 1 bit fi/fo cannot delete net - but maybe still cells */
+     if ((wpfi[wi] & wpfo[wi]) != 0) goto nxt_net;
+    }  
+   __gfinform(447, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+    "net %s disconnected: no procedural connections and no bit has both drivers and loads",
+    np->nsym->synam);
+   goto del_done;
+
+nxt_net:;
+  }
+}
+
+/*
+ * routine to remove all marked (n_isapthsrc is tmp flag)
+ * this routine is called only after eat cells (not first time)
+ * error if at least one not deleted
+ * only called if has nets
+ */
+static void rem_del_npps(void)
+{
+ register int32 ni;
+ register struct net_t *np;
+ register struct net_pin_t *npp;
+ struct net_pin_t *npp2, *last_npp;
+ int32 net_chged;
+
+ for (ni = 0, np = &(__inst_mod->mnets[0]); ni < __inst_mod->mnnum; ni++, np++)
+  {
+   if (np->n_mark || !np->n_isapthsrc || np->n_gone) continue;
+
+   /* first remove net pin elements connected to removed cells */ 
+   for (net_chged = FALSE, last_npp = NULL, npp = np->ndrvs; npp != NULL;)
+    {
+     switch ((byte) npp->npntyp) {
+      case NP_GATE:
+       /* know this is at most 1 wire and net pin element no xmr field */ 
+       if (!npp->elnpp.egp->g_gone) break;
+do_gate_npp_del:
+       if (last_npp == NULL) np->ndrvs = npp->npnxt;
+       else last_npp->npnxt = npp->npnxt;
+       npp2 = npp->npnxt;      
+       __my_free((char *) npp, sizeof(struct net_pin_t));  
+       npp = npp2;
+       net_chged = TRUE;
+       continue;
+      case NP_CONTA:
+       if (npp->elnpp.ecap->ca_gone) goto do_gate_npp_del;
+       break;
+     }
+     last_npp = npp;
+     npp = npp->npnxt; 
+    }
+   for (last_npp = NULL, npp = np->nlds; npp != NULL;)
+    {
+     switch ((byte) npp->npntyp) {
+      case NP_GATE:
+       /* know this is at most 1 wire and net pin element no xmr field */ 
+       if (!npp->elnpp.egp->g_gone) break;
+do_npp_del:
+       if (last_npp == NULL) np->nlds = npp->npnxt;
+       else last_npp->npnxt = npp->npnxt;
+       npp2 = npp->npnxt;      
+       __my_free((char *) npp, sizeof(struct net_pin_t));  
+       npp = npp2;
+       net_chged = TRUE;
+       continue;
+      case NP_CONTA:
+       if (npp->elnpp.ecap->ca_gone) goto do_npp_del;
+       break;
+       /* tf form should only be driver */
+     }
+     last_npp = npp;
+     npp = npp->npnxt; 
+    }
+   /* no net pin list change - do not rebuild the per bit table */
+   if (!net_chged) np->n_isapthsrc = FALSE;
+  }
+}
+
+/* 
+ * when net deleted, remove all npps 
+ */
+static void remove_all_npps(struct net_t *np)
+{
+ register struct net_pin_t *npp;
+ struct net_pin_t *npp2;
+
+ for (npp = np->ndrvs; npp != NULL;)
+  {
+   npp2 = npp->npnxt;      
+   __my_free((char *) npp, sizeof(struct net_pin_t));  
+   npp = npp2;
+  }
+ np->ndrvs = NULL;
+ for (npp = np->nlds; npp != NULL;)
+  {
+   npp2 = npp->npnxt;      
+   __my_free((char *) npp, sizeof(struct net_pin_t));  
+   npp = npp2;
+  }
+ np->nlds = NULL;
+}
+
+/*
+ * build (rebuild) the per bit fi/fo table
+ * sets nfi/nfo to 0 if entire wire unc. and 1 if at least one bit has conn.
+ * for implied driver nets, set to 1 even if no "real" drivers
+ */
+static void bld1vec_fifo(struct net_t *np)
+{
+ int32 *pbfi, *pbfo, *pbtcfo, wlen;
+ word32 *wp;
+
+ /* first try simple case */
+ pbfi = (int32 *) __my_malloc(sizeof(int32)*np->nwid);
+ pbfo = (int32 *) __my_malloc(sizeof(int32)*np->nwid);
+ pbtcfo = (int32 *) __my_malloc(sizeof(int32)*np->nwid);
+ /* inst. number not used here since never remove net iwth IS form */
+ __bld_pb_fifo(np, pbfi, pbfo, pbtcfo, 0);
+ wp = np->nu2.wp;
+ if (wp == NULL)
+  {
+   wlen = 2*wlen_(np->nwid);
+   wp = (word32 *) __my_malloc(wlen*WRDBYTES);
+   memset(wp, 0, wlen*WRDBYTES);
+   np->nu2.wp = wp;
+  }
+ update_vec_fifo(np, wp, pbfi, pbfo, pbtcfo);
+ __my_free((char *) pbfi, sizeof(int32)*np->nwid);
+ __my_free((char *) pbfo, sizeof(int32)*np->nwid);
+ __my_free((char *) pbtcfo, sizeof(int32)*np->nwid);
+}
+
+/*
+ * set per bit fi/fo values in net working fi/fo ares
+ * tri0/tri1 implied driver net has has fi 1
+ * if wire bit drivers timing check then still has driver and must stay
+ */
+static void update_vec_fifo(struct net_t *np, word32 *wpfi, int32 *pbfi, 
+ int32 *pbfo, int32 *pbtcfo)
+{
+ register int32 bi;
+ register int32 wi, biti;
+ int32 wlen, implied_drv;
+ word32 *wpfo;
+
+ wlen = wlen_(np->nwid);
+ wpfo = &(wpfi[wlen]);
+ implied_drv = wire_implied_driver(np);
+ for (bi = 0; bi < np->nwid; bi++)
+  {
+   wi = get_wofs_(bi);
+   biti = get_bofs_(bi);
+   if (pbfi[bi] == 0 && !implied_drv) wpfi[wi] &= ~(1L << biti);
+   else wpfi[wi] |= (1L << biti);
+   /* know 2 bits never cross word32 boundary */
+   if (pbfo[bi] == 0 && pbtcfo[bi] == 0) wpfo[wi] &= ~(1L << biti);
+   else wpfo[wi] |= (1L << biti);
+  }
+}
+
+/*
+ * return T if wire is implied driver type
+ */
+static int32 wire_implied_driver(struct net_t *np) 
+{
+ switch ((byte) np->ntyp) {
+  case N_TRI0: case N_TRI1: case N_TRIREG: case N_SUPPLY0: case N_SUPPLY1:
+   return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*
+ * delete cells (gate and non xmr source/destination module instances
+ * only gate and continuous assignments are removed
+ */
+static void eat_cells(int32 *some_eaten)
+{
+ register int32 i, gi;
+ register struct gate_t *gp;
+ register struct conta_t *cap;
+ int32 cai, out_unconn, ins_unconn;
+
+ /* go through module gates tryng to remove (disconnect) */
+ *some_eaten = FALSE;
+ for (gi = 0; gi < __inst_mod->mgnum; gi++)
+  {
+   gp = &(__inst_mod->mgates[gi]);
+   if (gp->g_gone) continue;
+
+   /* can never delete pullup or pulldown */
+   out_unconn = ins_unconn = FALSE;
+   if (gp->g_class == GC_PULL) continue;
+   /* for trans, in tran channels so do not process here */
+   if (gp->g_class == GC_TRAN || gp->g_class == GC_TRANIF) continue;
+
+   /* if output not gone, see if all inputs gone */
+   if (conn_expr_gone(gp->gpins[0])) out_unconn = TRUE;
+   for (i = 1; i < (int32) gp->gpnum; i++)
+    { if (!conn_expr_gone(gp->gpins[i])) goto try_delete; }
+   ins_unconn = TRUE;
+   /* mark the gate deleted */
+try_delete:
+   if (ins_unconn || out_unconn)
+    {
+     if (ins_unconn && out_unconn)
+      __gfinform(448, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+       "%s gate %s deleteable because all ports unconnected",
+       gp->gmsym->synam, gp->gsym->synam);
+     else if (out_unconn)
+      __gfinform(448, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+       "%s gate %s deleteable because output unconnected",
+       gp->gmsym->synam, gp->gsym->synam);
+     else 
+      __gfinform(448, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+       "%s gate %s deleteable because all inputs unconnected",
+       gp->gmsym->synam, gp->gsym->synam);
+     gp->g_gone = TRUE;
+     /* gate is gone - mark all nets not already deleted for fi-fo re-eval */
+     for (i = 1; i < (int32) gp->gpnum; i++)
+      mark_maybe_gone_nets(gp->gpins[i]);
+     *some_eaten = TRUE;
+     __flgates_removable += __inst_mod->flatinum;
+     __gates_removable++;
+    }
+  }
+ /* no module removable - better to first use some kind of inlining */
+ /* and then remove gates from that if possible */
+
+ /* try to remove (disconnect) continuous assigns */ 
+ /* go through module gates tryng to remove (disconnect) */
+ for (cap = __inst_mod->mcas, cai = 0; cai < __inst_mod->mcanum; cai++, cap++)
+  {
+   if (cap->ca_gone) continue;
+
+   /* can never delete pullup or pulldown */
+   out_unconn = ins_unconn = FALSE;  
+   /* if output not gone, see if all inputs gone */
+   if (conn_expr_gone(cap->lhsx)) out_unconn = TRUE;
+   if (conn_expr_gone(cap->rhsx)) ins_unconn = TRUE;
+   if (ins_unconn || out_unconn)
+    {
+     if (ins_unconn && out_unconn)
+      __gfinform(448, cap->casym->syfnam_ind, cap->casym->sylin_cnt,
+       "continuous assign deleteable because it has no connections");
+     else if (out_unconn)
+      __gfinform(448, cap->casym->syfnam_ind, cap->casym->sylin_cnt,
+       "continuous assign deletable because left hand side drives nothing");
+     else 
+      __gfinform(448, cap->casym->syfnam_ind, cap->casym->sylin_cnt,
+       "continuous assign deletable because right hand side unconnected");
+     cap->ca_gone = TRUE;
+     mark_maybe_gone_nets(cap->lhsx);
+     mark_maybe_gone_nets(cap->rhsx);
+     *some_eaten = TRUE;
+     __flcontas_removable += __inst_mod->flatinum;
+     __contas_removable++;
+    }
+  }
+}
+
+/*
+ * return T if expression is removable (no connectons) 
+ * notice constants cannot be deleted
+ *
+ * also n_mark set for undeletable nets that do not have fi-fo table
+ * know if n_mark off and not already deleted, know fi-fo table exists
+ */
+static int32 conn_expr_gone(struct expr_t *xp)
+{
+ register int32 bi;
+ int32 bi2, nfi, nfo;
+ struct net_t *np;
+ struct expr_t *ndx, *ndx2; 
+
+ switch ((byte) xp->optyp) {
+  case ID:
+   np = xp->lu.sy->el.enp; 
+   if (!np->n_gone) return(FALSE);
+   break;
+  case OPEMPTY: break;
+  case LSB: 
+   np = xp->lu.x->lu.sy->el.enp; 
+   if (!np->n_gone) 
+    {
+     if (np->n_mark) return(FALSE);
+     ndx = xp->ru.x; 
+     if (ndx->optyp == NUMBER)
+      {
+       bi = __comp_ndx(np, ndx);
+       if (bi == -1) return(FALSE);  
+       getbit_fifo(np, bi, &nfi, &nfo);
+       if (nfi == 0 || (nfo == 0 && !np->n_onprocrhs)) break;
+      }
+     return(FALSE);
+    }
+   break;
+  case PARTSEL:
+   np = xp->lu.x->lu.sy->el.enp; 
+   if (!np->n_gone) 
+    {
+     if (np->n_mark) return(FALSE);
+     ndx = xp->ru.x->lu.x;
+     if ((bi = __comp_ndx(np, ndx)) == -1) return(FALSE);
+     ndx2 = xp->ru.x->ru.x;
+     if ((bi2 = __comp_ndx(np, ndx2)) == -1) return(FALSE);
+     for (; bi >= bi2; bi--)
+      {
+       getbit_fifo(np, bi, &nfi, &nfo);
+       if (nfi != 0 && (nfo != 0 || np->n_onprocrhs)) return(FALSE);
+      }
+     /* fall thru, all bits of part select unc. */
+    }
+   break;
+  case LCB:
+   /* for concatenate all components must be gone */
+   for (ndx2 = xp->ru.x; ndx2 != NULL; ndx2 = ndx2->ru.x)
+    { if (!conn_expr_gone(ndx2->lu.x)) return(FALSE); }
+   break;
+  /* anything else (such as function or arithmetic expr. must stay */
+  default: return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * set n_isapthsrc to indicate net can be deleted and must have nlds and
+ * ndrvs updated and maybe removed
+ *
+ * must mark all nets in expr.
+ * notice constants cannot be deleted
+ */
+static void mark_maybe_gone_nets(struct expr_t *xp)
+{
+ struct net_t *np;
+ struct expr_t *ndx2;
+
+ switch ((byte) xp->optyp) {
+  case ID:
+   np = xp->lu.sy->el.enp; 
+   if (!np->n_gone) np->n_isapthsrc = TRUE;
+   break;
+  case OPEMPTY: break;
+  case LSB: case PARTSEL:
+   np = xp->lu.x->lu.sy->el.enp; 
+   if (!np->n_gone) np->n_isapthsrc = TRUE;
+   break;
+  case LCB:
+   /* for concatenate all components must be gone */
+   for (ndx2 = xp->ru.x; ndx2 != NULL; ndx2 = ndx2->ru.x)
+    mark_maybe_gone_nets(ndx2->lu.x);
+   break;
+ }
+}
+
+/*
+ * the the fi and fo for 1 bit
+ */
+static void getbit_fifo(struct net_t *np, int32 bi, int32 *nfi, int32 *nfo)
+{
+ int32 wi, biti, wlen;
+ word32 *wpfi, *wpfo;
+
+ /* must check the bit if constant */
+ wi = get_wofs_(bi);
+ biti = get_bofs_(bi);
+ /* DBG remove */
+ if ((wpfi = (word32 *) np->nu2.wp) == NULL) __misc_terr(__FILE__, __LINE__);
+ wlen = wlen_(np->nwid);
+ wpfo = &(wpfi[wlen]);
+ *nfi = ((wpfi[wi] & (1L << biti)) != 0L) ? 1 : 0;
+ *nfo = ((wpfo[wi] & (1L << biti)) != 0L) ? 1 : 0;
+}
+
+/*
+ * ROUTINES TO DETERMINE IF GATE CAN BE OPTIMIZED (USED ACC ROUTINE)
+ */
+
+/*
+ * return T if gate is acceleratable buf or not
+ * accelerate classes are 0 std non accel., 2 buf/not, 3 acc. logic
+ *
+ * will not accelerate if: 1) >3 inputs, 2) drives strength, 3) 1 in and style 
+ * 4) drives fi>1 wire, 5) output is not scalar or constant bit select,
+ * 6) inputs not accelerable
+ *
+ * notice whether or not has delay does effect acc class
+ */
+extern int32 __get_acc_class(struct gate_t *gp)
+{
+ register int32 gi;
+ int32 acc_class, st_on_input, wire_pthdel;
+ word32 gatid;
+ struct expr_t *xp;
+ struct net_t *np;
+
+ acc_class = ACC_NONE;
+ st_on_input = FALSE;
+ /* can have up to 3 inputs and 1 output for acceleration - fits in byte */
+ if (gp->g_hasst || gp->gpnum > 4) return(ACC_STD);
+ gatid = gp->gmsym->el.eprimp->gateid;
+ switch ((byte) gatid) { 
+  case G_NOT: case G_BUF: case G_ASSIGN: acc_class = ACC_BUFNOT; break; 
+  case G_NAND: case G_BITREDAND: case G_BITREDOR:
+  case G_NOR: case G_BITREDXOR: case G_REDXNOR:
+   /* never accelerate degenerate 2 input gates that are usually >=3 in */
+   if (gp->gpnum == 2) return(ACC_STD);
+   acc_class = ACC_4IGATE;
+   break;
+  default: return(ACC_STD);
+ }  
+ /* only get here for logic gates - mos, tran, etc. always std */
+ /* output must be simple wire or constant bsel from wire */
+ xp = gp->gpins[0];
+ /* cannot be fi>1 and know if in tran channel will be fi>1 */
+ if (xp->x_multfi) return(ACC_STD);
+ if (xp->optyp == ID)
+  {
+   np = xp->lu.sy->el.enp; 
+   if (np->n_isavec || np->n_stren) return(ACC_STD);
+  }
+ else if (xp->optyp == LSB)
+  {
+   if (xp->ru.x->optyp != NUMBER) return(ACC_STD);
+   np = xp->lu.x->lu.sy->el.enp; 
+   if (np->n_stren) return(ACC_STD);
+  }
+ else return(ACC_STD);
+ /* DBG remove */
+ if (np->ntraux != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ if (np->nrngrep == NX_DWIR) wire_pthdel = TRUE; else wire_pthdel = FALSE;
+
+ /* all inputs must be XL accelerateable */
+ for (st_on_input = FALSE, gi = 0; gi < (int32) gp->gpnum; gi++)
+  {
+   xp = gp->gpins[gi];
+   if (xp->optyp == ID)
+    {
+     np = xp->lu.sy->el.enp;
+     if (np->n_isavec) return(ACC_STD);
+     if (np->n_stren) st_on_input = TRUE; 
+    }
+   /* strength on bit select ok, slower does not need separate case */
+   else if (xp->optyp == LSB)
+    {
+     if (xp->ru.x->optyp != NUMBER) return(ACC_STD);
+     /* SJM 05/17/03 - array (memory) selects on input must not accelerate */
+     if (xp->lu.x->lu.sy->el.enp->n_isarr) return(ACC_STD);
+    }
+   else return(ACC_STD);
+  }
+ if (st_on_input)
+  {
+   if (acc_class == ACC_BUFNOT) acc_class = ACC_STIBUFNOT;
+   else if (acc_class == ACC_4IGATE) acc_class = ACC_ST4IGATE;
+  }
+ gp->g_pdst = wire_pthdel;
+ return(acc_class);
+}
+
+/*
+ * ROUTINES TO CONVERT FROM DT_NONE TO #0 FOR DELAY ANNOTATION
+ */
+
+/*
+ * add delay (set to #0) to gate
+ *
+ * know called after prep
+ */
+extern int32 __add_gate_pnd0del(struct gate_t *gp, struct mod_t *mdp,
+ char *sdfmsg)
+{
+ register int32 gsi;
+ int32 nbytes;
+ struct net_t *np;
+ struct primtab_t *ptp;
+ struct expr_t *xp;
+
+ ptp = gp->gmsym->el.eprimp;
+ /* make sure gate can have delay */
+ if (ptp->gateid == G_TRAN || ptp->gateid == G_RTRAN)
+  {
+   /* rnotice error here will stop simulation */
+   if (sdfmsg != NULL)
+    __pv_ferr(1199, 
+     "%s delay annotate to %s gate %s for which delay illegal", sdfmsg,
+     gp->gmsym->synam, gp->gsym->synam);
+   else __vpi_err(1893, vpiError,
+    "vpi_put_delays illegal for %s gate %s for which delay illegal",
+    gp->gmsym->synam, gp->gsym->synam);
+   return(FALSE);
+  }
+ /* set delay to pnd 0 */
+ gp->g_du.d1v = (word64 *) __my_malloc(sizeof(word64));
+ gp->g_du.d1v[0] = 0ULL;
+ gp->g_delrep = DT_1V;
+
+ /* allocate and initialize the inertial pending schd event table */
+ nbytes = mdp->flatinum*sizeof(i_tev_ndx); 
+ gp->schd_tevs = (i_tev_ndx *) __my_malloc(nbytes);
+ for (gsi = 0; gsi < mdp->flatinum; gsi++) gp->schd_tevs[gsi] = -1;
+
+ /* if accelerated set g resist if driven wire has delay or path dest */
+ if (__gate_is_acc(gp))
+  {
+   xp = gp->gpins[0];
+   if (xp->optyp == ID) np = xp->lu.sy->el.enp; 
+   else if (xp->optyp == LSB) np = xp->lu.x->lu.sy->el.enp; 
+   else { np = NULL;  __case_terr(__FILE__, __LINE__); }
+   if (np->nrngrep == NX_DWIR) gp->g_pdst = TRUE; 
+  }
+ return(TRUE);
+}
+
+/*
+ * add conta delay (add drivers and internal conta value too) (set to #0)
+ *
+ * know called after prep and know no delay 
+ * SJM 09/29/02 - if per bit this must set master delay and PB drv/schd
+ */
+extern int32 __add_conta_pnd0del(struct conta_t *cap, struct mod_t *mdp,
+ char *sdfmsg)
+{
+ register int32 i, bi;
+ struct conta_t *pbcap;
+
+ /* make sure gate can have delay */
+ if (cap->lhsx->getpatlhs)
+  {
+   /* rnotice error here will stop simulation */
+   __bld_lineloc(__xs, cap->casym->syfnam_ind, cap->casym->sylin_cnt);
+   if (sdfmsg != NULL)
+    __pv_ferr(1379, 
+     "%s delay annotate to $getpattern continuous assign at %s illegal",
+     sdfmsg, __xs);
+   else __vpi_err(1905, vpiError,
+     "vpi_put_delays illegal for $getpattern continuous assign at %s", __xs);
+   return(FALSE);
+  }
+ 
+ if (!cap->ca_pb_sim)
+  {
+   /* since before any sim or new PLI added del, initialized value correct */
+   if (!cap->lhsx->x_multfi)
+    {
+     /* DBG remove --- */
+     if (cap->ca_drv_wp.wp != NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     __allocinit_perival(&(cap->ca_drv_wp), mdp->flatinum,
+      cap->lhsx->szu.xclen, TRUE);
+    }
+   /* DBG remove --- */
+   if (cap->schd_drv_wp.wp != NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* nothing will be scheduled and this will not be allocated */
+   __allocinit_perival(&(cap->schd_drv_wp), mdp->flatinum,
+   cap->lhsx->szu.xclen, TRUE);
+   cap->caschd_tevs = (i_tev_ndx *)
+    __my_malloc(mdp->flatinum*sizeof(i_tev_ndx));
+   for (i = 0; i < mdp->flatinum; i++) cap->caschd_tevs[i] = -1;
+  }
+ else
+  {
+   for (bi = 0; bi < cap->lhsx->szu.xclen; bi++)
+    {
+     pbcap = &(cap->pbcau.pbcaps[bi]);
+     /* DBG remove */
+     if (pbcap->lhsx->szu.xclen != 1) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+
+     /* since before any sim or new PLI added del, init value correct */
+     /* SJM 09/28/02 - if master cat expr fi>1, need all per bits */
+     if (!cap->lhsx->x_multfi)
+      {
+       /* DBG remove --- */
+       if (pbcap->ca_drv_wp.wp != NULL) __misc_terr(__FILE__, __LINE__);
+       /* --- */
+       __allocinit_perival(&(pbcap->ca_drv_wp), mdp->flatinum, 1, TRUE);
+      }
+     /* DBG remove --- */
+     if (pbcap->schd_drv_wp.wp != NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     /* nothing will be scheduled and this will not be allocated */
+     __allocinit_perival(&(pbcap->schd_drv_wp), mdp->flatinum, 1, TRUE);
+     pbcap->caschd_tevs = (i_tev_ndx *)
+      __my_malloc(mdp->flatinum*sizeof(i_tev_ndx));
+     for (i = 0; i < mdp->flatinum; i++) pbcap->caschd_tevs[i] = -1;
+    } 
+  }
+
+ /* SJM 09/28/02 - delay always in master never per bit */
+ /* set delay to pnd 0 */
+ cap->ca_du.d1v = (word64 *) __my_malloc(sizeof(word64));
+ cap->ca_du.d1v[0] = 0ULL;
+ cap->ca_delrep = DT_1V;
+
+ return(TRUE);
+}
+
+/*
+ * ROUTINES TO REMOVE ALL 0 DELAY PATHS
+ */
+
+/*
+ * remove 0 path delays
+ *
+ * all this does is link out npp - rest of d.s. small and interlinked
+ * only remove source tchg npps if not part of other non removed path
+ *
+ * FIXME - for now not removing source changes - set ref. count but not using
+ * will do extra work in recording each path source change but no path 
+ * processing because destinations not path dests any more
+ */
+extern void __rem_0path_dels(void)
+{
+ register int32 pi;
+ register struct net_pin_t *npp;
+ struct spcpth_t *pthp; 
+ int32 has_0del, dbi, dbi2, ni;
+ int32 num_pthrem_mods, num_pthrems, num_flat_pthrems;
+ int32 num_pthrem_nets, num_flat_pthrem_nets;
+ struct mod_t *mdp;
+ struct pathel_t *spep, *dpep;
+ struct npaux_t *npauxp;
+ struct net_t *snp, *dnp;
+ struct pthdst_t *pdp, *pdp2, *last_pdp; 
+ struct rngdwir_t *dwirp; 
+ struct expr_t *lhsx;
+
+ num_pthrem_mods =  num_pthrems = num_flat_pthrems = 0;
+ num_pthrem_nets = num_flat_pthrem_nets = 0;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mspfy == NULL || mdp->mspfy->spcpths == NULL) continue;
+
+   /* know each delay is NUMBER or REALNUM */ 
+   has_0del = FALSE;
+   for (pthp = mdp->mspfy->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+    {
+     if (pthp->pth_gone) continue;
+
+     if (__chk_0del(pthp->pth_delrep, pthp->pth_du, mdp) == DBAD_0) 
+      {
+       pthp->pth_0del_rem = TRUE;
+       num_pthrem_mods++;
+       has_0del = TRUE;
+      } 
+    }
+   if (!has_0del) continue;
+
+   /* know at least one path must be removed */
+   /* step 1: set all path src ref counts - >1 dests for one src possible */
+   for (pthp = mdp->mspfy->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+    {
+     /* think impossible for some paths to be gone and make it to prep */   
+     if (pthp->pth_gone) continue;
+
+     for (pi = 0; pi <= pthp->last_pein; pi++)
+      {
+       spep = &(pthp->peins[pi]);
+       snp = spep->penp;
+       for (npp = snp->nlds; npp != NULL; npp = npp->npnxt) 
+        {
+         if (npp->npntyp != NP_TCHG || npp->chgsubtyp != NPCHG_PTHSRC)
+          continue;
+         /* know tchg sources always per bit - for scalar 0 */
+
+         /* path source npp's always one bit, -1 only if scalar */
+         if ((npauxp = npp->npaux) != NULL) dbi = npauxp->nbi1;
+         else dbi = -1;
+         if (spep->pthi1 == -1 || (dbi <= spep->pthi1 && dbi >= spep->pthi2)) 
+          {
+           /* inc ref. count - know value previously inited to 0 */
+           (npp->elnpp.etchgp->lastchg[0])++; 
+          }
+        }
+      }
+    } 
+   /* step 2: actually remove path dst npp's and decr. pstchg source counts */
+   for (pthp = mdp->mspfy->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+    {
+     if (!pthp->pth_0del_rem) continue;
+     
+     num_pthrems++;
+     num_flat_pthrems += mdp->flatinum;
+  
+     for (pi = 0; pi <= pthp->last_peout; pi++)
+      {
+       dpep = &(pthp->peouts[pi]);
+       dnp = dpep->penp;
+  
+       for (npp = dnp->nlds; npp != NULL; npp = npp->npnxt) 
+        {
+         if (npp->npntyp != NP_TCHG || npp->chgsubtyp != NPCHG_PTHSRC)
+          continue;
+         if (!dnp->n_isavec) dbi = dbi2 = 0; 
+         else
+          {
+           if (dpep->pthi1 == -1) { dbi = dnp->nwid - 1; dbi2 = 0; }  
+           else { dbi = dpep->pthi1; dbi2 = dpep->pthi2; }
+          }
+  
+         /* for every bit of destination path element */
+         dwirp = dnp->nu.rngdwir;
+         for (; dbi >= dbi2; dbi--)
+          {
+           last_pdp = NULL;
+           for (pdp = dwirp->n_du.pb_pthdst[dbi]; pdp != NULL;)
+            {
+             pdp2 = pdp->pdnxt;
+             if (pdp->pstchgp->chgu.chgpthp == pthp)
+              {
+               if (last_pdp == NULL) dwirp->n_du.pb_pthdst[dbi] = pdp->pdnxt; 
+               else last_pdp->pdnxt = pdp->pdnxt;
+               __my_free((char *) pdp, sizeof(struct pthdst_t)); 
+              }
+             else last_pdp = pdp;
+             pdp = pdp2; 
+            }
+          }
+        }
+      }
+    }
+
+   /* for path dest. nets with all pthdst removed - set as non path dest. */
+   for (ni = 0, dnp = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, dnp++) 
+    {
+     if (!dnp->n_isapthdst) continue;
+
+     dwirp = dnp->nu.rngdwir;
+     if (!dnp->n_isavec)
+      {
+       if (dwirp->n_du.pb_pthdst[0] != NULL) continue;
+      }
+     else
+      {
+       for (dbi = dnp->nwid - 1; dbi >= 0; dbi--)
+        {
+         if (dwirp->n_du.pb_pthdst[dbi] != NULL) continue;
+        }
+      } 
+     /* convert to non path dest. */
+     __my_free((char *) dwirp->n_du.pb_pthdst,
+      dnp->nwid*sizeof(struct pthdst_t *));
+     dwirp->n_du.d1v = NULL;
+     dwirp->n_delrep = DT_NONE;
+     dnp->n_isapthdst = FALSE;
+     num_pthrem_nets++;
+     num_flat_pthrem_nets += mdp->flatinum;
+     /* SJM 07/23/03 - must turn off all lhsx ndel marks for completely */
+     /* removed paths where driver is gate out or conta */
+     for (npp = dnp->ndrvs; npp != NULL; npp = npp->npnxt) 
+      {
+       if (npp->npntyp == NP_GATE) lhsx = npp->elnpp.egp->gpins[0];
+       else if (npp->npntyp == NP_CONTA) lhsx = npp->elnpp.ecap->lhsx; 
+       else continue;
+  
+       /* DBG remove */
+       if (!lhsx->lhsx_ndel) __misc_terr(__FILE__, __LINE__);
+       /* -- */
+       if (lhsx->lhsx_ndel) lhsx->lhsx_ndel = FALSE;
+      }
+    }
+
+   /* step 3: reset lastchg field and remove if needed - no longer ref cnt */
+   for (pthp = mdp->mspfy->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+    {
+     if (pthp->pth_gone) continue;
+
+     for (pi = 0; pi <= pthp->last_pein; pi++)
+      {
+       spep = &(pthp->peins[pi]);
+       snp = spep->penp;
+       for (npp = snp->nlds; npp != NULL; npp = npp->npnxt) 
+        {
+         if (npp->npntyp != NP_TCHG || npp->chgsubtyp != NPCHG_PTHSRC)
+          continue;
+         /* path source npp's always one bit, -1 only if scalar */
+         if ((npauxp = npp->npaux) != NULL) dbi = npauxp->nbi1;
+         else dbi = -1;
+         if (spep->pthi1 == -1 || (dbi <= spep->pthi1 && dbi >= spep->pthi2)) 
+          {
+           /* reset ref. count */
+           npp->elnpp.etchgp->lastchg[0] = 0ULL; 
+          }
+        }
+      }
+    } 
+  }
+ if (num_pthrem_mods != 0 && __verbose) 
+  {
+   __cv_msg(
+    "  %d zero delay paths (%d flat) in %d types removed - no effect.\n",
+    num_pthrems, num_flat_pthrems, num_pthrem_mods);
+  }
+ if (num_pthrem_nets != 0 && __verbose)
+  {
+   __cv_msg(
+    "  %d nets (%d flat) no longer path destinations (all paths zero delay).\n",
+    num_pthrem_nets, num_flat_pthrem_nets);
+  }
+}
diff --git a/src/v_prp2.c b/src/v_prp2.c
new file mode 100644
index 0000000..8539ed5
--- /dev/null
+++ b/src/v_prp2.c
@@ -0,0 +1,7206 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * Verilog simulation preparation routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+/* --- SJM REMOVED static void setchk_trchan_wire(struct net_t *); */
+static void setchk_1w_fifo(struct net_t *);
+static int32 cnt_scalar_fo(struct net_t *);
+static int32 has_npp_isform(register struct net_pin_t *);
+static void chkset_vec_fifo(struct net_t *, int32 *, int32 *, int32, int32,
+ int32);
+static int32 has_rng_npp(struct net_t *);
+static struct itree_t *cnvt_to_itp(struct mod_t *, int32);
+static struct itree_t *cnvt_todown_itp(struct itree_t *, struct mod_t *,
+ int32);
+static void chk_trifctrl_insame_chan(struct gate_t *, struct expr_t *);
+static void chk_samechan_trifctrl_simple(struct mod_t *, struct gate_t *,
+ int32, struct expr_t *, struct expr_t *);
+static int32 net_in_expr(struct expr_t *, struct net_t *);
+static void prep_tf_rwexprs(void);
+static int32 lhs_has_figt1(struct expr_t *);
+static void getpat_lhs_figt1(struct mod_t *, struct expr_t *,
+struct conta_t *);
+static void chk_decl_siderep(struct expr_t *, struct expr_t *, char *,
+int32, word32, int32);
+static int32 find_var_in_xpr(struct expr_t *, struct net_t *, int32 *);
+static void add_portbit_map(struct tenp_t *, struct expr_t *, int32);
+static void cmp_nchgbtabsize(void);
+static void set_1net_srep(struct net_t *);
+static void cmp_tabsizes(void);
+static void cmpadd_1var_storsiz(struct net_t *);
+static void alloc_var(struct net_t *);
+static void alloc_real_var(struct net_t *, int32);
+static void alloc_scal_var(struct net_t *, int32);
+static void alloc_sscal_var(struct net_t *, int32);
+static void alloc_svec_var(struct net_t *, int32);
+static void reinit_1wirereg(struct net_t *, struct mod_t *);
+static void alloc_dce_prevval(struct dcevnt_t *, struct mod_t *);
+static void init_dce_exprval(struct dcevnt_t *);
+static void init_dce_prevval(struct dcevnt_t *, struct mod_t *);
+static void prep_stskcalls(struct st_t *);
+static struct st_t *add_loopend_goto(struct st_t *, struct st_t *);
+static void push_prpstmt(struct st_t *);
+static void pop_prpstmt(void);
+static void prep_case(struct st_t *);
+static void prep_dctrl(struct st_t *);
+static void cnv_cmpdctl_todu(struct st_t *, struct delctrl_t *);
+static void prep_event_dctrl(struct delctrl_t *);
+static void bld_ev_dces(struct expr_t *, struct delctrl_t *);
+static void bld_evxpr_dces(struct expr_t *, struct delctrl_t *, int32);
+static void linkon_dce(struct net_t *, int32, int32, struct delctrl_t *,
+ int32, struct gref_t *);
+static void init_iact_dce(struct dcevnt_t *, struct delctrl_t *,
+ struct gref_t *);
+static void xmr_linkon_dce(struct net_t *, int32, int32, struct delctrl_t *,
+ int32, struct gref_t *);
+static struct dcevnt_t *linkon2_dce(struct net_t *, int32, int32,
+ struct delctrl_t *, int32, int32, struct mod_t *, struct mod_t *);
+static void prep_func_dsable(struct st_t *);
+static void bld_init_qcaf_dce_lstlst(struct st_t *);
+static void prep_qc_assign(struct st_t *, int32);
+static void prep_qc_deassign(struct st_t *);
+static struct dceauxlst_t *prep_noncat_qc_assign(struct st_t *,
+ struct expr_t *);
+static struct dceauxlst_t *prep_noncat_qc_regforce(struct st_t *,
+ struct expr_t *);
+static void init_qcval(struct qcval_t *);
+static void prep_qc_wireforce(struct st_t *);
+static void prep_qc_wirerelease(struct st_t *);
+static void prep_noncat_qc_wireforce(struct st_t *, struct expr_t *,
+ struct dceauxlstlst_t *);
+static void prep_noncat_qc_wirerelease(struct expr_t *);
+static void bld_qcaf_dces(struct expr_t *, struct qcval_t *);
+static void linkon_qcaf_dce(struct net_t *, int32, int32, struct gref_t *,
+ struct qcval_t *);
+static void process_upwards_grp(struct gref_t *);
+static void chk_downrel_inst_sels(struct gref_t *);
+static void prep_tchks(void);
+static struct tchg_t *bld_start_tchk_npp(struct tchk_t *, struct net_t *,
+ int32);
+static struct chktchg_t *bld_check_tchk_npp(struct net_t *, int32);
+static byte *bld_npp_oldval(struct net_t *, struct mod_t *);
+static void reinit_npp_oldval(byte *, struct net_t *, struct mod_t *);
+static void prep_pths(void);
+static int32 chk_pthels(struct spcpth_t *);
+static int32 bldchk_pb_pthdsts(struct spcpth_t *);
+static struct tchg_t *try_add_npp_dpthsrc(struct spcpth_t *, struct net_t *,
+ int32);
+static struct net_pin_t *find_1timchg_psnpp(struct net_t *, int32, int32);
+static int32 bldchk_1bit_pthdst(struct spcpth_t *, struct net_t *, int32,
+ struct net_t *, int32, int32, struct tchg_t *);
+static void get_pthbitwidths(struct spcpth_t *, int32 *, int32 *);
+static char *bld_bitref(char *, struct net_t *, int32);
+static int32 chk_biti_pthdst_driver(struct spcpth_t *, struct net_t *, int32);
+static void emit_pthdst_bit_informs(struct mod_t *);
+static void free_dctrl(struct delctrl_t *, int32);
+static void free_csitemlst(register struct csitem_t *);
+
+/* extern prototypes defined elsewhere */
+extern void __setchk_all_fifo(void);
+extern void __bld_pb_fifo(struct net_t *, int32 *, int32 *, int32 *, int32);
+extern void __prep_exprs_and_ports(void);
+extern void __alloc_tfdrv_wp(struct tfarg_t *, struct expr_t *,
+ struct mod_t *);
+extern void __init_tfdrv(struct tfarg_t *, struct expr_t *, struct mod_t *);
+extern void __prep_contas(void);
+extern void __allocinit_perival(union pck_u *, int32, int32, int32);
+extern void __allocinit_stperival(union pck_u *, int32, struct net_t *,
+ int32);
+extern void __alloc_nchgaction_storage(void);
+extern void __alloc_sim_storage(void);
+extern void __allocinit_arr_var(struct net_t *, int32, int32);
+extern void __init_vec_var(register word32 *, int32, int32, int32, word32,
+ word32);
+extern int32 __get_initval(struct net_t *, int32 *);
+extern void __allocinit_vec_var(struct net_t *, int32, int32);
+extern void __reinitialize_vars(struct mod_t *);
+extern void __initialize_dces(struct mod_t *);
+extern void __prep_stmts(void);
+extern struct st_t *__prep_lstofsts(struct st_t *, int32, int32);
+extern void __push_nbstk(struct st_t *);
+extern void __pop_nbstk(void);
+extern void __dce_turn_chg_store_on(struct mod_t *, struct dcevnt_t *, int32);  
+extern struct dcevnt_t *__alloc_dcevnt(struct net_t *);
+extern int32 __is_upward_dsable_syp(struct sy_t *, struct symtab_t *,
+ int32 *);
+extern void __prep_xmrs(void);
+extern void __fill_grp_targu_fld(struct gref_t *);
+extern void __prep_specify(void);
+extern void __xtract_wirng(struct expr_t *, struct net_t **, int32 *,
+ int32 *);
+extern void __free_1stmt(struct st_t *);
+extern void __free_xprlst(struct exprlst_t *);
+
+extern void __my_free(char *, int32);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_tsktyp(char *, word32);
+extern char *__my_malloc(int32);
+extern struct st_t *__alloc2_stmt(int32, int32, int32);
+extern void __getwir_range(struct net_t *, int32 *, int32 *);
+extern void __set_gchg_func(struct gate_t *);
+extern int32 __isleaf(struct expr_t *);
+extern struct net_t *__find_tran_conn_np(struct expr_t *);
+extern int32 __get_pcku_chars(int32, int32);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __st_perinst_val(union pck_u, int32, register word32 *,
+ register word32 *);
+extern char *__to_idnam(struct expr_t *);
+extern int32 __get_arrwide(struct net_t *);
+extern void __reinit_regwir_putvrec(struct net_t *, int32);
+extern void __reinit_netdrvr_putvrec(struct net_t *, struct mod_t *);
+extern void __init_1net_dces(struct net_t *, struct mod_t *);
+extern void __alloc_1instdce_prevval(struct dcevnt_t *);
+extern void __init_1instdce_prevval(struct dcevnt_t *);
+extern int32 __get_dcewid(struct dcevnt_t *, struct net_t *);
+extern void __ld_wire_sect(word32 *, word32 *, struct net_t *, register int32,
+ register int32);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern char *__to_sttyp(char *, word32);
+extern char *__bld_lineloc(char *, word32, int32);
+extern void __add_dctldel_pnp(struct st_t *);
+extern void __prep_delay(struct gate_t *, struct paramlst_t *, int32, int32,
+ char *, int32, struct sy_t *, int32);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern int32 __ip_indsrch(char *);
+extern struct itree_t *__find_unrt_targitp(struct gref_t *,
+ register struct itree_t *, int32);
+extern void __add_tchkdel_pnp(struct tchk_t *, int32);
+extern void __conn_npin(struct net_t *, int32, int32, int32, int32,
+ struct gref_t *, int32, char *);
+extern void __add_pathdel_pnp(struct spcpth_t *);
+extern char *__to_deltypnam(char *, word32);
+extern void __free_xtree(struct expr_t *);
+extern void __free_del(union del_u, word32, int32);
+extern int32 __chk_0del(word32, union del_u, struct mod_t *);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern void __dmp_exprtab(struct mod_t *, int32);
+extern void __dmp_msttab(struct mod_t *, int32);
+extern void __dmp_stmt(FILE *, struct st_t *, int32);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern char *__xregab_tostr(char *, word32 *, word32 *, int32,
+ struct expr_t *);
+extern char *__to_opname(word32);
+extern struct expr_t *__sim_copy_expr(struct expr_t *);
+extern struct expr_t *__copy_expr(struct expr_t *);
+extern struct mod_t *__get_mast_mdp(struct mod_t *);
+extern struct net_t *__tranx_to_netbit(register struct expr_t *, int32,
+ int32 *, struct itree_t *oside_itp);
+extern struct mipd_t *__get_mipd_from_port(struct mod_pin_t *, int32);
+extern struct tenp_t *__bld_portbit_netbit_map(struct mod_pin_t *);
+extern struct net_pin_t *__alloc_npin(int32, int32, int32);
+extern void __alloc_qcval(struct net_t *);
+extern void __get_qc_wirrng(struct expr_t *, struct net_t **, int32 *,
+ int32 *, struct itree_t **);
+extern void __prep_insrc_monit(struct st_t *, int32);
+extern int32 __cnt_dcelstels(register struct dcevnt_t *);
+extern void __dcelst_off(struct dceauxlst_t *);
+
+extern void __gfwarn(int32, word32, int32, char *, ...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __gfinform(int32, word32, int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __misc_sgfterr(char *, int32);
+extern void __misc_gfterr(char *, int32, word32, int32);
+extern void __sgfterr(int32, char *, ...);
+extern void __my_fprintf(FILE *, char *, ...);
+extern void __free_stlst(register struct st_t *);
+static void cmp_xform_delay(int32, union del_u);
+static void cmp_xform_ports(void);
+static void cmp_xform_ialst(void);
+static struct st_t *cmp_xform_lstofsts(register struct st_t *);
+static struct st_t *cmp_xform1_stmt(register struct st_t *, struct st_t *);
+static void xform_tf_syst_enable(struct st_t *);
+static struct expr_t *mv1_expr_totab(struct expr_t *);
+static void xform_tf_sysf_call(struct expr_t *);
+static void cmp_xform_csitemlst(register struct csitem_t *);
+static void cxf_fixup_loopend_goto(struct st_t *, struct st_t *);
+static void cxf_fixup_lstofsts_gotos(struct st_t *, int32);
+static void cxf_fixup_case_gotos(struct st_t *);
+static void cxf_fixup_func_dsabl_gotos(struct st_t *);
+static void cmp_xform_inst_conns(void);
+static void cmp_xform_gates(void);
+static void cmp_xform_contas(void);
+static void cmp_xform_tasks(void);
+static void cmp_xform_specify(void);
+static char *bld_opname(char *, struct expr_t *);
+
+extern word32 __masktab[];
+
+int32 __prep_numsts;
+
+/*
+ * FAN OUT AND PORT COLLAPSING ROUTINES
+ */
+
+/*
+ * set and check all wire fi and fo
+ * here must ignore any added for unc. bid. wires
+ * cannot check fifo for wires in tran channels 
+ *
+ * LOOKATME - maybe allocate different formats depending on fi/fo
+ * to keep lists short 
+ * 
+ * SJM - 06/25/00 - difference from 2018c since change chg state algorithm
+ */
+extern void __setchk_all_fifo(void)
+{
+ register int32 ni;
+ register struct net_t *np;
+ struct mod_t *mdp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mnnum == 0) continue;
+
+   __push_wrkitstk(mdp, 0);
+   for (ni = 0, np = &(__inst_mod->mnets[0]); ni < __inst_mod->mnnum;
+    ni++, np++)
+    {
+     /* --- SJM 11/20/01 - removed since useless and slow 
+     if (np->ntraux != NULL) { setchk_trchan_wire(np); continue; }
+     --- */
+     if (np->ntyp >= NONWIRE_ST) continue;
+     setchk_1w_fifo(np);
+    }
+   __pop_wrkitstk();
+  }
+} 
+
+/*
+ * check for tran channels with some bits in and some not
+ * for non tran channel wires (no edges) remove vibp
+ * notice all tran connected nets have fi>1 set 
+ */
+/* --- SJM 11/20/01 - removed since warning useless and this takes too
+      long to make freeing rare small amount of memory worth it 
+ 
+static void setchk_trchan_wire(struct net_t *np) 
+{
+ register int32 bi, ii;
+ struct traux_t *trap;
+ struct itree_t *itp;
+ struct vbinfo_t *vbip;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ trap = np->ntraux;
+ for (bi = 0; bi < np->nwid; bi++)
+  {
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    {
+     vbip = trap->vbitchans[ii*np->nwid + bi];
+     if (vbip != NULL) 
+      {
+       if (vbip->vivxp->vedges != NULL) continue;
+       __my_free((char *) vbip, sizeof(struct vbinfo_t));
+       trap->vbitchans[ii*np->nwid + bi] = NULL; 
+      } 
+     -* SJM 01/26/99 - new connect modules not in tran channels *- 
+     if ((itp = cnvt_to_itp(__inst_mod, ii)) == NULL) continue;
+
+     sprintf(s1, "in %s(%s):", __inst_mod->msym->synam,
+      __msg2_blditree(__xs, itp));
+     if (np->n_isavec) sprintf(s3, "%s[%d]", np->nsym->synam, bi);
+     else strcpy(s3, np->nsym->synam); 
+     __gfinform(450, np->nsym->syfnam_ind, np->nsym->sylin_cnt, 
+      "%s %s %s not in any transistor channel but other bits are",
+       s1, __to_wtnam(s2, np), s3);
+    }
+  }
+}
+--- */
+
+/*
+ * set and check for 1 wire
+ * but no warns or informs
+ *
+ * sets n_multfi bit, but not set for tran channel's which need fi>1 eval
+ * because instead x_multfi is set, n_multfi used for other checking
+ */
+static void setchk_1w_fifo(struct net_t *np)
+{
+ register int32 ii;
+ int32 scalfo, nd_fi_chk;
+ int32 *pbfi, *pbfo, *pbtcfo;
+ char s1[RECLEN];
+ 
+ /* no matter what tri0/tri1 and supply0/supply1 must be multi-fi */
+ switch ((byte) np->ntyp) {
+  case N_TRI0: case N_TRI1: case N_TRIREG: case N_SUPPLY0: case N_SUPPLY1:
+   np->n_multfi = TRUE;
+ }
+
+ /* special case 1: pullup - must be constant - no fi */
+ nd_fi_chk = TRUE;
+ /* special case 1: supply should not have fan-in - no effect */
+ if (np->ntyp == N_SUPPLY0 || np->ntyp == N_SUPPLY1)
+  {
+   if (np->ndrvs != NULL)
+    {
+     __gfwarn(607, np->nsym->syfnam_ind, np->nsym->sylin_cnt, 
+      "in %s: %s %s has driver(s) that have no effect",
+      __inst_mod->msym->synam, __to_wtnam(s1, np), np->nsym->synam);
+    }
+   /* pwr/gnd should not have drivers */
+   nd_fi_chk = FALSE;
+  }
+ /* case 2: scalar */
+ if (!np->n_isavec)
+  {
+   if (nd_fi_chk)
+    {
+     if (np->ndrvs == NULL)
+      {
+       if (np->nsym->sy_impldecl) 
+        __gfinform(420, np->nsym->syfnam_ind, np->nsym->sylin_cnt, 
+         "in %s: implicitly declared scalar wire %s has no drivers",
+         __inst_mod->msym->synam, np->nsym->synam);
+       else __gfinform(427, np->nsym->syfnam_ind, np->nsym->sylin_cnt, 
+        "in %s: scalar wire %s has no drivers", __inst_mod->msym->synam,
+        np->nsym->synam);
+      } 
+     else if (np->ndrvs->npnxt != NULL) np->n_multfi = TRUE;
+    }
+   /* scalar case multi fo set */  
+   scalfo = cnt_scalar_fo(np);
+   if (scalfo == 0)
+    {
+     if (np->nsym->sy_impldecl) 
+      __gfinform(429, np->nsym->syfnam_ind, np->nsym->sylin_cnt, 
+      "in %s: implicitly declared scalar wire %s drives no declarative fan-out",
+       __inst_mod->msym->synam, np->nsym->synam);
+     else __gfinform(426, np->nsym->syfnam_ind, np->nsym->sylin_cnt, 
+      "in %s: scalar wire %s drives no declarative fan-out",
+      __inst_mod->msym->synam, np->nsym->synam);
+    }
+   return;
+  }
+ /* case 4: wire that is not scalar */
+ pbfi = (int32 *) __my_malloc(sizeof(int32)*np->nwid);
+ pbfo = (int32 *) __my_malloc(sizeof(int32)*np->nwid);
+ pbtcfo = (int32 *) __my_malloc(sizeof(int32)*np->nwid);
+ if (!has_npp_isform(np->ndrvs))
+  {
+   /* notice not using t chg counts for now */
+   __bld_pb_fifo(np, pbfi, pbfo, pbtcfo, 0);
+   chkset_vec_fifo(np, pbfi, pbfo, 0, FALSE, nd_fi_chk);
+  }
+ else
+  {
+   /* tricky has IS form case - must do for every inst */
+   /* if any inst. has fi > 1, then wire must be all multi fan in */
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    chkset_vec_fifo(np, pbfi, pbfo, ii, TRUE, nd_fi_chk);
+  }
+  /* notice task/func/lb variables always regs - never fi > 1 */
+  /* done free the tables */
+ __my_free((char *) pbfi, sizeof(int32)*np->nwid);
+ __my_free((char *) pbfo, sizeof(int32)*np->nwid);
+ __my_free((char *) pbtcfo, sizeof(int32)*np->nwid);
+}
+
+/*
+ * return number of non TCHG fan out for scalar
+ * MIPD never seen here - only added by PLI or SDF after elaboration
+ */
+static int32 cnt_scalar_fo(struct net_t *np)
+{
+ register struct net_pin_t *npp;
+ int32 nfi;
+
+ for (nfi = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->npntyp != NP_TCHG) nfi++; 
+  }
+ return(nfi);
+}
+
+/*
+ * return T if has IS (-2) form net pin list entry  
+ */
+static int32 has_npp_isform(register struct net_pin_t *npp)
+{
+ struct npaux_t *npauxp;
+
+ for (; npp != NULL; npp = npp->npnxt)
+  { if ((npauxp = npp->npaux) != NULL && npauxp->nbi1 == -2) return(TRUE); }
+ return(FALSE);
+}
+
+/*
+ * build per bit fi and fo tables - caller must pass wide enough tables
+ */
+extern void __bld_pb_fifo(struct net_t *np, int32 *pbfi, int32 *pbfo,
+ int32 *pbtcfo, int32 ii)
+{
+ register struct net_pin_t *npp;
+ register int32 bi;
+ register struct npaux_t *npauxp;
+ word32 *wp;
+
+ memset(pbfi, 0, sizeof(int32)*np->nwid);
+ memset(pbfo, 0, sizeof(int32)*np->nwid);
+ memset(pbtcfo, 0, sizeof(int32)*np->nwid);
+
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   if ((npauxp = npp->npaux) == NULL || npauxp->nbi1 == -1) 
+    {
+     for (bi = 0; bi < np->nwid; bi++) (pbfi[bi])++;
+     continue;
+    }
+   if (npauxp->nbi1 == -2)
+    { 
+     /* SJM 10/12/04 - because contab realloced, must be ndx base of IS */
+     wp = &(__contab[npauxp->nbi2.xvi]);
+     /* DBG remove - here should never has x in index */
+     if (wp[2*ii + 1] != 0L) __arg_terr(__FILE__, __LINE__);
+     bi = (int32) wp[2*ii];
+     (pbfi[bi])++;
+     continue;
+    }
+   for (bi = npauxp->nbi1; bi >= npauxp->nbi2.i; bi--) (pbfi[bi])++;
+  }
+ for (npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   if ((npauxp = npp->npaux) == NULL || npauxp->nbi1 == -1) 
+    {
+     for (bi = 0; bi < np->nwid; bi++)
+      {
+       /* MIPD never seen here - only added by PLI or SDF after elaboration */
+       if (npp->npntyp == NP_TCHG) (pbtcfo[bi])++; else (pbfo[bi])++; 
+      }
+     continue;
+    }
+   if (npauxp->nbi1 == -2)
+    { 
+     /* SJM 10/12/04 - because contab realloced, must be ndx base of IS */
+     wp = &(__contab[npauxp->nbi2.xvi]);
+    
+     /* DBG remove - here should never has x in index */
+     if (wp[2*ii + 1] != 0L) __arg_terr(__FILE__, __LINE__);
+     bi = (int32) wp[2*ii];
+     if (npp->npntyp == NP_TCHG) (pbtcfo[bi])++; else (pbfo[bi])++; 
+     continue;
+    }
+   for (bi = npauxp->nbi1; bi >= npauxp->nbi2.i; bi--)
+    { if (npp->npntyp == NP_TCHG) (pbtcfo[bi])++; else (pbfo[bi])++; } 
+  }
+}
+
+/*
+ * check fan-in and fan-out and set multiple driver net bit for vector
+ * know vector or will not be called
+ * could call lds and drivers reorganization routine from in here
+ */
+static void chkset_vec_fifo(struct net_t *np, int32 *pbfi, int32 *pbfo,
+ int32 ii, int32 isform, int32 nd_fi_chk)
+{
+ register int32 bi;
+ int32 r1, r2;
+ int32 someno_fanin, someno_fanout, allno_fanin, allno_fanout;
+ struct itree_t *itp;
+ char s1[IDLEN], s2[RECLEN], s3[RECLEN];
+
+ /* DBG remove */
+ if (!np->vec_scalared && (has_rng_npp(np) || np->nsym->sy_impldecl))
+  __misc_terr(__FILE__, __LINE__);
+
+ someno_fanin = someno_fanout = FALSE;
+ allno_fanin = allno_fanout = TRUE;
+ /* first check to see if all of wire has no fan-in */ 
+ for (bi = 0; bi < np->nwid; bi++)
+  {
+   if (pbfi[bi] == 0) someno_fanin = TRUE;
+   /* notice for is form, any > 1 will set for entire wire */ 
+   else { allno_fanin = FALSE; if (pbfi[bi] >= 2) np->n_multfi = TRUE; }
+   if (pbfo[bi] == 0) someno_fanout = TRUE; else allno_fanout = FALSE;
+  }
+ if (!allno_fanin && !someno_fanin && !allno_fanout && !someno_fanout)
+  return;
+ /* if added net, no messages multi-fo set */ 
+ /* mark for cases where cannot determine fi/fo from load and driver list */
+ if (isform)
+  {
+   if ((itp = cnvt_to_itp(__inst_mod, ii)) != NULL)
+    {
+     sprintf(s1, "in %s(%s):", __inst_mod->msym->synam, __msg2_blditree(__xs,
+      itp));
+    }
+   else sprintf(s1, "in %s(CONNECT?):", __inst_mod->msym->synam);
+  }
+ else sprintf(s1, "in %s:", __inst_mod->msym->synam);
+ if (np->vec_scalared) strcpy(s2, ""); else strcpy(s2, " vectored");
+ __getwir_range(np, &r1, &r2);
+ if (allno_fanin && nd_fi_chk)
+  {
+   __gfinform(418, np->nsym->syfnam_ind, np->nsym->sylin_cnt, 
+    "%s %s%s [%d:%d] %s has no drivers (no bit has fan-in)", s1,
+    __to_wtnam(s3, np), s2, r1, r2, np->nsym->synam);
+  }
+ if (allno_fanout)
+  {
+   __gfinform(428, np->nsym->syfnam_ind, np->nsym->sylin_cnt, 
+    "%s %s%s [%d:%d] %s drives nothing (no bit has fan-out)", s1,
+    __to_wtnam(s3, np), s2, r1, r2, np->nsym->synam);
+  }
+ /* next emit bit by bit errors - know at least one error */ 
+ if (nd_fi_chk)
+  {
+   if (someno_fanin && !allno_fanin)    
+    {
+     for (bi = 0; bi < np->nwid; bi++)
+      {
+       if (pbfi[bi] == 0)
+        {
+         __gfinform(418, np->nsym->syfnam_ind, np->nsym->sylin_cnt, 
+          "%s %s%s [%d:%d] %s bit %d has no declarative drivers (no fan-in)",
+          s1, __to_wtnam(s3, np), s2, r1, r2, np->nsym->synam, bi);
+        }
+     }
+    } 
+  }
+ if (someno_fanout && !allno_fanout)
+  {
+   for (bi = 0; bi < np->nwid; bi++)
+    {
+     if (pbfo[bi] == 0)
+      {
+       __gfinform(428, np->nsym->syfnam_ind, np->nsym->sylin_cnt, 
+        "%s %s%s [%d:%d] %s bit %d drives nothing (no declartive fan-out)",
+        s1, __to_wtnam(s3, np), s2, r1, r2, np->nsym->synam, bi);
+      }
+    }
+  }
+}
+
+/*
+ * return T if any net pin is non -1 form
+ */
+static int32 has_rng_npp(struct net_t *np)
+{
+ register struct net_pin_t *npp;
+ struct npaux_t *npauxp;
+
+ for (npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   if ((npauxp = npp->npaux) != NULL && npauxp->nbi1 != -1) return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * convert a module and an itinum to the corresponding itp location
+ * this searches 
+ */
+static struct itree_t *cnvt_to_itp(struct mod_t *mdp, int32 itino)
+{
+ register int32 ii;
+ struct itree_t *itp;
+
+ for (ii = 0; ii < __numtopm; ii++)
+  {
+   if ((itp = cnvt_todown_itp(__it_roots[ii], mdp, itino)) != NULL)
+    return(itp);
+  }
+ __arg_terr(__FILE__, __LINE__);
+ return(NULL);
+}
+
+/*
+ * dump a down level of a tree
+ */
+static struct itree_t *cnvt_todown_itp(struct itree_t *itp,
+ struct mod_t *mdp, int32 itino)
+{
+ register int32 ii; 
+ int32 ofsnum;
+ struct itree_t *itp2;
+
+ if (itp->itip->imsym->el.emdp == mdp && itp->itinum == itino) return(itp);
+ ofsnum = itp->itip->imsym->el.emdp->minum;
+ for (ii = 0; ii < ofsnum; ii++)
+  {
+   if ((itp2 = cnvt_todown_itp(&(itp->in_its[ii]), mdp, itino)) != NULL)
+    return(itp2);
+  } 
+ return(NULL);
+}
+
+/* 
+ * ROUTINE TO PREPARE EXPRESSIONS 
+ */
+
+/*
+ * check all expr. things that cannot be checked until most of prep done
+ * 1) set expr. >1 fi bit
+ * check for port and inst psel direction mismatch (warning)  
+ * inout ports multi-fi and set here
+ */
+extern void __prep_exprs_and_ports(void)
+{
+ register int32 pi, ii, gi, cai;
+ register struct mod_pin_t *mpp;
+ int32 pnum, derrtyp;
+ struct inst_t *ip;
+ struct mod_t *mdp, *imdp;
+ struct gate_t *gp;
+ struct conta_t *cap;
+ struct expr_t *xp;
+ struct conta_t *pbcap;
+ char s1[RECLEN];
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   /* port lhs expr. that drive fi > 1 must be set for each inst. in mod */
+   for (ii = 0; ii < mdp->minum; ii++)
+    {
+     ip = &(mdp->minsts[ii]);
+     imdp = ip->imsym->el.emdp;
+     if ((pnum = imdp->mpnum) == 0) continue;
+
+     for (pi = 0; pi < pnum; pi++)
+      {
+       mpp = &(imdp->mpins[pi]);
+       /* any up iconn connection to inout is fi>1 here */
+       xp = ip->ipins[pi];
+
+       /* input port never lhs */
+       if (mpp->mptyp == IO_IN) continue;
+
+       /* will never see inouts, if in tran chan. no drivers */
+       if (lhs_has_figt1(xp)) xp->x_multfi = TRUE;
+      }
+    }
+   /* gate outputs may drive fi > 1 and be not strength */
+   for (gi = 0; gi < mdp->mgnum; gi++)
+    {
+     gp = &(mdp->mgates[gi]);
+
+     switch ((byte) gp->g_class) {
+      case GC_LOGIC: case GC_UDP: case GC_BUFIF: case GC_MOS: case GC_CMOS:
+       if (lhs_has_figt1(gp->gpins[0])) gp->gpins[0]->x_multfi = TRUE;
+       for (pi = 1; pi < (int32) gp->gpnum; pi++)
+        {
+         if (gp->g_class != GC_UDP)
+          sprintf(s1, "%s gate input %d", gp->gmsym->synam, pi + 1);
+         else sprintf(s1, "udp \"%s\" input %d", gp->gmsym->synam, pi + 1);
+         xp = gp->gpins[pi];
+
+         /* check for lhs and rhs same wire, delay type determines error */
+         derrtyp =  __chk_0del(gp->g_delrep, gp->g_du, mdp);
+         chk_decl_siderep(gp->gpins[0], xp, s1, derrtyp,
+          gp->gsym->syfnam_ind, gp->gsym->sylin_cnt);
+        }
+       /* set the input change eval routine for the gate */ 
+       __set_gchg_func(gp);
+       break;
+      /* no processing for trans - in separate tran switch channel */
+      /* tran. channel expressions never seen */
+      /* hard (channel input) driver expressions will be marked as fi>1 */
+      case GC_TRAN:
+       break;
+      case GC_TRANIF:
+       chk_trifctrl_insame_chan(gp, gp->gpins[2]);
+       /* if tranif ctrl expr non leaf, warn if in same channel as term */
+       if (!__isleaf(gp->gpins[2]))
+        {
+         chk_samechan_trifctrl_simple(mdp, gp, 0, gp->gpins[0], gp->gpins[2]);
+         chk_samechan_trifctrl_simple(mdp, gp, 1, gp->gpins[1], gp->gpins[2]);
+        }
+       break;
+      /* pull really source on wire not lhs */
+      case GC_PULL: break;
+      default: __case_terr(__FILE__, __LINE__); 
+     }
+    }
+
+   for (cap = &(mdp->mcas[0]), cai = 0; cai < mdp->mcanum; cai++, cap++)
+    {
+     if (lhs_has_figt1(cap->lhsx))
+      {
+       cap->lhsx->x_multfi = TRUE;
+       if (cap->ca_pb_sim)
+        {
+         for (pi = 0; pi < cap->lhsx->szu.xclen; pi++)
+          {
+           pbcap = &(cap->pbcau.pbcaps[pi]);
+           pbcap->lhsx->x_multfi = TRUE;
+          }
+        }
+      }
+    }
+
+   /* module in or inout ports can be non strength but drive fi > 1 */
+   pnum = mdp->mpnum;
+   for (pi = 0; pi < pnum; pi++)
+    {
+     mpp = &(mdp->mpins[pi]);
+     if (mpp->mptyp == IO_OUT) continue;
+     xp = mpp->mpref;
+     if (mpp->mptyp == IO_BID) { xp->x_multfi = TRUE; continue; }
+     if (lhs_has_figt1(xp)) xp->x_multfi = TRUE;
+    }
+  }
+ prep_tf_rwexprs();
+}
+
+/*
+ * check tranif 3rd ctrl input in same channel 
+ * LOOKATME - possible for xmr to cause this to be ok
+ */
+static void chk_trifctrl_insame_chan(struct gate_t *gp, struct expr_t *ndp)
+{
+ struct net_t *np0, *np1, *np2;
+ int32 pi;
+
+ if (__isleaf(ndp))
+  {
+   if (ndp->optyp == ID || ndp->optyp == GLBREF)
+    {
+     np2 = ndp->lu.sy->el.enp;
+     if (np2->ntraux == NULL) return;
+     np0 = __find_tran_conn_np(gp->gpins[0]);
+     np1 = __find_tran_conn_np(gp->gpins[1]);
+     pi = -1;
+     if (np2 == np0) pi = 0;
+     if (pi != -1 && (np2->ntyp != N_SUPPLY0 && np2->ntyp != N_SUPPLY1))
+      {
+       __gfinform(3011, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+        "%s %s non supply net %s (port %d) appears in tran channel and control input - possible infinite loop oscillation",
+        gp->gmsym->synam, gp->gsym->synam, np2->nsym->synam, pi);
+      }   
+     pi = -1;
+     if (np2 == np1) pi = 1;
+     if (pi != -1 && (np2->ntyp != N_SUPPLY0 && np2->ntyp != N_SUPPLY1))
+      {
+       __gfinform(3011, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+        "%s %s non supply net %s (port %d) appears in tran channel and control input - possible infinite loop oscillation",
+        gp->gmsym->synam, gp->gsym->synam, np2->nsym->synam, pi);
+      }   
+    }
+   return;
+  }
+ if (ndp->lu.x != NULL) chk_trifctrl_insame_chan(gp, ndp->lu.x);
+ if (ndp->ru.x != NULL) chk_trifctrl_insame_chan(gp, ndp->ru.x);
+}
+
+/*
+ * check to see if tranif enable in same channel as the bidirect terminals
+ * and expr non simple (if simple will use tranif node vertex value)
+ * if complex will not update the enable during tran switch channel relax 
+ */
+static void chk_samechan_trifctrl_simple(struct mod_t *mdp, struct gate_t *gp,
+ int32 pi, struct expr_t *termxp, struct expr_t *ctrlxp)
+{
+ register int32 ii;
+ int32 bi, bi2, chanid0, chanid2, inum2;
+ struct net_t *np0, *np2;
+ struct vbinfo_t *vbip;
+ struct gref_t *grp;
+
+ np0 = __find_tran_conn_np(termxp);
+ /* if terminal net is not in enable expr no problem possible */
+ if (!net_in_expr(ctrlxp, np0)) return;
+
+ /* DBG remove */
+ if (np0->ntraux == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ __push_itstk(mdp->moditps[0]);
+ /* SJM 08/02/01 - only called for tranif so other side itp same */
+ /* get terminal net/bit */
+ np0 = __tranx_to_netbit(termxp, 0, &bi, __inst_ptr);
+ /* DBG remove */
+ if (np0->ntraux == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ bi2 = (bi == -1) ? 0 : bi;
+ vbip = np0->ntraux->vbitchans[np0->nwid*__inum + bi2];
+ /* SJM 08/07/01 - bit may not be in channel */
+ if (vbip == NULL) goto done;
+ chanid0 = vbip->chan_id;
+
+ if (ctrlxp->optyp == LSB)
+  {
+   /* BEWARE - this assumes all constant folded */
+   if (termxp->ru.x->optyp != NUMBER)
+    {
+     __gfwarn(3112, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+      "%s %s third enable input net %s probably in same switch channel as terminal %d but bit select index non constant - updated node value not used when solving channel",
+      gp->gmsym->synam, gp->gsym->synam, np0->nsym->synam, pi);
+    }
+   goto done;
+  }
+ if (termxp->optyp == PARTSEL)
+  {
+   chanid2 = vbip->chan_id;
+   np2 = ctrlxp->lu.x->lu.sy->el.enp;
+   if (ctrlxp->lu.x->optyp == GLBREF)
+    {
+     grp = ctrlxp->lu.x->ru.grp;
+     for (ii = 0; ii < grp->targmdp->flatinum; ii++)
+      {
+       /* part select here uses low bit */
+
+       inum2 = grp->targmdp->moditps[ii]->itinum;
+       vbip = np0->ntraux->vbitchans[np0->nwid*inum2];
+       /* SJM 08/07/01 - low bit may not be in channel */
+       if (vbip == NULL) goto done;
+       chanid2 = vbip->chan_id;
+       if (chanid0 == chanid2)
+        {
+         __gfwarn(3115, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+          "%s %s third enable input heirarchical reference part select of net %s in same switch channel as terminal %d - updated node value not used when solving channel",
+          gp->gmsym->synam, gp->gsym->synam, np0->nsym->synam, pi);
+         goto done;
+        }
+      }
+     goto done;
+    }
+   /* non xmr part select case */  
+   bi = __contab[ctrlxp->ru.x->ru.xvi];
+   /* DBG remove */
+   if (np2->ntraux == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   vbip = np2->ntraux->vbitchans[np0->nwid*__inum + bi];
+   /* SJM 08/07/01 - low bit may not be in channel */
+   if (vbip == NULL) goto done;
+   chanid2 = vbip->chan_id;
+   if (chanid0 == chanid2)
+    {
+     __gfwarn(3116, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+      "%s %s third enable input part select of net %s in same switch channel as terminal %d - updated node value not used when solving channel",
+      gp->gmsym->synam, gp->gsym->synam, np0->nsym->synam, pi);
+    }
+   goto done; 
+  }
+ /* complex expression - can't tell if really in */
+ __gfwarn(3118, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+  "%s %s third enable input complex expression contains net %s possibly in same switch channel as terminal %d - updated node value not used when solving channel",
+  gp->gmsym->synam, gp->gsym->synam, np0->nsym->synam, pi);
+
+done:
+ __pop_itstk();
+}
+
+/*
+ * return T if net in expr
+ */
+static int32 net_in_expr(struct expr_t *ndp, struct net_t *np)
+{
+ struct net_t *np1;
+
+ if (__isleaf(ndp))
+  {
+   if (ndp->optyp == ID || ndp->optyp == GLBREF)
+    {
+     /* T even if different instances */
+     np1 = ndp->lu.sy->el.enp;
+     if (np == np1) return(TRUE);
+    }
+   return(FALSE);
+ }
+ if (ndp->lu.x != NULL)
+  { if (net_in_expr(ndp->lu.x, np)) return(TRUE); }
+ if (ndp->ru.x != NULL)
+  { if (net_in_expr(ndp->ru.x, np)) return(TRUE); }
+ return(FALSE);
+}
+
+/*
+ * prepare tf rw expressions 
+ * set multfi bits for tf_ rw expressions involving wires 
+ * concat never tf_ rw 
+ */
+static void prep_tf_rwexprs(void)
+{
+ register int32 pi;
+ register struct tfrec_t *tfrp; 
+ register struct tfarg_t *tfap;
+ struct expr_t *xp;
+
+ for (tfrp = __tfrec_hdr; tfrp != NULL; tfrp = tfrp->tfrnxt)
+  {
+   for (pi = 1; pi < tfrp->tfanump1; pi++)
+    {
+     tfap = &(tfrp->tfargs[pi]);
+     xp = tfap->arg.axp; 
+     if (!xp->tf_isrw) continue;
+     /* only wires have multiple fan in */
+     if (tfap->anp->ntyp >= NONWIRE_ST) continue;
+
+     /* no context module or inst neede in here */
+     if (lhs_has_figt1(xp))
+      { xp->x_multfi = TRUE; __alloc_tfdrv_wp(tfap, xp, tfrp->tf_inmdp); }
+    }
+  }
+}
+
+/*
+ * allocate the tfdrv wp
+ * notice this can never be array 
+ */ 
+extern void __alloc_tfdrv_wp(struct tfarg_t *tfap, struct expr_t *xp,
+ struct mod_t *mdp)
+{
+ int32 totchars;
+ 
+ if (xp->x_stren)
+  tfap->tfdrv_wp.bp = (byte *) __my_malloc(xp->szu.xclen*mdp->flatinum);
+ else
+  {
+   totchars = __get_pcku_chars(xp->szu.xclen, mdp->flatinum);
+   tfap->tfdrv_wp.wp = (word32 *) __my_malloc(totchars);
+  }
+ __init_tfdrv(tfap, xp, mdp);
+}
+
+/*
+ * initialize tf arg value to z 
+ * may be strength
+ */
+extern void __init_tfdrv(struct tfarg_t *tfap, struct expr_t *xp,
+ struct mod_t *mdp)
+{
+ register int32 i;
+ byte *sbp;
+ struct xstk_t *xsp;
+
+ if (xp->x_stren)
+  {
+   sbp = (byte *) tfap->tfdrv_wp.bp;
+   set_byteval_(sbp, mdp->flatinum*xp->szu.xclen, ST_HIZ);
+  }
+ else 
+  {
+   push_xstk_(xsp, xp->szu.xclen);
+   zero_allbits_(xsp->ap, xp->szu.xclen); 
+   one_allbits_(xsp->bp, xp->szu.xclen); 
+   /* this does not access mod con tab */
+
+   __push_wrkitstk(mdp, 0);
+   for (i = 0; i < mdp->flatinum; i++) 
+    {
+     __inst_ptr->itinum = i;
+     __inum = i;
+     /* no need to access mod con table here */
+     __st_perinst_val(tfap->tfdrv_wp, xp->szu.xclen, xsp->ap, xsp->bp);
+    }
+   __pop_xstk();
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * return T if lhs has at least 1 fi > 1 net  
+ * this is needed because expr. bit also set for any strength but for
+ * fi == 1 strength do not need 
+ * any wire in a tran/inout channel must be fi>1  
+ */
+static int32 lhs_has_figt1(struct expr_t *lhsx)
+{
+ struct expr_t *xp;
+ struct net_t *np;
+
+ switch ((byte) lhsx->optyp ) {
+  case OPEMPTY: break;
+  case ID:
+  case GLBREF:
+   np = lhsx->lu.sy->el.enp;
+chk_net_bit:
+   /* any wire in tran channel is fi>1 */ 
+   if (np->ntraux != NULL) return(TRUE);
+   if (np->n_multfi) return(TRUE);
+   break;
+  case LSB:
+  case PARTSEL:
+   np = lhsx->lu.x->lu.sy->el.enp;
+   goto chk_net_bit;
+  case LCB:
+   /* know for lhs at most 1 level of concatenate */
+   for (xp = lhsx->ru.x; xp != NULL; xp = xp->ru.x)
+    { if (lhs_has_figt1(xp->lu.x)) return(TRUE); }
+   break;
+  default: __case_terr(__FILE__, __LINE__); 
+ }
+ return(FALSE);
+}
+
+/*
+ * additional prep and checking of wide continuous assigns after fi known
+ *
+ * rules for delay and fi combinations of drivers and rhs save expr.:
+ * fi==1, delay =0 => driver access by loading net, do not need rhs val wp
+ *                    because no sched. value to re-eval  
+ *                    (eval and store)
+ * fi==1, delay >0 => driver access by loading net, has rhs val wp
+ *                    because need to re-eval expr. after delay for assign
+ *                    and so expr. no changes can be killed off early
+ * fi>1,  delay =0 => driver access just by loading rhs, may need to save
+ *                    rhs val save 
+ * fi>1,  delay >0 => need to save driver wp and need rhs val wp for sched.
+ *
+ * notice delays prepared before here
+ */
+extern void __prep_contas(void)
+{
+ register int32 i, bi;
+ register struct conta_t *cap, *pbcap;
+ int32 cai, insts, derrtyp;
+ struct mod_t *mdp; 
+ char s1[RECLEN];
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (cap = &(mdp->mcas[0]), cai = 0; cai < mdp->mcanum; cai++, cap++)
+    {
+     insts = mdp->flatinum;
+
+     /* first check and eliminate getpat conta form */
+     /* has neither rhsval wp or driver wp and no delay or error */
+     /* SJM 09/28/02 - get pat lhs never PB decomposed rhs concat form */
+     if (cap->lhsx->getpatlhs)
+      { getpat_lhs_figt1(mdp, cap->lhsx, cap); continue; }
+
+     /* need to eval rhs because of delay bit */
+     /* know 6 and 12 not possible here but is 4x possible here ? */
+     switch ((byte) cap->ca_delrep) {
+      case DT_4V: case DT_IS4V: case DT_IS4V1: case DT_IS4V2: case DT_4X:
+       cap->ca_4vdel = TRUE;
+       break;
+      default: cap->ca_4vdel = FALSE;
+     }
+
+     if (!cap->ca_pb_sim)
+      {
+       /* need to save rhs driver for any fi > 1 case either because driver */
+       /* different than rhs (delay > 0) or to avoid possible re-evaluation */
+       /* of rhs func. call also need to save if has delay for accurate */
+       /* inertial delay algorithm */
+       if (cap->lhsx->x_multfi || cap->ca_delrep != DT_NONE)
+        __allocinit_perival(&cap->ca_drv_wp, insts, cap->lhsx->szu.xclen,
+         TRUE);
+
+       /* if conta has delay, need scheduled event array */
+       /* fi >1 but no delay does not need schedule event table */
+       if (cap->ca_delrep != DT_NONE)
+        {
+         __allocinit_perival(&(cap->schd_drv_wp), insts,
+          cap->lhsx->szu.xclen, TRUE);
+         cap->caschd_tevs = (i_tev_ndx *)
+          __my_malloc(insts*sizeof(i_tev_ndx));
+         for (i = 0; i < insts; i++) cap->caschd_tevs[i] = -1;
+        }
+       /* need to check for variable on both sides, even if 0 delay */ 
+       derrtyp =  __chk_0del(cap->ca_delrep, cap->ca_du, mdp);
+       chk_decl_siderep(cap->lhsx, cap->rhsx, "continuous assign", derrtyp,
+        cap->casym->syfnam_ind, cap->casym->sylin_cnt);
+      }
+     else
+      {
+       derrtyp =  __chk_0del(cap->ca_delrep, cap->ca_du, mdp);
+       for (bi = 0; bi < cap->lhsx->szu.xclen; bi++)
+        {
+         pbcap = &(cap->pbcau.pbcaps[bi]);
+         /* DBG remove -- */
+         if (pbcap->lhsx->szu.xclen != 1) __misc_terr(__FILE__, __LINE__);
+         /* --- */
+         /* if conta lhs expr fi>1, then all bit must be and need drv wp */
+         if (cap->lhsx->x_multfi || cap->ca_delrep != DT_NONE)
+          __allocinit_perival(&(pbcap->ca_drv_wp), insts, 1, TRUE);
+         if (cap->ca_delrep != DT_NONE)
+          {
+           __allocinit_perival(&(pbcap->schd_drv_wp), insts, 1, TRUE);
+           pbcap->caschd_tevs = (i_tev_ndx *)
+            __my_malloc(insts*sizeof(i_tev_ndx));
+           for (i = 0; i < insts; i++) pbcap->caschd_tevs[i] = -1;
+          }
+         /* need to check for variable on both sides, even if 0 delay */ 
+         sprintf(s1, "per bit %d continuous assign", bi);
+         chk_decl_siderep(pbcap->lhsx, pbcap->rhsx, s1, derrtyp,
+          cap->casym->syfnam_ind, cap->casym->sylin_cnt);
+        }
+      }
+    }
+  }
+}
+
+/*
+ * initialize and maybe allocate the continuous assign sched. and drive tabs
+ *
+ * this is always used for mod port input and output half drivers using
+ * dummy conta for union place holder 
+ *
+ * initial value is z since needed for inout port in and out drivers 
+ * think also better for conta but for conta's always overwritten?
+ * this is only for non strength case - stren must be initialized
+ * to strength wire type init value
+ */
+extern void __allocinit_perival(union pck_u *nvap, int32 insts, int32 blen,
+ int32 nd_alloc)
+{
+ int32 totchars, wlen;
+
+ if (blen == 1)
+  {
+   totchars = insts;
+   if (nd_alloc) nvap->bp = (byte *) __my_malloc(totchars);
+   set_byteval_(nvap->bp, insts, 2);
+  }
+ else
+  {
+   wlen = wlen_(blen); 
+   totchars = 2*insts*wlen*WRDBYTES;
+   if (nd_alloc) nvap->wp = (word32 *) __my_malloc(totchars);
+   /* initialize to z - do not know driver - sim init will set */
+   __init_vec_var(nvap->wp, insts, wlen, blen, 0L, 0xffffffffL); 
+  }
+}
+
+/*
+ * allocate (if flag T) and initialize strength perinst value
+ * this is for tran channels
+ */
+extern void __allocinit_stperival(union pck_u *nvap, int32 insts,
+ struct net_t *np, int32 nd_alloc)
+{
+ int32 totbits, stval;
+ byte sval;
+
+ totbits = insts*np->nwid;
+ if (nd_alloc) nvap->bp = (byte *) __my_malloc(totbits);
+ /* for trireg in tran channel, hard driver must be z - it will set value */
+ if (np->ntraux != NULL && np->ntyp == N_TRIREG) stval = ST_HIZ;
+ else __get_initval(np, &stval);
+ sval = (byte) stval;
+ set_byteval_(nvap->bp, totbits, sval);
+}
+
+/*
+ * check a lhs expr. and emit error for every wire that has fi > 1
+ * message for getpat only
+ * LOOKATME - should bit select of scalared wire be legal for getpattern
+ */
+static void getpat_lhs_figt1(struct mod_t *mdp, struct expr_t *lhsx,
+ struct conta_t *cap)
+{
+ struct net_t *np;
+
+ switch ((byte) lhsx->optyp) {
+  case OPEMPTY: break;
+  case ID:
+  case GLBREF:
+   np = lhsx->lu.sy->el.enp;
+   if (np->n_multfi)
+    {
+     /* wire for getpat will be scalar or will not get this far */
+     __gferr(858, cap->casym->syfnam_ind, cap->casym->sylin_cnt,
+     "$getpattern lvalue wire %s more than one driver illegal - no way to removebus contention",
+     __to_idnam(lhsx)); 
+    }
+   if (np->ntraux != NULL)
+    {
+     __gferr(858, cap->casym->syfnam_ind, cap->casym->sylin_cnt,
+      "$getpattern lvalue wire %s inout port or tran connection illegal",
+      __to_idnam(lhsx)); 
+    }
+   if (np->nrngrep == NX_DWIR)
+    {
+     __gferr(938, cap->casym->syfnam_ind, cap->casym->sylin_cnt,
+      "$getpattern lvalue wire %s delay or path destination illegal",
+      __to_idnam(lhsx)); 
+    }
+   break;
+  case LCB:
+   /* know for lhs at most 1 level of concatenate */
+   {
+    struct expr_t *xp2;
+    for (xp2 = lhsx->ru.x; xp2 != NULL; xp2 = xp2->ru.x)
+     getpat_lhs_figt1(mdp, xp2->lu.x, cap);
+   }
+   break;
+  default: __case_terr(__FILE__, __LINE__); 
+ }
+}
+
+/*
+ * check continous assign or gate for same variable on both sides
+ * if delay then inform, if no delay warn - probable inf. loop
+ *
+ * possible for 2 same wire globals to be on both sides but not caught here
+ */
+static void chk_decl_siderep(struct expr_t *lhsx, struct expr_t *rhsx,
+ char *objnam, int32 deltyp, word32 fnind, int32 lcnt)
+{
+ int32 nd_inform, wire_issel;
+ struct expr_t *ndp;
+ struct net_t *np;
+ char s1[RECLEN];
+
+ /* expect rhs to be wider */
+ nd_inform = TRUE;
+ switch (rhsx->optyp) {
+  case ID: 
+   nd_inform = FALSE;
+   np = rhsx->lu.sy->el.enp; 
+cmp_wire:
+   if (!find_var_in_xpr(lhsx, np, &wire_issel)) break;
+
+   if (deltyp == DBAD_NONE) { strcpy(s1, "no delay"); nd_inform = FALSE; }
+   else if (deltyp == DBAD_EXPR || deltyp == DBAD_MAYBE0) 
+    { strcpy(s1, "possible 0 delay"); nd_inform = FALSE; }
+   else if (deltyp == DBAD_0)
+    { strcpy(s1, "all 0 delay"); nd_inform = FALSE; }
+   else strcpy(s1, "delay");
+
+   if (nd_inform || wire_issel)
+    __gfinform(444, fnind, lcnt,
+     "wire %s repeated on both sides of %s - has %s", np->nsym->synam,
+     objnam, s1);
+   else __gfwarn(624, fnind, lcnt,
+    "wire %s repeated on both sides of %s - has %s", np->nsym->synam, objnam,
+    s1);
+   break;
+  case LSB: case PARTSEL:
+   np = rhsx->lu.x->lu.sy->el.enp;
+   goto cmp_wire;
+  case LCB:
+   for (ndp = rhsx->ru.x; ndp != NULL; ndp = ndp->ru.x)
+    chk_decl_siderep(lhsx, ndp->lu.x, objnam, deltyp, fnind, lcnt);
+   break;
+  case FCALL: 
+   for (ndp = rhsx->ru.x; ndp != NULL; ndp = ndp->ru.x)
+    chk_decl_siderep(lhsx, ndp->lu.x, objnam, deltyp, fnind, lcnt);
+ }
+}
+
+/*
+ * find a variable in an expr.
+ * if same variable but global xmr, not a match
+ */
+static int32 find_var_in_xpr(struct expr_t *xp, struct net_t *np, 
+ int32 *wire_sel)
+{
+ register struct expr_t *ndp;
+ struct net_t *npx;
+
+ if (np->ntyp >= NONWIRE_ST) return(FALSE);
+
+ *wire_sel = TRUE;
+ switch (xp->optyp) {
+  case ID: 
+   *wire_sel = FALSE;
+   npx = xp->lu.sy->el.enp;
+comp_net:
+   return(np == npx);
+  case LSB: case PARTSEL:
+   npx = xp->lu.x->lu.sy->el.enp;
+   goto comp_net;
+  case LCB:
+   for (ndp = xp->ru.x; ndp != NULL; ndp = ndp->ru.x)
+    { if (find_var_in_xpr(ndp->lu.x, np, wire_sel)) return(TRUE); } 
+   break;
+  case FCALL: 
+   for (ndp = xp->ru.x; ndp != NULL; ndp = ndp->ru.x)
+    { if (find_var_in_xpr(ndp->lu.x, np, wire_sel)) return(TRUE); } 
+ }
+ return(FALSE);
+}
+
+/*
+ * ROUTINES TO DYNAMICALLY SET UP MIPDS
+ */
+   
+/*
+ * allocate, initialize, and link in NP MIPD load delay npp for a net 
+ *
+ * reinit does not turn off SDF annotated delays - if task called
+ * with replace form works, increment adds
+ */
+extern void __add_alloc_mipd_npp(struct net_t *np, struct mod_t *mdp)
+{
+ register int32 bi;
+ int32 ii;
+ struct net_pin_t *npp;
+ struct mipd_t *mipdp;
+
+ /* DBG remove --- */
+ if (np->nlds != NULL && np->nlds->npntyp == NP_MIPD_NCHG)
+  __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ __cur_npnp = np;
+ __cur_npnum = 0;
+ /* always for entire net - table nil if no MIPD on bit for any inst */
+ /* this also inserts on front of list */
+ npp = __alloc_npin(NP_MIPD_NCHG, -1, -1);
+
+ if (np->nlds == NULL)
+  {
+   /* DBG remove -- */
+   if (__optimized_sim && !__sdf_from_cmdarg)
+    {
+     __misc_terr(__FILE__, __LINE__);
+    }
+   /* -- */
+
+   /* LOOKATME - think since input port will always have load */
+   /* add the one new mipd net pin - know np never a reg becaus in/inout */
+   np->nlds = npp;
+
+   /* SJM 07/25/01 - was not setting all needed bits right */
+   /* need to set the various bits to indicate has load so net changes */
+   /* put on nchg list */ 
+   np->nchg_has_lds = TRUE;
+
+   /* when add mipd load, must turn off all chged */
+   /* even if dce list was not empty, if match itp dces some action bits */
+   /* will be wrongly off */
+   /* SJM 01/06/03 - is is possible to only turn on current inst? */
+   for (ii = 0; ii < mdp->flatinum; ii++)
+    { np->nchgaction[ii] &= ~(NCHG_ALL_CHGED); }
+  }
+ else { npp->npnxt = np->nlds; np->nlds = npp; }
+
+ /* SJM 07/26/01 - alloc was wrong size - needs to be one per bit */
+ npp->elnpp.emipdbits = (struct mipd_t *)
+  __my_malloc(np->nwid*sizeof(struct mipd_t));
+
+ /* need basic setup especially turning on no mipd bit for each */
+ for (bi = 0; bi < np->nwid; bi++)
+  {
+   mipdp = &(npp->elnpp.emipdbits[bi]);
+   /* BEWARE - this is crucial T bit indicating no path for this bit */
+   mipdp->no_mipd = TRUE;
+   mipdp->pth_mipd = FALSE;
+   mipdp->impthtab = NULL;
+   /* rest of fields set if path ends on bit */
+  } 
+ /* SJM 02/06/03 - may have npps but not dces so must turn this on */
+ /* SJM 06/23/04 - ### ??? LOOKATME - is this needed without regen? */
+ /* since nchg nd chgstore on, know nchg action right */
+ if (np->ntyp >= NONWIRE_ST) np->nchg_has_dces = TRUE;
+}
+
+/*
+ * initialize a (PORT form path - first step in annotating either path delay
+ * value is the (PORT form destination for one bit
+ */
+extern void __setup_mipd(struct mipd_t *mipdp, struct net_t *np, int32 ninsts)
+{
+ register int32 ii;
+ int32 stval;
+ byte bv;
+
+ mipdp->no_mipd = FALSE;
+ mipdp->pb_mipd_delrep = DT_1V;
+ mipdp->pb_mipd_du.d1v = (word64 *) __my_malloc(sizeof(word64));
+ /* SJM 07/22/01 - nee to start value at 0 so unset stay as 0 */
+ mipdp->pb_mipd_du.d1v[0] = 0ULL;
+
+ mipdp->oldvals = (byte *) __my_malloc(ninsts); 
+
+ if (!np->n_stren) bv = (byte) __get_initval(np, &stval);
+ else { __get_initval(np, &stval); bv = (byte) stval; }
+ for (ii = 0; ii < ninsts; ii++) mipdp->oldvals[ii] = bv;
+ 
+ mipdp->mipdschd_tevs = (i_tev_ndx *) __my_malloc(ninsts*sizeof(i_tev_ndx));
+ for (ii = 0; ii < ninsts; ii++) mipdp->mipdschd_tevs[ii] = -1;
+ if (mipdp->pth_mipd)
+  {
+   mipdp->impthtab = (struct impth_t **)
+    __my_malloc(ninsts*sizeof(struct impth_t *));
+   for (ii = 0; ii < ninsts; ii++) mipdp->impthtab[ii] = NULL;
+  }
+}
+
+/*
+ * re-init all mipds for a port - only called if port has mipds
+ * this just reset old value
+ */
+extern void __reinit_mipd(struct mod_pin_t *mpp, struct mod_t *mdp)
+{
+ register int32 ndx, bi, ii;
+ register struct impth_t *impthp;
+ int32 stval;
+ byte bv;
+ struct tenp_t *prtnetmap;
+ struct mipd_t *mipdp;
+ struct net_t *np;
+
+ prtnetmap = __bld_portbit_netbit_map(mpp);
+ /* for every port bit - just reinit connected bits */
+ /* other ports will reinit other bits if used */ 
+ for (ndx = 0; ndx < mpp->mpwide; ndx++)
+  { 
+   np = prtnetmap[ndx].tenu.np;
+   /* notice ndx is port bit index but bi is connecting net bit index */
+   bi = prtnetmap[ndx].nbi;
+   /* DBG remove -- */
+   if (np->nlds == NULL || np->nlds->npntyp != NP_MIPD_NCHG)
+    __misc_terr(__FILE__, __LINE__);
+   /* -- */
+   mipdp = &(np->nlds->elnpp.emipdbits[bi]);
+
+   if (!np->n_stren) bv = (byte) __get_initval(np, &stval);
+   else { __get_initval(np, &stval); bv = (byte) stval; }
+   for (ii = 0; ii < mdp->flatinum; ii++) mipdp->oldvals[ii] = bv;
+ 
+   for (ii = 0; ii < mdp->flatinum; ii++) mipdp->mipdschd_tevs[ii] = -1;
+
+   if (mipdp->pth_mipd)
+    {
+     /* only need to re-init change times */ 
+     for (ii = 0; ii < mdp->flatinum; ii++) 
+      {
+       impthp = mipdp->impthtab[ii];
+       for (; impthp != NULL; impthp = impthp->impthnxt)
+        { impthp->lastchg = 0ULL; }
+      }
+    }
+  } 
+ __my_free((char *) prtnetmap, mpp->mpwide*sizeof(struct tenp_t));
+}
+
+/*
+ * access mipd from port and port index
+ *
+ * for scalar ndx passed as 0 not -1 here
+ * only called if port has mipd
+ */
+extern struct mipd_t *__get_mipd_from_port(struct mod_pin_t *mpp, int32 ndx)
+{
+ int32 bi;
+ struct mipd_t *mipdp;
+ struct tenp_t *prtnetmap;
+ struct net_t *np;
+
+ prtnetmap = __bld_portbit_netbit_map(mpp);
+ np = prtnetmap[ndx].tenu.np;
+ bi = prtnetmap[ndx].nbi;
+ mipdp = &(np->nlds->elnpp.emipdbits[bi]);
+ __my_free((char *) prtnetmap, mpp->mpwide*sizeof(struct tenp_t));
+ return(mipdp);
+}
+
+/*
+ * for a lhs port, malloc and build tenp map from port bit to net bit 
+ * know port always lhs here
+ */
+extern struct tenp_t *__bld_portbit_netbit_map(struct mod_pin_t *mpp)
+{
+ register struct expr_t *catxp;
+ int32 pi;
+ struct tenp_t *prtnetmap;
+
+ prtnetmap = (struct tenp_t *) __my_malloc(mpp->mpwide*sizeof(struct tenp_t));
+
+ /* concatenate - add each component */
+ if (mpp->mpref->optyp == LCB)
+  {
+   pi = mpp->mpwide - 1;
+   for (catxp = mpp->mpref->ru.x; catxp != NULL; catxp = catxp->ru.x)
+    {
+     pi -= catxp->lu.x->szu.xclen; 
+     add_portbit_map(prtnetmap, catxp->lu.x, pi);
+    }
+   return(prtnetmap);
+  } 
+ /* add simple port to map */
+ add_portbit_map(prtnetmap, mpp->mpref, 0);
+ return(prtnetmap);
+}
+
+/*
+ * for a lhs port, add non concat lhs port to port to bit map
+ * notice nbi index is 0 for scalar
+ */
+static void add_portbit_map(struct tenp_t *prtnetmap, struct expr_t *xp,
+ int32 base_pi)
+{
+ register int32 pi, bi; 
+ int32 psi1, psi2;
+ word32 *wp;
+ struct net_t *np;
+ struct expr_t *ndx;
+ 
+ switch ((byte) xp->optyp) {
+  case ID:
+   np = xp->lu.sy->el.enp;
+   if (!np->n_isavec)
+    {
+     prtnetmap[base_pi].tenu.np = np;
+     prtnetmap[base_pi].nbi = 0;
+    }
+   else 
+    {
+     for (pi = base_pi; pi < base_pi + xp->szu.xclen; pi++)
+      { prtnetmap[pi].tenu.np = np; prtnetmap[pi].nbi = pi - base_pi; }
+    }
+   break;
+  case OPEMPTY:
+   for (pi = base_pi; pi < base_pi + xp->szu.xclen; pi++)
+    {
+     /* LOOKATME - index illegal -1 here since think won't occur */
+     prtnetmap[pi].tenu.np = NULL;
+     prtnetmap[pi].nbi = -1;
+    }
+   break;
+  case PARTSEL:
+   np = xp->lu.x->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   wp = &(__contab[ndx->lu.x->ru.xvi]);
+   psi1 = (int32) wp[0];
+   wp = &(__contab[ndx->ru.x->ru.xvi]);
+   psi2 = (int32) wp[0];
+   /* part select always constant */
+   for (pi = base_pi, bi = psi2; pi < base_pi + xp->szu.xclen; pi++, bi++)
+    {
+     prtnetmap[pi].tenu.np = np;
+     prtnetmap[pi].nbi = bi;
+    }
+   break;
+  case LSB:
+   /* LOOKATME - think IS bit selects always split before here */
+   /* DBG remove */
+   if (xp->ru.x->optyp != NUMBER) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   np = xp->lu.x->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   wp = &(__contab[ndx->ru.xvi]);
+   psi1 = (int32) wp[0];
+   prtnetmap[base_pi].tenu.np = np;
+   prtnetmap[base_pi].nbi = psi1;
+   break;
+  /* since know only 1 level, removed before here */
+  case LCB: __case_terr(__FILE__, __LINE__);
+  /* xmr can't connect to port */
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * ROUTINES TO ALLOCATE NCHG ACTION STORAGE
+ */
+
+/*
+ * allocate nchg byte table and set nchgaction net ptrs
+ * even for cver-cc compiler, nchg storage malloc since access through net
+ *
+ * 08/22/02 - always need nchg store for dmpvars
+ * FIXME - should align ptrs at least on 4 byte boundaries
+ */
+extern void __alloc_nchgaction_storage(void)
+{
+ register int32 ni;
+ register struct net_t *np;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+
+ __nchgbtabbsiz = 0;
+ cmp_nchgbtabsize();
+ if (__nchgbtabbsiz > 0)
+  {
+   __nchgbtab = (byte *) __my_malloc(__nchgbtabbsiz);
+  }
+ __nchgbtabbi = 0;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mnnum != 0)
+    {
+     for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+      {
+       /* always need the changed byte array even for event */
+       np->nchgaction = (byte *) &(__nchgbtab[__nchgbtabbi]);
+       /* set to zero for now - initialize after lds/dces added */
+       memset(np->nchgaction, 0, mdp->flatinum);
+       __nchgbtabbi += mdp->flatinum; 
+      }
+    }
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if (tskp->trnum == 0) continue;
+
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       /* always need the changed byte array even for event */
+       np->nchgaction = (byte *) &(__nchgbtab[__nchgbtabbi]);
+       /* set to zero for now - initialize after dces/lds built */
+       memset(np->nchgaction, 0, mdp->flatinum);
+       __nchgbtabbi += mdp->flatinum;
+      }
+    }
+  }
+}
+
+/*
+ * compute size of needed nchg byte table in bytes
+ * also sets srep since always called
+ */
+static void cmp_nchgbtabsize(void)
+{
+ register int32 ni;
+ register struct net_t *np;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mnnum != 0)
+    {
+     for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+      {
+       /* storage for byte per inst. all changed table */
+       /* change state bytes go into scalar (byte) storage table */
+       __nchgbtabbsiz += mdp->flatinum;
+
+       set_1net_srep(np);
+      } 
+    }
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if (tskp->trnum == 0) continue;
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       /* always need the changed byte array even for event */
+       /* change state bytes go into scalar (byte) storage table */
+       __nchgbtabbsiz += mdp->flatinum;
+
+       set_1net_srep(np);
+      }
+    }
+  }
+}
+
+/*
+ * set the storage rep type for one net
+ *
+ * SJM 05/04/05 - since not calling alloc storage routine for cver-cc, 
+ * must set sreps in separate routine called from nchg routines that
+ * are always called
+ */
+static void set_1net_srep(struct net_t *np)
+{
+ if (np->ntyp == N_EVENT) return;
+
+ if (np->n_isarr) { np->srep = SR_ARRAY; return; }
+ if (np->ntyp == N_REAL) { np->srep = SR_VEC; return; } 
+ if (!np->n_isavec)
+  {
+   if (np->n_stren) np->srep = SR_SSCAL; else np->srep = SR_SCAL;
+   return;
+  }
+ if (!np->n_stren) np->srep = SR_VEC; else np->srep = SR_SVEC;
+}
+
+/*
+ * initialize nchg action byte table for all modules
+ *
+ * always assume dumpvars off also after reset (re-initialize)
+ * this must be called after dces reinited
+ */
+extern void __set_nchgaction_bits(void)
+{
+ register int32 ii, ni;
+ register struct net_t *np;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+ 
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+    {
+     for (ii = 0; ii < mdp->flatinum; ii++)
+      {
+       /* start with all dumpvars off - now independent of var chg */
+       /* all all other fields 0 off */
+       np->nchgaction[ii] = NCHG_DMPVNOTCHGED; 
+
+       if (np->ntyp >= NONWIRE_ST)
+        {
+         /* SJM - 07/01/00 - for regs, if no lds, all var insts stay */
+         /* all chged and never record */
+         if (np->nlds == NULL) np->nchgaction[ii] |= NCHG_ALL_CHGED;
+        }
+       else
+        { 
+         /* SJM 07/24/00 - for wires, if has dces not all changed */
+         if (np->nlds == NULL && (np->dcelst == NULL
+          || __cnt_dcelstels(np->dcelst) == 0))
+          np->nchgaction[ii] |= NCHG_ALL_CHGED;
+        }
+      }
+     /* SJM - 07/01/00 - set various per variable bits in 0th element */
+     /* SJM - 03/15/01 - change to fields in net record */
+     if (np->nlds != NULL) np->nchg_has_lds = TRUE;
+
+     /* SJM 07/24/00 - only nchg has dces on for regs immediate prop/wakeup */
+     if (np->ntyp >= NONWIRE_ST && np->dcelst != NULL)
+      np->nchg_has_dces = TRUE;
+
+     /* SJM REMOVEME */
+     /* --- 
+     if (np->nlds == NULL && np->dcelst == NULL && np->dmpv_in_src)
+      __misc_terr(__FILE__, __LINE__); 
+     -- */
+
+     /* if any lds, dces or dmpvs, need chg store  */
+     if (np->nlds != NULL || np->dcelst != NULL || np->dmpv_in_src)
+      np->nchg_nd_chgstore = TRUE;
+    }
+  
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       for (ii = 0; ii < mdp->flatinum; ii++)
+        {
+         /* start with all dumpvars off - now independent of var chg */
+         /* all all other fields 0 off */
+         np->nchgaction[ii] = NCHG_DMPVNOTCHGED; 
+
+         /* SJM - 07/01/00 - if no lds, all var insts stay all chged */
+         /* now all chged only for loads */
+         /* SJM 07/24/00 - here since know reg, all chged if no lds */
+         if (np->nlds == NULL) np->nchgaction[ii] |= NCHG_ALL_CHGED;
+        }
+       /* SJM - 07/01/00 - set various per var bits in 0th element */
+       /* SJM 03/15/01 - change to fields in net record */
+       if (np->nlds != NULL) np->nchg_has_lds = TRUE;
+
+       /* SJM 07/24/00 - only nchg has dces on for regs but task vars regs */
+       if (np->dcelst != NULL) np->nchg_has_dces = TRUE;
+
+       /* if any lds, dces or dmpvs, need chg store  */
+       if (np->nlds != NULL || np->dcelst != NULL || np->dmpv_in_src)
+        np->nchg_nd_chgstore = TRUE;
+      }
+    }
+  }
+}
+
+/*
+ * set computed optimtab bits for all vars in entire design
+ */
+extern void __set_optimtab_bits(void)
+{
+ register int32 ni;
+ register struct net_t *np;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+ 
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+    {
+     /* assume need chg store */
+     if (__dv_allform_insrc || mdp->mod_dvars_in_src)
+      {
+       np->dmpv_in_src = TRUE;
+       np->nchg_nd_chgstore = TRUE;
+      }
+    }
+  
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       if (__dv_allform_insrc || mdp->mod_dvars_in_src)
+        {
+         np->dmpv_in_src = TRUE;
+         np->nchg_nd_chgstore = TRUE;
+        }
+      }
+    }
+  }
+}
+
+/*
+ * ROUTINES TO ALLOCATE VARIABLE STORAGE
+ */
+
+/*
+ * allocate storage for all simulation variables
+ */
+extern void __alloc_sim_storage(void)
+{
+ register int32 ni;
+ register struct net_t *np;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+
+ /* always calculate var storage size - but only emit for interpreter */
+ __wtabwsiz = 0;
+ __btabbsiz = 0; 
+ cmp_tabsizes();
+
+ /* for cver-cc, gen .comm lable in bss section */
+ /* LOOKATME - is 0 storage size possible - think yes */
+ if (__btabbsiz > 0)
+  {
+   __btab = (byte *) __my_malloc(__btabbsiz);
+  }
+ if (__wtabwsiz > 0)
+  {
+   __wtab = (word32 *) __my_malloc(__wtabwsiz*sizeof(word32));
+  }
+ __wtabwi = 0; 
+ __btabbi = 0; 
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   if (__inst_mod->mnnum != 0)
+    {
+     for (ni = 0, np = &(__inst_mod->mnets[0]); ni < __inst_mod->mnnum;
+      ni++, np++) 
+      {
+       /* no allocated storage here for parameters - in different list */
+       /* also none for events (if dce will be allocated when used) */
+       if (np->ntyp == N_EVENT) continue;
+
+       /* for now always zeroing variables - when x/z */
+       /* could free later if no fan-in and no fan-out */
+       alloc_var(np);
+      } 
+    }
+   for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if (tskp->trnum == 0) continue;
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       if (np->ntyp == N_EVENT) continue;
+
+       /* for now always zeroing variables - when x/z */
+       alloc_var(np);
+      }
+    }
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * compute size of needed startage tables
+ *
+ * PORTABILITY FIXME - maybe need 8 byte alignment for ptr too?
+ * SJM 05/02/05 - now setting net srep here
+ */
+static void cmp_tabsizes(void)
+{
+ register int32 ni;
+ register struct net_t *np;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   if (__inst_mod->mnnum != 0)
+    {
+     for (ni = 0, np = &(__inst_mod->mnets[0]); ni < __inst_mod->mnnum;
+      ni++, np++) 
+      {
+       /* no allocated storage here for parameters - in different list */
+
+       /* also none for events (if dce will be allocated when used) */
+       if (np->ntyp == N_EVENT) continue;
+
+       /* because arrays may be large, must really alloc - so not counted */ 
+       if (np->n_isarr) continue;
+
+       cmpadd_1var_storsiz(np);
+      } 
+    }
+   for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     if (tskp->trnum == 0) continue;
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       if (np->ntyp == N_EVENT) continue;
+
+       /* no allocated storage here for parameters - in different list */
+       /* SJM 05/02/05 - was previously counting task arrays as part of */
+       /* the tab storage but still mallocing for interpreter */
+       if (np->n_isarr) continue;
+
+       /* for now always zeroing variables - when x/z */
+       cmpadd_1var_storsiz(np);
+      }
+    }
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * computer size for one variable
+ *
+ * never called for memories
+ */
+static void cmpadd_1var_storsiz(struct net_t *np)
+{
+ register int32 insts;
+
+ /* allocate array of srep structs for each inst. */
+ insts = __inst_mod->flatinum;
+
+ /* 05/03/05 - reals now just put in wtab (take 2 words) */
+ if (np->ntyp == N_REAL) { __wtabwsiz += 2*insts; return; }
+
+ /* compute needed size in bits */
+ /* non vectors */
+ if (!np->n_isavec)
+  {
+   /* SJM 10/16/99 - now scalars always 1 byte even non strength */
+   __btabbsiz += insts;
+  }
+ else
+  {
+   if (!np->n_stren)
+    {
+     /* hard non strength packed vector case - bits later converted to wrds */
+     /* SJM 12/16/99 - now packed vector packs from 2 to 16 bits into 1 word */
+     /* SJM 07/15/00 - now for vars only bits packed into bytes */
+     __wtabwsiz += 2*wlen_(np->nwid)*insts;
+    }
+   else
+    { 
+     /* strength vector 1 byte per bit case */
+     __btabbsiz += insts*np->nwid;
+    }
+  }
+}
+
+/*
+ * allocate storage for a variable
+ * know at this point storage form is compile (ct) union member
+ * allocation here is module specific - all inst here indistinguishable
+ * but at this point types determine initial values
+ */
+static void alloc_var(struct net_t *np)
+{
+ int32 insts;
+
+ /* allocate array of srep structs for each inst. */
+ insts = __inst_mod->flatinum;
+
+ /* need to handle REAL as special case - has special representation */
+ /* and now real can be array */
+ if (np->ntyp == N_REAL) { alloc_real_var(np, insts); return; }
+
+ if (np->n_isarr) __allocinit_arr_var(np, insts, TRUE);
+ else if (!np->n_isavec)
+  {
+   if (!np->n_stren) alloc_scal_var(np, insts);
+   else alloc_sscal_var(np, insts);
+  }
+ else
+  {
+   if (!np->n_stren) __allocinit_vec_var(np, insts, TRUE);
+   else alloc_svec_var(np, insts);
+  }
+}
+
+/*
+ * initialize a real variable
+ */
+static void alloc_real_var(struct net_t *np, int32 insts)
+{
+ register int32 i;
+ int32 arrw, totchars;
+ double *dp;
+
+ /* case 1: new real array - must be malloced */
+ /* must malloc arrays because they can be large */
+ if (np->n_isarr)
+  {
+   arrw = __get_arrwide(np);
+   totchars = arrw*(2*WRDBYTES*insts*wlen_(REALBITS));
+   np->nva.wp = (word32 *) __my_malloc(totchars);
+   /* reals arrays contiguous a/b 8 bytes with no x/z */
+   dp = np->nva.dp;
+   for (i = 0; i < arrw*insts; i++)
+    {
+     *dp++ = 0.0;
+    }
+   __arrvmem_use += totchars;
+   return;
+  }
+
+ /* case 2 non array */
+ np->nva.wp = (word32 *) &(__wtab[__wtabwi]);
+ dp = np->nva.dp;
+ for (i = 0; i < insts; i++) *dp++ = 0.0; 
+ __wtabwi += 2*insts;
+}
+
+/*
+ * allocate all instances for a array var
+ *
+ * notice for now to access must call get packbits - store somewhere
+ * never need to access nva through stu strength union because array cannot
+ * have strength 
+ *
+ * initialization easy since know arrays are registers that are always
+ * initialized to x's
+ * notice this routine is somewhat dependent on 32 bit words
+ */
+extern void __allocinit_arr_var(struct net_t *np, int32 insts,
+ int32 nd_alloc)
+{
+ register int32 i;
+ int32 arrw, wlen, totchars, elwlen, totcells;
+ word32 *rap, mask;
+
+ totchars = 0;
+ /* arrw is number of cells in memory */
+ arrw = __get_arrwide(np);
+ /* case 1, each cell is a scalar */
+ if (!np->n_isavec)
+  {
+   wlen = wlen_(2*arrw*insts);
+   if (nd_alloc)
+    {
+     totchars = WRDBYTES*wlen;
+     np->nva.wp = (word32 *) __my_malloc(totchars);
+     __arrvmem_use += totchars;
+    }
+   /* notice packed densly, index by cell array of 2 bit cells */
+   for (i = 0; i < wlen; i++) np->nva.wp[i] = ALL1W;
+   /* must mask off unused bits in last word32 */
+   np->nva.wp[wlen - 1] &= __masktab[ubits_(2*arrw*insts)];
+   goto done;
+  }
+
+ /* case 2: each cell cannot be packed */
+ if (np->nwid > WBITS/2)
+  {
+   if (nd_alloc)
+    {
+     wlen = arrw*wlen_(np->nwid);
+     totchars = 2*WRDBYTES*insts*wlen;
+     np->nva.wp = (word32 *) __my_malloc(totchars);
+     __arrvmem_use += totchars;
+    }
+
+   /* array is linear array of arrw*insts elements */
+   /* each element has 2 elwlen x (1w) regions */
+   elwlen = wlen_(np->nwid);
+   rap = np->nva.wp;
+   totcells = arrw*insts;
+   for (i = 0;;) 
+    {
+     one_allbits_(rap, np->nwid);
+     rap = &(rap[elwlen]);
+     one_allbits_(rap, np->nwid); 
+     if (++i >= totcells) break; 
+     rap = &(rap[elwlen]);
+    }
+   goto done;
+  }
+ /* case 3a: packs into byte */
+ if (np->nwid <= 4)
+  {
+   /* each cell has 1 byte */
+   if (nd_alloc)
+    {
+     totchars = arrw*insts;
+     np->nva.bp = (byte *) __my_malloc(totchars);
+     __arrvmem_use += totchars;
+    }
+   /* pack into 2 contiguous low bit side sections of byte */
+   mask = __masktab[2*np->nwid];
+   for (i = 0; i < arrw*insts; i++) np->nva.bp[i] = (byte) mask;
+   goto done;
+  }
+ /* case 3b: packs into half word32 */
+ if (np->nwid <= 8)
+  {
+   if (nd_alloc)
+    {
+     totchars = 2*arrw*insts;
+     np->nva.hwp = (hword *) __my_malloc(totchars);
+     __arrvmem_use += totchars;
+    }
+   mask = __masktab[2*np->nwid];
+   for (i = 0; i < arrw*insts; i++) np->nva.hwp[i] = (hword) mask;
+   goto done;
+  }
+ /* case 3c: pcks in word32 */
+ if (nd_alloc)
+  {
+   totchars = 4*arrw*insts;
+   np->nva.wp = (word32 *) __my_malloc(totchars);
+   __arrvmem_use += totchars;
+  }
+ mask = __masktab[2*np->nwid];
+ for (i = 0; i < arrw*insts; i++) np->nva.wp[i] = mask;
+
+done:
+ if (__debug_flg && nd_alloc)
+  {
+   __dbg_msg(
+    "==> array %s: %d insts of %d, %d bit per inst. cells uses %d bytes\n",
+    np->nsym->synam, insts, arrw, np->nwid, totchars);
+  }
+}
+
+/*
+ * allocate all instances for a scalar var
+ * storage here is 2 contiguous bits for a and b value of scalar
+ * needed because eliminates need for unavailable total insts value
+ *
+ * notice important optimization here 1 bit per non strenth scalar,
+ * but selection now takes array access, shift, and and
+ */
+static void alloc_scal_var(struct net_t *np, int32 insts)
+{
+ int32 ival, stval;
+
+ /* variables accessed as section of design wide storage table */
+ np->nva.bp = &(__btab[__btabbi]);
+ __btabbi += insts;
+
+ ival = __get_initval(np, &stval);
+ if (ival == 0L) memset(np->nva.bp, 0, insts);
+ /* initialize net storage */
+ else set_byteval_(np->nva.bp, insts, ival);
+}
+
+/*
+ * determine the initial value and strength for any wire type
+ * stval is entire 8 bit value - ival returned is low 2 bits only
+ * strength format is (st0 (7-5), st1 (4-2), val (1-0) 
+ */
+extern int32 __get_initval(struct net_t *np, int32 *stval)
+{
+ int32 ival, sval;
+
+ switch ((byte) np->ntyp) { 
+  case N_WIRE: case N_TRI: case N_TRIAND: case N_WA: case N_TRIOR: case N_WO:
+   /* normal wires are z (hiz(0),hiz(0), z) */
+   ival = 2; sval = ST_HIZ;
+   break;
+  /* these are normal wires, that have pull0 or pull driver added */  
+  case N_TRI0: ival = 0; sval = ST_PULL0; break; /* <5:5>=0 Pu0 10110100 */
+  case N_TRI1: ival = 1; sval = ST_PULL1; break; /* <5:5>=1 pu1 10110101 */
+  case N_TRIREG:
+   /* even if delay do not schedule decay to z at initialize */
+   ival = 3; 
+   if (np->n_capsiz == CAP_LARGE) sval = 0x93; /* <4:4>=x LaX 10010011 */
+   else if (np->n_capsiz == CAP_SMALL) sval = 0x27; /* <1:1>=x SmX 00100111 */
+   else sval = 0x4b; /* <2:2>=x MeX 01001011 */
+   break;
+  /* <7:7>=1 Su1 ll111101 */
+  case N_SUPPLY1: ival = 1; sval = ST_SUPPLY1; break;
+ /* <7:7>=0 Su0 11111100 */
+  case N_SUPPLY0: ival = 0; sval = ST_SUPPLY0; break;
+  /* register initialized to 0 */
+  case N_REG: case N_INT: case N_TIME: case N_EVENT:
+   ival = 3; sval = 0xdb; /* strength meaningless but <6:6>=X Stx 11011011 */
+   break;
+  default: __case_terr(__FILE__, __LINE__); return(0);
+ } 
+ *stval = sval;
+ return(ival); 
+}
+
+/*
+ * allocate all instances for a strength scalar var
+ * 1 byte per value (low 2 bits value), next 3 bits 1 stren, high 3 0 stren 
+ */
+static void alloc_sscal_var(struct net_t *np, int32 insts)
+{
+ byte *sbp;
+ byte sval;
+ int32 stval;
+
+ /* first allocate the normal 2 bits packed per inst values */
+ /* for sscal 1 byte per instance for strength and value (s000,s111,vv) */
+ __get_initval(np, &stval);
+ /* here byte array value allocated in some words */
+ sbp = &(__btab[__btabbi]);
+ __btabbi += insts;
+ sval = (byte) stval;
+ set_byteval_(sbp, insts, sval);
+ np->nva.bp = sbp;
+}
+
+/*
+ * allocate all instances for a vector variable
+ */
+extern void __allocinit_vec_var(struct net_t *np, int32 insts,
+ int32 nd_alloc)
+{
+ int32 ival, stval;
+ int32 wlen, totchars;
+ word32 maska, maskb;
+
+ ival = __get_initval(np, &stval);
+ maska = maskb = 0L;
+ /* SJM 07/15/00 - no longer pack <16 bit vecs - still pack scalar in byte */ 
+ wlen = wlen_(np->nwid);
+ totchars = 2*WRDBYTES*insts*wlen;
+ if (nd_alloc)
+  {
+   np->nva.wp = &(__wtab[__wtabwi]);
+   __wtabwi += 2*insts*wlen;
+  }
+ switch ((byte) ival) {
+  case 0: memset(np->nva.wp, 0, totchars); return;
+  case 1: maska = 0xffffffffL; break;
+  case 2: maskb = 0xffffffffL; break;
+  case 3: maska = 0xffffffffL; maskb = 0xffffffffL; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ /* initialize net storage */
+ __init_vec_var(np->nva.wp, insts, wlen, np->nwid, maska, maskb);
+}
+
+/*
+ * build a packed mask depending on ival 
+ */
+
+/*
+ * initialize a non strength vector (non packed) to z 
+ */
+extern void __init_vec_var(register word32 *wp, int32 insts, int32 wlen,
+ int32 vecw, word32 maska, word32 maskb)
+{ 
+ register int32 ii, wi;
+ word32 *iwp;
+ int32 ubits;
+
+ /* insts number of <= 1 word32 vectors that each occuppy part of 1 word32 */
+ /* use normal full word32 initialization masks but make sure high bits 0 */
+ if (vecw <= WBITS)
+  {
+   maska &= __masktab[vecw];
+   maskb &= __masktab[vecw];
+   /* for vectors <= WBITS, alternate high 0 masked init values per inst. */
+   for (ii = 0; ii < insts; ii++) { *wp++ = maska; *wp++ = maskb; }
+   return;
+  }
+ ubits = ubits_(vecw);
+ iwp = wp;
+ /* insts number of multiword per vector elements */
+ for (ii = 0; ii < insts; ii++) 
+  {
+   /* for 1 insts's vector value, initial a part */
+   for (wi = 0; wi < wlen; wi++) iwp[wi] = maska;
+   iwp[wlen - 1] &= __masktab[ubits]; 
+
+   /* then b part */
+   for (wi = wlen; wi < 2*wlen; wi++) iwp[wi] = maskb;
+   iwp[2*wlen - 1] &= __masktab[ubits]; 
+   /* finally move iwp to vector location for next inst. */
+   iwp = &(iwp[2*wlen]);
+  }
+}
+
+/*
+ * allocate all instances for a strength vector variable
+ * using byte vector here so total if no. of bits in vec times no. of insts
+ */
+static void alloc_svec_var(struct net_t *np, int32 insts)
+{
+ int32 stval, totbits;
+ byte sval;
+ byte *bp;
+
+ totbits = insts*np->nwid;
+ bp = &(__btab[__btabbi]);
+ __btabbi += totbits;
+
+ __get_initval(np, &stval);
+ sval = (byte) stval;
+ set_byteval_((char *) bp, totbits, sval);
+ np->nva.bp = bp;
+}
+
+/*
+ * routine to re-initialize variables for 1 module
+ *
+ * this just reinits wire/reg value - after dces reinited sets chg action bits
+ */
+extern void __reinitialize_vars(struct mod_t *mdp)
+{
+ register int32 ni;
+ register struct net_t *np;
+ register struct task_t *tskp;
+
+ if (mdp->mnnum == 0) goto do_tasks; 
+ for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+  {
+   /* if any instances any bits in tran channel, need to re-init */
+   /* all hard drivers */ 
+   if (np->ntraux != NULL)
+    {
+     if (np->n_stren)
+      __allocinit_stperival(&np->ntraux->trnva, mdp->flatinum, np, FALSE);
+     else
+      __allocinit_perival(&np->ntraux->trnva, mdp->flatinum, np->nwid, FALSE);
+    }
+   /* need all changed even for event */
+   if (np->ntyp == N_EVENT) continue;
+   reinit_1wirereg(np, mdp);
+  }
+
+do_tasks:
+ for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt) 
+  {
+   if (tskp->trnum == 0) continue;
+   for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+    {
+     if (np->ntyp == N_EVENT) continue;
+     reinit_1wirereg(np, mdp);
+    }
+  }
+}
+
+/*
+ * reinitialize 1 wire or reg
+ */
+static void reinit_1wirereg(struct net_t *np, struct mod_t *mdp)
+{
+ register int32 i;
+ register struct qcval_t *qcvalp;
+ int32 stval, arrw, ival;
+ byte *sbp, sval;
+ double d1;
+ i_tev_ndx *itevpp;
+
+ d1 = 0.0; 
+ /* initialize per bit per inst scheduled event tab if needed */
+ if (np->nrngrep == NX_DWIR)
+  {
+   itevpp = np->nu.rngdwir->wschd_pbtevs;
+   for (i = 0; i < mdp->flatinum*np->nwid; i++) itevpp[i] = -1;
+  }
+ if (np->frc_assgn_allocated)
+  {
+   if (np->ntyp >= NONWIRE_ST)
+    {
+     qcvalp = np->nu2.qcval;
+     /* reset all force/assigns to off and turn off any dces for active */
+     for (i = 0; i < 2*mdp->flatinum; i++, qcvalp++)
+      {
+       qcvalp = &(np->nu2.qcval[i]);
+       if (qcvalp->qc_active)
+        { 
+         /* turn off dces then empty fields by re-initializing record */
+         if (qcvalp->qcdcep != NULL) __dcelst_off(qcvalp->qcdcep); 
+         init_qcval(qcvalp); 
+        }
+       else if (qcvalp->qc_overridden)
+        {
+         /* here fields filled so need to re-init but dces off */
+         init_qcval(qcvalp); 
+        }
+      }
+    }
+   else
+    {
+     /* reset all force/assigns on to off and reinit - no assign of wire */
+     /* forces per bit */
+     for (i = 0; i < np->nwid*mdp->flatinum; i++, qcvalp++)
+      {
+       qcvalp = &(np->nu2.qcval[i]);
+       if (qcvalp->qc_active)
+        { 
+         if (qcvalp->qcdcep != NULL) __dcelst_off(qcvalp->qcdcep); 
+         init_qcval(qcvalp); 
+        }
+      }
+    }
+  }
+ /* reinitialize any pending vpi_put_value records */
+ /* leave the record but change driver to nil and cancel any scheduled tevs */ 
+ if (np->ntyp < NONWIRE_ST)
+  { 
+   if (np->vpi_ndrvs != NULL) __reinit_netdrvr_putvrec(np, mdp);
+   if (np->regwir_putv_tedlst != NULL)
+    __reinit_regwir_putvrec(np, mdp->flatinum);
+  }
+ else 
+  {
+   if (np->regwir_putv_tedlst != NULL)
+    __reinit_regwir_putvrec(np, mdp->flatinum);
+  }
+
+ if (np->ntyp == N_REAL)
+  {
+   if (np->n_isarr)
+    {
+     arrw = __get_arrwide(np);
+     /* LOOKATME - assumes real fits in 8 bytes and WBITS is 32 */
+     for (i = 0; i < arrw*mdp->flatinum; i++)
+      {
+       memcpy(&(np->nva.wp[2*i]), &d1, sizeof(double));
+      }
+     return;
+    }
+   for (i = 0; i < mdp->flatinum; i++)
+    {
+     memcpy(&(np->nva.wp[2*i]), &d1, sizeof(double));
+    } 
+   return;
+  }
+ /* not for real arrays */
+ if (np->n_isarr) { __allocinit_arr_var(np, mdp->flatinum, FALSE); return; }
+ if (!np->n_isavec)
+  {
+   if (!np->n_stren)
+    {
+     ival = __get_initval(np, &stval);
+     if (ival == 0) memset(np->nva.bp, 0, mdp->flatinum);
+     else set_byteval_(np->nva.bp, mdp->flatinum, ival);
+     return;
+    }
+   __get_initval(np, &stval);
+   sbp = np->nva.bp;
+   sval = (byte) stval;
+   set_byteval_(sbp, mdp->flatinum, sval);
+   return;
+  }
+ if (!np->n_stren) { __allocinit_vec_var(np, mdp->flatinum, FALSE); return; }
+ __get_initval(np, &stval);
+ sval = (byte) stval;
+ set_byteval_(np->nva.bp, mdp->flatinum*np->nwid, sval);
+}
+
+/*
+ * initialize all dces (and tchk old vals) in design
+ */
+extern void __initialize_dsgn_dces(void)
+{
+ register struct mod_t *mdp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+   __initialize_dces(__inst_mod);
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * routine to re-initialize dces (and tchk npp old vals) for 1 module
+ *
+ * do not need to (re)initialize npps except path and timing check which have
+ * internal state - normal npp's need processing on any kind of change
+ */
+extern void __initialize_dces(struct mod_t *mdp)
+{
+ register int32 i, ni;
+ register struct net_t *np;
+ register struct net_pin_t *npp;
+ int32 insts;
+ word64 tim0;
+ struct tchg_t *tchgp;
+ struct chktchg_t *chktcp;
+ struct task_t *tskp;
+
+ insts = mdp->flatinum;
+ for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+  {
+   if (np->ntyp == N_EVENT) goto skip_spec;
+
+   /* reinitialize timing check state values - only accessible thru npps */
+   /* if no specify section do not need to go through npp loads list */
+   if (mdp->mspfy != NULL)
+    {
+     tim0 = 0ULL;
+     for (npp = np->nlds; npp != NULL; npp = npp->npnxt) 
+      {
+       if (npp->npntyp != NP_TCHG) continue; 
+
+       switch ((byte) npp->chgsubtyp) {
+        case NPCHG_TCSTART: case NPCHG_PTHSRC:
+         tchgp = npp->elnpp.etchgp;
+         reinit_npp_oldval(tchgp->oldval, np, mdp);
+         for (i = 0; i < insts; i++) tchgp->lastchg[i] = tim0;
+         break;
+        case NPCHG_TCCHK:
+         chktcp = npp->elnpp.echktchgp;
+         reinit_npp_oldval(chktcp->chkoldval, np, mdp);
+         for (i = 0; i < insts; i++) chktcp->chklastchg[i] = tim0;
+         break;
+        default: __case_terr(__FILE__, __LINE__);
+       }
+      }
+    }
+skip_spec:
+   __init_1net_dces(np, mdp);
+  }
+ for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt) 
+  {
+   if (tskp->trnum == 0) continue;
+   for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+    {
+     /* LOOKATME - think need to do this for events too */
+     __init_1net_dces(np, mdp);
+    }
+  }
+}
+
+/*
+ * initialize one net's dces (called faster cver-cc compile and $reset)
+ *
+ * for XMR mdp is the define (target) itree loc since dce on define var
+ * FIXME (OR FINDOUT) - why is algorithm to remove PLI 1.0 vcls
+ * but leave PLI 2.0 val chg cbs
+ */
+extern void __init_1net_dces(struct net_t *np, struct mod_t *mdp)
+{
+ register int32 i;
+ int32 insts;
+ i_tev_ndx *itevpp;
+ struct dcevnt_t *dcep; 
+ struct mod_t *decl_mdp;
+
+ insts = mdp->flatinum;
+ /* must go through setting all dce schedule per inst tables to nil */
+ for (dcep = np->dcelst; dcep != NULL;)
+  {
+   switch (dcep->dce_typ) {
+    case DCE_RNG_INST: case DCE_INST:
+     /* set per inst. schedule table to nil but leave this type of dce */
+     /* not per bit since filter applied to range */
+     /* also for dce forms accessed from ref. not target itree loc. */
+     itevpp = dcep->st_dctrl->dceschd_tevs;
+     /* DBG remove --- */
+     if (itevpp == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     for (i = 0; i < insts; i++) itevpp[i] = -1;
+
+     /* set dce previous values to initial wire value */
+     if (dcep->dce_1inst)
+      {
+       if (dcep->prevval.wp != NULL)
+        {
+         __push_itstk(dcep->dce_matchitp);
+         __init_1instdce_prevval(dcep);
+         __pop_itstk();
+        }
+      }
+     else
+      {
+       if (dcep->dce_expr != NULL) init_dce_exprval(dcep);
+       else
+        {
+         if (dcep->prevval.wp != NULL)
+          {
+           /* 05/18/03 - for XMR there is one for each decl in inst */
+           if (dcep->dce_xmrtyp != XNP_LOC)
+            decl_mdp = dcep->dceu.dcegrp->targmdp;
+           else decl_mdp = __inst_mod;
+           init_dce_prevval(dcep, decl_mdp);
+          }
+        }
+      }
+     break;
+    case DCE_RNG_MONIT: case DCE_MONIT:
+     /* DBG remove -- */
+     if (!dcep->dce_1inst) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+   
+     /* SJM 12/30/02 - since monits can't be removed - only turned off */
+     /* on reset must turn off and initialize to start value */
+     /* previous fix was wrong */
+     dcep->dce_off = TRUE;
+     /* initialize old value as if this was first time - can never be XMR */
+     __push_itstk(dcep->dce_matchitp);
+     __init_1instdce_prevval(dcep);
+     __pop_itstk();
+     break;
+    case DCE_RNG_QCAF: case DCE_QCAF:
+     /* always 1 qca dce load per statement exec */
+     /* never a previous value since better to repeat assign of forced */
+     /* DBG remove --- */
+     if (dcep->prevval.bp != NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     /* 11/22/02 AIV - no longer freeing QCAF dces - turned off instead */
+     /* also no previous value to re-initialize */
+     dcep->dce_off = TRUE;
+     break;
+    case DCE_RNG_PVC: case DCE_PVC:
+     /* DBG remove -- */
+     if (!dcep->dce_1inst) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+
+     /* SJM 01/02/03 - for the dce - always inst specific - just reinit in */
+     /* case has previous value */
+     __push_itstk(dcep->dce_matchitp);
+     __init_1instdce_prevval(dcep);
+     __pop_itstk();
+     break;
+    case DCE_CBVC: case DCE_RNG_CBVC:
+    case DCE_CBF: case DCE_RNG_CBF: case DCE_CBR: case DCE_RNG_CBR:
+     /* DBG remove -- */
+     if (!dcep->dce_1inst) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+
+     /* this handles re-init of PLI 2.0 dce that must be left on */
+     /* know will always exist */  
+     /* LOOKATME - why left on? or why not consistent with PLI 1 */
+     __push_itstk(dcep->dce_matchitp);
+     __alloc_1instdce_prevval(dcep);
+     __pop_itstk();
+     break;
+    /* notice iact never seen here since only enabled from iact stmt */
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   dcep = dcep->dcenxt;
+  }
+}
+
+/*
+ * allocate normal multiple instance case dce prevval
+ * need value for every instance (itree loc. not used)
+ *
+ * 05/07/03 - now separate alloc and initialize
+ */
+static void alloc_dce_prevval(struct dcevnt_t *dcep, struct mod_t *mdp)
+{
+ int32 dcewid, totchars;
+ struct net_t *np;
+
+ np = dcep->dce_np;
+ /* PLI change values always need previous value because >1 change during */ 
+ /* one time slot possible */
+ if (dcep->dce_typ < ST_ND_PREVVAL)
+  {
+   /* no previous value for arrays or non edge entire wire regs */
+   if (np->n_isarr || (np->ntyp >= NONWIRE_ST && dcep->dci1 == -1
+    && !dcep->dce_edge))
+    return;
+  }
+
+
+ /* build old value for wire range change detection */ 
+ dcewid = __get_dcewid(dcep, np);
+ if (np->n_stren)
+  {
+   /* notice this can never be array */
+   dcep->prevval.bp = (byte *) __my_malloc(dcewid*mdp->flatinum);
+  }
+ else
+  {
+   totchars = __get_pcku_chars(dcewid, mdp->flatinum);
+   dcep->prevval.wp = (word32 *) __my_malloc(totchars);
+  }
+}
+
+/*
+ * initialize by setting to current value of wire the dce preval
+ * need value for every instance (itree loc. not used)
+ *
+ * SJM 05/07/03 - now separate alloc and initialize
+ * only called if dce prev val non nil
+ */
+static void init_dce_prevval(struct dcevnt_t *dcep, struct mod_t *decl_mdp)
+{
+ register int32 ii;
+ int32 i1;
+ word32 *wp;
+ byte *sbp, *sbp2, *sbp3;
+ int32 dcewid;
+ struct net_t *np;
+ struct xstk_t *xsp;
+
+ np = dcep->dce_np;
+ /* build old value for wire range change detection */ 
+ dcewid = __get_dcewid(dcep, np);
+ if (np->n_stren)
+  {
+   /* notice this can never be array */
+   sbp = dcep->prevval.bp;
+   if (dcep->dci1 == -2)
+    {
+     /* SJM 10/12/04 - because contab realloced, must be ndx base of IS */
+     wp = &(__contab[dcep->dci2.xvi]);
+     for (ii = 0; ii < decl_mdp->flatinum; ii++)
+      {
+       /* know i1 not -1 since must be 1 bit */
+       i1 =  (int32) wp[2*ii];
+       sbp2 = &(np->nva.bp[np->nwid*ii + i1]);
+       sbp3 = &(sbp[ii*dcewid]);
+       memcpy(sbp3, sbp2, dcewid); 
+      }
+    }
+   else
+    {
+     /* here set every instance */
+     for (ii = 0; ii < decl_mdp->flatinum; ii++)
+      {
+       /* notice start addr. must be low (2nd) index */
+       i1 = (dcep->dci1 == -1) ? 0 : dcep->dci2.i;
+       sbp2 = &(np->nva.bp[np->nwid*ii + i1]);
+       sbp3 = &(sbp[ii*dcewid]);
+       memcpy(sbp3, sbp2, dcewid); 
+      }
+    }
+   return;
+  }
+ push_xstk_(xsp, dcewid);
+ /* dummy itree loc needed so can change inum */
+ __push_wrkitstk(decl_mdp, 0);
+ /* this is impossible for monit form */ 
+ if (dcep->dci1 == -2)
+  {
+   /* SJM 10/12/04 - because contab realloced, must be ndx base of IS */
+   wp = &(__contab[dcep->dci2.xvi]);
+   /* know this is all inst. since monit/iact cannot be -2 form */
+   for (ii = 0; ii < decl_mdp->flatinum; ii++)
+    {
+     /* no need to access mod con table here */
+     __inst_ptr->itinum = ii;
+     __inum = ii;
+     i1 =  (int32) wp[2*ii];
+     __ld_wire_sect(xsp->ap, xsp->bp, np, i1, i1);
+     /* minus 2 form only possible for bit select */
+     st_scalval_(dcep->prevval.bp, xsp->ap[0], xsp->bp[0]);
+    }
+  }
+ else
+  {
+   for (ii = 0; ii < decl_mdp->flatinum; ii++)
+    {
+     /* no need to access mod con table here */
+     __inst_ptr->itinum = ii;
+     __inum = ii;
+     /* notice dci1 will be -1 for entire wire and this handles */ 
+     __ld_wire_sect(xsp->ap, xsp->bp, np, dcep->dci1, dcep->dci2.i);
+     __st_perinst_val(dcep->prevval, dcewid, xsp->ap, xsp->bp);
+    }  
+  }
+ __pop_wrkitstk();
+ __pop_xstk();
+}
+
+/*
+ * initialize dce expr old (expr. not variable) value 
+ *
+ * only called if dce has expr. and this is master (1st) for XMR 
+ *
+ * since expr evaluated in ref XMR loc, module context is referenced module
+ * or XMR case which is set by caller
+ *
+ * SJM 05/06/03 - need to eval and save in ref mod loc XMR dce case
+ * SJM 05/04/05 - notice this 
+ */
+static void init_dce_exprval(struct dcevnt_t *dcep)
+{
+ register int32 ii;
+ struct xstk_t *xsp;
+ struct mod_t *ref_mdp;
+ struct gref_t *grp;
+
+ if (dcep->dce_xmrtyp != XNP_LOC)
+  {
+   if (dcep->dce_xmrtyp == XNP_RTXMR)
+    {
+     ref_mdp = dcep->dce_refitp->itip->imsym->el.emdp;
+    }
+   else
+    {
+     grp = dcep->dceu.dcegrp;
+     ref_mdp = grp->gin_mdp;
+    }
+  }
+ else ref_mdp = __inst_mod;
+
+ /* edges always 1 bit (maybe low of vector) */
+
+ /* LOOKATME - can expr. be evaluated here? probably since can load wire */ 
+ /* need to eval. from initialized wires */
+ /* SJM 05/06/03 - must eval expr in ref loc itree context not define */
+ for (ii = 0; ii < ref_mdp->flatinum; ii++)
+  {
+   __push_itstk(ref_mdp->moditps[ii]);
+   xsp = __eval_xpr(dcep->dce_expr->edgxp);
+   st_scalval_(dcep->dce_expr->bp,
+    (xsp->ap[0] & 1L), (xsp->bp[0] & 1L));
+   __pop_xstk();
+   __pop_itstk();
+  }
+}
+
+/*
+ * allocate one inst form dce
+ *
+ * since called before dce filled, can only allocate - can't initialize
+ * variant for one inst forms - monit and XMR
+ * this also figures out if previous value needed for 1i case
+ */
+extern void __alloc_1instdce_prevval(struct dcevnt_t *dcep)
+{
+ int32 dcewid, totchars;
+ struct net_t *np;
+
+ /* SJM 05/08/03 - dce expr can never be 1 inst - always var and never XMR */
+ /* DBG remove -- */
+ if (dcep->dce_expr != NULL) __misc_terr(__FILE__, __LINE__); 
+ /* --- */
+
+ np = dcep->dce_np;
+
+ /* always need prevval for PLI, multiple change at same time possible */ 
+ if (dcep->dce_typ < ST_ND_PREVVAL)
+  { 
+   /* no previous value for arrays or non edge entire wire regs */
+   /* but needed for all others and always build if nd prev val T */ 
+   if (np->n_isarr || (np->ntyp >= NONWIRE_ST && dcep->dci1 == -1
+    && !dcep->dce_edge)) return;
+  }
+
+ dcewid = __get_dcewid(dcep, np);
+ if (np->n_stren) dcep->prevval.bp = (byte *) __my_malloc(dcewid);
+ else
+  {
+   totchars = __get_pcku_chars(dcewid, 1);
+   dcep->prevval.wp = (word32 *) __my_malloc(totchars);
+  }
+}
+
+/*
+ * initialize and set to current value into dce preval
+ * variant for one inst forms - monit and XMR
+ * SJM 05/07/03 - now only can be called after all of dce filled 
+ *
+ * this routine must be passed declare (target) itree context on top of
+ * inst stack and ref loc 1 under
+ */
+extern void __init_1instdce_prevval(struct dcevnt_t *dcep)
+{
+ byte *sbp, *sbp2;
+ int32 dcewid;
+ struct net_t *np;
+ struct xstk_t *xsp;
+
+ np = dcep->dce_np;
+ /* DBG remove -- */
+ if (dcep->dce_expr != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ if (dcep->prevval.bp == NULL) return;
+
+ dcewid = __get_dcewid(dcep, np);
+ /* SJM 05/08/03 - eval in match context but store as 0 since only 1 inst */
+ __push_itstk(dcep->dce_matchitp);
+ if (np->n_stren)
+  {
+   /* notice this can never be array */
+   sbp = dcep->prevval.bp;
+   /* must load for initialize from right inst. */
+   get_stwire_addr_(sbp2, np);
+   if (dcep->dci1 != -1) sbp2 = &(sbp2[dcep->dci2.i]);
+   memcpy(sbp, sbp2, dcewid);
+  }
+ else
+  {
+   push_xstk_(xsp, dcewid);
+   /* must load value from correct (match_itp instance) on it stack */
+   __ld_wire_sect(xsp->ap, xsp->bp, np, dcep->dci1, dcep->dci2.i);
+
+   /* need dummy place for itree inst num since know only 1 inst. */
+   /* this is match loc but only 1 inst - so any would work */
+   __push_wrkitstk(__inst_mod, 0);
+   __st_perinst_val(dcep->prevval, dcewid, xsp->ap, xsp->bp);
+   __pop_wrkitstk();
+   __pop_xstk();
+  }
+ __pop_itstk();
+}
+
+/*
+ * STATEMENT PREPARATION ROUTINES
+ */
+
+/*
+ * for every always, add surrounding forever statement
+ *
+ * all variable storage must have been allocated by here
+ * all id (and glbid) expression nodes made to point to variable
+ */
+extern void __prep_stmts(void)
+{
+ register int32 i; 
+ register struct ialst_t *ialp; 
+ register struct task_t *tskp;
+ struct mod_t *mdp;
+ int32 sav_declobj;
+
+ /* bottom of if/case/delay control continuation stack must be null */
+ /* for cases where continuation is really NULL - no goto */
+ __prpsti = 0;
+ __nbsti = -1;
+ __prpstk[0] = NULL;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   __prep_numsts = 0;
+   __processing_func = FALSE;
+   for (ialp = __inst_mod->ialst; ialp != NULL; ialp = ialp->ialnxt)
+    {
+     /* for always, must be first - tails of last must point to 1st stmt */
+     /* here may be list and will be put on end */
+     if (ialp->iatyp == ALWAYS)
+      add_loopend_goto(ialp->iastp, ialp->iastp);
+     ialp->iastp = __prep_lstofsts(ialp->iastp, TRUE, FALSE);
+     /* DBG remove --- */
+     if (__prpsti != 0) __misc_terr(__FILE__, __LINE__); 
+     /* --- */
+    }
+   /* notice, there is one set of task variables per instance */
+   /* but a task in one itree inst. can be enabled multiple times */
+   /* tthrds for tasks (not functions) is per inst. list of active thrds */
+   /* so if disable can disable all below */
+   for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     /* never need task threads for function */ 
+     if (tskp->tsktyp == FUNCTION) continue; 
+     tskp->tthrds = (struct tskthrd_t **)
+      __my_malloc(__inst_mod->flatinum*sizeof(struct tskthrd_t *));
+     for (i = 0; i < __inst_mod->flatinum; i++) tskp->tthrds[i] = NULL;
+    }
+  
+   sav_declobj = __cur_declobj;
+   __cur_declobj = TASK;
+   for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     /* named blocks handled as statement where they occur */
+     if (tskp->tsktyp == FUNCTION) __processing_func = TRUE;
+     else if (tskp->tsktyp == TASK) __processing_func = FALSE; 
+     else continue;
+
+     tskp->tskst = __prep_lstofsts(tskp->tskst, FALSE, FALSE);
+     /* no branch continue here because must schedule/disable thread */
+     /* need inform if function never enable */
+     if (!tskp->t_used)
+      {
+       char s1[RECLEN], s2[RECLEN];
+
+       if (__processing_func) strcpy(s2, "called");
+       else strcpy(s2, "enabled"); 
+       __gfinform(439, tskp->tsksyp->syfnam_ind, tskp->tsksyp->sylin_cnt, 
+        "%s %s never %s", __to_tsktyp(s1, tskp->tsktyp), tskp->tsksyp->synam,
+        s2);
+      }
+     /* DBG remove --- */ 
+     if (__prpsti != 0) __misc_terr(__FILE__, __LINE__); 
+     /* --- */
+    }
+   __processing_func = FALSE;
+   __cur_declobj = sav_declobj;
+
+   /* DBG remove --
+   {
+    extern void __dmp_mod(FILE *, struct mod_t *mdp);
+
+    if (__debug_flg) __dmp_mod(stdout, mdp);
+   }
+   --- */   
+   /* DBG remove ---
+   if (__prep_numsts != __inst_mod->mstnum) __misc_terr(__FILE__, __LINE__);
+   --- */
+
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * routine to prepare (optimize) list of statements for simulation
+ * returns front (may be new statement for for)
+ *
+ * know begin ends already turned into statements list wherever possible
+ * know if containing statement is loop, goto added at end before here
+ */
+extern struct st_t *__prep_lstofsts(struct st_t *hdrstp, int32 nd_endgoto,
+ int32 is_dctrl_chain)
+{
+ register struct st_t *stp;
+ register int32 ii;
+ int32 tei, fji;
+ struct for_t *forp;
+ struct st_t *astp, *astp2, *last_stp, *fjstp;
+ struct delctrl_t *dctp;
+
+ for (stp = hdrstp, last_stp = NULL; stp != NULL; stp = stp->stnxt)
+  {
+   __sfnam_ind = stp->stfnam_ind;
+   __slin_cnt = stp->stlin_cnt;
+   /* DBG remove ---
+   if (__debug_flg)
+    {
+     __dbg_msg("%04d: AT %s %s - STMT PREP (%s)\n", stp->stalloc_ndx, 
+      __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt),
+      __inst_mod->msym->synam, __to_sttyp(__xs2, stp->stmttyp));
+    }
+   --- */
+   /* --- ALTERNATE DBG remove ---
+     __dbg_msg("AT %s %s - STMT PREP %04d (%s)\n",
+      __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt),
+      __inst_mod->msym->synam, __prep_numsts - 1,
+      __to_sttyp(__xs2, stp->stmttyp));
+    }
+   --- */ 
+
+   switch ((byte) stp->stmttyp) {
+    case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA: case S_NBPROCA: break;
+    case S_IF:
+     if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+     stp->st.sif.thenst = __prep_lstofsts(stp->st.sif.thenst, TRUE, FALSE);
+     if (stp->st.sif.elsest != NULL)
+      stp->st.sif.elsest = __prep_lstofsts(stp->st.sif.elsest, TRUE, FALSE);
+     if (stp->stnxt != NULL) pop_prpstmt();
+     break;
+    case S_CASE:
+     prep_case(stp);
+     break;
+    case S_FOR:
+     /* must link so old for assign is replaced by for inc. that points */
+     /* to for body (added) - key is that for inc next is not used */ 
+     /* first add goto to for statement itself at end of body */
+     /* notice initial assign already precedes for */
+     forp = stp->st.sfor;
+     astp2 = add_loopend_goto(forp->forbody, forp->forbody);
+     /* change to point to for itself */
+     astp2->stnxt->st.sgoto = stp;
+     astp2->stnxt->st.sgoto->lpend_goto_dest = TRUE;
+
+     /* insert inc stmt before goto */
+     forp->forinc->stnxt = astp2->stnxt;
+     astp2->stnxt = forp->forinc;
+     /* inc will be fixed up in body of loop */
+     forp->forbody = __prep_lstofsts(forp->forbody, FALSE, FALSE);
+     break;
+    case S_FOREVER:
+    case S_WHILE:
+     /* scheme here if evaluation of while means if non NULL xpr see if T */
+     /* if not do not exec statement else exec - loops to same statement */
+     /* something like while (x) begin : y ... end becomes: */
+     /* L: while () begin ... end; goto L; */
+     add_loopend_goto(stp->st.swh.lpst, stp);
+     stp->st.swh.lpst = __prep_lstofsts(stp->st.swh.lpst, FALSE, FALSE);
+     break;
+    case S_REPEAT:
+     /* first allocate special repeat setup statement and link on front */
+     astp = __alloc2_stmt(S_REPSETUP, stp->stfnam_ind, stp->stlin_cnt);
+     /* fill guts of new statement with repeat guts - astp2 pnts to nxt st */
+     *astp = *stp;       
+
+     stp->stmttyp = S_REPSETUP;
+     stp->rl_stmttyp = stp->stmttyp;
+     stp->st_unbhead = FALSE;
+     stp->st.scausx = NULL;
+
+     /* then exchange stp and astp pointers (since prev nxt is stp) */
+     astp2 = astp;
+     astp = stp;
+     stp = astp2;
+     astp->stnxt = stp;
+
+     /* stp now points to rep setup */
+     /* DBG remove --
+     if (__debug_flg)
+      {
+       __dbg_msg("AT %s %s - STMT PREP (%s)\n",
+        __bld_lineloc(__xs, astp->stfnam_ind, astp->stlin_cnt),
+        __inst_mod->msym->synam, __to_sttyp(__xs2, astp->stmttyp));
+      }
+     --- */
+     /* DBG remove --
+     __prep_numsts++;
+     if (__debug_flg)
+      {
+       __dbg_msg("%04d: AT %s %s - STMT PREP (%s)\n", astp->stalloc_ndx,
+        __bld_lineloc(__xs, astp->stfnam_ind, astp->stlin_cnt),
+        __inst_mod->msym->synam, __to_sttyp(__xs2, astp->stmttyp));
+      }
+     --- */
+     /* ALTERNATE DBG remove ---
+     __prep_numsts++;
+     if (__debug_flg)
+      {
+       __dbg_msg("AT %s %s - STMT PREP %04d (%s)\n",
+        __bld_lineloc(__xs, astp->stfnam_ind, astp->stlin_cnt),
+        __inst_mod->msym->synam, __prep_numsts - 1,
+        __to_sttyp(__xs2, astp->stmttyp));
+      }
+     --- */
+     /* allocate per inst. count storage */ 
+     /* add loop back to repeat header */
+     add_loopend_goto(stp->st.srpt.repst, stp);
+     /* 32 bit word32 width built in here */
+     stp->st.srpt.reptemp = (word32 *)
+      __my_malloc(WRDBYTES*__inst_mod->flatinum);
+     memset(stp->st.srpt.reptemp, 0, WRDBYTES*__inst_mod->flatinum);
+     /* end must loop back to actual repeat not setup */
+     stp->st.srpt.repst = __prep_lstofsts(stp->st.srpt.repst, FALSE, FALSE);
+     break;
+    case S_WAIT:
+     /* build and adding dc events is just change expr. case here */
+     dctp = stp->st.swait.wait_dctp;
+     /* must turn on iact bit so linkon dce adds to free list when done */ 
+     if (__iact_state) dctp->dc_iact = TRUE;
+     /* wait is simple expression - EV OR illegal - edge illegal state dep. */
+     bld_evxpr_dces(stp->st.swait.lpx, dctp, FALSE);
+     /* wait @ event triggers on loop exp and executes wait to evaluate */
+     /* the loop expression */
+     dctp->actionst = stp;
+     /* fill the delay/event scheduled action rec that is needed by wait */
+     /* for arming and triggering */
+     dctp->dctyp = DC_WAITEVENT;
+     /* need to alloc and init scheduled tevs table */
+     dctp->dceschd_tevs = (i_tev_ndx *)
+      __my_malloc(__inst_mod->flatinum*sizeof(i_tev_ndx));
+     for (tei = 0; tei < __inst_mod->flatinum; tei++)
+      dctp->dceschd_tevs[tei] = -1;
+
+     /* prepare the statements */ 
+     /* wait needs end link to next statement after wait not beginning */
+     if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+     /* last statement (normally only 1, will have goto to continuation */
+     stp->st.swait.lpst = __prep_lstofsts(stp->st.swait.lpst, TRUE, FALSE);
+     if (stp->stnxt != NULL) pop_prpstmt();
+     break;
+    case S_DELCTRL:
+     dctp = stp->st.sdc;
+     /* 10/28/00 - if repeat form, insert repeat dc setup in front */
+     if (dctp->repcntx != NULL)
+      {
+       /* first allocate special repeat setup statement and link on front */
+       /* this is needed so can insert after to get lists nexts right */
+       /* but still have setup first */
+       astp = __alloc2_stmt(S_REPDCSETUP, stp->stfnam_ind, stp->stlin_cnt);
+       /* fill guts of new statement with  delctrl statment guts */
+       /* astp2 points to next stmt */
+       *astp = *stp;       
+
+       stp->stmttyp = S_REPDCSETUP;
+       stp->rl_stmttyp = stp->stmttyp;
+       stp->st_unbhead = FALSE;
+       stp->st.scausx = NULL;
+
+       /* then exchange stp and astp pointers (since prev nxt is stp) */
+       /* so stp will be at original (after inserted setup) so next works */
+       /* right in loop */
+       astp2 = astp;
+       astp = stp;
+       stp = astp2;
+       astp->stnxt = stp;
+       /* DBG remove */
+       if (stp->st.sdc != dctp) __misc_terr(__FILE__, __LINE__);
+       /* --- */
+       /* finally, alloc and initialize to 0 per inst repeat down counter */ 
+       /* SJM 04/02/01 - inter ectl rep counter now word32 */
+       dctp->dce_repcnts = (word32 *)
+        __my_malloc(sizeof(word32)*__inst_mod->flatinum);
+       memset(dctp->dce_repcnts, 0, sizeof(word32)*__inst_mod->flatinum);
+      }
+     /* 10/28/00 SJM - always still prepare dctrl as usual */
+     prep_dctrl(stp);
+     break;
+    case S_NAMBLK:
+     /* for named block, no continuation - must be subthread except in func */
+     __push_nbstk(stp);
+     if (__processing_func)
+      { 
+       if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+       stp->st.snbtsk->tskst = __prep_lstofsts(stp->st.snbtsk->tskst,
+        TRUE, FALSE);
+       if (stp->stnxt != NULL) pop_prpstmt();
+      }
+     else
+      {
+       push_prpstmt((struct st_t *) NULL);
+       stp->st.snbtsk->tskst = __prep_lstofsts(stp->st.snbtsk->tskst, FALSE,
+        FALSE);
+       pop_prpstmt();
+      }
+     __pop_nbstk();
+     break;
+    case S_UNBLK:
+     if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+     /* need continuation for simple block */
+     stp->st.sbsts = __prep_lstofsts(stp->st.sbsts, TRUE, FALSE);
+     if (stp->stnxt != NULL) pop_prpstmt();
+     break;
+    case S_UNFJ:
+     push_prpstmt((struct st_t *) NULL);
+     /* continuation inside these must be NULL, not stacked val */
+     for (fji = 0;; fji++)
+      {
+       if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+       stp->st.fj.fjstps[fji] = __prep_lstofsts(fjstp, FALSE, FALSE);
+      }
+     pop_prpstmt();
+     break;
+    case S_QCONTA:
+     /* first build the one for each lhs cat element list of per inst */
+     /* qcaf dce lists and initialize - then during build just fill */
+     bld_init_qcaf_dce_lstlst(stp);
+
+     /* separate prepare because different qcval record for each inst */
+     /* qcaf dces per inst because only one active on a reg at a time */
+     for (ii = 0; ii < __inst_mod->flatinum; ii++)
+      {
+       __push_itstk(__inst_mod->moditps[ii]);
+
+       if (stp->st.sqca->qcatyp == ASSIGN) prep_qc_assign(stp, FALSE);
+       else
+        {
+         /* force of reg, is like assign except overrides assign */
+         if (stp->st.sqca->regform) prep_qc_assign(stp, TRUE);
+         else prep_qc_wireforce(stp);
+        }
+       __pop_itstk();
+      }
+     break;
+    case S_QCONTDEA:
+     for (ii = 0; ii < __inst_mod->flatinum; ii++)
+      {
+       __push_itstk(__inst_mod->moditps[ii]);
+
+       if (stp->st.sqcdea.qcdatyp == DEASSIGN) prep_qc_deassign(stp);
+       else
+        {
+         /* SJM 06/21/02 - since deassign/release just allocs qcvals */
+         /* no diff between release/deassign */
+         if (stp->st.sqcdea.regform) prep_qc_deassign(stp);
+         else prep_qc_wirerelease(stp);
+        } 
+       __pop_itstk();
+      } 
+     break;
+    case S_DSABLE:
+     /* inside function disables are gotos to next statement in up block */
+     if (__processing_func) prep_func_dsable(stp);
+
+     /* since for any other name block or task cannot optimize since can */
+     /* be disabled from interactive command */ 
+     break;
+    case S_TSKCALL:
+     /* identify and build dces only for monit/fmonit here */
+     prep_stskcalls(stp);
+     break;
+   }
+   last_stp = stp;
+  }
+ /* now at end of list */
+ /* fix up by working up stack to point where statement has next */
+ if (nd_endgoto && __prpstk[__prpsti] != NULL) 
+  {
+   /* DBG remove ---*/
+   if (last_stp == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* need to save cur location so allocate get right stmt loc */ 
+   astp = __alloc2_stmt(S_GOTO, last_stp->stfnam_ind, last_stp->stlin_cnt);
+   astp->st.sgoto = __prpstk[__prpsti];
+
+   if (is_dctrl_chain) astp->dctrl_goto = TRUE;
+   else astp->lstend_goto = TRUE;
+
+   /* in this rare case will not have line number - can it happen */
+   /* LOOKATME - can this happen */ 
+   if (last_stp == NULL) hdrstp = astp;
+   else
+    {
+     last_stp->stnxt = astp;
+    }
+   /* DBG remove --
+   __prep_numsts++;
+   if (__debug_flg)
+    {
+     __dbg_msg("AT %s %s - STMT PREP %04d (s)\n",
+      __bld_lineloc(__xs, astp->stfnam_ind, astp->stlin_cnt),
+      __inst_mod->msym->synam, __prep_numsts - 1,
+      __to_sttyp(__xs2, astp->stmttyp));
+    }
+   --- */
+   /* ALTERNATE DBG remove --
+   __prep_numsts++;
+   if (__debug_flg)
+    { 
+     __dbg_msg("AT %s %s - STMT PREP %04d (s)\n",
+      __bld_lineloc(__xs, astp->stfnam_ind, astp->stlin_cnt),
+      __inst_mod->msym->synam, __prep_numsts - 1,
+      __to_sttyp(__xs2, astp->stmttyp));
+    }
+   -- */
+  }
+ return(hdrstp);
+}
+
+/*
+ * prepare sys task enable - only for monit/fmonit and builds dces for those
+ *
+ * SJM 06/21/02 - new algorithm builds monit/fmonit dces during prep
+ */
+static void prep_stskcalls(struct st_t *stp)
+{
+ struct expr_t *tkxp;
+ struct tskcall_t *tkcp;
+ struct sy_t *syp;
+ struct systsk_t *stbp;
+
+ tkcp = &(stp->st.stkc);
+ tkxp = tkcp->tsksyx;
+
+ /* nothing to do for non system task calls */
+ if (tkxp->optyp == ID && *(tkxp->lu.sy->synam) == '$')
+  {
+   syp = tkxp->lu.sy;
+   stbp = syp->el.esytbp;
+
+   switch (stbp->stsknum) {
+    /* system task args do not have type or width - take what is there */
+    case STN_MONITOR: case STN_MONITORB: case STN_MONITORH: case STN_MONITORO:
+     __prep_insrc_monit(stp, FALSE);
+     break;
+    /* tasks that take a multichannel descriptor followed by anything */
+    case STN_FMONITOR: case STN_FMONITORB: case STN_FMONITORH:
+    case STN_FMONITORO:
+     __prep_insrc_monit(stp, TRUE);
+     break;
+    default: break;
+   }
+  }
+}
+
+/*
+ * for list of statements that is loop body, add goto that links
+ * back to front of loop
+ * returns previous last statement - error to be called withh begstp nul
+ */
+static struct st_t *add_loopend_goto(struct st_t *begstp,
+ struct st_t *targstp)
+{
+ register struct st_t *stp; 
+ struct st_t *last_stp, *gtstp;
+
+ /* DBG remove --- */
+ if (begstp == NULL) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* find last statement in loop - know has at least one */
+ for (stp = begstp, last_stp = NULL; stp != NULL; stp = stp->stnxt)
+  last_stp = stp;
+ if (last_stp == NULL) __arg_terr(__FILE__, __LINE__);
+ gtstp = __alloc2_stmt(S_GOTO, last_stp->stfnam_ind, last_stp->stlin_cnt);
+ gtstp->lpend_goto = TRUE;
+ gtstp->st.sgoto = targstp;
+ targstp->lpend_goto_dest = TRUE;
+
+ gtstp->stfnam_ind = last_stp->stfnam_ind;
+ gtstp->stlin_cnt = last_stp->stlin_cnt;
+ last_stp->stnxt = gtstp;
+ if (__debug_flg)
+  {
+   char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+   __dbg_msg("++ loop: adding goto after %s at %s back to stmt %s at %s\n",
+    __to_sttyp(s1, last_stp->stmttyp), __bld_lineloc(__xs, 
+    last_stp->stfnam_ind, last_stp->stlin_cnt), __to_sttyp(s2,
+    begstp->stmttyp), __bld_lineloc(s3, targstp->stfnam_ind,
+    targstp->stlin_cnt));
+  }
+ /* --- */
+ return(last_stp);
+}
+
+/*
+ * push a nested preparation statement
+ * this is for control flow so many not pushed
+ */
+static void push_prpstmt(struct st_t *stp)
+{
+ if (++__prpsti >= MAXPRPSTNEST)
+  __sgfterr(317, "statements nested too deeply (%d)", MAXPRPSTNEST);
+ __prpstk[__prpsti] = stp;
+ /* DBG remove --
+ if (__debug_flg)
+  {
+   if (stp != NULL)
+    {
+     __dbg_msg(".. push nested stmt stack to %d at %s\n", __prpsti,
+      __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt));
+    }
+   else
+    {  
+     __dbg_msg(".. push NULL nested stmt stack to %d\n", __prpsti);
+    }
+  }
+ --- */
+}
+
+/*
+ * pop a nested preparation statement
+ */
+static void pop_prpstmt(void)
+{ 
+ /* should never undeflow */
+ if (__prpsti < 0) __misc_sgfterr(__FILE__, __LINE__);
+ __prpsti--;
+ /* DBG remove --
+ if (__debug_flg)
+  {
+   struct st_t *stp;
+
+    stp = __prpstk[__prpsti];
+    if (stp != NULL)
+     {
+      __dbg_msg(".. pop nested stmt stack to %d at %s\n", __prpsti,
+       __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt));
+     }
+    else
+     {  
+      __dbg_msg(".. pop NULL nested stmt stack to %d\n", __prpsti);
+     }
+  }
+ --- */
+}
+
+/*
+ * push a nested named block statement - this is for disable processing
+ * and only used during preparation
+ */
+extern void __push_nbstk(struct st_t *stp)
+{
+ if (++__nbsti >= MAXPRPSTNEST)
+  __sgfterr(318, "named blocks nested too deeply (%d)", MAXPRPSTNEST);
+ __nbstk[__nbsti] = stp;
+}
+
+/*
+ * pop a nested named block statement
+ */
+extern void __pop_nbstk(void)
+{ 
+ /* named blocks during prep. also should not undeflow */
+ if (__nbsti < 0) __misc_sgfterr(__FILE__, __LINE__);
+ __nbsti--;
+}
+
+/*
+ * prepare case statement for simulation
+ */
+static void prep_case(struct st_t *stp)
+{
+ register struct csitem_t *csip;
+ struct csitem_t *dflt_csip;
+
+ if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+
+ dflt_csip = stp->st.scs.csitems;
+ /* this will move up stack to add goto after ending stp */
+ for (csip = dflt_csip->csinxt; csip != NULL; csip = csip->csinxt)
+  csip->csist = __prep_lstofsts(csip->csist, TRUE, FALSE);
+
+ /* this will move up stack to connect ending stnxt to next exec. place */
+ if (dflt_csip->csist != NULL)
+  dflt_csip->csist = __prep_lstofsts(dflt_csip->csist, TRUE, FALSE);
+ if (stp->stnxt != NULL) pop_prpstmt();
+}
+
+/*
+ * prepare a declare control
+ * tricky because #<> #<> #<> etc [stmt] legal
+ */
+static void prep_dctrl(struct st_t *stp)
+{
+ register struct st_t *stp2;
+ struct delctrl_t *dctp;
+ struct st_t *last_stp;
+
+ dctp = stp->st.sdc;
+ if (__iact_state) dctp->dc_iact = TRUE;
+ cnv_cmpdctl_todu(stp, dctp);
+ /* if no statement just prepare expr. - stnxt correct */
+ if (dctp->actionst == NULL) return;
+
+ /* for #[d1] #[d2] #[d3] ... <stmt> chain, add goto to end only */ 
+ last_stp = NULL;
+ for (stp2 = dctp->actionst;; stp2 = stp2->st.sdc->actionst)
+  {
+   /* keep going until delay control has no action statement or */
+   /* a non delay control action statement */
+   /* case "#10 begin #20 ..." - is not delay control chain */
+   if (stp2 == NULL || stp2->stmttyp != S_DELCTRL || stp2->st_unbhead)
+    break;
+   dctp = stp2->st.sdc;
+   cnv_cmpdctl_todu(stp2, dctp);
+
+/* DBG remove --
+   if (__debug_flg)
+    {
+     __dbg_msg("AT %s %s - STMT PREP %04d (%s)\n",
+      __bld_lineloc(__xs, stp2->stfnam_ind, stp2->stlin_cnt),
+      __inst_mod->msym->synam, __to_sttyp(__xs2, stp2->stmttyp));
+    }
+--- */
+
+   last_stp = stp2;
+  }
+ if (stp2 == NULL)
+  {
+   __sgfwarn(562, "INTERNAL - delay control chain does not end with stmt.");
+   /* unrecognized delay control chain */
+   if (last_stp == NULL) __misc_terr(__FILE__, __LINE__);
+   stp2 = last_stp;
+  }
+ /* finally, just add goto from stp2 to original statement next */
+ if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+ stp2 = __prep_lstofsts(stp2, TRUE, TRUE);
+ if (stp->stnxt != NULL) pop_prpstmt();
+}
+
+/*
+ * convert a delay control CMP LST form to run tim delay 
+ */
+static void cnv_cmpdctl_todu(struct st_t *stp, struct delctrl_t *dctp)
+{
+ register int32 tei;
+ struct gate_t gwrk;
+ struct sy_t tmpsym;
+
+ /* notice for delay controls schd event tevs field not used */
+ if (dctp->dctyp == DC_DELAY || dctp->dctyp == DC_RHSDELAY)
+  {
+   __add_dctldel_pnp(stp); 
+   tmpsym.syfnam_ind = (word32) __sfnam_ind;
+   tmpsym.sylin_cnt = __slin_cnt;
+   __prep_delay(&gwrk, dctp->dc_du.pdels, FALSE, FALSE,
+    "procedural delay control", FALSE, &tmpsym, FALSE);
+   if (__nd_neg_del_warn)
+    {
+     __sgferr(974, "delay control negative delay illegal (0 used)");
+     __nd_neg_del_warn = FALSE;
+    } 
+   dctp->dc_delrep = gwrk.g_delrep;
+   dctp->dc_du = gwrk.g_du;
+  }
+ else
+  {
+   prep_event_dctrl(dctp);
+   /* need to alloc and init scheduled tevs table */
+   dctp->dceschd_tevs = (i_tev_ndx *)
+    __my_malloc(__inst_mod->flatinum*sizeof(i_tev_ndx));
+   for (tei = 0; tei < __inst_mod->flatinum; tei++)
+    dctp->dceschd_tevs[tei] = -1L;
+  }
+}
+
+/*
+ * for every value in expr. add the dc list to appropriate wire 
+ */
+static void prep_event_dctrl(struct delctrl_t *dctp)
+{
+ register struct expr_t *xp;
+ struct expr_t *evx;
+ struct paramlst_t *pmp;
+
+ /* must change delay representation to DT_1X */
+ pmp = dctp->dc_du.pdels;
+ evx = pmp->plxndp;
+ /* first free param list form */
+ __my_free((char *) pmp, sizeof(struct paramlst_t));
+ dctp->dc_du.d1x = evx;
+ dctp->dc_delrep = DT_1X;
+
+ /* SJM 06/28/05 - for degenerate form no dces to build but must catch */  
+ /* nil event expr */
+ if (evx == NULL)
+  {
+   __sgfwarn(3139,
+    "implicit event control - no events in statement - will never trigger");
+   return;
+  }
+
+ if (evx->optyp != OPEVOR && evx->optyp != OPEVCOMMAOR)
+  { bld_ev_dces(evx, dctp); return; }
+ /* notice evor tree must associate left to right - i.e. evor chain */
+ /* extends down left links */
+ for (xp = evx;;) 
+  {
+   bld_ev_dces(xp->ru.x, dctp);
+   if (xp->lu.x->optyp != OPEVOR && xp->lu.x->optyp != OPEVCOMMAOR)
+    {
+     /* left is bottom of tree */
+     bld_ev_dces(xp->lu.x, dctp);
+     break;
+    }
+   xp = xp->lu.x;
+  }
+}
+
+/*
+ * build the event control dcevnt list element(s) for one event control 
+ *
+ * know xp is not evor - main expr of operand of evor or wait simple expr
+ * this cannot assume any itree loc. 
+ *
+ * for constant bit select, ID, or global do not need expr.
+ * otherwise use normal variable in expr. change mechanism but before 
+ * triggering armed evaluate expression and see if correct edge
+ * aux dce_expr record contains previous entire expr. value
+ */
+static void bld_ev_dces(struct expr_t *xp, struct delctrl_t *dctp)
+{
+ int32 biti, bitj, e_val;
+ word32 *wp;
+ struct net_t *np;
+ struct expr_t *endp, *ndx, *idndp;
+ struct gref_t *grp;
+
+ __cur_dce_expr = NULL;
+ /* know evor must be at top and associates right (right tree) */
+ e_val = NOEDGE; 
+ if (xp->optyp == OPNEGEDGE || xp->optyp == OPPOSEDGE)
+  {
+   if (xp->optyp == OPNEGEDGE) e_val = E_NEGEDGE;
+   else if (xp->optyp == OPPOSEDGE) e_val = E_POSEDGE;
+   else __case_terr(__FILE__, __LINE__);
+
+   endp = xp->lu.x;
+   biti = bitj = -1;
+   if (endp->optyp == LSB)
+    {
+     idndp = endp->lu.x;
+     np = idndp->lu.sy->el.enp; 
+     /* array never scalared and if not scalared need dce expr eval */
+     /* this will force expr eval for array index (not bsel) */
+     if (!np->vec_scalared) goto expr_edge;
+
+     ndx = endp->ru.x;
+     if (ndx->optyp == NUMBER)
+      {
+       /* this can be reg constant out of range of x */
+       /* becomes entire range */
+       wp = &(__contab[ndx->ru.xvi]);
+       if (wp[1] == 0L) biti = bitj = (int32) wp[0];
+      }
+     else if (ndx->optyp == ISNUMBER)
+      {
+       __isform_bi_xvi = ndx->ru.xvi;
+       biti = -2;
+       bitj = 0;
+      }
+     else goto expr_edge;
+    }
+   else if (endp->optyp == ID || endp->optyp == GLBREF)
+    {
+     idndp = endp;
+     np = idndp->lu.sy->el.enp;
+     /* since using low bit only vectored wire do not need expr. */
+     /* unindexed array illegal in rhs expr. */
+    }
+   else goto expr_edge;
+
+   grp = (idndp->optyp == GLBREF) ? idndp->ru.grp : NULL; 
+   linkon_dce(np, biti, bitj, dctp, e_val, grp);
+   return;
+
+expr_edge:
+   __cur_dce_expr = (struct dce_expr_t *)
+    __my_malloc(sizeof(struct dce_expr_t));
+   __cur_dce_expr->edgxp = endp; 
+   __cur_dce_expr->bp = NULL;
+   __cur_dce_expr->mast_dcep = NULL; 
+   /* this will set global dce expr for each allocated in bld routine */
+   bld_evxpr_dces(xp, dctp, e_val);
+   __cur_dce_expr = NULL;
+   return;
+  }
+
+ /* LOOKATME - slight bug here - trigger on variable change */
+ /* instead of expression change - rare (eval. to 1 bit logical mostly) */
+ /* cases where there is a difference (sending question to P1364 committee */
+ /* allocate for every variable including indices in expr. */
+
+ bld_evxpr_dces(xp, dctp, FALSE);
+}
+
+/*
+ * build and link on dce vents for 1 normal not evor expression but can be
+ * many dces since 1 per variable for non edge expr. that is handled here
+ * need itree place since called while running
+ */
+static void bld_evxpr_dces(struct expr_t *xp, struct delctrl_t *dctp,
+ int32 eval)
+{
+ struct net_t *np;
+ int32 biti, bitj;
+ word32 *wp;
+ struct expr_t *idndp, *ndx;
+ struct gref_t *grp;
+
+ switch ((byte) xp->optyp) {
+  case GLBREF:
+   idndp = xp; 
+   np = xp->lu.sy->el.enp;
+   linkon_dce(np, -1, -1, dctp, eval, idndp->ru.grp);
+   break;
+  case ID:
+   idndp = xp; 
+   np = xp->lu.sy->el.enp;
+   linkon_dce(np, -1, -1, dctp, eval, (struct gref_t *) NULL);
+   break;
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   break;
+  case LSB:
+   /* SJM - 07/02/00 - arrays also here if constant index makes range form */
+   idndp = xp->lu.x; 
+   np = idndp->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   biti = bitj = -1;
+   if (ndx->optyp == NUMBER)
+    {
+     /* know if out of range or x/z - will be all x value */
+     wp = &(__contab[ndx->ru.xvi]);
+     if (wp[1] == 0L) biti = bitj = (int32) wp[0];
+    }
+   else if (ndx->optyp == ISNUMBER)
+    {
+     __isform_bi_xvi = ndx->ru.xvi;
+     biti = -2;
+     bitj = 0;
+    }
+   else
+    {
+     /* notice for monitor and dctrl event change, variable here is legal */
+     /* and implies change for index and trigger on all bits of variable */
+     bld_evxpr_dces(ndx, dctp, eval);
+    }
+   /* SJM - 07/03/00 - for arrays need index, i.e. value but not array */
+   /* index scalared - works since no way to refer to both bit and index */
+   if (biti != -1 && !np->n_isarr && !np->vec_scalared) biti = bitj = -1;
+   grp = (idndp->optyp == GLBREF) ? idndp->ru.grp : NULL; 
+   linkon_dce(np, biti, bitj, dctp, eval, grp);
+   break;
+  case PARTSEL:
+   idndp = xp->lu.x; 
+   np = idndp->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   /* know part select never IS, will not get here if x/z or out of rng */
+   biti = __contab[ndx->lu.x->ru.xvi];
+   bitj = __contab[ndx->ru.x->ru.xvi];
+   if (!np->vec_scalared) biti = bitj = -1;
+   grp = (idndp->optyp == GLBREF) ? idndp->ru.grp : NULL; 
+   linkon_dce(np, biti, bitj, dctp, eval, grp);
+   break;
+  case FCALL:
+   {
+    register struct expr_t *fax;
+
+    /* if any args of system or user functions chg, monitor triggers */
+    /* notice $time function do not have arguments */
+    for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+     bld_evxpr_dces(fax->lu.x, dctp, eval);
+   }
+   break;
+  case LCB:
+   {
+    register struct expr_t *fax;
+
+    for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+     bld_evxpr_dces(fax->lu.x, dctp, eval);
+   }
+   break;
+  default:
+   if (xp->lu.x != NULL) bld_evxpr_dces(xp->lu.x, dctp, eval);
+   if (xp->ru.x != NULL) bld_evxpr_dces(xp->ru.x, dctp, eval);
+   break;
+ } 
+}
+
+/*
+ * for dces: to move from expr. reference to target where var. stored 
+ *  -- if xmr, xmr ref. to target by calling xmrpush refgrp to targ(grp)
+ *     [notice np is right but itree loc. wrong]
+ * to move from target variable location back to expr. ref.
+ *  -- if xmr, xmr target to ref cal xmrpush targ to ref(xmrtyp, npu1)
+ */
+
+/*
+ * link the delay event control element for wire np
+ * this builds the dcelst on np that is never removed  
+ *
+ * when called __inst_mod is module ref. in, (not declare in target)
+ * and np is wire possibly xmr target but not itree context only mod here
+ * if ref. expr is xmr, grp non nil 
+ */
+static void linkon_dce(struct net_t *np, int32 biti, int32 bitj,
+ struct delctrl_t *dctp, int32 e_val, struct gref_t *grp)
+{
+ struct dcevnt_t *dcep;
+
+ /* case 1: all xmr cases including xmr target */
+ /* notice because of preprocessing never need 2 steps from target to ref */
+ if (grp != NULL)
+  {
+   xmr_linkon_dce(np, biti, bitj, dctp, e_val, grp);
+   return;
+  }
+ /* case 2: simple in module */
+ dcep = linkon2_dce(np, biti, bitj, dctp, e_val, FALSE, __inst_mod,
+  __inst_mod);
+ dcep->dce_xmrtyp = XNP_LOC;
+ if (dctp->dc_iact) init_iact_dce(dcep, dctp, NULL);
+}
+
+/*
+ * initialize interactive only dces 
+ * 
+ * expects inst mod to be set to module where net declared in
+ * SJM 01/14/03 - LOOKATME - think there is reason need to pass grp
+ *
+ * SJM 05/04/05 - because putting var storage (np.nva) in .bss section
+ * for cver-cc, this is only for interactive init using interpreter
+ * after linking in .bss .so lib var values, now initializing by net in mod
+ */
+static void init_iact_dce(struct dcevnt_t *dcep, struct delctrl_t *dctp,
+ struct gref_t *grp)
+{
+ struct net_t *np;
+ struct dceauxlst_t *dclp;
+ struct mod_t *decl_mdp;
+
+ np = dcep->dce_np;
+ /* SJM 05/08/03 - not that dce filled can initialize with proper handling */
+ /* of XMRs and interactive cases */
+ if (dcep->dce_1inst)
+  { 
+   if (dcep->prevval.wp != NULL)
+    {
+     __push_itstk(dcep->dce_matchitp);
+     __init_1instdce_prevval(dcep);
+     __pop_itstk();
+    }
+  }
+ else
+  {
+   if (dcep->dce_expr != NULL) init_dce_exprval(dcep);
+   else
+    {
+     if (dcep->prevval.wp != NULL)
+      {
+       /* 05/18/03 - for XMR there is one for each decl in inst */
+       if (dcep->dce_xmrtyp != XNP_LOC) decl_mdp = dcep->dceu.dcegrp->targmdp;
+       else decl_mdp = __inst_mod;
+       init_dce_prevval(dcep, decl_mdp);
+      }
+    }
+  }
+ if (dctp->dc_iact)
+  {
+   /* add to iact list for this statement - will be linked to hctrl */  
+   dclp = (struct dceauxlst_t *) __my_malloc(sizeof(struct dceauxlst_t));
+   dclp->ldcep = dcep; 
+   dclp->dclnxt = __iact_dcehdr;
+   __iact_dcehdr = dclp;
+   /* SJM 05/03/03 - LOOKATME - think iact XMR event controls converted */
+   /* to per inst.  is that true? */
+   dcep->iact_itp = __inst_ptr;
+
+   /* since no dce, no loads, and no dmpvars must always turn chg store on */
+   if (!np->nchg_nd_chgstore)
+    {
+     /* this also turn regen of net's decl iops from dce if -O on */
+     __dce_turn_chg_store_on(__inst_mod, dcep, TRUE);  
+    }
+   /* SJM 04/14/04 - even if need chg store if dumpvars in future but that */
+   /* can happen if need only has dce added from iact code and dumpvars */
+   np->nchg_has_dces = TRUE;
+  }
+}
+
+/*
+ * routine to handle all cases where dce expr. is xmr (global ref. expr)
+ * ref. in module __inst_mod - these all always one instance forms
+ * notice all rooted dce xmrs are 1inst forms also npps
+ */
+static void xmr_linkon_dce(struct net_t *np, int32 biti, int32 bitj,
+ struct delctrl_t *dctp, int32 e_val, struct gref_t *grp)
+{
+ register int32 ii;
+ struct dcevnt_t *dcep;
+ struct itree_t *itp;
+ struct mod_t *ref_mdp;
+
+ /* handle xmr */
+ if (!grp->is_rooted)
+  {
+   /* SJM 05/04/03 - for non rooted where need prev. val, must set */
+   /* module instance context for any instance such as inst 0 */
+   /* (many instance and do not need to know here) */
+   dcep = linkon2_dce(np, biti, bitj, dctp, e_val, FALSE, grp->gin_mdp,
+    grp->targmdp);
+
+   if (grp->upwards_rel)
+    { dcep->dceu.dcegrp = grp; dcep->dce_xmrtyp = XNP_UPXMR; }
+   /* downward case */
+   else { dcep->dceu.dcegrp = grp; dcep->dce_xmrtyp = XNP_DOWNXMR; }
+   /* SJM 05/08/03 - now initialize only after complete dce built */
+   if (dctp->dc_iact) init_iact_dce(dcep, dctp, grp);
+   return;
+  }
+
+ /* rooted xmr handled here */
+ for (ii = 0; ii < __inst_mod->flatinum; ii++)
+  {
+   /* itp is itree loc. of xmr reference */
+   itp = __inst_mod->moditps[ii]; 
+   /* reference itree loc. */
+   __push_itstk(itp);
+   ref_mdp = __inst_ptr->itip->imsym->el.emdp;
+   /* xmr target (declared in) */
+   __xmrpush_refgrp_to_targ(grp);
+   /* SJM 05/06/03 - BEWARE - TOS must be def (targ) and TOS-1 must be ref */ 
+   dcep = linkon2_dce(np, biti, bitj, dctp, e_val, TRUE, ref_mdp, __inst_mod);
+   /* if one inst form needs xmr target (where wire decled) itree loc */
+   dcep->dce_1inst = TRUE; 
+   /* match is target itree loc */
+   dcep->dce_matchitp = __inst_ptr;
+   __pop_itstk();
+   dcep->dce_refitp = __inst_ptr;
+   /* SJM 05/07/03 - must set as rooted dce XMR */ 
+   __pop_itstk();
+   dcep->dce_xmrtyp = XNP_RTXMR;
+
+   /* SJM 05/08/03 - now initialize only after complete dce built */
+   if (dctp->dc_iact) init_iact_dce(dcep, dctp, grp);
+  }
+}
+
+/*
+ * actually link on event dce - other routines for monitor and dumpvars 
+ * created dce is returned
+ *
+ * assumes inst mod set to declared in module context 
+ *
+ * if oninst, know the itree context of the one inst targed (declared in) set
+ * this allocates any old value storage but does not initialize it 
+ *
+ * SJM 05/07/03 - now since caller for XMR sets some dce fields must only 
+ * set fields here, can't call routines that use dce fields
+ * this was cause of most of the XMR event control dce bugs
+ */
+static struct dcevnt_t *linkon2_dce(struct net_t *np, int32 biti, int32 bitj,
+ struct delctrl_t *dctp, int32 e_val, int32 oneinst, struct mod_t *ref_mdp,
+ struct mod_t *decl_mdp)
+{
+ struct dcevnt_t *dcep;
+ struct dceauxlst_t *dclp;
+
+ /* allocate, init, and fill the fields */
+ dcep = __alloc_dcevnt(np);
+
+ /* if unused for non complicated edge expression will be nil */ 
+ if (__cur_dce_expr != NULL)
+  {
+   dcep->dce_expr = __cur_dce_expr;
+   /* DBG remove -- */
+   if (dcep->dce_1inst) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   
+   /* notice for dce expr, old value only for each ref inst since */
+   /* must eval expr in ref inst */
+   if (__cur_dce_expr->mast_dcep == NULL)
+    {
+     __cur_dce_expr->mast_dcep = dcep; 
+     dcep->dce_expr->bp = (byte *) __my_malloc(ref_mdp->flatinum);
+    }
+  }
+
+ if (biti == -1) dcep->dce_typ = DCE_INST;
+ else
+  {
+   dcep->dce_typ = DCE_RNG_INST;
+   dcep->dci1 = biti;
+   if (biti == -2)
+    {
+     /* for one inst. form must access -2 form to actual index */
+     /* because know itree context pushed for one inst - from now on not IS */
+     if (oneinst)
+      {
+       /* SJM 10/12/04 - because contab is realloc must be index */
+       dcep->dci1 = dcep->dci2.i = __contab[__isform_bi_xvi + 2*__inum];
+      }
+     /* since correct for direction here will be right bits */
+     /* has normal user error of connecting opposite direction bus problem */
+     else dcep->dci2.xvi = __isform_bi_xvi;
+    }  
+   else dcep->dci2.i = bitj;
+  }
+ /* 07/01/00 - just added a dce - also need change store */
+ /* 07/24/00 - has dces only on if reg for immediate propagate/wakeup */
+ /* but recording bits set after here */
+ if (!dctp->dc_iact)
+  {
+   if (np->ntyp >= NONWIRE_ST) np->nchg_has_dces = TRUE;
+   np->nchg_nd_chgstore = TRUE;
+  }  
+
+ /* link onto front of d ctrl list for np */
+ dcep->dcenxt = np->dcelst;
+ np->dcelst = dcep;
+ dcep->st_dctrl = dctp;
+ if (e_val != NOEDGE)
+  {
+   dcep->dce_edge = TRUE;
+   dcep->dce_edgval = (word32) e_val;
+  }
+ /* if has edge needs per inst. old value table for last value */
+ /* if oneinst know right itree loc. set */
+ /* SJM 05/09/03 - if have 1 bit edge expr, previous value not needed */
+ if (dcep->dce_expr == NULL)
+  {
+   if (oneinst)
+    {
+     /* notice this does need inst context */
+     __alloc_1instdce_prevval(dcep);
+    }
+   else alloc_dce_prevval(dcep, decl_mdp);
+  }
+
+ /* DBG remove ---
+ if (__debug_flg)
+  {
+   if (dctp->dc_iact) strcpy(__xs, " (interactive)");
+   else strcpy(__xs, ""); 
+   if (oneinst) strcat(__xs, " (xmr)");
+   __dbg_msg(
+    ".. ref. mod %s decl. %s adding net %s delay ctrl type %d%s ([%d:%d])\n",
+    ref_mdp->msym->synam, decl_mod->msym->synam, np->nsym->synam,
+    dcep->dce_typ, __xs, dcep->dci1, dcep->dci2.i);
+  }
+ --- */
+ if (dctp->dc_iact)
+  {
+   /* add to iact list for this statement - will be linked to hctrl */  
+   dclp = (struct dceauxlst_t *) __my_malloc(sizeof(struct dceauxlst_t));
+   dclp->ldcep = dcep; 
+   dclp->dclnxt = __iact_dcehdr;
+   __iact_dcehdr = dclp;
+   /* for after sim start iact dctrl add, know the iact itree loc set */  
+   dcep->iact_itp = __inst_ptr;
+  }
+ return(dcep);
+}
+
+/*
+ * routine to turn chg store on when new dce added but previously chg store
+ * off because no dces, and no loads, and not dumpvars 
+ *
+ * SJM 02/08/03 - for -O this only regens any needed proc insns but
+ * caller must regen the net with the new dces added - proc regen
+ * is only for case where net was not compiled in proc code
+ * case where
+ */
+extern void __dce_turn_chg_store_on(struct mod_t *in_mdp,
+ struct dcevnt_t *dcep, int32 all_insts)  
+{
+ register int32 ii;
+ struct mod_t *mdp;
+ struct net_t *np;
+
+ if (dcep->dce_1inst)
+  {
+   mdp = dcep->dce_matchitp->itip->imsym->el.emdp;
+   /* DBG remove -- */
+   if (in_mdp != mdp) __misc_terr(__FILE__, __LINE__); 
+   /* --- */
+  }
+ else if (dcep->dce_xmrtyp != XNP_LOC) mdp = dcep->dceu.dcegrp->targmdp;
+ else mdp = in_mdp;
+ np = dcep->dce_np;
+
+ /* SJM 01/06/03 - fix interpreter bug since need chg store on if */
+ /* net had no dces, no nlds, and dumpvars was off */
+ np->nchg_nd_chgstore = TRUE;
+
+ /* SJM 04/14/04 - for iact added dce if dumpvars and unc. need this on */
+ np->nchg_has_dces = TRUE;
+
+ if (all_insts)
+  {
+   /* SJM 01/06/03 - LOOKATME - is is possible to only turn on this inst? */
+   for (ii = 0; ii < __inst_mod->flatinum; ii++)
+    { np->nchgaction[ii] &= ~(NCHG_ALL_CHGED); }
+  }
+ else np->nchgaction[__inst_ptr->itinum] &= ~(NCHG_ALL_CHGED);
+}
+
+/*
+ * allocate a delay control event record
+ *
+ * this assumes non XMR and non 1inst - if not caller must set
+ * SJM 05/07/03 - must set net at beginning since needed by following code
+ */
+extern struct dcevnt_t *__alloc_dcevnt(struct net_t *np)
+{ 
+ struct dcevnt_t *dcep;
+
+ dcep = (struct dcevnt_t *) __my_malloc(sizeof(struct dcevnt_t));
+ dcep->dce_np = NULL;
+
+ dcep->dce_typ = DCE_NONE;
+ dcep->dce_np = np;
+
+ dcep->dce_xmrtyp = XNP_LOC; 
+ dcep->dce_1inst = FALSE;
+ dcep->dce_tfunc = FALSE;
+ /* SJM 07/22/00 - for re-entrant problem and vpi control off - never off */
+ /* unless set by vpi (sim) control or call back entry */
+ /* SJM 06/13/02 - now also interpreter always filters dce for on/off */
+ /* because (f)monitor and qcaf now added during design load (prep) */
+ /* for these builder must explicitlyturn off */
+ dcep->dce_off = FALSE;
+ dcep->is_fmon = FALSE;
+ dcep->dce_nomonstren = TRUE; 
+ dcep->dci1 = -1;
+ dcep->dci2.i = -1;
+ dcep->prevval.wp = NULL;
+ dcep->dce_edge = FALSE;
+ dcep->dce_edgval = NOEDGE;
+ dcep->st_dctrl = NULL;
+ dcep->dceu.dcegrp = NULL;
+ dcep->dceu2.dce_fmon = NULL;
+ dcep->dce_matchitp = NULL;
+ dcep->dce_refitp = NULL; 
+ dcep->iact_itp = NULL;
+ dcep->dcenxt = NULL;
+ dcep->dce_expr = NULL;
+ return(dcep);
+}
+
+/*
+ * prepare a disable inside a function by setting to next statement to goto
+ * inside function disable are like c continue and are just gotos
+ */
+static void prep_func_dsable(struct st_t *stp)
+{
+ register int32 i;
+ struct expr_t *dsxp;
+ struct sy_t *syp;
+ struct task_t *dsatskp;
+
+ dsxp = stp->st.sdsable.dsablx;
+ syp = dsxp->lu.sy; 
+ /* disable of func. indicated by nil next statmenet - use fcall stack */
+ if (syp->sytyp == SYM_F)
+  {
+   stp->st.sdsable.func_nxtstp = NULL;
+   return;
+  }
+
+ /* must be disabling named block */
+ if (syp->sytyp != SYM_LB || syp->el.etskp->tsktyp == FORK
+  || dsxp->optyp == GLBREF) __misc_sgfterr(__FILE__, __LINE__);
+ dsatskp = syp->el.etskp;
+ /* know every named block when entered in function name block is stacked */
+ for (i = __nbsti; i >= 0; i--)
+  {
+   if (__nbstk[i]->st.snbtsk == dsatskp)
+    {
+     /* this can be nil */
+     stp->st.sdsable.func_nxtstp = __nbstk[i]->stnxt;
+     return;
+    }
+  }
+ /* know always enclosing, or will not get here - earlier error */
+ __case_terr(__FILE__, __LINE__);
+}
+
+/*
+ * return T if disable targsyp above cursytp 
+ * i.e. is upward break type disable
+ * if any named block on path sets nbonpath to T
+ *
+ * because of xmr disabling of named begin-end blocks need thread so cannot
+ * use goto except inside function
+ */
+extern int32 __is_upward_dsable_syp(struct sy_t *targsyp,
+ struct symtab_t *cursytp, int32 *nbonpath)
+{
+ register struct symtab_t *sytp;
+ struct sy_t *syp;
+
+ *nbonpath = FALSE;
+ if (targsyp->sytyp != SYM_LB) return(FALSE); 
+ /* notice top of upward chain will be module, but disable of module */
+ /* illegal so will return match top of chain module */
+ for (sytp = cursytp; sytp != NULL; sytp = sytp->sytpar) 
+  {
+   syp = sytp->sypofsyt;
+   if (targsyp == syp) return(TRUE);
+   if (syp->sytyp == SYM_LB) *nbonpath = TRUE;
+  }
+ return(FALSE);
+}
+
+/*
+ * FORCE/ASSIGN/MONITOR PREPARATION ADD DCE ROUTINES
+ */
+
+/*
+ * for qcaf stmts, build the per lhs cat element 
+ * for reg per cat component dce lists are per inst and for wire
+ * they are per bit of cat expr per inst
+ */
+static void bld_init_qcaf_dce_lstlst(struct st_t *stp)
+{
+ register int32 ii;
+ int32 ibase;
+ struct expr_t *lhsx;
+ struct expr_t *catndp, *catlhsx;
+ struct dceauxlstlst_t *dcllp, *end_dcllp;
+ 
+ lhsx = stp->st.sqca->qclhsx;
+ if (lhsx->optyp != LCB)
+  {
+   /* one list of peri lists */
+   dcllp = (struct dceauxlstlst_t *)
+    __my_malloc(sizeof(struct dceauxlstlst_t)); 
+   stp->st.sqca->rhs_qcdlstlst = dcllp;
+   if (stp->st.sqca->regform)
+    {
+     /* for reg list field is peri table of dce lists - starting at empty */
+     dcllp->dcelsttab = (struct dceauxlst_t **)
+      __my_malloc(__inst_mod->flatinum*sizeof(struct dceauxlst_t *));
+     
+     for (ii = 0; ii < __inst_mod->flatinum; ii++) 
+      dcllp->dcelsttab[ii] = NULL; 
+    }
+   else
+    {
+     /* for wire list field is peri/bit tab of dce lists - starts at empty */
+     ibase = __inst_mod->flatinum*lhsx->szu.xclen;
+     dcllp->dcelsttab = (struct dceauxlst_t **)
+      __my_malloc(ibase*sizeof(struct dceauxlst_t *));
+     for (ii = 0; ii < ibase; ii++) dcllp->dcelsttab[ii] = NULL; 
+    }
+   /* since non concat, only one element */
+   dcllp->dcelstlstnxt = NULL;
+  } 
+ else
+  {
+   end_dcllp = NULL;
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    {
+     catlhsx = catndp->lu.x;
+
+     /* allocate list of peri lists element */
+     dcllp = (struct dceauxlstlst_t *)
+      __my_malloc(sizeof(struct dceauxlstlst_t)); 
+     if (end_dcllp == NULL) stp->st.sqca->rhs_qcdlstlst = dcllp;
+     else end_dcllp->dcelstlstnxt = dcllp;
+     end_dcllp = dcllp;
+
+     if (stp->st.sqca->regform)
+      {
+       /* reg list field is peri table of dce lists - starting at empty */
+       dcllp->dcelsttab = (struct dceauxlst_t **)
+        __my_malloc(__inst_mod->flatinum*sizeof(struct dceauxlst_t *));
+       for (ii = 0; ii < __inst_mod->flatinum; ii++) 
+        dcllp->dcelsttab[ii] = NULL; 
+      }
+     else
+      {
+       ibase = __inst_mod->flatinum*catlhsx->szu.xclen;
+       /* if not list end, next pass will set */
+       dcllp->dcelsttab = (struct dceauxlst_t **)
+        __my_malloc(ibase*sizeof(struct dceauxlst_t *));
+       for (ii = 0; ii < ibase; ii++) dcllp->dcelsttab[ii] = NULL; 
+      }
+     dcllp->dcelstlstnxt = NULL;
+    }
+  }
+}
+
+/*
+ * prepare a quasi-continuous assign or force of reg (same as qc assign)
+ * this is for both reg force and reg assign
+ *
+ * SJM 06/14/02 - same as old exec qc assign for each inst but at prep time
+ * to build and fill d.s
+ */
+static void prep_qc_assign(struct st_t *stp, int32 is_force)
+{
+ register struct expr_t *catndp;
+ register struct dceauxlstlst_t *dcllp;
+ struct expr_t *lhsx, *catlhsx;
+ struct dceauxlst_t *qcdep;
+
+ /* first evaluate rhs */
+ lhsx = stp->st.sqca->qclhsx;
+ /* only possibilities are concat and ID */
+ /* this builds and initializes the reg assign/frc qcval records */ 
+ if (lhsx->optyp != LCB)
+  {
+   if (is_force) qcdep = prep_noncat_qc_regforce(stp, lhsx);
+   else qcdep = prep_noncat_qc_assign(stp, lhsx);
+   /* only one list of lists element since not lhs concat */
+   stp->st.sqca->rhs_qcdlstlst->dcelsttab[__inum] = qcdep;
+  }
+ else
+  {
+   /* concatenate case know lhs entire var */
+   dcllp = stp->st.sqca->rhs_qcdlstlst;
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x,
+    dcllp = dcllp->dcelstlstnxt)
+    {
+     catlhsx = catndp->lu.x;
+     if (is_force) qcdep = prep_noncat_qc_regforce(stp, catlhsx);
+     else qcdep = prep_noncat_qc_assign(stp, catlhsx);
+     dcllp->dcelsttab[__inum] = qcdep;
+    }
+  }
+}
+
+/*
+ * prepare a quasi-continuous deassign (same as old exec but at per/inst now)
+ * inverse of assign and reg only defined for regs
+ */
+static void prep_qc_deassign(struct st_t *stp)
+{
+ register struct expr_t *catndp;
+ int32 nd_itpop;
+ struct expr_t *lhsx, *catlhsx;
+ struct net_t *np;
+ struct gref_t *grp;
+
+ /* SJM 07/19/02 - was wrongly accessing qconta not qcontdea record */
+ lhsx = stp->st.sqcdea.qcdalhs;
+ /* only possibilities are concat and ID */
+ if (lhsx->optyp != LCB)
+  {
+   /* just need to alloc qcval records here - dce list built from assgn */
+   np = lhsx->lu.sy->el.enp;
+   if (np->nu2.qcval == NULL)
+    {
+     /* SJM 05/23/03 - must alloc in context of XMR */
+     if (lhsx->optyp == GLBREF)
+      { grp = lhsx->ru.grp; __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+     else nd_itpop = FALSE;
+
+     __alloc_qcval(np);
+
+     if (nd_itpop) __pop_itstk();
+    }
+  }
+ else
+  {
+   /* concatenate case know lhs full wire - tricky extractions of rhs */
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    {
+     catlhsx = catndp->lu.x;
+     np = catlhsx->lu.sy->el.enp;
+     if (np->nu2.qcval == NULL)
+      {
+       /* SJM 05/23/03 - must alloc in context of XMR */
+       if (lhsx->optyp == GLBREF)
+        {
+         grp = lhsx->ru.grp;
+         __xmrpush_refgrp_to_targ(grp);
+         nd_itpop = TRUE;
+        }
+       else nd_itpop = FALSE;
+
+       __alloc_qcval(np);
+
+       if (nd_itpop) __pop_itstk();
+      }
+    }
+  }
+}
+
+/*
+ * prep quasi continuous assign for one expr in one inst.
+ *
+ * know lhs always entire register - no assign for wires - lhs can be xmr 
+ * this is called for every inst of module tha contains stmt
+ * LOOKATME - do not need stmt since can get from qcval already built
+ */
+static struct dceauxlst_t *prep_noncat_qc_assign(struct st_t *qcstp,
+ struct expr_t *lhsx)
+{
+ int32 nd_itpop;
+ struct net_t *np;
+ struct qcval_t *assgn_qcp;
+ struct gref_t *grp;
+
+ /* SJM 05/29/03 - must allocate and find qcval rec from lhs itree loc */
+ nd_itpop = FALSE;
+ if (lhsx->optyp == GLBREF)
+  {
+   grp = lhsx->ru.grp;
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+  }
+ else if (lhsx->optyp != ID) __case_terr(__FILE__, __LINE__);
+
+ np = lhsx->lu.sy->el.enp;
+ if (np->nu2.qcval == NULL) __alloc_qcval(np);
+ assgn_qcp = &(np->nu2.qcval[2*__inum + 1]);
+
+ /* add qcaf from soruce location of statment */
+ if (nd_itpop) __pop_itstk();
+
+ /* SJM 05/29/03 - must build the qcaf dce in reference not declare context */ 
+ __qcaf_dcehdr = NULL;
+ /* for constant rhs this can be nil */
+ bld_qcaf_dces(qcstp->st.sqca->qcrhsx, assgn_qcp);
+
+ return(__qcaf_dcehdr);
+}
+
+/*
+ * prepare the quasi continuous force for reg variables - just alloc qcval rec
+ *
+ * know lhs always entire register
+ * lhs here can be xmr 
+ * force of entire reg only overrides possible active reg assign
+ */
+static struct dceauxlst_t *prep_noncat_qc_regforce(struct st_t *qcastp,
+ struct expr_t *lhsx)
+{
+ int32 nd_itpop;
+ struct net_t *np;
+ struct qcval_t *frc_qcp; 
+ struct gref_t *grp;
+
+ nd_itpop = FALSE;
+ /* 05/28/03 - must get fource qc record ptr from lhs decl itree loc */
+ if (lhsx->optyp == GLBREF)
+  {
+   grp = lhsx->ru.grp;
+   __xmrpush_refgrp_to_targ(grp);
+   nd_itpop = TRUE;
+  }
+ else if (lhsx->optyp != ID) __case_terr(__FILE__, __LINE__);
+
+ np = lhsx->lu.sy->el.enp;
+ /* DBG remove -- */
+ if (!np->frc_assgn_allocated) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ if (np->nu2.qcval == NULL) __alloc_qcval(np);
+ frc_qcp = &(np->nu2.qcval[2*__inum]);
+
+ /* 05/28/03 - but must bld qcaf dces in ref itree context */
+ if (nd_itpop) __pop_itstk();
+
+ __qcaf_dcehdr = NULL;
+ /* for constant rhs thsi can be nil */
+ bld_qcaf_dces(qcastp->st.sqca->qcrhsx, frc_qcp);
+
+ return(__qcaf_dcehdr);
+}
+
+/*
+ * allocate a new qc assign value aux. record
+ * itree location must be set before calling here since needs to know mod in
+ *
+ * SJM 12/21/02 - this is per inst of mod net declared in when called as XMR
+ */
+extern void __alloc_qcval(struct net_t *np)
+{
+ register int32 i;
+ register struct qcval_t *qcvalp;
+
+ /* AIV 03/09/05 - if force from vpi bit needs to be set */
+ np->frc_assgn_allocated = TRUE;
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   /* here need 1 qcval per inst. but need 1 for assign and 1 for force */
+   np->nu2.qcval = (struct qcval_t *)
+    __my_malloc(2*__inst_mod->flatinum*sizeof(struct qcval_t));
+  
+   qcvalp = np->nu2.qcval;
+   for (i = 0; i < 2*__inst_mod->flatinum; i++, qcvalp++) init_qcval(qcvalp);
+  }
+ else
+  {
+   /* here need 1 per inst bit product */
+   /* LOOKATME - could have 1 bit per inst. for vectored wires */ 
+   np->nu2.qcval = (struct qcval_t *)
+    __my_malloc(__inst_mod->flatinum*np->nwid*sizeof(struct qcval_t));
+   qcvalp = np->nu2.qcval;
+   for (i = 0; i < __inst_mod->flatinum*np->nwid; i++, qcvalp++)
+    init_qcval(qcvalp);
+  }
+}
+
+/*
+ * allocate a qcval record
+ */
+static void init_qcval(struct qcval_t *qcvalp) 
+{
+ qcvalp->qc_active = FALSE;
+ qcvalp->qc_overridden = FALSE;
+ qcvalp->qcstp = NULL;
+ qcvalp->qcrhsbi = -1;
+ qcvalp->qclhsbi = -1;
+ qcvalp->lhsitp = NULL;
+ qcvalp->qcdcep = NULL;
+}
+
+/*
+ * QUASI CONTINUOUS WIRE FORCE/RELEASE PREP ROUTINES 
+ */
+
+/*
+ * prepare quasi-continuous force on a wire
+ * possibilities here are wire, constant bit select, part select
+ * also concat of above
+ * wire must be scalared and everything decomposed to bits
+ */
+static void prep_qc_wireforce(struct st_t *stp)
+{
+ register struct expr_t *catndp;
+ register struct dceauxlstlst_t *dcllp;
+ struct expr_t *lhsx, *catlhsx;
+
+ /* first evaluate rhs */
+ lhsx = stp->st.sqca->qclhsx;
+ /* only possibilities are concat and ID */
+ /* this builds and initializes the reg assign/frc qcval records */ 
+ if (lhsx->optyp != LCB)
+  {
+   prep_noncat_qc_wireforce(stp, lhsx, stp->st.sqca->rhs_qcdlstlst);
+  }
+ else
+  {
+   /* concatenate case know lhs full wire - tricky extractions of rhs */
+   dcllp = stp->st.sqca->rhs_qcdlstlst;
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x,
+    dcllp = dcllp->dcelstlstnxt)
+    {
+     catlhsx = catndp->lu.x;
+     prep_noncat_qc_wireforce(stp, catlhsx, dcllp);
+    }
+  }
+}
+
+/*
+ * prepare a quasi-continuous release - only decomposes into lhs exprs
+ * only scalared wires or selects or cats not regs
+ * wire force/release is one level only
+ * called in itree context of release stmt 
+ * 
+ * 06/24/02 - wire release just alloc qcvals for all nets so it must
+ * decompose into cat elements to get net - for wire all bits need
+ * qcval even if only some can be forced/released 
+ */
+static void prep_qc_wirerelease(struct st_t *stp)
+{
+ register struct expr_t *catndp;
+ struct expr_t *lhsx, *catlhsx;
+
+ lhsx = stp->st.sqcdea.qcdalhs; 
+ /* only possibilities are concat and ID */
+ if (lhsx->optyp != LCB) prep_noncat_qc_wirerelease(lhsx);
+ else
+  {
+   /* concatenate case know lhs full wire - tricky extractions of rhs */
+   for (catndp = lhsx->ru.x; catndp != NULL; catndp = catndp->ru.x)
+    { catlhsx = catndp->lu.x; prep_noncat_qc_wirerelease(catlhsx); }
+  }
+}
+/*
+ * after possible concat unwinding, prepare wire force
+ *
+ * wire force is bit by bit unless vectored wire (when only entire wire)
+ *
+ * force which is for debugging overrides any wire delay assign
+ * when wire change happens (wire event process) if force active, no assign
+ * rhsbi is low bit of possible rhs section select (0 for not concat)
+ * this is called with stmt itree loc even if lhs xmr and handled push/pop
+ *
+ * SJM 11/14/00 - tran channel (inout port) force now is separate routine
+ * LOOKATME - think could simplify since for wire force always one bit
+ *
+ * sjm 12/21/02 - attached to statement so dcllp element must use stmt
+ * itree inst loc even for XMR lhs expr
+ */
+static void prep_noncat_qc_wireforce(struct st_t *qcfstp, struct expr_t *lhsx,
+ struct dceauxlstlst_t *dcllp)
+{
+ register int32 bi, xbi, ibase;
+ int32 biti, bitj;
+ struct qcval_t *frc_qcp;
+ struct net_t *np;
+ struct itree_t *itp;
+
+ /* step 1: get the wire range */
+ /* for psel or vector, range is biti down to bitj - for scalar 0,0 */
+ /* this computes any xmr new itp but does not push it - nil if not XMR */
+ __get_qc_wirrng(lhsx, &np, &biti, &bitj, &itp); 
+
+ /* for tran channel wire, no dces - forcing wire forces channel */
+ /* LOOKATME - think no need also no need for qcvals */
+
+ /* SJM 07/19/02 - for lhs xmr need target itree loc */
+ /* rest needs possible lhs xmr itree context including qcval alloc */
+ if (itp != NULL) __push_itstk(itp);
+
+ /* allocate the qcval record for wire if not yet alloced */
+ /* also needed for tran channel force */
+ /* for XMR attached net per inst values are from pushed defined in mod */
+ if (np->nu2.qcval == NULL) __alloc_qcval(np);
+
+ /* 05/28/03 - need to get per bit frc qc record from lhs decl itree cntxt */ 
+ ibase = __inum*np->nwid;
+ if (itp != NULL) __pop_itstk();
+
+ if (np->ntraux != NULL) return;
+
+ for (bi = bitj, xbi = 0; bi <= biti; bi++, xbi++)
+  {
+   /* for normal add dces for every bit */
+   frc_qcp = &(np->nu2.qcval[ibase + bi]);
+
+   __qcaf_dcehdr = NULL;
+   /* for constant rhs thsi can be nil */
+   /* LOOKATME-could decompose lhs-rhs bit but rare and speed non-critical */
+   bld_qcaf_dces(qcfstp->st.sqca->qcrhsx, frc_qcp);
+
+   /* SJM 12/22/02 - per inst here is stmt when lhs XMR */ 
+   dcllp->dcelsttab[__inum*lhsx->szu.xclen + xbi] = __qcaf_dcehdr;
+  }
+}
+
+/*
+ * after possible concat unwinding, prepare lhs expr release
+ * just allocs qcval if needed in case seen before force
+ */
+static void prep_noncat_qc_wirerelease(struct expr_t *lhsx)
+{
+ int32 biti, bitj;
+ struct net_t *np;
+ struct itree_t *itp;
+ 
+ /* get the wire range - using common routine but only need net here */
+ __get_qc_wirrng(lhsx, &np, &biti, &bitj, &itp); 
+
+ /* SJM 07/19/02 - for lhs xmr need target itree loc */
+ /* rest needs possible lhs xmr itree context including qcval alloc */
+ if (itp != NULL) __push_itstk(itp);
+
+ /* allocate the qcval record for wire in case see release before force */
+ if (np->nu2.qcval == NULL) __alloc_qcval(np);
+
+ if (itp != NULL) __pop_itstk();
+}
+
+/*
+ * ROUTINES TO SETUP QUASI-CONTINOUS ASSIGN STORE AND DCE LIST
+ */
+
+/*
+ * build and link on special qc assign/force rhs simple dce
+ * xp is rhs expr and called from itree loc. where exec qc assign
+ */
+static void bld_qcaf_dces(struct expr_t *xp, struct qcval_t *qcvalp)
+{
+ register word32 *wp;
+ struct net_t *np;
+ int32 biti, bitj;
+ struct expr_t *idndp, *ndx;
+ struct expr_t *fax;
+ 
+ switch ((byte) xp->optyp) {
+  case GLBREF:
+   idndp = xp; 
+   /* for global - do not need ref. point - just link on 1 (because only 1 */
+   /* monit call from 1 inst.) target wire */
+   biti = bitj = -1;
+glb_dce:
+   np = idndp->lu.sy->el.enp;
+   linkon_qcaf_dce(np, biti, bitj, idndp->ru.grp, qcvalp);
+   break;
+  case ID:
+   idndp = xp; 
+   np = xp->lu.sy->el.enp;
+   linkon_qcaf_dce(np, -1, -1, (struct gref_t *) NULL, qcvalp);
+   break;
+  /* SJM 05/18/00 - must do nothing for reals */ 
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   return;
+  case LSB:
+   idndp = xp->lu.x; 
+   np = idndp->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   /* for monits, any reg or non scalaraed wire must trigger on any chg */
+   if (ndx->optyp == NUMBER)
+    {
+     wp = &(__contab[ndx->ru.xvi]);
+     if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
+    }
+   else if (ndx->optyp == ISNUMBER)
+    {
+     wp = &(__contab[ndx->ru.xvi]);
+     wp = &(wp[2*__inum]);
+     /* need length for IS number because can be wider - but get low */
+     if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
+    }
+   else
+    {
+     /* notice for monitor and dctrl event change, variable here is legal */
+     /* and implies change for index and trigger on all bits of variable */
+     bld_qcaf_dces(ndx, qcvalp);
+     biti = -1;
+    }
+   bitj = biti;
+   if (biti != -1 && !np->vec_scalared) biti = bitj = -1;
+   if (idndp->optyp == GLBREF) goto glb_dce;
+   linkon_qcaf_dce(np, biti, biti, (struct gref_t *) NULL, qcvalp);
+   break;
+  case PARTSEL:
+   idndp = xp->lu.x; 
+   np = idndp->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   /* know part select never IS */
+   biti = __contab[ndx->lu.x->ru.xvi];
+   bitj = __contab[ndx->ru.x->ru.xvi];
+   if (!np->vec_scalared) biti = bitj = -1;
+   if (idndp->optyp == GLBREF) goto glb_dce;
+   linkon_qcaf_dce(np, biti, bitj, (struct gref_t *) NULL, qcvalp);
+   break;
+  case FCALL:
+   /* if any arguments of system or user functions change, monitor triggers */
+   /* notice $time function do not have arguments */
+   for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+    bld_qcaf_dces(fax->lu.x, qcvalp);
+   break;
+  case LCB:
+   for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+    bld_qcaf_dces(fax->lu.x, qcvalp);
+   break;
+  default:
+   if (xp->lu.x != NULL) bld_qcaf_dces(xp->lu.x, qcvalp);
+   if (xp->ru.x != NULL) bld_qcaf_dces(xp->ru.x, qcvalp);
+   break;
+ } 
+}
+
+/*
+ * link on a special (simplified) qc assign/force dce rhs load
+ * caller must decompose any scalared wire part selects into bit selects
+ * before here
+ * -2 IS form impossible since any one inst. IS form converted to constant
+ * before here
+ *
+ * this must be called from source reference location of the qc stmt 
+ *
+ * notice never a need for an old value since better to just re-eval assign
+ * this goes on front but after any DMPV 
+ */
+static void linkon_qcaf_dce(struct net_t *np, int32 biti, int32 bitj,
+ struct gref_t *grp, struct qcval_t *qcvalp)
+{
+ int32 nd_itpop;
+ struct itree_t *ref_itp;
+ struct dcevnt_t *dcep;
+ struct dceauxlst_t *dclp;
+
+ ref_itp = __inst_ptr;
+ nd_itpop = FALSE;
+ if (grp != NULL) { __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ /* allocate, init, and fill the fields */
+ dcep = __alloc_dcevnt(np);
+ if (biti == -1) dcep->dce_typ = DCE_QCAF;
+ else
+  {
+   dcep->dce_typ = DCE_RNG_QCAF;
+   dcep->dci1 = biti;
+   dcep->dci2.i = bitj;
+  }
+ dcep->dce_np = np;
+ /* dce's start out on so must explicitly turn prep time built qc off here */
+ dcep->dce_off = TRUE;
+
+ /* link this on front */
+ dcep->dcenxt = np->dcelst;
+ np->dcelst = dcep;
+
+ /* set ref. itree location - since dcep on target */
+ dcep->dce_1inst = TRUE;
+ dcep->dce_matchitp = __inst_ptr;
+ dcep->dce_refitp = ref_itp;
+ /* SJM 07/19/02 needed to make sure chg form iops get gened */ 
+ np->nchg_nd_chgstore = TRUE;
+
+ /* also set unused fmon field to qcval for bit or wire if reg */
+ dcep->dceu2.dce_qcvalp = qcvalp;
+
+ /* then link on undo/chg list */
+ dclp = (struct dceauxlst_t *) __my_malloc(sizeof(struct dceauxlst_t));
+ dclp->ldcep = dcep; 
+ dclp->dclnxt = __qcaf_dcehdr;
+ __qcaf_dcehdr = dclp;
+
+ /* SJM 06/23/04 ### ??? - without regen is this needed? */
+ /* SJM 02/06/03 - may have npps but not dces so must turn this on */
+ /* since nchg nd chgstore on, know nchg action right */
+ if (np->ntyp >= NONWIRE_ST) np->nchg_has_dces = TRUE;
+
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * XMR VARIABLE PREPARATION ROUTINES
+ */
+
+/*
+ * prepare xmrs - allocate per inst. storage and set itree pointers
+ *
+ * no itree context here - must use explicit itree locs
+ */
+extern void __prep_xmrs(void)
+{
+ register int32 gri; 
+ register struct mod_t *mdp;
+ register struct gref_t *grp;
+ int32 ii;
+ struct itree_t *itp;
+
+ /* first process rooted and count upward rel. in static tree */
+ __num_uprel_glbs = 0;
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (gri = 0, grp = &(mdp->mgrtab[0]); gri < mdp->mgrnum; gri++, grp++)
+    {
+     /* DBG remove - if any gr_err should not get here */
+     if (grp->gr_err) __misc_terr(__FILE__, __LINE__);
+     if (grp->gr_gone) continue;
+
+     /* if guessed wrong xmr from used in instance argument loc., undo */
+     /* if rooted set root target itp */ 
+     if (grp->is_rooted)
+      {
+       /* find itree root corresponding to root path staring module name */
+       /* never constant inst array select */
+       if ((ii = __ip_indsrch(grp->grcmps[0]->synam)) == -1)
+	__misc_gfterr(__FILE__, __LINE__, grp->grfnam_ind, grp->grflin_cnt);
+       itp = __it_roots[ii];
+
+       if (grp->last_gri != 0)
+        grp->targu.targitp = __find_unrt_targitp(grp, itp, 1);
+       /* one component rooted, so already have itp */
+       else grp->targu.targitp = itp;
+
+       /* must mark module as containing rooted gref */
+       /* and first rooted gref - allocate flatinum style itree table */
+       continue;
+      }
+     /* notice one uprel xmr has flatinum number in itree */
+     if (grp->upwards_rel)
+      {
+       /* setting of inst. selects in upward rels, handled elsewhere */
+       __num_uprel_glbs += mdp->flatinum; 
+       process_upwards_grp(grp);
+       continue;
+      }
+     /* for downward relative with array of inst. selects must check ranges */
+     if (grp->path_has_isel) chk_downrel_inst_sels(grp);
+    }
+  }
+} 
+
+/*
+ * fill grp targ field for rooted grp and uprel itps tabl for upward rel
+ * called for interactive and delay setting run time xmr eval only
+ */
+extern void __fill_grp_targu_fld(struct gref_t *grp)
+{
+ int32 ii;
+ struct itree_t *itp2;
+
+ if (grp->gr_err || grp->gr_gone) return;
+
+ /* if rooted set root target itp */ 
+ if (grp->is_rooted)
+  {
+   /* find itree root corresponding to root path staring module name */
+   if ((ii = __ip_indsrch(grp->grcmps[0]->synam)) == -1)
+    __misc_gfterr(__FILE__, __LINE__, grp->grfnam_ind, grp->grflin_cnt);
+   itp2 = __it_roots[ii];
+   /* may be rooted and in top module */
+   if (grp->last_gri != 0)
+     grp->targu.targitp = __find_unrt_targitp(grp, itp2, 1);
+   else grp->targu.targitp = itp2;
+   return;
+  }
+ /* since never more than 1 inst. of interactive scope, up from current */
+ /* scope - this implies must always reparse interactive statements */
+ /* SJM 09/15/00 - this fills the per ref. indexed targ itps table */
+ if (grp->upwards_rel) process_upwards_grp(grp);
+}
+
+/*
+ * process upward relative gref by building downward reverse of upward
+ * path to first above module of matching type
+ *
+ * rule is go upward until find matching 0th component type, then down
+ * this is needed because for inst. upward distance may be different
+ * because inst array pound param range types copied before defparam
+ * splitting, first upward rel. first component symbol will be right split off
+ */
+static void process_upwards_grp(struct gref_t *grp)
+{
+ register int32 ii;
+ struct mod_t *imdp, *up_mdp, *mast_imdp, *up_mast_mdp;
+ struct itree_t *in_itp, *up_itp, *titp;
+ struct inst_t *ip;
+ struct sy_t *syp;
+ struct itree_t **uprelitps;
+
+ /* notice for upward relative, first component is module type not inst */  
+ syp = grp->grcmps[0];
+ /* DBG remove - upward relative xmr head not module type */
+ if (syp->sytyp != SYM_M)
+  __misc_gfterr(__FILE__, __LINE__, grp->grfnam_ind, grp->grflin_cnt);
+ /* -- */
+
+ uprelitps = (struct itree_t **)
+  __my_malloc(grp->gin_mdp->flatinum*sizeof(struct itree_t *));
+ grp->targu.uprel_itps = uprelitps;
+
+ /* for upward distance is per inst. variable - up to find target mod */
+ up_mdp = syp->el.emdp;
+ up_mast_mdp = __get_mast_mdp(up_mdp);
+ for (ii = 0; ii < grp->gin_mdp->flatinum; ii++)
+  {
+   in_itp = grp->gin_mdp->moditps[ii];
+
+   for (up_itp = in_itp;;)
+    {
+     if (up_itp == NULL)
+      {
+       __gferr(981, grp->grfnam_ind, grp->grflin_cnt,
+        "unqualified use of upward relative task/func %s illegal - matched upward relative task/func undefined above instance %s",
+        grp->gnam, __msg2_blditree(__xs, in_itp)); 
+       return;
+      }
+
+     /* upward xmr reference no matching type above */
+     ip = up_itp->itip;
+     imdp = ip->imsym->el.emdp;
+     mast_imdp = __get_mast_mdp(imdp);
+     /* DBG remove --
+     __dbg_msg("upwards rel: %s: first comp=%s, current mdp: %s(%s)=%d\n",
+      grp->gnam, up_mast_mdp->msym->synam, mast_imdp->msym->synam,
+      ip->isym->synam, up_itp->itinum);
+     -- */
+     if (mast_imdp == up_mast_mdp) break;
+     up_itp = up_itp->up_it;
+    }
+   /* next trace down from upward module type match (using it inst) */
+   /* 0th is module that determines upward distance */
+   if (grp->last_gri != 0) titp = __find_unrt_targitp(grp, up_itp, 1);
+   /* one component upward relative module name */
+   else titp = up_itp;
+
+   uprelitps[ii] = titp;
+  }
+}     
+
+/*
+ * given possible split off module type get the mast type
+ *
+ * pound params may be 1 level split off and defparams one more
+ * i.e. all pound parameters split off from one master (maybe >1 inst)
+ * then defparam split off from either normal or pound split off
+ */
+extern struct mod_t *__get_mast_mdp(struct mod_t *mdp)
+{
+ struct mod_t *mast_mdp;
+
+ if (mdp->msplit) 
+  {
+   mast_mdp = mdp->mspltmst;
+   if (mast_mdp->mpndsplit) mast_mdp = mast_mdp->mpndspltmst;
+  }
+ else if (mdp->mpndsplit) mast_mdp = mdp->mpndspltmst;
+ else mast_mdp = mdp;
+ return(mast_mdp);
+}
+
+/*
+ * check all instances of downward relative instance selects
+ *
+ * only called for downward relative that have inst array selects
+ */
+static void chk_downrel_inst_sels(struct gref_t *grp)
+{
+ register int32 ii; 
+ struct mod_t *mdp; 
+ struct itree_t *itp;
+ int32 sav_ecnt;
+
+ sav_ecnt = __pv_err_cnt;
+ mdp = grp->gin_mdp;
+ for (ii = 0; ii < mdp->flatinum; ii++)
+  {
+   itp = mdp->moditps[ii];
+   /* DBG remove --- */
+   if (itp == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* this does checking for each and emits error */  
+   __find_unrt_targitp(grp, itp, 0);
+   /* once error is found stop */
+   if (__pv_err_cnt > sav_ecnt) break;
+  }
+}
+
+/*
+ * SPECIFY SECTION PREPARATION ROUTINES
+ */
+
+extern void __prep_specify(void)
+{
+ prep_tchks();
+ prep_pths();
+}
+
+/*
+ * TIMING CHECK REPRESENTATION CHANGE ROUTINES
+ */
+
+/*
+ * routine to prepare timing checks 
+ * for vectors in timing check event slots must split into 1 bit wide
+ * checks since each bit timing reference and data events separate
+ *
+ * notice timing checks cannot be xmrs (must be I/O ports) so no xmr
+ * processing net pin elements
+ */
+static void prep_tchks(void)
+{
+ register struct tchk_t *tcp;
+ register int32 i1, i2;
+ int32 starti1, starti2, chki1, chki2;
+ struct mod_t *mdp;
+ struct net_t *startnp, *chknp;
+ struct tchg_t *start_tchgp;
+ struct chktchg_t *chk_tchgp;
+ struct gate_t gwrk;
+ 
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+
+   /* multiple blocks each with different symbol table legal */
+   /* if option to ignore, specify will be remove before here */
+   if (mdp->mspfy == NULL) continue;
+
+   __push_wrkitstk(mdp, 0);
+   for (tcp = mdp->mspfy->tchks; tcp != NULL; tcp = tcp->tchknxt)
+    {
+     /* do not convert since always will not get initialized - invisible */
+     if (tcp->tc_gone) continue;
+
+     /* convert ref. and data events to wire and range */
+     /* know events is non concatente lhs (wire, const. bit/part select) */
+     __xtract_wirng(tcp->startxp, &startnp, &starti1, &starti2);
+     if (tcp->tchktyp == TCHK_PERIOD || tcp->tchktyp == TCHK_WIDTH) 
+      {
+       chknp = startnp; chki1 = starti1; chki2 = starti2;
+       /* need to copy to make timing check violation check code work */
+       tcp->chkxp = __copy_expr(tcp->startxp);
+       tcp->chkcondx = __copy_expr(tcp->startcondx);
+       if (tcp->tchktyp == TCHK_WIDTH)
+        {
+         /* opposite edge */
+         if (tcp->startedge == E_NEGEDGE) tcp->chkedge = E_POSEDGE;
+         else if (tcp->startedge == E_POSEDGE) tcp->chkedge = E_NEGEDGE;
+         else __case_terr(__FILE__, __LINE__);
+        }
+       /* same edge */
+       else tcp->chkedge = tcp->startedge;
+      }
+     else __xtract_wirng(tcp->chkxp, &chknp, &chki1, &chki2);
+
+     switch ((byte) tcp->tchktyp) {
+      /* SJM 01/16/04 - added $removal - reversed terms of $recovery */
+      case TCHK_SETUP: case TCHK_HOLD: case TCHK_SKEW: case TCHK_RECOVERY:
+      case TCHK_SETUPHOLD: case TCHK_REMOVAL: case TCHK_RECREM:
+       /* timing check range all full - every bit time checked against */
+       for (i1 = starti1; i1 >= starti2; i1--)
+        {
+         start_tchgp = bld_start_tchk_npp(tcp, startnp, i1); 
+         for (i2 = chki1; i2 >= chki1; i2--)
+         {
+          chk_tchgp = bld_check_tchk_npp(chknp, i2); 
+          /* check event needs access to start - also path to tchk master */
+          chk_tchgp->startchgp = start_tchgp;
+         }
+        } 
+       break;
+      case TCHK_WIDTH: case TCHK_PERIOD:
+       /* after above fixup, like normal except ==> not *> form */  
+       /* maybe wrong and should be ? */
+       for (i1 = starti1; i1 >= starti2; i1--)
+        {
+         /* for $period no reference event, data and reference the same */
+         /* so this build ref. but no npp */
+         start_tchgp = bld_start_tchk_npp(tcp, startnp, i1); 
+         chk_tchgp = bld_check_tchk_npp(chknp, i1); 
+         /* check event needs access to start - also path to tchk master */
+         chk_tchgp->startchgp = start_tchgp;
+        } 
+       break;
+      default: __case_terr(__FILE__, __LINE__);
+     }
+    /* no delay preparation for added hold of setuphold */
+    if (tcp->tc_supofsuphld || tcp->tc_recofrecrem) continue;
+
+    /* first set &&& conditional fields net still acessed from t event */
+    /* width irrelevant know will always only be 1 delay */
+    /* know every timing check has 1 limit field */
+    __add_tchkdel_pnp(tcp, TRUE);
+    __prep_delay(&gwrk, tcp->tclim_du.pdels, FALSE, FALSE,
+     "first timing check limit", TRUE, tcp->tcsym, TRUE);
+    if (__nd_neg_del_warn)
+     {
+      __gfwarn(601, tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt,
+       "timing check negative delay changed to 0 (ok for timing verifier)");
+       __nd_neg_del_warn = FALSE;
+     }
+    tcp->tc_delrep = gwrk.g_delrep;
+    tcp->tclim_du = gwrk.g_du;
+
+    /* notice for setuphold (actually hold part) this always on */
+    if (tcp->tc_haslim2)
+     {
+      /* width irrelevant know will always only be 1 delay */
+      __add_tchkdel_pnp(tcp, FALSE);
+      __prep_delay(&gwrk, tcp->tclim2_du.pdels, FALSE, FALSE,
+       "2nd timing check limit", TRUE, tcp->tcsym, TRUE);
+      if (__nd_neg_del_warn)
+       {
+        __gfwarn(601, tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt,
+         "timing check negative delay changed to 0 (ok for timing verifier)");
+        __nd_neg_del_warn = FALSE;
+       } 
+      tcp->tc_delrep2 = gwrk.g_delrep;
+      tcp->tclim2_du = gwrk.g_du;
+     }
+    }
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * extract wire and range
+ * know ranges always constants
+ */
+extern void __xtract_wirng(struct expr_t *xp, struct net_t **np,
+ int32 *i1, int32 *i2)
+{
+ word32 *wp;
+
+ switch ((byte) xp->optyp) {
+  case ID:
+   *np = xp->lu.sy->el.enp;
+   *i1 = *i2 = -1;
+   break;
+  case LSB:
+   *np = xp->lu.x->lu.sy->el.enp;
+   wp = &(__contab[xp->ru.x->ru.xvi]);
+   *i1 = *i2 = (int32) wp[0]; 
+   break;
+  case PARTSEL:
+   *np = xp->lu.x->lu.sy->el.enp;
+   *i1 = (int32) __contab[xp->ru.x->lu.x->ru.xvi];
+   *i2 = (int32) __contab[xp->ru.x->ru.x->ru.xvi];
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * build the start (earliest reference) event
+ * for period need the start change (ref.) event but no npp
+ */
+static struct tchg_t *bld_start_tchk_npp(struct tchk_t *tcp,
+ struct net_t *startnp, int32 bi1)
+{
+ register int32 ii;
+ word64 t;
+ struct tchg_t *start_tchgp;
+
+ start_tchgp = (struct tchg_t *) __my_malloc(sizeof(struct tchg_t));
+ start_tchgp->chgu.chgtcp = tcp;
+ start_tchgp->oldval = bld_npp_oldval(startnp, __inst_mod);
+ start_tchgp->lastchg = (word64 *)
+  __my_malloc(__inst_mod->flatinum*sizeof(word64));
+ /* FIXME - why are 2nd later change time and t chg rec unused here */
+ t = 0ULL;
+ for (ii = 0; ii < __inst_mod->flatinum; ii++) start_tchgp->lastchg[ii] = t;
+
+ /* for $period, no npp just placer holder set when data event occurs */ 
+ if (tcp->tchktyp != TCHK_PERIOD)
+  {
+   __cur_npnum = 0;
+   if (!startnp->n_isavec) bi1 = -1;
+   __conn_npin(startnp, bi1, bi1, FALSE, NP_TCHG, (struct gref_t *) NULL,
+     NPCHG_TCSTART, (char *) start_tchgp);
+
+   /* SJM - 04/04/02 need to turn on chg processing if only load */
+   /* DBG remove -- */
+   if (startnp->nlds == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   if (startnp->nlds->npnxt == NULL)
+    {
+     startnp->nchg_has_lds = TRUE;
+     startnp->nchg_nd_chgstore = TRUE;
+
+     /* if also no dces, now when add tchk load, must turn off all chged */
+     if (startnp->dcelst == NULL)
+      {
+       for (ii = 0; ii < __inst_mod->flatinum; ii++)
+        { startnp->nchgaction[ii] &= ~(NCHG_ALL_CHGED); }
+      }
+    }
+  }
+ return(start_tchgp);
+}
+
+/*
+ * build the check net pin event (later data event)
+ */
+static struct chktchg_t *bld_check_tchk_npp(struct net_t *chknp, int32 bi1)
+{
+ register int32 ii; 
+ word64 t;
+ struct chktchg_t *chk_tchgp;
+
+ chk_tchgp = (struct chktchg_t *) __my_malloc(sizeof(struct chktchg_t));
+ /* link to start and tchk master accessed through start but caller sets */
+ /* tchk master accessed through union in start tim chg */
+ /* FIXME - why are 2nd later change time and t chg rec unused here */
+ chk_tchgp->chklastchg = (word64 *)
+  __my_malloc(__inst_mod->flatinum*sizeof(word64));
+ t = 0ULL;
+ for (ii = 0; ii < __inst_mod->flatinum; ii++) chk_tchgp->chklastchg[ii] = t;
+ chk_tchgp->chkoldval = bld_npp_oldval(chknp, __inst_mod);
+ __cur_npnum = 0;
+ if (!chknp->n_isavec) bi1 = -1;
+ __conn_npin(chknp, bi1, bi1, FALSE, NP_TCHG, (struct gref_t *) NULL,
+  NPCHG_TCCHK, (char *) chk_tchgp);
+
+ /* SJM - 04/04/02 need to turn on chg processing if only load */
+ /* DBG remove -- */
+ if (chknp->nlds == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ if (chknp->nlds->npnxt == NULL)
+  {
+   chknp->nchg_has_lds = TRUE;
+   chknp->nchg_nd_chgstore = TRUE;
+
+   /* if also no dces, now when add tchk load, must turn off all chged */
+   if (chknp->dcelst == NULL)
+    {
+     for (ii = 0; ii < __inst_mod->flatinum; ii++)
+      { chknp->nchgaction[ii] &= ~(NCHG_ALL_CHGED); }
+    }
+  }
+ return(chk_tchgp);
+}
+
+/*
+ * build net pin old value for detecting path source and tc event bit chgs
+ */
+static byte *bld_npp_oldval(struct net_t *np, struct mod_t *mdp)
+{
+ int32 stval, ival, insts;
+ byte sval, *bp;
+
+ insts = mdp->flatinum;
+ if (np->n_stren)
+  { 
+   bp = (byte *) __my_malloc(insts);
+   __get_initval(np, &stval);
+   sval = (byte) stval;
+   set_byteval_(bp, insts, sval);
+   return(bp);
+  }
+ bp = (byte *) __my_malloc(insts);
+ ival = __get_initval(np, &stval);
+ set_byteval_(bp, insts, ival);
+ return(bp);
+}
+
+/*
+ * build net pin old value for detecting path source and tc event bit chgs
+ */
+static void reinit_npp_oldval(byte *bp, struct net_t *np, struct mod_t *mdp)
+{
+ int32 stval;
+ int32 insts, ival;
+ byte sval;
+
+ insts = mdp->flatinum;
+ if (np->n_stren)
+  { 
+   __get_initval(np, &stval);
+   sval = (byte) stval;
+   set_byteval_(bp, insts, sval);
+  }
+ else 
+  {
+   ival = __get_initval(np, &stval);
+   set_byteval_(bp, insts, ival);
+  }
+}
+
+/*
+ * prepare path elements and delays
+ * 1) convert path expr. lists to path elements
+ * 2) convert delays - know delay expression is 1, 2, 3, or 6 numbers
+ *    here delay expr. must still be scaled
+ * 3) check inout ports that are path srcs to be sure has input driver
+ *    pattern and path and path dest. has output driver pattern only
+ *
+ * LOOKATME - also somewhere back annotation can create IS forms ?
+ */
+static void prep_pths(void)
+{
+ register struct spcpth_t *pthp;
+ int32 rv, mod_has_path;
+ struct mod_t *mdp;
+ struct gate_t gwrk;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mspfy == NULL) continue;
+
+   __push_wrkitstk(mdp, 0);
+
+   mod_has_path = FALSE;
+   /* know each delay is NUMBER or REALNUM */ 
+   for (pthp = __inst_mod->mspfy->spcpths; pthp != NULL;
+    pthp = pthp->spcpthnxt)
+    {
+     /* do not convert since always will not get initialized - invisible */
+     if (pthp->pth_gone) continue;
+
+     if (!chk_pthels(pthp)) { pthp->pth_gone = TRUE; continue; }
+     if (!bldchk_pb_pthdsts(pthp)) { pthp->pth_gone = TRUE; continue; }
+
+     /* prepare the delay - notice this uses __inst_mod */
+     __add_pathdel_pnp(pthp);
+     __prep_delay(&gwrk, pthp->pth_du.pdels, TRUE, FALSE, "path delay",
+      TRUE, pthp->pthsym, TRUE);
+     if (__nd_neg_del_warn)
+      {
+       __gferr(981, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt, 
+        "path delay negative (used 0)");
+       __nd_neg_del_warn = FALSE;
+      } 
+     pthp->pth_delrep = gwrk.g_delrep;
+     pthp->pth_du = gwrk.g_du;
+     if (pthp->datasrcx != NULL)
+      {
+       __gfinform(481, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt, 
+        "path polarity operator ignored meaningless in simulator"); 
+      } 
+     /* and check for any illegal 0 delays */
+     if ((rv = __chk_0del(pthp->pth_delrep, pthp->pth_du, __inst_mod))
+      != DGOOD)
+      {
+       if (rv != DBAD_MAYBE0 && rv != DBAD_0)
+        {
+         __gferr(964, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+          "path delay illegal (%s delay form)", __to_deltypnam(__xs,
+          pthp->pth_delrep));
+        }
+       else
+        {
+         /* for IO PAD cells some 0 delays common */
+         if (rv == DBAD_MAYBE0)
+          {
+           __gfinform(483, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+           "path delay (%s form) contains some zero delays - primitive delay may be better",
+           __to_deltypnam(__xs, pthp->pth_delrep));
+          }
+         else
+          {
+           __gfinform(484, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+            "path delay (%s form) all zeros - no effect unless annotated to",
+            __to_deltypnam(__xs, pthp->pth_delrep));
+          }
+        }
+      }
+     mod_has_path = TRUE;
+    }
+   if (mod_has_path) emit_pthdst_bit_informs(__inst_mod);
+   __pop_wrkitstk();
+  }
+}
+
+/*
+ * check all path components - check things that apply to path elements
+ * check for bit by bit things when building sim path d.s.
+ */
+static int32 chk_pthels(struct spcpth_t *pthp)
+{
+ register int32 pei;
+ struct pathel_t *pep;
+ struct net_t *np;
+ int32 gd_path;
+
+ gd_path = TRUE;
+ for (pei = 0; pei <= pthp->last_pein; pei++)
+  {
+   pep = &(pthp->peins[pei]);
+   np = pep->penp; 
+   /* DBG remove */
+   if (!np->n_isapthsrc) __misc_terr(__FILE__, __LINE__);
+   /* --- */ 
+   /* path source can be vectored or scalared (can be reg) */
+   /* since source just timing check ref. event - record time of any chg */
+  }
+ for (pei = 0; pei <= pthp->last_peout; pei++)
+  {
+   pep = &(pthp->peouts[pei]);
+   np = pep->penp; 
+   if (np->n_isavec && !np->vec_scalared)
+    {
+     __gferr(825, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+      "vectored path destination wire %s illegal - must be scalared",
+      np->nsym->synam);
+     gd_path = FALSE;
+    }
+   /* if both has wire delay and dest., pth dst bit was turned off */
+   /* LOOKATME - not sure what to check here */
+   if (np->ntyp == N_TRIREG)
+    {
+     __gferr(826, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+      "path destination wire %s illegal trireg type", np->nsym->synam);
+     gd_path = FALSE;
+    }
+   else if (!np->n_isapthdst
+    || (np->nrngrep == NX_DWIR && np->nu.rngdwir->n_delrep != DT_PTHDST))
+    {
+     __gferr(826, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+      "path destination wire %s illegal - has wire delay", np->nsym->synam);
+     gd_path = FALSE;
+    }
+  }
+ return(gd_path);
+}
+
+/*
+ * build and check the per bit but not per inst path dest table lists
+ * all non bit specific path properties already checked
+ */
+static int32 bldchk_pb_pthdsts(struct spcpth_t *pthp)
+{
+ register int32 spi, dpi;
+ register struct pathel_t *spep, *dpep;
+ int32 pbiwid, pbowid;
+ int32 sbi, sbi2, dbi, dbi2, pb_gd, nxt_spep, nxt_dpep;
+ struct net_t *snp, *dnp;
+ struct tchg_t *src_tchg;
+
+ pb_gd = TRUE; 
+ /* needed since loop initialization indirect and lint cannot detect */
+ sbi = sbi2 = dbi = dbi2 = -1;
+ snp = dnp = NULL;
+ src_tchg = NULL;
+ if (pthp->pthtyp == PTH_PAR)
+  { 
+   get_pthbitwidths(pthp, &pbiwid, &pbowid);
+   if (pbiwid != pbowid)
+    {
+     __gferr(839, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+      "parallel path input bit length %d and output %d differ",
+      pbiwid, pbowid);
+     return(FALSE);
+    }
+   /* know bit lengths the same and if vectors or selects scalared */
+   for (spi = dpi = -1, nxt_spep = nxt_dpep = TRUE;;)   
+    {
+     if (nxt_spep)
+      {
+       /* before moving to next bit always add net pin element */
+       if (++spi > pthp->last_pein)
+        {
+         if (!nxt_dpep || (dpi + 1) <= pthp->last_peout)
+          __misc_terr(__FILE__, __LINE__);
+         break;
+        }
+       spep = &(pthp->peins[spi]);
+       snp = spep->penp;
+       if (!snp->n_isavec) sbi = sbi2 = 0; 
+       else
+        {
+         if (spep->pthi1 == -1) { sbi = snp->nwid - 1; sbi2 = 0; }  
+         else { sbi = spep->pthi1; sbi2 = spep->pthi2; }
+        }
+       /* build and add (if non already added) path dest. NP_DPTHSRC */
+       src_tchg = try_add_npp_dpthsrc(pthp, snp, sbi);
+       nxt_spep = FALSE; 
+      }
+     if (nxt_dpep)
+      {
+       /* if done, will always exit on src over run of end */ 
+       if (++dpi > pthp->last_peout) __misc_terr(__FILE__, __LINE__);
+       dpep = &(pthp->peouts[dpi]);
+       dnp = dpep->penp;
+       if (!dnp->n_isavec) dbi = dbi2 = 0; 
+       else
+        {
+         if (dpep->pthi1 == -1) { dbi = dnp->nwid - 1; dbi2 = 0; }  
+         else { dbi = dpep->pthi1; dbi2 = dpep->pthi2; }
+        }
+       nxt_dpep = FALSE; 
+      }
+     if (!bldchk_1bit_pthdst(pthp, snp, sbi, dnp, dbi, dnp->nwid, src_tchg))
+      pb_gd = FALSE;
+     if (--sbi < sbi2) nxt_spep = TRUE;
+     if (--dbi < dbi2) nxt_dpep = TRUE;
+    }
+   return(pb_gd);
+  }
+ /* handle full path case - for every source bit */
+ for (spi = 0; spi <= pthp->last_pein; spi++)
+  {
+   spep = &(pthp->peins[spi]);
+   snp = spep->penp;
+   if (!snp->n_isavec) sbi = sbi2 = 0; 
+   else
+    {
+     if (spep->pthi1 == -1) { sbi = snp->nwid - 1; sbi2 = 0; }  
+     else { sbi = spep->pthi1; sbi2 = spep->pthi2; }
+    }
+   for (; sbi >= sbi2; sbi--)
+    {
+     src_tchg = try_add_npp_dpthsrc(pthp, snp, sbi);
+     /* for given bit of input path - for every output path */ 
+     for (dpi = 0; dpi <= pthp->last_peout; dpi++)
+      {
+       dpep = &(pthp->peouts[dpi]);
+       dnp = dpep->penp;
+       if (!dnp->n_isavec) dbi = dbi2 = 0; 
+       else
+        {
+         if (dpep->pthi1 == -1) { dbi = dnp->nwid - 1; dbi2 = 0; }  
+         else { dbi = dpep->pthi1; dbi2 = dpep->pthi2; }
+        }
+       /* for every bit of destination path element */
+       for (; dbi >= dbi2; dbi--)
+        {
+         /* notice here, must check every sbits by dbits combination */
+         if (!bldchk_1bit_pthdst(pthp, snp, sbi, dnp, dbi, dnp->nwid,
+          src_tchg)) pb_gd = FALSE;
+        }
+      }
+    }
+  }
+ return(pb_gd);
+}
+
+/*
+ * build and add the path source net pin entry - like tc ref. event
+ * just records latest change
+ *
+ * for cases with mulitple source for 1 path only add first time
+ * here special indirect npp that allows indexing by bit and comparison
+ *
+ * if non empty or separate bit lists make sense
+ * best is to put in pass that checks to see if needed and adds after here
+ */
+static struct tchg_t *try_add_npp_dpthsrc(struct spcpth_t *pthp,
+ struct net_t *snp, int32 sbi)
+{
+ register int32 ii;
+ struct net_pin_t *npp;
+ word64 t;
+ struct tchg_t *start_tchgp;
+
+ if ((npp = find_1timchg_psnpp(snp, sbi, NPCHG_PTHSRC)) != NULL)
+  return(npp->elnpp.etchgp);
+
+ start_tchgp = (struct tchg_t *) __my_malloc(sizeof(struct tchg_t));
+ start_tchgp->chgu.chgpthp = pthp;
+ start_tchgp->oldval = bld_npp_oldval(snp, __inst_mod);
+ start_tchgp->lastchg = (word64 *)
+  __my_malloc(__inst_mod->flatinum*sizeof(word64));
+ 
+ t = 0ULL;
+ for (ii = 0; ii < __inst_mod->flatinum; ii++) start_tchgp->lastchg[ii] = t;
+ __cur_npnum = 0;
+ /* sbi access inst. table so must be 0 but must be -1 for npp */
+ if (!snp->n_isavec) sbi = -1;
+
+ /* with table for moving down to col. from inst. */
+ __conn_npin(snp, sbi, sbi, FALSE, NP_TCHG, (struct gref_t *) NULL,
+  NPCHG_PTHSRC, (char *) start_tchgp);
+ return(start_tchgp);
+}
+
+/*
+ * find a path source time change npp 
+ * know __inst_mod set 
+ */
+static struct net_pin_t *find_1timchg_psnpp(struct net_t *snp, int32 bi,
+ int32 subtyp)
+{
+ register struct net_pin_t *npp;
+ struct npaux_t *npauxp;
+
+ for (npp = snp->nlds; npp != NULL; npp = npp->npnxt) 
+  {
+   if (npp->npntyp == NP_TCHG && npp->chgsubtyp == subtyp
+    && ((npauxp = npp->npaux) != NULL && npauxp->nbi1 == bi)) return(npp);
+  }
+ return(NULL);
+}
+
+/*
+ * build 1 bit path dest. pair simulation path and do 1 bit path checking
+ * if error path dest. not built
+ *
+ * for scalar dbi will be 0
+ */
+static int32 bldchk_1bit_pthdst(struct spcpth_t *pthp, struct net_t *s_np,
+ int32 sbi, struct net_t *d_np, int32 dbi, int32 dnwid,
+ struct tchg_t *src_tchg)
+{
+ register int32 i;
+ int32 pb_gd;
+ struct pthdst_t *pdp;
+ char s1[RECLEN], s2[RECLEN];
+
+ /* for inouts - source and dest. cannot be the same */
+ pb_gd = TRUE;
+ if (d_np->nsym == s_np->nsym && dbi == sbi)
+  {
+   __gfwarn(617, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+    "ignoring path from %s%s to %s%s because source and destination same wire - simulators that split inout ports results may differ",
+    s_np->nsym->synam, bld_bitref(s1, s_np, sbi), d_np->nsym->synam,
+    bld_bitref(s2, d_np, dbi));
+   return(FALSE);
+  }
+ /* if previous error, net marked as gone here */
+ if (d_np->n_gone || s_np->n_gone) return(FALSE);
+
+ /* check for no more than one driver per bit */ 
+ /* LOOKATME - now driver for 1364 can be anything and */ 
+ /* tran or inouts are not drivers (not hard), does this work? */
+ if (!chk_biti_pthdst_driver(pthp, d_np, dbi)) return(FALSE);
+
+ /* know for dest. rng dwir already allocated */
+ /* if first bit of this wire, allocate table and mark all unused */
+ if (d_np->nu.rngdwir->n_du.pb_pthdst == NULL)
+  {
+   d_np->nu.rngdwir->n_du.pb_pthdst = (struct pthdst_t **)
+    __my_malloc(dnwid*sizeof(struct pthdst_t *));
+   for (i = 0; i < dnwid; i++) d_np->nu.rngdwir->n_du.pb_pthdst[i] = NULL;
+  }
+ /* if this is path with different source but same destination, allocate */
+ pdp = (struct pthdst_t *) __my_malloc(sizeof(struct pthdst_t));
+ pdp->pstchgp = src_tchg;
+ pdp->pdnxt = d_np->nu.rngdwir->n_du.pb_pthdst[dbi];
+ d_np->nu.rngdwir->n_du.pb_pthdst[dbi] = pdp;
+ return(pb_gd);
+}
+
+/*
+ * compute a path's input and output bit widths
+ */
+static void get_pthbitwidths(struct spcpth_t *pthp, int32 *pinwid,
+ int32 *poutwid)
+{
+ register int32 pei;
+ int32 pbwid;
+ struct pathel_t *pep;
+
+ for (pei = 0, pbwid = 0; pei <= pthp->last_pein; pei++)
+  {
+   pep = &(pthp->peins[pei]);
+   /* notice all ranges normalized to h:l here */
+   if (pep->pthi1 == -1) pbwid += pep->penp->nwid; 
+   else pbwid += (pep->pthi1 - pep->pthi2 + 1); 
+  }
+ *pinwid = pbwid;
+  for (pei = 0, pbwid = 0; pei <= pthp->last_peout; pei++)
+   {
+    pep = &(pthp->peouts[pei]);
+    if (pep->pthi1 == -1) pbwid += pep->penp->nwid;
+    else pbwid += (pep->pthi1 - pep->pthi2 + 1); 
+   }
+ *poutwid = pbwid;
+} 
+
+/*
+ * build a bit reference of form [<bit>] or ""
+ */
+static char *bld_bitref(char *s, struct net_t *np, int32 bi)
+{
+ if (!np->n_isavec || bi == -1) strcpy(s, "");
+ else sprintf(s, "[%d]", bi);
+ return(s);
+}
+
+/*
+ * check driver of bit to make sure bit has exactly one driver
+ */
+static int32 chk_biti_pthdst_driver(struct spcpth_t *pthp, struct net_t *np,
+ int32 biti)
+{
+ register struct net_pin_t *npp;
+ register struct npaux_t *npauxp;
+ int32 num_drvs;
+ char s1[RECLEN];
+
+ if (!np->n_isavec)
+  {
+   if (np->ndrvs == NULL) goto no_drv;
+   for (num_drvs = 0, npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+    {
+     if (npp->npntyp > NP_MDPRT) continue;
+     if (npp->npntyp <= NP_MDPRT && npp->np_xmrtyp != XNP_LOC)
+      goto pthdst_xmr;
+     if (++num_drvs > 1)
+      {
+       __gferr(827, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+        "path destination %s illegal - scalar wire has more than one driver",
+        np->nsym->synam);
+       return(FALSE);
+      }  
+    }
+   if (num_drvs == 0) goto no_drv;
+  }
+
+ /* here only check drivers of this bit */
+ for (num_drvs = 0, npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   if ((npauxp = npp->npaux) == NULL || npauxp->nbi1 == -1) goto got_match;
+   /* must never see IS form driver here - must cause copying earlier */ 
+   /* DBG remove --- */
+   if (npauxp->nbi1 == -2) __misc_terr(__FILE__, __LINE__);   
+   /* --- */
+
+   if (biti > npauxp->nbi1 || biti < npauxp->nbi2.i) continue;
+
+got_match:
+   /* found driver of bit - know only 1 */
+   if (npp->npntyp <= NP_MDPRT && npp->np_xmrtyp != XNP_LOC)
+    {
+pthdst_xmr:
+     __gferr(961, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+      "path destination %s%s cross module reference driver illegal",
+      np->nsym->synam, bld_bitref(s1, np, biti));
+     return(FALSE);
+    }
+   if (++num_drvs > 1)
+    {
+     __gferr(827, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+      "path destination %s%s illegal - more than one driver",
+      np->nsym->synam, bld_bitref(s1, np, biti));
+    }  
+  }
+ if (num_drvs != 0) return(TRUE);
+
+no_drv:
+ __gfwarn(616, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt,
+  "path destination %s%s does not have a driver - path delay no effect",
+  np->nsym->synam, bld_bitref(s1, np, biti));
+ return(TRUE);
+}
+
+/*
+ * emit path dest bit informs where bits not in any path for vectors
+ * processes path dests in current module.
+ * know module has specify section and at least one path
+ *
+ * SJM 06/06/00 - also emitting inform for inout as both path src/dest
+ */
+static void emit_pthdst_bit_informs(struct mod_t *mdp)
+{
+ register int32 ni, bi;
+ register struct net_t *np;
+ 
+ if (mdp->mnnum == 0) return;
+ for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+  {
+   /* SJM 06/06/00 - emit inform if inout used as path src and dst */   
+   /* SJM 07/16/01 - removed warning, it was wrong - inout paths now work */
+
+   if (!np->n_isapthdst || !np->n_isavec) continue;
+   /* DBG remove --- */
+   if (np->nu.rngdwir->n_delrep != DT_PTHDST)
+    __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   
+   for (bi = 0; bi < np->nwid; bi++)   
+    {
+     if (np->nu.rngdwir->n_du.pb_pthdst[bi] == NULL)
+      {
+       __gfinform(474, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+        "for delay path destination %s, bit %d is not destionation of any path",
+        np->nsym->synam, bi); 
+      }
+    }
+  }
+}
+
+/*
+ * check path delay non zero and non expression
+ */
+extern int32 __chk_0del(word32 drep, union del_u du, struct mod_t *mdp)
+{
+ register int32 i;
+ int32 some_0, all_0;
+
+ some_0 = FALSE;
+ all_0 = TRUE;
+ switch ((byte) drep) {
+  /* think ,, form will work right here for timing checks */
+  case DT_NONE: return(DBAD_NONE);
+  case DT_1X: case DT_4X: return(DBAD_EXPR);
+  case DT_1V:
+   if (*du.d1v == 0ULL) return(DBAD_0);
+   return(DGOOD);
+  case DT_IS1V:
+   for (i = 0; i < mdp->flatinum; i++)
+    { if (du.dis1v[i] == 0ULL) some_0 = TRUE; else all_0 = FALSE; }
+   break;
+  case DT_IS1V1:
+   for (i = 0; i < mdp->flatinum; i++)
+    { if (du.dis1v1[i] == 0) some_0 = TRUE; else all_0 = FALSE; }
+   break;
+  case DT_IS1V2:
+   for (i = 0; i < mdp->flatinum; i++)
+    { if (du.dis1v2[i] == 0) some_0 = TRUE; else all_0 = FALSE; }
+   break;
+  case DT_4V:
+   for (i = 0; i < 4; i++)
+    { if (du.d4v[i] == 0ULL) some_0 = TRUE; else all_0 = FALSE; }
+   break;
+  case DT_IS4V:
+   for (i = 0; i < 4*mdp->flatinum; i++)
+    { if (du.dis4v[i] == 0ULL) some_0 = TRUE; else all_0 = FALSE; }
+   break; 
+  case DT_IS4V1:
+   some_0 = FALSE;
+   all_0 = TRUE;
+   for (i = 0; i < 4*mdp->flatinum; i++)
+    { if (du.dis4v1[i] == 0) some_0 = TRUE; else all_0 = FALSE; }
+   break;
+  case DT_IS4V2:
+   some_0 = FALSE;
+   all_0 = TRUE;
+   for (i = 0; i < 4*mdp->flatinum; i++)
+    { if (du.dis4v2[i] == 0) some_0 = TRUE; else all_0 = FALSE; }
+   break;
+  case DT_16V:
+   for (i = 1; i < 16; i++)
+    {
+     /* must skip unused that will be 0 */
+     if (i == 5 || i == 10 || i == 15) continue;
+     if (du.d16v[i] == 0ULL) some_0 = TRUE; else all_0 = FALSE;
+    }
+   break;
+  case DT_IS16V:
+   for (i = 1; i < 16*mdp->flatinum; i++)
+    { 
+     if ((i % 16) == 5 || (i % 16) == 10 || (i % 16) == 15) continue; 
+     if (du.dis16v[i] == 0ULL) some_0 = TRUE; else all_0 = FALSE;
+    }
+   break;
+  case DT_IS16V1:
+   for (i = 1; i < 16*mdp->flatinum; i++)
+    {
+     if ((i % 16) == 5 || (i % 16) == 10 || (i % 16) == 15) continue; 
+     if (du.dis16v1[i] == 0) some_0 = TRUE; else all_0 = FALSE;
+    }
+   break;
+  case DT_IS16V2:
+   for (i = 0; i < 16*mdp->flatinum; i++)
+    {
+     if ((i % 16) == 5 || (i % 16) == 10 || (i % 16) == 15) continue; 
+     if (du.dis16v2[i] == 0) some_0 = TRUE; else all_0 = FALSE;
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ if (all_0) return(DBAD_0); 
+ if (some_0) return(DBAD_MAYBE0);
+ return(DGOOD);
+}
+
+/*
+ * DESIGN PART FREE ROUTINES 
+ */
+
+/*
+ * free one statement
+ * this requires set __inst_mod  
+ * LOOKATME - how come only called from interactive and always 1 flat inst?
+ */
+extern void __free_1stmt(struct st_t *stp)
+{
+ int32 fji;
+ struct for_t *frp;
+ struct qconta_t *qcafs;
+ struct st_t *fjstp;
+
+ if (stp == NULL) return;
+
+ switch ((byte) stp->stmttyp) {
+  case S_NULL: case S_STNONE: break;
+  case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA: case S_NBPROCA:
+   __free_xtree(stp->st.spra.lhsx);
+   __free_xtree(stp->st.spra.rhsx);
+   break;
+  case S_IF:
+   __free_xtree(stp->st.sif.condx);
+   __free_stlst(stp->st.sif.thenst);
+   __free_stlst(stp->st.sif.elsest);
+   break;
+  case S_CASE:
+   __free_xtree(stp->st.scs.csx);
+   /* this also frees default: (maybe just place holder) and list els */
+   free_csitemlst(stp->st.scs.csitems);
+   break;
+  case S_REPEAT:
+   __free_xtree(stp->st.srpt.repx);
+   /* if after preparation need to free temp. repeat count array */
+   /* LOOKATME - why is this only per. inst. stor. place in stmts? */ 
+   if (stp->st.srpt.reptemp != NULL)
+    __my_free((char *) stp->st.srpt.reptemp,
+     __inst_mod->flatinum*sizeof(word32 *));
+   __free_stlst(stp->st.srpt.repst);
+   break;
+  case S_FOREVER:
+  case S_WHILE:
+   __free_xtree(stp->st.swh.lpx);
+   __free_stlst(stp->st.swh.lpst);
+   break;
+  case S_WAIT:
+   __free_xtree(stp->st.swait.lpx);
+   /* free statement list since del. ctrl. points to wait itself */
+   __free_stlst(stp->st.swait.lpst);
+   /* do not free action statement which is wait itself */
+   free_dctrl(stp->st.swait.wait_dctp, FALSE);
+   break;
+  case S_FOR:
+   frp = stp->st.sfor;
+   /* notice for assign already freed */
+   __free_xtree(frp->fortermx);
+   __free_1stmt(frp->forinc);
+   __free_stlst(frp->forbody);
+   __my_free((char *) frp, sizeof(struct for_t));
+   break;
+  case S_DELCTRL: free_dctrl(stp->st.sdc, TRUE); break;
+  case S_UNBLK:
+   __free_stlst(stp->st.sbsts);
+   break;
+  case S_UNFJ:
+   for (fji = 0;; fji++)
+    {
+     if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+     __free_stlst(fjstp); 
+    }
+   __my_free((char *) stp->st.fj.fjstps, (fji + 1)*sizeof(struct st_t *)); 
+   __my_free((char *) stp->st.fj.fjlabs, (fji + 1)*sizeof(int32)); 
+   break;
+  case S_TSKCALL:
+   __free_xtree(stp->st.stkc.targs);
+   /* cannot free symbol */
+   /* only interactive can be freed so cannot have tfrec */
+   if (stp->st.stkc.tkcaux.trec != NULL) __misc_terr(__FILE__, __LINE__);
+   break;
+  case S_QCONTA:
+   qcafs = stp->st.sqca;
+   /* notice for assign already freed */
+   __free_xtree(qcafs->qclhsx);
+   __free_xtree(qcafs->qcrhsx);
+   __my_free((char *) qcafs, sizeof(struct qconta_t));
+   break;
+  case S_QCONTDEA:
+   __free_xtree(stp->st.sqcdea.qcdalhs);
+   break;
+  case S_CAUSE: break;
+  case S_DSABLE:
+   __free_xtree(stp->st.sdsable.dsablx);
+   break;
+  /* statement added for execution */
+  case S_REPSETUP:
+   /* union field unused */
+   stp->st.scausx = NULL;
+   break;
+  case S_REPDCSETUP:
+   /* union field unused */
+   stp->st.scausx = NULL;
+   break;
+  case S_GOTO: break;
+  /* notice named block non freeable (at least for now) */
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * free a delay control record
+ */
+static void free_dctrl(struct delctrl_t *dctp, int32 free_action)
+{
+ /* free the delay value or expr. for event controls */
+ __free_del(dctp->dc_du, dctp->dc_delrep, __inst_mod->flatinum);
+
+ /* SJM - 08/03/01 - also free repeat cout expr if present */
+ if (dctp->repcntx != NULL) __free_xtree(dctp->repcntx);
+
+ /* for delay not event control, will not have scheduled tevs */
+ if (dctp->dceschd_tevs != NULL)
+  __my_free((char *) dctp->dceschd_tevs,
+   __inst_mod->flatinum*sizeof(struct tev_t *));
+ dctp->dceschd_tevs = NULL;
+ if (free_action) __free_stlst(dctp->actionst);
+ __my_free((char *) dctp, sizeof(struct delctrl_t));
+}
+
+/*
+ * free case item list
+ */
+static void free_csitemlst(register struct csitem_t *csip)
+{
+ struct csitem_t *csip2;
+
+ for (;csip != NULL;)
+  {
+   csip2 = csip->csinxt;
+   /* nil expr list always nil for default */
+   if (csip->csixlst != NULL) __free_xprlst(csip->csixlst);
+   /* if no default, stmt of first nil */
+   if (csip->csist != NULL) __free_stlst(csip->csist);
+   __my_free((char *) csip, sizeof(struct csitem_t));
+   csip = csip2;
+  }
+}
+
+/*
+ * free a list of statements - i.e. next fields connect to make block list
+ */
+extern void __free_stlst(register struct st_t *stp)
+{
+ register struct st_t *stp2;
+
+ for (; stp != NULL;) { stp2 = stp->stnxt; __free_1stmt(stp); stp = stp2; }
+}
+
+/*
+ * free an expression list
+ */
+extern void __free_xprlst(struct exprlst_t *xplp)
+{
+ register struct exprlst_t *xplp2;
+
+ for (; xplp != NULL;)
+  {
+   xplp2 = xplp->xpnxt;
+   __free_xtree(xplp->xp);
+   __my_free((char *) xplp, sizeof(struct exprlst_t));
+   xplp = xplp2;
+  }
+}
+
+/*
+ * ROUTINES TO TRANFORM INTERNAL NET LIST FOR COMPILATION 
+ */
+
+/*
+ * process all net list data structures tranforming for compilation
+ */
+extern void __xform_nl_to_modtabs(void)
+{
+ struct mod_t *mdp;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   __push_wrkitstk(mdp, 0);
+
+   /* allocate table filled with all exprs in module */
+   if (__inst_mod->mexprnum == 0) __inst_mod->mexprtab = NULL;
+   else
+    {
+     __inst_mod->mexprtab = (struct expr_t *)
+      __my_malloc(__inst_mod->mexprnum*sizeof(struct expr_t));
+    }
+   __last_modxi = -1;
+
+   if (__inst_mod->mstnum == 0) __inst_mod->msttab = NULL;
+   else
+    {
+     __inst_mod->msttab = (struct st_t *)
+      __my_malloc(__inst_mod->mstnum*sizeof(struct st_t));
+    }
+   __last_modsti = -1;
+   
+   cmp_xform_ports();
+   cmp_xform_ialst();
+   cmp_xform_inst_conns();
+   cmp_xform_gates();
+   cmp_xform_contas();
+   cmp_xform_tasks();
+ 
+   if (__inst_mod->mspfy != NULL) cmp_xform_specify();
+
+   /* LOOKATME - do analog block statement and expressions need to be */
+   /* xformed since not accessed in digital sim, think not */
+
+   /* many expressions (say from xmrs) not copied since not needed during */ 
+   /* exec - check and adjust mod expr no. here */
+   if (__last_modxi + 1 > __inst_mod->mexprnum)
+    __misc_terr(__FILE__, __LINE__);
+   __inst_mod->mexprnum = __last_modxi + 1;
+
+   /* DBG remove --
+   if (__last_modsti + 1 != __inst_mod->mstnum)
+    __misc_terr(__FILE__, __LINE__);
+   --- */
+   __pop_wrkitstk();
+
+/* DBG remove ---
+   if (__debug_flg)
+    {
+     __dmp_exprtab(mdp, mdp->mexprnum);
+     __dmp_msttab(mdp, mdp->mstnum);
+    }
+--- */
+  }
+}
+
+/*
+ * compile transform all port lists for one module 
+ */
+static void cmp_xform_ports(void)
+{
+ register int32 pi, pnum;
+ register struct mod_pin_t *mpp;
+
+ mpp = &(__inst_mod->mpins[0]);  
+ pnum = __inst_mod->mpnum;
+ for (pi = 0; pi < pnum; pi++, mpp++)
+  {
+   mpp->mpref = mv1_expr_totab(mpp->mpref);
+  }
+}
+
+/*
+ * copy a statement list (linked list of statements)
+ */
+static struct st_t *cmp_xform_lstofsts(register struct st_t *ostp)
+{
+ register struct st_t *nstp_hdr, *nstp, *last_nstp, *ostp2;
+
+ nstp_hdr = NULL;
+ for (last_nstp = NULL; ostp != NULL;)
+  {
+   nstp = cmp_xform1_stmt(ostp, last_nstp);
+   /* must not free internal parts of old statement */
+
+   if (last_nstp == NULL) nstp_hdr = nstp; else last_nstp->stnxt = nstp;
+   nstp->stnxt = NULL;
+   last_nstp = nstp;
+   ostp2 = ostp->stnxt;
+   __my_free((char *) ostp, sizeof(struct st_t));
+   ostp = ostp2;
+  }
+ return(nstp_hdr);
+}
+
+/*
+ * compile transform one statement
+ */
+static struct st_t *cmp_xform1_stmt(register struct st_t *ostp,
+ struct st_t *last_stp)
+{
+ register struct st_t *nstp;
+ int32 fji;
+ struct sy_t *syp; 
+ struct systsk_t *stbp;
+ struct st_t *fjstp;
+
+/* DBG remove --
+ if (__debug_flg)
+  {
+-* --
+   __dbg_msg("%04d: AT %s %s - STMT XFORM (%s)\n", ostp->stalloc_ndx,
+    __bld_lineloc(__xs, ostp->stfnam_ind, ostp->stlin_cnt),
+    __inst_mod->msym->synam, __to_sttyp(__xs2, ostp->stmttyp));
+-- *-
+-* -- *-
+   __dbg_msg("AT %s %s - STMT XFORM %04d (%s)\n",
+    __bld_lineloc(__xs, ostp->stfnam_ind, ostp->stlin_cnt),
+    __inst_mod->msym->synam, __last_modsti + 1,
+    __to_sttyp(__xs2, ostp->stmttyp));
+-* -- *-
+  }
+--- */
+
+ if (ostp == NULL) return(NULL);
+
+ /* DBG remove -- */
+ if (__last_modsti + 2 > __inst_mod->mstnum) __misc_terr(__FILE__, __LINE__);
+ /* ---*/
+
+ nstp = &(__inst_mod->msttab[++__last_modsti]);
+
+ /* because union for common case now in statement, gets copied here */
+ *nstp = *ostp;
+ nstp->stnxt = NULL;
+
+ switch ((byte) ostp->stmttyp) {
+  /* null just has type value and NULL pointer (i.e. ; by itself) */
+  case S_NULL: case S_STNONE: break;
+  /* SJM 09/24/01 - for fj, must not make for assign separate stmt */
+  case S_PROCA: case S_RHSDEPROCA: case S_NBPROCA: case S_FORASSGN:
+   nstp->st.spra.lhsx = mv1_expr_totab(ostp->st.spra.lhsx);
+   nstp->st.spra.rhsx = mv1_expr_totab(ostp->st.spra.rhsx);
+   break;
+  case S_IF:
+   nstp->st.sif.condx = mv1_expr_totab(ostp->st.sif.condx);
+   nstp->st.sif.thenst = cmp_xform_lstofsts(ostp->st.sif.thenst);
+   nstp->st.sif.elsest = cmp_xform_lstofsts(ostp->st.sif.elsest);
+   break;
+  case S_CASE:
+   nstp->st.scs.castyp = ostp->st.scs.castyp;
+   nstp->st.scs.maxselwid = ostp->st.scs.maxselwid;
+   nstp->st.scs.csx = mv1_expr_totab(ostp->st.scs.csx);
+
+   /* if case has no default, st and expr list fields nil */ 
+   /* no copy but must transform st lists and expr inside */
+   nstp->st.scs.csitems = ostp->st.scs.csitems;
+   cmp_xform_csitemlst(nstp->st.scs.csitems);
+   break;
+  case S_REPEAT:
+   nstp->st.srpt.repx = mv1_expr_totab(ostp->st.srpt.repx);
+   /* move ptr to new, old freed so no wrong cross links */
+   nstp->st.srpt.reptemp = ostp->st.srpt.reptemp;
+   nstp->st.srpt.repst = cmp_xform_lstofsts(ostp->st.srpt.repst);
+   break;
+  case S_REPSETUP:
+   /* no contents just indicator for setting up next actual rep stmt */
+   break;
+ 
+  case S_FOREVER: case S_WHILE:
+   nstp->st.swh.lpx = mv1_expr_totab(ostp->st.swh.lpx);
+   nstp->st.swh.lpst = cmp_xform_lstofsts(ostp->st.swh.lpst);
+   break;
+  case S_WAIT:
+   nstp->st.swait.lpx = mv1_expr_totab(ostp->st.swait.lpx);
+   nstp->st.swait.lpst = cmp_xform_lstofsts(ostp->st.swait.lpst);
+   /* here just move pointer since needed by new statement in table */
+   /* LOOKATME - is this already copied */
+   nstp->st.swait.wait_dctp = ostp->st.swait.wait_dctp;
+   /* also point dctp statement to new one */
+   nstp->st.swait.wait_dctp->actionst = nstp->st.swait.lpst;
+   break;
+  case S_FOR:
+   /* DBG remove --- */
+   if (last_stp == NULL) __misc_terr(__FILE__, __LINE__);
+   if (last_stp->stmttyp != S_FORASSGN) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* notice using already allocated storage - assumes dynamic dlopen so */
+   /* no need to save and copy storage to runtime */
+   nstp->st.sfor = ostp->st.sfor;
+   nstp->st.sfor->forassgn = last_stp;
+   /* still need to xform expressions */
+   nstp->st.sfor->fortermx = mv1_expr_totab(ostp->st.sfor->fortermx);
+
+   /* for inc xformed in here */
+   nstp->st.sfor->forbody = cmp_xform_lstofsts(ostp->st.sfor->forbody);
+   
+   {
+    struct st_t *stp2, *last_stp2, *last_stp3;
+
+    stp2 = nstp->st.sfor->forbody;
+    for (last_stp2 = last_stp3 = NULL; stp2 != NULL; stp2 = stp2->stnxt)
+     {
+      last_stp3 = last_stp2;
+      last_stp2 = stp2;
+     }
+    /* DBG remove --- */
+    if (last_stp3->stmttyp != S_PROCA) __misc_terr(__FILE__, __LINE__);
+    /* --- */
+    nstp->st.sfor->forinc = last_stp3;
+   }
+   break;
+  case S_REPDCSETUP:
+   /* no contents just indicator for setting up next actual rep stmt */
+   break;
+  case S_DELCTRL:
+   /* stmt contents do not fit in record so link old ptr to new */ 
+   nstp->st.sdc = ostp->st.sdc;
+   /* here fix but no need to copy dellst */
+   cmp_xform_delay(nstp->st.sdc->dc_delrep, nstp->st.sdc->dc_du);
+   nstp->st.sdc->actionst = cmp_xform_lstofsts(ostp->st.sdc->actionst);
+   break;
+  case S_NAMBLK:
+   nstp->st.snbtsk->tsksyp->el.etskp->st_namblkin = nstp;
+   /* for named block, no continuation - must be subthread except in func */
+   nstp->st.snbtsk->tskst = cmp_xform_lstofsts(ostp->st.snbtsk->tskst);
+   break;
+  case S_UNBLK:
+   nstp->st.sbsts = cmp_xform_lstofsts(ostp->st.sbsts);
+   break;
+  case S_UNFJ:
+   for (fji = 0;; fji++)
+    {
+     if ((fjstp = ostp->st.fj.fjstps[fji]) == NULL) break;
+     nstp->st.fj.fjstps[fji] = cmp_xform_lstofsts(fjstp);
+    }
+   break;
+  case S_TSKCALL:
+   /* find new task through old to new symbol */
+   /* for system tasks since points to itself gets same (right) sym */
+   nstp->st.stkc.tsksyx = mv1_expr_totab(ostp->st.stkc.tsksyx);
+   nstp->st.stkc.targs = mv1_expr_totab(ostp->st.stkc.targs);
+   /* task itself xforms in xform task routine */
+
+   /* need to fixup PLI tf systf cross linked tf recs only - not vpi */
+   syp = nstp->st.stkc.tsksyx->lu.sy;
+   if (syp->sytyp == SYM_STSK)
+    {
+     stbp = syp->el.esytbp;
+     /* only way to tell if tf_ is by range of tsk veriusertf index */
+     if (stbp->stsknum >= BASE_VERIUSERTFS
+      && (int32) stbp->stsknum <= __last_veriusertf)
+      {
+       xform_tf_syst_enable(nstp);
+      }
+    }
+   /* for vpi registered and built-in system tasks nothing to do */  
+   /* for vpi systasks accessing vpi_ systf has index and values */
+   /* needed in vpi_ t vpi systf data record */
+   break;
+  case S_QCONTA:
+   /* SJM 02/23/02 - now malloc aux info, but can still use - no new malloc */
+   nstp->st.sqca->qcatyp = ostp->st.sqca->qcatyp;
+   nstp->st.sqca->regform = ostp->st.sqca->regform;
+   nstp->st.sqca->qclhsx = mv1_expr_totab(ostp->st.sqca->qclhsx);
+   nstp->st.sqca->qcrhsx = mv1_expr_totab(ostp->st.sqca->qcrhsx);
+   nstp->st.sqca->rhs_qcdlstlst = ostp->st.sqca->rhs_qcdlstlst;
+   break;
+  case S_QCONTDEA:
+   nstp->st.sqcdea.qcdatyp = ostp->st.sqcdea.qcdatyp;
+   nstp->st.sqcdea.regform = ostp->st.sqcdea.regform;
+   nstp->st.sqcdea.qcdalhs = mv1_expr_totab(ostp->st.sqcdea.qcdalhs);
+   break;
+  case S_CAUSE:
+   /* must copy expr. even though know just event name */
+   nstp->st.scausx = mv1_expr_totab(ostp->st.scausx);
+   break;
+  case S_DSABLE:
+   nstp->st.sdsable.dsablx = mv1_expr_totab(ostp->st.sdsable.dsablx);
+   break;
+  case S_GOTO:
+   /* must 0 out dest. since fixed later with right target */
+   nstp->st.sgoto = NULL;
+   break;
+  /* LOOKATME - need name resolving statement type no? */
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(nstp);
+}
+
+/*
+ * xform tf_ style sys task enable by updating tf rec 
+ *
+ * not needed for vpi style syst enables because compiletf already called
+ *
+ * LOOKATME - could pass systf ptrs since already computed
+ */
+static void xform_tf_syst_enable(struct st_t *nstp)
+{
+ register int32 ai;
+ struct tskcall_t *tkcp;
+ struct tfrec_t *tfrp;
+ struct expr_t *argxp;
+ struct tfarg_t *tfap;
+
+ tkcp = &(nstp->st.stkc);
+ /* DBG remove --- */
+ if (tkcp->tkcaux.trec == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ /* tsk call record contains tfrec for PLI 1.0 registered */
+ tfrp = tkcp->tkcaux.trec;
+
+ /* back link tfrec for systask enable to new moved stmt */
+ tfrp->tfu.tfstp = nstp;
+ /* notice for tsk, targs 1st left has actual argument - no need for next */
+ argxp = tkcp->targs;
+ /* update all the tfarg expr ptrs to moved expr */
+ for (ai = 1; ai < tfrp->tfanump1; ai++, argxp = argxp->ru.x)
+  {
+   /* DBG remove -- */
+   if (argxp == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   tfap = &(tfrp->tfargs[ai]);
+   tfap->arg.axp = argxp->lu.x;
+  }
+}
+
+/*
+ * ROUTINES TO XFORM (MOVE TO INDEXABLE TABLE) EXPRESSIONS
+ */
+/*
+ * routine to move one leaf or non leaf expression into table
+ */
+static struct expr_t *mv1_expr_totab(struct expr_t *oxp)
+{ 
+ struct expr_t *nxp;
+ struct sy_t *syp;
+ struct sysfunc_t *sfbp;
+
+ if (oxp == NULL) return(NULL);
+
+ /* DBG remove -- */
+ if (__last_modxi + 2 > __inst_mod->mexprnum) __misc_terr(__FILE__, __LINE__);
+ /* ---*/
+
+ nxp = &(__inst_mod->mexprtab[++__last_modxi]);
+ switch ((byte) oxp->optyp) { 
+  case ID: case OPEMPTY:
+   /* op empty works since both lu and ru are nil */
+   *nxp = *oxp;
+   /* notice symbol name in symbol table so ptr can be subtracted from */
+   /* symbol table base */
+   break;
+  case GLBREF:
+   /* for global ru is gref and lu is symbol in target mod symbol table */
+   /* know ru.grp always in module and already built as table */
+   *nxp = *oxp;
+   nxp->ru.grp->gxndp = nxp;
+   break;
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM:
+   /* know constant table already built so can just copy */ 
+   *nxp = *oxp;
+   break;
+  case FCALL:
+   syp = oxp->lu.x->lu.sy;
+   *nxp = *oxp;
+   /* start by copying call expr. */
+   if (oxp->lu.x != NULL) nxp->lu.x = mv1_expr_totab(oxp->lu.x);
+   if (oxp->ru.x != NULL) nxp->ru.x = mv1_expr_totab(oxp->ru.x);
+
+   /* need to fixup PLI systf cross linked records when change repl expr */
+   if (syp->sytyp == SYM_SF)
+    {
+     sfbp = syp->el.esyftbp;
+     if (sfbp->tftyp == SYSF_TF) xform_tf_sysf_call(nxp);
+    }
+   /* for vpi registered and built-in system function nothing to do */  
+   /* for vpi sysfuncs accessing vpi_ sysfunc t has index and values */
+   /* needed in vpi_ t vpi systf data record */
+   break;
+  case TOK_NONE: case BADOBJ: case LITSTR:
+   __misc_terr(__FILE__, __LINE__); break;
+  default:
+   *nxp = *oxp;
+   if (oxp->lu.x != NULL) nxp->lu.x = mv1_expr_totab(oxp->lu.x);
+   if (oxp->ru.x != NULL) nxp->ru.x = mv1_expr_totab(oxp->ru.x);
+ }
+ /* last step - contained in expr. link in parents right dir ptr */
+ __my_free((char *) oxp, sizeof(struct expr_t)); 
+ return(nxp);
+}
+
+/*
+ * xform tf_ style sysf call by updating sysf call record
+ *
+ * not needed for vpi style sysf calls because compiletf already called
+ */
+static void xform_tf_sysf_call(struct expr_t *nxp)
+{
+ register int32 ai;
+ struct sy_t *syp;
+ struct sysfunc_t *sfbp;
+ struct tfrec_t *tfrp;
+ struct expr_t *argxp;
+ struct tfarg_t *tfap;
+
+ syp = nxp->lu.x->lu.sy;
+ sfbp = syp->el.esyftbp;
+
+ /* DBG remove --- */
+ if (sfbp->syfnum < BASE_VERIUSERTFS
+  || sfbp->syfnum > __last_veriusertf) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ /* szu field used for ptr to the tfrec - nothing to set in new expr*/
+ tfrp = nxp->lu.x->szu.xfrec;
+ /* back link tfrec for sysf call to new moved expr */
+ tfrp->tfu.callx = nxp;
+ /* update all the tfarg expr ptrs to moved expr */
+ argxp = nxp->ru.x;
+ for (ai = 1; ai < tfrp->tfanump1; ai++, argxp = argxp->ru.x)
+  {
+   /* DBG remove -- */
+   if (argxp == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   tfap = &(tfrp->tfargs[ai]);
+   tfap->arg.axp = argxp->lu.x;
+  }
+}
+
+/*
+ * compile transform list of case items
+ *
+ * no need to copy but must replace statement lists and exprs inside
+ */
+static void cmp_xform_csitemlst(register struct csitem_t *csip)
+{
+ register struct exprlst_t *xplp;
+
+ for (; csip != NULL; csip = csip->csinxt)
+  {
+   if (csip->csist != NULL) csip->csist = cmp_xform_lstofsts(csip->csist);
+   /* know for first default, selector x list nil */
+   for (xplp = csip->csixlst; xplp != NULL; xplp = xplp->xpnxt)
+    {
+     xplp->xp = mv1_expr_totab(xplp->xp);
+    }
+  }
+}
+
+/*
+ * must replace expressions in case dellst one of the expr forms
+ *
+ * by here delays already converted to one of 16 forms
+ */
+static void cmp_xform_delay(int32 drep, union del_u du)
+{
+ struct expr_t *tmpxp;
+
+ switch ((byte) drep) {
+  /* nothing to do for the delay value table forms */
+  case DT_NONE:
+  case DT_1V: case DT_IS1V: case DT_IS1V1: case DT_IS1V2: case DT_4V:
+  case DT_IS4V: case DT_IS4V1: case DT_IS4V2: case DT_16V: case DT_IS16V:
+  case DT_IS16V1: case DT_IS16V2:
+   break;
+  case DT_1X:
+   /* since must copy from something that gets freed, must first */
+   /* copy expr to tmp that is then immediately freed by expr mv */
+   tmpxp = __sim_copy_expr(du.d1x);
+   du.d1x = mv1_expr_totab(tmpxp);
+   break;
+  case DT_4X:
+   if (du.d4x[0] != NULL)
+    { tmpxp = __sim_copy_expr(du.d4x[0]); du.d4x[0] = mv1_expr_totab(tmpxp); }
+   if (du.d4x[1] != NULL)
+    { tmpxp = __sim_copy_expr(du.d4x[1]); du.d4x[1] = mv1_expr_totab(tmpxp); }
+   if (du.d4x[2] != NULL)
+    { tmpxp = __sim_copy_expr(du.d4x[2]); du.d4x[2] = mv1_expr_totab(tmpxp); }
+   if (du.d4x[3] != NULL)
+    { tmpxp = __sim_copy_expr(du.d4x[3]); du.d4x[3] = mv1_expr_totab(tmpxp); }
+   break;
+  case DT_CMPLST:
+   /* LOOKATME - is this legal */
+   __misc_terr(__FILE__, __LINE__);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * GOTO FIXUP ROUTINES
+ */
+
+/*
+ * compile transform all initial/always statement lists
+ */
+static void cmp_xform_ialst(void)
+{
+ register struct ialst_t *ialp;
+
+ __processing_func = FALSE;
+ for (ialp = __inst_mod->ialst; ialp != NULL; ialp = ialp->ialnxt)
+  {
+   ialp->iastp = cmp_xform_lstofsts(ialp->iastp);
+  } 
+ __prpsti = 0;
+ __nbsti = -1;
+ __prpstk[0] = NULL;
+ for (ialp = __inst_mod->ialst; ialp != NULL; ialp = ialp->ialnxt)
+  {
+   if (ialp->iatyp == ALWAYS)
+    {
+     cxf_fixup_loopend_goto(ialp->iastp, ialp->iastp);
+    }
+   cxf_fixup_lstofsts_gotos(ialp->iastp, TRUE);
+
+   /* DBG remove --- */ 
+   if (__prpsti != 0) __misc_terr(__FILE__, __LINE__); 
+   /* --- */
+  } 
+}
+
+/*
+ * fixup loop end gotos
+ */
+static void cxf_fixup_loopend_goto(struct st_t *begstp, struct st_t *targstp)
+{
+ register struct st_t *stp; 
+ struct st_t *last_stp;
+
+ /* DBG remove --- */
+ if (begstp == NULL) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* find last statement in loop - know has at least one */
+ for (stp = begstp, last_stp = NULL; stp != NULL; stp = stp->stnxt)
+  last_stp = stp;
+ /* DBG remove --- */
+ if (last_stp == NULL) __arg_terr(__FILE__, __LINE__);
+ if (last_stp->stmttyp != S_GOTO) __arg_terr(__FILE__, __LINE__);
+ if (!last_stp->lpend_goto) __arg_terr(__FILE__, __LINE__);
+ if (targstp == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ last_stp->st.sgoto = targstp;
+
+ if (__debug_flg)
+  {
+   char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+   __dbg_msg("++ loop: xform goto after %s at %s back to stmt %s at %s\n",
+    __to_sttyp(s1, last_stp->stmttyp), __bld_lineloc(__xs, 
+    last_stp->stfnam_ind, last_stp->stlin_cnt), __to_sttyp(s2,
+    begstp->stmttyp), __bld_lineloc(s3, targstp->stfnam_ind,
+    targstp->stlin_cnt));
+  }
+}
+
+/*
+ * fixup all gotos in list of stmts
+ *
+ * know all statement transformed - sets correct new goto dest.
+ */
+static void cxf_fixup_lstofsts_gotos(struct st_t *hdrstp, int32 has_endgoto)
+{
+ register struct st_t *stp;
+ int32 fji;
+ struct for_t *forp;
+ struct st_t *stp2, *fjstp;
+
+ for (stp = hdrstp; stp != NULL; stp = stp->stnxt)
+  {
+   __sfnam_ind = stp->stfnam_ind;
+   __slin_cnt = stp->stlin_cnt;
+
+   switch ((byte) stp->stmttyp) {
+    case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA: case S_NBPROCA: break;
+    case S_IF:
+     if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+     cxf_fixup_lstofsts_gotos(stp->st.sif.thenst, TRUE);
+     if (stp->st.sif.elsest != NULL)
+      cxf_fixup_lstofsts_gotos(stp->st.sif.elsest, TRUE);
+     if (stp->stnxt != NULL) pop_prpstmt();
+     break;
+    case S_CASE:
+     cxf_fixup_case_gotos(stp);
+     break;
+    case S_FOR:
+     forp = stp->st.sfor;
+     /* LOOKATME - is prep change needed */
+     /* goto to for itself */
+     cxf_fixup_loopend_goto(forp->forbody, stp);
+     cxf_fixup_lstofsts_gotos(forp->forbody, FALSE);
+     break;
+    case S_FOREVER: case S_WHILE:
+     cxf_fixup_loopend_goto(stp->st.swh.lpst, stp);
+     cxf_fixup_lstofsts_gotos(stp->st.swh.lpst, FALSE);
+     break;
+    case S_REPEAT:
+     /* allocate per inst. count storage */ 
+     /* add loop back to repeat header */
+     cxf_fixup_loopend_goto(stp->st.srpt.repst, stp);
+     cxf_fixup_lstofsts_gotos(stp->st.srpt.repst, FALSE);
+     break;
+    case S_WAIT:
+     if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+     cxf_fixup_lstofsts_gotos(stp->st.swait.lpst, TRUE);
+     if (stp->stnxt != NULL) pop_prpstmt();
+     break;
+    case S_DELCTRL:
+     /* first find end of decltrl chain */
+     /* if no actoin statement - nothing to do */
+     if (stp->st.sdc->actionst == NULL) break; 
+     for (stp2 = stp->st.sdc->actionst;; stp2 = stp2->st.sdc->actionst)
+      {
+       /* keep going until delay control has no action statement or */
+       /* a non delay control action statement */
+       /* case "#10 begin #20 ..." - is not delay control chain */
+       if (stp2 == NULL || stp2->stmttyp != S_DELCTRL || stp2->st_unbhead)
+        break;
+      }
+     /* ??? 11/10/99 -  if (stp2 == NULL || stp2->stmttyp != S_GOTO) break; */
+     if (stp2 == NULL) break;
+     /* do the goto fix up */
+     if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+     cxf_fixup_lstofsts_gotos(stp2, TRUE);
+     /* only end of chain can have "real" statement */
+     if (stp->stnxt != NULL) pop_prpstmt();
+     break;
+    case S_NAMBLK:
+     /* for named block, no continuation - must be subthread except in func */
+     __push_nbstk(stp);
+     if (__processing_func)
+      { 
+       /* for function no task scheduled - run inline to need goto to cont */
+       /* at end */
+       if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+       cxf_fixup_lstofsts_gotos(stp->st.snbtsk->tskst, TRUE);
+       if (stp->stnxt != NULL) pop_prpstmt();
+      }
+     else
+      {
+       push_prpstmt((struct st_t *) NULL);
+       cxf_fixup_lstofsts_gotos(stp->st.snbtsk->tskst, FALSE);
+       pop_prpstmt();
+      }
+     __pop_nbstk();
+     break;
+    case S_UNBLK:
+     if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+     /* need continuation for simple block */
+     cxf_fixup_lstofsts_gotos(stp->st.sbsts, TRUE);
+     if (stp->stnxt != NULL) pop_prpstmt();
+     break;
+    case S_UNFJ:
+     push_prpstmt((struct st_t *) NULL);
+     /* continuation inside these must be NULL, not stacked val */
+     for (fji = 0;; fji++)
+      {
+       if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+       cxf_fixup_lstofsts_gotos(fjstp, FALSE);
+      }
+     pop_prpstmt();
+     break;
+    case S_DSABLE:
+     /* inside function disables are gotos to next statement in up block */
+     if (__processing_func) cxf_fixup_func_dsabl_gotos(stp);
+     /* any other disable is task scheduled */
+     break;
+    case S_GOTO:
+     /* goto can only be last */
+     /* DBG remove --- */
+     if (stp->stnxt != NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     /* if loopend dest. set and nothing to do here */
+     if (stp->lpend_goto) return;
+     if (has_endgoto && __prpstk[__prpsti] != NULL) 
+      {
+       stp->st.sgoto = __prpstk[__prpsti];
+       /* in this rare case will not have line number - can it happen */
+      }
+     /* DBG remove -- */
+     else __case_terr(__FILE__, __LINE__); 
+     /* -- */
+     return;
+    default:
+     /* statements with no processing ignored thru here */
+     break;
+   }
+  }
+ /* block with no loop end goto returns thru here */ 
+}
+
+/*
+ * fixup all gotos in case stmt
+ */
+static void cxf_fixup_case_gotos(struct st_t *stp)
+{
+ register struct csitem_t *csip;
+ struct csitem_t *dflt_csip;
+
+ if (stp->stnxt != NULL) push_prpstmt(stp->stnxt);
+
+ dflt_csip = stp->st.scs.csitems;
+ /* this will move up stack to add goto after ending stp */
+ for (csip = dflt_csip->csinxt; csip != NULL; csip = csip->csinxt)
+  {
+   cxf_fixup_lstofsts_gotos(csip->csist, TRUE);
+  }
+
+ /* this will move up stack to connect ending stnxt to next exec. place */
+ if (dflt_csip->csist != NULL)
+  cxf_fixup_lstofsts_gotos(dflt_csip->csist, TRUE);
+ if (stp->stnxt != NULL) pop_prpstmt();
+}
+
+/*
+ *
+ * inside function disable are like c continue and are just gotos
+ */
+static void cxf_fixup_func_dsabl_gotos(struct st_t *stp)
+{
+ register int32 i;
+ struct expr_t *dsxp;
+ struct sy_t *syp;
+ struct task_t *dsatskp;
+
+ dsxp = stp->st.sdsable.dsablx;
+ syp = dsxp->lu.sy; 
+ /* disable of func. indicated by nil next statmenet - use fcall stack */
+ /* system function disable no next */
+ if (syp->sytyp == SYM_F) return;
+
+ dsatskp = syp->el.etskp;
+ /* know every named block when entered in function name block is stacked */
+ for (i = __nbsti; i >= 0; i--)
+  {
+   if (__nbstk[i]->st.snbtsk == dsatskp)
+    {
+     /* this can be nil */
+     stp->st.sdsable.func_nxtstp = __nbstk[i]->stnxt;
+     return;
+    }
+  }
+ /* know always enclosing, or will not get here - earlier error */
+ __case_terr(__FILE__, __LINE__);
+}
+
+/*
+ * compile transform instance connections
+ */
+static void cmp_xform_inst_conns(void)
+{
+ register int32 ii, pi;
+ register struct inst_t *ip;
+ int32 pnum;
+
+ if (__inst_mod->minum == 0) return;
+
+ for (ii = 0; ii < __inst_mod->minum; ii++)
+  {
+   ip = &(__inst_mod->minsts[ii]);
+   pnum = ip->imsym->el.emdp->mpnum;
+   for (pi = 0; pi < pnum; pi++)
+    ip->ipins[pi] = mv1_expr_totab(ip->ipins[pi]);
+  }
+}
+
+/*
+ * compile transform gates
+ */
+static void cmp_xform_gates(void)
+{
+ register int32 gi, pi;
+ register struct gate_t *gp;
+ int32 pnum;
+ 
+ for (gi = 0; gi < __inst_mod->mgnum; gi++)
+  {
+   gp = &(__inst_mod->mgates[gi]);
+   /* fixex (moves expr)  only delay expression forms */
+   cmp_xform_delay(gp->g_delrep, gp->g_du);
+   pnum = gp->gpnum;
+   for (pi = 0; pi < pnum; pi++)
+    gp->gpins[pi] = mv1_expr_totab(gp->gpins[pi]);
+  }
+}
+
+/*
+ * compile transform cont assigns
+ */
+static void cmp_xform_contas(void)
+{
+ register int32 bi;
+ register struct conta_t *cap, *pbcap; 
+ int32 cai;
+
+ for (cap = &(__inst_mod->mcas[0]), cai = 0; cai < __inst_mod->mcanum;
+  cai++, cap++)
+  {
+   /* fixex (moves expr)  only delay expression forms */
+   cmp_xform_delay(cap->ca_delrep, cap->ca_du);
+
+   cap->lhsx = mv1_expr_totab(cap->lhsx);
+   cap->rhsx = mv1_expr_totab(cap->rhsx);
+   if (cap->ca_pb_sim) 
+    {
+     for (bi = 0; bi < cap->lhsx->szu.xclen; bi++)
+      {
+       pbcap = &(cap->pbcau.pbcaps[bi]);
+       pbcap->lhsx = mv1_expr_totab(pbcap->lhsx);
+       pbcap->rhsx = mv1_expr_totab(pbcap->rhsx);
+      }
+    }
+  }
+}
+
+/*
+ * compile transform tasks
+ *
+ * this also handle tasks - task specific task field (one for now)
+ * set when statemetns tranformed
+ *
+ * task args do not have expr. forms
+ */
+static void cmp_xform_tasks(void)
+{
+ register struct task_t *tskp;
+
+ /* finally check user tasks and function statements */
+ for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+   /* named blocks handled as statement where they occur */
+   if (tskp->tsktyp == FUNCTION) __processing_func = TRUE;
+   else if (tskp->tsktyp == TASK) __processing_func = FALSE; 
+   else continue;
+   /* DBG remove -- */
+   if (__debug_flg)
+    {
+     __dbg_msg("+++ xforming task %s\n", tskp->tsksyp->synam); 
+    }
+   /* --- */
+
+   tskp->tskst = cmp_xform_lstofsts(tskp->tskst);
+  }
+ __prpsti = 0;
+ __nbsti = -1;
+ __prpstk[0] = NULL;
+ for (tskp = __inst_mod->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+   /* named blocks handled as statement where they occur */
+   if (tskp->tsktyp == FUNCTION) __processing_func = TRUE;
+   else if (tskp->tsktyp == TASK) __processing_func = FALSE; 
+   else continue;
+
+   cxf_fixup_lstofsts_gotos(tskp->tskst, FALSE);
+  } 
+ /* DBG remove --- */ 
+ if (__prpsti != 0) __misc_terr(__FILE__, __LINE__); 
+ /* --- */
+}
+
+/*
+ * compile transform specify sections expressions
+ *
+ * only called if module has specify section
+ * maybe do not need to copy these expressions
+ *
+ * notice by here pathel's no longer expressions and expr. delay forms
+ * illegal in paths (error before here)
+ */
+static void cmp_xform_specify(void)
+{
+ register struct spcpth_t *pthp;
+ register struct tchk_t *tcp;
+
+ /* prepare paths */
+ for (pthp = __inst_mod->mspfy->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+  {
+   /* data source not really used in simulator but moved still */ 
+   pthp->datasrcx = mv1_expr_totab(pthp->datasrcx);
+   /* need to move this since condition eval can eliminates path */
+   pthp->pthcondx = mv1_expr_totab(pthp->pthcondx);
+  }
+ /* copy these because needed at run time for timing check error msgs */
+ for (tcp = __inst_mod->mspfy->tchks; tcp != NULL; tcp = tcp->tchknxt)
+  {
+   if (tcp->startxp != NULL) tcp->startxp = mv1_expr_totab(tcp->startxp);
+
+   if (tcp->startcondx != NULL)
+    tcp->startcondx = mv1_expr_totab(tcp->startcondx);
+
+   if (tcp->chkxp != NULL) tcp->chkxp = mv1_expr_totab(tcp->chkxp);
+
+   if (tcp->chkcondx != NULL) tcp->chkcondx = mv1_expr_totab(tcp->chkcondx);
+
+   /* both sides of setuphold determined from hold half and both sides of*/
+   /* recrem determined removal half */
+   if (tcp->tc_supofsuphld || tcp->tc_recofrecrem) continue;
+
+   /* LOOKATME - are these needed since think spec delays can't be exprs */
+   cmp_xform_delay(tcp->tc_delrep, tcp->tclim_du);
+   if (tcp->tc_haslim2) cmp_xform_delay(tcp->tc_delrep2, tcp->tclim2_du);
+  }
+}
+
+/*
+ * dump a module's statement table
+ *
+ * number to dump is arg so can use on partially built table
+ */
+extern void __dmp_msttab(struct mod_t *mdp, int32 snum)
+{
+ register int32 si;
+ register struct st_t *stp;
+ int32 si2;
+
+ if (mdp->mstnum == 0) 
+  {
+   __dbg_msg("+++ module %s has no statements +++\n", mdp->msym->synam);
+   return;
+  }
+ /* DBG remove --- */
+ if (mdp->msttab == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ __dbg_msg("+++ module %s has %d statements +++\n", mdp->msym->synam,
+  mdp->mstnum);
+ __push_wrkitstk(mdp, 0); 
+ for (si = 0; si < snum; si++)
+  {
+   stp = &(mdp->msttab[si]);
+   if (stp->stmttyp == S_GOTO)
+    {
+     si2 = stp->st.sgoto - &(mdp->msttab[0]);
+     __dbg_msg("GOTO STMT %d (goto %d):\n", si, si2);
+    }
+   else __dbg_msg("STMT %d:\n", si);
+   __dmp_stmt(stdout, stp, FALSE);
+   __dbg_msg("\n");
+  }
+ __pop_wrkitstk();
+}
+
+/*
+ * dump a module's expr table
+ *
+ * number to dump is arg so can use on partially built table
+ */
+extern void __dmp_exprtab(struct mod_t *mdp, int32 xnum)
+{
+ register int32 xi;
+ register struct expr_t *xp;
+ int32 lxi, rxi;
+ char s1[RECLEN];
+
+ if (mdp->mexprnum == 0) 
+  {
+   __dbg_msg("+++ module %s has no expressions +++\n", mdp->msym->synam);
+   return;
+  }
+ /* DBG remove --- */
+ if (mdp->mexprtab == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ __dbg_msg("+++ module %s has %d expression nodes +++\n", mdp->msym->synam,
+  mdp->mexprnum);
+ __push_wrkitstk(mdp, 0); 
+ for (xi = 0; xi < xnum; xi++)
+  {
+   xp = &(mdp->mexprtab[xi]);
+
+   if (__isleaf(xp))
+    {
+     __dbg_msg("EXPR %d:  leaf %s\n", xi, bld_opname(s1, xp));
+    }
+   else
+    {
+     lxi = rxi = -1;
+     if (xp->lu.x != NULL) lxi = xp->lu.x - &(mdp->mexprtab[0]);
+     if (xp->ru.x != NULL) rxi = xp->ru.x - &(mdp->mexprtab[0]); 
+     __dbg_msg("EXPR %d:  op %s left [%d] right [%d]\n", xi,
+      bld_opname(s1, xp), lxi, rxi);
+    }
+  }
+ __pop_wrkitstk();
+}
+
+/*
+ * build name of an operator in a string
+ *
+ * LOOKATME - this is almost same as to_xndnam but here names in symbol
+ * table and expridtab not filled
+ */
+static char *bld_opname(char *s, struct expr_t *ndp)
+{
+ int32 wlen;
+ word32 *ap, *bp;
+ char s1[2*IDLEN], s2[RECLEN];
+
+ switch ((byte) ndp->optyp) {
+  case ID:
+   sprintf(s1, "IDENTIFIER: %s", ndp->lu.sy->synam);
+   break;
+   /* LOOKATME - can GLBREF occur here */
+  case GLBREF:
+   sprintf(s1, "XMR: %s", ndp->ru.grp->gnam);
+   break;
+  case NUMBER:
+  case ISNUMBER:
+   ap = &(__contab[ndp->ru.xvi]);
+   wlen = wlen_(ndp->szu.xclen);
+   bp = &ap[wlen];
+   sprintf(s1, "NUMBER: %s", __xregab_tostr(s2, ap, bp, ndp->szu.xclen, ndp));
+   break;
+  case REALNUM: case ISREALNUM:
+   /* just pass a for both here */ 
+   /* LOOKATME - should just format as double */ 
+   ap = &(__contab[ndp->ru.xvi]);
+   sprintf(s1, "REAL: %s", __regab_tostr(s2, ap, ap, ndp->szu.xclen, BDBLE,
+    FALSE));
+   break;
+  case OPEMPTY:
+   strcpy(s, "<EMPTY>");
+   return(s);
+  case UNDEF:
+   strcpy(s, "<EXPR END>");
+   return(s);
+  default:
+   strcpy(s, __to_opname(ndp->optyp)); return(s);
+ }
+ if ((int32) strlen(s1) >= RECLEN - 1) s1[RECLEN - 1] = '\0';
+ strcpy(s, s1);
+ return(s);
+}
diff --git a/src/v_sdf.c b/src/v_sdf.c
new file mode 100644
index 0000000..a3d2233
--- /dev/null
+++ b/src/v_sdf.c
@@ -0,0 +1,7342 @@
+/* Copyright (c) 1993-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * modules to read and back annotate from sdf file
+ *
+ * uses own itree context does not expect inst_ptr or inst mod to be set
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* REMOVEME - no longer supporting SunOS - maybe needed for hpux? */
+#if defined(__sparc) && !defined(__SVR4)  
+extern ungetc(int32 c, FILE *);
+#endif
+
+/* this shares some vpi_ delay code */
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* some max number of delay components */
+#define SDF_MTMDNUM 3
+#define SDF_PULDNUM 3
+#define SDF_MAXDELS 12
+
+/* rvalue types */
+#define SDF_NOVAL 1
+#define SDF_1VAL 2
+#define SDF_MTMVAL 3
+
+/* sdf only constants */
+#define DFLT_SEP_CHAR '.'
+#define SDF_DOL 91
+#define SDF_BACKQ 92
+#define SDF_QUOTE 93
+#define SDF_BACKSLASH 94
+#define SDF_UNKN 0
+
+/* delay form keyword constants - must start above 99 (verilog op region) */
+/* mostly overlapping Verilog directive range */
+/* SJM 12/15/03 - added new 2001 LRM time checks and renumbered */
+#define SDF_ABSOLUTE 100
+#define SDF_ARRIVAL 101 
+#define SDF_CCOND 102
+#define SDF_CELL 103
+#define SDF_CELLTYPE 104
+#define SDF_COND 105
+#define SDF_CONDELSE 106
+#define SDF_DATE 107
+#define SDF_DELAY 108
+#define SDF_DELAYFILE 109
+#define SDF_DEPARTURE 110
+#define SDF_DESIGN 111
+#define SDF_DEVICE 112
+#define SDF_DIFF 113
+#define SDF_DIVIDER 114
+#define SDF_EXCEPTION 115
+#define SDF_FULLSKEW 116
+#define SDF_HOLD 117
+#define SDF_INCREMENT 118
+#define SDF_INSTANCE 119
+#define SDF_INTERCONNECT 120
+#define SDF_IOPATH 121
+#define SDF_LABEL 122
+#define SDF_NAME 123
+#define SDF_NOCHANGE 124
+#define SDF_PATHCONSTRAINT 125
+#define SDF_PERIODCONSTRAINT 126
+#define SDF_PATHPULSE 127
+#define SDF_PATHPULSEPERCENT 128
+#define SDF_PERIOD 129
+#define SDF_PORT 130
+#define SDF_PROCESS 131
+#define SDF_PROGRAM 132
+#define SDF_RECREM 133
+#define SDF_RECOVERY 134
+#define SDF_REMOVAL 135
+#define SDF_RETAIN 136
+#define SDF_SCOND 137
+#define SDF_SKEWCONSTRAINT 138
+#define SDF_SLACK 139
+#define SDF_SETUP 140 
+#define SDF_SETUPHOLD 141 
+#define SDF_SKEW 142 
+#define SDF_SUM 143
+#define SDF_TEMPERATURE 144
+#define SDF_TIMESCALE 145
+#define SDF_TIMESKEW 146
+#define SDF_TIMINGCHECK 147
+#define SDF_TIMINGENV 148
+#define SDF_VENDOR 149
+#define SDF_VERSION 150
+#define SDF_VOLTAGE 151
+#define SDF_WAVEFORM 152
+#define SDF_WIDTH 153
+#define SDF_NEGEDGE 154
+#define SDF_POSEDGE 155
+
+#define SDF_BKEYS SDF_ABSOLUTE
+
+/* sdf only records */
+struct pthlst_t {
+ struct spcpth_t *lpthp;
+ struct pthlst_t *pthlnxt;
+};
+
+struct tclst_t {
+ struct tchk_t *tcp;
+ struct tclst_t *tclnxt;
+};
+
+struct tcterm_t {
+ char *tnam;
+ int32 ti1, ti2, eval;
+ char *cndnam;
+ int32 cndi1, cndi2;
+ int32 cnd_op, cnd_const;
+};
+
+/* sdf only declares */
+static char __pathsep; 
+static char __sdf_none_str[20];
+static char __sdf_work_str[IDLEN];
+static char __sdf_varnam[IDLEN];
+static char *__sdf_version;
+static char *__sdf_design;
+static char *__sdf_date; 
+static char *__sdf_vendor;
+static char *__sdf_program;
+static char *__sdf_progversion;
+static double __sdf_voltage;
+static double __sdf_temp;
+static char *__sdf_process;
+static int32 __sdf_timescale;    /* this is internal pos. time unit exp */    
+static char __sdf_star_val[4]; /* special " * " string for all inst. star */ 
+static int32 __sdf_tokval;
+static struct itree_t *__sdf_cntxt_itp;
+static int32 __seen_ppulse;      /* per SDF file, 1 warn if path pulse used */
+static int32 __seen_pc_ppulse;   /* same for path pulse percent */
+static int32 __seen_rlim_delval; /* 1 warn if reject limit in delval */ 
+static int32 __seen_xlim_delval; /* 1 warn if x (error) limit in delval */ 
+static int32 __sdf_nd_tscale;    /* T => SDF file timescale different */
+static int32 __sdf_ts_units;     /* unit difference for SDF TIMESCALE */
+static struct t_vpi_delay *__sdf_delp;
+static struct t_vpi_delay *__sdf_delp2;
+static int32 __id_qualpath;
+static int32 __id_select;
+static int32 __id_partsel;
+static int32 __rding_cond_expr;  /* reading cond form - scalars cons allowd */ 
+
+/* SJM 07/08/01 - change so user can specify log file - then replaces here */
+static char *__sdf_log_fnam;   /* name of SDF log file */
+static FILE *__sdf_log_s;      /* and stream */ 
+static FILE *__sdf_sav_log_s;  /* just need to save normal log file */  
+
+/* local prototypes */
+static void alloc_sdf_mdp(void);
+static void sdf_annotate(char *, char *, int32, int32);
+static void do_systsk_sdf_annotate(char *, struct itree_t *, int32, int32);
+static void do_sdf_annotate(char *, int32, int32);
+static void free_sdf_hdrvals(void);
+static char *get_sdfcntxtnam(char *, struct itree_t *);
+static void init_vpi_del(struct t_vpi_delay *, int32);
+static void rd_sdf_file(FILE *);
+static char *mtm_sel_tonam(char *, int32);
+static int32 rd_sdf_sepchar(FILE *, char *);
+static int32 rd_sdf_timescaleval(FILE *, int32 *);
+static int32 rdset_sdf_cells(FILE *);
+static struct itree_t *get_sdfdownrel_itp(struct expr_t *, struct itree_t *,
+ struct sy_t **, char *);
+static int32 rdset_prim_delay(FILE *, struct sy_t *, int32, char *, struct sy_t *);
+static int32 prim_rdset_device_del(FILE *, struct itree_t *, struct sy_t *,
+ struct gate_t *);
+static void set_device_del(struct itree_t *, struct gate_t *, struct sy_t *);
+static void prep_sdfdev_verbmsg(struct gate_t *, struct gate_t *,
+ struct itree_t *, struct mod_t *);
+static void emit_sdfdev_verbmsg(struct gate_t *, struct gate_t *, char *);
+static int32 rdset_timing_spec(FILE *, struct itree_t *, struct mod_t *);
+static char *get_sdfinam(char *, struct itree_t *, struct mod_t *);
+static int32 rdset_deltyps(FILE *, struct itree_t *, struct mod_t *);
+static int32 port_qual_nam(char *, char *);
+static int32 rd_1_val(FILE *, char *);
+static int32 rd2_1_val(FILE *);
+static int32 rd_1or2_vals(FILE *, char *);
+static int32 rd_4_vals(FILE *, char *);
+static int32 rd_deldef(FILE *, struct itree_t *, struct mod_t *, char *);
+static void dellst_err(char *, char *);
+static void formend_err(char *);
+static int32 rd_iopath(FILE *, struct itree_t *, struct mod_t *,
+ struct expr_t *, int32, char *);
+static void set_1pthdel(struct pthlst_t *, struct itree_t *, struct mod_t *);
+static void prep_sdfiopath_verbmsg(struct spcpth_t *, struct gate_t *,
+ struct itree_t *, struct mod_t *);
+static void emit_sdfiopath_verbmsg(struct spcpth_t *, struct gate_t *, char *);
+static int32 upd_sdf_perinst_del(struct gate_t *, p_vpi_delay, struct mod_t *,
+ int32, int32, int32, char *);
+static int32 itp_under_cntxt(register struct itree_t *);
+static int32 rd_port_spec(FILE *, char *, int32 *, int32 *, int32 *, int32);
+static int32 rd_port(FILE *, char *, int32 *, int32 *);
+static struct pthlst_t *bld_match_spcpth(struct mod_t *, char *, int32, int32,
+ int32, char *, int32, int32, struct expr_t *, int32);
+static void free_pthlst(struct pthlst_t *);
+static char *msg_sdfpath_tostr(char *, char *, int32, int32, int32, char *, int32,
+ int32, struct expr_t *, int32);
+static int32 rd_del_def_cond(FILE *, struct itree_t *, struct mod_t *, char *);
+static int32 col_cond_port_expr(FILE *);
+static int32 sdf_bld_expnode(void);
+static int32 rdset_tchk_defs(FILE *, struct itree_t *, struct mod_t *);
+static void set_half_setuphold_tchk_defs(struct tclst_t *, int32,
+ struct itree_t *, struct mod_t *);
+static void set_half_recrem_tchk_defs(struct tclst_t *, int32,
+ struct itree_t *, struct mod_t *);
+static int32 rdset_2term_1v_tchk(struct tclst_t **, int32 *, FILE *,
+ struct mod_t *, char *, int32, int32, int32 *);
+static int32 rdset_1term_1v_tchk(struct tclst_t **, FILE *, struct mod_t *,
+ char *, int32, int32, int32 *);
+static int32 rdset_2term_2v_tchk(struct tclst_t **, FILE *, struct mod_t *,
+ char *, int32, int32, int32 *);
+static void prep_sdftchk_verbmsg(struct tchk_t *, char *, struct gate_t *,
+ struct itree_t *, struct mod_t *, char *);
+static void emit_sdftchk_verbmsg(struct tchk_t *, char *, struct gate_t *,
+ char *, char *);
+static int32 rd_port_tchk(FILE *, struct tcterm_t *);
+static int32 rd_tchk_cond(FILE *, struct tcterm_t *);
+static int32 rd_scalar_node(FILE *, char *, int32 *);
+static int32 from_sdf_tctyp(int32);
+static struct tclst_t *bld_match_tchk(struct mod_t *, struct tcterm_t *,
+ struct tcterm_t *, int32, char *);
+static int32 same_tchk_cond(struct tcterm_t *, struct expr_t *);
+static void free_tclst(struct tclst_t *);
+static void free_tct_insides(struct tcterm_t *);
+static int32 rdset_port_mipd(FILE *, struct itree_t *, struct mod_t *, char *);
+static void set_mipd_dels(struct itree_t *, char *, int32, int32);
+static char *msgpref_tostr(char *, struct mod_pin_t *);
+static struct itree_t *find_1under_itp(struct mod_t *);
+static int32 xtrct_portdev(struct itree_t **, char *, char *, struct itree_t *,
+ char *, char *);
+static struct mod_pin_t *get_inport_fr_nam(struct mod_t *, char *);
+static int32 getsrch_portnam(struct mod_t *, register char *);
+static struct mod_pin_t *get_outport_fr_nam(struct mod_t *, char *);
+static struct mod_pin_t *get_bidport_fr_nam(struct mod_t *, char *);
+static int32 rdset_interconn_dels(FILE *, struct itree_t *, struct mod_t *,
+ char *);
+static void chkset_interconn_dels(struct itree_t *, char *, int32, int32, char *,
+ int32, int32);
+static char *bld_prefnam(char *, char *, int32, int32);
+static void add_srcdst_impth(struct mipd_t *, struct mod_pin_t *, int32, int32,
+ struct itree_t *, char *);
+static int32 rdset_devpath_dels(FILE *, struct itree_t *, struct mod_t *,
+ char *);
+static void set_allpths_dels(struct itree_t *, struct mod_t *);
+static void set_alloutpths_dels(char *, int32, int32, struct itree_t *,
+ struct mod_t *);
+static int32 not_a_port(char *, int32, struct mod_t *, char *);
+static int32 rdskip_te_defs(FILE *);
+static int32 rd_exception(FILE *);
+static int32 rd_constraint_path(FILE *, char *, int32);
+static int32 rd_edgepair_list(FILE *);
+static int32 rdset_labels(FILE *, struct itree_t *, struct mod_t *);
+static int32 xtrct_param(struct itree_t **, char *, struct itree_t *);
+static struct xstk_t *sdf_push_rvalue(struct net_t *, double);
+static void emit_sdflblverb_msg(struct net_t *, struct xstk_t *, char *);
+static int32 sdf_adjust_incr(struct net_t *, struct xstk_t *, int32);
+static int32 bld_sdfnewdu(struct gate_t *, struct gate_t *, p_vpi_delay,
+ struct itree_t *, int32, int32, char *);
+static int32 sdf_fillchk_tim(word64 *, int32 *, int32 *, int32 *, p_vpi_delay, char *);
+static int32 vpi_delay_all0s(p_vpi_delay);
+static int32 rd_sdf_dellst(FILE *, char *);
+static int32 rd_rtriple(FILE *, register struct t_vpi_time *);
+static int32 rd_sdf_formtyp(FILE *);
+static int32 rd2_sdf_formtyp(FILE *);
+static int32 rd_sdf_strval(FILE *);
+static void get_sdftok(FILE *);
+static int32 sdf_rd_comment(FILE *);
+static int32 sdf_collect_str(FILE *);
+static int32 sdf_collect_num(FILE *, int32);
+static int32 chkcnv_sdfpath(char *, int32 *, int32 *, char *, int32);
+static char *fnd_pth_sep(register char *);
+static int32 chkcnv_sdfid(char *, int32 *, int32 *, char *, int32);
+static int32 sdf_getsel_indices(int32 *, int32 *, char *);
+static int32 sdf_skip_form(FILE *);
+static int32 rd_edge_ident(FILE *);
+static int32 rd_scalar_const(FILE *);
+static char *prt_sdftok(void);
+static int32 get_sdfkeywrd(register char *);
+static char *get_skeynam(char *, int32);
+
+/* extern prototypes (maybe defined in this module) */
+extern void __process_sdf_files(void);
+extern void __chg_param_tois(struct net_t *, struct mod_t *);
+
+extern FILE *__my_fopen(char *, char *);
+extern FILE *__tilde_fopen(char *, char *);
+extern void __my_fclose(FILE *);
+extern void __my_free(char *, int32);
+extern char *__my_malloc(int32);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern char *__pv_stralloc(char *);
+extern char *__to_timunitnam(char *, word32);
+extern char *__get_tmult(char *, word32 *);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern struct expr_t *__glbnam_to_expr(char *);
+extern char *__to_glbcmp_nam(struct expr_t *);
+extern int32 __ip_indsrch(char *);
+extern int32 __add_gate_pnd0del(struct gate_t *, struct mod_t *, char *);
+extern void __chg_1inst_del(struct gate_t *, struct itree_t *, struct gate_t *);
+extern void __free_del(union del_u, word32, int32);
+extern char *__bld_delay_str(char *, union del_u, word32);
+extern char *__bld_lineloc(char *, word32, int32);
+extern char *__to_edgenam(char *, word32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern void __xtract_wirng(struct expr_t *, struct net_t **, int32 *, int32 *);
+extern void __add_alloc_mipd_npp(struct net_t *, struct mod_t *);
+extern void __re_prep_dels(struct net_t *, struct itree_t *, struct mod_t *,
+ int32);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern int32 __real_to_v64tim(word64 *, double);
+extern void __sizchgxs(register struct xstk_t *, int32);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern void __ld_wire_val(register word32 *, register word32 *, struct net_t *);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern int32 __do_widecmp(int32 *, register word32 *, register word32 *, register word32 *, register word32 *, int32);
+extern word32 __lsub(word32 *, word32 *, word32 *, int32);
+extern void __ladd(word32 *, word32 *, word32 *, int32);
+extern void __extract_delval(word64 *, int32 *, union del_u, word32);
+extern void __fill_16vconst(word64 *, word64 *, int32);
+extern void __fill_4vconst(word64 *, word64 *, word64 *, word64 *, int32, int32);
+extern double __my_strtod(char *, char **, int32 *);
+extern word32 __my_strtoul(char *, char **, int *);
+extern struct xstk_t *__eval2_xpr(struct expr_t *);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern void __free_xtree(struct expr_t *);
+extern void __init_mod(struct mod_t *, struct sy_t *);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern char * __get_eval_cstr(struct expr_t *, int32 *);
+extern char *__to_timstr(char *, word64 *);
+extern int32 __cmp_xpr(struct expr_t *, struct expr_t *);
+extern void __bld_xtree(int32);
+extern void __set_xtab_errval(void);
+extern int32 __alloc_shareable_cval(word32, word32, int32);
+extern int32 __allocfill_cval_new(word32 *, word32 *, int32);
+extern struct expr_t *__alloc_exprnd(void);
+extern struct expridtab_t *__alloc_expridnd(char *);
+extern struct tenp_t *__bld_portbit_netbit_map(struct mod_pin_t *);
+extern void __setup_mipd(struct mipd_t *, struct net_t *, int32);
+
+extern void __cv_msg(char *, ...);
+extern void __pv_ferr(int32, char *, ...);
+extern void __pv_fwarn(int32, char *, ...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __finform(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+
+extern char __pv_ctab[];
+extern word32 __masktab[];
+extern double __dbl_toticks_tab[];
+extern struct opinfo_t __opinfo[];
+
+/*
+ * process all sdf annotate files (from options) just before init for sim
+ */
+extern void __process_sdf_files(void)
+{
+ register struct sdfnamlst_t *sdfp;
+ int32 sav_slin_cnt, sav_sfnam_ind;
+ char *sav_fnam;
+
+ __sdf_from_cmdarg = TRUE;
+ if (__sdf_opt_log_fnam != NULL)
+  {
+   if ((__sdf_opt_log_s = __tilde_fopen(__sdf_opt_log_fnam, "w")) == NULL)
+    {
+     __sgfwarn(505,
+      "cannot open SDF log file %s from +sdf_log_file option - using normal log file",
+      __sdf_opt_log_fnam);
+     __sdf_opt_log_s = NULL;
+     __sdf_opt_log_fnam = NULL;
+    }
+   else
+    { 
+     __cv_msg(
+      "  SDF: writing SDF annotation messages and errors to separate SDF log file %s\n",
+      __sdf_opt_log_fnam); 
+     __sdf_sav_log_s = __log_s;
+     __log_s = __sdf_opt_log_s;
+    }
+  }
+
+ /* since this is before simulation sdf mdp always nil here */
+ if (__sdf_mdp == NULL) alloc_sdf_mdp();
+
+ /* need to treat as interactive state call from first top level */
+ __cur_thd = NULL;
+ sav_fnam = __in_fils[0];
+ /* need to save-restore sgf... type locations since used as work vars */
+ sav_slin_cnt = __slin_cnt;
+ sav_sfnam_ind = __sfnam_ind;
+ for (sdfp = __sdflst; sdfp != NULL; sdfp = sdfp->sdfnamnxt)
+  {
+   /* need slincnt and sfnam ind for string path name processing here */
+   __in_fils[0] = sdfp->optfnam;
+   /* here - after annotation complete - cleans up and frees memory */
+   __sdf_from_cmdarg = TRUE;
+   sdf_annotate(sdfp->fnam, sdfp->scopnam, 0, sdfp->opt_slcnt);
+   __sdf_from_cmdarg = FALSE;
+  }
+
+ /* SJM 07/08/01 - put back normal log file if changed */ 
+ if (__sdf_opt_log_s != NULL) __log_s = __sdf_sav_log_s;
+
+ __in_fils[0] = sav_fnam;
+ __slin_cnt = sav_slin_cnt; 
+ __sfnam_ind = sav_sfnam_ind;
+ /* LOOKATME - could free sdf mdp here */
+}
+
+/*
+ * routine to allocate sdf_mdp - need for converting instance names
+ * to path
+ */
+static void alloc_sdf_mdp(void)
+{
+ struct sy_t *syp;
+
+ /* allocate work sdf module - needed glbndp con tab */
+ __sdf_mdp = (struct mod_t *) __my_malloc(sizeof(struct mod_t)); 
+ syp = (struct sy_t *) __my_malloc(sizeof(struct sy_t));
+ syp->synam = __pv_stralloc("**SDF WORK**");
+ syp->sydecl = TRUE;
+
+ __init_mod(__sdf_mdp, syp);
+ __sdf_mdp->flatinum = 1;
+ syp->el.emdp = __sdf_mdp;
+}
+
+/*
+ * open - read - close the sdf annotation file and annotate (set) values
+ *
+ * run at compile time because can set delays on non delay element
+ * simulation not run if error here
+ * runs in isolation - all trace gone when routine returns
+ * knows slin cnt environment set 
+ */
+static void sdf_annotate(char *sdf_fnam, char *sdf_scopnam, int32 fnind,
+ int32 slcnt)
+{
+ int32 sdfenum, sav_no_errs, sav_no_warns;
+ struct expr_t *glbndp;
+ char s1[RECLEN], s2[RECLEN];
+
+ /* open sdf annotation file */
+ if ((__sdf_s = __my_fopen(sdf_fnam, "r")) == NULL)
+  {
+   __gferr(1370, fnind, slcnt, 
+    "cannot open +sdf_annotate SDF input file %s", sdf_fnam);
+   return;
+  }
+
+ /* need to save error count for system task - will be 0 if from option */
+ __sdf_sav_enum = __pv_err_cnt;
+
+ /* if no scope use first top module */
+ __cur_thd = NULL;
+ if (sdf_scopnam == NULL || strcmp(sdf_scopnam, "") == 0)
+   __sdf_cntxt_itp = NULL;
+ else
+  {
+   /* scope context for sdf file must always be rooted and is Verilog path */
+   /* need to use interactive global context here */
+   __push_wrkitstk(__sdf_mdp, 0);
+   /* this does not use itree context but uses expr routines that need */
+   /* inst mod set */
+   if ((glbndp = __glbnam_to_expr(sdf_scopnam)) != NULL) 
+    {
+     /* for null context, down rel is really rooted */
+     __sdf_cntxt_itp = get_sdfdownrel_itp(glbndp, NULL, NULL, s2);
+     /* now done with glb expr. */ 
+     __free_xtree(glbndp);
+     __pop_wrkitstk();
+     if (__sdf_cntxt_itp == NULL)
+      {
+       __gferr(1350, fnind, slcnt, 
+        "for +sdf_annotate SDF input file %s context %s illegal: %s", sdf_fnam,
+        sdf_scopnam, s2);  
+annot_fail:
+       __my_fclose(__sdf_s);
+       if (__verbose)
+        {
+        __cv_msg(
+         "  SDF delay +sdf_annotate failed for \"%s\" in context scope %s\n",
+         sdf_fnam, s1);
+        }
+       return;
+      }
+    }
+   else
+    {
+     __pop_wrkitstk();
+     __gferr(1350, fnind, slcnt, 
+      "for +sdf_annotate SDF input file %s context %s illegal - rooted instance not found",
+      sdf_fnam, sdf_scopnam);  
+     goto annot_fail;
+    }
+  }
+ /* here always use command option mintypmax delay selector */
+ __sdf_mintypmax_sel = __mintypmax_sel;
+
+ /* SJM 06/16/00 - must never stop no matter how many SDF errors */
+ __sdf_sav_maxerrs = __max_errors;
+ __max_errors = 0;
+ __sdf_active = TRUE;
+
+ /* SJM 07/08/01 - add new do not print sdf errors and warns option */
+ sav_no_errs = __no_errs;
+ sav_no_warns = __no_warns;
+ if (__sdf_no_errs) __no_errs = TRUE;
+ if (__sdf_no_warns) __no_warns = TRUE;
+
+ do_sdf_annotate(sdf_fnam, fnind, slcnt);
+ __max_errors = __sdf_sav_maxerrs;
+ __sdf_active = FALSE;
+
+ /* always replace saved no errs and no warns */
+ __no_errs = sav_no_errs;
+ __no_warns = sav_no_warns; 
+
+ get_sdfcntxtnam(s1, __sdf_cntxt_itp);
+ __sdf_cntxt_itp = NULL;
+
+ /* SJM 06/06/00 - change so report but do not count SDF errors */
+ if (__pv_err_cnt > __sdf_sav_enum)
+  {
+   sdfenum = __pv_err_cnt - __sdf_sav_enum;
+   __pv_err_cnt = __sdf_sav_enum;
+
+   __cv_msg(
+    "  **%d SDF Errors** during +sdf_annotate of \"%s\" context scope %s.\n",
+    sdfenum, sdf_fnam, s1);
+  }
+ if (__verbose) 
+  {
+   __cv_msg(
+    "  SDF delay +sdf_annotate completed for \"%s\" context scope %s.\n",
+    sdf_fnam, s1);
+  }
+}
+
+/*
+ * execute $sdf_annotate call
+ *
+ * SJM 07/08/01 - change to allow setting different log file during SDF read
+ */
+extern void __exec_sdf_annotate_systsk(struct expr_t *axp)
+{
+ register int32 argi;
+ int32 slen, slen2;
+ struct itree_t *cntxtitp;
+ char *fnchp, *mtmchp, *sdflogfn_chp;
+
+ /* always need sdf mdp (so inst mod set) for decomping sdf qualified name */
+ /* does not need instance context, just needs to be set */ 
+ if (__sdf_mdp == NULL) alloc_sdf_mdp();
+
+ fnchp = NULL;
+ sdflogfn_chp = NULL;
+ __sdf_log_fnam = NULL;
+ 
+ cntxtitp = NULL;
+ mtmchp = NULL;
+ slen = slen2 = 0;
+ /* assume sdf annotate systf call does not override command line option */
+ __sdf_mintypmax_sel = __mintypmax_sel;
+ 
+ /* SJM 07/09/01 - must skip opempty non required arguments */
+ for (argi = 0; axp != NULL; axp = axp->ru.x, argi++)
+  {
+   /* know there will always be at least one arg */
+   if (argi == 0)
+    {
+     fnchp = __get_eval_cstr(axp->lu.x, &slen);
+     continue;
+    }
+   if (argi == 1)
+    {
+     if (axp->lu.x->optyp == OPEMPTY) continue;
+
+     /* module instance context */
+     __xmrpush_refgrp_to_targ(axp->lu.x->ru.grp);
+     cntxtitp = __inst_ptr;
+     __pop_itstk();
+     continue;
+    }
+   if (argi == 3)
+    {
+     if (axp->lu.x->optyp == OPEMPTY) continue;
+
+     /* name of different log file */
+     sdflogfn_chp = __get_eval_cstr(axp->lu.x, &slen);
+     continue;
+    } 
+   if (argi == 4)
+    {
+     if (axp->lu.x->optyp == OPEMPTY) continue;
+
+     /* MTM selector */
+     mtmchp = __get_eval_cstr(axp->lu.x, &slen2);
+     if (strcmp(mtmchp, "MINIMUM") == 0) __sdf_mintypmax_sel = DEL_MIN;
+     else if (strcmp(mtmchp, "TYPICAL") == 0) __sdf_mintypmax_sel = DEL_TYP; 
+     else if (strcmp(mtmchp, "MAXIMUM") == 0) __sdf_mintypmax_sel = DEL_MAX; 
+     else if (strcmp(mtmchp, "TOOL_CONTROL") == 0)
+      __sdf_mintypmax_sel = __mintypmax_sel;
+     else
+      {
+       __sgfwarn(627,
+        "$sdf_annotate fifth mtm_spec argument %s illegal - using default TOOL_CONTROL",
+        mtmchp);
+      }
+    }
+  }
+ /* if not 2nd arg, use current itree context */
+ if (cntxtitp == NULL) cntxtitp = __inst_ptr;
+
+ /* change to sdf log file, if given in system task */ 
+ if (fnchp != NULL && sdflogfn_chp != NULL)
+  {
+   if ((__sdf_log_s = __tilde_fopen(sdflogfn_chp, "w")) == NULL)
+    {
+     __sgfwarn(505,
+      "cannot open fourth argument separate SDF log file %s - using normal log file",
+      sdflogfn_chp);
+     __sdf_log_s = NULL;
+     __sdf_log_fnam = NULL;
+     goto log_chg_done;
+    }
+   __sdf_log_fnam = __my_malloc(strlen(sdflogfn_chp) + 1);
+   strcpy(__sdf_log_fnam, sdflogfn_chp);
+   __sdf_sav_log_s = __log_s;
+   if (__sdf_opt_log_fnam != NULL)
+    {
+     __sgfwarn(505,
+      "use of fourth argument SDF log file %s over-rides SDF log file %s set on command line",
+      sdflogfn_chp, __sdf_opt_log_fnam);
+    }
+   /* notice message about use of log file goes to normal log file */
+   __cv_msg(
+    "  SDF: writing SDF annotation messages and errors to separate SDF log file %s\n",
+    __sdf_log_fnam); 
+   __log_s = __sdf_log_s;
+   goto log_chg_done;
+  }
+ /* SJM 07/08/01 - see if SDF log file set from command line */
+ if (__sdf_opt_log_fnam != NULL)
+  {
+   if (__sdf_opt_log_s != NULL)
+    {
+     __sdf_log_s = __sdf_opt_log_s;
+     __sdf_log_fnam = __sdf_opt_log_fnam;
+     __sdf_sav_log_s = __log_s;
+     __log_s = __sdf_log_s;
+     goto log_chg_done;
+    }
+
+   if ((__sdf_opt_log_s = __tilde_fopen(__sdf_opt_log_fnam, "w")) == NULL)
+    {
+     __sgfwarn(505,
+      "cannot open SDF log file %s from +sdf_log_file option - using normal log file",
+      __sdf_opt_log_fnam);
+     __sdf_log_s = NULL;
+     __sdf_log_fnam = NULL;
+     __sdf_opt_log_fnam = NULL;
+     goto log_chg_done;
+    }
+   __cv_msg(
+    "  SDF: writing SDF annotation messages and errors to separate SDF log file %s\n",
+    __sdf_opt_log_fnam); 
+
+   __sdf_log_s = __sdf_opt_log_s;
+   __sdf_log_fnam = __sdf_opt_log_fnam;
+   __sdf_sav_log_s = __log_s;
+   __log_s = __sdf_log_s;
+  }
+
+log_chg_done:
+ if (__sdf_verbose)
+  {
+   char s1[RECLEN], s2[RECLEN];
+
+   __cv_msg(
+    "  SDF: now %s executing $sdf_annotate task at %s in %s context %s\n",
+    __to_timstr(s1, &__simtime), __bld_lineloc(__xs, __sfnam_ind,
+    __slin_cnt), __msg2_blditree(s2, __inst_ptr), __msg2_blditree(__xs2,
+    cntxtitp)); 
+
+   if (__sdf_mintypmax_sel != __mintypmax_sel)
+    {
+     __cv_msg(
+      "  SDF: selecting %s delays instead of %s from mtm_spec $sdf_annotate argument\n",
+      mtm_sel_tonam(__xs, __sdf_mintypmax_sel), mtm_sel_tonam(__xs2,
+      __mintypmax_sel));
+    }
+  } 
+
+ /* LOOKATME - can fnchp be nil */
+ if (fnchp != NULL)
+  {
+   do_systsk_sdf_annotate(fnchp, cntxtitp, __sfnam_ind, __slin_cnt);
+   __my_free(fnchp, slen + 1);
+  }
+ if (mtmchp != NULL) __my_free(mtmchp, slen2);
+
+ /* SJM 07/08/01 - put back normal log file if changed */ 
+ if (__sdf_log_s != NULL) 
+  {
+   __sdf_log_s = NULL;
+   __sdf_log_fnam = NULL;
+   __log_s = __sdf_sav_log_s;
+  }
+}
+
+/*
+ * open - read - close the sdf annotation file from $sdf_annotate system task
+ * call routine to do annotation
+ *
+ * this runs in run time context $sdf_annotate task call
+ */
+static void do_systsk_sdf_annotate(char *sdf_fnam, struct itree_t *itp,
+ int32 fnind, int32 slcnt)
+{
+ int32 sdfenum, sav_no_errs, sav_no_warns;
+ char s1[RECLEN];
+
+ /* open sdf annotation file */
+ if ((__sdf_s = __my_fopen(sdf_fnam, "r")) == NULL)
+  {
+   __gferr(1370, fnind, slcnt, 
+    "cannot open $sdf_annotate SDF input file %s", sdf_fnam);
+   return;
+  }
+
+ /* need to save error count for system task - will be 0 if from option */
+ __sdf_sav_enum = __pv_err_cnt;
+
+ /* SJM 06/16/00 - must never stop no matter how many SDF errors */
+ __sdf_active = TRUE;
+ __sdf_sav_maxerrs = __max_errors;
+ __max_errors = 0;
+
+ /* SJM 07/08/01 - add new do not print sdf errors and warns option */
+ sav_no_errs = __no_errs;
+ sav_no_warns = __no_warns;
+ if (__sdf_no_errs) __no_errs = TRUE;
+ if (__sdf_no_warns) __no_warns = TRUE;
+
+ __sdf_cntxt_itp = itp;
+ do_sdf_annotate(sdf_fnam, fnind, slcnt);
+ __max_errors = __sdf_sav_maxerrs;
+ __sdf_active = FALSE;
+ /* always replace saved no errs and no warns */
+ __no_errs = sav_no_errs;
+ __no_warns = sav_no_warns; 
+
+ get_sdfcntxtnam(s1, __sdf_cntxt_itp);
+ __sdf_cntxt_itp = NULL;
+
+ /* SJM 06/06/00 - change so report but do not count SDF errors */
+ if (__pv_err_cnt > __sdf_sav_enum)
+  {
+   sdfenum = __pv_err_cnt - __sdf_sav_enum;
+   __pv_err_cnt = __sdf_sav_enum;
+   __cv_msg(
+    "  **%d SDF errors during $sdf_annotate of \"%s\" context scope %s\n",
+    sdfenum, sdf_fnam, s1);
+  }
+ else if (__verbose) 
+  {
+   __cv_msg(
+    "  SDF delay $sdf_annotate completed for \"%s\" context scope %s.\n",
+    sdf_fnam, s1);
+  }
+}
+
+/*
+ * routine to read and annotate sdf file 
+ *
+ * called either by +sdf_annotate command line option processing routine
+ * or $sdf_annotate system task 
+ *
+ * use global __sdf_s stream to read sdf file
+ */
+static void do_sdf_annotate(char *sdf_fnam, int32 fnind, int32 slcnt)
+{
+ int32 sav_lin_cnt, ndels;
+ char *sav_fnam;
+
+ /* assume none for these since form optional */
+ strcpy(__sdf_none_str, "[none]");
+ __sdf_version = __sdf_none_str; 
+ __sdf_design = __sdf_none_str;
+ __sdf_date = __sdf_none_str;
+ __sdf_vendor = __sdf_none_str; 
+ __sdf_program = __sdf_none_str; 
+ __sdf_progversion = __sdf_none_str; 
+ __sdf_process = __sdf_none_str; 
+
+ /* allocate the global work vpi delay record */
+ __sdf_delp = (struct t_vpi_delay *) __my_malloc(sizeof(struct t_vpi_delay));
+ /* need extra delay need to read 13th for error detection */
+ ndels = SDF_MTMDNUM*SDF_PULDNUM*(SDF_MAXDELS+1);
+ __sdf_delp->da = (struct t_vpi_time *)
+  __my_malloc(ndels*sizeof(struct t_vpi_time)); 
+ init_vpi_del(__sdf_delp, ndels);
+ /* 2nd needed for separating timing check limits */
+ __sdf_delp2 = (struct t_vpi_delay *) __my_malloc(sizeof(struct t_vpi_delay));
+ __sdf_delp2->da = (struct t_vpi_time *)
+  __my_malloc(ndels*sizeof(struct t_vpi_time)); 
+ init_vpi_del(__sdf_delp2, ndels);
+ 
+ /* set flag so only one warning emitted if used */ 
+ __seen_ppulse = FALSE;
+ __seen_pc_ppulse = FALSE;
+ __seen_rlim_delval = FALSE;
+ __seen_xlim_delval = FALSE;
+
+ sav_lin_cnt = __lin_cnt;
+ sav_fnam = __cur_fnam;
+ __cur_fnam = sdf_fnam; 
+ __lin_cnt = 1;
+ __pathsep = DFLT_SEP_CHAR;
+
+ /* default is 1 ns - stored as negative so 9 is 10**-9 */
+ __sdf_timescale = 9;
+ /* need module to pass to real to ticks conversion routine */
+ /* sdf is like dummy module with possibly different time scale */ 
+ if (__des_timeprec == __sdf_timescale)
+  { __sdf_nd_tscale = FALSE; __sdf_ts_units = 0; }
+ else
+  {
+   __sdf_nd_tscale = TRUE;
+   __sdf_ts_units = (int32) __des_timeprec - __sdf_timescale;
+  }
+
+ /* notice extra spaces insure no conflict with escaped ID */
+ strcpy(__sdf_star_val, " * ");
+
+ /* read the file and build internal sdf d.s. */
+ rd_sdf_file(__sdf_s);
+ __my_fclose(__sdf_s);
+ __lin_cnt = sav_lin_cnt;
+ __cur_fnam = sav_fnam;
+ /* free all sdf values - no trace should be left after here except maybe */
+ /* changed delays */ 
+ free_sdf_hdrvals();
+}
+
+/*
+ * free the sdf current values (free header strings)
+ */
+static void free_sdf_hdrvals(void)
+{
+ int32 slen;
+
+ if (__sdf_delp != NULL)
+  {
+   /* number of delays is maximum possible */
+   __my_free((char *) __sdf_delp->da,
+    SDF_MTMDNUM*SDF_PULDNUM*SDF_MAXDELS*sizeof(struct t_vpi_time)); 
+   __my_free((char *) __sdf_delp, sizeof(struct t_vpi_delay));
+  }
+ if (__sdf_delp2 != NULL)
+  {
+   /* number of delays is maximum possible */
+   __my_free((char *) __sdf_delp2->da,
+    SDF_MTMDNUM*SDF_PULDNUM*SDF_MAXDELS*sizeof(struct t_vpi_time)); 
+   __my_free((char *) __sdf_delp2, sizeof(struct t_vpi_delay));
+  }
+ if (__sdf_version != __sdf_none_str) 
+  {
+   slen = strlen(__sdf_version) + 1;
+   __my_free((char *) __sdf_version, slen); 
+   __sdf_version = NULL;
+  }
+ if (__sdf_design != __sdf_none_str) 
+  {
+   slen = strlen(__sdf_design) + 1;
+   __my_free((char *) __sdf_design, slen); 
+   __sdf_design = NULL;
+  }
+ if (__sdf_date != __sdf_none_str) 
+  {
+   slen = strlen(__sdf_date) + 1;
+   __my_free((char *) __sdf_date, slen); 
+   __sdf_date = NULL;
+  }
+ if (__sdf_vendor != __sdf_none_str) 
+  {
+   slen = strlen(__sdf_vendor) + 1;
+   __my_free((char *) __sdf_vendor, slen); 
+   __sdf_vendor = NULL;
+  }
+ if (__sdf_program != __sdf_none_str) 
+  {
+   slen = strlen(__sdf_program) + 1;
+   __my_free((char *) __sdf_program, slen); 
+   __sdf_program = NULL;
+  }
+ if (__sdf_progversion != __sdf_none_str) 
+  {
+   slen = strlen(__sdf_progversion) + 1;
+   __my_free((char *) __sdf_progversion, slen); 
+   __sdf_progversion = NULL;
+  }
+ if (__sdf_process != __sdf_none_str) 
+  {
+   slen = strlen(__sdf_process) + 1;
+   __my_free((char *) __sdf_process, slen); 
+   __sdf_process = NULL;
+  }
+}
+
+/*
+ * get the scope context name in which annotation takes place
+ */
+static char *get_sdfcntxtnam(char *cntxtnam, struct itree_t *cntxt_itp)
+{
+ if (cntxt_itp == NULL) strcpy(cntxtnam, "**design**");  
+ else __msg2_blditree(cntxtnam, cntxt_itp);
+ return(cntxtnam);
+}
+
+/*
+ * initialize a vpi delay record
+ */
+static void init_vpi_del(struct t_vpi_delay *vdp, int32 ndels)
+{
+ register int32 i;
+ vdp->no_of_delays = 0;
+ /* only type supported by SDF */
+ vdp->time_type = vpiScaledRealTime;
+ vdp->mtm_flag = FALSE; 
+ vdp->pulsere_flag = FALSE;
+ vdp->append_flag = FALSE;
+ for (i = 0; i < ndels; i++)
+  {
+   vdp->da[i].type = vpiSimTime; 
+   vdp->da[i].high = 0;
+   vdp->da[i].low = 0;
+  }
+}
+
+/*
+ * SDF FORM INPUT ROUTINES
+ */
+
+/*
+ * read and process (set delays) for an sdf standard file 
+ *
+ * although lower level routines attempt to resync - here give up on err 
+ * at least one cell requered so do not need to catch errors here
+ */
+static void rd_sdf_file(FILE *f)
+{
+ struct t_vpi_time *vtp = &(__sdf_delp->da[0]);
+
+ get_sdftok(f);
+ if (__toktyp != LPAR)
+  {
+bad_file:
+   __pv_ferr(1370,
+    "initial (DELAYFILE missing (probably not SDF file) - %s read",
+    prt_sdftok());
+   return;
+  }
+ get_sdftok(f);
+ if (__toktyp != SDF_DELAYFILE) goto bad_file;
+
+ /* sdf version required rest optional - but must be inorder */
+ get_sdftok(f);
+ if (__toktyp != LPAR)
+  {
+bad_vershdr:
+   __pv_ferr(1349, "required (SDFVERSION header missing - %s read",
+    prt_sdftok());
+   return;
+  }
+ get_sdftok(f);
+ if (__toktyp != SDF_VERSION) goto bad_vershdr;
+ /* mallocs string if nil not returned and reads ending ) */
+ if (!rd_sdf_strval(f)) return;
+ __sdf_version = __pv_stralloc(__sdf_work_str);
+ if (strchr(__sdf_version, '3') == NULL)
+  {
+   __finform(460,
+   "(SDFVERSION %s) unexpected - should be 3.x - but if no errors still works", 
+    __sdf_version);
+  }
+
+ /* know there will be one - maybe just cell */ 
+ /* also know if present will be in order */
+ if (!rd2_sdf_formtyp(f)) return;
+
+ if (__toktyp == SDF_DESIGN)
+  {
+   if (!rd_sdf_strval(f)) return;
+   __sdf_design = __pv_stralloc(__sdf_work_str);
+   if (!rd2_sdf_formtyp(f)) return;
+  }
+ if (__toktyp == SDF_DATE) 
+  {
+   if (!rd_sdf_strval(f)) return;
+   __sdf_date = __pv_stralloc(__sdf_work_str);
+   if (!rd2_sdf_formtyp(f)) return;
+  }
+ if (__toktyp == SDF_VENDOR) 
+  {
+   if (!rd_sdf_strval(f)) return;
+   __sdf_vendor = __pv_stralloc(__sdf_work_str);
+   if (!rd2_sdf_formtyp(f)) return;
+  }
+ if (__toktyp ==  SDF_PROGRAM)
+  {
+   if (!rd_sdf_strval(f)) return;
+   __sdf_program = __pv_stralloc(__sdf_work_str);
+   if (!rd2_sdf_formtyp(f)) return;
+  }
+ if (__toktyp == SDF_VERSION)
+  {
+   if (!rd_sdf_strval(f)) return;
+   __sdf_progversion = __pv_stralloc(__sdf_work_str);
+   if (!rd2_sdf_formtyp(f)) return;
+  }
+ if (__toktyp ==  SDF_DIVIDER)
+  {
+   if (!rd_sdf_sepchar(f, &__pathsep)) return;
+   if (__pathsep == '/')
+    {
+     __pv_fwarn(675,
+   "(DIVIDER '/' unexpected - Verilog uses '.' separator so SDF path matching uses '.'");
+    }
+   if (!rd2_sdf_formtyp(f)) return;
+  }
+ if (__toktyp == SDF_VOLTAGE)
+  { 
+   /* form is (VOLTAGE min:typ:max) - no () or list - one value ok */
+   get_sdftok(f);
+
+   /* on T, reads ending ) - reads value too */
+   if (!rd_rtriple(f, vtp)) return;
+   if (vtp->type == vpiSuppressTime)
+    {
+     __pv_fwarn(662, "(VOLTAGE value missing in rtriple field \"%s\"",
+      mtm_sel_tonam(__xs, __sdf_mintypmax_sel));
+    }
+   else __sdf_voltage = vtp->real;
+   /* ) read - this reads either form that must be present */
+   if (!rd2_sdf_formtyp(f)) return;
+  }
+ if (__toktyp == SDF_PROCESS)
+  { 
+   get_sdftok(f);
+   /* empty (PROCESS) now legal */
+   if (__toktyp == RPAR) goto get_process_nxtform;
+   /* SJM 03/20/00 - for SDF all tokens and strings limited to id len */
+   if (__toktyp == LITSTR) strcpy(__sdf_work_str, __token);
+   else
+    { 
+     __pv_ferr(1320,
+      "(PROCESS right parenthesis or string value expected - %s read",
+      prt_sdftok());
+     return;
+    }
+   get_sdftok(f);
+   if (__toktyp != RPAR)
+    {
+     __pv_ferr(1322, "(PROCESS string value not followed by ) - %s read",
+      prt_sdftok());
+     return;
+    }
+   __sdf_process = __pv_stralloc(__sdf_work_str);
+
+get_process_nxtform:
+   if (!rd2_sdf_formtyp(f)) return;
+  }
+ if (__toktyp == SDF_TEMPERATURE)
+  { 
+   /* form is (TEMPERATURE min:typ:max) - no () or list - one value ok */
+   get_sdftok(f);
+   /* on T, reads ending ) - reads value too */
+   if (!rd_rtriple(f, vtp)) return;
+   if (vtp->type == vpiSuppressTime)
+    {
+     __pv_fwarn(662, "(TEMPERATURE value missing in rtriple field \"%s\"",
+      mtm_sel_tonam(__xs, __sdf_mintypmax_sel));
+    }
+   else __sdf_temp = vtp->real;
+   if (!rd2_sdf_formtyp(f)) return;
+  }
+ if (__toktyp == SDF_TIMESCALE)
+  {
+   if (!rd_sdf_timescaleval(f, &__sdf_timescale)) return;
+
+   if (__sdf_timescale > __des_timeprec)
+    {
+     __pv_fwarn(660,
+      "SDF TIMESCALE unit %s less than minimum unit %s in design - round to 0 probable",
+     __to_timunitnam(__xs, (word32) __sdf_timescale),
+     __to_timunitnam(__xs2, __des_timeprec));
+     return;
+    }
+   if (__sdf_timescale == __des_timeprec)
+    { __sdf_nd_tscale = FALSE; __sdf_ts_units = 0; }
+   else
+    {
+     __sdf_nd_tscale = TRUE;
+     __sdf_ts_units = (int32) __des_timeprec - __sdf_timescale;
+    }
+   if (!rd2_sdf_formtyp(f)) return;
+  }
+
+ /* multiple cells possible at least one required */
+ /* returns F on first file structure error - resync not possible */
+ /* if annotation errors only, returns T but does nothing */
+ if (!rdset_sdf_cells(f)) return;
+
+ /* will not have read eof since end with ) of cells */ 
+ get_sdftok(f);
+ if (__toktyp != TEOF)
+  __pv_fwarn(661,
+   "tokens after end of SDF DELAYFILE ignored - %s first ignored",
+   prt_sdftok());
+}
+
+/*
+ * convert current runs mtm selector to a name
+ */
+static char *mtm_sel_tonam(char *s, int32 mtmtyp)
+{
+ if (mtmtyp == DEL_MIN) strcpy(s, "min");
+ else if (mtmtyp == DEL_TYP) strcpy(s, "typ");
+ else if (mtmtyp == DEL_MAX) strcpy(s, "max");
+ else strcpy(s, "-unknown-");
+ return(s);
+}
+
+/*
+ * read the separator char form ending value
+ * here always returns some char - if error sets to default
+ * form and value can be missing
+ */
+static int32 rd_sdf_sepchar(FILE *f, char *sep)
+{
+ int32 c;
+
+ /* this is tricky cannot use get sdf token - skips to any non white space */
+ do { c = getc(f); } while(vis_white_(c)); 
+
+ get_sdftok(f);
+ if (__toktyp != RPAR) { formend_err("DIVIDER"); return(FALSE); }
+ 
+ /* cannot be part of id or escape */
+ if (c != '.' && c != '/')
+  {
+   __pv_ferr(1316, "DIVIDER form separator character %c illegal", c);
+   c = DFLT_SEP_CHAR;
+  }
+ *sep = c;
+ return(TRUE);
+}
+
+/*
+ * read a timescale form ending value (TIMESCALE read
+ * set tunits which is -1 to -15 normal timescale units value
+ */
+static int32 rd_sdf_timescaleval(FILE *f, int32 *tunits)
+{
+ int32 mult, mval;
+ word32 t1;
+ char *chp;
+
+ get_sdftok(f);
+ if (__toktyp == RPAR) { *tunits = 9; return(TRUE); }
+ /* 1ns form - will still return just number */ 
+ if (__toktyp == REALNUM) mval = (int32) __itok_realval;
+ else if (__toktyp == NUMBER) mval = (int32) __sdf_tokval;
+ else 
+  {
+   __pv_ferr(1318,
+    "TIMESCALE form unit value or ) (omitted form) missing - %s read",
+    prt_sdftok());
+   return(FALSE);
+  }
+ if (mval == 1) mult = 0;
+ else if (mval == 10) mult = 1;
+ else if (mval == 100) mult = 2;
+ else
+  {
+   __pv_ferr(1317, "(TIMESCALE form timescale units %d illegal",
+    __sdf_tokval);
+   mult = -1; 
+  }
+ get_sdftok(f);
+ if (__toktyp != ID)
+  { 
+   __pv_ferr(1373, "(TIMESCALE form scale suffix expected - %s read",
+    prt_sdftok());
+   return(FALSE);
+  } 
+ if ((chp = __get_tmult(__token, &t1)) == NULL || *chp != '\0') 
+  {
+bad_timfmt:
+   __pv_ferr(1319, "(TIMESCALE form scale suffix %s illegal", __token);
+   mult = -1;
+  }
+ if (mult == -1) *tunits = 9; 
+ else
+  {
+   if (t1 == 0 && mult != 0) goto bad_timfmt;
+   /* 10 subtracts 1 and 100 subtracts 2 - i.e ns (9 - 2 (for 10) = 7 */
+   *tunits = (int32) t1 - mult;
+  }
+ get_sdftok(f);
+ if (__toktyp != RPAR) { formend_err("TIMESCALE"); return(FALSE); }
+ return(TRUE);
+}
+
+/*
+ * ROUTINES TO READ CELL FORMS 
+ */
+
+/*
+ * read every sdf cell entry and set delays for it (at least one required)
+ *
+ * returns F on error 
+ * upon entry will have read CELL keyword of form
+ * on exit has read ending ) but not eof
+ * instances qualified names - for paths must select exact instance
+ */
+static int32 rdset_sdf_cells(FILE *f)
+{
+ int32 all_insts, i1, i2;
+ struct itree_t *itp, *top_itp;
+ struct expr_t *glbndp;
+ struct mod_t *ctmdp;
+ struct sy_t *syp, *syp2;
+ char ctnam[IDLEN], inam[IDLEN], ginam[IDLEN], s1[RECLEN];
+
+ /* expects (CELL to have been read */
+ for (;;)  
+  {
+   if (__toktyp != SDF_CELL)
+    {
+     __pv_ferr(1323, "(CELL form expected - (%s read", prt_sdftok());
+     return(FALSE);
+    }
+   if (!rd2_sdf_formtyp(f)) return(FALSE);
+   if (__toktyp != SDF_CELLTYPE)
+    {
+     __pv_ferr(1324, "(CELLTYPE form expected - (%s read", prt_sdftok());
+     return(FALSE);
+    }
+   /* this reads ending ) */
+   if (!rd_sdf_strval(f)) return(FALSE);
+   /* this can not be qualified name or contain selects */
+   if (!chkcnv_sdfid(ctnam, &i1, &i2, __sdf_work_str, FALSE) || i1 != -1)
+    {
+     __pv_ferr(1330, "(CELLTYPE Verilog type name %s illegal format",
+      __sdf_work_str);
+     return(FALSE);
+    }
+
+   /* read instance form - path can be concatenation of instance forms */  
+   if (!rd2_sdf_formtyp(f)) return(FALSE); 
+   if (__toktyp != SDF_INSTANCE)
+    {
+     __pv_ferr(1324, "(INSTANCE form expected - (%s read", prt_sdftok());
+     return(FALSE);
+    }
+   get_sdftok(f);
+   all_insts = FALSE;
+   i1 = i2 = -1;
+   itp = NULL;
+   strcpy(inam, "");
+   strcpy(ginam, ""); 
+   if (__toktyp == ID)
+    {
+     if (__id_qualpath)
+      {
+       /* because this is inst. non variable name, last component select ok */
+       if (!chkcnv_sdfpath(inam, &i1, &i2, __token, TRUE) || i1 != i2)
+        {
+         __pv_ferr(1325,
+          "(INSTANCE hierarchical instance name %s illegal Verilog path name",
+          __token);
+         return(FALSE);
+        }
+      }
+     else if (!chkcnv_sdfid(inam, &i1, &i2, __token, TRUE) || i1 != i2)
+      {
+       __pv_ferr(1325, "(INSTANCE form name of instance %s illegal",
+        __token);
+      }
+    }
+   else if (__toktyp == TIMES)
+    {
+     /* inam empty string here */
+     all_insts = TRUE;
+     get_sdftok(f);
+     if (__toktyp != ID) goto chk_rpar;
+     if (__id_qualpath)
+      {
+       __pv_ferr(1245,
+        "(INSTANCE * [gate instance name]) qualified gate name path %s illegal",
+        __token);
+       return(FALSE);
+      }
+     /* gate instance name here can have index */
+     if (!chkcnv_sdfid(ginam, &i1, &i2, __token, TRUE) || i1 != i2)
+      {
+       __pv_ferr(1245, "(INSTANCE * [gate name]) name of gate %s illegal",
+        __token);
+       return(FALSE);
+      }
+     /* for simple gate name with index - can not add index as suffix */
+    }
+   else if (__toktyp == RPAR)
+    {
+     /* empty cell name case - means in context (or first top if none) */
+     /* leave inam as "" - also know ginam "" */
+     goto chk_rpar;
+    }
+   else 
+    {
+     __pv_ferr(1328, "(INSTANCE form path, primitive or * expected - %s read", 
+      prt_sdftok());
+     return(FALSE);
+    }
+   get_sdftok(f);
+chk_rpar:
+   /* either gate instance name (non path) or instance path but not both set */
+   if (__toktyp != RPAR) { formend_err("INSTANCE"); return(FALSE); }
+   get_sdftok(f);
+   /* this reads either timing spec keyword or ) */
+   if (!rd_sdf_formtyp(f)) return(FALSE); 
+
+   /* this can be gate type name or module type name for (* [gate inst]) */
+   /* but never xmr or gate/instance select */
+   if ((syp =__get_sym(ctnam, __modsyms)) == NULL)
+    {
+     __pv_ferr(1389,
+      "(CELL form (CELLTYPE \"%s\" is not a module type or primitive name",
+      ctnam);
+     /* cell type unknown, unable to process instance */
+skip_cell:
+     if (!sdf_skip_form(f)) return(FALSE);
+     goto nxt_cell;
+    }  
+   /* case 1: primitive gate or udp - must be (DEVICE delay */ 
+   if (syp->sytyp == SYM_PRIM || syp->sytyp == SYM_UDP)
+    {
+     if (all_insts)
+      { 
+       __pv_ferr(1397,
+        "SDF DEVICE primitive wildcard form illegal - setting delay for all meaningless");
+       goto skip_cell;
+      } 
+     /* if non * [gate inst] form, syp is (CELLTYPE, inam is gate inst path */
+     /* for array of gates i1 is gate index and inam is base name */
+     if (!rdset_prim_delay(f, syp, i1, inam, (struct sy_t *) NULL))
+      goto skip_cell;
+     goto nxt_cell;
+    }
+
+   /* DBG remove -- */
+   if (syp->sytyp != SYM_M) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* case 1a: all instances of primitive (gate) in type */ 
+   if (strcmp(ginam, "") != 0)
+    {
+     /* ginam only set if all insts * form */
+     /* DBG remove -- */
+     if (!all_insts) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     /* look up gate instance name - must be gate in type */
+     /* can be base name of gate instance array */
+     if ((syp2 = __get_sym(ginam, syp->el.emdp->msymtab)) == NULL
+      || (syp2->sytyp != SYM_PRIM && syp2->sytyp != SYM_UDP))
+      {
+       __pv_ferr(1360,
+        "(CELLTYPE * [gate]) form primitive %s not defined in type %s", 
+        ginam, syp->synam);
+       goto skip_cell;
+      }
+     /* * [gate inst] form, syp is (CELLTYPE mod, inam nil, syp2 gate inst */
+     /* for array of gates syp2 is base element and i1 is index */ 
+     if (!rdset_prim_delay(f, syp, i1, inam, syp2)) goto skip_cell;
+     goto nxt_cell;
+    }
+   ctmdp = syp->el.emdp;
+
+   if (all_insts) goto rd_timspec;
+
+   /* case 2 - one specific named (maybe "" for in context) instance */
+   /* need to fixup instance name by adding index if any back on */
+   if (i1 != -1)
+    {
+     char s2[IDLEN];
+
+     sprintf(s2, "%s[%d]", inam, i1);
+     strcpy(inam, s2);
+    }
+   /* empty iname form - use first top or context */
+   /* case 2a - no instance - in context or first top level */
+   if (strcmp(inam, "") == 0)
+    {
+     if (__sdf_cntxt_itp == NULL)
+      { 
+       itp = __it_roots[0];
+       if (__numtopm != 1)
+        {
+         __pv_fwarn(648,
+          "(INSTANCE ) form with no context ambiguous because more than one top level module - using first (%s)",
+          itp->itip->imsym->synam);
+        }
+      }
+     else itp = __sdf_cntxt_itp;
+     goto rd_timspec;
+    }
+   /* case 2b - have instance path */
+   /* need to use interactive global context here */
+   __push_wrkitstk(__sdf_mdp, 0);
+   if ((glbndp = __glbnam_to_expr(inam)) == NULL)
+    {
+     __pop_wrkitstk();
+     goto skip_cell;
+    }
+   /* case 2b-1 - no context */
+   if (__sdf_cntxt_itp == NULL)
+    {
+     /* no context first try rooted */
+     if ((itp = get_sdfdownrel_itp(glbndp, NULL, NULL, s1)) != NULL)
+      { 
+       __free_xtree(glbndp);
+       __pop_wrkitstk();
+       goto rd_timspec;
+      }
+
+     /* then try in first top level */ 
+     top_itp = __it_roots[0];
+     if (__numtopm != 1)
+      {
+       __pv_fwarn(648,
+        "(INSTANCE form non rooted instance path %s ambiguous because more than one top level module - using first (%s)",
+        inam, top_itp->itip->imsym->synam);
+      }
+     itp = get_sdfdownrel_itp(glbndp, top_itp, NULL, s1);
+     /* done with glb ndp thru this code path */
+     __free_xtree(glbndp);
+     __pop_wrkitstk();
+  
+     if (itp == NULL)
+      { 
+       __pv_ferr(1378, "(CELL instance %s not found as rooted path or in first top level module: %s",
+        inam, s1);
+       goto skip_cell;
+      }
+     goto rd_timspec; 
+    }
+
+   /* case 2b-2 - must be in context annotation context instance */ 
+   itp = get_sdfdownrel_itp(glbndp, __sdf_cntxt_itp, NULL, s1);
+   /* done with glb ndp thru this code path */
+
+   /* if not in sdf context - see if name is rooted */
+   if (itp == NULL)
+    {
+     /* SJM 01/14/00 - need to search for rooted cell instance */ 
+     /* previously only worked if no context command option was used */
+     /* not search first in context for cell (not device) then rooted always */
+     if ((itp = get_sdfdownrel_itp(glbndp, NULL, NULL, s1)) != NULL)
+      { 
+       __free_xtree(glbndp);
+       __pop_wrkitstk();
+       goto rd_timspec;
+      }
+     __pv_ferr(1378, "(CELL instance %s undefined rooted or in context %s: %s",
+      inam, get_sdfcntxtnam(__xs, __sdf_cntxt_itp), s1);
+    }
+   __free_xtree(glbndp);
+   __pop_wrkitstk();
+
+rd_timspec:
+   /* read/set 1 or more timing specs - if design context, then '*' all */ 
+   if (!rdset_timing_spec(f, itp, ctmdp)) return(FALSE);
+
+nxt_cell:
+   /* know cell ending ) read to get here */
+   /* see if more cells */
+   get_sdftok(f);
+   if (!rd_sdf_formtyp(f)) return(FALSE); 
+   if (__toktyp == RPAR) break;
+  }
+ return(TRUE);
+}
+
+/*
+ * find sdf path instance (always downward relative) given global expr
+ *
+ * possibly no context so name must be rooted 
+ * last component may be non scope variable end (found and ignored here)
+ * only for use during SDF annotation - caller must emit error on nil return
+ *
+ * if tailsyp nil, calling from known instance xmr where last must be
+ * instance or error, else last must be non instance and tail name copied
+ * into passed string variable
+ *
+ * called after fixup so know miarr's built
+ */
+static struct itree_t *get_sdfdownrel_itp(struct expr_t *glbndp,
+ struct itree_t *cntxt_itp, struct sy_t **tailsyp, char *errmsg) 
+{
+ int32 ii;
+ byte *bp1, *bp2;
+ struct expr_t *gcmp_ndp;
+ struct itree_t *itp;
+ struct mod_t *mdp;
+ struct sy_t *isyp;
+ struct inst_t *ip;
+ struct giarr_t *giap;
+ char *chp;
+
+ gcmp_ndp = glbndp->ru.x;
+ /* here context is annotate scope not cell context */
+ /* for down rel. path in cell context and '*' form, pass first of type */
+ if (cntxt_itp == NULL)
+  {
+   /* know top level rooted first component never indexed */
+   chp = __to_glbcmp_nam(gcmp_ndp);
+   if ((ii = __ip_indsrch(chp)) == -1)
+    {
+     strcpy(errmsg, "root undefined");
+     return(NULL);
+    }
+   itp = __it_roots[ii];
+   gcmp_ndp = gcmp_ndp->ru.x;
+  }
+ else itp = cntxt_itp;
+
+ /* this is for getting type, on inst '*' form */ 
+ for (;gcmp_ndp != NULL; gcmp_ndp = gcmp_ndp->ru.x)
+  {
+   mdp = itp->itip->imsym->el.emdp;
+   chp = __to_glbcmp_nam(gcmp_ndp);
+   /* look up component in module symbol table */
+   if ((isyp = __get_sym(chp, mdp->msymtab)) == NULL)
+    {
+     sprintf(errmsg, "component %s undefined in %s", chp, mdp->msym->synam);
+     return(NULL);
+    }
+
+   if (isyp->sytyp != SYM_I)
+    {
+     if (tailsyp == NULL)
+      {
+       strcpy(errmsg, "no non-scope (probably gate) ending symbol");
+       return(NULL);
+      }
+     if (gcmp_ndp->ru.x != NULL)
+      {
+       strcpy(errmsg, "non-scope symbol inside path");
+       return(NULL);
+      }
+     *tailsyp = isyp;
+     return(itp);
+    }
+
+   ip = isyp->el.eip; 
+   /* making use of c pointer subtraction correction object size here */
+   /* changing to byte ptr because not sure of c ptr size object rules */
+   bp1 = (byte *) ip;
+   bp2 = (byte *) mdp->minsts;
+   ii = (bp1 - bp2)/sizeof(struct inst_t);
+   if (mdp->miarr == NULL || (giap = mdp->miarr[ii]) == NULL)
+    {
+     /* must be ID component */
+     if (gcmp_ndp->lu.x->optyp != XMRID)
+      {
+       sprintf(errmsg, "select of non-instance array %s", ip->isym->synam);
+       return(NULL);
+      }
+    }
+   else
+    {
+     int32 indx;
+     struct xstk_t *xsp;
+
+     /* DBG remove -- */
+     if (!isyp->sy_giabase) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+
+     /* must be inst select component */
+     if (gcmp_ndp->lu.x->optyp != LSB)
+      {
+       sprintf(errmsg, "select of instance array %s required", isyp->synam);
+       return(NULL);
+      }
+
+     __push_wrkitstk(mdp, 0);
+     xsp = __eval_xpr(gcmp_ndp->lu.x->ru.x);
+     __pop_wrkitstk();
+     indx = xsp->ap[0]; 
+     __pop_xstk(); 
+     /* high to low case - bit h is gia bi th (first) */
+     if (giap->gia1 > giap->gia2)
+      {
+       if (indx > giap->gia1 || indx < giap->gia2) return(NULL);
+       else ii = giap->gia_bi + (giap->gia1 - indx);
+      }
+     else
+      {
+       /* low to high case - bit h is gia bi + h (last) */
+       if (indx < giap->gia1 || indx > giap->gia2) return(NULL);
+       ii = giap->gia_bi + (indx - giap->gia1);
+      }
+    }
+   itp = &(itp->in_its[ii]);
+  } 
+ /* instance path expected but has name (gate?) at end */
+ if (tailsyp != NULL)
+  {
+   strcpy(errmsg, "path end must be instance"); 
+   return(NULL);
+  }
+ return(itp);
+}
+
+/*
+ * PRIMITIVE (GATE) DELAY FORM READING AND SETTING ROUTINES
+ */
+
+/*
+ * read set a primitive delay - must be (DEVICE form or error
+ *
+ * itp = nil for all insts, where tsyp is mod type and gisyp is gate inst
+ * when itp not nil tsyp set to module type symbol
+ *
+ * inam may end in gate instance where for array of gates it is base with
+ * index i1 which must not be -1
+ *
+ * since there is always one in tsyp gate instance, ctgp always set to it
+ * for (instance * [gate inst]) (CELLTYPE is tsyp, and gate inst is ctgp
+ *
+ * (DEVICE that is abbreviation for all paths handled elsewhere
+ * know DEVICE keyword or ) read
+ */
+static int32 rdset_prim_delay(FILE *f, struct sy_t *tsyp, int32 i1, char *inam,
+ struct sy_t *gisyp)
+{
+ int32 first_time, gi;
+ char *chp;
+ byte *bp1, *bp2;
+ struct giarr_t *giap;
+ struct sy_t *gsyp, *dumsyp;
+ struct gate_t *ctgp;
+ struct mod_t *mdp;
+ struct expr_t *glbndp;
+ struct itree_t *itp;
+ char ctgnam[IDLEN], s1[RECLEN];
+ 
+ /* * form requires instance name of gate in all instance of type */
+ /* already have the instance symbol in gisyp */
+ if (gisyp != NULL) { itp = NULL; ctgp = gisyp->el.egp; }
+ else
+  {
+   /* DBG remove -- */
+   if (strcmp(inam, "") == 0) __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   /* need to use interactive global context here */
+   __push_wrkitstk(__sdf_mdp, 0);
+   if ((glbndp = __glbnam_to_expr(inam)) == NULL)
+    {
+     __pop_wrkitstk();
+     return(FALSE);
+    }
+
+   /* case 1 - gate instance name has only one component */
+   if (glbndp->ru.x->ru.x == NULL)
+    {
+     /* DBG remove --- */
+     if (glbndp->ru.x->lu.x->optyp == LSB) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     chp = __to_glbcmp_nam(glbndp->ru.x);
+     strcpy(ctgnam, chp);
+     /* done with glb ndp thru this code path */
+     __free_xtree(glbndp);
+     __pop_itstk();
+
+     /* for design scope (one above any top level module), path needed */ 
+     if (__sdf_cntxt_itp == NULL)
+      {
+       __pv_ferr(1392,
+        "primitive non hierarchical instance %s illegal because SDF context is entire design",  
+        ctgnam);
+       return(FALSE);
+      }
+     else itp = __sdf_cntxt_itp;
+    }
+   else
+    { 
+     /* remove the tail that is primitive (i.e. gate) inst and set itp */
+     itp = get_sdfdownrel_itp(glbndp, __sdf_cntxt_itp, &dumsyp, s1);
+     /* done with glb ndp thru this code path */
+     __free_xtree(glbndp);
+     __pop_itstk();
+
+     if (itp == NULL)
+      {
+       __pv_ferr(1351, 
+        "for primitive delay, (CELL instance %s undefined in context %s: %s",
+        inam, get_sdfcntxtnam(__xs, __sdf_cntxt_itp), s1);
+       return(FALSE);
+      }
+
+     /* DBG remove --- */
+     if (dumsyp == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     /* for array of gates this is base name with i1 (non -1) index */  
+     strcpy(ctgnam, dumsyp->synam);
+    }
+   /* if type is primitive, look up inst name in module's symbol table */
+   tsyp = itp->itip->imsym;
+   mdp = tsyp->el.emdp;
+   /* for non * qualified path the one gate gname in mdp */
+   if ((gsyp =__get_sym(ctgnam, mdp->msymtab)) == NULL)
+    {
+     __pv_ferr(1351,
+      "%s primitive instance %s not found in module %s (from instance path %s)",
+      tsyp->synam, ctgnam, mdp->msym->synam, inam); 
+     return(FALSE); 
+    }
+   ctgp = gsyp->el.egp;
+
+   /* making use of c pointer subtraction correction object size here */
+   /* changing to byte ptr because not sure of c ptr size object rules */
+   bp1 = (byte *) ctgp;
+   bp2 = (byte *) mdp->mgates;
+   gi = (bp1 - bp2)/sizeof(struct gate_t);
+   if (mdp->mgarr != NULL && (giap = mdp->mgarr[gi]) != NULL)
+    {
+     /* DBG remove -- */
+     if (!gsyp->sy_giabase) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+
+     /* must be array of gates select component */
+     if (i1 == -1)
+      {
+       __pv_ferr(1393,
+        "%s primitive instance %s is array of gates - required select missing",
+        tsyp->synam, gsyp->synam); 
+       return(FALSE);
+      }
+
+     if (giap->gia1 > giap->gia2)
+      {
+       if (i1 > giap->gia1 || i1 < giap->gia2)
+        {
+bad_sel:
+         __pv_ferr(1501,
+          "%s primitive array of gates instance %s index %d out of range [%d:%d]",
+           tsyp->synam, gsyp->synam, i1, giap->gia1, giap->gia2);
+         return(FALSE);
+        }
+       else gi = giap->gia_bi + (giap->gia1 - i1);
+      }
+     else
+      {
+       if (i1 < giap->gia1 || i1 > giap->gia2) goto bad_sel;
+       gi = giap->gia_bi + (i1 - giap->gia1);
+      }
+     ctgp = &(mdp->mgates[gi]);
+    }
+   else
+    {
+     if (i1 != -1)
+      {
+       __pv_ferr(1502,
+        "%s primitive instance %s select of non arrayed gate illegal",
+        tsyp->synam, gsyp->synam); 
+       return(FALSE);
+      }
+    }
+   /* know ctgp set to gate (maybe bit of array of gates here) */
+  }
+ /* read and set the device delay */
+ /* cell can contain any number (at least one) but only (DEVICE */ 
+ for (first_time = TRUE;;)
+  {
+   if (__toktyp == RPAR)
+    {
+     if (first_time)
+      {
+       __finform(477,
+        "(CELL %s primitive instance del_spec empty - no delays annotated",
+        tsyp->synam);
+      }
+     goto done;
+    }
+   if (__toktyp != SDF_DELAY)
+    {
+     __pv_ferr(1336, "only (DELAY form allowed for primitive delay - (%s read",
+      prt_sdftok());
+     return(FALSE);
+    }
+   if (!prim_rdset_device_del(f, itp, tsyp, ctgp)) return(FALSE);
+   first_time = FALSE;
+   get_sdftok(f);
+   if (!rd_sdf_formtyp(f)) return(FALSE);
+  }
+done:
+ return(TRUE);
+}
+
+/*
+ * read absolute or increment primitive gate form
+ *
+ * for instance form ctgp is gate instance in itp
+ * for (CELL (CELLTYPE "RSLATCH") (INSTANCE * bufa) (DEVICE 3 4))
+ * itp=nil, 
+ */
+static int32 prim_rdset_device_del(FILE *f, struct itree_t *itp,
+ struct sy_t *tsyp, struct gate_t *ctgp)
+{
+ int32 first_time, first2_time, ndels, lcnt, sav_lcnt;
+ char formnam[RECLEN];
+
+ for (first_time = TRUE;;) 
+  {
+   get_sdftok(f);
+   if (!rd_sdf_formtyp(f)) return(FALSE);
+   if (__toktyp == RPAR)
+    {
+     if (first_time)
+      {
+       __pv_ferr(1333,
+        "primitive (DELAY form empty - at least one (ABOSLUTE or (INCREMENT required");
+       return(FALSE);
+      }
+     break;
+    }
+   if (__toktyp != SDF_ABSOLUTE && __toktyp != SDF_INCREMENT)
+    {
+     __pv_ferr(1336,
+      "primitive instance (ABSOLUTE or (INCREMENT expected - (%s read",
+      prt_sdftok());
+     return(FALSE);
+    } 
+   first_time = FALSE;
+   strcpy(formnam, __token);
+   for (first2_time = TRUE;;) 
+    {
+     get_sdftok(f);
+     if (!rd_sdf_formtyp(f)) return(FALSE);
+     if (__toktyp == RPAR)
+      {
+       if (first2_time)
+        {
+         __pv_ferr(1337,
+          "(%s form empty - at least one primitive instance (DEVICE form required",
+          formnam);
+         return(FALSE);
+        }
+       break;
+      } 
+     lcnt = __lin_cnt;
+     if (__toktyp != SDF_DEVICE)
+      {
+       __pv_ferr(1336,
+        "for primitive instance only (DEVICE form allowed - (%s read",
+        prt_sdftok());
+       return(FALSE);
+      }
+     first2_time = FALSE;
+     get_sdftok(f);
+     if (__toktyp != LPAR) { dellst_err(formnam, "DEVICE"); return(FALSE); }
+     get_sdftok(f);
+     if ((ndels = rd_sdf_dellst(f, "DEVICE")) == -1) return(FALSE);
+     /* except for next 2 fields all t_vpi_delay fields fixed in SDF */
+     __sdf_delp->no_of_delays = ndels; 
+     if (strcmp(formnam, "INCREMENT") == 0) __sdf_delp->append_flag = TRUE;
+     else __sdf_delp->append_flag = FALSE;
+
+     /* need to be able to emit f errors for first token in form */
+     sav_lcnt = __lin_cnt; 
+     __lin_cnt = lcnt;  
+     set_device_del(itp, ctgp, tsyp);
+     __lin_cnt = sav_lcnt;
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * set device primitive delays
+ *
+ * uses global sdf delp
+ * wildcard form is extension (not in standard), (i * [gate inst]) 
+ * normal * wild card form does not make sense because need all gate
+ * instances in type
+ *
+ * for both forms tsyp is symbol of instance type - ctgp is gate inst.
+ */
+static void set_device_del(struct itree_t *itp, struct gate_t *ctgp,
+ struct sy_t *tsyp)
+{
+ int32 ndels, dfix;
+ struct gate_t ogat, ngat;
+ struct mod_t *mdp;
+ char s1[IDLEN];
+
+ /* even for all instances of one gate instance, only check once */
+ ndels = __sdf_delp->no_of_delays;
+ mdp = tsyp->el.emdp;
+ dfix = 4;
+ if (ctgp->g_class == GC_UDP || ctgp->g_class == GC_LOGIC)
+  {
+   if (ndels > 2)
+    {
+     __pv_ferr(1398,
+      "SDF (CELLTYPE %s (DEVICE primitive %s has %d delay values - must be 1 or 2",
+      mdp->msym->synam, ctgp->gmsym->synam, ndels);
+     return; 
+    }
+   dfix = 2;
+  }
+ else
+  {
+   if (ndels > 3)
+    {
+     __pv_ferr(1398,
+      "SDF (CELLTYPE %s (DEVICE primitive %s has %d delay values - must be 1, 2 or 3",
+      mdp->msym->synam, ctgp->gmsym->synam, ndels);
+     return;
+    }  
+   dfix = 3;
+  }
+
+ /* this is needed because if no insts in SDF scope context no #0 del add */ 
+ if (itp == NULL)
+  {
+   if (find_1under_itp(mdp) == NULL)
+    {
+     __pv_fwarn(665,
+      "delays not changed for (DEVICE gate %s because no instance of type %s in context", 
+      ctgp->gmsym->synam, mdp->msym->synam);
+     return;
+    }
+  }
+
+ sprintf(s1, "(DEVICE %s %s in %s", ctgp->gmsym->synam, ctgp->gsym->synam,
+  mdp->msym->synam);  
+ /* already checked for adding delay in non load run state */
+ if (ctgp->g_delrep == DT_NONE)
+  { if (!__add_gate_pnd0del(ctgp, mdp, s1)) return; } 
+
+ ogat.g_du = ctgp->g_du;
+ ogat.g_delrep = ctgp->g_delrep;
+ if (itp == NULL)
+  {
+   /* this handles any needed delay freeing */
+   if (!upd_sdf_perinst_del(&ogat, __sdf_delp, mdp, FALSE, FALSE,
+    dfix, s1)) return;
+  }
+ else
+  {
+   /* build the new value, maybe using old to append to if append flag */
+   /* uses itree loc. from hp if needed for append access */
+   /* only allocate delay that needs to be freed if returns T */ 
+   if (!bld_sdfnewdu(&ngat, &ogat, __sdf_delp, itp, FALSE, FALSE, s1))
+    return;
+
+   /* this must always recomputer toz (logic) and tox all because never */
+   /* explicitly given */
+   if (ngat.g_delrep == DT_4V)
+    {
+     if (dfix == 2)
+      {
+       if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
+        {
+         ngat.g_du.d4v[2] = ngat.g_du.d4v[0];
+         ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
+        }
+       else
+        {
+         ngat.g_du.d4v[2] = ngat.g_du.d4v[1];
+         ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
+        }
+      }
+     else if (dfix == 3)
+      {
+       if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
+        ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
+       else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
+      }
+    }
+   /* this handles freeing and realloc of delay union if needed */
+   __chg_1inst_del(&ogat, itp, &ngat);
+   __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
+  }
+ ctgp->g_du = ogat.g_du;  
+ ctgp->g_delrep = ogat.g_delrep;
+ if (__sdf_verbose) prep_sdfdev_verbmsg(ctgp, &ogat, itp, mdp);
+}
+
+/*
+ * wrapper to prepare and call device sdf verbose tracing message
+ */
+static void prep_sdfdev_verbmsg(struct gate_t *gp, struct gate_t *ogp,
+ struct itree_t *itp, struct mod_t *mdp)
+{
+ register int32 ii;
+ register struct itree_t *itp2;
+ char s1[RECLEN], s2[RECLEN];
+
+ if (itp == NULL)
+  {
+   for (ii = 0; ii < mdp->flatinum; ii++)
+    {
+     itp2 = mdp->moditps[ii];
+     __push_itstk(itp2);
+     sprintf(s1, "%s(%s) from '*'", __msg2_blditree(s2, itp2),
+      mdp->msym->synam);
+     emit_sdfdev_verbmsg(gp, ogp, s1);
+     __pop_itstk();
+    }
+  } 
+ else
+  {
+   __push_itstk(itp);
+   sprintf(s1, "%s(%s)", __msg2_blditree(s2, itp), mdp->msym->synam);
+   emit_sdfdev_verbmsg(gp, ogp, s1);
+   __pop_itstk();
+  }
+}
+
+/*
+ * emit sdf device verbose tracing message 
+ */
+static void emit_sdfdev_verbmsg(struct gate_t *gp, struct gate_t *ogp,
+ char *celloc)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ __cv_msg("  SDF **%s(%d): (DEVICE %s %s delay set to (%s) in %s at %s\n",
+  __cur_fnam, __lin_cnt, gp->gmsym->synam, gp->gsym->synam,
+  __bld_delay_str(s1, ogp->g_du, ogp->g_delrep), celloc,
+  __bld_lineloc(s2, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt));
+}
+
+/*
+ * ROUTINES TO READ AND TIMING TIMING SPEC FORMS 
+ */
+
+/*
+ * read and set delay for one or more timing spec forms
+ *
+ * know first token read ([timing spec name] or )) and reads cell ending ) 
+ */
+static int32 rdset_timing_spec(FILE *f, struct itree_t *itp, struct mod_t *ctmdp)
+{
+ int32 first_time;
+
+ /* DBG remove -- */
+ if (ctmdp == NULL) __arg_terr(__FILE__, __LINE__);
+ /* --- */ 
+
+ /* cell can contain any number (at least one) timing_specs */ 
+ for (first_time = TRUE;;)
+  {
+   switch ((byte) __toktyp) {
+    case RPAR:
+     if (first_time)
+      {
+       __finform(477, "(CELL instance %s missing timing specifications",
+        get_sdfinam(__xs, itp, ctmdp));
+      }
+     goto done;
+    case SDF_DELAY:
+     if (!rdset_deltyps(f, itp, ctmdp)) return(FALSE);
+     break;
+    case SDF_TIMINGCHECK:
+     if (!rdset_tchk_defs(f, itp, ctmdp)) return(FALSE);
+     break;
+    case SDF_TIMINGENV:
+     /* for simulator these are just skipped */
+     if (!rdskip_te_defs(f)) return(FALSE);
+     break;
+    case SDF_LABEL:
+     if (!rdset_labels(f, itp, ctmdp)) return(FALSE);
+     break;
+    default:
+     __pv_ferr(1353, "timing_spec form name expected - %s read", 
+      prt_sdftok());
+     return(FALSE);
+   }
+   first_time = FALSE;  
+   get_sdftok(f);
+   if (!rd_sdf_formtyp(f)) return(FALSE); 
+  }
+done:
+ return(TRUE);
+}
+
+/*
+ * get sdf cell instance name (may be * for all under) 
+ */
+static char *get_sdfinam(char *s, struct itree_t *itp, struct mod_t *ctmdp)
+{
+ char s1[RECLEN];
+
+ if (itp == NULL) sprintf(s, "* (all instances of type %s under %s",
+  ctmdp->msym->synam, get_sdfcntxtnam(s1, __sdf_cntxt_itp));
+ else sprintf(s, "%s (type %s)", itp->itip->isym->synam, ctmdp->msym->synam); 
+ return(s);
+}
+
+/*
+ * read a delay timing spec form
+ * know (DELAY read - can be multiple deltyp records
+ * reads ending )
+ */
+static int32 rdset_deltyps(FILE *f, struct itree_t *itp, struct mod_t *ctmdp)
+{
+ int32 first_time, i11, i12, i21, i22, pptyp;
+ char formnam[RECLEN], pnam1[IDLEN], pnam2[IDLEN];
+
+ for (first_time = TRUE;;) 
+  {
+   get_sdftok(f);
+   if (!rd_sdf_formtyp(f)) return(FALSE);
+   if (__toktyp == RPAR)
+    {
+     if (first_time)
+      {
+       __pv_ferr(1333,
+        "(DELAY form empty - at least one deltype form required");
+       return(FALSE);
+      }
+     break;
+    }
+   first_time = FALSE;
+   switch ((byte) __toktyp) {
+    case SDF_PATHPULSE:
+    case SDF_PATHPULSEPERCENT:
+     pptyp = __toktyp;
+     strcpy(formnam, __token);
+     get_sdftok(f); 
+     if (__toktyp == ID)
+      {
+       /* qualified port names now alwayhs use . separator */
+       if (!rd_port(f, pnam1, &i11, &i12)) return(FALSE);
+       if (!rd_port(f, pnam2, &i21, &i22)) return(FALSE);
+
+       /* AIV 11/20/03 only need to be checked if pnams set */
+       /* need to check but since syntax good just continue */
+       port_qual_nam(pnam1, "(PATHPULSE port"); 
+       port_qual_nam(pnam2, "(PATHPULSE port");
+      }
+     /* this reads ) ending form */
+     if (rd_1or2_vals(f, formnam) == -1) return(FALSE); 
+
+     /* SJM 03/13/04 - move into ID case above by AIV - why? */ 
+
+     if (pptyp == SDF_PATHPULSE)
+      { 
+       if (!__seen_ppulse)
+        {
+         __seen_ppulse = TRUE;
+         __pv_fwarn(666,
+          "all (PATHPULSE forms ignored - actual delay used for reject or x limits"); 
+        }
+      }
+     else
+      {
+       if (!__seen_pc_ppulse)
+        {
+         __seen_pc_ppulse = TRUE;
+         __pv_fwarn(656,
+          "all (PATHPULSEPERCENT forms ignored - 100%% of delay for r or x limits used"); 
+        }
+      }
+     if (ctmdp == NULL)
+      {
+       __pv_ferr(1395, "primitive (gate or UDP) CELLTYPE illegal for PATHPULSE");
+      }
+     break;
+    case SDF_ABSOLUTE:
+    case SDF_INCREMENT:
+     strcpy(formnam, __token);
+     rd_deldef(f, itp, ctmdp, formnam);
+     break;
+    default:
+     __pv_ferr(1336, "expected deltype form - (%s read", prt_sdftok());
+     return(FALSE);
+   }
+  }
+ return(TRUE);
+}
+
+/*
+ * return T and emit error if port is a qualified name
+ *
+ * for places where port must be top level port or node name
+ * no error message if emsg nil, used for places where legal
+ * to see if must find downward itree loc. 
+ */
+static int32 port_qual_nam(char *nam, char *emsg)
+{
+ register char *chp, *chp2;
+
+ chp = nam;
+try_more:
+ if ((chp = strchr(chp, '.')) == NULL) return(FALSE);
+ if (chp == nam) goto emit_msg;
+ chp2 = chp - 1;
+ /* not escaped, has separator */ 
+ if (*chp2 != '\\') goto emit_msg;
+ chp++;
+ goto try_more;
+
+emit_msg:
+ if (emsg != NULL)
+  {
+   __pv_ferr(1381,
+    "hierarchical name %s illegal for %s - must be (CELL top level name",
+    nam, emsg);
+  }
+ return(TRUE);
+}
+
+/*
+ * fill 1 value list - returns no. of delays (-1 for error else 1)
+ *
+ * fill work value tables position 0 - no need to pre-initialize
+ * ( read and reads one after ending )
+ * fills pos. 1 of global sdf delp but does not set number of delays
+ */
+static int32 rd_1_val(FILE *f, char *formnam)
+{
+ struct t_vpi_time *vtp = &(__sdf_delp->da[0]);
+
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(1334, "(%s required first rvalue bad - %s read", formnam,
+    prt_sdftok());
+   return(-1);
+  }
+ get_sdftok(f);
+ /* this reads and checks ending ) */ 
+ if (!rd_rtriple(f, vtp)) return(-1);
+ get_sdftok(f); 
+ return(1);
+}
+
+/*
+ * fill 1 value list (2nd version where know first value token read)
+ *
+ * fill work value tables position 0 - no need to pre-initialize
+ * ( read and reads one after ending )
+ */
+static int32 rd2_1_val(FILE *f)
+{
+ struct t_vpi_time *vtp = &(__sdf_delp->da[0]);
+
+ /* this reads and checks ending ) */ 
+ if (!rd_rtriple(f, vtp)) return(FALSE);
+ get_sdftok(f); 
+ return(TRUE);
+}
+
+/*
+ * fill 1 or 2 value list - for path pulse and timing checks
+ * caller determines if found number is right
+ * returns number found (-1 on error)
+ *
+ * fill work value tables position 0 and maybe 1 - no need to pre-initialize
+ * ( read and reads one after ending )
+ */
+static int32 rd_1or2_vals(FILE *f, char *formnam)
+{
+ int32 nvals;
+ struct t_vpi_time *vtp = &(__sdf_delp->da[0]);
+
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(1334, "(%s required first rvalue bad - %s read", formnam,
+    prt_sdftok());
+   return(-1);
+  }
+ get_sdftok(f);
+ /* this reads and checks ending ) */ 
+ if (!rd_rtriple(f, vtp)) return(-1);
+ get_sdftok(f); 
+ if (__toktyp == LPAR)
+  {
+   get_sdftok(f);
+   /* this reads and checking ending ) */ 
+   if (!rd_rtriple(f, &(vtp[1]))) return(-1);
+   get_sdftok(f);
+   nvals = 2;
+  }
+ else nvals = 1;
+ return(nvals);
+}
+
+/*
+ * fill exactly 4 value list (not for delays - for timing constraints) 
+ *
+ * fill work value tables position 0, 1, 2, and 3 - no need to pre-initialize
+ * ( read and reads one after ending )
+ */
+static int32 rd_4_vals(FILE *f, char *formnam)
+{
+ int32 i;
+ struct t_vpi_time *vtp = &(__sdf_delp->da[0]);
+
+ for (i = 0; i < 4; i++)
+  {
+   if (__toktyp != LPAR)
+    {
+     __pv_ferr(1334, "(%s required rvalue (pos %d) bad - %s read", formnam,
+      i, prt_sdftok());
+     return(FALSE);
+    }
+   get_sdftok(f);
+   /* this reads and checks ending ) */ 
+   if (!rd_rtriple(f, &(vtp[i]))) return(FALSE);
+   get_sdftok(f); 
+  }
+ return(TRUE);
+}
+
+/*
+ * read an absolute or increment delay form 
+ *
+ * grammar type is del_def+
+ * name of del_def form read - reads form ending )
+ */
+static int32 rd_deldef(FILE *f, struct itree_t *itp, struct mod_t *ctmdp,
+ char *formnam)
+{
+ int32 first_time;
+
+ /* at least one required */
+ for (first_time = TRUE;;) 
+  {
+   get_sdftok(f);
+   if (!rd_sdf_formtyp(f)) return(FALSE);
+   if (__toktyp == RPAR)
+    {
+     if (first_time)
+      {
+       __pv_ferr(1337, "(%s form empty - at least one del_def form required",
+         formnam);
+       return(FALSE);
+      }
+     break;
+    }
+   if (ctmdp == NULL && __toktyp != SDF_DELAY)
+    {
+     __pv_ferr(1399,
+      "primitive (gate or UDP) CELLTYPE illegal for %s form", prt_sdftok());
+     if (!sdf_skip_form(f)) return(FALSE);
+     continue; 
+    }
+   first_time = FALSE;
+   switch ((byte) __toktyp) {
+    case SDF_IOPATH:
+     if (!rd_iopath(f, itp, ctmdp, NULL, FALSE, formnam))
+      return(FALSE);
+     break;
+    case SDF_COND:
+     /* this calls rd iopath to match and set path delay */
+     if (!rd_del_def_cond(f, itp, ctmdp, formnam)) return(FALSE);
+     break;
+    case SDF_CONDELSE:
+     get_sdftok(f); 
+     if (__toktyp != LPAR)
+      {
+bad_condelse:
+       __pv_ferr(1335, "(%s CONDELSE form bad - %s read", formnam,
+        prt_sdftok());
+       return(FALSE);
+      }
+     get_sdftok(f);
+     if (__toktyp != SDF_IOPATH) goto bad_condelse;
+     if (!rd_iopath(f, itp, ctmdp, NULL, TRUE, formnam))
+      return(FALSE);
+     get_sdftok(f);
+     if (__toktyp != RPAR) goto bad_condelse;
+     break;
+    case SDF_PORT:
+     if (!rdset_port_mipd(f, itp, ctmdp, formnam)) return(FALSE);             
+     break;
+    case SDF_INTERCONNECT:
+     if (!rdset_interconn_dels(f, itp, ctmdp, formnam)) return(FALSE);
+     break;
+    case SDF_DEVICE:
+     if (!rdset_devpath_dels(f, itp, ctmdp, formnam))
+      return(FALSE);
+     break;
+    default:
+     __pv_ferr(1353, "timing_spec form name expected - %s read", 
+      prt_sdftok());
+     return(FALSE);
+   }
+  }
+ return(TRUE);
+}
+
+/*
+ * emit a missing delay list starting ( error 
+ */
+static void dellst_err(char *formnam, char *formnam2)
+{
+ __pv_ferr(1352, "(%s (%s form delay list starting ( expected - %s read",
+  formnam, formnam2, prt_sdftok());
+}
+
+/*
+ * emit a missing form end ) error
+ */
+static void formend_err(char *formnam)
+{
+ __pv_ferr(1354, "(%s form ending ) expected - %s read",
+  formnam, prt_sdftok());
+}
+
+/*
+ * read and process an IOPATH form - Verilog specify path
+ *
+ * this returns F on syntax error but T if syntax good and annotate error
+ * know (IOPATH read and reads ending )
+ * qualified name illegal here
+ */
+static int32 rd_iopath(FILE *f, struct itree_t *itp, struct mod_t *ctmdp,
+ struct expr_t *cndx, int32 is_condelse, char *formnam)
+{
+ register struct pthlst_t *plp;
+ int32 si1, si2, di1, di2, ndels, eval, sav_lcnt, lcnt;
+ struct pthlst_t *plhd;
+ char portsrc[IDLEN], portdst[IDLEN];
+
+ get_sdftok(f);
+ lcnt = __lin_cnt;
+ if (__toktyp == ID || __toktyp == LPAR)
+  {
+   if (!rd_port_spec(f, portsrc, &si1, &si2, &eval, FALSE)) return(FALSE);
+   if (!rd_port(f, portdst, &di1, &di2)) return(FALSE);
+  }
+ else
+  {
+   __pv_ferr(1339, "(IOPATH source portspec starting token expected - %s read",
+    prt_sdftok()); 
+   return(FALSE);
+  }    
+ if (__toktyp != LPAR) { dellst_err(formnam, "IOPATH"); return(FALSE); }
+ get_sdftok(f);
+ /* LOOKATME - grammar allows multiple but have no semantic meaning */
+ if (__toktyp == SDF_RETAIN)
+  {
+   /* not supported by Cver - need warning for every one */ 
+   __pv_fwarn(632,
+    "SDF (RETAIN form (time value retained) skipped - not supported");
+   get_sdftok(f);
+   if (__toktyp != LPAR) { dellst_err(formnam, "RETAIN"); return(FALSE); }
+   get_sdftok(f);
+   /* need first after ( to have been read and reads ) one past end */
+   if ((ndels = rd_sdf_dellst(f, "IOPATH RETAIN")) == -1) return(FALSE);
+   get_sdftok(f);
+   if (__toktyp != LPAR)
+    { dellst_err(formnam, "delval aftere RETAIN"); return(FALSE); }
+   get_sdftok(f);
+  }
+ /* this reads end of io path form */
+ if ((ndels = rd_sdf_dellst(f, "IOPATH")) == -1) return(FALSE);
+
+ /* syntax good but can not set delays */
+ if (port_qual_nam(portsrc, "(IOPATH port")) return(TRUE); 
+ if (port_qual_nam(portdst, "(IOPATH port")) return(TRUE); 
+
+ /* now always return T since syntax good even if annotate fails */ 
+ /* need to be able to emit f errors for first token in form from here on */
+ sav_lcnt = __lin_cnt; 
+ __lin_cnt = lcnt;  
+
+ /* except for next 2 fields all t_vpi_delay fields fixed in SDF */
+ __sdf_delp->no_of_delays = ndels; 
+ if (strcmp(formnam, "INCREMENT") == 0) __sdf_delp->append_flag = TRUE;
+ else __sdf_delp->append_flag = FALSE;
+
+ /* build list of candidate path matches, nil if none */
+ /* edge always included in filter of src-dsts */
+ if ((plhd = bld_match_spcpth(ctmdp, portsrc, si1, si2, eval, portdst,
+  di1, di2, cndx, is_condelse)) == NULL) goto done;
+
+ for (plp = plhd; plp != NULL; plp = plp->pthlnxt)
+  set_1pthdel(plp, itp, ctmdp);
+
+done:
+ __lin_cnt = sav_lcnt;  
+ free_pthlst(plhd);
+ return(TRUE);
+}
+
+/*
+ * convert SDF path string components to path string for output
+ */
+static char *msg_sdfpath_tostr(char *s, char *psrcnam, int32 si1, int32 si2,
+ int32 eval, char *pdstnam, int32 di1, int32 di2, struct expr_t *cndx,
+ int32 is_condelse)
+{
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (si1 == -1) strcpy(s1, "");
+ else if (si1 == si2) sprintf(s1, "[%d]", si1);
+ else sprintf(s1, "[%d:%d]", si1, si2);
+
+ if (di1 == -1) strcpy(s2, "");
+ else if (di1 == di2) sprintf(s2, "[%d]", di1);
+ else sprintf(s2, "[%d:%d]", di1, di2);
+
+ if (eval == NOEDGE) sprintf(s3, "%s%s", psrcnam, s1);
+ else if (eval == E_POSEDGE) sprintf(s3, "(posedge %s%s)", psrcnam, s1);
+ else if (eval == E_NEGEDGE) sprintf(s3, "(negedge %s%s)", psrcnam, s1);
+ else __case_terr(__FILE__, __LINE__);
+
+ if (cndx != NULL)
+  sprintf(s, "(COND ... (IOPATH %s %s%s", s3, pdstnam, s2);
+ else if (is_condelse)
+  sprintf(s, "(CONDELSE ... (IOPATH %s %s%s", s3, pdstnam, s2);
+ else sprintf(s, "(IOPATH %s %s%s", s3, pdstnam, s2);
+ return(s);
+}
+
+/*
+ * set one path delay - given a one element from list of selected paths
+ *
+ * this handles itp nil wildcard instance case too
+ */
+static void set_1pthdel(struct pthlst_t *plp, struct itree_t *itp,
+ struct mod_t *ctmdp)
+{
+ register struct spcpth_t *pthp;
+ struct gate_t ogat, ngat;
+ char s1[RECLEN];
+
+ pthp = plp->lpthp;
+ /* old path delay - maybe none */
+ ogat.g_du = pthp->pth_du;
+ ogat.g_delrep = pthp->pth_delrep;
+
+ /* update the delays */
+ sprintf(s1, "(IOPATH for path at %s", __bld_lineloc(__xs,
+  pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt));
+ if (itp == NULL)
+  { 
+   /* result starts in ogat moves to ngat then finally put back in ogat */
+   if (!upd_sdf_perinst_del(&ogat, __sdf_delp, ctmdp, TRUE, FALSE,
+    4, s1)) return;
+  }
+ else
+  {
+   if (!bld_sdfnewdu(&ngat, &ogat, __sdf_delp, itp, TRUE, FALSE, s1))
+    return;
+   __chg_1inst_del(&ogat, itp, &ngat);
+   __free_del(ngat.g_du, ngat.g_delrep, ctmdp->flatinum);
+  }
+ pthp->pth_du = ogat.g_du;  
+ pthp->pth_delrep = ogat.g_delrep;
+ if (__sdf_verbose) prep_sdfiopath_verbmsg(pthp, &ogat, itp, ctmdp);
+}
+
+/*
+ * wrapper to prepare and call iopath sdf verbose tracing message
+ */
+static void prep_sdfiopath_verbmsg(struct spcpth_t *pthp, struct gate_t *ogp, 
+ struct itree_t *itp, struct mod_t *mdp)
+{
+ register int32 ii;
+ register struct itree_t *itp2;
+ char s1[RECLEN], s2[RECLEN];
+
+ if (itp == NULL)
+  {
+   for (ii = 0; ii < mdp->flatinum; ii++)
+    {
+     itp2 = mdp->moditps[ii];
+     __push_itstk(itp2);
+     sprintf(s1, "%s(%s) from '*'", __msg2_blditree(s2, itp2),
+      mdp->msym->synam);
+     emit_sdfiopath_verbmsg(pthp, ogp, s1);
+     __pop_itstk();
+    }
+  } 
+ else
+  {
+   __push_itstk(itp);
+   sprintf(s1, "%s(%s)", __msg2_blditree(s2, itp), mdp->msym->synam);
+   emit_sdfiopath_verbmsg(pthp, ogp, s1);
+   __pop_itstk();
+  }
+}
+
+/*
+ * emit sdf device verbose tracing message 
+ */
+static void emit_sdfiopath_verbmsg(struct spcpth_t *pthp, struct gate_t *ogp,
+ char *celloc)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ __cv_msg("  SDF **%s(%d): (IOPATH at %s delay set to (%s) in %s\n",
+  __cur_fnam, __lin_cnt,
+  __bld_lineloc(s1, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt),
+ __bld_delay_str(s2, ogp->g_du, ogp->g_delrep), celloc);
+}
+
+/*
+ * update sdf per instance (inst wildcard * form) delay 
+ * when done ogp will have new probably per instance delay for object
+ * this updates old (ogp) by copying to work then updating in ogp
+ *
+ * new gate is just work place to hold delay
+ * first will change to correct instance form, then rest will usually 
+ * just fill in the other instances
+ * bld vpi new du need to have lin and fnam ind set for f errors
+ * this handles any freeing of work delays it creates
+ *
+ * dfix is expected transitions for delay usually 4 (includes x/z) but
+ * sometimes 2 or 3
+ */
+static int32 upd_sdf_perinst_del(struct gate_t *ogp, p_vpi_delay delay_p,  
+ struct mod_t *ctmdp, int32 is_path, int32 is_trireg, int32 dfix, char *sdfmsg)
+{
+ register int32 ii;
+ int32 has_err, none_chged;
+ struct gate_t wgat;
+ struct itree_t *itp;
+
+ /* case 1: need loop for selected instances */
+ if (delay_p->append_flag || __sdf_cntxt_itp != NULL)
+  {
+   has_err = FALSE;
+   for (none_chged = TRUE, ii = 0; ii < ctmdp->flatinum; ii++)
+    {
+     itp = ctmdp->moditps[ii];
+     if (__sdf_cntxt_itp != NULL && !itp_under_cntxt(itp)) continue;
+
+     /* need error for every, if problem */
+     if (!bld_sdfnewdu(&wgat, ogp, __sdf_delp, itp, is_path, is_trireg,
+      sdfmsg)) { has_err = TRUE; continue; }
+
+     if (wgat.g_delrep == DT_4V)
+      {
+       if (dfix == 2)
+        {
+         if (wgat.g_du.d4v[0] < wgat.g_du.d4v[1])
+          {
+           wgat.g_du.d4v[2] = wgat.g_du.d4v[0];
+           wgat.g_du.d4v[3] = wgat.g_du.d4v[0];
+          }
+         else
+          {
+           wgat.g_du.d4v[2] = wgat.g_du.d4v[1];
+           wgat.g_du.d4v[3] = wgat.g_du.d4v[1];
+          }
+        }
+       else if (dfix == 3)
+        {
+         if (wgat.g_du.d4v[0] < wgat.g_du.d4v[1])
+          wgat.g_du.d4v[3] = wgat.g_du.d4v[0];
+         else wgat.g_du.d4v[3] = wgat.g_du.d4v[1];
+        }
+      }
+
+     none_chged = FALSE;
+     __chg_1inst_del(ogp, itp, &wgat);
+     __free_del(wgat.g_du, wgat.g_delrep, ctmdp->flatinum);
+    }
+   if (none_chged)
+    {
+     __pv_fwarn(665,
+      "delays not changed for %s because no instance of type %s in context", 
+      sdfmsg, ctmdp->msym->synam);
+    }
+   if (has_err) return(FALSE);
+   return(TRUE);
+  }
+ /* case 2: change to per type delay (no context and not append) */
+ /* since not append, just need itp for getting module for scaling */
+ itp = ctmdp->moditps[0];
+ if (!bld_sdfnewdu(&wgat, ogp, __sdf_delp, itp, is_path, is_trireg, sdfmsg))
+  return(FALSE); 
+
+ if (wgat.g_delrep == DT_4V)
+  {
+   if (dfix == 2)
+    {
+     if (wgat.g_du.d4v[0] < wgat.g_du.d4v[1])
+      {
+       wgat.g_du.d4v[2] = wgat.g_du.d4v[0];
+       wgat.g_du.d4v[3] = wgat.g_du.d4v[0];
+      }
+     else
+      {
+       wgat.g_du.d4v[2] = wgat.g_du.d4v[1];
+       wgat.g_du.d4v[3] = wgat.g_du.d4v[1];
+      }
+    }
+   else if (dfix == 3)
+    {
+     if (wgat.g_du.d4v[0] < wgat.g_du.d4v[1])
+      wgat.g_du.d4v[3] = wgat.g_du.d4v[0];
+     else wgat.g_du.d4v[3] = wgat.g_du.d4v[1];
+    }
+  }
+ /* freeing old probably per inst. */
+ __free_del(ogp->g_du, ogp->g_delrep, ctmdp->flatinum);
+
+ /* replacing with known per type form */
+ ogp->g_du = wgat.g_du;
+ ogp->g_delrep = wgat.g_delrep;
+ return(TRUE);
+}
+
+/*
+ * return T if instance itp under context itp (work up)
+ */
+static int32 itp_under_cntxt(register struct itree_t *itp)
+{
+ for (;;)
+  {
+   if (itp == __sdf_cntxt_itp) return(TRUE); 
+   if (itp == NULL) break;
+   itp = itp->up_it;
+  }
+ return(FALSE);
+}
+
+/*
+ * read a port spec (path input or timing check terminal)
+ * this expects first token read and reads one past end
+ *
+ * even though in Verilog only posedge and negedge for path sources - for
+ * SDF can any edge but will just not match 
+ */
+static int32 rd_port_spec(FILE *f, char *pnam, int32 *i1, int32 *i2, int32 *eval,
+ int32 is_tchk)
+{
+ int32 nd_rpar, ettyp;
+
+ /* skip the edge form - form not currently readable because of [val][val] */
+ *eval = NOEDGE;
+ nd_rpar = FALSE;
+ if (__toktyp == LPAR)
+  {
+   if ((ettyp = rd_edge_ident(f)) == -1) return(FALSE);
+   *eval = ettyp; 
+   /* for non timing checks (iopaths), only pos and neg edges allowed */
+   /* error will inhibit simulation but does not effect sdf reading */
+   if (!is_tchk && ettyp != E_POSEDGE && ettyp != E_NEGEDGE)
+    { 
+     __pv_ferr(1340,
+      "(IOPATH portspec port_edge %s impossible in Verilog - only posedge or negedge legal",
+      __to_edgenam(__xs, (word32) ettyp));
+    } 
+   nd_rpar = TRUE;
+   get_sdftok(f);
+  }
+ if (!rd_port(f, pnam, i1, i2)) return(FALSE);
+ if (nd_rpar)
+  {
+   /* know one past port spec read */
+   if (__toktyp != RPAR)
+    {
+     __pv_ferr(1346, "portspec port_edge ending ) expected - %s read",
+      prt_sdftok()); 
+     return(FALSE);
+    }
+   get_sdftok(f);
+  }
+ return(TRUE);
+}
+
+/*
+ * read a port specification 
+ *
+ * name (id) read and reads one past end
+ * portnam is verilog name (escaped and path separator handled)
+ * can be qualified name here - caller may allow or not
+ * vector ports can appear with or without range - SDF side determines
+ * for matching
+ */
+static int32 rd_port(FILE *f, char *portnam, int32 *i1, int32 *i2)
+{
+ *i1 = *i2 = -1;
+ if (__toktyp != ID)
+  {
+   __pv_ferr(1343, "SDF port reference expected - %s read", prt_sdftok());
+   return(FALSE);
+  }
+ if (__id_qualpath)
+  {
+   if (!chkcnv_sdfpath(portnam, i1, i2, __token, TRUE))
+    {
+     __pv_ferr(1366,
+      "hierarchical port name reference %s illegal Verilog name",
+      __token);
+     return(FALSE);
+    }
+  }
+ else if (!chkcnv_sdfid(portnam, i1, i2, __token, TRUE))
+  {
+   __pv_ferr(1366, "port name %s illegal SDF or Verilog identifier",
+      __token);
+   return(FALSE);
+  }
+ /* need to read one past */
+ get_sdftok(f);
+ return(TRUE);
+}
+
+/*
+ * build a list of matching specify paths
+ *
+ * rule is that missing SDF is treated as wildcard (all match) but if
+ * present in SDF must match exactly (including path has edge)
+ * idea: only as much SDF constructs as needed must be code in SDF file 
+ */
+static struct pthlst_t *bld_match_spcpth(struct mod_t *ctmdp, char *psrcnam,
+ int32 si1, int32 si2, int32 eval, char *pdstnam, int32 di1, int32 di2, 
+ struct expr_t *cndx, int32 is_condelse)
+{
+ register struct spcpth_t *pthp;
+ int32 rv, rv2;
+ struct pathel_t *pep1, *pep2;
+ struct pthlst_t *plp, *plhd, *plend;
+
+ if (ctmdp->mspfy == NULL)
+  {
+   not_a_port(psrcnam, IO_IN, ctmdp, "(IOPATH [source]");
+   not_a_port(pdstnam, IO_OUT, ctmdp, "(IOPATH [dest.]");
+   __pv_ferr(1387, "unable to match (IOPATH in type %s - no specify section", 
+    ctmdp->msym->synam);
+   return(NULL);
+  }
+ plhd = plend = NULL;
+ /* build list of matching source-dest but ignore cond or condelse for now */ 
+ for (pthp = ctmdp->mspfy->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+  {
+   /* step 1: match src and dest name and range - rule is to use first only */
+   pep1 = &(pthp->peins[0]);
+   pep2 = &(pthp->peouts[0]); 
+   /* eliminate if net names do not match */
+   if (strcmp(pep1->penp->nsym->synam, psrcnam) != 0 ||
+    strcmp(pep2->penp->nsym->synam, pdstnam) != 0) continue;
+
+   /* this is just matching to stuff delay into right path */
+   /* therefore if Verilog source is vector without range SDF no range too */
+   /* and vice versa */
+   if (pep1->pthi1 != si1 || pep1->pthi2 != si2) continue;
+   if (pep2->pthi1 != di1 || pep2->pthi2 != di2) continue;
+
+   /* step 2: match edge, but no SDF edge means match all */ 
+   /* i.e. if SDF has edge but path does not, no match */
+   if (eval != NOEDGE)
+    { if (pthp->pthedge != eval) continue; }
+   /* step 3: if SDF condition or SDF condelse (Verilog ifnone), */
+   /* must match - know not both condx and condelse */
+   /* if missing from SDF, then always matches even if path has cond */
+   if (cndx != NULL)
+    {
+     if (pthp->pthcondx == NULL) continue;
+     /* if expr's do not match, keep looking */
+     if (!__cmp_xpr(pthp->pthcondx, cndx)) continue; 
+    }
+   else if (is_condelse && !pthp->pth_ifnone) continue;
+
+   /* have match */
+   /* src-dst match emit warning even though cond or edge may eliminate */
+   if (pthp->last_pein > 0 || pthp->last_peout > 0)
+    {
+     __finform(475,
+      "(IOPATH matches first component only of Verilog component path list at %s in %s",
+      __bld_lineloc(__xs, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt),
+      ctmdp->msym->synam);
+    }
+   plp = (struct pthlst_t *) __my_malloc(sizeof(struct pthlst_t));
+   plp->lpthp = pthp;
+   plp->pthlnxt = NULL; 
+   if (plend == NULL) plhd = plend = plp;
+   else { plend->pthlnxt = plp; plend = plp; }
+  }
+ if (plhd == NULL)
+  {
+   rv = not_a_port(psrcnam, IO_IN, ctmdp, "(IOPATH [source]");
+   rv2 = not_a_port(pdstnam, IO_OUT, ctmdp, "(IOPATH [dest.]");
+   if (rv || rv2) return(NULL);
+
+   __pv_ferr(1369,
+    "no module %s specify path (first component used) matches %s",
+    ctmdp->msym->synam, msg_sdfpath_tostr(__xs, psrcnam, si1, si2, eval,
+    pdstnam, di1, di2, cndx, is_condelse));
+  }
+ return(plhd);
+}
+
+/* SJM 06/15/00 - removed old (COND as string compare - now compare exprs */
+
+/*
+ * free a path list
+ */
+static void free_pthlst(struct pthlst_t *pthlhd)
+{
+ register struct pthlst_t *pthlp, *pthlp2;
+
+ for (pthlp = pthlhd; pthlp != NULL;)
+  {
+   pthlp2 = pthlp->pthlnxt;
+   __my_free((char *) pthlp, sizeof(struct pthlst_t));
+   pthlp = pthlp2;
+  }
+}
+ 
+/*
+ * read a del (COND form
+ *
+ * (COND read and reads ending )
+ * LOOKATME - building token list as ascii string for matching
+ */
+static int32 rd_del_def_cond(FILE *f, struct itree_t *itp, struct mod_t *ctmdp,
+ char *formnam)
+{
+ int32 sav_declobj;
+ struct expr_t *cond_expr;
+ char labnam[IDLEN];
+
+ get_sdftok(f);   
+ /* LOOKATME - ignoring label - think Verilog can not use labels? */
+ if (__toktyp == LITSTR) { strcpy(labnam, __token); get_sdftok(f); }
+ 
+ /* SJM - 06/15/00 - build expr. using src reading mechanism */
+ if (__top_sti != 0) __misc_terr(__FILE__, __LINE__);
+ /* need to save since will probably be interactive mode */
+ sav_declobj = __cur_declobj;
+ __cur_declobj = SPECIFY;
+ __cur_spfy = ctmdp->mspfy;
+ __venviron[0] = ctmdp->msymtab; 
+ __venviron[1] = __cur_spfy->spfsyms;
+ __top_sti = 1;
+
+ __saverr_cnt = __pv_err_cnt;
+
+ /* SJM 05/14/01 - only allow scalar constants in io path conds */ 
+ /* scalars in timing check conditions in fixed place so no expr collect */
+ __rding_cond_expr = TRUE;
+ if (!col_cond_port_expr(f)) { __rding_cond_expr = FALSE; return(FALSE); }
+ __rding_cond_expr = FALSE;
+
+ __bld_xtree(0);
+ cond_expr = __root_ndp;
+ __top_sti = 0;
+ __cur_declobj = sav_declobj;
+ /* if already error, do not check expr. */ 
+ if (__pv_err_cnt != __saverr_cnt)
+  {
+   __pv_ferr(1390, "invalid SDF (COND expression");
+   return(FALSE);
+  }
+
+ if (!rd_iopath(f, itp, ctmdp, cond_expr, FALSE, formnam)) return(FALSE);
+ get_sdftok(f);
+ if (__toktyp != RPAR)
+  {
+   __pv_ferr(1335, "(%s (COND form ending ) expected - %s read",
+    formnam, prt_sdftok());
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * collect and build expression to (IOPATH 
+ *
+ * expects 1st expr. token to have been read (after '(') 
+ * and reads ending ( IOPATH sequence  
+ *
+ * LOOKATME - uses pass 1 expr mechanism - see if works
+ */
+static int32 col_cond_port_expr(FILE *f)
+{
+ int32 last_sdftok;
+
+ /* this is illegal empty case */
+ __last_xtk = -1;
+ if (__toktyp == LPAR)
+  {
+   get_sdftok(f);
+   if (__toktyp != SDF_IOPATH)
+    {
+     last_sdftok = __toktyp;
+     __toktyp = LPAR;
+     /* BEWARE - this works because for operator token name unchanged */
+     if (!sdf_bld_expnode()) goto bad_end;
+     __toktyp = last_sdftok;
+     goto col_expr;
+    } 
+
+   __pv_ferr(1390, "empty SDF IOPATH (COND expression illegal");
+bad_end:
+   /* notice cannot free here since in __exprtab (links just overwritten) */
+   /* also make look like empty expr. */
+   __set_xtab_errval();
+   return(FALSE);
+  }
+
+ /* notice SDF expressions can't be parenthesized */
+col_expr:
+ for (;;)
+  {
+   if (!sdf_bld_expnode()) goto bad_end;
+   last_sdftok = __toktyp; 
+   get_sdftok(f);
+   if (__toktyp == LPAR && (last_sdftok != BOOLAND && last_sdftok != BOOLOR))
+    {
+     get_sdftok(f);
+     if (__toktyp == SDF_IOPATH) break;
+     __pv_ferr(1390, "expected (IOPATH missing - %s read", prt_sdftok());
+     goto bad_end;
+    }
+   else if (__toktyp == TEOF || __toktyp == SEMI)
+    {
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1390, "illegal token %s in SDF (COND expression",
+       prt_sdftok());
+     goto bad_end;
+    }
+   last_sdftok = SDF_UNKN;
+  }
+ return(TRUE);
+}
+
+/*
+ * build sdf expression tree node from current token
+ * always places it in next free place in __exprtab
+ * reuses storage so bld_xtree must allocate nodes
+ *
+ * puts ID name in expr_idtab that is changed to symbol in
+ * parse term routine (either ID or xmr component)
+ */
+static int32 sdf_bld_expnode(void)
+{
+ struct opinfo_t *oip;
+ struct expr_t *ndp;
+ struct xstk_t *xsp;
+
+ ndp = __alloc_exprnd();
+ switch ((byte) __toktyp) {
+  case ID:
+   /* if can be inst. ref, assume global fix later */
+   /* notice anthing in this case but id and glb wrong - caught later */
+   ndp->optyp = ID;
+   __alloc_expridnd(__token);
+   break;
+  case NUMBER:
+   /* notice scanner only returns number */  
+   ndp->optyp = NUMBER;
+   ndp->szu.xclen = WBITS;
+   ndp->unsiznum = FALSE;
+   ndp->has_sign = FALSE;
+   ndp->ibase = BDEC;
+   ndp->sizdflt = TRUE;
+   ndp->ru.xvi = __alloc_shareable_cval(__sdf_tokval, 0, WBITS);
+   break;
+  case REALNUM:
+   /* num storage pted to by a part - usually (except xstk) no b part */ 
+   ndp->optyp = REALNUM;
+   ndp->szu.xclen = REALBITS;
+   ndp->ibase = BDBLE;
+   ndp->is_real = TRUE;
+   ndp->has_sign = TRUE;
+   /* LOOKATME - SIZE assuming size of real is 8 bytes here */
+// ==========### SJM 02/17/05 - FIXME - WHY NOT PUT IN REAL CON TAB 
+   push_xstk_(xsp, WBITS);
+   memcpy(xsp->ap, &(__itok_realval), sizeof(double));
+   ndp->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, 1);
+   __pop_xstk();
+/* ---
+   wp = &(__contab[ndp->ru.xvi]);
+   memcpy(wp, &__itok_realval, sizeof(double));
+--- */
+   break;
+  case TEOF: case LITSTR:
+   /* since no error recovery in interactive - this is finish path */
+   /* caller sets to error expression */ 
+   ndp->optyp = BADOBJ;
+   return(FALSE);
+  default:
+   if (__toktyp > LASTOP)
+    {
+     /* keywords can not be in or end expressions */
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1104, "illegal token %s in SDF expression", prt_sdftok());
+     return(FALSE);
+    }
+   /* build an operator node */
+   oip = &(__opinfo[__toktyp]);
+   if (oip->opclass == NOTANOP)
+    {
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1105, "illegal punctuation %s in SDF expression",
+       prt_sdftok());
+     return(FALSE);
+    }
+   /* build an operator node */
+   ndp->optyp = __toktyp;
+  }
+ return(TRUE);
+}
+
+/*
+ * ROUTINES TO READ TIMING CHECKS
+ */
+
+/*
+ * read a timing spec form
+ * timing checks terminals can not be qualified names
+ *
+ * qualified (xmr) terminal name illegal here
+ */
+static int32 rdset_tchk_defs(FILE *f, struct itree_t *itp, struct mod_t *ctmdp)
+{
+ register struct tclst_t *tclp;
+ int32 first_time, sdf_tctyp, tchktyp, ndels, lcnt, sav_lcnt, match_tctyp;
+ struct tchk_t *tcp; 
+ struct tclst_t *tclhd;
+ struct gate_t ogat, ngat;
+ char sdf_tcnam[RECLEN], s1[RECLEN]; 
+
+ for (first_time = TRUE;;) 
+  {
+   /* this returns T if ) */
+   get_sdftok(f);
+   lcnt = __lin_cnt; 
+   if (!rd_sdf_formtyp(f)) return(FALSE);
+   if (__toktyp == RPAR)
+    {
+     if (first_time)
+      {
+       __pv_ferr(1341,
+        "(TIMINGCHECK form empty - at least one tc_def required");
+       return(FALSE);
+      }
+     break;
+    }
+   first_time = FALSE;
+   sdf_tctyp = __toktyp;
+   /* must be tchk form - any other form error */
+   if ((tchktyp = from_sdf_tctyp(sdf_tctyp)) == -1)
+    {
+     __pv_ferr(1342, "tc_def timing check form expected - (%s read",
+      prt_sdftok());
+     return(FALSE);
+    }
+   /* this is SDF side timing check name */
+   strcpy(sdf_tcnam, prt_sdftok());
+   ndels = 1;
+   switch ((byte) tchktyp) {
+    case TCHK_SETUP: case TCHK_HOLD: case TCHK_RECOVERY:
+    case TCHK_REMOVAL: case TCHK_SKEW: case TCHK_FULLSKEW:
+    case TCHK_TIMESKEW:
+     /* 10/30/00 SJM - for setup and hold if no match tries to match */
+     /* corresponding ports of setuphold */
+     /* match tctyp can be setuphold if SDF hold or setup matches */
+     /* Verilog setuphold */
+     if (!rdset_2term_1v_tchk(&tclhd, &match_tctyp, f, ctmdp, sdf_tcnam,
+      tchktyp, lcnt, &sav_lcnt)) return(FALSE);
+
+     if (tclhd == NULL) continue;
+
+     /* 10/27/00 SJM - setup or hold matches setuphold, annotate the half */
+     /* this is needed to match XL behavior */
+     if (match_tctyp == TCHK_SETUPHOLD)
+      {
+       /* 10/28/00 SJM - this is special case where SDF hold or setup */
+       /* terminals do not match same setup/hold type but do match a */
+       /* setuphold in Verilog source*/
+       /* this uses loop to process every timing check as loop below */
+       set_half_setuphold_tchk_defs(tclhd, tchktyp, itp, ctmdp);
+       goto nxt_tchk;
+      }
+     else if (match_tctyp == TCHK_RECREM)
+      {
+       /* SJM 01/16/04 - same questionable algorithm for recrem */
+       set_half_recrem_tchk_defs(tclhd, tchktyp, itp, ctmdp);
+       goto nxt_tchk;
+      }
+     break;
+    case TCHK_WIDTH: case TCHK_PERIOD:
+     if (!rdset_1term_1v_tchk(&tclhd, f, ctmdp, sdf_tcnam, tchktyp, lcnt,
+      &sav_lcnt)) return(FALSE);
+     if (tclhd == NULL) continue;
+     break;
+    case TCHK_SETUPHOLD: case TCHK_RECREM:
+     /* SJM 01/16/04 - recrem also same two terminals */
+     if (!rdset_2term_2v_tchk(&tclhd, f, ctmdp, sdf_tcnam, tchktyp, lcnt,
+      &sav_lcnt)) return(FALSE);
+     if (tclhd == NULL) continue;
+
+     /* normal annotate to both delays of setup hold at once */ 
+     ndels = 2;
+     break;
+    case TCHK_NOCHANGE:
+     /* 10/27/00 - SJM here ignore matched tc typ only used for setup hold */
+     if (!rdset_2term_2v_tchk(&tclhd, f, ctmdp, sdf_tcnam, tchktyp, lcnt,
+      &sav_lcnt)) return(FALSE);
+     if (tclhd == NULL) continue;
+     ndels = 2;
+     break;
+    default: __case_terr(__FILE__, __LINE__); return(FALSE);
+   }
+  /* know either one or two delays */
+  for (tclp = tclhd; tclp != NULL; tclp = tclp->tclnxt)
+   {
+    tcp = tclp->tcp;
+
+    /* know always at least one delay */
+    ogat.g_du = tcp->tclim_du;
+    ogat.g_delrep = tcp->tc_delrep;
+    if (ogat.g_delrep == DT_NONE) __misc_terr(__FILE__, __LINE__);
+
+    /* update the delays */
+    sprintf(s1, "(TIMINGCHECK (%s at %s", sdf_tcnam,
+     __bld_lineloc(__xs, tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt));
+    if (itp == NULL)
+     {
+      /* result starts in ogat and also ends up there */
+      if (!upd_sdf_perinst_del(&ogat, __sdf_delp, ctmdp, FALSE, 4, FALSE, s1))
+       goto none_chged;
+     }
+    else
+     {
+      if (!bld_sdfnewdu(&ngat, &ogat, __sdf_delp, itp, FALSE, FALSE, s1))
+       goto none_chged;
+      __chg_1inst_del(&ogat, itp, &ngat);
+      __free_del(ngat.g_du, ngat.g_delrep, ctmdp->flatinum);
+     }
+    /* if found no delays to change, must not assign old gate */ 
+    tcp->tclim_du = ogat.g_du;  
+    tcp->tc_delrep = ogat.g_delrep;
+    if (__sdf_verbose)
+     prep_sdftchk_verbmsg(tcp, sdf_tcnam, &ogat, itp, ctmdp, "");
+none_chged:
+    if (ndels == 1) continue;
+
+    sprintf(s1, "(TIMINGCHECK (%s at %s second limit", sdf_tcnam,
+     __bld_lineloc(__xs, tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt));
+    ogat.g_du = tcp->tclim2_du;
+    ogat.g_delrep = tcp->tc_delrep2;
+    if (ogat.g_delrep == DT_NONE) __misc_terr(__FILE__, __LINE__);
+    if (itp == NULL)
+     {
+      if (!upd_sdf_perinst_del(&ogat, __sdf_delp2, ctmdp, FALSE, 4, FALSE,
+       s1)) continue;
+     }
+    else
+     {
+      if (!bld_sdfnewdu(&ngat, &ogat, __sdf_delp2, itp, FALSE, FALSE, s1))
+       continue;
+      __chg_1inst_del(&ogat, itp, &ngat);
+      __free_del(ngat.g_du, ngat.g_delrep, ctmdp->flatinum);
+     }
+    tcp->tclim2_du = ogat.g_du;  
+    tcp->tc_delrep2 = ogat.g_delrep;
+    if (__sdf_verbose)
+     prep_sdftchk_verbmsg(tcp, sdf_tcnam, &ogat, itp, ctmdp, "2nd ");
+   }
+nxt_tchk:
+   /* must put back each time */
+   __lin_cnt = sav_lcnt;  
+   free_tclst(tclhd);
+  }
+ return(TRUE);
+}
+
+/*
+ * set setup or hold half (only) of setuphold timing check 
+ *
+ * know all reading done and only called for special case where  
+ * have found setup or hold form in SDF that matches $setuphold
+ * in vrilog so need to update only one of the 2 timing delays 
+ *
+ * 10/27/00 SJM - this is special case routine for matching XL that allows
+ * SDF that does not have setuphold's but has separate setup and hold forms
+ */
+static void set_half_setuphold_tchk_defs(struct tclst_t *tclhd,
+ int32 sdf_tctyp, struct itree_t *itp, struct mod_t *ctmdp)
+{
+ register struct tclst_t *tclp;
+ struct tchk_t *tcp;
+ struct gate_t ogat, ngat;
+ char sdf_tcnam[RECLEN], s1[RECLEN], s2[RECLEN];
+
+ if (sdf_tctyp == TCHK_SETUP)
+  strcpy(sdf_tcnam, "SETUP matched to $setuphold");
+ else strcpy(sdf_tcnam, "HOLD matched to $setuphold");
+
+ /* LOOKATME - this is normal SDF algorithm where one SDF can match all ver */
+ for (tclp = tclhd; tclp != NULL; tclp = tclp->tclnxt)
+  {
+   tcp = tclp->tcp;
+ 
+   /* know always at least one delay */
+   /* match type determines which limit set */  
+   /* LOOKATME - algorithm implies it is legal to use SDF to set one half */
+   /* of setuphold but not other - questionable algorithm but matching XL */
+   if (sdf_tctyp == TCHK_SETUP)
+    {
+     ogat.g_du = tcp->tclim_du;
+     ogat.g_delrep = tcp->tc_delrep;
+     strcpy(s2, "setup");
+    }
+   else
+    {
+     ogat.g_du = tcp->tclim2_du;
+     ogat.g_delrep = tcp->tc_delrep2;
+     strcpy(s2, "hold");
+    }
+   /* DBG remove -- */
+   if (ogat.g_delrep == DT_NONE) __misc_terr(__FILE__, __LINE__);
+   /* --- */ 
+
+   /* update the delays */
+   sprintf(s1, "%s half of (TIMINGCHECK (%s at %s", sdf_tcnam, s2,
+    __bld_lineloc(__xs, tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt));
+
+   /* this builds delay into work "gate" place holder */
+   if (itp == NULL)
+    {
+     /* result starts in ogat and also ends up there */
+     if (!upd_sdf_perinst_del(&ogat, __sdf_delp, ctmdp, FALSE, 4, FALSE, s1))
+      continue;
+    }
+   else
+    {
+     if (!bld_sdfnewdu(&ngat, &ogat, __sdf_delp, itp, FALSE, FALSE, s1))
+      continue;
+     __chg_1inst_del(&ogat, itp, &ngat);
+     __free_del(ngat.g_du, ngat.g_delrep, ctmdp->flatinum);
+    }
+   /* for Verilog $setuphold, first limit is setup and 2nd is hold */
+   if (sdf_tctyp == TCHK_SETUP)
+    {
+     tcp->tclim_du = ogat.g_du;  
+     tcp->tc_delrep = ogat.g_delrep;
+    }
+   else if (sdf_tctyp == TCHK_HOLD)
+    {
+     tcp->tclim2_du = ogat.g_du;  
+     tcp->tc_delrep2 = ogat.g_delrep;
+    }
+   else __case_terr(__FILE__, __LINE__);
+   if (__sdf_verbose)
+    prep_sdftchk_verbmsg(tcp, sdf_tcnam, &ogat, itp, ctmdp, "");
+  }
+}
+
+/*
+ * set recovery or removal half (only) of recrem timing check 
+ *
+ * know all reading done and only called for special case where  
+ * have found recovery or removal form in SDF that matches $recrem
+ * in verilog so need to update only one of the 2 timing delays 
+ *
+ * 10/27/00 SJM - this is special case routine for matching XL that allows
+ * SDF that does not have recrem's but has separate recovery and removal
+ */
+static void set_half_recrem_tchk_defs(struct tclst_t *tclhd,
+ int32 sdf_tctyp, struct itree_t *itp, struct mod_t *ctmdp)
+{
+ register struct tclst_t *tclp;
+ struct tchk_t *tcp;
+ struct gate_t ogat, ngat;
+ char sdf_tcnam[RECLEN], s1[RECLEN], s2[RECLEN];
+
+ if (sdf_tctyp == TCHK_RECOVERY)
+  strcpy(sdf_tcnam, "RECOVERY matched to $recrem");
+ else strcpy(sdf_tcnam, "REMOVAL matched to $recrem");
+
+ /* LOOKATME - this is normal SDF algorithm where one SDF can match all ver */
+ for (tclp = tclhd; tclp != NULL; tclp = tclp->tclnxt)
+  {
+   tcp = tclp->tcp;
+ 
+   /* know always at least one delay */
+   /* match type determines which limit set */  
+   /* LOOKATME - algorithm implies it is legal to use SDF to set one half */
+   /* of recrem but not other - questionable algorithm but matching XL */
+   if (sdf_tctyp == TCHK_RECOVERY)
+    {
+     ogat.g_du = tcp->tclim_du;
+     ogat.g_delrep = tcp->tc_delrep;
+     strcpy(s2, "recovery");
+    }
+   else
+    {
+     ogat.g_du = tcp->tclim2_du;
+     ogat.g_delrep = tcp->tc_delrep2;
+     strcpy(s2, "removal");
+    }
+   /* DBG remove -- */
+   if (ogat.g_delrep == DT_NONE) __misc_terr(__FILE__, __LINE__);
+   /* --- */ 
+
+   /* update the delays */
+   sprintf(s1, "%s half of (TIMINGCHECK (%s at %s", sdf_tcnam, s2,
+    __bld_lineloc(__xs, tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt));
+
+   /* this builds delay into work "gate" place holder */
+   if (itp == NULL)
+    {
+     /* result starts in ogat and also ends up there */
+     if (!upd_sdf_perinst_del(&ogat, __sdf_delp, ctmdp, FALSE, 4, FALSE, s1))
+      continue;
+    }
+   else
+    {
+     if (!bld_sdfnewdu(&ngat, &ogat, __sdf_delp, itp, FALSE, FALSE, s1))
+      continue;
+     __chg_1inst_del(&ogat, itp, &ngat);
+     __free_del(ngat.g_du, ngat.g_delrep, ctmdp->flatinum);
+    }
+   /* for Verilog $recrem, first limit is recovery and 2nd is removal */
+   if (sdf_tctyp == TCHK_RECOVERY)
+    {
+     tcp->tclim_du = ogat.g_du;  
+     tcp->tc_delrep = ogat.g_delrep;
+    }
+   else if (sdf_tctyp == TCHK_REMOVAL)
+    {
+     tcp->tclim2_du = ogat.g_du;  
+     tcp->tc_delrep2 = ogat.g_delrep;
+    }
+   else __case_terr(__FILE__, __LINE__);
+   if (__sdf_verbose)
+    prep_sdftchk_verbmsg(tcp, sdf_tcnam, &ogat, itp, ctmdp, "");
+  }
+}
+
+/*
+ * read common 2 terminals and 1 delay value timing check
+ *
+ * for (SETUP, (HOLD, (RECOVERY, (REMOVAL, (SKEW 
+ * delay put into sdf delp global work vpi delay record
+ *
+ * notice SDF HOLD terminal order reverse of Verilog so reverse terminals
+ * here for matching
+ *
+ */
+static int32 rdset_2term_1v_tchk(struct tclst_t **tclhd, int32 *match_tctyp,
+ FILE *f, struct mod_t *ctmdp, char *sdf_tcnam, int32 tchktyp, int32 lcnt,
+ int32 *sav_lcnt)
+{
+ struct tcterm_t reftct, dattct;
+ 
+ *tclhd = NULL;
+ /* assume SDF matches same type in Verilog */
+ *match_tctyp = tchktyp;
+ get_sdftok(f);
+ /* this skips COND form, but just get port - source has cond or edge */
+ if (!rd_port_tchk(f, &reftct)) return(FALSE);
+ if (!rd_port_tchk(f, &dattct)) return(FALSE);
+
+ if (__toktyp != LPAR)
+  { dellst_err("TIMINGCHECK", sdf_tcnam); return(FALSE); }
+
+ /* only one delay allowed for these common tchk types */
+ if (rd_1_val(f, sdf_tcnam) == -1) return(FALSE);
+ if (__toktyp != RPAR) { formend_err(sdf_tcnam); return(FALSE); }
+ __sdf_delp->no_of_delays = 1; 
+
+ /* need to be able to emit f errors for first token in form from here on */
+ *sav_lcnt = __lin_cnt; 
+ __lin_cnt = lcnt;  
+
+ if (port_qual_nam(reftct.tnam, "(TIMINGCHECK first terminal")) return(TRUE);
+ if (port_qual_nam(dattct.tnam, "(TIMINGCHECK second terminal")) return(TRUE);
+
+ /* now always return T since syntax good even if annotate fails */ 
+ if (reftct.cndnam != NULL)
+  {
+   if (port_qual_nam(reftct.cndnam, "(TIMINGCHECK reference condition signal"))
+    return(TRUE);
+  }
+ if (dattct.cndnam != NULL)
+  {
+   if (port_qual_nam(dattct.cndnam, "(TIMINGCHECK data condition signal"))
+    return(TRUE);
+  }
+ /* build list of candidate path matches, nil if none */
+ /* edge always included in filter of src-dsts */
+ /* SDF hold uses same order as setup but in Verilog reversed, so reverse */
+ /* only hold for matching */ 
+ if (tchktyp != TCHK_HOLD)
+  *tclhd = bld_match_tchk(ctmdp, &reftct, &dattct, tchktyp, sdf_tcnam);
+ else *tclhd = bld_match_tchk(ctmdp, &dattct, &reftct, tchktyp, sdf_tcnam);
+
+ /* 10/27/00 SJM - if did not match same , see if can match ver setuphold */ 
+ if (*tclhd == NULL && (tchktyp == TCHK_HOLD || tchktyp == TCHK_SETUP))
+  {
+   /* try to see if can match setuphold */
+   /* Verilog setup reversed port order compared to SDF */
+
+   /* AIV 11/11/03 - both Verilog and SDF setuphold have data first */
+   /* previous separate hold condition was same */
+   *tclhd = bld_match_tchk(ctmdp, &dattct, &reftct, TCHK_SETUPHOLD,
+    sdf_tcnam);
+
+   if (*tclhd != NULL) *match_tctyp = TCHK_SETUPHOLD; 
+   else
+    {
+     /* SJM 06/04/01 - if no timinchg checks do not emit error */ 
+     if (__no_tchks) goto fail_do_free;
+
+     __pv_ferr(1391,
+      "no module %s timing check matches SDF (TIMINGCHECK (%s) - also tried matching $setuphold in Verilog source", 
+        ctmdp->msym->synam, sdf_tcnam);
+     goto fail_do_free;  
+    }
+   /* fall thru since know match one or other half of setuphold */
+   /* if SDF syntax ok, always return T even if no match */
+  }
+ /* 01/16/04 SJM - if did not match same , see if can match ver recrem */ 
+ if (*tclhd == NULL && (tchktyp == TCHK_RECOVERY || tchktyp == TCHK_REMOVAL))
+  {
+   /* try to see if can match recrem */
+   /* Verilog recovery reversed port order compared to SDF */
+   /* AIV 11/11/03 - both Verilog and SDF recrem have data first */
+   /* previous separate removal condition was same */
+   *tclhd = bld_match_tchk(ctmdp, &dattct, &reftct, TCHK_RECREM,
+    sdf_tcnam);
+   if (*tclhd != NULL) *match_tctyp = TCHK_RECREM; 
+   else
+    {
+     /* SJM 06/04/01 - if no timinchg checks do not emit error */ 
+     if (__no_tchks) goto fail_do_free;
+
+     __pv_ferr(1391,
+      "no module %s timing check matches SDF (TIMINGCHECK (%s) - also tried matching $recrem in Verilog source", 
+        ctmdp->msym->synam, sdf_tcnam);
+     goto fail_do_free;  
+    }
+   /* fall thru since know match one or other half of setuphold */
+   /* if SDF syntax ok, always return T even if no match */
+  }
+
+ /* free only the strings allocated inside a tchk term rec */ 
+fail_do_free:
+ free_tct_insides(&reftct);
+ free_tct_insides(&dattct);
+ return(TRUE);
+}
+
+/*
+ * read 1 terminal and 1 delay value timing check
+ *
+ * for (WIDTH, and (PERIOD
+ * delay put into sdf delp global work vpi delay record
+ */
+static int32 rdset_1term_1v_tchk(struct tclst_t **tclhd, FILE *f,
+ struct mod_t *ctmdp, char *sdf_tcnam, int32 tchktyp, int32 lcnt, int32 *sav_lcnt)
+{
+ struct tcterm_t reftct;
+ 
+ *tclhd = NULL;
+ get_sdftok(f);
+ /* this skips COND form, but just get port - source has cond or edge */
+ if (!rd_port_tchk(f, &reftct)) return(FALSE);
+
+ if (__toktyp != LPAR)
+  { dellst_err("TIMINGCHECK", sdf_tcnam); return(FALSE); }
+
+ /* only one delay allowed for these common tchk types */
+ if (rd_1_val(f, sdf_tcnam) == -1) return(FALSE);
+ if (__toktyp != RPAR) { formend_err(sdf_tcnam); return(FALSE); }
+ __sdf_delp->no_of_delays = 1; 
+
+ /* need to be able to emit f errors for first token in form from here on */
+ *sav_lcnt = __lin_cnt; 
+ __lin_cnt = lcnt;  
+
+ if (port_qual_nam(reftct.tnam, "(TIMINGCHECK first terminal")) return(TRUE);
+
+ /* now always return T since syntax good even if annotate fails */ 
+ if (reftct.cndnam != NULL)
+  {
+   if (port_qual_nam(reftct.cndnam, "(TIMINGCHECK reference condition signal"))
+    return(TRUE);
+  }
+ /* build list of candidate path matches, nil if none */
+ /* edge always included in filter of src-dsts */
+ *tclhd = bld_match_tchk(ctmdp, &reftct, NULL, tchktyp, sdf_tcnam);
+
+ /* free only the strings allocated inside a tchk term rec */ 
+ free_tct_insides(&reftct);
+ return(TRUE);
+}
+
+/*
+ * read 2 terminals, 2 delay values SDF tchk form with optional 2nd and ccond 
+ *
+ * for (SETUPHOLD, (RECREM, and (NOCHANGE (no scond and cond for this)
+ */
+static int32 rdset_2term_2v_tchk(struct tclst_t **tclhd, FILE *f,
+ struct mod_t *ctmdp, char *sdf_tcnam, int32 tchktyp, int32 lcnt, int32 *sav_lcnt)
+{
+ int32 seen_scond, seen_ccond;
+ struct t_vpi_time tmpda;
+ struct tcterm_t reftct, dattct;
+
+ seen_scond = seen_ccond = FALSE;
+ /* 10/27/00 SJM - assumes for setup hold matches setuphold not a half */
+ *tclhd = NULL;
+ get_sdftok(f);
+ /* this skips COND form, but just get port - source has cond or edge */
+ if (!rd_port_tchk(f, &reftct)) return(FALSE);
+ if (!rd_port_tchk(f, &dattct)) return(FALSE);
+
+ if (__toktyp != LPAR)
+  { dellst_err("TIMINGCHECK", sdf_tcnam); return(FALSE); }
+
+ /* exactly two delay required */
+ if (rd_1_val(f, sdf_tcnam) == -1) return(FALSE); 
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(1239, "(TIMINGCHECK (%s two delays required", sdf_tcnam);
+  }
+ tmpda = __sdf_delp->da[0];
+ if (rd_1_val(f, sdf_tcnam) == -1) return(FALSE); 
+ /* now set first and 2nd delays t_vpi_delay records */
+ __sdf_delp2->da[0] = __sdf_delp->da[0];
+ __sdf_delp->da[0] = tmpda;
+ __sdf_delp->no_of_delays = 1;
+ __sdf_delp2->no_of_delays = 1;
+
+ /* (SSCOND and (CCOND can appear but no meaning in Verilog */
+ /* and not needed for matching */
+ if (__toktyp == LPAR)
+  {
+read_cond:
+   get_sdftok(f);
+   if (__toktyp == SDF_SCOND)
+    {
+     if (seen_scond)
+      {
+       __pv_ferr(1362, "(TIMINGCHECK (%s only one (SCOND allowed", sdf_tcnam); 
+      }
+     else seen_scond = TRUE;
+    }
+   else if (__toktyp == SDF_CCOND)
+    {
+     if (seen_scond)
+      {
+       __pv_ferr(1362, "(TIMINGCHECK (%s only one (CCOND allowed", sdf_tcnam); 
+      }
+     else seen_ccond = TRUE;
+    }
+   /* this reads ending ')' */
+   if (!sdf_skip_form(f)) return(FALSE);
+   get_sdftok(f);
+   if (__toktyp == LPAR) goto read_cond;
+  }
+ if (__toktyp != RPAR) { formend_err(sdf_tcnam); return(FALSE); }
+
+ /* need to be able to emit f errors for first token in form from here on */
+ *sav_lcnt = __lin_cnt; 
+ __lin_cnt = lcnt;  
+
+ if (port_qual_nam(reftct.tnam, "(TIMINGCHECK first terminal")) return(TRUE);
+ if (port_qual_nam(dattct.tnam, "(TIMINGCHECK second terminal")) return(TRUE);
+
+ /* now always return T since syntax good even if annotate fails */ 
+ if (reftct.cndnam != NULL)
+  {
+   if (port_qual_nam(reftct.cndnam, "(TIMINGCHECK reference condition signal"))
+    return(TRUE);
+  }
+ if (dattct.cndnam != NULL)
+  {
+   if (port_qual_nam(dattct.cndnam, "(TIMINGCHECK data condition signal"))
+    return(TRUE);
+  }
+ /* build list of candidate path matches, nil if none */
+ /* edge always included in filter of src-dsts */
+ if (tchktyp == TCHK_SETUPHOLD)
+  {
+   /* AIV 11/11/03 - setuphold SDF has data terminal first but it */
+   /* much match Verilog where ref terminal is first */
+   /* i.e. the SDF ref terminal is really the 2nd one in SDF file */
+   *tclhd = bld_match_tchk(ctmdp, &dattct, &reftct, tchktyp, sdf_tcnam);
+  }
+ else if (tchktyp == TCHK_RECREM)
+  {
+   /* AIV 11/11/03 - recrem SDF has data terminal first but it */
+   /* much match Verilog where ref terminal is first */
+   /* i.e. the SDF ref terminal is really the 2nd one in SDF file */
+   *tclhd = bld_match_tchk(ctmdp, &dattct, &reftct, tchktyp, sdf_tcnam);
+  }
+ else *tclhd = bld_match_tchk(ctmdp, &reftct, &dattct, tchktyp, sdf_tcnam);
+
+ /* free only the strings allocated inside a tchk term rec */ 
+ free_tct_insides(&reftct);
+ free_tct_insides(&dattct);
+ return(TRUE);
+}
+
+/*
+ * wrapper to prepare and call tchk sdf verbose tracing message
+ */
+static void prep_sdftchk_verbmsg(struct tchk_t *tcp, char *tcnam,
+ struct gate_t *ogp, struct itree_t *itp, struct mod_t *mdp, char *limnam)
+{
+ register int32 ii;
+ register struct itree_t *itp2;
+ char s1[RECLEN], s2[RECLEN];
+
+ if (itp == NULL)
+  {
+   for (ii = 0; ii < mdp->flatinum; ii++)
+    {
+     itp2 = mdp->moditps[ii];
+     __push_itstk(itp2);
+     sprintf(s1, "%s(%s) from '*'", __msg2_blditree(s2, itp2),
+      mdp->msym->synam);
+     emit_sdftchk_verbmsg(tcp, tcnam, ogp, s1, limnam);
+     __pop_itstk();
+    }
+  } 
+ else
+  {
+   __push_itstk(itp);
+   sprintf(s1, "%s(%s)", __msg2_blditree(s2, itp), mdp->msym->synam);
+   emit_sdftchk_verbmsg(tcp, tcnam, ogp, s1, limnam);
+   __pop_itstk();
+  }
+}
+
+/*
+ * emit sdf timing check limit verbose tracing message 
+ */
+static void emit_sdftchk_verbmsg(struct tchk_t *tcp, char *tcnam,
+ struct gate_t *ogp, char *celloc, char *lim)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ __cv_msg("  SDF **%s(%d): (TIMINGCHECK %s %slimit set to %s in %s at %s\n",
+  __cur_fnam, __lin_cnt, tcnam, lim, __bld_delay_str(s2, ogp->g_du,
+  ogp->g_delrep), celloc, __bld_lineloc(s1, tcp->tcsym->syfnam_ind,
+  tcp->tcsym->sylin_cnt));
+}
+
+/*
+ * read a time check port reference
+ * assume first token read and reads one past last 
+ *
+ * tricky because (COND [tchk cond. expr] [port spec]) possible
+ * nnam only for cond 
+ * other possibility just [port spec]
+ * where [port spec] can be (edge [port ref.]) or [port ref.]
+ */
+static int32 rd_port_tchk(FILE *f, struct tcterm_t *tctp)
+{
+ char pnam[IDLEN];
+ int32 i1, i2, eval, ettyp;
+
+ tctp->ti1 = tctp->ti2 = -1;
+ tctp->cndnam = NULL;
+ tctp->cndi1 = tctp->cndi2 = -1;
+ tctp->cnd_op = UNDEF;
+ tctp->cnd_const = -1;
+ tctp->eval = NOEDGE;
+
+ if (__toktyp == LPAR) 
+  {
+   /* collects ID (maybe strange edge) into __token */
+   ettyp = rd_edge_ident(f);
+   /* if (COND form contains port tchk */
+   if (ettyp == -1 && __toktyp == SDF_COND)
+    return(rd_tchk_cond(f, tctp));
+   /* port_edge */
+   if (ettyp == -1)
+    {
+     __pv_ferr(1386, "port_edge edge expected - %s read", prt_sdftok());
+     return(FALSE);
+    }
+   tctp->eval = ettyp;
+   get_sdftok(f);
+   if (!rd_port_spec(f, pnam, &i1, &i2, &eval, TRUE)) return(FALSE);
+   tctp->tnam = __pv_stralloc(pnam); 
+   tctp->ti1 = i1;
+   tctp->ti2 = i2;
+   tctp->eval = eval;
+   if (__toktyp != RPAR)
+    {
+     __pv_ferr(1363, "port_edge ending ) expected - %s read", prt_sdftok());
+     return(FALSE);
+    }
+   get_sdftok(f);
+   return(TRUE);
+  }
+ /* port_instance */
+ if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+ tctp->tnam = __pv_stralloc(pnam);
+ tctp->ti1 = i1;
+ tctp->ti2 = i2;
+ return(TRUE);
+}
+
+/*
+ * read a timing_check_condition into tcterm record
+ *
+ * sets sdf globals
+ * know (COND read and reads final port spec and ending ) 
+ * record good only if returns T
+ */
+static int32 rd_tchk_cond(FILE *f, struct tcterm_t *tctp)
+{
+ char labnam[IDLEN], nam[IDLEN];
+ int32 ni1, i1, i2, eval;
+
+ get_sdftok(f);
+ /* save literal string "label" but for now not used */
+ if (__toktyp == LITSTR) { strcpy(labnam, __token); get_sdftok(f); }
+ /* expression can have up to 3 term of certain simple form only */  
+ tctp->cnd_op = UNDEF;
+ tctp->cnd_const = -1;
+ if (__toktyp == BITNOT || __toktyp == NOT) 
+  {
+   tctp->cnd_op = __toktyp;
+   get_sdftok(f);
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1394,
+      "timing_check_condition unary operator following identifier expected - %s read",
+      prt_sdftok());
+     return(FALSE);
+    }
+   if (!rd_scalar_node(f, nam, &ni1)) return(FALSE); 
+   tctp->cndnam = __pv_stralloc(nam);
+   tctp->cndi1 = tctp->cndi2 = ni1;
+  }
+ else if (__toktyp == ID)
+  {
+   if (!rd_scalar_node(f, nam, &ni1)) return(FALSE); 
+   tctp->cndnam = __pv_stralloc(nam);
+   
+   if (__toktyp == RELEQ || __toktyp == RELCEQ || __toktyp == RELNEQ
+    || __toktyp == RELCNEQ) 
+    {
+     tctp->cnd_op = __toktyp;
+     if ((tctp->cnd_const = rd_scalar_const(f)) == -1) return(FALSE);
+     get_sdftok(f);
+    }
+  }
+ else
+  {
+   __pv_ferr(1356, "timing_check_condition expression expected - %s read",
+    prt_sdftok());
+   return(FALSE);
+  }
+ if (!rd_port_spec(f, nam, &i1, &i2, &eval, TRUE)) return(FALSE);
+ tctp->tnam = __pv_stralloc(nam);
+ tctp->ti1 = i1;
+ tctp->ti2 = i2;
+ tctp->eval = eval; 
+ if (__toktyp != RPAR)
+  {
+   __pv_ferr(1367, "timing_check_cond ending ) expected - %s read",
+    prt_sdftok());
+   return(FALSE);
+  }
+ get_sdftok(f);
+ return(TRUE);
+}
+
+/*
+ * read a scalar node
+ *
+ * read and set global for a scalar (ID or bit select node)
+ * this can not be qualified path and emits its own error message
+ *
+ * know scalar ID read and reads one past end
+ */
+static int32 rd_scalar_node(FILE *f, char *nnam, int32 *i1)
+{
+ int32 i2;
+
+ *i1 = -1;
+ if (__id_qualpath)
+  {
+   __pv_ferr(1245, "scalar node qualified path %s illegal", __token);
+   return(FALSE);
+  }
+ /* part select illegal */
+ if (!chkcnv_sdfid(nnam, i1, &i2, __token, TRUE) || *i1 != i2)
+  {
+   __pv_ferr(1227,
+    "scalar node %s illegal Verilog identifier or illegal part select",
+    __token);
+   return(FALSE);
+  }
+ get_sdftok(f);
+ return(TRUE);
+}
+
+/*
+ * convert from SDF timing check token type to internal tchk number
+ * returns -1 on error
+ */
+static int32 from_sdf_tctyp(int32 sdf_tctyp)
+{
+ switch ((byte) sdf_tctyp) {
+  case SDF_SETUP: return(TCHK_SETUP);
+  case SDF_HOLD: return(TCHK_HOLD);
+  case SDF_RECOVERY: return(TCHK_RECOVERY);
+  case SDF_SKEW: return(TCHK_SKEW);
+  case SDF_SETUPHOLD: return(TCHK_SETUPHOLD);
+  case SDF_NOCHANGE: return(TCHK_NOCHANGE);
+  case SDF_WIDTH: return(TCHK_WIDTH); 
+  case SDF_PERIOD: return(TCHK_PERIOD);
+  /* SJM 12/15/03 - added new 2001 LRM time checks */
+  case SDF_FULLSKEW: return(TCHK_FULLSKEW);
+  case SDF_REMOVAL: return(TCHK_REMOVAL);
+  case SDF_RECREM: return(TCHK_RECREM);
+  case SDF_TIMESKEW: return(TCHK_TIMESKEW);
+ }
+ return(-1);
+}
+
+/*
+ * build a list of matching timing checks
+ *
+ * rule is that missing SDF is treated as wildcard (all match) but if
+ * present in SDF must match exactly (including path has edge)
+ * idea: only as much SDF constructs as needed must be code in SDF file 
+ *
+ * sdf tc nam is SDF name for timing check, tc typ is internal tchk const
+ * know line count is beginning of this ([tchk name] form
+ *
+ * know reftctp always set but dattctp may be nil
+ */
+static struct tclst_t *bld_match_tchk(struct mod_t *ctmdp,
+ struct tcterm_t *reftctp, struct tcterm_t *dattctp, int32 tctyp,
+ char *sdf_tcnam)
+{
+ register struct tchk_t *tcp;
+ int32 tci1, tci2;
+ int32 rv, rv2;
+ struct tclst_t *tclp, *tclhd, *tclend;
+ struct net_t *np;
+ char s1[RECLEN]; 
+
+ /* SJM 09/26/99 - allow no matching of timing checks if +notimingchecks */
+ /* option selected */ 
+ if (__no_tchks) return(NULL);
+
+ if (ctmdp->mspfy == NULL)
+  {
+   /* ports can be any type */
+   sprintf(s1, "(TIMINGCHECK (%s [ref.]", sdf_tcnam); 
+   not_a_port(reftctp->tnam, IO_BID, ctmdp, s1);
+   if (dattctp != NULL)
+    {
+     sprintf(s1, "(TIMINGCHECK (%s [data]", sdf_tcnam); 
+     not_a_port(dattctp->tnam, IO_BID, ctmdp, s1);
+    }
+
+   __pv_ferr(1396, "unable to match (TIMINGCHECK (%s in type %s - no specify section", 
+    sdf_tcnam, ctmdp->msym->synam);
+   return(NULL);
+  }
+
+ /* build list of matching source-dest but ignore cond or condelse for now */ 
+ tclhd = tclend = NULL;
+ for (tcp = ctmdp->mspfy->tchks; tcp != NULL; tcp = tcp->tchknxt)
+  {
+   /* always ignore gone (can they happen?) and added setup hold half */
+   /* and added rec rem half */
+   if (tcp->tc_gone || tcp->tc_supofsuphld || tcp->tc_recofrecrem) continue;
+
+   /* step 1: obviously must match timing check type */
+   if (tcp->tchktyp != tctyp) continue;
+
+   /* step 2: match ref and dat name and range */
+   /* since know constant select or wire can never fail */
+   __xtract_wirng(tcp->startxp, &np, &tci1, &tci2);
+
+   /* ??? RELEASE REMOVEME --
+   __cv_msg("... trying to match Verilog ref %s[%d:%d] to SDF %s[%d:%d]\n",
+    np->nsym->synam, tci1, tci2, reftctp->tnam, reftctp->ti1, reftctp->ti2);
+   --- */
+
+   if (strcmp(np->nsym->synam, reftctp->tnam) != 0) continue;
+   if (tci1 != reftctp->ti1 || tci2 != reftctp->ti2) continue;
+
+   if (dattctp != NULL)
+    {
+     __xtract_wirng(tcp->chkxp, &np, &tci1, &tci2);
+     /* ??? RELEASE REMOVEME ---
+     __cv_msg("... trying to match Verilog data %s[%d:%d] to SDF %s[%d:%d]\n",
+      np->nsym->synam, tci1, tci2, dattctp->tnam, dattctp->ti1, dattctp->ti2);
+     --- */
+     if (strcmp(np->nsym->synam, dattctp->tnam) != 0) continue;
+     if (tci1 != dattctp->ti1 || tci2 != dattctp->ti2) continue;
+    }
+
+   /* step 3: match 2 edge, but no SDF edge (either) means match all */ 
+   /* i.e. if SDF has edge but tchk does not have corresonding, no match */
+   if (reftctp->eval != NOEDGE)
+    { if (reftctp->eval != tcp->startedge) continue; } 
+   if (dattctp != NULL && dattctp->eval != NOEDGE)
+    { if (dattctp->eval != tcp->chkedge) continue; } 
+
+   /* step 4: if SDF condition (either terminal), must match */
+   /* if no SDF condition matches all including cond's */  
+   if (reftctp->cndnam != NULL)
+    { if (!same_tchk_cond(reftctp, tcp->startcondx)) continue; }
+   if (dattctp != NULL && dattctp->cndnam != NULL)
+    { if (!same_tchk_cond(dattctp, tcp->chkcondx)) continue; }
+
+   /* have match */
+   tclp = (struct tclst_t *) __my_malloc(sizeof(struct tclst_t));
+   tclp->tcp = tcp;
+   tclp->tclnxt = NULL; 
+   if (tclend == NULL) tclhd = tclend = tclp;
+   else { tclend->tclnxt = tclp; tclend = tclp; }
+  }
+ if (tclhd == NULL)
+  {
+   /* ports can be any */
+   sprintf(s1, "(TIMINGCHECK (%s [ref.]", sdf_tcnam); 
+   rv = not_a_port(reftctp->tnam, IO_BID, ctmdp, s1);
+   
+   if (dattctp != NULL)
+    {
+     sprintf(s1, "(TIMINGCHECK (%s [data]", sdf_tcnam); 
+     rv2 = not_a_port(dattctp->tnam, IO_BID, ctmdp, s1);
+    }
+   else rv2 = FALSE;
+   if (rv || rv2) return(NULL); 
+
+   /* 10/27/00 SJM - no error if setup or hold, error only if after also */
+   /* trying to match setuphold, not found */
+   if (tctyp == TCHK_SETUP || tctyp == TCHK_HOLD) return(NULL);
+   /* 01/16/04 SJM - also not error if recovery or removal */
+   if (tctyp == TCHK_RECOVERY || tctyp == TCHK_REMOVAL) return(NULL);
+
+   __pv_ferr(1391, "no module %s timing check matches SDF (TIMINGCHECK (%s)", 
+    ctmdp->msym->synam, sdf_tcnam);
+   /* falls thru and correctly return nil */
+  }
+ return(tclhd);
+}
+
+/*
+ * compare a tc term condition (know exists) against tchk condx (expr.)
+ * returns T on match else F
+ */
+static int32 same_tchk_cond(struct tcterm_t *tctp, struct expr_t *condxp)
+{
+ int32 i1, i2, cval; 
+ word32 *wp;
+ struct net_t *np;
+ struct expr_t *xp;
+
+ if ((xp = condxp) == NULL) return(FALSE);
+ switch ((byte) xp->optyp) {
+  case ID:
+   if (tctp->cnd_op != UNDEF || tctp->cnd_const != -1) return(FALSE);
+
+chk_id:
+   if (tctp->cndi1 != -1 || tctp->cndi2 != -1) return(FALSE);
+   np = xp->lu.sy->el.enp;
+   if (strcmp(tctp->cndnam, np->nsym->synam) != 0) return(FALSE);
+   break; 
+  case LSB:
+   if (tctp->cnd_op != UNDEF || tctp->cnd_const != -1) return(FALSE);
+
+chk_bsel:
+   if (xp->ru.x->optyp != NUMBER) __case_terr(__FILE__, __LINE__);
+   __xtract_wirng(xp, &np, &i1, &i2);
+   if (strcmp(tctp->cndnam, np->nsym->synam) != 0) return(FALSE);
+   if (i1 != tctp->cndi1 || i2 != tctp->cndi2) return(FALSE);
+   break; 
+  case BITNOT:
+   if (tctp->cnd_op != BITNOT || tctp->cnd_const != -1) return(FALSE);
+   xp = condxp->lu.x; 
+do_scalar_var:
+   if (xp->optyp == ID) goto chk_id;
+   if (xp->optyp == LSB) goto chk_bsel;
+   /* not sure if legal, but can never match SDF in any case */
+   return(FALSE);
+  case NOT: 
+   if (tctp->cnd_op != NOT || tctp->cnd_const != -1) return(FALSE);
+   xp = condxp->lu.x; 
+   goto do_scalar_var;
+  case RELCEQ: case RELEQ: case RELCNEQ: case RELNEQ:
+   if (tctp->cnd_op != (int32) xp->optyp) return(FALSE); 
+   if (xp->ru.x->szu.xclen != 1) __misc_terr(__FILE__, __LINE__);
+   wp = &(__contab[xp->ru.x->ru.xvi]);
+   if (wp[1] != 0L) __misc_terr(__FILE__, __LINE__);
+   cval = (int32) wp[0];
+
+   if (cval != 0 && cval != 1) __misc_terr(__FILE__, __LINE__);
+   if (cval != tctp->cnd_const) return(FALSE);
+   xp = condxp->lu.x; 
+   goto do_scalar_var;
+  /* according to LRM, wider expr where just low bit used legal */
+  /* can never match an SDF condition expr. */
+  default: return(FALSE);
+ } 
+ return(TRUE);
+}
+
+/*
+ * free a tchk list
+ */
+static void free_tclst(struct tclst_t *tclhd)
+{
+ register struct tclst_t *tclp, *tclp2;
+
+ for (tclp = tclhd; tclp != NULL;)
+  {
+   tclp2 = tclp->tclnxt;
+   __my_free((char *) tclp, sizeof(struct tclst_t));
+   tclp = tclp2;
+  }
+}
+
+/*
+ * free insides only (strings) from a tchk terminal record
+ */
+static void free_tct_insides(struct tcterm_t *tctp)
+{
+ if (tctp->tnam != NULL) __my_free(tctp->tnam, strlen(tctp->tnam) + 1);
+ if (tctp->cndnam != NULL) __my_free(tctp->cndnam, strlen(tctp->cndnam) + 1);
+}
+
+/*
+ * MIPD PORT ROUTINES
+ */
+
+/*
+ * read and set MIPD delays for (PORT form
+ *
+ * here port can and will usually be qualified name
+ */
+static int32 rdset_port_mipd(FILE *f, struct itree_t *itp, struct mod_t *ctmdp,
+ char *formnam)
+{
+ register int32 ii;
+ int32 sav_lcnt, lcnt, si1, si2, ndels, none_set;
+ struct itree_t *itp2;
+ char qualport[IDLEN];
+
+ get_sdftok(f);
+ lcnt = __lin_cnt;
+ /* this can and usually will be qualified name */
+ if (!rd_port(f, qualport, &si1, &si2)) return(FALSE);
+ if (__toktyp != LPAR) { dellst_err(formnam, "PORT"); return(FALSE); }
+ get_sdftok(f);
+ /* know at least one read or returns -1 and emits error */
+ /* this reads (PORT form ending ) */
+ if ((ndels = rd_sdf_dellst(f, "PORT"))== -1) return(FALSE);
+
+ /* need to be able to emit f errors for first token in form from here on */
+ sav_lcnt = __lin_cnt; 
+ __lin_cnt = lcnt;  
+
+ /* except for next 2 fields all t_vpi_delay fields fixed in SDF */
+ __sdf_delp->no_of_delays = ndels; 
+ if (strcmp(formnam, "INCREMENT") == 0) __sdf_delp->append_flag = TRUE;
+ else __sdf_delp->append_flag = FALSE;
+
+ if (itp == NULL)
+  {
+   for (none_set = TRUE, ii = 0; ii < ctmdp->flatinum; ii++)
+    {
+     itp2 = ctmdp->moditps[ii];
+     if (__sdf_cntxt_itp != NULL && !itp_under_cntxt(itp2)) continue;
+
+     none_set = FALSE;
+     set_mipd_dels(itp2, qualport, si1, si2);
+    }
+   if (none_set)
+    {
+     __pv_fwarn(670,
+      "no MIPD delays changed because no instance of type %s in context", 
+      ctmdp->msym->synam); 
+    }
+  }
+ else set_mipd_dels(itp, qualport, si1, si2);
+
+ __lin_cnt = sav_lcnt;  
+ return(TRUE);
+}
+
+
+/*
+ * set/update MIPD delays - used by (PORT 
+ *
+ * uses already set global sdf_del table
+ * here port can be xmr path if range already extracted
+ *
+ * range here optional - if not present uses port width 
+ * MIPD delays are 16 value (both old and new used in get_del)
+ * know this called just before sim, i.e. n lds lists built
+ */
+static void set_mipd_dels(struct itree_t *itp, char *qualport, int32 si1,
+ int32 si2)
+{
+ register int32 ndx;
+ int32 fr, to, bi;
+ struct tenp_t *prtnetmap;
+ struct mipd_t *mipdp;
+ struct net_t *np;
+ struct itree_t *itp2;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+ struct gate_t ogat, ngat;
+ char port[IDLEN], s1[RECLEN];
+
+ /* setting to one instance case - this get instance only */
+ if (!xtrct_portdev(&itp2, port, qualport, itp, "PORT", "PORT")) return;
+ mdp = itp2->itip->imsym->el.emdp;
+ /* SJM 07/10/01 - now allowing MIPD delays on input and inout ports */
+ if ((mpp = get_inport_fr_nam(mdp, port)) == NULL
+  && (mpp = get_bidport_fr_nam(mdp, port)) == NULL)
+  { 
+   if (vpi_delay_all0s(__sdf_delp))
+    {
+     /* SJM 07/10/01 - ignore cases with 0 delay - it is what XL does */
+     __finform(3002,
+      "SDF (PORT form port %s is not an input or inout port of module %s but ignored because delays all 0",
+      port, mdp->msym->synam);
+    }
+   else 
+    {
+     __pv_ferr(1384,
+      "SDF (PORT form port %s is not an input or inout port of module %s",
+      port, mdp->msym->synam);
+    }
+   return;
+  }
+ /* LOOKATME - assuming vector ports require ranges */
+ if (si1 == -1)
+  {
+   if (mpp->mpwide != 1) { fr = mpp->mpwide - 1; to = 0; } else fr = to = 0;
+  }
+ else { fr = si1; to = si2; } 
+
+ prtnetmap = NULL;
+ /* build the MIPD d.s. if needed */
+ if (!mpp->has_mipd) 
+  {
+   /* if setting 0 del (always only 1 inst.) and none before no need to add */ 
+   /* if later other inst. needs will be set then */
+   if (vpi_delay_all0s(__sdf_delp))
+    {
+     __num_rem_mipds += (fr - to) + 1; 
+     return;
+    }
+   /* must allocate for all nets that connect to port - not just rng */
+   prtnetmap = __bld_portbit_netbit_map(mpp);
+   for (ndx = 0; ndx < mpp->mpwide; ndx++)
+    {
+     np = prtnetmap[ndx].tenu.np;
+     /* LOOKATME - think unc not possible here */
+     if (np == NULL || (np->nlds != NULL && np->nlds->npntyp == NP_MIPD_NCHG))
+      continue;
+
+     /* allocate path for every connected net */ 
+     __add_alloc_mipd_npp(np, mdp);
+    }
+
+   /* add the per bit mipd npp and set all bits to no IMPD */
+   mdp->mod_has_mipds = TRUE;
+   mpp->has_mipd = TRUE; 
+  }
+
+ if (prtnetmap == NULL) prtnetmap = __bld_portbit_netbit_map(mpp);
+ sprintf(s1, "(PORT %s in %s", port, mdp->msym->synam);
+ for (ndx = fr; ndx >= to; ndx--)
+  {
+   np = prtnetmap[ndx].tenu.np;
+   bi = prtnetmap[ndx].nbi;
+
+   /* DBG remove -- */
+   if (np->nlds == NULL || np->nlds->npntyp != NP_MIPD_NCHG)
+    __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   mipdp = &(np->nlds->elnpp.emipdbits[bi]);
+
+   /* if no active mipd for this net/bit, must enable with 0 delay */
+   if (mipdp->no_mipd) __setup_mipd(mipdp, np, mdp->flatinum);
+
+   ogat.g_du = mipdp->pb_mipd_du;
+   ogat.g_delrep = mipdp->pb_mipd_delrep;
+
+   /* change bit in every instance if all insts * form */
+   if (itp == NULL)
+    { 
+     /* result starts in ogat moves to ngat then finally put back in ogat */
+     if (!upd_sdf_perinst_del(&ogat, __sdf_delp, mdp, TRUE, FALSE, 4, s1))
+      continue;
+    }
+   else
+    {
+     if (!bld_sdfnewdu(&ngat, &ogat, __sdf_delp, itp2, TRUE, FALSE, s1))
+      continue;
+     if (ngat.g_delrep == DT_4V)
+      {
+       if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
+        ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
+       else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
+      }
+     __chg_1inst_del(&ogat, itp2, &ngat);
+     __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
+    }
+   mipdp->pb_mipd_du = ogat.g_du; 
+   mipdp->pb_mipd_delrep = ogat.g_delrep; 
+   if (__sdf_verbose)
+    {
+     char s2[RECLEN], s3[RECLEN];
+
+     if (mpp->mpwide > 1) sprintf(s1, " bit %d", ndx); else strcpy(s1, "");
+     __push_itstk(itp2);
+     __cv_msg("  SDF **%s(%d): (PORT %s%s MIPD set to %s (in %s type %s)\n", 
+      __cur_fnam, __lin_cnt,
+      msgpref_tostr(__xs, mpp), s1, __bld_delay_str(s2, ogat.g_du,
+      ogat.g_delrep), __msg2_blditree(s3, itp2), mdp->msym->synam);
+     __pop_itstk();
+    }
+  }
+ __my_free((char *) prtnetmap, mpp->mpwide*sizeof(struct tenp_t));
+}
+
+/*
+ * build a port expr. for tracing
+ */
+static char *msgpref_tostr(char *s, struct mod_pin_t *mpp)
+{
+ char s1[RECLEN];
+
+ if (mpp->mp_explicit)
+  {
+   if (mpp->mpref->optyp == ID
+    && strcmp(mpp->mpsnam, mpp->mpref->lu.sy->synam) == 0)
+    strcpy(s, mpp->mpsnam);
+   /* un-named but explicit module port stored wrong */
+   else sprintf(s, ".%s(%s)", mpp->mpsnam, __msgexpr_tostr(s1, mpp->mpref));
+  }
+ else __msgexpr_tostr(s, mpp->mpref); 
+ return(s); 
+}
+
+/*
+ * find one "underneath" instance of given type
+ * return nil if none
+ */
+static struct itree_t *find_1under_itp(struct mod_t *ctmdp)
+{
+ register int32 ii;
+ struct itree_t *itp;
+
+ /* if top level context, any will do, know at least one */
+ if (__sdf_cntxt_itp == NULL) return(ctmdp->moditps[0]);
+ else
+  {
+   for (ii = 0; ii < ctmdp->flatinum; ii++)
+    {
+     itp = ctmdp->moditps[ii];
+     if (itp_under_cntxt(itp)) return(itp);
+    }
+  } 
+ /* no types in this context */
+ return(NULL);
+}
+
+/*
+ * extract a (possibly qualified) port or device name
+ * and set instance object in
+ *
+ * inst '*' form and xmr port reference do not make sense - so an
+ * error is emitted
+ * select of last component allowed
+ */
+static int32 xtrct_portdev(struct itree_t **itp2, char *nam, char *qualport,
+ struct itree_t *itp, char *formnam, char *onam)
+{
+ struct expr_t *glbndp;
+ struct sy_t *tailsyp;
+ char s1[RECLEN];
+
+ if (itp == NULL)
+  {
+   __pv_ferr(1201,
+    "(%s hierarchical %s name %s illegal with (INSTANCE *) form - type unknown",
+    formnam, onam, qualport);
+   return(FALSE);
+  }
+
+ /* case 1, simple name (no path), just check and copy - this can have range */
+ if (!port_qual_nam(qualport, (char *) NULL))
+  {
+   *itp2 = itp;
+   strcpy(nam, qualport);
+   return(TRUE);
+  }
+
+ /* case 2: qualified name */
+ /* need to use interactive global context here */
+ __push_wrkitstk(__sdf_mdp, 0);
+ if ((glbndp = __glbnam_to_expr(qualport)) == NULL)
+  {
+   __pop_wrkitstk();
+   return(FALSE);
+  }
+
+ /* find downward itree loc */
+ *itp2 = get_sdfdownrel_itp(glbndp, itp, &tailsyp, s1);
+ /* done with glb ndp thru this code path */
+ __free_xtree(glbndp);
+ __pop_itstk();
+
+ if (*itp2 == NULL)
+  {
+   __pv_ferr(1388, "(%s form %s qualified name %s illegal in context %s: %s",
+    formnam, onam, qualport, get_sdfcntxtnam(__xs, itp), s1);
+   return(FALSE);
+  }
+ strcpy(nam, tailsyp->synam);
+ return(TRUE);
+}
+
+/*
+ * given a module and an input port name, find the port 
+ *
+ * tricky because port name space may be different
+ * first try for net that is IO_IN then search for drivers since
+ * input port only possibility 
+ * then sequentially search port list if not found
+ *
+ * this should be efficient since rare with lots of ports and
+ * connecting nets have different name but there can be designs
+ * where lots of sequential searching needed
+ *
+ * LOOKATME - could build symbol tables for large ones only (>10)
+ */
+static struct mod_pin_t *get_inport_fr_nam(struct mod_t *mdp, char *pnam)
+{
+ register struct net_pin_t *npp;
+ int32 pi;
+ struct sy_t *syp;
+ struct net_t *np; 
+ struct mod_pin_t *mpp;
+
+ if ((syp = __get_sym(pnam, mdp->msymtab)) != NULL)
+  {
+   if (syp->sytyp != SYM_N) goto nd_srch;
+   np = syp->el.enp;
+   if (np->iotyp != IO_IN) goto nd_srch;
+   for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+    {
+     /* can be multiple, but assume this is input port down driver */
+     /* SJM 12/15/03 - match both md port and new separated per bit md prt */
+     if (npp->npntyp != NP_MDPRT && npp->npntyp != NP_PB_MDPRT) continue;
+
+     mpp = &(mdp->mpins[npp->obnum]);    
+     /* could be separate port and net name space conflict, must search */ 
+     if (mpp->mp_explicit) goto nd_srch;
+     return(mpp);
+    }
+   __misc_terr(__FILE__, __LINE__);
+  }
+nd_srch:
+ if ((pi = getsrch_portnam(mdp, pnam)) == -1) return(NULL);
+ mpp = &(mdp->mpins[pi]);
+ if (mpp->mptyp != IO_IN) return(NULL);
+ return(mpp);
+}
+
+/*
+ * since port names in different name space must search here
+ * 
+ * slow sequential but only needed if not found in normal name space
+ * maybe fix this - can be SDF problem if lots of sarching needed
+ */
+static int32 getsrch_portnam(struct mod_t *mdp, register char *nam)
+{
+ register int32 pi;
+ register struct mod_pin_t *mpp;
+
+ for (pi = 0; pi < mdp->mpnum; pi++)
+  {
+   mpp = &(mdp->mpins[pi]);
+   if (mpp->mpsnam == NULL) continue;
+   if (strcmp(mpp->mpsnam, nam) == 0) return(pi);
+  }
+ return(-1);
+}
+
+/*
+ * given a module and an output port name, find the port 
+ *
+ * tricky because port name space may be different
+ */
+static struct mod_pin_t *get_outport_fr_nam(struct mod_t *mdp, char *pnam)
+{
+ register struct net_pin_t *npp;
+ int32 pi;
+ struct sy_t *syp;
+ struct net_t *np; 
+ struct mod_pin_t *mpp;
+
+ if ((syp = __get_sym(pnam, mdp->msymtab)) != NULL)
+  {
+   if (syp->sytyp != SYM_N) goto nd_srch;
+   np = syp->el.enp;
+   if (np->iotyp != IO_OUT) goto nd_srch;
+   for (npp = np->nlds; npp != NULL; npp = npp->npnxt)
+    {
+     /* can be multiple, but assume this is output port down load */
+     /* SJM 12/15/03 - match both md port and new separated per bit md prt */
+     if (npp->npntyp != NP_MDPRT && npp->npntyp != NP_PB_MDPRT) continue;
+
+     mpp = &(mdp->mpins[npp->obnum]);    
+     /* could be separate port and net name space conflict, must search */ 
+     if (mpp->mp_explicit) goto nd_srch;
+     return(mpp);
+    }
+   __misc_terr(__FILE__, __LINE__);
+  }
+nd_srch:
+ if ((pi = getsrch_portnam(mdp, pnam)) == -1) return(NULL);
+ mpp = &(mdp->mpins[pi]);
+ if (mpp->mptyp != IO_OUT) return(NULL);
+ return(mpp);
+}
+
+/*
+ * given a module and an inout port name, find the port 
+ *
+ * FIXME - because of no npps, must explicitly search
+ */
+static struct mod_pin_t *get_bidport_fr_nam(struct mod_t *mdp, char *pnam)
+{
+ int32 pi;
+ struct mod_pin_t *mpp;
+
+ if ((pi = getsrch_portnam(mdp, pnam)) == -1) return(NULL);
+ mpp = &(mdp->mpins[pi]);
+ if (mpp->mptyp != IO_BID) return(NULL);
+ return(mpp);
+}
+
+/*
+ * ROUTINES TO PROCESS INTERCONNECT DELAYS - IGNORED
+ */
+
+/*
+ * read and set all interconnect delays
+ *
+ * Verilog does not module real inter module paths (MIPD selected) 
+ * just ignoring these delay since not supported by Verilog
+ *
+ * need to support single source (same as (PORT for path dest.)
+ * because design compiler emits (INTERCONNECT delays
+ */
+static int32 rdset_interconn_dels(FILE *f, struct itree_t *itp,
+ struct mod_t *ctmdp, char *formnam)
+{
+ register int32 ii;
+ int32 ndels, none_set, si1, si2, di1, di2, sav_lcnt, lcnt;
+ struct itree_t *itp2;
+ char portsrc[IDLEN], portdst[IDLEN]; 
+
+ get_sdftok(f);
+ lcnt = __lin_cnt;
+ /* these can and usually will be qualified name */
+ if (!rd_port(f, portsrc, &si1, &si2)) return(FALSE);
+ if (!rd_port(f, portdst, &di1, &di2)) return(FALSE);
+ if (__toktyp != LPAR)
+  { dellst_err(formnam, "INTERCONNECT"); return(FALSE); }
+ get_sdftok(f);
+ if ((ndels = rd_sdf_dellst(f, "INTERCONNECT")) == -1) return(FALSE);
+
+ /* need to be able to emit f errors for first token in form from here on */
+ sav_lcnt = __lin_cnt; 
+ __lin_cnt = lcnt;  
+
+ /* except for next 2 fields all t_vpi_delay fields fixed in SDF */
+ __sdf_delp->no_of_delays = ndels; 
+ if (strcmp(formnam, "INCREMENT") == 0) __sdf_delp->append_flag = TRUE;
+ else __sdf_delp->append_flag = FALSE;
+
+ if (itp == NULL)
+  {
+   for (none_set = TRUE, ii = 0; ii < ctmdp->flatinum; ii++)
+    {
+     itp2 = ctmdp->moditps[ii];
+     if (__sdf_cntxt_itp != NULL && !itp_under_cntxt(itp2)) continue;
+
+     none_set = FALSE;
+     chkset_interconn_dels(itp2, portsrc, si1, si2, portdst, di1, di2);
+    }
+   if (none_set)
+    {
+     __pv_fwarn(670,
+      "no (INTERCONNECT delays changed because no instance of type %s in context", 
+      ctmdp->msym->synam); 
+    }
+  }
+ else chkset_interconn_dels(itp, portsrc, si1, si2, portdst, di1, di2);
+
+ __lin_cnt = sav_lcnt;  
+ return(TRUE);
+}
+
+/*
+ * update MIPD delays - used by (INTERCONNECT 
+ *
+ * uses already set global sdf_del table
+ * here port can be xmr path if range already extracted
+ *
+ * for all instances case - decomposed above so this called for each inst
+ */
+static void chkset_interconn_dels(struct itree_t *itp, char *portsrc,
+ int32 si1, int32 si2, char *portdst, int32 di1, int32 di2)
+{
+ register int32 ndx;
+ int32 fr, to, swid, dwid, bi;
+ struct tenp_t *prtnetmap;
+ struct mipd_t *mipdp;
+ struct itree_t *sitp2, *ditp2;
+ struct mod_t *smdp, *dmdp;
+ struct mod_pin_t *smpp, *dmpp;
+ struct gate_t ogat, ngat;
+ struct net_t *np;
+ char sport[IDLEN], dport[RECLEN], s1[RECLEN];
+
+ /* first need to know instances (probably down xmrs) of ports */
+ if (!xtrct_portdev(&sitp2, sport, portsrc, itp, "INTERCONNECT", "PORT"))
+  return;
+ if (!xtrct_portdev(&ditp2, dport, portdst, itp, "INTERCONNECT", "PORT"))
+  return;
+
+ /* next access and check the source port */
+ smdp = sitp2->itip->imsym->el.emdp;
+ if ((smpp = get_outport_fr_nam(smdp, sport)) == NULL &&
+  (smpp = get_bidport_fr_nam(smdp, sport)) == NULL) 
+  { 
+   /* 11/06/00 SJM - change to warn, because no multi-driver path inter- */
+   /* module paths, this is just MIPD - (PORT form and work fine */
+   __pv_fwarn(3106,
+    "SDF (INTERCONNECT form source port %s is not an output or inout port of module %s - works because annotated as (PORT form MIPD delay",
+    sport, smdp->msym->synam);
+  }
+
+ /* then the destination input port */
+ dmdp = ditp2->itip->imsym->el.emdp;
+ /* SJM 08/14/01 - was checking src not dest for input port */
+ if ((dmpp = get_inport_fr_nam(dmdp, dport)) == NULL 
+  && (dmpp = get_bidport_fr_nam(dmdp, dport)) == NULL) 
+  { 
+   __pv_ferr(1384,
+    "SDF (INTERCONNECT form destination port %s is not an input or inout port of module %s",
+    dport, dmdp->msym->synam);
+   return;
+  }
+
+ /* 11/06/00 SJM - only check for same width if input/inout port set */
+ /* since same as (PORT works fine */ 
+ if (smpp != NULL)
+  {
+   if (si1 == -1) swid = smpp->mpwide; else swid = si1 - si2 + 1;
+   if (di1 == -1) dwid = dmpp->mpwide; else dwid = di1 - di2 + 1;
+   if (swid != dwid)
+    {
+     __pv_fwarn(3105,
+      "SDF (INTERCONNECT form source %s width %d not same as destination %s width %d",
+      bld_prefnam(__xs, sport, si1, si2), swid, bld_prefnam(__xs2, dport, di1,
+      di2), dwid);
+    } 
+  }
+
+ /* LOOKATME - assuming vector ports require ranges */
+ if (di1 == -1)
+  {
+   if (dmpp->mpwide != 1) { fr = dmpp->mpwide - 1; to = 0; } else fr = to = 0;
+  }
+ else { fr = di1; to = di2; } 
+
+ prtnetmap = NULL;
+ /* always build the MIPD d.s. on dest if not built yet */
+ if (!dmpp->has_mipd) 
+  {
+   /* if setting 0 del (always only 1 inst.) and none before no need to add */ 
+   /* if later other inst. needs will be set then and no src path */
+   if (smpp == NULL && vpi_delay_all0s(__sdf_delp))
+    {
+     __num_rem_mipds += (fr - to) + 1; 
+     return;
+    }
+
+   /* must allocate for all nets that connect to port - not just rng */
+   prtnetmap = __bld_portbit_netbit_map(dmpp);
+   for (ndx = 0; ndx < dmpp->mpwide; ndx++)
+    {
+     np = prtnetmap[ndx].tenu.np;
+     /* LOOKATME - think unc not possible here */
+     if (np == NULL || (np->nlds != NULL && np->nlds->npntyp == NP_MIPD_NCHG))
+      continue;
+
+     /* allocate path for ever net connected to port */
+     __add_alloc_mipd_npp(np, dmdp);
+    }
+
+   /* add the per bit mipd npp and set all bits to no IMPD */
+   dmdp->mod_has_mipds = TRUE;
+   dmpp->has_mipd = TRUE; 
+  }
+
+ if (prtnetmap == NULL) prtnetmap = __bld_portbit_netbit_map(dmpp);
+ if (smpp == NULL)
+  {
+   sprintf(s1,
+    "(INTERCONNECT (but invalid source port %s) destination port %s in %s",
+    portsrc, dport, dmdp->msym->synam);
+  }
+ else
+  {
+   sprintf(s1, "(INTERCONNECT destination port %s in %s", dport,
+    dmdp->msym->synam);
+  }
+ for (ndx = fr; ndx >= to; ndx--)
+  {
+   np = prtnetmap[ndx].tenu.np;
+   bi = prtnetmap[ndx].nbi;
+
+   /* DBG remove -- */
+   if (np->nlds == NULL || np->nlds->npntyp != NP_MIPD_NCHG)
+    __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   mipdp = &(np->nlds->elnpp.emipdbits[bi]);
+
+   /* if no active mipd for this net/bit, must enable (PORT FORM with 0 del */
+   if (mipdp->no_mipd) __setup_mipd(mipdp, np, dmdp->flatinum);
+
+   /* FIXME - for now still not simulating src-dst path delays */
+   /* if use impth delays add the source path but set non src-dst too */
+   if (smpp != NULL && __use_impthdels && mipdp->pth_mipd)
+    add_srcdst_impth(mipdp, smpp, si1, si2, sitp2, s1);
+
+   /* even if setting, interconnect src-dst impth src, still set (PORT form */
+   ogat.g_du = mipdp->pb_mipd_du;
+   ogat.g_delrep = mipdp->pb_mipd_delrep;
+
+   if (!bld_sdfnewdu(&ngat, &ogat, __sdf_delp, ditp2, TRUE, FALSE, s1))
+    continue;
+
+   if (ngat.g_delrep == DT_4V)
+    {
+     if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
+      ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
+     else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
+    }
+
+   /* always set dest (PORT delay - either add or replace depending on SDF */
+   __chg_1inst_del(&ogat, ditp2, &ngat);
+   __free_del(ngat.g_du, ngat.g_delrep, dmdp->flatinum);
+
+   mipdp->pb_mipd_du = ogat.g_du; 
+   mipdp->pb_mipd_delrep = ogat.g_delrep; 
+   if (__sdf_verbose)
+    {
+     char s2[RECLEN], s3[RECLEN];
+
+     if (dmpp->mpwide > 1) sprintf(s1, " bit %d", ndx); else strcpy(s1, "");
+     __push_itstk(ditp2);
+     __cv_msg(
+      "  SDF **%s(%d): (INTERCONNECT (non src-dst port) %s%s MIPD set to %s (in %s type %s)\n", 
+      __cur_fnam, __lin_cnt,
+      msgpref_tostr(__xs, dmpp), s1, __bld_delay_str(s2, ogat.g_du,
+      ogat.g_delrep), __msg2_blditree(s3, ditp2), dmdp->msym->synam);
+     __pop_itstk();
+    }
+  }
+ __my_free((char *) prtnetmap, dmpp->mpwide*sizeof(struct tenp_t));
+}
+
+/*
+ * build a port reference name
+ */
+static char *bld_prefnam(char *s, char *pnam, int32 i1, int32 i2)
+{
+ if (i1 == -1) strcpy(s, pnam);
+ else if (i1 == i2) sprintf(s, "%s[%d]", pnam, i1); 
+ else sprintf(s, "%s[%d:%d]", pnam, i1, i2); 
+ return(s);
+} 
+
+/*
+ * routine to compute delay and fill interconnect src-dst source impth element
+ *
+ * this is called from inside dest range loop so same as full path
+ */
+static void add_srcdst_impth(struct mipd_t *mipdp, struct mod_pin_t *smpp,
+ int32 si1, int32 si2, struct itree_t *sitp, char *s1)
+{
+ int32 fr, to, bi, save_append_flg, ndx;
+ word64 tmpdval; 
+ struct tenp_t *prtnetmap;
+ struct gate_t ngat, ogat;
+ struct net_t *np;
+ struct impth_t *impthp; 
+
+ if (si1 == -1)
+  {
+   if (smpp->mpwide != 1) { fr = smpp->mpwide - 1; to = 0; } else fr = to = 0;
+  }
+ else { fr = si1; to = si2; } 
+
+ prtnetmap = __bld_portbit_netbit_map(smpp);
+ for (ndx = fr; ndx >= to; ndx--)
+  {
+   np = prtnetmap[ndx].tenu.np;
+   bi = prtnetmap[ndx].nbi;
+
+   impthp = (struct impth_t *) __my_malloc(sizeof(struct impth_t));
+   impthp->snp = np; 
+   impthp->sbi = bi;
+   impthp->sitp = sitp;
+   /* notice just one for each full path bit */
+   impthp->lastchg = 0ULL;
+
+   /* need to convert SDF delay_p (just using vpi because convenient) to del */
+   /* pass as non append and ogat as 0 and makes right non IS */
+   ogat.g_delrep = DT_1V;
+   ogat.g_du.d1v = &tmpdval;
+   tmpdval = 0ULL;
+
+   save_append_flg = __sdf_delp->append_flag;
+   /* LOOKATME - does this emit warns on delay problems? */
+   if (!bld_sdfnewdu(&ngat, &ogat, __sdf_delp, NULL, TRUE, FALSE, s1))
+    {
+     __sdf_delp->append_flag = save_append_flg;
+     /* ??? FIXME - HOW HANDLE THIS */
+     __misc_terr(__FILE__, __LINE__);
+     continue;
+    }
+   __sdf_delp->append_flag = save_append_flg;
+
+   /* notice must not free but bld sdfnewdu allocates new for each call */
+   impthp->impth_delrep = ngat.g_delrep;
+   impthp->impth_du = ngat.g_du;
+
+   /* LOOKATME - think linking on front works */
+   impthp->impthnxt = mipdp->impthtab[__inum];
+   mipdp->impthtab[__inum] = impthp;
+  }
+ __my_free((char *) prtnetmap, smpp->mpwide*sizeof(struct tenp_t));
+}
+
+/*
+ * ROUTINES TO PROCESS DEVICE DELAYS
+ */
+
+/*
+ * read and set delays for a device delay form that is cell all paths
+ *
+ * primitive delays handled elsewhere
+ * also can set IOPATH delays for all paths to output or in cell
+ * this can be qualified name (all outputs of the xmr path dest in xmr dest
+ * cell) but iopath because have both source and dest. can not be qualified
+ */
+static int32 rdset_devpath_dels(FILE *f, struct itree_t *itp,
+ struct mod_t *ctmdp, char *formnam)
+{
+ int32 si1, si2, ndels, sav_lcnt, lcnt;
+ char portdst[IDLEN];
+
+ /* DBG remove -- */
+ if (ctmdp == NULL) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+
+ get_sdftok(f);
+ lcnt = __lin_cnt;
+ /* ( is start of delval_list so portinst missing */
+ if (__toktyp != LPAR)
+  {
+   /* this can be qualified name */
+   if (!rd_port(f, portdst, &si1, &si2)) return(FALSE);
+   if (__toktyp != LPAR)
+    { dellst_err(formnam, "DEVICE"); return(FALSE); }
+  }
+ else { strcpy(portdst, ""); si1 = si2 = -1; }
+ get_sdftok(f);
+ if ((ndels = rd_sdf_dellst(f, "DEVICE")) == -1) return(FALSE);
+
+ /* except for next 2 fields all t_vpi_delay fields fixed in SDF */
+ __sdf_delp->no_of_delays = ndels; 
+ if (strcmp(formnam, "INCREMENT") == 0) __sdf_delp->append_flag = TRUE;
+ else __sdf_delp->append_flag = FALSE;
+
+ /* need to be able to emit f errors for first token in form from here on */
+ sav_lcnt = __lin_cnt; 
+ __lin_cnt = lcnt;  
+
+ if (strcmp(portdst, "") == 0)  
+  {
+   /* build list of all paths in ctmdp and update delays */
+   set_allpths_dels(itp, ctmdp);
+  }
+ /* all paths to one output */
+ else set_alloutpths_dels(portdst, si1, si2, itp, ctmdp);
+ __lin_cnt = sav_lcnt;
+ return(TRUE);
+}
+
+/*
+ * for (DEVICE no port instance form set delay for all paths in module
+ */
+static void set_allpths_dels(struct itree_t *itp, struct mod_t *ctmdp)
+{
+ register struct spcpth_t *pthp;
+ register struct pthlst_t *plp;
+ struct pthlst_t *plhd, *plend;
+
+ if (ctmdp->mspfy == NULL || ctmdp->mspfy->spcpths == NULL)
+  {
+   __pv_fwarn(668,
+    "SDF DEVICE module CELLTYPE %s has no paths - nothing to do",
+    ctmdp->msym->synam);
+   return;
+  }
+ plhd = plend = NULL;
+ for (pthp = ctmdp->mspfy->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+  {
+   plp = (struct pthlst_t *) __my_malloc(sizeof(struct pthlst_t));
+   plp->lpthp = pthp;
+   plp->pthlnxt = NULL; 
+   if (plend == NULL) plhd = plend = plp;
+   else { plend->pthlnxt = plp; plend = plp; }
+  }
+ for (plp = plhd; plp != NULL; plp = plp->pthlnxt)
+  set_1pthdel(plp, itp, ctmdp);
+ free_pthlst(plhd);
+} 
+
+/*
+ * for (DEVICE port instance (maybe xmr) set delay for all paths to output
+ *
+ * this differs from all paths by matching output and range 
+ * if any path component (, list in Verilog) matches delay is set for all 
+ */
+static void set_alloutpths_dels(char *qualport, int32 pi1, int32 pi2,
+ struct itree_t *itp, struct mod_t *ctmdp)
+{
+ register struct spcpth_t *pthp;
+ register struct pthlst_t *plp;
+ int32 pei;
+ struct pthlst_t *plhd, *plend;
+ struct itree_t *cor_itp, *itp2;
+ struct mod_t *mdp;
+ struct pathel_t *pep;
+ char portnam[IDLEN];
+
+ /* if wildcard all insts of type under form have same module type */
+ /* therefore need to find a "corrected" itp */
+ /* type will be same */
+ if (itp == NULL)
+  {
+   if ((cor_itp = find_1under_itp(ctmdp)) == NULL)
+    {
+     __pv_fwarn(669,
+      "delays not changed for (DEVICE portinst %s because no instance of type %s in context", 
+      qualport, ctmdp->msym->synam);
+     return;
+    }
+  }
+ else cor_itp = itp;
+
+ /* setting to one instance case */
+ if (!xtrct_portdev(&itp2, portnam, qualport, cor_itp, "DEVICE", "PORT"))
+  return;
+ mdp = itp2->itip->imsym->el.emdp;
+
+ if (ctmdp->mspfy == NULL || ctmdp->mspfy->spcpths == NULL)
+  {
+   not_a_port(portnam, IO_OUT, mdp, "(DEVICE");
+   __pv_fwarn(668,
+    "SDF DEVICE module CELLTYPE %s has no paths - nothing to do",
+    ctmdp->msym->synam);
+   return;
+  }
+ plhd = plend = NULL;
+ for (pthp = ctmdp->mspfy->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+  {
+   /* only match outputs */
+   for (pei = 0; pei <= pthp->last_peout; pei++)
+    {
+     pep = &(pthp->peouts[pei]);
+     if (strcmp(pep->penp->nsym->synam, portnam) != 0) continue;
+     /* if any bit overlaps matches */
+     if (pi1 != -1 && pep->pthi1 != -1)
+      { if (pi1 > pep->pthi1 && pi2 < pep->pthi2) continue; }
+
+     /*if either whole range or pi1:pi2 range at least one bit inside */
+     if (pi1 == -1 || pep->pthi1 == -1
+      || (pi1 <= pep->pthi1 && pi1 >= pep->pthi2)
+      || (pi2 <= pep->pthi1 && pi2 >= pep->pthi2))
+      {
+       plp = (struct pthlst_t *) __my_malloc(sizeof(struct pthlst_t));
+       plp->lpthp = pthp;
+       plp->pthlnxt = NULL; 
+       if (plend == NULL) plhd = plend = plp;
+       else { plend->pthlnxt = plp; plend = plp; }
+
+       /* once path in list, other matches irrelevant */
+       goto nxt_pth;
+      }
+    }
+nxt_pth:;
+  }
+ if (plhd == NULL)
+  {
+   if (not_a_port(portnam, IO_OUT, mdp, "(DEVICE")) return;
+
+   __pv_ferr(1329, 
+    "for (DEVICE no module %s specify path ends on output/inout port %s", 
+    mdp->msym->synam, portnam); 
+   return;
+  }
+ for (plp = plhd; plp != NULL; plp = plp->pthlnxt)
+  set_1pthdel(plp, itp, ctmdp);
+ free_pthlst(plhd);
+} 
+
+/*
+ * return T and emit error if name in (DEVICE or (TIMINGCHECK port name slot
+ * not a port
+ *
+ * here always check inout and passed port type
+ */
+static int32 not_a_port(char *pnam, int32 ptyp, struct mod_t *mdp, char *formnam)
+{
+ if (ptyp == IO_BID)
+  {
+   if (get_inport_fr_nam(mdp, pnam) != NULL) return(FALSE); 
+   if (get_outport_fr_nam(mdp, pnam) != NULL) return(FALSE); 
+   if (get_bidport_fr_nam(mdp, pnam) != NULL) return(FALSE); 
+  }
+ else
+  {
+   if (ptyp == IO_IN)
+    { if (get_inport_fr_nam(mdp, pnam) != NULL) return(FALSE); }
+   else
+    { if (get_outport_fr_nam(mdp, pnam) != NULL) return(FALSE); }
+
+   if (get_bidport_fr_nam(mdp, pnam) != NULL) return(FALSE); 
+  }
+
+ /* know port slot is not a port of given type for this module */
+ __pv_ferr(1385, "%s form port %s not a port of %s",
+  formnam, pnam, mdp->msym->synam); 
+ return(TRUE);
+}
+
+/*
+ * FORWARD TIMING EVIRONMENT ROUTINES - NOT USED BUT CHECKED
+ */
+
+/*
+ * read but skip one or more te_defs
+ *
+ * know (TIMINGENV read and reads one token after last
+ * think timing environment constraints do not make sense in a simulator 
+ * maybe user would code timing checks for simulation checking?
+ *
+ */
+static int32 rdskip_te_defs(FILE *f)
+{
+ int32 first_time, i1, i2, eval;
+ char tenam[RECLEN], constraint_name[IDLEN], pnam[IDLEN];
+
+ if (__sdf_verbose)
+  {
+   __cv_msg(
+    "  SDF: (TIMINGENV form skipped - constraints no effect in simulator\n");
+  }
+ for (first_time = FALSE;;)
+  {
+   /* this returns T if ) */
+   get_sdftok(f);
+   if (!rd_sdf_formtyp(f)) return(FALSE);
+   if (__toktyp == RPAR)
+    {
+     if (first_time)
+      {
+       __pv_ferr(1357,
+        "(TIMINGENV form empty - at least one te_def required");
+       return(FALSE);
+      }
+     break;
+    }
+   first_time = FALSE;
+   switch ((byte) __toktyp) {
+    case SDF_PATHCONSTRAINT:
+     get_sdftok(f);
+     if (__toktyp == LPAR)
+      {
+       get_sdftok(f);
+       if (__toktyp != SDF_NAME)
+        {
+bad_name:
+         __pv_ferr(1359, "(NAME [string]) of PATHCONSTRAINT bad - %s read",
+          prt_sdftok());  
+        }
+       get_sdftok(f);
+       if (__toktyp != LITSTR) goto bad_name;
+       strcpy(constraint_name, __token);
+       get_sdftok(f);   
+       if (__toktyp != RPAR) goto bad_name;
+       get_sdftok(f);
+      }
+     /* do not need to save since just skipping */
+     if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+     if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+     for (;;)
+      {
+       if (__toktyp == LPAR) break; 
+       if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+      }
+     if (rd_1or2_vals(f, tenam) != 2)
+      {
+       __pv_ferr(1239, "(PATHCONSTRAINT two values required");
+       return(FALSE); 
+      }
+     if (__toktyp != RPAR) formend_err(tenam);
+     /* would process constaint32 here */
+     break;
+    case SDF_PERIODCONSTRAINT:
+     get_sdftok(f);
+     if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+     if (rd_1_val(f, tenam) == -1) return(FALSE); 
+     if (__toktyp == LPAR) { if (!rd_exception(f)) return(FALSE); }
+     get_sdftok(f);
+     if (__toktyp != RPAR) formend_err(tenam);
+     /* process here */
+     break;
+    case SDF_SUM:
+     get_sdftok(f);
+     if (!rd_constraint_path(f, tenam, TRUE)) return(FALSE);
+     get_sdftok(f);
+     if (!rd_constraint_path(f, tenam, TRUE)) return(FALSE);
+     for (;;)
+      {
+       get_sdftok(f);   
+       if (!rd_constraint_path(f, tenam, FALSE)) return(FALSE);
+       if (__toktyp == NUMBER || __toktyp == REALNUM || __toktyp == COLON)
+        break;
+       if (__toktyp == TEOF)
+        {
+         __pv_ferr(1297, "(SUM constraint path list bad syntax - EOF read");
+         return(FALSE); 
+        }
+      }
+     if (!rd2_1_val(f)) return(FALSE);
+     if (__toktyp == RPAR) break;
+     /* would need to copy and save if need actual value */
+     if (rd_1_val(f, tenam) == -1) return(FALSE);
+     if (__toktyp != RPAR) { formend_err(tenam); return(FALSE); }
+     break;
+    case SDF_DIFF:
+     get_sdftok(f);
+     if (!rd_constraint_path(f, tenam, TRUE)) return(FALSE);
+     get_sdftok(f);
+     if (!rd_constraint_path(f, tenam, TRUE)) return(FALSE);
+     get_sdftok(f);  
+     if (rd_1or2_vals(f, tenam) == -1) return(FALSE); 
+     if (__toktyp != RPAR) formend_err(tenam);
+     break;
+    case SDF_SKEWCONSTRAINT:
+     get_sdftok(f);
+     /* since does nothing allowing full edge pair syntax */
+     if (!rd_port_spec(f, pnam, &i1, &i2, &eval, TRUE)) return(FALSE);
+     if (rd_1_val(f, tenam) == -1) return(FALSE);
+     if (__toktyp != RPAR) { formend_err(tenam); return(FALSE); }
+     break;
+    case SDF_ARRIVAL: case SDF_DEPARTURE:
+     get_sdftok(f);
+     if (__toktyp == LPAR)
+      {
+       if ((eval = rd_edge_ident(f)) == -1) return(FALSE);
+       get_sdftok(f);
+       if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+       if (__toktyp != RPAR) { formend_err(tenam); return(FALSE); }
+       get_sdftok(f);
+      }
+     if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+     if (!rd_4_vals(f, tenam)) return(FALSE);
+     if (__toktyp != RPAR) { formend_err(tenam); return(FALSE); }
+     break;
+    case SDF_SLACK:
+     get_sdftok(f);
+     if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+     if (!rd_4_vals(f, tenam)) return(FALSE);
+     if (__toktyp == NUMBER || __toktyp == REALNUM)
+      {
+       /* save number to process */
+       get_sdftok(f);
+      }
+     if (__toktyp != RPAR) { formend_err(tenam); return(FALSE); }
+     break;
+    case SDF_WAVEFORM:
+     get_sdftok(f);
+     if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+     if (__toktyp != NUMBER && __toktyp != REALNUM)
+      {
+       __pv_ferr(1361, "(WAVEFORM NUMBER expected - %s read", prt_sdftok());
+       return(FALSE);
+      }
+     if (!rd_edgepair_list(f)) return(FALSE);
+     break;
+    default:
+     __pv_ferr(1358, "te_def timing check form expected - (%s read",
+      prt_sdftok());
+     return(FALSE);
+   }
+  }
+ return(TRUE);
+}
+
+/*
+ * read an exception form
+ *
+ * know ( read and reads ending )
+ */
+static int32 rd_exception(FILE *f)
+{
+ int32 first_time;
+
+ get_sdftok(f);
+ if (__toktyp != SDF_EXCEPTION)
+  { 
+bad_except:
+   __pv_ferr(1200, "bad cns_def (PERIODCONSTRAINT (EXCEPTION form - %s read",
+    prt_sdftok());
+   return(FALSE);
+  }
+ /* read the cell_instance+ */
+ for (first_time = TRUE;;)
+  {
+   get_sdftok(f);
+   if (__toktyp == RPAR)
+    {
+     if (first_time) goto bad_except;
+     break;
+    }
+   if (__toktyp != LPAR) goto bad_except;
+   first_time = FALSE;
+   get_sdftok(f);
+   if (__toktyp != SDF_INSTANCE) goto bad_except;
+   get_sdftok(f);
+   if (__toktyp != RPAR)
+    {
+     if (__toktyp != ID && __toktyp != TIMES) goto bad_except;
+     get_sdftok(f);
+    }
+   if (__toktyp != RPAR) { formend_err("INSTANCE"); return(FALSE); }
+  }
+ return(TRUE);
+}
+
+/*
+ * read a constraint path
+ *
+ * know ( read and reads ending )
+ */
+static int32 rd_constraint_path(FILE *f, char *formnam, int32 required)
+{
+ int32 i1, i2;
+ char pnam[IDLEN];
+ 
+ get_sdftok(f);
+ /* if not required next will be ([num or :] */
+ if (!required) { if (__toktyp != ID) return(TRUE); }
+ if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+ if (!rd_port(f, pnam, &i1, &i2)) return(FALSE);
+ if (__toktyp != RPAR) { formend_err(formnam); return(FALSE); }
+ return(TRUE);
+}
+
+/*
+ * read either a start with neg edge or start with pos edge list (1 or more)
+ *
+ * reads first ( and last ) - this reads NUMBER not triple
+ *
+ * LOOKATME - should always be (negedge (num))(posedge (num)) or opposite but  
+ * not checked for now
+ */
+static int32 rd_edgepair_list(FILE *f)
+{
+ int32 first_time;
+
+ for (first_time = TRUE;;)
+  {
+   get_sdftok(f);
+   if (__toktyp == RPAR)
+    {
+     if (first_time) goto bad_edgepair;
+     break;
+    }
+   if (__toktyp != LPAR) 
+    {
+bad_edgepair:
+     __pv_ferr(1358, "bad tenv_def (WAVEFORM edgelist - %s read",
+      prt_sdftok());
+     return(FALSE);
+    }
+   first_time = FALSE;
+   get_sdftok(f);
+   if (__toktyp != SDF_NEGEDGE && __toktyp != SDF_POSEDGE) goto bad_edgepair;
+   /* first number required */
+   get_sdftok(f);
+   if (__toktyp != REALNUM && __toktyp != NUMBER) goto bad_edgepair;
+   /* 2nd optionsal */
+   get_sdftok(f);
+   if (__toktyp == RPAR) continue;
+   if (__toktyp != REALNUM && __toktyp != NUMBER) 
+    {
+bad_elend:
+     formend_err("edgelist");
+     return(FALSE);
+    }
+   get_sdftok(f);
+   if (__toktyp != RPAR) goto bad_elend; 
+  } 
+ return(TRUE);
+}
+
+/*
+ * LABEL PROCESSING AND PARAM SETTING ROUTINES
+ *
+ * grammar:
+ * lbl_spec    := (LABEL lbltype)
+ * lbltype     := (ABSOLUTE lbl_def+)
+ *             := (INCREMENT lbl_def+)
+ * lbl_def     := (IDENTIFIER-maybe-xmr rvalue)
+ *
+ * (LABEL read - reads ending ) 
+ *
+ * notice labels must be in units of ctmdp time scale because other
+ * parts of expression will be in those units - not SDF timescale
+ *
+ * qualified names illegal here - (INSTANCE must select exact instance
+ */
+static int32 rdset_labels(FILE *f, struct itree_t *itp, struct mod_t *ctmdp)
+{
+ register int32 ii;
+ int32 first_time, is_incr, is_minus, wlen, sav_lcnt, lcnt;
+ double d1;
+ word32 *wp;
+ struct t_vpi_time *vtp = &(__sdf_delp->da[0]);
+ struct sy_t *syp;
+ struct net_t *np;
+ struct xstk_t *xsp;
+ struct itree_t *itp2;
+ struct mod_t *mdp;
+ char labnam[IDLEN], s1[RECLEN], s2[RECLEN];
+
+ get_sdftok(f);
+ lcnt = __lin_cnt;
+ if (!rd_sdf_formtyp(f)) return(FALSE);
+ if (__toktyp == SDF_ABSOLUTE) is_incr = FALSE;
+ else if (__toktyp == SDF_INCREMENT) is_incr = TRUE;
+ else
+  {
+   __pv_ferr(1310,
+    "expected lbltype ABSOLUTE or INCREMENT expected - (%s read",
+    prt_sdftok());
+   return(FALSE);
+  }
+ for (first_time = TRUE;;)
+  {
+   get_sdftok(f);
+   if (__toktyp == RPAR)
+    {
+     if (first_time)
+      {
+       if (is_incr) strcpy(s1, "INCREMENT"); else strcpy(s1, "ABSOLUTE");
+       __pv_ferr(1380,
+        "(LABEL (%s lbl_def section empty - at least one lbl_def required",
+        s1);
+      }
+     break;
+    }
+   if (__toktyp != LPAR)
+    {
+     __pv_ferr(1307, "SDF lbldef ( expected - %s read", prt_sdftok());
+     return(FALSE);
+    }
+   first_time = FALSE;
+   get_sdftok(f);
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1306,
+      "SDF label expected - Verilog defparam or specparam reference - %s read",
+      prt_sdftok());
+     return(FALSE);
+    }
+   if (!xtrct_param(&itp2, labnam, itp)) return(FALSE);
+   get_sdftok(f);
+   /* this reads triple ending ) */
+   if (!rd_rtriple(f, vtp)) return(FALSE);
+   if (__toktyp != RPAR)
+    {
+     __pv_ferr(1308,
+      "SDF (LABEL form ending ) expected - %s read", prt_sdftok());
+     return(FALSE);
+    }
+   sav_lcnt = __lin_cnt; 
+   __lin_cnt = lcnt;  
+   if (itp2 != NULL) mdp = itp2->itip->imsym->el.emdp;
+   else mdp = ctmdp;
+   /* first look up symbol in specify symbol table if exists */
+   if (mdp->mspfy != NULL && mdp->mspfy->spfsyms != NULL) 
+    {
+     if ((syp =__get_sym(labnam, mdp->mspfy->spfsyms)) != NULL)
+      goto got_lab_param;
+    }
+   if ((syp =__get_sym(labnam, mdp->msymtab)) == NULL)
+    {
+     __pv_ferr(1309,
+      "(LABEL form label (spec or def param) %s not found in cell type %s",
+      labnam, mdp->msym->synam);
+     goto done;
+    }
+   __pv_fwarn(2304,
+    "(LABEL form back annotation to parameter %s non standard - will need to change to module scope specparam for Verilog 2000",
+     syp->synam);
+
+got_lab_param:
+   np = syp->el.enp;
+   if (vtp->type == vpiSuppressTime)
+    {
+     __pv_fwarn(671,
+      "(LABEL form %s parameter %s value missing - parameter not changed",
+      (is_incr ? "INCREMENT" : "ABSOLUTE"), syp->synam);
+     goto done;
+    }
+   d1 = vtp->real;
+   if (d1 < 0.0) { is_minus = TRUE; d1 = -d1; } else is_minus = FALSE;
+   if ((xsp = sdf_push_rvalue(np, d1)) == NULL) goto done;
+ 
+   /* now know correct value to store in xsp of width n wid */
+   wlen = wlen_(np->nwid);
+   /* case 1: specific instance maybe downward xmr reference */
+   if (itp2 != NULL)
+    {
+     /* load value and combine (add/subtract) if increment form */
+     if (is_incr)
+      {
+       __push_itstk(itp2);
+       if (!sdf_adjust_incr(np, xsp, is_minus))
+        { __pop_itstk(); goto done2; }
+       __pop_itstk();
+      }
+
+     /* change range rep to IS if needed */
+     if (np->srep == SR_PNUM)
+      __chg_param_tois(np, itp2->itip->imsym->el.emdp);
+     wp = &(np->nva.wp[2*wlen*itp2->itinum]);
+     memcpy(wp, xsp->ap, 2*WRDBYTES*wlen);
+
+     /* leave original parameter rhs expr. if case user codes wants */
+     /* different parameter algorithm - only paramter value changed */
+     /* but original param assign RHS left as is */ 
+
+     if (__sdf_verbose)
+      {
+       sprintf(s1, "%s(%s)", __msg2_blditree(s2, itp2), mdp->msym->synam);
+       emit_sdflblverb_msg(np, xsp, s1);
+      }
+     goto done2;
+    }
+   /* case 2: itp nil, all of design, never xmr port ref. */
+   if (!is_incr && itp2 == NULL && __sdf_cntxt_itp == NULL)
+    {
+     /* change back from IS form since all instances */
+     if (np->srep == SR_PISNUM) 
+      {
+       wp = np->nva.wp;
+       np->nva.wp = (word32 *) __my_malloc(2*wlen*WRDBYTES);
+       __my_free((char *) wp, mdp->flatinum*2*wlen*WRDBYTES); 
+       np->srep = SR_PNUM; 
+      }
+     wp = np->nva.wp;
+     memcpy(wp, xsp->ap, 2*WRDBYTES*wlen);
+     if (__sdf_verbose)
+      {
+       sprintf(s1, "all instances of %s", mdp->msym->synam);
+       emit_sdflblverb_msg(np, xsp, s1);
+      }
+     goto done2;
+    }
+   /* case 3: itp nil and under not all of design or incr */
+   for (ii = 0; ii < mdp->flatinum; ii++)
+    {
+     itp2 = mdp->moditps[ii];
+     if (__sdf_cntxt_itp != NULL && !itp_under_cntxt(itp2)) continue;
+     
+     if (is_incr)
+      {
+       __push_itstk(itp2);
+       if (!sdf_adjust_incr(np, xsp, is_minus)) { __pop_itstk(); continue; }
+       __pop_itstk();
+      }
+     /* change range rep to IS if needed */
+     if (np->srep == SR_PNUM)
+      __chg_param_tois(np, itp2->itip->imsym->el.emdp);
+     wp = &(np->nva.wp[2*wlen*itp2->itinum]);
+     memcpy(wp, xsp->ap, 2*WRDBYTES*wlen);
+
+     /* leave original parameter rhs expr. if case user codes wants */
+     /* different parameter algorithm - only paramter value changed */
+     /* but original param assign RHS left as is */ 
+
+     if (__sdf_verbose)
+      {
+       sprintf(s1, "instance %s under %s)", __msg2_blditree(s2, itp2),
+        mdp->msym->synam);
+       emit_sdflblverb_msg(np, xsp, s1);
+      }
+    }
+
+done2:
+   __pop_xstk(); 
+   /* SJM = 07/05/00 - even during simulation recomputing params/delays */
+   /* from labels works */
+   /* final step is to re-compute (and prep) all delays param effects */
+   __re_prep_dels(np, itp2, mdp, FALSE);
+done:
+   __lin_cnt = sav_lcnt;
+  }
+ /* lbltype ) read - now read lbl_spec ) - checked by caller */
+ get_sdftok(f);
+ return(TRUE);
+}
+
+/*
+ * extract a (possibly qualified) parameter name
+ * and set instance object in
+ *
+ * know ID (maybe qual. path) read 
+ * range illegal
+ * itp and *itp2 can both be nil 
+ */
+static int32 xtrct_param(struct itree_t **itp2, char *pnam, struct itree_t *itp)
+{
+ int32 i1, i2;
+ struct expr_t *glbndp;
+ struct sy_t *tailsyp;
+ char s1[IDLEN], s2[RECLEN];
+
+ if (itp == NULL)
+  {
+   __pv_ferr(1201,
+    "SDF (LABEL hierarchical parameter reference %s illegal with (INSTANCE *) form - type unknown",
+    __token);
+   return(FALSE);
+  }
+
+ /* case 1, simple name (no path), just check and copy */
+ if (!__id_qualpath)
+  {
+   /* if illegal verilog identifier convert to escaped */
+   if (!chkcnv_sdfid(pnam, &i1, &i2, __token, FALSE))
+    {
+     __pv_ferr(1344, "(LABEL %s illegal Verilog parameter name", __token);
+     return(FALSE);
+    }
+   *itp2 = itp;
+   return(TRUE);
+  }
+ /* case 2: qualified name */
+ /* convert to Verilog name and check */
+ /* LOOKATME - maybe should allow select from param here */
+ if (!chkcnv_sdfpath(s1, &i1, &i2, __token, FALSE))
+  {
+   __pv_ferr(1348,
+    "(LABEL hierarchical parameter name %s illegal Verilog global reference",
+    __token);
+   return(FALSE);
+  }
+ /* this emits its own error and returns nil on error */
+ /* need to use interactive global context here */
+ __push_wrkitstk(__sdf_mdp, 0);
+ if ((glbndp = __glbnam_to_expr(s1)) == NULL)
+  {
+   __pop_wrkitstk();
+   return(FALSE); 
+  }
+
+ /* find downward itree loc */
+ *itp2 = get_sdfdownrel_itp(glbndp, itp, &tailsyp, s2);
+ /* done with glb ndp */
+ __free_xtree(glbndp);
+ __pop_itstk();
+ if (*itp2 == NULL)
+  {
+   __pv_ferr(1388,
+    "(LABEL form qualified path %s.%s name illegal in context %s: %s",
+    s1, pnam, get_sdfcntxtnam(__xs, itp), s2);
+   return(FALSE);
+  }
+ if (tailsyp->sytyp != SYM_N || !tailsyp->el.enp->n_isaparam) 
+  {
+   __pv_ferr(1201,
+    "SDF (LABEL hierarchical parameter reference %s illegal - %s not a parameter",
+    __token, tailsyp->synam);
+   return(FALSE);
+  }
+ strcpy(pnam, tailsyp->synam);
+ return(TRUE);
+}
+
+/*
+ * push rtriple value onto stack with param matching type and width
+ *
+ * since SDF rtriple real (if present), convert to match param if needed
+ * after here know stack contains param width new value 
+ */
+static struct xstk_t *sdf_push_rvalue(struct net_t *np, double d1)
+{
+ int32 i1;
+ word64 timval;
+ struct xstk_t *xsp;
+
+ if (np->ntyp != N_REAL)
+  {
+   if (np->ntyp == N_INT) 
+    {
+     i1 = (int32) d1;
+     push_xstk_(xsp, np->nwid);
+     xsp->ap[0] = (word32) i1;
+     xsp->bp[0] = 0L;
+    }
+   else
+    {
+     if (!__real_to_v64tim(&timval, d1))
+      {
+       __pv_ferr(1327,
+        "precision lost in converting (LABEL rvalue %g to 64 bit", d1);
+       __pop_xstk();
+       return(NULL);
+      }
+     push_xstk_(xsp, 64);
+     xsp->ap[0] = (word32) (timval & WORDMASK_ULL);
+     xsp->ap[1] = (word32) ((timval >> 32) & WORDMASK_ULL);
+     xsp->bp[0] = xsp->bp[1] = 0L;
+     if (np->nwid != 64) __sizchgxs(xsp, np->nwid);
+    }
+  }
+ else
+  {
+   push_xstk_(xsp, WBITS);
+   /* value real and pushing real */
+   memcpy(xsp->ap, &d1, sizeof(double)); 
+  }
+ return(xsp);
+}
+
+/*
+ * emit a label sdf verbose message for param assign
+ */
+static void emit_sdflblverb_msg(struct net_t *np, struct xstk_t *xsp,
+ char *celloc)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ /* DBG remove -- */ 
+ if (!np->n_isaparam) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ if (np->nu.ct->p_specparam) strcpy(s1, "specparam"); 
+ else strcpy(s1, "defparam");
+
+ __cv_msg("  SDF **%s(%d): (LABEL %s %s set to %s in %s\n",
+  __cur_fnam, __lin_cnt, s1, np->nsym->synam,
+  __regab_tostr(s2, xsp->ap, xsp->bp, xsp->xslen, BDEC, FALSE), celloc);
+}
+
+/*
+ * for SDF label adjust increment parameter 
+ *
+ * leaves expr. stack same as entry
+ */
+static int32 sdf_adjust_incr(struct net_t *np, struct xstk_t *xsp, int32 is_minus)
+{
+ int32 i1, i2, isxz, cmp;
+ double d1, d2;
+ struct xstk_t *xsp2, *xsp3;
+
+ push_xstk_(xsp2, np->nwid);
+ __ld_wire_val(xsp2->ap, xsp2->bp, np);
+ if (np->ntyp == N_REAL)
+  {
+   memcpy(&d1, xsp->ap, sizeof(double));
+   memcpy(&d2, xsp2->ap, sizeof(double));
+   if (is_minus) d2 -= d1; else d2 += d1;
+   memcpy(xsp->ap, &d2, sizeof(double));
+   return(TRUE);
+  }
+ if (!vval_is0_(xsp2->bp, xsp2->xslen))
+  {
+   __pv_ferr(1250,
+    "(LABEL INCREMENT form impossible - parameter %s value %s x/z",
+    np->nsym->synam, __regab_tostr(__xs, xsp2->ap, xsp2->bp, xsp->xslen,
+    BDEC, FALSE));
+   __pop_xstk();
+   return(FALSE);
+  }
+ /* int32 - result can be negative */
+ /* know neiher value can have x/z bits on */
+ if (np->ntyp == N_INT)
+  {
+   i1 = (int32) xsp2->ap[0]; 
+   i2 = (int32) xsp->ap[0];
+   if (is_minus) i2 -= i1; else i2 += i1;
+   xsp->ap[0] = i2;
+   __pop_xstk();
+   return(TRUE);
+  }
+ /* word32 case fits in word32 case */
+ if (np->nwid <= WBITS)
+  {
+   if (is_minus)
+    {
+     if (xsp2->ap[0] < xsp->ap[0])
+      {
+incr_neg:
+       __pv_ferr(1250,
+        "(LABEL INCREMENT form impossible - word32 parameter %s incremented value negative",
+        np->nsym->synam);
+       __pop_xstk();
+       return(FALSE);
+      }
+     xsp2->ap[0] -= xsp->ap[0]; 
+     xsp->ap[0] = xsp2->ap[0];
+    }
+   else xsp->ap[0] += xsp2->ap[0];
+   __pop_xstk();
+   return(TRUE);
+  }
+ /* word32 wider than one word32 */
+ push_xstk_(xsp3, np->nwid);
+ if (is_minus)
+  {
+   /* SJM 05/10/04 LOOKATME SIGNED - think do not need signed wide comp here */
+   cmp = __do_widecmp(&isxz, xsp->ap, xsp->bp, xsp2->ap, xsp2->bp, np->nwid);
+   /* DBG remove --- */
+   if (isxz) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   if (cmp < 0) { __pop_xstk(); goto incr_neg; }
+   __lsub(xsp3->ap, xsp2->ap, xsp->ap, np->nwid);
+  }
+ else __ladd(xsp3->ap, xsp2->ap, xsp->ap, np->nwid);
+ cp_walign_(xsp->ap, xsp3->ap, np->nwid);
+ __pop_xstk();
+ __pop_xstk();
+ return(TRUE);
+}
+
+/*
+ * change parameter from SR_PNUM to SR_PISNUM range all values same
+ * no error possible here
+ *
+ * LOOKATME - does this still work with v2k param override scheme?
+ */
+extern void __chg_param_tois(struct net_t *np, struct mod_t *imdp)
+{
+ register int32 ii;
+ int32 wlen2x;
+ word32 *wp, *wp2;
+
+ wlen2x = 2*wlen_(np->nwid);
+ wp = np->nva.wp;
+ wp2 = (word32 *) __my_malloc(wlen2x*WRDBYTES*imdp->flatinum); 
+ for (ii = 0; ii < imdp->flatinum; ii++)
+  { memcpy(&(wp2[ii*wlen2x]), wp, WRDBYTES*wlen2x); }
+ __my_free((char *) wp, WRDBYTES*wlen2x);
+ np->srep = SR_PISNUM;
+ np->nva.wp = wp2;
+ imdp->mhasisform = TRUE;
+}
+
+/*
+ * DELAY CHANGING MECHANISM ROUTINES (USES VPI) 
+ */
+
+/*
+ * given an SDF vpi delay_p filled by user, build the _du for it
+ *
+ * know delay number correct
+ * vpi delay_p filled 
+ * if no source delay caller changes to #0 before calling
+ * any time scaling uses SDF timescale (can be smaller than design prec)
+ *
+ * this always builds non IS form, so never a need for packed but does
+ * try to reduce
+ *
+ * this can be called multiple times provided append flg turned off
+ * also if append flg turned off, itp can be passed as il
+ */
+static int32 bld_sdfnewdu(struct gate_t *ngp, struct gate_t *ogp,
+ p_vpi_delay delay_p, struct itree_t *itp, int32 is_path, int32 is_trireg,
+ char *sdfmsg)
+{
+ register int32 di;
+ int32 ndels, ondels, negdel[16], empty_fld[16], has_emp;
+ word64 tim[16], otim[16], ntim[16], *dtab;
+
+ /* if empty place holders in delay p, set to old delay or 0 if append */ 
+ /* this trims all tail empty place holders */
+ if ((ndels = sdf_fillchk_tim(tim, negdel, empty_fld, &has_emp,
+  delay_p, sdfmsg)) == -1) return(FALSE); 
+
+ /* if no dels, no change for both append (change 0) or absolute (ignore) */
+ if (ndels == 0) return(FALSE);
+
+ /* handle appending - must be on delay_p array */ 
+ if (delay_p->append_flag)
+  { 
+   __push_itstk(itp);
+   __extract_delval(otim, &ondels, ogp->g_du, ogp->g_delrep);
+   __pop_itstk();
+   /* if either 1, widen with inform by replicating the 1 to width of other */
+   if ((ondels == 1 || ndels == 1) && (ondels != ndels)) 
+    {
+     __finform(479,
+      "%s INCREMENT old (%d) and new (%d) number of delays differ - one delay replicated",
+      sdfmsg, ondels, ndels);   
+
+     if (ondels != 1)
+      {
+       for (di = 1; di < ondels; di++) tim[di] = tim[0];
+       ndels = ondels;
+      }
+     else
+      { 
+       for (di = 1; di < ndels; di++) otim[di] = otim[0];
+       ondels = ndels;
+      }
+    }
+   /* here need 2 delay case that is not normally reduced to */
+   if (!is_path && ondels == 3)
+    {
+     if (is_trireg) 
+      { if (otim[3]== otim[0] || otim[3] == otim[1]) ondels = 2; }
+     else
+      {
+       if ((otim[2] == otim[0] || otim[2] == otim[1]) 
+        && (otim[3] == otim[0] || otim[3] == otim[1]))
+        ondels = 2; 
+      }
+    }
+   /* if too few new delays, use 0 for those (i.e. unchanged) */
+   if (ndels < ondels)
+    {
+     __finform(478,
+      "%s INCREMENT more old delays (%d) than new (%d) - 0 used for missing",
+      sdfmsg, ondels, ndels);   
+     for (di = ndels; di < ondels; di++) tim[di] = 0ULL;
+     ndels = ondels;
+    }
+   /* too many - ignore with warning */
+   else if (ndels > ondels)
+    {
+     __pv_fwarn(674,
+      "%s INCREMENT more new delays (%d) than old (%d) - extra ignored",
+      sdfmsg, ndels, ondels);   
+     ndels = ondels;
+    }
+   /* do the update - know ndels and odels same */
+   for (di = 0; di < ndels; di++) ntim[di] = tim[di];
+   for (di = 0; di < ndels; di++)
+    {
+     if (negdel[di])
+      {
+       if (ntim[di] > otim[di])
+        {
+         __pv_fwarn(667,
+          "%s INCREMENT append result (pos %d) negative (0 used)", sdfmsg,
+           di + 1);
+         tim[di] = 0ULL;
+        }
+       else tim[di] = otim[di] - ntim[di];
+      } 
+     else tim[di] = otim[di] + ntim[di];
+    }
+  }
+ /* easy 1 delay case */
+ if (ndels == 1)
+  {
+del1form:
+   ngp->g_du.d1v = (word64 *) __my_malloc(sizeof(word64));
+   *(ngp->g_du.d1v) = tim[0];
+   ngp->g_delrep = DT_1V;
+   return(TRUE);
+  }
+
+ /* if absolute and has empty place holders, must fill empty */
+ /* problem is that for empty, time value 0 but should be old value */
+ if (has_emp && !delay_p->append_flag)
+  {
+   __push_itstk(itp);
+   __extract_delval(otim, &ondels, ogp->g_du, ogp->g_delrep);
+   __pop_itstk();
+   for (di = 0; di < ndels; di++)
+    {
+     if (!empty_fld[di]) continue;
+      
+     /* if ondels shorter than new and empty field, warning with 0 */
+     if (di >= ondels)
+      {
+       __pv_fwarn(673,
+        "%s ABSOLUTE empty delay place holder but no original delay (pos. %d) - 0 used",
+       sdfmsg, di);
+      }  
+     else tim[di] = otim[di];
+    }
+  }
+ /* see if can reduce to 1 - know at least 2 */
+ for (di = 1; di < ndels; di++) { if (tim[0] != tim[di]) goto no_reduce1; }
+ goto del1form;
+
+no_reduce1:
+ /* know tim has right new delay value - fill dtab (always 1 or 16 for path) */
+ if (is_path)
+  {
+   dtab = (word64 *) __my_malloc(16*sizeof(word64));
+   __fill_16vconst(dtab, tim, ndels);
+   ngp->g_delrep = DT_16V;
+   ngp->g_du.d16v = dtab;
+  }
+ else
+  {
+   dtab = (word64 *) __my_malloc(4*sizeof(word64));
+   __fill_4vconst(dtab, &(tim[0]), &(tim[1]), &(tim[2]), ndels, is_trireg);
+   ngp->g_delrep = DT_4V;
+   ngp->g_du.d4v = dtab;
+  }
+ return(TRUE);
+}
+
+/*
+ * fill and check internal tim[] value from delay p for SDF
+ * return -1 on error else number of delays after tail place holder removed
+ *
+ * know all delays vpiScaledRealTime
+ * for SDF any mtm or pulsere already removed
+ * for empty () place holders, set empty_fld for pos. and time to 0
+ * but also removed all end since have no effect
+ */
+static int32 sdf_fillchk_tim(word64 *tim, int32 *negdel, int32 *empty_fld,
+ int32 *has_emp, p_vpi_delay delay_p,  char *sdfmsg)
+{
+ register int32 di, nndels;
+ int32 ndels, has_empty;
+ double d1;
+ struct t_vpi_time *vpitimp;
+
+ has_empty = FALSE;
+ *has_emp = FALSE;
+ ndels = delay_p->no_of_delays;
+ for (di = 0; di < ndels; di++) negdel[di] = empty_fld[di] = FALSE;
+ /* step 1: convert to internal ticks and set neg - maybe needed for inc */
+ for (di = 0; di < ndels; di++)
+  {
+   /* always ignore any pulse limits (2 and 3 or 3 through 8 if mtm) */
+   vpitimp = &(delay_p->da[di]);
+
+   /* if delay field empty (SDF place holder), set pos. flag */
+   if (vpitimp->type == vpiSuppressTime)
+    {
+     empty_fld[di] = TRUE;
+     tim[0] = 0ULL;   
+     has_empty = TRUE;
+     continue;
+    }
+
+   /* DBG remove --- */
+   if (vpitimp->type == vpiSimTime) __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   d1 = vpitimp->real;
+   if (d1 < 0.0)
+    {
+     if (!delay_p->append_flag)
+      {
+       __pv_fwarn(667, "%s ABSOLUTE value %g (pos %d) negative (0 used)",
+        sdfmsg, d1, di + 1);
+        tim[di] = 0ULL;
+       continue;
+      }  
+     d1 = -d1;
+     negdel[di] = TRUE;
+    }
+   /* first scale to real but in design time prec (min. ticks) */
+   if (__sdf_nd_tscale)
+    {
+     if (__sdf_ts_units < 0) d1 /= __dbl_toticks_tab[-__sdf_ts_units];
+     else d1 *= __dbl_toticks_tab[__sdf_ts_units];
+    }
+   /* once know in design time prec. units, convert to ticks (from real) */ 
+   if (!__real_to_v64tim(&(tim[di]), d1))
+    {
+     __pv_ferr(1365, "%s delay value %g (pos. %d) too large for 64 bit time",
+      sdfmsg, d1, di + 1);
+     return(-1);
+    }
+  }
+ /* remove place holders - if all empty emit warning */
+ if (has_empty)
+  {
+   for (nndels = ndels, di = ndels - 1; di >= 0; di--)
+    {
+     if (!empty_fld[di]) break;
+     nndels--;
+    }
+   if (nndels == 0)
+    {
+     __pv_fwarn(650,
+     "%s all delay list values (size %d) empty place holders - no delay change",
+      sdfmsg, ndels);
+    }
+   ndels = nndels;
+  }
+ if (has_empty) *has_emp = TRUE;
+ return(ndels);
+}
+
+/*
+ * return T if vpi_delay records all 0 (or missing) 
+ *
+ * used for MIPDs to not set 0 delays
+ */
+static int32 vpi_delay_all0s(p_vpi_delay delay_p)
+{
+ register int32 di;
+ register struct t_vpi_time *vpitimp;
+ double d1;
+
+ for (di = 0; di < delay_p->no_of_delays; di++)
+  {
+   /* always ignore any pulse limits (2 and 3 or 3 through 8 if mtm) */
+   vpitimp = &(delay_p->da[di]);
+   /* missing for append mode same as 0 */
+   if (vpitimp->type == vpiSuppressTime) continue;
+
+   /* DBG remove --- */
+   if (vpitimp->type != vpiScaledRealTime) __arg_terr(__FILE__, __LINE__);
+   /* --- */
+   d1 = vpitimp->real;
+   /* for non append mode, <0 converted to 0.0 so same as 0 */
+   if (delay_p->append_flag) { if (d1 != 0.0) return(FALSE); }
+   else { if (d1 > 0.0) return(FALSE); }
+  }
+ return(TRUE);
+}
+
+/*
+ * SDF FILE OBJECT LOW LEVEL READ ROUTINES
+ */
+
+/*
+ * read a delay list - fills extern 12 value maximum value and in use tables
+ * returns no. of delays (some may be missing) or -1 on error
+ *
+ * ( and first value read and reads one past list end - must be )
+ * at least one required but can be ()
+ *
+ * syntax for delay lists:
+ *  rvalue ::= ([some kind of real number - maybe mtm])
+ *  delval ::= ([rnumber]) | (([delay rnumber]) ([rlim rnumber]))
+ *           | ((delay rnumber]) ([rlim rnumber]) ([xlim rnumber]))   
+ * -- notice no parentheses around this - context has parens
+ * delval_list ::= [from 1 to 12 delvals] 
+ *
+ * examples of delval: (mtm), (), ((mtm) (mtm)), ((mtm), (mtm), (mtm))
+ * list: () ((mtm) ()) (mtm) ((mtm) (mtm) (mtm)) ()
+ * notice some members of list can have rlim, xlim and other not
+ * also missing needed for delay setting - no change
+ *
+ * SJM 10/23/00 - () not at end was not working - i.e. it was not being added
+ * to delay list as empty form - now do not just skip when seeing ()
+ */
+static int32 rd_sdf_dellst(FILE *f, char *formnam)
+{
+ register int32 nvals;
+ struct t_vpi_time *vtp = &(__sdf_delp->da[0]);
+ struct t_vpi_time tmpvtim;
+
+ for (nvals = 0;;)
+  {
+   /* case 1: position "nval" empty () form */
+   if (__toktyp == RPAR)
+    {
+     vtp[nvals].type = vpiSuppressTime;
+     nvals++;  
+     if (nvals > 12) goto too_many;
+     goto nxt_del;
+    }
+
+   /* case 2: r limit 2-tuple or r and x 3-tuple form - starts with (( */
+   if (__toktyp == LPAR)
+    {
+     get_sdftok(f);
+     /* know triple always reads required ending ) - room for illegal 13th */
+     if (!rd_rtriple(f, &(vtp[nvals]))) return(-1);
+     nvals++;  
+     if (nvals > 12)
+      {
+too_many:
+       __pv_ferr(1332, "(%s form delval_list illegal - more than 12 delvals",
+        formnam);
+       if (!sdf_skip_form(f)) return(-1);
+       return(nvals);
+      }
+     get_sdftok(f); 
+     if (__toktyp != LPAR)
+      {
+bad_list:
+       __pv_ferr(1331, "(%s form delval_list illegal - error at delay pos. %d",
+        formnam, nvals + 1);
+       return(-1);
+      }
+     if (!rd_rtriple(f, &(tmpvtim))) return(-1);
+     if (tmpvtim.type != vpiSuppressTime)
+      {
+       if (!__seen_rlim_delval)
+        {
+         __seen_rlim_delval = TRUE;
+         __pv_fwarn(657,
+          "some delval(s) contain reject limits - ignored (this is first)");
+        }
+      } 
+     get_sdftok(f); 
+     /* 2-tuple without x limit legal */
+     if (__toktyp == RPAR) goto nxt_del;
+     if (__toktyp != LPAR) goto bad_list; 
+     if (!rd_rtriple(f, &(tmpvtim))) return(-1);
+     if (tmpvtim.type != vpiSuppressTime)
+      {
+       if (!__seen_xlim_delval)
+        {
+         __seen_xlim_delval = TRUE;
+         __pv_fwarn(658,
+          "some delval(s) contain error (x) limits - ignored (this is first)");
+        }
+      } 
+    }
+   else
+    { 
+     /* case 3: non r/e lim value - normal delay from list */
+     if (!rd_rtriple(f, &(vtp[nvals]))) return(-1);
+     nvals++;  
+     if (nvals > 12) goto too_many;
+    }
+
+nxt_del:
+   get_sdftok(f);
+   if (__toktyp == RPAR) break;
+   if (__toktyp != LPAR) goto bad_list; 
+   get_sdftok(f);
+  }
+ /* starts from 0 but nvals set at unfilled next to fill so same as number */
+ return(nvals);
+}
+
+/*
+ * read one real (including negative) numeric expression as vpi time
+ *
+ * fills dap and returns T - if error returns F dap may or may not be set
+ *
+ * <value> or <min>:<typ>:<max> where all but one can be omitted 
+ * for <min>:<typ>:<max> at least one value and two : required
+ * RNUMBER form also read 
+ *
+ * assumes rtriple (or degenerate one value) always followed by )
+ * mintypmax selector from command line option or sdf syst override
+ * used to select value - sets vpiSuppressTime if missing 
+ *
+ * this does not scale, delay preparation does that
+ *
+ * first token read (probably after '(') and reads ending )
+ * LOOKATME - possibly faster if not always convert to double but
+ * think SDF standard requires
+ */
+static int32 rd_rtriple(FILE *f, register struct t_vpi_time *dap)
+{
+ double d1, d2, d3;
+ register int32 has_min, has_typ, has_max;
+
+ d1 = d2 = d3 = 0.0;
+ dap->type = vpiScaledRealTime;
+ has_min = has_typ = has_max = TRUE;
+ if (__toktyp == COLON) { has_min = FALSE; goto get_typ; }
+
+ if (__toktyp == REALNUM) d1 = __itok_realval; 
+ else if (__toktyp == NUMBER) d1 = (double) __sdf_tokval;
+ else 
+  {  
+bad_rexp:
+   __pv_ferr(1372, "SDF rtriple value or : expected - %s read",
+    prt_sdftok());
+   return(FALSE);
+  }  
+
+ get_sdftok(f);
+ /* ([rnumber]) case */  
+ if (__toktyp == RPAR) { dap->real = d1; return(TRUE); }
+ if (__toktyp != COLON) goto bad_rexp; 
+
+get_typ:
+ get_sdftok(f);
+ if (__toktyp == COLON) { has_typ = FALSE; goto get_max; }
+ if (__toktyp == REALNUM) d2 = __itok_realval;
+ else if (__toktyp == NUMBER) d2 = (double) __sdf_tokval;
+ else goto bad_rexp; 
+ get_sdftok(f);
+ if (__toktyp != COLON) goto bad_rexp;
+
+get_max:
+ get_sdftok(f);
+ if (__toktyp == RPAR) { has_max = FALSE; goto set_val; }
+ if (__toktyp == REALNUM) d3 = __itok_realval;
+ else if (__toktyp == NUMBER) d3 = (double) __sdf_tokval;
+ else goto bad_rexp; 
+
+ get_sdftok(f);
+ if (__toktyp != RPAR) goto bad_rexp;
+ 
+set_val:
+ if (__sdf_mintypmax_sel == DEL_TYP)
+  {
+   if (!has_typ) dap->type = vpiSuppressTime; else dap->real = d2;
+  }
+ else if (__sdf_mintypmax_sel == DEL_MIN)
+  {
+   if (!has_min) dap->type = vpiSuppressTime; else dap->real = d1;
+  }
+ else if (__sdf_mintypmax_sel == DEL_MAX)
+  {
+   if (!has_max) dap->type = vpiSuppressTime; else dap->real = d3;
+  }
+ else __case_terr(__FILE__, __LINE__);
+ return(TRUE);
+}
+
+/*
+ * get a form ([name] (name in token) or )
+ * return F on error
+ */
+static int32 rd_sdf_formtyp(FILE *f)
+{
+ if (__toktyp != LPAR)
+  {
+   if (__toktyp == RPAR) return(TRUE);
+   __pv_ferr(1371, "SDF form starting '(' expected - %s read",
+    prt_sdftok());
+   return(FALSE);
+  }
+ get_sdftok(f);
+ if (__toktyp < SDF_BKEYS)
+  {
+   __pv_ferr(1321, "SDF form name expected - %s read", prt_sdftok());
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * get a form ([name] (name in token) - error if not present
+ * return F on error
+ */
+static int32 rd2_sdf_formtyp(FILE *f)
+{
+ get_sdftok(f);
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(1371, "SDF form starting '(' expected - %s read",
+    prt_sdftok());
+   return(FALSE);
+  }
+ get_sdftok(f);
+ if (__toktyp < SDF_BKEYS)
+  {
+   __pv_ferr(1321, "SDF form name expected - %s read", prt_sdftok());
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * read a string value (name of something) also reads terminating )
+ * puts string into sdf work string - caller must allocate
+ * in SDF 3.0, value can not be missing
+ */
+static int32 rd_sdf_strval(FILE *f)
+{
+ get_sdftok(f);
+ if (__toktyp != LITSTR)
+  {
+   __pv_ferr(1320, "string value expected - %s read", prt_sdftok());
+   return(FALSE);
+  }
+ strcpy(__sdf_work_str, __token);
+ get_sdftok(f);
+ if (__toktyp != RPAR)
+  {
+   __pv_ferr(1322, "string value not followed by ) - %s read", prt_sdftok());
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+
+/*
+ *  SDF TOKEN INPUT ROUTINES
+ */
+
+/*
+ * ascii character table for processing end of ID tokens
+ * 0: continue - legal ID char (letter, digit, _) 
+ * 1: end and don't back up (white space)
+ * 2: end and back up (operators)
+ * 3: inc lin_cnt and end - only new line
+ * 4: illegal ID char
+ * 5: \\ escape - include next char unless white space
+ * 6: [] - bit select part of ID - need to set flag
+ * 7: :  - part select part of ID - in expr. (not embedded in ID) normal op
+ *
+ * . can start number only except for catching separator path prefix error
+ * table allows [], ., and : in IDs because that is SDF semantics
+ * ID where [ is possible must be parsed by caller 
+ *
+ * 0x5f is _ and $ are legal starting and in IDs (value 0)
+ */
+static char sdf_ctab[128] = {
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 3, 4, 1, 1, 4, 4, /* ^i,\n,\f,\r */
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ /* need to handle " */
+ 1, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* sp,!,%,#,(,),*,',+,-,.,/ */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 2, 2, 2, 2, 2, /* digits, :,;,<,-,>,? */
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @, cap letters */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 6, 2, 0, /* letters, [, \\,], ^, */
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* `, letters */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2  /* lettes, {, |, },~,EOF */
+};
+
+/* DBG remove and fix ---
+static void get_sdftok(FILE *f)
+{
+ static void get2_sdftok(FILE *);
+
+ get2_sdftok(f);
+ __cvsim_msg("-- line %d: token [%s]\n", __lin_cnt, prt_sdftok());
+}
+--- */
+
+/*
+ * get a -f file option token - only white space separation
+ * (modified from yylex in "The Unix Programming Environment" p. 337)
+ * notice no push back token here
+ *
+ * this collects selects (including part select) and xmrs because that
+ * is SDF semantics - part of ID - caller must parse because selects
+ * and non escaped path separator must appear as selects and XMRs in Verilog 
+ *
+ * LOOKATME - algorithm is to allow any [], . or : in ID, only checked when
+ * ID mapped to Verilog - where [] becomes selects
+ */
+static void get_sdftok(FILE *f)
+{
+ /* the char must be an int32 for machine independence */
+ register int32 c, ctval;
+ register char *cp;
+ register int32 len, c1, t1typ;
+ int32 toolong;
+ 
+ len = 0;
+ /* these must be turned off because possibly set by last call */
+ __id_qualpath = FALSE;
+ __id_select = FALSE;
+ __id_partsel = FALSE;
+
+again:
+ do { ctval = sdf_ctab[(c = getc(f)) & 0x7f]; } while (ctval == 1);
+ if (c == '\n')
+  {
+again2:
+   __lin_cnt++;
+   do { ctval = sdf_ctab[(c = getc(f)) & 0x7f]; } while (ctval == 1);
+   if (c == '\n') goto again2; 
+  }
+ switch (c) {
+  case EOF: __toktyp = TEOF; return;
+  /* notice as first char - token for ?: expr. operator or mtm value */
+  /* but in ID since selector part, part of token */
+  case ':':__toktyp = COLON; return;
+  case '#': __toktyp = SHARP; return;
+  /* CHECKME - where can $ appear, ` in number? */
+  case '$': __toktyp = SDF_DOL; return;
+  case ',': __toktyp = COMMA; return;
+  case '[': __toktyp = LSB; return; 
+  case ']': __toktyp = RSB; return; 
+  case '{': __toktyp = LCB; return;
+  case '}': __toktyp = RCB; return;
+  case '?': __toktyp = QUEST; return;
+  case '(': __toktyp = LPAR; return;
+  case ')': __toktyp = RPAR; return;
+  /* special for ' in 1'b[val] form */ 
+  case '\'':
+   /* SJM 05/14/01 - need to collect 4 cases of `[bB][01] form scalars */
+   /* if scalar not allowed in context just return quote, error later */
+   if (!__rding_cond_expr) { __toktyp = SDF_QUOTE; return; }
+
+   c = getc(f) & 0x7f;
+   if (c != 'b' && c != 'B') 
+    { ungetc(c, f); __toktyp = SDF_QUOTE; return; }
+rd_scalar_const:
+   c1 = getc(f) & 0x7f;
+   if (c1 == '0') { __sdf_tokval = 0; __toktyp = NUMBER; return; }
+   if (c1 == '1') { __sdf_tokval = 1; __toktyp = NUMBER; return; }
+bad_scalar:
+   __pv_ferr(1382,
+    "SDF path delay condition scalar constant %c illegal value - only 0 or 1 allowed",
+    c1);
+   __token[0] = '\''; __token[1] = c; __token[2] = c1; __token[3] = '\0';
+   __toktyp = BADOBJ;
+   return;
+  case '`': __toktyp = SDF_BACKQ; return;
+  case '*': __toktyp = TIMES; return;
+  case '/': 
+   if ((t1typ = sdf_rd_comment(f)) == UNDEF) goto again;
+   /* know path sep '/' or ID not returned */
+   if (t1typ == ID)
+    {
+     __id_qualpath = TRUE;
+     ctval = sdf_ctab[(c = getc(f)) & 0x7f];
+     cp = __token;
+     *cp++ = '/';  
+     len = 1;
+     goto collect_id;
+    }
+   if (t1typ == TEOF) __toktyp = t1typ; else __toktyp = DIV;
+   return;
+  case '%': __toktyp = MOD; return;
+  case '~':
+   if ((c1 = getc(f)) == '^') { __toktyp = REDXNOR; return; }
+   ungetc(c1, f);
+   __toktyp = BITNOT;
+   return;
+  case '&':
+   if ((c1 = getc(f)) == '&') { __toktyp = BOOLAND; return; }
+   ungetc(c1, f);
+   __toktyp = BITREDAND;
+   return;
+  case '|':
+   if ((c1 = getc(f)) == '|') { __toktyp = BOOLOR; return; }
+   ungetc(c1, f);
+   __toktyp = BITREDOR;
+   return;
+  case '^':
+   if ((c1 = getc(f)) == '~') { __toktyp = REDXNOR; return; }
+   ungetc(c1, f);
+   __toktyp = BITREDXOR;
+   return;
+  /* notice no C assignment op operators */
+  case '=':
+   if ((c1 = getc(f)) != '=')
+    {
+     __pv_ferr(1374, "SDF operator '=' illegal");
+     __token[0] = '?';
+     __token[1] = '\0';
+     __toktyp = BADOBJ;
+     return;
+    }
+   if ((c1 = getc(f)) != '=') { ungetc(c1, f); __toktyp = RELEQ; return; }
+   __toktyp = RELCEQ;
+   return;
+  case '!':
+   if ((c1 = getc(f)) != '=') { ungetc(c1, f); __toktyp = NOT; return; }
+   if ((c1 = getc(f)) != '=') { ungetc(c1, f); __toktyp = RELNEQ; return; }
+   __toktyp = RELCNEQ;
+   return;
+  case '>':
+   if ((c1 = getc(f)) == '=') { __toktyp = RELGE; return; }
+   else if (c1 == '>')
+    {
+     /* SJM 10/01/03 - add parsing of arithmetic right shift >>> */  
+     if ((c1 = getc(f)) == '>') { __toktyp = ASHIFTR; return; }
+     ungetc(c1, f);
+     __toktyp = SHIFTR;
+     return;
+    }
+   ungetc(c1, f);
+   __toktyp = RELGT;
+   return;
+  case '<':
+   if ((c1 = getc(f)) == '=') { __toktyp = RELLE; return; }
+   else if (c1 == '<') 
+    {
+     /* SJM 10/01/03 - add parsing of arithmetic right shift >>> */  
+     if ((c1 = getc(f)) == '<') { __toktyp = ASHIFTL; return; }
+     ungetc(c1, f);
+     __toktyp = SHIFTL;
+     return;
+    }
+   ungetc(c1, f);
+   __toktyp = RELLT;
+   return;   
+  case '\\':
+   /* IDs can start with escaped characters */
+   c = getc(f);
+   ctval = sdf_ctab[c & 0x7f];
+   if (ctval == 1 || ctval == 3)  
+    {
+     __pv_ferr(1377,
+      "escaped white space illegal in SDF file (illegal in IDs)");
+     __toktyp = BADOBJ;
+     __token[0] = '?';
+     __token[1] = '\0';  
+     return;
+    }
+   cp = __token;
+   *cp++ = '\\';  
+   len = 1;
+   goto collect_id;
+  case '"': __toktyp = sdf_collect_str(f); return;
+
+  case '1':
+   /* SJM 05/14/01 - 1 special case if reading IOPATH cond expr */
+   /* if scalar not allowed in context, treat as normal number */
+   if (!__rding_cond_expr) goto get_num;
+   c1 = getc(f) & 0x7f;
+   /* if not scalar constant, collect as normal number */
+   if (c1 != '\'') { ungetc(c1, f); goto get_num; }
+   c = getc(f) & 0x7f;
+   if (c != 'b' && c != 'B') goto bad_scalar;
+   goto rd_scalar_const;
+
+  case '+': case '-': case '.': case '0':
+  case '2': case '3':
+  case '4': case '5': case '6': case '7': case '8': case '9':
+get_num: 
+   __toktyp = sdf_collect_num(f, c);
+   /* if path separator . and starts with ".[letter]", the ID returned */
+   if (__toktyp == ID)
+    {
+     /* ID first char, un-getted in collect number, must reread */
+     __id_qualpath = TRUE;
+     ctval = sdf_ctab[(c = getc(f)) & 0x7f];
+     cp = __token;
+     *cp++ = '.';  
+     len = 1;
+     goto collect_id;
+    }
+   return;
+ }
+ /* here know digits eliminated so only letters, $, and _ have ct val 0 */
+ /* i.e. ID must start with _, $, or letter */ 
+ if (ctval != 0)
+  {
+   __token[0] = '?';
+   __token[1] = '\0';
+   __pv_ferr(1375, "SDF file contains illegal character %c (%x)", c, c);
+   /* just some impossible token */
+   __toktyp = BADOBJ;  
+   return;
+  }
+ /* try to recognize some kind of id - only - know c and ctval */
+ /* obviously in spite of SDF LRM, ID can not start with number */
+ cp = __token;
+collect_id:
+ for (toolong = FALSE;;)
+  {
+   /* loop backward - know good character to add here - check and fix below */
+   if (++len >= IDCHARS)
+    {
+     if (!toolong)
+      {
+       __pv_ferr(1376, "SDF identifier too long (%d) - truncated",
+        IDCHARS - 1);
+       toolong = TRUE;
+      }
+    }
+   else *cp++ = c;
+
+   c = getc(f);
+   if ((ctval = sdf_ctab[c & 0x7f]) == 0) continue;
+
+   /* if entire escaped - will not see any of these */
+   /* if component escaped - may need to fixup later */
+   if (c == __pathsep) { __id_qualpath = TRUE; continue; }
+   if (ctval == 6) { __id_select = TRUE; continue; }
+   if (ctval == 7) { __id_partsel = TRUE; continue; }
+/* ---
+   if (c == __pathsep)
+    { *cp++ = c; len++, c = getc(f); __id_qualpath = TRUE; continue; }
+   if (ctval == 6) 
+    { *cp++ = c; len++; c = getc(f); __id_select = TRUE; continue; }
+   if (ctval == 7) 
+    { *cp++ = c; len++; c = getc(f); __id_partsel = TRUE; continue; }
+--- */
+
+   /* any escaped part of SDF ID - escape remains and next not special */ 
+   if (ctval == 5) 
+    {
+     c = getc(f);
+     ctval = sdf_ctab[c & 0x7f];
+     if (ctval == 1 || ctval == 3)  
+      {
+       __pv_ferr(1377, "SDF identifier cannot escape white space - ended");
+       *cp = '\0';
+       goto end_id;
+      }
+     /* must leave escape character in ID */
+     *cp++ = '\\';
+     len++;
+     /* c is character after ID, always added above then get next above */
+     /* i.e. no special checking for current c */
+     continue;
+    }
+   ungetc(c, f);
+   goto end_id;
+  }
+end_id:
+ *cp = '\0';
+ /* no reason to lookup if has select or path separator - know can't match */
+ if (__id_qualpath || __id_select || __id_partsel) __toktyp = ID;
+ else __toktyp = get_sdfkeywrd(__token);
+}
+
+/*
+ * read a comment (either / * or //)
+ */
+static int32 sdf_rd_comment(FILE *f)
+{
+ register int32 c;
+ int32 c2;
+
+ c2 = getc(f);
+ /* /[ID] possible as path - return with indicator */  
+ if (__pathsep == '/' && (isalpha(c2) || c2 == '_'))
+  { ungetc(c2, f); return(ID); }
+
+ /* // to EOL comment */
+ if (c2 == '/')
+  {
+   while ((c = getc(f)) != '\n') if (c == EOF) return(TEOF);
+   ungetc(c, f);
+   return(UNDEF);
+  }
+ /* slash-star comments don't nest */
+ if (c2 == '*')
+  {
+more_comment:
+   while ((c = getc(f)) != '*')
+    {
+     /* error if / * comments nested */
+     if (c == '/')
+      {
+       if ((c2 = getc(f)) == '*')
+        {
+         __pv_fwarn(663, "SDF delay file nested /* in /* style comment");
+         continue;
+        }
+       c = c2;
+      }
+     if (c == EOF) return(TEOF);
+     if (c == '\n') __lin_cnt++;
+    }
+got_star:
+   if ((c = getc(f)) == '/') return(UNDEF);
+   if (c == '*') goto got_star;
+   if (c == '\n') __lin_cnt++;
+   goto more_comment;
+  }
+ /* not a comment so treat as name token */
+ /* notice c2 here must be most recent because above if never falls through */
+ ungetc(c2, f);
+ return(DIV);
+}
+
+/*
+ * collect an sdf file form string
+ */
+static int32 sdf_collect_str(FILE *f)
+{
+ register char *cp;
+ register int32 c;
+ int32 namlen;
+
+ for (cp = __token, namlen = 0;;)
+  {
+   /* SJM 03/20/00 - for SDF all tokens and strings limited to id len */
+   if (++namlen >= IDLEN - 1)
+    {
+     __pv_ferr(1311, "SDF quoted string too long (%d) - truncated", IDLEN);
+     *cp = '\0';
+     for (;;)
+      {
+       if ((c = getc(f)) == '"') return(LITSTR);
+       if (c == '\n') __lin_cnt++;
+       if (c == EOF) goto unterm_str;
+      }
+    }
+   if ((c = getc(f)) == '"') break;
+   if (c == '\n')
+    {
+     __pv_fwarn(672, "new line embedded in SDF quoted string");
+     __lin_cnt++;
+    }
+   if (c == EOF)
+    {
+unterm_str:
+     __pv_ferr(1312, "unterminated SDF string");
+     return(TEOF);
+    }
+   *cp++ = c; 
+  }
+ *cp = '\0';
+ return(LITSTR);
+}
+
+/*
+ * collect a number and convert to value
+ * if has . becomes real - this uses c scanf to read
+ */
+static int32 sdf_collect_num(FILE *f, int32 c)
+{
+ register char *cp;
+ int32 c1, fill, namlen, is_real, errnum, signv, t1;
+ double d1;
+ char *endp;
+ 
+ /* for .[letter] form and path separator dot handle rooted path */
+ if (c == '.' &&__pathsep == '.')
+  {
+   c1 = getc(f);
+   ungetc(c1, f);
+   if (isalpha(c1) || c1 == '_') return(ID);
+  }
+
+ signv = FALSE;
+ if (c == '+' || c == '-')  
+  {
+   if (c == '-') signv = TRUE;
+   c1 = getc(f);
+   if (!isdigit(c1) && c1 != '.') 
+    {
+     if (c == '-') return(MINUS);
+     return(PLUS);
+    }
+   c = c1;
+  }
+ fill = TRUE;
+ is_real = FALSE;
+ for (namlen = 0, cp = __token;;)
+  {
+   if (++namlen >= IDLEN - 1)
+    {
+     __pv_ferr(1313, "SDF number too long (%d) - truncated", IDLEN);
+     *cp = '\0';
+     fill = FALSE;
+    }
+   switch (c) {
+    case '+': case '-': case '0': case '1': case '2': case '3':
+    case '4': case '5': case '6': case '7': case '8': case '9': 
+     if (fill) *cp++ = c; break;
+    case '.': case 'e': case 'E':
+     is_real = TRUE;
+     if (fill) *cp++ = c; break;
+    default: *cp = '\0'; goto got_num;
+   }
+   c = getc(f);
+  }
+got_num: 
+  ungetc(c, f);
+  if (is_real)
+   {
+    d1 = __my_strtod(__token, &endp, &errnum);   
+    if (errnum != 0 || *endp != '\0')
+     {
+      __pv_ferr(1314, "SDF real number %s illegal", __token);
+      d1 = 1.0;
+     }
+    __itok_realval = d1;
+    return(REALNUM);
+   }
+ /* integer number */
+ t1 = __my_strtoul(__token, &endp, &errnum);
+ if (errnum != 0 || *endp != '\0')
+  {
+   __pv_ferr(1315, "SDF integer number %s illegal", __token);
+   t1 = 1;
+  }
+ if (signv) t1 = -t1;
+ __sdf_tokval = t1;
+ return(NUMBER);
+}
+
+/*
+ * check and convert SDF path name (always . separator) to Verilog ID 
+ * returns F on error - caller must emit any error
+ *
+ * this builds the Verilog path ID that is converted to xmr expr later
+ * indices here extracted according to SDF format and convert to Verilog fmt
+ */
+static int32 chkcnv_sdfpath(char *verid, int32 *i1, int32 *i2, char *sdfid,
+ int32 allow_select)
+{
+ register char *chp, *chp2;
+ int32 ind1, ind2;
+ char s1[IDLEN], s2[RECLEN];
+
+ /* step 1: convert from rooted if needed */
+ if (*sdfid == __pathsep) 
+  {
+   __pv_fwarn(676,
+    "SDF leading %c removed from %s - SDF paths downward relative from context",
+    __pathsep, sdfid); 
+   sdfid++;  
+   if (*sdfid == __pathsep) return(FALSE);
+  }
+ /* check all but ending component of path */
+ strcpy(verid, "");
+ for (chp = sdfid; *chp != '\0';)
+  {
+   if ((chp2 = fnd_pth_sep(chp)) == NULL) break;
+
+   /* if path component starts with separator, illegal empty */
+   if (chp == chp2) return(FALSE);
+   strncpy(s1, chp, chp2 - chp);
+   s1[chp2 - chp] = '\0';
+   /* even in non select variable path, internal insts can have selects */
+   if (!chkcnv_sdfid(s2, &ind1, &ind2, s1, TRUE)) return(FALSE);
+
+   /* part select of instance array never allowed */
+   if (ind1 != ind2) return(FALSE);
+
+   /* add select back onto end as suffix if needed */
+   if (ind1 != -1) { sprintf(s1, "%s[%d]", s2, ind1); strcpy(s2, s1); }
+
+   if (strlen(verid) + strlen(s2) >= IDLEN - 2)
+    {
+toolong:
+     __pv_ferr(1368, "Verilog path name too long (%d)", IDLEN); 
+     return(FALSE);
+    }
+   if (*verid != '\0') strcat(verid, ".");
+   strcat(verid, s2);
+   chp = ++chp2;
+  }
+ /* s1 is path tail */
+ /* part select of tail may be legal */
+ /* add select back onto end as suffix if needed */
+ if (!chkcnv_sdfid(s1, i1, i2, chp, allow_select)) return(FALSE);
+
+ if (strlen(verid) + strlen(s1) >= IDLEN - 2) goto toolong;
+ if (*verid != '\0') strcat(verid, ".");
+ strcat(verid, s1);
+ return(TRUE);
+}
+
+/*
+ * find path separator - must skip over escaped
+ */
+static char *fnd_pth_sep(register char *chp)
+{
+ register char *chp2;
+
+again:
+ if ((chp2 = strchr(chp, __pathsep)) == NULL) return(NULL);
+ if (chp2 == chp) return(chp2);
+ if (chp2[-1] == '\\') { chp = ++chp2; goto again; } 
+ return(chp2);
+}
+
+/*
+ * check and convert SDF ID to Verilog ID (may need to be escaped)
+ * because of possible select this can fail - return F and caller emits error
+ *
+ * notice path separators here '.' or '/' are part of Verilog escaped IDs
+ * because if escaped as char will be embedded in sdfid
+ *
+ * know simple id (not a path)
+ * if called with path (non escaped separator(s)) in non path context
+ * becomes escaped ID and will probably not match Verilog 
+ */
+static int32 chkcnv_sdfid(char *verid, int32 *i1, int32 *i2, char *sdfid,
+ int32 allow_select)
+{
+ register char *chp, *chp2;
+ int32 nd_escver_id;
+ char s1[IDLEN], s2[IDLEN];
+
+ *i1 = *i2 = -1;
+ if (__id_select || __id_partsel)
+  {
+   /* here have qualified path where some component has select */
+   /* if not this one tread as non select */
+   if ((chp = strrchr(sdfid, '[')) == NULL)
+    {
+     strcpy(s1, sdfid);
+     goto comp_non_sel;
+    }
+   strcpy(s1, ++chp);
+   if (!sdf_getsel_indices(i1, i2, s1)) return(FALSE);
+   chp--;
+   strncpy(s1, sdfid, chp - sdfid);
+   s1[chp - sdfid] = '\0';
+   if (!allow_select) return(FALSE);
+  }
+ else strcpy(s1, sdfid);
+
+comp_non_sel:
+ nd_escver_id = FALSE;
+ if (isdigit(s1[0])) nd_escver_id = TRUE; 
+ for (chp = s1, chp2 = verid; *chp != '\0'; chp++) 
+  {
+   if (sdf_ctab[*chp & 0x7f] != 0) nd_escver_id = TRUE;
+   *chp2++ = *chp;
+   if (chp2 - verid >= IDLEN - 1)
+    {
+toolong:
+     __pv_ferr(1368, "Verilog identifier name too long (%d) - truncated",
+      IDLEN); 
+     break;
+    }
+  }
+ *chp2 = '\0';
+ if (nd_escver_id)
+  {
+   if (strlen(verid) + 2 >= IDLEN + 1)
+    { verid[IDLEN - 3] = '\0'; goto toolong; }
+   chp = s2;
+   *chp++ = '\\';
+   for (chp2 = verid; *chp2 != '\0';) 
+    {
+     if (*chp2 == '\\') { chp2++; continue; }
+     *chp++ = *chp2++;
+    }
+   *chp++ = ' ';
+   *chp = '\0';
+   strcpy(verid, s2);
+  }
+ return(TRUE);
+}
+
+/*
+ * extract range(s) from select part of sdf id - s starts with one past [
+ *
+ * because passed with real (non escaped) [ at start no escape checking needed
+ * escaped digit or escaped ] is error
+ */
+static int32 sdf_getsel_indices(int32 *i1, int32 *i2, char *s)
+{
+ register char *chp, *chp2;
+ char s1[RECLEN], s2[RECLEN];
+
+ *i1 = *i2 = -1;
+ /* check for illegal chars after ending ] */ 
+ if ((chp = strrchr(s, ']')) == NULL) __arg_terr(__FILE__, __LINE__);
+ chp++;
+ if (*chp != '\0' || chp[-1] == '\\') return(FALSE);
+ chp--;
+ strncpy(s1, s, chp - s);
+ s1[chp - s] = '\0';
+
+ /* extract 2nd range if present */
+ if (__id_partsel)
+  {
+   if ((chp = strchr(s1, ':')) == NULL) __arg_terr(__FILE__, __LINE__);
+   chp++;
+   strcpy(s2, chp);
+   chp--;
+   chp--;
+   *chp = '\0';
+   /* 2nd index in s2 */
+   for (chp2 = s2; *chp2 != '\0'; chp2++)
+    {
+     if (!isdigit(*chp2)) return(FALSE);
+    }
+   if (sscanf(s2, "%d", i2) != 1) return(FALSE);
+  }
+ /* extract first range - know it is in s1 */
+ /* first index in s1 */
+ for (chp2 = s1; *chp2 != '\0'; chp2++)
+  {
+   if (!isdigit(*chp2)) return(FALSE);
+  }
+ if (sscanf(s1, "%d", i1) != 1) return(FALSE);
+ if (!__id_partsel) *i2 = *i1;
+ return(TRUE);
+}
+
+/*
+ * after reading ([name] form - skip to matching )
+ * returns F on no match before eof
+ */
+static int32 sdf_skip_form(FILE *f)
+{
+ register int32 par_cnt = 0;
+
+ for (;;)
+  {
+   get_sdftok(f);
+   if (__toktyp == RPAR) { if (--par_cnt < 0) break; }
+   if (__toktyp == LPAR) par_cnt++;
+   if (__toktyp == TEOF) return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * read an SDF edge - if edge returns edge number else -1
+ * if returns -1 sets __toktyp and __token as if normal ID read
+ * 
+ * this must read chars since not normal tokens
+ * timing checks allow edge expressions but not paths
+ * only called in places where operators illegal
+ */
+static int32 rd_edge_ident(FILE *f)
+{
+ register char *cp;
+ int32 c, ctval, len;
+
+ /* skip white space */
+ do { ctval = sdf_ctab[(c = getc(f)) & 0x7f]; } while (ctval == 1);
+ if (ctval != 0)
+  {
+   __pv_ferr(1345,
+    "possible EDGE_IDENTIFIER starting character %c (%x) illegal",
+    c, c);
+   return(-1);
+  }
+ /* collect non white space chars */
+ for (cp = __token, len = 0;;)  
+  {
+   *cp++ = c;
+   if (++len >= IDLEN)
+    {
+     __pv_ferr(1347, "EDGE_IDENTIFIER too many characters (%d)", IDLEN);
+     return(-1);
+    }
+   ctval = sdf_ctab[(c = getc(f)) & 0x7f];
+   if (ctval != 0) { ungetc(c, f); break; }  
+  }
+ *cp = '\0';
+ if (strcmp(__token, "posedge") == 0) return(E_POSEDGE);
+ if (strcmp(__token, "negedge") == 0) return(E_NEGEDGE);
+ if (strcmp(__token, "01") == 0) return(EDGE01);
+ if (strcmp(__token, "10") == 0) return(EDGE10);
+ if (strcmp(__token, "0x") == 0) return(EDGE0X);
+ if (strcmp(__token, "x1") == 0) return(EDGEX1);
+ if (strcmp(__token, "1x") == 0) return(EDGE1X);
+ if (strcmp(__token, "x0") == 0) return(EDGEX0);
+ __toktyp = get_sdfkeywrd(__token);
+ return(-1);
+}
+
+/*
+ * read an SDF cond scalar constant - returns val (-1 on error)
+ * 
+ * needed because ' in constants not defined in SDF
+ * this must read chars since not normal tokens
+ * this expect nothing read and reads just to end of constant
+ */
+static int32 rd_scalar_const(FILE *f)
+{
+ int32 c, ctval;
+
+ /* skip white space */
+ do { ctval = sdf_ctab[(c = getc(f)) & 0x7f]; } while (ctval == 1);
+ if (c == '1')
+  {
+   /* SJM 01/24/02 - was not reading next c so only 1'b0 and 1'b1 wrong err */ 
+   c = getc(f) & 0x7f;
+   if (c == '\'')
+    {
+do_base:
+     c = getc(f);
+     if (c != 'b' && c != 'B') goto bad_scalar;
+     c = getc(f);
+     /* wrong following char caught by next get token call */
+     if (c == '0') return(0);
+     if (c == '1') return(1);
+     goto bad_scalar;
+    }
+   if (c == '0') return(0);
+   if (c == '1') return(1);
+   goto bad_scalar;
+  }
+ if (c == '\'') goto do_base;  
+
+bad_scalar:
+ __pv_ferr(1355, "SCALAR_CONSTANT illegal - %c (%x) bad", c, c);
+ return(-1);
+}
+
+/*
+ * print a sdf token
+ *
+ * uses prt vtok since value in __token value except for number or real num.
+ */
+static char *prt_sdftok(void)
+{
+ /* notice this must not change current val. of token */
+ if (__toktyp >= SDF_BKEYS)
+  { get_skeynam(__sdf_varnam, __toktyp); return(__sdf_varnam); }
+
+ switch ((byte) __toktyp) {
+  case TEOF: strcpy(__token, "**EOF**"); break;
+  case ID: return(__token);
+  /* must recreate because sign may be missing */
+  case NUMBER: sprintf(__token, "%d", __sdf_tokval); break;
+  case REALNUM: sprintf(__token, "%#g", __itok_realval); break;
+  case LITSTR: return(__token);
+  case COLON: strcpy(__token, ":"); break;
+  case SHARP: strcpy(__token, "#"); break;
+  case SDF_DOL: strcpy(__token, "$"); break; 
+
+  /* SJM - 05/14/01 - next 2 illegal but needed for error msg */
+  case SDF_BACKQ: strcpy(__token, "`"); break; 
+  case SDF_QUOTE: strcpy(__token, "'"); break; 
+
+  case COMMA: strcpy(__token, ","); break;
+  case LCB: strcpy(__token, "{"); break; 
+  case RCB: strcpy(__token, "}"); break;
+  case QUEST: strcpy(__token, "?"); break;
+  case LSB: strcpy(__token, "["); break;
+  case RSB: strcpy(__token, "]"); break;
+  case LPAR: strcpy(__token, "("); break;
+  case RPAR: strcpy(__token, ")"); break; 
+  case PLUS: strcpy(__token, "+"); break; 
+  case MINUS: strcpy(__token, "-"); break;
+  case TIMES: strcpy(__token, "*"); break;
+  case DIV: strcpy(__token, "/"); break; 
+  case MOD: strcpy(__token, "%"); break; 
+  case BITNOT: strcpy(__token, "~"); break; 
+  case REDXNOR: strcpy(__token, "^~"); break;
+  case BOOLAND: strcpy(__token, "&&"); break;
+  case BITREDAND: strcpy(__token, "&"); break;
+  case BOOLOR: strcpy(__token, "||"); break; 
+  case BITREDOR: strcpy(__token, "|"); break;
+  case BITREDXOR: strcpy(__token, "^"); break; 
+  case RELEQ: strcpy(__token, "=="); break;
+  case RELCEQ: strcpy(__token, "==="); break; 
+  case NOT: strcpy(__token, "!"); break;
+  case RELNEQ: strcpy(__token, "!="); break;  
+  case RELCNEQ: strcpy(__token, "!=="); break;
+  case RELGE: strcpy(__token, ">="); break;
+  case SHIFTR: strcpy(__token, ">>"); break;
+  case ASHIFTR: strcpy(__token, ">>>"); break;
+  case RELGT:  strcpy(__token, ">"); break;
+  case RELLE: strcpy(__token, "<="); break;
+  case SHIFTL: strcpy(__token, "<<"); break;
+  case ASHIFTL: strcpy(__token, "<<<"); break;
+  case RELLT: strcpy(__token, "<"); break;
+  case UNDEF: strcpy(__token, "**NONE**"); break; 
+  case BADOBJ: strcpy(__token, "**ILLEGAL**"); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(__token);
+}
+
+/* keyword types (already know token is a name) */
+struct sdfkeywds_t {
+ char *sknam;
+ int32 sknum;
+};
+
+/* since sharing operators for expr. processing with Verilog, first > 99 */
+/* BEWARE - must be kept in alphabetical order */
+static struct sdfkeywds_t skeywds[] = {
+ { "ABSOLUTE", SDF_ABSOLUTE },
+ { "ARRIVAL", SDF_ARRIVAL },
+ { "CCOND", SDF_CCOND },
+ { "CELL", SDF_CELL },
+ { "CELLTYPE", SDF_CELLTYPE },
+ { "COND", SDF_COND },
+ { "CONDELSE", SDF_CONDELSE },
+ { "DATE", SDF_DATE },
+ { "DELAY", SDF_DELAY },
+ { "DELAYFILE", SDF_DELAYFILE },
+ { "DEPARTURE", SDF_DEPARTURE },
+ { "DESIGN", SDF_DESIGN },
+ { "DEVICE", SDF_DEVICE },
+ { "DIFF", SDF_DIFF },
+ { "DIVIDER", SDF_DIVIDER },
+ { "EXCEPTION", SDF_EXCEPTION },
+ { "FULLSKEW", SDF_FULLSKEW },
+ { "HOLD", SDF_HOLD },
+ { "INCREMENT", SDF_INCREMENT },
+ { "INSTANCE", SDF_INSTANCE },
+ { "INTERCONNECT", SDF_INTERCONNECT },
+ { "IOPATH", SDF_IOPATH },
+ { "LABEL", SDF_LABEL },
+ { "NAME", SDF_NAME },
+ { "NOCHANGE", SDF_NOCHANGE },
+ { "PATHCONSTRAINT", SDF_PATHCONSTRAINT },
+ { "PATHPULSE", SDF_PATHPULSE },
+ { "PATHPULSEPERCENT", SDF_PATHPULSEPERCENT },
+ { "PERIOD", SDF_PERIOD },
+ { "PERIODCONSTRAINT", SDF_PERIODCONSTRAINT },
+ { "PORT", SDF_PORT },
+ { "PROCESS", SDF_PROCESS },
+ { "PROGRAM", SDF_PROGRAM },
+ { "RECOVERY", SDF_RECOVERY },
+ { "RECREM", SDF_RECREM },
+ { "REMOVAL", SDF_REMOVAL },
+ { "RETAIN", SDF_RETAIN },
+ { "SCOND", SDF_SCOND },
+ { "SDFVERSION", SDF_VERSION }, 
+ { "SETUP", SDF_SETUP }, 
+ { "SETUPHOLD", SDF_SETUPHOLD }, 
+ { "SKEWCONSTRAINT", SDF_SKEWCONSTRAINT },
+ { "SLACK", SDF_SLACK },
+ { "SKEW", SDF_SKEW }, 
+ { "SUM", SDF_SUM }, 
+ { "TEMPERATURE", SDF_TEMPERATURE },
+ { "TIMESCALE", SDF_TIMESCALE },
+ { "TIMESKEW", SDF_TIMESKEW },
+ { "TIMINGCHECK", SDF_TIMINGCHECK },
+ { "TIMINGENV", SDF_TIMINGENV },
+ { "VENDOR", SDF_VENDOR },
+ { "VERSION", SDF_VERSION },
+ { "VOLTAGE", SDF_VOLTAGE },
+ { "WAVEFORM", SDF_WAVEFORM },
+ { "WIDTH", SDF_WIDTH },
+ { "negedge", SDF_NEGEDGE },
+ { "posedge", SDF_POSEDGE }
+};
+#define NSKEYWDS (sizeof(skeywds) / sizeof(struct sdfkeywds_t))
+
+/*
+ * determine type of keyword or ident
+ * binary search because the table is so big
+ */
+static int32 get_sdfkeywrd(register char *tstr)
+{
+ int32 l, h;
+ register int32 m, cv;
+
+ l = 0; h = NSKEYWDS - 1;
+ for (;;)
+  {
+   m = (l + h)/2;
+   if ((cv = strcmp(skeywds[m].sknam, tstr)) == 0) return(skeywds[m].sknum);
+   if (cv < 0) l = m + 1; else h = m - 1;
+   if (h < l) break;
+  }
+ return(ID);
+}
+
+/*
+ * determine keyword name from number
+ * must use linear search since not sorted
+ */
+static char *get_skeynam(char *s, int32 knum)
+{
+ register int32 vi;
+
+ for (vi = 0; vi < NSKEYWDS; vi++)
+  {
+   if (skeywds[vi].sknum == knum)
+   {
+    strcpy(s, skeywds[vi].sknam);
+    return(s);
+   }
+  }
+ strcpy(s, "--none--");
+ return(s);
+}
diff --git a/src/v_sim.c b/src/v_sim.c
new file mode 100644
index 0000000..0c0e369
--- /dev/null
+++ b/src/v_sim.c
@@ -0,0 +1,7137 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * Verilog simulation routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <signal.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+
+/* local prototypes */
+static void process_pnd0s(void);
+static void exec_slotend_dv(void);
+static void process_all_netchgs(void);
+static void free_chgedvars(void);
+static void eval_netchg_lds(register struct net_t *, int32, int32, int32);
+static void process_mipd_nchg_ev(register struct tev_t *);
+static void emit_nchglds_trmsg(struct net_t *, struct net_pin_t *);
+static int32 is2_chg_match(int32, int32, int32);
+static void std_chg_logic_gate(register struct gate_t *, register word32);
+static void acc_chg_bufnot(struct gate_t *, word32);
+static void acc_stichg_bufnot(register struct gate_t *, word32);
+static void acc_chg_4igate(register struct gate_t *, word32);
+static void acc_stichg_4igate(register struct gate_t *, word32);
+static void trace_gunchg(struct gate_t *, word32);
+static void std_chg_udp_gate(register struct gate_t *, register word32);
+static void std_chg_bufif_gate(register struct gate_t *, register word32);
+static void std_chg_mos_gate(register struct gate_t *, register word32);
+static void std_chg_cmos_gate(register struct gate_t *, register word32);
+static void prop_gatechg(register struct gate_t *, register int32, int32);
+static void evtr_prop_gatechg(register struct gate_t *, register word32,
+ int32);
+static word32 get_showcancele_val(struct gate_t *);
+static i_tev_ndx schedule_1gev(register struct gate_t *, word64, word64, int32);
+static i_tev_ndx reschedule_1gev(i_tev_ndx, word64, word64, word32, int32);
+static void emit_pulsewarn(struct gate_t *, struct tev_t *, word64 *,
+ word64 *, char *);
+static void process_gatechg_ev(register struct tev_t *);
+static void acc_evchg_gate_outwire(register struct gate_t *);
+static void emit_gev_trace(struct gate_t *, struct tev_t *);
+static void change_gate_outwire(register struct gate_t *);
+static void trace_chg_gateout(struct gate_t *, struct expr_t *);
+static void gate_st_bit(union pck_u, int32, int32, int32, register word32,
+ register word32);
+static void gate_st_scalval(register word32 *, register word32, register word32);
+static int32 chg_mos_instate(register struct gate_t *, word32);
+static int32 chg_cmos_instate(register struct gate_t *, word32);
+static void eval_tranif_onoff(struct gate_t *);
+static void evtr_eval_conta_rhs_ld(struct net_pin_t *);
+static void schedule_1caev(struct conta_t *, word64, word64, struct xstk_t *);
+static void reschedule_1caev(i_tev_ndx, word64, word64, struct xstk_t *);
+static void process_conta_ev(register struct tev_t *tevp);
+static void process_wire_ev(register struct tev_t *tevp);
+static void process_nbpa_ev(struct tev_t *tevp);
+static int32 force_inhibit_wireassign(struct net_t *, register int32,
+ struct itree_t *);
+static void process_trpthdst_ev(register struct tev_t *);
+static int32 filter_edge_expr(register struct dce_expr_t *, register word32 *,
+ register word32 *);
+static void trigger_evctrl(struct delctrl_t *, register i_tev_ndx);
+static int32 stfilter_dce_chg(register struct net_t *,
+ register struct dcevnt_t *, word32 *, word32 *, int32);
+static int32 vccb_vec_standval_filter(register struct net_t *,
+ register struct dcevnt_t *, word32 *, word32 *, int32);
+static int32 vccb_scal_standval_filter(register struct net_t *,
+ register struct dcevnt_t *, word32 *, word32 *, int32);
+static int32 filter_dce_chg(register struct net_t *, register struct dcevnt_t *,
+ word32 *, word32 *, int32);
+static int32 scal_stfilter_dce_chg(register struct net_t *,
+ register struct dcevnt_t *, word32 *, word32 *, int32);
+static void bld_xmrsrc_ref(char *, struct net_t *);
+static void bld_srcfilter_ref(char *, word32, word32, struct expr_t *);
+static int32 filter_bitchange(register word32, register byte *,
+ register word32, struct expr_t *);
+static void add_tchk_chged(struct chktchg_t *);
+static void process_all_tchk_violations(void);
+static void process_notify(struct net_t *);
+static char *bld_tchk_srcdump(char *, struct tchk_t *, word64 *, word64 *,
+ word64 *, word64 *);
+static void init_stime(void);
+static void reinit_stime(void);
+static void init_wires(void);
+static void init_itinsts(struct itree_t *);
+static void init_sched_thd(struct mod_t *);
+static void gate_initeval(struct gate_t *);
+static void init_udp(struct gate_t *);
+static void init_logic_gate(struct gate_t *);
+static void init_bufif_gate(struct gate_t *);
+static void init_tranif_gate(struct gate_t *);
+static void conta_initeval(struct conta_t *, struct conta_t *);
+static int32 move_to_time0(void);
+static int32 move_time(void);
+static void chk_event_consist(void);
+static void add_ovfetim(word64, i_tev_ndx, struct tev_t *);
+static struct bt_t *alloc_btnod(int32);
+static struct bt_t *find_fringe(word64);
+static struct bt_t *insert_fringe(struct bt_t *, word64, i_tev_ndx);
+static void splitinsert_nonfringe(void);
+static void ovflow_into_wheel(void);
+static void divide_fringe_node(struct bt_t *);
+static void divide_internal_node(struct bt_t *);
+static void remove_empty_upwards(void);
+static void mv_subtree_towheel(struct bt_t *);
+static void mv_to_wheel(word64, struct telhdr_t *);
+static struct telhdr_t *tfind_btnode_after(struct bt_t *, word64);
+static void dmp_twheel(void);
+static int32 dmp_events(register i_tev_ndx);
+static void dmp_btree(struct bt_t *);
+static void dmp2_btree(struct bt_t *, int32);
+static void dmp_btnode(struct bt_t *, int32);
+static char *to_evtronam(char *, char *, struct itree_t *, struct task_t *);
+/* SJM UNUSED static void chk_schd_dces(void); */
+static void chk_tev_list(register i_tev_ndx);
+
+/* extern prototypes defined elsewhere */
+extern void __pv_sim(void);
+extern void __get_cor_range(register int32, union intptr_u, register int32 *,
+ register int32 *);
+extern void __set_gchg_func(struct gate_t *);
+extern void __vpi_set_chg_proc(struct gate_t *);
+extern int32 __gate_is_acc(struct gate_t *);
+extern void __add_nchglst_el(register struct net_t *);
+extern void __add_dmpv_chglst_el(struct net_t *);
+extern void __eval_conta_rhs_ld(register struct net_pin_t *);
+extern void __eval_tranif_ld(register struct gate_t *, register int32);
+extern void __add_select_nchglst_el(register struct net_t *, register int32,
+ register int32);
+extern void __wakeup_delay_ctrls(register struct net_t *, register int32,
+ register int32);
+extern void __process_npp_timofchg(struct net_t *,
+ register struct net_pin_t *);
+
+extern char *__to_evtrcanam(char *, struct conta_t *, struct itree_t *);
+extern void __evtr_resume_msg(void);
+extern void __process_getpat(struct conta_t *);
+extern char *__to_evtrwnam(char *, struct net_t *, int32, int32,
+ struct itree_t *);
+extern char *__to_evtrpnam(char *, struct mod_pin_t *, int32,
+ struct itree_t *);
+extern void __init_sim(void);
+extern void __reinit_sim(void);
+extern void __insert_event(register i_tev_ndx);
+extern void __free_btree(struct bt_t *);
+extern void __free_telhdr_tevs(register struct telhdr_t *);
+extern void __free_1tev(i_tev_ndx);
+extern void __free_xtree(struct expr_t *);
+extern void __call_misctfs_simstart(void);
+extern void __vpi_startsim_trycall(void);
+extern void __call_misctfs_endreset(void);
+extern void __vpi_endreset_trycall(void);
+extern void __do_interactive_loop(void);
+extern void __process_thrd_ev(register struct tev_t *);
+extern char *__to_timstr(char *, word64 *);
+extern void __setdel_call_misctf(i_tev_ndx);
+extern void __process_putpdel_ev(i_tev_ndx);
+extern void __process_vpidrv_ev(i_tev_ndx);
+extern void __process_vpi_varputv_ev(i_tev_ndx);
+extern void __delay_callback(i_tev_ndx);
+extern void __sync_call_misctf(struct tev_t *);
+extern void __exec_monit(struct dceauxlst_t *, int32);
+extern void __exec_fmonits(void);
+extern void __exec_strobes(void);
+extern void __exec_rosync_misctf(void);
+extern void __vpi_del_rosync_call(void);
+extern void __vpi_del_nxtsimtim_trycall(void);
+extern void __do_dmpvars_baseline(char *);
+extern void __turnoff_all_dumpvars(void);
+extern void __turnon_all_dumpvars(void);
+extern void __do_dmpvars_chg(void);
+extern int32 __tilde_creat(char *);
+extern int32 __my_creat(char *);
+extern void __setup_dmpvars(void);
+extern int32 __move_to_npprefloc(struct net_pin_t *);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_tetyp(char *, word32);
+extern char *__var_tostr(char *, struct net_t *, int32, int32, int32);
+extern char *__to_npptyp(char *, struct net_pin_t *);
+extern int32 __eval_logic_gate(struct gate_t *, word32, int32 *);
+extern void __ld_bit(register word32 *, register word32 *,
+ register struct net_t *, int32);
+extern int32 __correct_forced_newwireval(struct net_t *, word32 *, word32 *);
+extern int32 __forced_inhibit_bitassign(struct net_t *, struct expr_t *,
+ struct expr_t *);
+extern void __chg_st_bit(struct net_t *, int32, register word32, register word32);
+extern word32 __wrd_redxor(word32);
+extern int32 __eval_udp(register struct gate_t *, word32, int32 *, int32);
+extern int32 __eval_bufif_gate(register struct gate_t *, word32, int32 *);
+extern void __eval_pmos_gate(register word32);
+extern void __eval_rpmos_gate(register word32);
+extern void __eval_nmos_gate(register word32);
+extern void __eval_rnmos_gate(register word32);
+extern void __eval_cmos_gate(struct gate_t *);
+extern int32 __get_acc_class(struct gate_t *);
+extern void __hizstrengate_getdel(word64 *, register struct gate_t *);
+extern void __get_del(register word64 *, register union del_u, word32);
+extern int32 __em_suppr(int32);
+extern char *__to_ginam(char *, struct gate_t *, word32, int32);
+extern char *__to_gonam(char *, struct gate_t *, word32);
+extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
+extern char *__schop(char *, char *);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern void __mdr_assign_or_sched(register struct expr_t *);
+extern void __exec_conta_assign(struct expr_t *, register word32 *,
+ register word32 *, int32);
+extern char *__gstate_tostr(char *, struct gate_t *, int32);
+extern void __immed_eval_trifchan(struct gate_t *);
+extern char *__to_gassign_str(char *, struct expr_t *);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern void __lhsbsel(register word32 *, register int32, word32);
+extern struct xstk_t *__ndst_eval_xpr(struct expr_t *);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern void __sgn_xtnd_widen(struct xstk_t *, int32);
+extern void __sizchg_widen(register struct xstk_t *, int32);
+extern void __narrow_sizchg(register struct xstk_t *, int32);
+extern void __fix_widened_toxs(register struct xstk_t *, int32);
+extern void __st_perinst_val(union pck_u, int32, register word32 *,
+ register word32 *);
+extern void __grow_xstk(void);
+extern void __grow_tevtab(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __st_standval(register byte *, register struct xstk_t *, byte);
+extern void __stren_exec_ca_concat(struct expr_t *, byte *, int32);
+extern void __exec_ca_concat(struct expr_t *, register word32 *,
+ register word32 *, int32);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern int32 __vval_is1(register word32 *, int32);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern char *__st_regab_tostr(char *, byte *, int32);
+extern char *__bld_lineloc(char *, word32, int32);
+extern void __my_free(char *, int32);
+extern char *__my_malloc(int32);
+extern char *__my_realloc(char *, int32 , int32);
+extern char *__to_vvnam(char *, word32);
+extern char *__xregab_tostr(char *, word32 *, word32 *, int32, struct expr_t *);
+extern void __exec2_proc_assign(struct expr_t *, register word32 *,
+ register word32 *);
+extern int32 __unnormalize_ndx(struct net_t *, int32);
+extern char *__to_mpnam(char *, char *);
+extern void __eval_tran_1bit(register struct net_t *, register int32);
+extern int32 __match_push_targ_to_ref(word32, struct gref_t *);
+extern void __assign_qcaf(struct dcevnt_t *);
+extern void __pvc_call_misctf(struct dcevnt_t *);
+extern void __cbvc_callback(struct cbrec_t *, struct h_t *);
+extern void __exec_vpi_gateoutcbs(int32);
+extern void __add_ev_to_front(register i_tev_ndx);
+extern int32 __get_dcewid(struct dcevnt_t *, struct net_t *);
+extern void __ld_wire_sect(word32 *, word32 *, struct net_t *, register int32,
+ register int32);
+extern void __ld_wire_val(register word32 *, register word32 *, struct net_t *);
+extern char *__to_tcnam(char *, word32);
+extern void __vpi_tchkerr_trycall(struct tchk_t *, struct itree_t *);
+extern void __chg_st_val(struct net_t *, register word32 *, register word32 *);
+extern void __adds(char *);
+extern void __chg_xprline_size(int32);
+extern char *__to_edgenam(char *, word32);
+extern void __trunc_exprline(int32, int32);
+extern char *__pv_stralloc(char *);
+extern void __init_interactive(void);
+extern void __my_fclose(FILE *);
+extern void __init_all_trchans(void);
+extern void __init_instdownport_contas(struct itree_t *, struct itree_t *);
+extern void __init_instupport_contas(struct itree_t *);
+extern struct thread_t *__alloc_thrd(void);
+extern void __ld_perinst_val(register word32 *, register word32 *, union pck_u,
+ int32);
+extern int32 __sim_sigint_handler(void);
+extern void __dmp_event_tab(void);
+extern void __dmp1_nplstel(struct mod_t *, struct net_t *, struct net_pin_t *);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern void __sched_mipd_nchg(struct net_t *, int32, struct mipd_t *);
+extern void __exec_var_decl_init_assigns(void);
+
+extern void __cv_msg(char *, ...);
+extern void __cvsim_msg(char *, ...);
+extern void __tr_msg(char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __pv_err(int32, char *, ...);
+extern void __pv_warn(int32, char *,...);
+extern void __gfwarn(int32, word32, int32, char *, ...);
+extern void __pv_terr(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __ia_warn(int32, char *, ...);
+extern void __my_fprintf(FILE *, char *, ...);
+
+extern word32 __masktab[];
+extern byte __stren_map_tab[];
+extern byte __hizstren_del_tab[];
+
+/*
+ * ROUTINES TO RUN SIMULATION
+ */
+
+/*
+ * actually run the simulation
+ * need better way to handle p0 (events that must go at end) queue
+ *
+ * LOOKATME - set up so never check entering interact unless one event
+ * processed (except -s entry before start of sim)
+ */
+extern void __pv_sim(void)
+{
+ register struct tev_t *tevp;
+ i_tev_ndx tevp2i;
+ struct tev_t *tevp2;
+
+ /* unless quiet mode, need blank line before sim writing */
+ __cv_msg("\n");
+ /* possible that no events scheduled at 0, must really move time to 0 */
+ /* this assumes wrap works ? */
+ __simtime = 0xffffffffffffffffULL;
+ __cur_twi = -1;
+
+ /* move time to 0 */
+ move_to_time0();
+
+ /* now have timing wheel - can run vpi sim controls that are like */
+ /* system task execs */
+ __can_exec = TRUE;
+
+ /* do not call vpiStartOfSim routine if resetting */
+ if (__now_resetting)
+  {
+   __now_resetting = FALSE;
+   if (__tfrec_hdr != NULL) __call_misctfs_endreset();
+   if (__have_vpi_actions) __vpi_endreset_trycall();
+
+   /* if no events after reset - nothing to do so terminate */
+   if (__num_twhevents == 0 && __btqroot == NULL && __cur_te_hdri == -1
+     && __p0_te_hdri == -1)
+    {
+     __pv_warn(614,
+     "no pending statements or events after reset to time 0 - nothing to do");
+     return;
+    }
+  }
+ else
+  {
+   /* no sim (variables) d.s. and time before here */
+   /* notice these routines cannot cause inside entry of debugger */
+   /* so can call from here - just scan and register */
+   if (__tfrec_hdr != NULL) __call_misctfs_simstart();
+   if (__have_vpi_actions) __vpi_startsim_trycall();
+
+   /* if no events after initializationand PLI start of sim - nothing to do */
+   if (__num_twhevents == 0 && __btqroot == NULL && __cur_te_hdri == -1
+     && __p0_te_hdri == -1)
+    {
+     __pv_warn(614,
+      "no pending statements or events after initialization - nothing to do");
+     return;
+    }
+  }
+
+ /* enter immediately if -s option, . here just starts sim */
+ __cur_tevpi = -1;
+
+ /* if this is at least 100 entering from debugger reset */
+ if (__dbg_stop_before >= 100)
+  {
+   if (__dbg_stop_before != 101) { __dbg_stop_before = 0; goto no_stop; }
+   __dbg_stop_before = 0;
+   goto stop;
+  }
+
+ /* else use -s option to decide if stop before sim */
+ if (__stop_before_sim)
+  {
+   /* if no interactive ignore stop before sim with warning */
+   if (__no_iact)
+    {
+     __pv_warn(628,
+      "-s option ignored - +nointeractive disabled interactive mode");
+     goto no_stop;
+    }
+stop:
+   /* interactive loop expects int32 (^c) signal to be ignored */
+   __do_interactive_loop();
+  }
+
+no_stop:
+ /* set up during simulation control c signal handler - can set flag only */
+#if defined(INTSIGS)
+ signal(SIGINT, __sim_sigint_handler);
+#else
+ signal(SIGINT, (void (*)()) __sim_sigint_handler);
+#endif
+
+ /* SJM 09/30/04 - execute all new Verilog 2001 variable decl assigns */
+ /* as the first step in simulation - do not need any events */
+ /* SJM 09/30/04 - LOOKATME - could build and schedule separate init block */
+ __exec_var_decl_init_assigns();
+
+ /* repeat this loop for every time */
+ __processing_pnd0s = FALSE;
+ for (;;)
+  {
+   /* execute events until current time event list empty */
+   /* events never added here (maybe to pound 0) */
+   __cur_tevpi = __cur_te_hdri;
+   for (; __cur_tevpi != -1; __cur_tevpi = __tevtab[__cur_tevpi].tenxti)
+    {
+     tevp = &(__tevtab[__cur_tevpi]);
+     /* canceled because of inertial delay reschedule */
+     if (tevp->te_cancel)
+      { __num_cancel_tevents++; __num_twhevents--; continue; }
+
+     /* every event has associated itree element */
+     __push_itstk(tevp->teitp);
+     /* notice before event executed, cur. itp set from event */
+     switch ((byte) tevp->tetyp) {
+      case TE_THRD:
+       __process_thrd_ev(tevp);
+       break;
+      /* for gates and 1 bit continous assigns */
+      case TE_CA: process_conta_ev(tevp); break;
+      case TE_G: process_gatechg_ev(tevp); break;
+      case TE_WIRE: process_wire_ev(tevp); break;
+      case TE_BIDPATH: process_trpthdst_ev(tevp); break;
+      case TE_MIPD_NCHG: process_mipd_nchg_ev(tevp); break;
+      case TE_NBPA:
+       /* 10/27/00 SJM - this is rhs delay that has elapsed - never rep form */
+       /* non blocking proc assign, jump to #0 queue to process */
+       alloc_tev_(tevp2i, TE_NBPA, tevp->teitp, __simtime);
+       /* this moves entire nb records - since not needed here */
+       tevp2 = &(__tevtab[tevp2i]);
+       /* if present ptr to constant index lhs expr. copy also copied */
+       tevp2->tu.tenbpa = tevp->tu.tenbpa;
+       tevp->tu.tenbpa = NULL;
+       __num_proc_tevents--;
+       /* notice tevp not counted and contents freed */
+       /* AIV 06/28/05 - if option set add to the end of the nb #0 list */
+       if (!__nb_sep_queue)
+        {
+         if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevp2i;
+         else
+          {
+           __tevtab[__p0_te_endi].tenxti = tevp2i;
+           __p0_te_endi = tevp2i;
+          }
+        }
+       else
+        {
+         /* AIV 07/05/05 - to match XL need nb te list that only processed */
+         /* when all pnd 0 done effectively adds another section to current */
+         /* time event queue */
+         if (__nb_te_hdri == -1) __nb_te_hdri = __nb_te_endi = tevp2i;
+         else
+          { __tevtab[__nb_te_endi].tenxti = tevp2i; __nb_te_endi = tevp2i; }
+        }
+       break;
+      case TE_TFSETDEL:
+       /* RELEASE remove ---
+       if (__debug_flg && __ev_tracing)
+        {
+         __tr_msg("-- processing tf_ set delay misctf call at %s\n",
+  	  __to_timstr(__xs, &__simtime));
+        }
+       --- */
+       __setdel_call_misctf(__cur_tevpi);
+       break;
+      case TE_TFPUTPDEL: __process_putpdel_ev(__cur_tevpi); break;
+      case TE_VPIPUTVDEL: __process_vpi_varputv_ev(__cur_tevpi); break;
+      case TE_VPIDRVDEL: __process_vpidrv_ev(__cur_tevpi); break;
+      case TE_VPICBDEL: __delay_callback(__cur_tevpi); break;
+      /* sync event only pound 0 */
+      default: __case_terr(__FILE__, __LINE__);
+     }
+     __num_proc_tevents++;
+     __num_twhevents--;
+     __pop_itstk();
+
+     /* DBG remove - notice between events itree stack must be empty ---
+     if (__itspi != -1) __misc_terr(__FILE__, __LINE__);
+     --- */
+
+     /* notice adding to front adds after current which is really done */
+     /* see if pending control c, if add to front, next is right header */
+     if (__pending_enter_iact) __do_interactive_loop();
+    }
+
+   /* done with normal events, free and remove from time wheel */
+   if (__cur_te_hdri != -1)
+    {
+     __tevtab[__cur_te_endi].tenxti = __tefreelsti;
+     __tefreelsti = __cur_te_hdri;
+     __twheel[__cur_twi]->te_hdri = -1;
+     __twheel[__cur_twi]->num_events = 0;
+     __cur_te_hdri = __cur_te_endi = -1;
+    }
+
+   process_pnd0s();
+
+   /* AIV 07/05/05 - added processing of separate after all pnd0's non */
+   /* blocking events processing nb events can add new pnd0's that are */
+   /* processed as added and new nb's that are saved and added to do */
+   /* after all current level nbs and pnd0s done */
+   if (__nb_te_hdri != -1)
+    {
+     for (;;)
+      { 
+       __p0_te_hdri = __nb_te_hdri; 
+       __p0_te_endi = __nb_te_endi;
+       __nb_te_hdri = __nb_te_endi = -1;
+
+       /* notice the move to pnd 0 queue events add to free list in */
+       /* process pnd0 routine */
+       process_pnd0s();
+       if (__nb_te_hdri == -1) break;
+     }
+    }
+   /* --- DBG remove
+   if (__debug_flg && __ev_tracing
+    && (__nchg_futhdr != NULL || __p0_te_hdri != -1))
+     __tr_msg("-- processing #0 end of slot events\n");
+   --- */
+
+   /* final step do slot end timing checks and monitoring */
+   /* cannot schedule any events from here */
+   if (__slotend_action != 0)
+    {
+     if ((__slotend_action & SE_TCHK_VIOLATION) != 0)
+      process_all_tchk_violations();
+     if ((__slotend_action & SE_DUMPVARS) != 0) exec_slotend_dv();
+     if (__monit_active && ((__slotend_action
+      & (SE_MONIT_TRIGGER | SE_MONIT_CHG)) != 0))
+      __exec_monit(__monit_dcehdr,
+       (int32) (__slotend_action & SE_MONIT_CHG) != 0);
+
+     /* LOOKATME - should monitoroff (on) effect fmonitor (think no) */
+     if ((__slotend_action & SE_FMONIT_TRIGGER) != 0) __exec_fmonits();
+     if ((__slotend_action & SE_STROBE) != 0) __exec_strobes();
+     if ((__slotend_action & SE_TFROSYNC) != 0) __exec_rosync_misctf();
+     if ((__slotend_action & SE_VPIROSYNC) != 0) __vpi_del_rosync_call();
+     __slotend_action = 0;
+    }
+   /* contrl c here serviced at beginning of next time slot */
+   /* if no more events done */
+   if (!move_time()) break;
+
+   /* call backs from vpi cb NextSimTime (after debugger entered) */
+   if (__have_vpi_actions) __vpi_del_nxtsimtim_trycall();
+  }
+}
+
+/*
+ *  process all net changes - this can only enter pnd0 events at now
+ * next process net changes, if any new pnd0's process
+ * may then add new net changes that in turn can add pnd0's
+ * if no 0 delay loop (must catch) will eventually terminate
+ * can add normal delays but will occur in future
+ */
+static void process_pnd0s(void)
+{
+ register struct tev_t *tevp;
+
+ for (__processing_pnd0s = TRUE, __cur_tevpi = -1;;)
+  {
+   if (__nchg_futhdr != NULL) process_all_netchgs();
+
+   /* needed in case PLI tf_dostop or vpi_control(vpiStop called */
+   if (__pending_enter_iact) __do_interactive_loop();
+
+   /* no pending net changes and no more pound 0 events, can move time */
+   if (__p0_te_hdri == -1) break;
+
+   /* every event has associated itree element */
+   __cur_tevpi = __p0_te_hdri;
+   for (; __cur_tevpi != -1; __cur_tevpi = __tevtab[__cur_tevpi].tenxti)
+    {
+     tevp = &(__tevtab[__cur_tevpi]);
+
+     /* canceled because interactive thread disabled */
+     /* but pound 0 events not counted as timing wheel events */
+     if (tevp->te_cancel) { __num_cancel_tevents++; continue; }
+
+     /* notice, pnd0 never canceled since can just replace guts */
+     __push_itstk(tevp->teitp);
+
+     /* notice before event executed, cur. itp set from event */
+     switch ((byte) tevp->tetyp) {
+      case TE_THRD:
+       __process_thrd_ev(tevp);
+       break;
+       break;
+      case TE_CA: process_conta_ev(tevp); break;
+      /* for gates and 1 bit continous assigns */
+      case TE_G: process_gatechg_ev(tevp); break;
+      case TE_WIRE: process_wire_ev(tevp); break;
+      case TE_BIDPATH: process_trpthdst_ev(tevp); break;
+      /* #0 here is normal 0 delay - start as no delay */
+      case TE_MIPD_NCHG: process_mipd_nchg_ev(tevp); break;
+      case TE_NBPA: process_nbpa_ev(tevp); break;
+      case TE_TFSETDEL: __setdel_call_misctf(__cur_tevpi); break;
+
+      case TE_TFPUTPDEL: __process_putpdel_ev(__cur_tevpi); break;
+      case TE_VPIPUTVDEL: __process_vpi_varputv_ev(__cur_tevpi); break;
+      case TE_VPIDRVDEL: __process_vpidrv_ev(__cur_tevpi); break;
+      case TE_VPICBDEL: __delay_callback(__cur_tevpi); break;
+      case TE_SYNC: __sync_call_misctf(tevp); break;
+      default: __case_terr(__FILE__, __LINE__);
+      }
+     __num_proc_tevents++;
+     /* when put into pnd0 list, no inc. of number of twheel events */
+     __pop_itstk();
+     /* here cur_tevpi done so any add to front after it */
+     if (__pending_enter_iact) __do_interactive_loop();
+    }
+
+   /* all #0 events for this time slot processed but may be new net chgs */
+   if (__p0_te_hdri != -1)
+    {
+     __tevtab[__p0_te_endi].tenxti = __tefreelsti;
+     __tefreelsti = __p0_te_hdri;
+     __p0_te_hdri = __p0_te_endi = -1;
+    }
+   __cur_tevpi = -1;
+  }
+ __processing_pnd0s = FALSE;
+}
+
+/*
+ * routine to exec dump vars functions
+ *
+ * notice only normal dumpvars will change to over file size limit state
+ * from then on until flush or limit change will not do any dumping
+ * or for that matter recording.
+ */
+static void exec_slotend_dv(void)
+{
+ /* must only emit time once in all processing */
+ __dv_time_emitted = FALSE;
+ /* first execute any dumpall */
+ if ((__slotend_action & SE_DUMPALL) != 0)
+  {
+   /* if over limit silently do nothing */
+   /* dump all is indpendent of normal dumpvars processing */
+   if (__dv_state != DVST_OVERLIMIT)
+    __do_dmpvars_baseline("$dumpall");
+  }
+
+ switch ((byte) __dv_state) {
+  case DVST_DUMPING:
+   /* if encountered dumpoff, handle here */
+   if ((__slotend_action & SE_DUMPOFF) != 0)
+    {
+     /* remove any pending changes */
+     if (__dv_chgnethdr != NULL) free_chgedvars();
+     __do_dmpvars_baseline("$dumpoff");
+     __dv_state = DVST_NOTDUMPING;
+     __turnoff_all_dumpvars();
+     break;
+    }
+   /* if no changes this time slot, nothing to do */
+   /* on file over dump limit, will return */
+   if (__dv_chgnethdr != NULL) __do_dmpvars_chg();
+   break;
+  case DVST_NOTDUMPING:
+   /* if not dumpon and no dump on action do nothing here */
+   if ((__slotend_action & SE_DUMPON) != 0)
+    {
+     /* start with baseline dump */
+     __do_dmpvars_baseline("$dumpon");
+     __dv_state = DVST_DUMPING;
+     /* turn on dump change recording and dumping for next time slot */
+     __turnon_all_dumpvars();
+    }
+   break;
+  /* if not set up only way for pending to be on if need to setup */
+  case DVST_NOTSETUP:
+
+   /* try to open the file */
+   if ((__dv_fd = __tilde_creat(__dv_fnam)) == -1)
+    {
+     if (strcmp(__dv_fnam, DFLTDVFNAM) == 0)
+      {
+bad_dvfnam:
+       __pv_err(759,
+	"cannot open $dumpvars output file at %s - $dumpvars not executed",
+	 __to_timstr(__xs, &__simtime));
+       /* not setup but dv seen stops any future setup */
+       __dv_seen = TRUE;
+       __dv_state = DVST_NOTSETUP;
+       return;
+      }
+     else
+      {
+       __pv_warn(589, "cannot open $dumpvars output file %s trying %s",
+	__dv_fnam, DFLTDVFNAM);
+       strcpy(__dv_fnam, DFLTDVFNAM);
+       if ((__dv_fd = __my_creat(__dv_fnam)) == -1) goto bad_dvfnam;
+      }
+    }
+   /* write the file reference header and setup dv "events" on wires */
+   __setup_dmpvars();
+   __do_dmpvars_baseline("$dumpvars");
+   if (__verbose)
+    {
+     __cv_msg(
+      "  $dumpvars setup complete at %s - variables dumped to file %s.\n",
+      __to_timstr(__xs, &__simtime), __dv_fnam);
+    }
+   if (__dv_state != DVST_OVERLIMIT)
+    {
+     __dv_state = DVST_DUMPING;
+     /* enable dmpv change recording */
+    }
+   /* more setup now disabled */
+   __dv_seen = TRUE;
+   break;
+  case DVST_OVERLIMIT:
+   if (__dv_chgnethdr != NULL) __misc_terr(__FILE__, __LINE__);
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * reset and free all changed vars when dump all needed
+ *
+ * in case of dump all - from dv state change may be some changed
+ * vars that need to be reset
+ */
+static void free_chgedvars(void)
+{
+ register struct dvchgnets_t *dvchgnp;
+ struct dvchgnets_t *dvchg_last;
+
+ dvchg_last = NULL;
+ /* need to find end to free because putting on front */
+ for (dvchgnp = __dv_chgnethdr; dvchgnp != NULL; dvchgnp = dvchgnp->dvchgnxt)
+  dvchg_last = dvchgnp;
+ /* nothing was on list if last nil */
+ if (dvchg_last != NULL)
+  {
+   dvchg_last->dvchgnxt = __dv_netfreelst;
+   __dv_netfreelst = __dv_chgnethdr;
+   __dv_chgnethdr = NULL;
+  }
+}
+
+/*
+ * AFTER CHANGE PROPOGATION FROM RHS ROUTINES
+ */
+
+/*
+ * go through processing all nets (maybe a select) that changed
+ * a pass may create more net changes that are in turn processed
+ * until list empty
+ * this is heuristic to try to cause breath first processing
+ * when done future net change list empty
+ *
+ * if net (probably reg) has no load and no dcelst els not added to chg list
+ *
+ * SJM - 06/19/00 - now only save up and process structural net changes
+ * event controls must be checked (and for force/release) done immediately
+ */
+static void process_all_netchgs(void)
+{
+ register struct net_t *np;
+ register struct nchglst_t *nchglp, *last_nchglp;
+ struct nchglst_t *sav_nchglp;
+ int32 num_this_pass, num_passes, total_num;
+
+ num_passes = 0;
+ total_num = 0;
+ for (;;)
+  {
+   if (__nchg_futhdr == NULL) break;
+
+   /* point nchglp to all pending net chg elements for processing */
+   nchglp = __nchg_futhdr;
+   /* save head so can free at end of pass */
+   sav_nchglp = nchglp;
+   /* empty future so all net change elements added here will be put on */
+   /* end of list and processed when all these done - breadth first */
+   __nchg_futend = __nchg_futhdr = NULL;
+   last_nchglp = NULL;
+   for (num_this_pass = 0; nchglp != NULL; nchglp = nchglp->nchglnxt)
+    {
+     np = nchglp->chgnp;
+     /* must eval. in definition itree loc. */
+     __push_itstk(nchglp->nchg_itp);
+     /* SJM 04/19/01 - must turn off all changed to allow load propagation */
+     /* switch channel changes to be added to next pass change list */
+     /* turn off all changed - if get here know has n lds */
+     np->nchgaction[__inum] &= (~NCHG_ALL_CHGED);
+
+     /* DEBUG remove ---
+     {
+      struct net_pin_t *npp;
+
+      __dbg_msg("*** dumping loads for net %s (itp=%s)***\n",
+       np->nsym->synam, __msg2_blditree(__xs, __inst_ptr));
+      for (npp = np->nlds; npp != NULL; npp = npp->npnxt)
+       {
+        __dmp1_nplstel(__inst_mod, np, npp);
+       }
+      __dbg_msg("*** end of loads ***\n");
+     }
+    --- */
+
+     /* SJM 07/24/00 - propagate changes to dces for wires at end of queue */
+     /* new algorithm - for regs immediate propagate, for wires end of queue */
+     /* LOOKATME - think event controls should be before lds */
+     if (np->ntyp < NONWIRE_ST && np->dcelst != NULL)
+      __wakeup_delay_ctrls(np, nchglp->bi1, nchglp->bi2);
+
+     /* SJM 07/24/00 - for wires with no lds but only dces still need */
+     /* to record nothing to do here */
+     if (np->nlds != NULL)
+      eval_netchg_lds(np, nchglp->bi1, nchglp->bi2, nchglp->delayed_mipd);
+
+     last_nchglp = nchglp;
+     num_this_pass++;
+     __pop_itstk();
+    }
+   total_num += num_this_pass;
+   if (++num_passes > 1000 && (num_passes % 1000) == 0)
+    {
+     if (__pending_enter_iact)
+      {
+       __ia_warn(1604,
+         "interactive mode probably entered from zero delay oscillation - no scheduling");
+       __do_interactive_loop();
+      }
+    }
+
+   /* know last nchg lp set since routine not called if at least one */
+   /* SJM 08/02/01 - add if to keep lint happy */
+   if (last_nchglp != NULL) last_nchglp->nchglnxt = __nchgfreelst;
+   __nchgfreelst = sav_nchglp;
+   /* LINUX DBG - add me */
+   /* chk_nchgnlst(__nchgfreelst); */
+   /* --- */
+  }
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg("-- net change event scheduling %d processed in %d passes\n",
+    total_num, num_passes);
+  }
+ __num_netchges += total_num;
+}
+
+/*
+ * check nchg free list
+ */
+/* UNUSED LINUX DEBUG ---
+void chk_nchgnlst(struct nchglst_t *hdr)
+{
+ register struct nchglst_t *nchglp;
+ int32 ndx;
+
+ ndx = 0;
+ for (nchglp = hdr; nchglp != NULL; nchglp = nchglp->nchglnxt)
+  {
+   if ((void *) nchglp > (void *) 0x13257400)
+    {
+     __tr_msg("problem at index %d\n", ndx);
+     __misc_terr(__FILE__, __LINE__);
+    }
+   if (nchglp->nchglnxt > (void *) 0x13257400)
+    {
+     __tr_msg("problem at index %d\n", ndx);
+     __misc_terr(__FILE__, __LINE__);
+    }
+   ndx++;
+  }
+}
+--- */
+
+/*
+ * after changed net (wire or reg) go through loads evaluating the
+ * load net's drivers assigning to the load net a new value
+ *
+ * bit range passed and used to eliminate fan-out for other bit here
+ * all ranges here normalized high to low form
+ * notice will neve get to event trigger through this path (through cause)
+ * this is called with current itstk set to wire targ. (maybe target of xmr)
+ *
+ * the driver evaluations caused by this cause any changed wires to be
+ * added to a list which is then used to provide the next pass of wire
+ * loads
+ */
+static void eval_netchg_lds(register struct net_t *np, int32 chgi1, int32 chgi2,
+ int32 is_delayed_mipd)
+{
+ register struct net_pin_t *npp;
+ register struct npaux_t *npauxp;
+ register int32 bi;
+ int32 nd_itpop;
+ struct mod_t *downmdp;
+ struct mod_pin_t *mpp;
+ struct itree_t *itp;
+ struct inst_t *ip;
+ struct gate_t *gp;
+ struct mipd_t *mipdp;
+
+ if (__ev_tracing)
+  {
+   __evtr_resume_msg();
+   __tr_msg("-- evaluating loads of reg/wire %s\n",
+    __to_evtrwnam(__xs, np, chgi1, chgi2, __inst_ptr));
+  }
+
+ /* must process all loads on net */
+ for (npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   /* immediately filter out - npp's that require particular inst. */
+   if (npp->npproctyp == NP_PROC_FILT
+    && npp->npaux->npu.filtitp != __inst_ptr)
+    continue;
+
+   /* first need non empty union with 2 ranges */
+   /* case 1: all bits of changed or driven bits unknown */
+   if ((npauxp = npp->npaux) == NULL || npauxp->nbi1 == -1 || chgi1 == -1)
+    goto got_match;
+   /* case 2: range of npp is IS form */
+   if (npauxp->nbi1 == -2)
+    {
+     if (is2_chg_match(npauxp->nbi2.xvi, chgi1, chgi2))
+      goto got_match;
+     continue;
+    }
+   /* case 3: must check to see if net chg in range */
+   if (chgi1 < npauxp->nbi2.i || chgi2 > npauxp->nbi1) continue;
+
+got_match:
+   /* process various xmr special cases */
+   /* know any instance filtering done before here */
+   /* move from definition target xmr loc. back to ref. loc */
+   /* for vpi_ just pushed same inst. on to stack again since no ref. loc. */
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - if XMR path does not match, do not eval */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+   else nd_itpop = FALSE;
+
+   /* maybe some tracing info */
+   if (__ev_tracing) emit_nchglds_trmsg(np, npp);
+
+   switch ((byte) npp->npntyp) {
+    case NP_ICONN:
+     /* notice iconn load (rhs) causes assign to down lhs mdprt */
+     /* but iconn driver assigns from down rhs to iconn lhs for out port */
+     __immed_assigns++;
+     /* SJM 09/08/01 - can now remove this consistency check */
+     /* DBG remove ---
+     if (npp->elnpp.eii >= __inst_ptr->itip->imsym->el.emdp->minum)
+      __misc_terr(__FILE__, __LINE__);
+     --- */
+
+     itp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+     ip = itp->itip;
+     downmdp = ip->imsym->el.emdp;
+     /* SJM 09/08/01 - can now remove this consistency check */
+     /* DBG remove ---
+     if (npp->obnum >= downmdp->mpnum) __misc_terr(__FILE__, __LINE__);
+     --- */
+     mpp = &(downmdp->mpins[npp->obnum]);
+     /* assign from rhs up rhs iconn to lhs down mpp ref. for input port */
+     /* notice down always take only 4 args, down do not have first mpp */
+     (*mpp->mpaf.mpp_downassgnfunc)(mpp->mpref, ip->ipins[npp->obnum], itp);
+     break;
+    case NP_PB_ICONN:
+     /* notice iconn load (rhs) causes assign to down lhs mdprt */
+     /* but iconn driver assigns from down rhs to iconn lhs for out port */
+     __immed_assigns++;
+     /* SJM 09/08/01 - can now remove this consistency check */
+     /* DBG remove ---
+     if (npp->elnpp.eii >= __inst_ptr->itip->imsym->el.emdp->minum)
+      __misc_terr(__FILE__, __LINE__);
+     --- */
+     itp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+     ip = itp->itip;
+     downmdp = ip->imsym->el.emdp;
+     /* SJM 09/08/01 - can now remove this consistency check */
+     /* DBG remove ---
+     if (npp->obnum >= downmdp->mpnum) __misc_terr(__FILE__, __LINE__);
+     --- */
+     mpp = &(downmdp->mpins[npp->obnum]);
+     mpp = &(mpp->pbmpps[npp->pbi]);
+     /* assign from rhs up rhs iconn to lhs down mpp ref. for input port */
+     /* notice down always take only 4 args, down do not have first mpp */
+     (*mpp->mpaf.mpp_downassgnfunc)(mpp->mpref,
+      ip->pb_ipins_tab[npp->obnum][npp->pbi], itp);
+     break;
+    case NP_MDPRT:
+     /* top of itstk determines which module inst this is and */
+     /* which up instance port to assign to for output port */
+     __immed_assigns++;
+     downmdp = npp->elnpp.emdp;
+     /* DBG remove --- */
+     if (npp->obnum >= downmdp->mpnum) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     mpp = &(downmdp->mpins[npp->obnum]);
+     itp = __inst_ptr->up_it;
+     /* DBG remove - bug if trying to assign output of top module --- */
+     if (itp == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+     /* assign from rhs down mpp ref. to up lhs iconn for output port */
+     /* for input port, assign from rhs up iconn to down mod port */
+     /* notice up always take only 3 args, down have extra 1st arg mpp */
+     (*mpp->mpaf.mpp_upassgnfunc)(__inst_ptr->itip->ipins[npp->obnum],
+      mpp->mpref, itp);
+     break;
+    case NP_PB_MDPRT:
+     /* top of itstk determines which module inst this is and */
+     /* which up instance port to assign to for output port */
+     __immed_assigns++;
+     downmdp = npp->elnpp.emdp;
+     mpp = &(downmdp->mpins[npp->obnum]);
+     mpp = &(mpp->pbmpps[npp->pbi]);
+     itp = __inst_ptr->up_it;
+     (*mpp->mpaf.mpp_upassgnfunc)(
+      __inst_ptr->itip->pb_ipins_tab[npp->obnum][npp->pbi],
+      mpp->mpref, itp);
+     break;
+    case NP_GATE:
+     /* evaluate load that is gate input and probably schedule gate chg */
+     gp = npp->elnpp.egp;
+     (*gp->gchg_func)(gp, npp->obnum);
+     break;
+    case NP_CONTA:
+     /* know input that changed is always port 0 (only input) */
+     /* SJM - 09/18/02 - for per bit rhs concat form same net pin type */
+     __eval_conta_rhs_ld(npp);
+     break;
+    case NP_TRANIF:
+     __eval_tranif_ld(npp->elnpp.egp, (int32) npp->obnum);
+     break;
+    case NP_TCHG:
+     __process_npp_timofchg(np, npp);
+     break;
+    case NP_MIPD_NCHG:
+     /* SJM 07/09/01 - for MIPD inserted between net(s) that connect to port */
+     /* and loads, net pin t that causes schedule before processing rest */
+
+     /* DBG remove --- */
+     if (np->nlds != npp) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+
+     /* SJM 07/13/01 if mipd net load processing already delayed, skip sched */
+     /* and stop processing, algorithm is to store port conn net val and */
+     /* sched ev, then ev processing routine puts on nchg list as if store */
+     /* had happened after del - can't propagate MIPD nchges until normal */
+     /* nchg loop */
+
+     if (is_delayed_mipd) break;
+
+     /* scalar is special case */
+     if (!np->n_isavec)
+      {
+       mipdp = &(npp->elnpp.emipdbits[0]);
+       if (mipdp->no_mipd) break;
+       __sched_mipd_nchg(np, -1, mipdp);
+      }
+     else if (chgi1 == -1)
+      {
+       for (bi = np->nwid - 1; bi >= 0; bi--)
+        {
+         mipdp = &(npp->elnpp.emipdbits[bi]);
+         if (mipdp->no_mipd) break;
+         __sched_mipd_nchg(np, bi, mipdp);
+        }
+      }
+     else
+      {
+       for (bi = chgi1; bi >= chgi2; bi--)
+        {
+         mipdp = &(npp->elnpp.emipdbits[bi]);
+         if (mipdp->no_mipd) break;
+         __sched_mipd_nchg(np, bi, mipdp);
+        }
+      }
+     if (nd_itpop) __pop_itstk();
+     /* notice must return since because of MIPD wasn't really changed */
+     /* works because mipd npp always first on list */
+     return;
+     /* pull driver only illlegal here */
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   if (nd_itpop) __pop_itstk();
+  }
+}
+
+/*
+ * process MIPD event
+ *
+ * simple proc that just processes all but first MIPD delay schedule NPP
+ * routine here since same as eval nchgs
+ *
+ * all MIPD events do is delay propagation from changed net(s) connected
+ * to input or inout ports to its loads by delay amount - tricky part is
+ * path-src delay value calculation
+ */
+static void process_mipd_nchg_ev(struct tev_t *tevp)
+{
+ register struct net_t *np;
+ register struct mipd_t *mipdp;
+ int32 bi, bi2;
+
+ np = tevp->tu.tenp->tenu.np;
+ bi = tevp->tu.tenp->nbi;
+
+ if (__ev_tracing)
+  {
+   __evtr_resume_msg();
+   __tr_msg("-- tracing MIPD event for %s\n",
+    __to_evtrwnam(__xs, np, bi, bi, __inst_ptr));
+  }
+
+ /* turn off mipd sheduled event */
+ bi2 = (bi == -1) ? 0 : bi;
+ mipdp = &(np->nlds->elnpp.emipdbits[bi2]);
+ mipdp->mipdschd_tevs[__inum] = -1;
+
+ /* add to nchg list if net not already all changed */
+ /* dmpvars bits chg not turned on since dumpvar happens when net changes */
+ /* also can't use normal macro, because never need reg dce wakeup */
+ if (!np->n_isavec)
+  {
+   if ((np->nchgaction[__inum] & NCHG_ALL_CHGED) == 0)
+    {
+     __add_nchglst_el(np);
+     /* SJM 19/01/02 - T because this is 2nd delayed event one so must */
+     /* not schedule */
+     /* BEWARE - this assumes last element added to end of list */
+     __nchg_futend->delayed_mipd = TRUE;
+    }
+  }
+ else
+  {
+   if ((np->nchgaction[__inum] & NCHG_ALL_CHGED) == 0)
+    {
+     __add_select_nchglst_el(np, bi, bi);
+     /* SJM 19/01/02 - T because this is 2nd delayed event one so must */
+     /* not schedule */
+     /* BEWARE - this assumes last element added to end of list */
+     __nchg_futend->delayed_mipd = TRUE;
+    }
+  }
+
+ /* free mipd event auxialiary field here since bit and wire extracted */
+ __my_free((char *) tevp->tu.tenp, sizeof(struct tenp_t));
+ tevp->tu.tenp = NULL;
+}
+
+/*
+ * emit eval netchg lds trace message
+ */
+static void emit_nchglds_trmsg(struct net_t *np, struct net_pin_t *npp)
+{
+ int32 i1, i2;
+ struct npaux_t *npauxp;
+ char s1[RECLEN], s2[RECLEN];
+
+ __evtr_resume_msg();
+ if (__debug_flg)
+  {
+   if ((npauxp = npp->npaux) == NULL) i1 = i2 = -1;
+   else __get_cor_range(npauxp->nbi1, npauxp->nbi2, &i1, &i2);
+   __tr_msg("-- after %s %s changed to %s processing %s\n",
+    __to_wtnam(s1, np), __to_evtrwnam(__xs, np, i1, i2, __inst_ptr),
+   __var_tostr(__xs2, np, i1, i2, BHEX), __to_npptyp(s2, npp));
+  }
+}
+
+/*
+ * return T if is IS2 form bit range (depends on itree place) matches
+ * T if bit inside npi1..npi2
+ * will overlap unless either high changed below low of range
+ * or low changed above high of range
+ *
+ * SJM 10/12/04 - changed to pass contab ndx instead of ptr since contab
+ * realloced
+ */
+static int32 is2_chg_match(int32 nbi2_xvi, int32 npi1, int32 npi2)
+{
+ int32 i1;
+ word32 *wp;
+
+ wp = &(__contab[nbi2_xvi]);
+ wp = &(wp[2*__inum]);
+ /* if value x - force match since unknown - only can happen for procedural */
+ if (wp[1] != 0L) return(TRUE);
+ i1 = (int32) wp[0];
+ /* know form here h:0 */
+ return(npi1 >= i1 && npi2 <= i1);
+}
+
+/*
+ * get an possibly correctd for is2 form bit index (part select always split)
+ */
+extern void __get_cor_range(register int32 oi1, union intptr_u oi2,
+ register int32 *i1, register int32 *i2)
+{
+ register word32 *wp;
+
+ if (oi1 != -2) { *i1 = oi1; *i2 = oi2.i; }
+ else
+  {
+   /* SJM 10/12/04 - because contab realloced, must be ndx base of IS */
+   wp = &(__contab[oi2.xvi]);
+   *i1 = *i2 = (int32) wp[2*__inum];
+  }
+}
+
+/*
+ * DECLARATIVE EVENT SCHEDULING/PROCESSING ROUTINES
+ */
+
+/*
+ * GATE EVENT ROUTINES
+ */
+
+/*
+ * GENERAL COMMENTS FOR ALL ROUTINES:
+ *
+ * evaluate a gate because gate input changed and the gate input is
+ * a load of the changed wire
+ *
+ * when gate gp input i of inst. cur. itp changes, eval. gate and maybe
+ * schedule output change if has delay and output changed
+ * after changing input in gate/inst. state vector
+ *
+ * notice 1 bit conta's are transformed to gates during fix up
+ * so changes handled here
+ *
+ * after these if inputs differ all of old gate value, new gate val,
+ * old gate strength and new gate strength set
+ */
+
+/* --- unused non proc call gate eval routine
+static void eval_gatein_ld(struct gate_t *gp, int32 i)
+{
+ switch ((byte) gp->g_class) {
+  case GC_LOGIC: std_chg_logic_gate(gp, i); break;
+  case GC_UDP: std_chg_udp_gate(gp, i); break;
+  case GC_BUFIF: std_chg_bufif_gate(gp, i); break;
+  case GC_MOS: std_chg_mos_gate(gp, i); break;
+  case GC_CMOS: std_chg_cmos_gate(gp, i); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+--- */
+
+/*
+ * evaluate a logic - std not optimized version
+ */
+static void std_chg_logic_gate(register struct gate_t *gp, register word32 i)
+{
+ int32 out_chg;
+
+ if (!__eval_logic_gate(gp, i, &out_chg))
+  { if (__ev_tracing) trace_gunchg(gp, i); return; }
+
+ if (__ev_tracing) evtr_prop_gatechg(gp, i, out_chg);
+ else
+  {
+   if (gp->g_delrep == DT_NONE) { if (out_chg) change_gate_outwire(gp); }
+   else prop_gatechg(gp, out_chg, FALSE);
+  }
+}
+
+/*
+ * accelerated 2 input gate (all XL style simple expressions)
+ *
+ * if no delay and not ev trace does all inline, if delay call normal prop
+ * both ports must be constant bit select or scalar
+ * inputs can not be strength for this most optimized routine
+ */
+static void acc_chg_bufnot(struct gate_t *gp, word32 i)
+{
+ register word32 ouwrd, uwrd, ngav, ngbv;
+ int32 out_chg, gatid, biti;
+ word32 igav, igbv;
+ struct expr_t *xp;
+ struct net_t *np;
+
+ xp = gp->gpins[1];
+ if (xp->optyp == ID)
+  ld_scalval_(&igav, &igbv, xp->lu.sy->el.enp->nva.bp);
+ else
+  {
+   __ld_bit(&igav, &igbv, xp->lu.x->lu.sy->el.enp,
+    (int32) __contab[xp->ru.x->ru.xvi]);
+  }
+
+ __new_inputval = igav | (igbv << 1);
+ /* eval changed input and store in gstate if needed */
+ /* 12/19/99 SJM - notice buf or not still packed into 1 byte but vars */
+ /* only packed into word32 as smallest */
+ ouwrd = (word32) gp->gstate.bp[__inum];
+
+ /* input for not is bits 0 and 2 */
+ uwrd = ouwrd & ~(0x5L);
+ uwrd |= (igav | (igbv << 2));
+ /* input change did not change gate */
+ if (uwrd == ouwrd) { if (__ev_tracing) trace_gunchg(gp, i); return; }
+ gp->gstate.bp[__inum] = (byte) uwrd;
+
+ /* value for not is bits 1 and 3 */
+ __old_gateval = ((uwrd >> 1) & 1L) | ((uwrd >> 2) & 2L);
+
+ /* evaluate - not and buf always convert z to x */
+ gatid = gp->gmsym->el.eprimp->gateid;
+ ngbv = (uwrd >> 2) & 1L;
+ if (gatid == G_NOT) ngav = !(uwrd & 1L) | ngbv;
+ else if (gatid == G_BUF) ngav = (uwrd & 1L) | ngbv;
+ /* but cont. ASSIGN passes z */
+ else ngav = (uwrd & 1L);
+
+ __new_gateval = ngav | (ngbv << 1);
+ /* set to T (non 0) if not equal if changed (different) */
+ out_chg = (__old_gateval != __new_gateval);
+ /* if tracing must use std trace store-propagate routine */
+ if (__ev_tracing) { evtr_prop_gatechg(gp, i, out_chg); return; }
+ /* handle delay case using normal gate chg */
+ /* third param means acc possible because called from acc routine */
+ if (gp->g_delrep != DT_NONE) { prop_gatechg(gp, out_chg, TRUE); return; }
+
+ /* immediate fast assign for accelerated */
+ /* inline steps in store gate output value */
+ if (!out_chg) return;
+
+ /* g pdst on if wire driven by gate is path dest. or has delay */
+ if (gp->g_pdst) { change_gate_outwire(gp); return; }
+
+ /* non delay acc immediate assign code */
+ xp = gp->gpins[0];
+ /* update state with computed output value is bits 1 and 3 */
+ uwrd = uwrd & ~(0x2L) & ~(0x8L);
+ uwrd |= ((ngav << 1) | (ngbv << 3));
+ gp->gstate.bp[__inum] = (byte) uwrd;
+
+ /* accelerated assign to pin 0 (output) */
+ if (xp->optyp == ID)
+  {
+   np = xp->lu.sy->el.enp;
+   if (np->frc_assgn_allocated)
+    {
+     igav = ngav; igbv = ngbv;
+     if (!__correct_forced_newwireval(np, &igav, &igbv))
+      goto try_trace;
+    }
+   /* here since avoiding value store, need to add net change el. */
+   chg_st_scalval_(np->nva.bp, ngav, ngbv);
+   /* not 0 for mask ands is T */
+   /* if lhs chged and no lds/dces and not entire inst changed, record it */
+   if (__lhs_changed) record_nchg_(np);
+  }
+ else
+  {
+   np = xp->lu.x->lu.sy->el.enp;
+   biti = (int32) __contab[xp->ru.x->ru.xvi];
+
+   /* if the 1 bit is forced nothing to do else normal assign */
+   if (np->frc_assgn_allocated
+    && __forced_inhibit_bitassign(np, xp->lu.x, xp->ru.x)) goto try_trace;
+   /* notice this adds the net chg element if needed */
+   __chg_st_bit(np, biti, ngav, ngbv);
+  }
+try_trace:
+ if (__ev_tracing) trace_chg_gateout(gp, xp);
+}
+
+/*
+ * accelerated 1 input (maybe stren) gate (all XL style simple expressions)
+ *
+ * if no delay and not ev trace does all inline, if delay call normal prop
+ * both ports must be constant bit select or scalar
+ * here inputs may be strength (removed), but cannot drive stren
+ *
+ * only difference is slow if for accessing value from strength
+ */
+static void acc_stichg_bufnot(register struct gate_t *gp, word32 i)
+{
+ register struct expr_t *xp;
+ register word32 ouwrd, uwrd, ngav, ngbv;
+ register struct net_t *np;
+ int32 out_chg, gatid, biti;
+ word32 igav, igbv;
+
+ xp = gp->gpins[1];
+ if (xp->optyp == ID)
+  {
+   np = xp->lu.sy->el.enp;
+   if (np->n_stren)
+    {
+     uwrd = (word32) np->nva.bp[__inum];
+     igav = uwrd & 1L;
+     igbv = (uwrd >> 1) & 1L;
+    }
+   else ld_scalval_(&igav, &igbv, np->nva.bp);
+  }
+ else __ld_bit(&igav, &igbv, xp->lu.x->lu.sy->el.enp,
+  (int32) __contab[xp->ru.x->ru.xvi]);
+
+ __new_inputval = igav | (igbv << 1);
+ /* eval changed input and store in gstate if needed */
+ ouwrd = (word32) gp->gstate.bp[__inum];
+ /* input for not is bits 0 and 2 */
+ uwrd = ouwrd & ~(0x5L);
+ uwrd |= (igav | (igbv << 2));
+ /* input change did not change gate */
+ if (uwrd == ouwrd) { if (__ev_tracing) trace_gunchg(gp, i); return; }
+ gp->gstate.bp[__inum] = (byte) uwrd;
+
+ /* value for not is bits 1 and 3 */
+ __old_gateval = ((uwrd >> 1) & 1L) | ((uwrd >> 2) & 2L);
+
+ /* evaluate - not and buf always convert z to x */
+ gatid = gp->gmsym->el.eprimp->gateid;
+ ngbv = (uwrd >> 2) & 1L;
+ if (gatid == G_NOT) ngav = !(uwrd & 1L) | ngbv;
+ else if (gatid == G_BUF) ngav = (uwrd & 1L) | ngbv;
+ /* but cont. ASSIGN passes z */
+ else ngav = (uwrd & 1L);
+
+ __new_gateval = ngav | (ngbv << 1);
+ /* set to T (non 0) if not equal if changed (different) */
+ out_chg = (__old_gateval != __new_gateval);
+ /* if tracing must use std trace store-propagate routine */
+ if (__ev_tracing) { evtr_prop_gatechg(gp, i, out_chg); return; }
+ /* handle delay case using normal gate chg */
+ /* thrd param T because being called from acc routine */
+ if (gp->g_delrep != DT_NONE) { prop_gatechg(gp, out_chg, TRUE); return; }
+
+ /* immediate fast assign for accelerated */
+ /* inline steps in store gate output value */
+ if (!out_chg) return;
+
+ /* g pdst on if wire driven by gate is path dest. or has delay */
+ if (gp->g_pdst) { change_gate_outwire(gp); return; }
+
+ /* non delay acc assign code */
+ xp = gp->gpins[0];
+ /* update state with computed output value is bits 1 and 3 */
+ uwrd = uwrd & ~(0x2L) & ~(0x8L);
+ uwrd |= ((ngav << 1) | (ngbv << 3));
+ gp->gstate.bp[__inum] = (byte) uwrd;
+ /* accelerated assign to pin 0 (output) */
+ if (xp->optyp == ID)
+  {
+   np = xp->lu.sy->el.enp;
+   if (np->frc_assgn_allocated)
+    {
+     igav = ngav; igbv = ngbv;
+     if (!__correct_forced_newwireval(np, &igav, &igbv))
+      goto try_trace;
+    }
+   /* here since avoiding value store, need to add net change el. */
+   chg_st_scalval_(np->nva.bp, ngav, ngbv);
+
+   /* not 0 for mask ands is T */
+   /* if lhs chged and no lds/dces and not entire inst changed, record it */
+   if (__lhs_changed) record_nchg_(np);
+  }
+ else
+  {
+   np = xp->lu.x->lu.sy->el.enp;
+   biti = (int32) __contab[xp->ru.x->ru.xvi];
+   /* if the 1 bit is forced nothing to do else normal assign */
+   if (np->frc_assgn_allocated
+    && __forced_inhibit_bitassign(np, xp->lu.x, xp->ru.x)) goto try_trace;
+   /* notice this adds the net chg element if needed */
+   __chg_st_bit(np, biti, ngav, ngbv);
+  }
+try_trace:
+ if (__ev_tracing) trace_chg_gateout(gp, xp);
+}
+
+/*
+ * acceleated up to 3 input (4 pints) gate with no delay
+ *
+ * could unwind to separate for each gate type
+ * if no delay and not ev trace does all inline, if delay call normal prop
+ * both ports must be constant bit select or scalar
+ * inputs must not be stren wires
+ * degenerate 2 input gate not accelerated
+ */
+static void acc_chg_4igate(register struct gate_t *gp, word32 i)
+{
+ register struct expr_t *xp;
+ register word32 ouwrd, uwrd, ngav, ngbv, gwid;
+ struct net_t *np;
+ int32 out_chg, biti, bi;
+ word32 gav, gbv, mask;
+
+ xp = gp->gpins[i];
+ if (xp->optyp == ID) ld_scalval_(&gav, &gbv, xp->lu.sy->el.enp->nva.bp);
+ else __ld_bit(&gav, &gbv, xp->lu.x->lu.sy->el.enp,
+  (int32) __contab[xp->ru.x->ru.xvi]);
+ bi = i - 1;
+ gwid = gp->gpnum;
+ __new_inputval = gav | (gbv << 1);
+
+ /* eval changed input and store in gstate if needed */
+ ouwrd = (word32) gp->gstate.bp[__inum];
+ uwrd = ouwrd & ~(1L << bi) & ~(1L << (gwid + bi));
+ uwrd |= ((gav << bi) | (gbv << (gwid + bi)));
+ /* input change did not change gate */
+ if (uwrd == ouwrd) { if (__ev_tracing) trace_gunchg(gp, i); return; }
+ gp->gstate.bp[__inum] = (byte) uwrd;
+
+ /* mask off a/b output bit - now gav/gbv all inputs */
+ mask = __masktab[gwid - 1];
+ gav = uwrd & mask;
+ gbv = (uwrd >> gwid) & mask;
+ /* works since know n ins at least 1 - b shifts 1 less, goes b bit */
+ __old_gateval = ((uwrd >> (gwid - 1)) & 1L) | ((uwrd >> (2*gwid - 2)) & 2L);
+
+ /* evaluate gate */
+ /* LOOKATME - could split and copy for each pin/gate combination */
+ ngav = ngbv = 1L;
+ switch ((byte) gp->gmsym->el.eprimp->gateid) {
+  case G_BITREDAND:
+   /* if even 1 0 value in any used bit, result is 0 */
+   if (gbv == 0L) { ngav = (gav != mask) ? 0L : 1L; ngbv = 0L; }
+   else if ((gav | gbv) != mask) ngav = ngbv = 0L;
+   break;
+  case G_NAND:
+   /* if even 1 0 value in any used bit, result is 1 */
+   if (gbv == 0L) { ngav = (gav != mask) ? 1L : 0L; ngbv = 0L; }
+   else if ((gav | gbv) != mask) ngbv = 0L;
+   break;
+  case G_BITREDOR:
+   /* if even 1 1 value in any used bit, result is 1 */
+   if (gbv == 0L) { ngav = (gav != 0L) ? 1L : 0L; ngbv = 0L; }
+   else if ((gav & ~gbv) != 0L) ngbv = 0L;
+   break;
+  case G_NOR:
+   /* if even 1 1 value in any used bit, result is 0 */
+   if (gbv == 0L) { ngav = (gav != 0L) ? 0L : 1L; ngbv = 0L; }
+   else if ((gav & ~gbv) != 0L) ngav = ngbv = 0L;
+   break;
+  case G_BITREDXOR:
+   if (gbv == 0L) { ngbv = 0L; ngav = __wrd_redxor(gav); }
+   break;
+  case G_REDXNOR:
+   if (gbv == 0L) { ngbv = 0L; ngav = !__wrd_redxor(gav); }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ __new_gateval = ngav | (ngbv << 1);
+ /* set to T (non 0) if not equal if changed (different) */
+ out_chg = (__old_gateval != __new_gateval);
+ /* if tracing must use std trace store-propagate routine */
+ if (__ev_tracing) { evtr_prop_gatechg(gp, i, out_chg); return; }
+ /* handle delay case using normal gate chg */
+ /* thrd param T because being called from acc routine */
+ if (gp->g_delrep != DT_NONE) { prop_gatechg(gp, out_chg, TRUE); return; }
+
+ /* immediate fast assign for accelerated */
+ /* inline steps in store gate output value */
+ if (!out_chg) return;
+
+ /* g pdst on if wire driven by gate is path dest. or has delay */
+ if (gp->g_pdst) { change_gate_outwire(gp); return; }
+
+ /* non delay acc immediate assign code */
+ xp = gp->gpins[0];
+ /* mask off separated value bits to update output value in uwrd */
+ uwrd = uwrd & ~(1L << (gwid - 1)) & ~(1L << (2*gwid - 1));
+ /* works because ngav and ngbv exactly 1 low bit */
+ uwrd |= ((ngav << (gwid - 1)) | (ngbv << (2*gwid - 1)));
+ /* must store twice because update of input may not change output */
+ gp->gstate.bp[__inum] = (byte) uwrd;
+ /* accelerated assign to pin 0 (output) */
+ if (xp->optyp == ID)
+  {
+   np = xp->lu.sy->el.enp;
+   if (np->frc_assgn_allocated)
+    {
+     gav = ngav; gbv = ngbv;
+     if (!__correct_forced_newwireval(np, &gav, &gbv))
+      goto try_trace;
+    }
+   /* here since avoiding value store, need to add net change el. */
+   chg_st_scalval_(np->nva.bp, ngav, ngbv);
+   if (__lhs_changed) record_nchg_(np);
+  }
+ else
+  {
+   np = xp->lu.x->lu.sy->el.enp;
+   biti = (int32) __contab[xp->ru.x->ru.xvi];
+   /* if the 1 bit is forced nothing to do else normal assign */
+   if (np->frc_assgn_allocated
+    && __forced_inhibit_bitassign(np, xp->lu.x, xp->ru.x)) goto try_trace;
+   /* this adds the nchg el if needed */
+   __chg_st_bit(np, biti, ngav, ngbv);
+  }
+try_trace:
+ if (__ev_tracing) trace_chg_gateout(gp, xp);
+}
+
+/*
+ * accelerated up to 4 input gate
+ *
+ * could unwind to separate for each gate type
+ * if no delay and not ev trace does all inline, if delay call normal prop
+ * both ports must be constant bit select or scalar
+ *
+ * inputs can be strength wires (removed) but cannot driver stren
+ */
+static void acc_stichg_4igate(register struct gate_t *gp, word32 i)
+{
+ register struct expr_t *xp;
+ register word32 ouwrd, uwrd, ngav, ngbv, gwid;
+ struct net_t *np;
+ int32 out_chg, biti, bi;
+ word32 gav, gbv, mask;
+
+ xp = gp->gpins[i];
+ if (xp->optyp == ID)
+  {
+   np = xp->lu.sy->el.enp;
+   if (np->n_stren)
+    {
+     uwrd = (word32) np->nva.bp[__inum];
+     gav = uwrd & 1L;
+     gbv = (uwrd >> 1) & 1L;
+    }
+   else ld_scalval_(&gav, &gbv, np->nva.bp);
+  }
+ else __ld_bit(&gav, &gbv, xp->lu.x->lu.sy->el.enp,
+   (int32) __contab[xp->ru.x->ru.xvi]);
+ bi = i - 1;
+ gwid = gp->gpnum;
+ __new_inputval = gav | (gbv << 1);
+
+ /* eval changed input and store in gstate if needed */
+ ouwrd = (word32) gp->gstate.bp[__inum];
+ uwrd = ouwrd & ~(1L << bi) & ~(1L << (gwid + bi));
+ uwrd |= ((gav << bi) | (gbv << (gwid + bi)));
+ /* input change did not change gate */
+ if (uwrd == ouwrd) { if (__ev_tracing) trace_gunchg(gp, i); return; }
+ gp->gstate.bp[__inum] = (byte) uwrd;
+
+ /* mask off a/b output bit - now gav/gbv all inputs */
+ mask = __masktab[gwid - 1];
+ gav = uwrd & mask;
+ gbv = (uwrd >> gwid) & mask;
+ /* works since know n ins at least 1 - b shifts 1 less, goes b bit */
+ __old_gateval = ((uwrd >> (gwid - 1)) & 1L) | ((uwrd >> (2*gwid - 2)) & 2L);
+
+ /* evaluate gate */
+ /* LOOKATME - could split and copy for each pin/gate combination */
+ ngav = ngbv = 1L;
+ switch ((byte) gp->gmsym->el.eprimp->gateid) {
+  case G_BITREDAND:
+   /* if even 1 0 value in any used bit, result is 0 */
+   if (gbv == 0L) { ngav = (gav != mask) ? 0L : 1L; ngbv = 0L; }
+   else if ((gav | gbv) != mask) ngav = ngbv = 0L;
+   break;
+  case G_NAND:
+   /* if even 1 0 value in any used bit, result is 1 */
+   if (gbv == 0L) { ngav = (gav != mask) ? 1L : 0L; ngbv = 0L; }
+   else if ((gav | gbv) != mask) ngbv = 0L;
+   break;
+  case G_BITREDOR:
+   /* if even 1 1 value in any used bit, result is 1 */
+   if (gbv == 0L) { ngav = (gav != 0L) ? 1L : 0L; ngbv = 0L; }
+   else if ((gav & ~gbv) != 0L) ngbv = 0L;
+   break;
+  case G_NOR:
+   /* if even 1 1 value in any used bit, result is 0 */
+   if (gbv == 0L) { ngav = (gav != 0L) ? 0L : 1L; ngbv = 0L; }
+   else if ((gav & ~gbv) != 0L) ngav = ngbv = 0L;
+   break;
+  case G_BITREDXOR:
+   if (gbv == 0L) { ngbv = 0L; ngav = __wrd_redxor(gav); }
+   break;
+  case G_REDXNOR:
+   if (gbv == 0L) { ngbv = 0L; ngav = !__wrd_redxor(gav); }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ __new_gateval = ngav | (ngbv << 1);
+ /* set to T (non 0) if not equal if changed (different) */
+ out_chg = (__old_gateval != __new_gateval);
+ /* if tracing must use std trace store-propagate routine */
+ if (__ev_tracing) { evtr_prop_gatechg(gp, i, out_chg); return; }
+ /* handle delay case using normal gate chg */
+ /* thrd param T because being called from acc routine */
+ if (gp->g_delrep != DT_NONE) { prop_gatechg(gp, out_chg, TRUE); return; }
+
+ /* immediate fast assign for accelerated */
+ /* inline steps in store gate output value */
+ if (!out_chg) return;
+
+ /* g pdst on if wire driven by gate is path dest. or has delay */
+ if (gp->g_pdst) { change_gate_outwire(gp); return; }
+
+ /* non delay acc immediate assign code */
+ xp = gp->gpins[0];
+ /* mask off separated value bits to update output value in uwrd */
+ uwrd = uwrd & ~(1L << (gwid - 1)) & ~(1L << (2*gwid - 1));
+ /* works because ngav and ngbv exactly 1 low bit */
+ uwrd |= ((ngav << (gwid - 1)) | (ngbv << (2*gwid - 1)));
+ /* must store twice because update of input may not change output */
+ gp->gstate.bp[__inum] = (byte) uwrd;
+ /* accelerated assign to pin 0 (output) */
+ if (xp->optyp == ID)
+  {
+   np = xp->lu.sy->el.enp;
+   if (np->frc_assgn_allocated)
+    {
+     gav = ngav; gbv = ngbv;
+     if (!__correct_forced_newwireval(np, &gav, &gbv))
+      goto try_trace;
+    }
+   /* here since avoiding value store, need to add net change el. */
+   chg_st_scalval_(np->nva.bp, ngav, ngbv);
+   if (__lhs_changed) record_nchg_(np);
+  }
+ else
+  {
+   np = xp->lu.x->lu.sy->el.enp;
+   biti = (int32) __contab[xp->ru.x->ru.xvi];
+   /* if the 1 bit is forced nothing to do else normal assign */
+   if (np->frc_assgn_allocated
+    && __forced_inhibit_bitassign(np, xp->lu.x, xp->ru.x)) goto try_trace;
+   /* this adds the nchg el if needed */
+   __chg_st_bit(np, biti, ngav, ngbv);
+  }
+try_trace:
+ if (__ev_tracing) trace_chg_gateout(gp, xp);
+}
+
+/*
+ * write gate value unchanged when input changes trace msg
+ */
+static void trace_gunchg(struct gate_t *gp, word32 i)
+{
+ char s1[RECLEN];
+
+ __tr_msg("-- %s %s %s input %u value unchanged\n",
+  gp->gmsym->synam, (gp->g_class == GC_UDP) ? "udp" : "gate",
+  to_evtronam(s1, gp->gsym->synam, __inst_ptr, (struct task_t *) NULL), i);
+}
+
+/*
+ * evaluate a udp - std not optimized version
+ */
+static void std_chg_udp_gate(register struct gate_t *gp, register word32 i)
+{
+ register int32 is_edge;
+ int32 out_chg;
+
+ __cur_udp = gp->gmsym->el.eudpp;
+ is_edge = (__cur_udp->utyp == U_EDGE) ? TRUE : FALSE;
+ if (!__eval_udp(gp, i, &out_chg, is_edge))
+  { if (__ev_tracing) trace_gunchg(gp, i); return; }
+
+ if (__ev_tracing) evtr_prop_gatechg(gp, i, out_chg);
+ else
+  {
+   if (gp->g_delrep == DT_NONE)
+    { if (out_chg) change_gate_outwire(gp); return; }
+   prop_gatechg(gp, out_chg, FALSE);
+  }
+}
+
+/*
+ * evaluate a bufif gate - std not optimized version
+ */
+static void std_chg_bufif_gate(register struct gate_t *gp, register word32 i)
+{
+ int32 out_chg;
+
+ /* this sets __new_gateval to strength if out changed T */
+ if (!__eval_bufif_gate(gp, i, &out_chg))
+  { if (__ev_tracing) trace_gunchg(gp, i); return; }
+
+ if (__ev_tracing) evtr_prop_gatechg(gp, i, out_chg);
+ else
+  {
+   if (gp->g_delrep == DT_NONE)
+    { if (out_chg) change_gate_outwire(gp); return; }
+   prop_gatechg(gp, out_chg, FALSE);
+  }
+}
+
+/*
+ * evaluate a mos gate - std not optimized version
+ *
+ * g resist here is for real resistive gate not flag for acc
+ */
+static void std_chg_mos_gate(register struct gate_t *gp, register word32 i)
+{
+ register int32 out_chg, gid;
+
+ /* this sets __new_gateval to strength if out changed T */
+ if (!chg_mos_instate(gp, i))
+  { if (__ev_tracing) trace_gunchg(gp, i); return; }
+
+ out_chg = TRUE;
+ gid = gp->gmsym->el.eprimp->gateid;
+ switch (gid) {
+  case G_NMOS: __eval_nmos_gate(gp->gstate.wp[__inum]); break;
+  case G_RNMOS: __eval_rnmos_gate(gp->gstate.wp[__inum]); break;
+  case G_PMOS: __eval_pmos_gate(gp->gstate.wp[__inum]); break;
+  case G_RPMOS: __eval_rpmos_gate(gp->gstate.wp[__inum]); break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ if (__new_gateval == __old_gateval) out_chg = FALSE;
+
+ if (__ev_tracing) evtr_prop_gatechg(gp, i, out_chg);
+ else
+  {
+   if (gp->g_delrep == DT_NONE)
+    { if (out_chg) change_gate_outwire(gp); return; }
+   prop_gatechg(gp, out_chg, FALSE);
+  }
+}
+
+/*
+ * evaluate a cmos gate - std not optimized version
+ */
+static void std_chg_cmos_gate(register struct gate_t *gp, register word32 i)
+{
+ register int32 out_chg;
+
+ if (!chg_cmos_instate(gp, i))
+  { if (__ev_tracing) trace_gunchg(gp, i); return; }
+
+ /* this sets __new_gateval to strength if out changed T */
+ __eval_cmos_gate(gp);
+ if (__new_gateval == __old_gateval) out_chg = FALSE; else out_chg = TRUE;
+
+ if (__ev_tracing) evtr_prop_gatechg(gp, i, out_chg);
+ else
+  {
+   if (gp->g_delrep == DT_NONE)
+    { if (out_chg) change_gate_outwire(gp); return; }
+   prop_gatechg(gp, out_chg, FALSE);
+  }
+}
+
+/*
+ * routine used during prep to determine and set gate in change routine
+ * called for all including udp but not trans
+ */
+extern void __set_gchg_func(struct gate_t *gp)
+{
+ int32 acc_class;
+
+ switch ((byte) gp->g_class) {
+  case GC_LOGIC:
+   /* accelerate class is 2 for buf/not and 3 for any up to 4 logic gate */
+   /* 0 for cannot accelerate */
+   if (!__accelerate) gp->gchg_func = std_chg_logic_gate;
+   else
+    {
+     acc_class = __get_acc_class(gp);
+     switch ((byte) acc_class) {
+      case ACC_STD: gp->gchg_func = std_chg_logic_gate; break;
+      case ACC_BUFNOT: gp->gchg_func = acc_chg_bufnot; break;
+      case ACC_STIBUFNOT: gp->gchg_func = acc_stichg_bufnot; break;
+      case ACC_4IGATE: gp->gchg_func = acc_chg_4igate; break;
+      case ACC_ST4IGATE: gp->gchg_func = acc_stichg_4igate; break;
+      default: __case_terr(__FILE__, __LINE__);
+     }
+    }
+   break;
+  case GC_UDP: gp->gchg_func = std_chg_udp_gate; break;
+  case GC_BUFIF: gp->gchg_func = std_chg_bufif_gate; break;
+  case GC_MOS: gp->gchg_func = std_chg_mos_gate; break;
+  case GC_CMOS: gp->gchg_func = std_chg_cmos_gate; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * routine to turn off acceleration for logic gates when gate out terminal
+ * value change call back registered
+ */
+extern void __logic_acc_off(struct gate_t *gp)
+{
+ if (gp->g_class == GC_LOGIC && gp->gchg_func != std_chg_logic_gate)
+  gp->gchg_func = std_chg_logic_gate;
+}
+
+/*
+ * for gate that because of added vpi driver needs to be chaned to fi>1
+ * set the standard unoptimized gate assign routine
+ */
+extern void __vpi_set_chg_proc(struct gate_t *gp)
+{
+ /* if non logic gate, never optimized so can just use the std */
+ if (gp->g_class == GC_LOGIC)
+  {
+   if (gp->gchg_func != std_chg_logic_gate)
+    {
+     gp->gchg_func = std_chg_logic_gate;
+    }
+  }
+}
+
+/*
+ * return T if gate has accelerated action routine
+ */
+extern int32 __gate_is_acc(struct gate_t *gp)
+{
+ if (gp->gchg_func == acc_chg_bufnot || gp->gchg_func == acc_stichg_bufnot
+  || gp->gchg_func == acc_chg_4igate || gp->gchg_func == acc_stichg_4igate)
+  return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * propagate the gate change - normal version called when event tracing off
+ * complicated because of spike analysis
+ * this works for strength
+ * this assumed old and new gateval globals set before here
+ *
+ * if gate or udp drives highz[01] strength used to access delay but gate
+ * must drive actual value which is converted when assigned to wire
+ * outchg for highz[01] not changed since same hiz will be same 0 or 1
+ *
+ * show cancel e analysis uses gate output not possible hiz wire since 0/1
+ * glitch will just map to hiz spikes
+ *
+ * only called if know has delay and know old gateval and new gateval
+ * globals set
+ */
+static void prop_gatechg(register struct gate_t *gp, register int32 outchg,
+ int32 is_acc)
+{
+ i_tev_ndx tevpi;
+ word64 gdel, schtim;
+ struct tev_t *tevp;
+
+ /* no pending scheduled event */
+ if ((tevpi = gp->schd_tevs[__inum]) == -1)
+  {
+   /* case 1a: output changed */
+   if (outchg)
+    {
+     /* if 0 or 1 and hiz strength gate need to use to hiz delay */
+     if (gp->g_hasst && (__new_gateval & 2) == 0
+      && __hizstren_del_tab[gp->g_stval] == 1)
+      __hizstrengate_getdel(&gdel, gp);
+     else __get_del(&gdel, gp->g_du, gp->g_delrep);
+
+     schtim = __simtime + gdel;
+     schedule_1gev(gp, gdel, schtim, is_acc);
+    }
+   /* if output did not change, nothing to do */
+   return;
+  }
+
+ /* need time of new value scheduled change for this analysis */
+ if (gp->g_hasst && (__new_gateval & 2) == 0
+  && __hizstren_del_tab[gp->g_stval] == 1) __hizstrengate_getdel(&gdel, gp);
+ else __get_del(&gdel, gp->g_du, gp->g_delrep);
+
+ schtim = __simtime + gdel;
+
+ /* pending event */
+ tevp = &(__tevtab[tevpi]);
+ /* new and old same - scheduled different - real pulse/glitch */
+ if (!outchg)
+  {
+   if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+    emit_pulsewarn(gp, tevp, &(tevp->etime), &schtim, "drives glitch");
+
+   /* if spike, suppress future but schedule to x at currently scheduled */
+   if (__show_cancel_e)
+    {
+     if (__showe_onevent)
+      { tevp->outv = get_showcancele_val(gp); return; }
+
+     /* immediate assign then cancel */
+on_detect_show_x:
+     __new_gateval = get_showcancele_val(gp);
+     if (tevp->gev_acc) acc_evchg_gate_outwire(gp);
+     else change_gate_outwire(gp);
+     /* newly scheduled to same so no event */
+     tevp->te_cancel = TRUE;
+     __inertial_cancels++;
+     gp->schd_tevs[__inum] = -1;
+     return;
+    }
+   /* newly scheduled to same so no event */
+   tevp->te_cancel = TRUE;
+   __inertial_cancels++;
+   gp->schd_tevs[__inum] = -1;
+   return;
+  }
+ /* new schedule to same value case */
+ /* know that delay same and later so just discard new event */
+ /* done silently here - trace message only */
+ if (tevp->outv == (byte) __new_gateval) return;
+
+ /* normal inertial reschedule */
+ if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+  emit_pulsewarn(gp, tevp, &(tevp->etime), &schtim, "unstable");
+
+ if (__show_cancel_e)
+  {
+   if (__showe_onevent) { tevp->outv = get_showcancele_val(gp); return; }
+   goto on_detect_show_x;
+  }
+ /* reschedule - handles cancel */
+ tevpi = reschedule_1gev(tevpi, gdel, schtim, __new_gateval, is_acc);
+}
+
+/*
+ * propagate the gate change
+ * complicated because of show cancel e analysis
+ *
+ * notice new gateval and old gateval set and has strength value if present
+ * see prop gatechg routines for more comments
+ * unlike prop_gatechg, this must be called for DT_NONE assigns
+ * all events scheduled from here must not set event accelerate bit
+ *
+ * SJM 11/27/00 - this always calls or schedules change gate outwire where
+ * the gate terminal call back is checked so do not need separate code
+ */
+static void evtr_prop_gatechg(register struct gate_t *gp, register word32 i,
+ int32 outchg)
+{
+ i_tev_ndx tevpi;
+ word64 gdel, schtim;
+ struct tev_t *tevp;
+ char vs1[10], vs2[10], vs3[10];
+ char s1[RECLEN], s2[RECLEN];
+
+ __tr_msg("-- %s gate %s input %d changed to %s:\n",
+  gp->gmsym->synam, to_evtronam(s1, gp->gsym->synam, __inst_ptr,
+  (struct task_t *) NULL), i, __to_ginam(vs1, gp, __new_inputval, i));
+
+ /* case 0: gate has no delay - not even #0 */
+ if (gp->g_delrep == DT_NONE)
+  {
+   if (!outchg) { __tr_msg(" NODEL, NOCHG\n"); return; }
+
+   /* this assigns or schedules the 1 bit net change */
+   __tr_msg(" NODEL <OV=%s, NV=%s>\n",
+    __to_gonam(vs1, gp, __old_gateval), __to_gonam(vs2, gp, __new_gateval));
+   change_gate_outwire(gp);
+   return;
+  }
+
+ /* need time of new value scheduled change for this analysis */
+ if (gp->g_hasst && (__new_gateval & 2) == 0
+  && __hizstren_del_tab[gp->g_stval] == 1) __hizstrengate_getdel(&gdel, gp);
+ else __get_del(&gdel, gp->g_du, gp->g_delrep);
+ schtim = __simtime + gdel;
+
+ /* case 1: no pending scheduled event */
+ if ((tevpi = gp->schd_tevs[__inum]) == -1)
+  {
+   /* output did not change */
+   if (!outchg)
+    {
+     /* no net change and must cancel any already scheduled event */
+     __tr_msg(" DEL, NOCHG <OV=%s>\n",
+      __to_gonam(vs1, gp, __old_gateval));
+     return;
+    }
+   __tr_msg(" DEL, SCHD AT %s <OV=%s, NSV=%s>\n",
+    __to_timstr(s1, &schtim), __to_gonam(vs1, gp, __old_gateval),
+    __to_gonam(vs2, gp, __new_gateval));
+   /* schedule */
+   schedule_1gev(gp, gdel, schtim, FALSE);
+   return;
+  }
+ /* pending event */
+ tevp = &(__tevtab[tevpi]);
+ /* new and old same - scheduled different - real pluse/glitch */
+ if (!outchg)
+  {
+   if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+    emit_pulsewarn(gp, tevp, &(tevp->etime), &schtim, "drives glitch");
+
+   /* if spike on set to x at time of previous change not inertial */
+   if (__show_cancel_e)
+    {
+     if (__showe_onevent) sprintf(s2, "%s (on event)", __to_timstr(__xs,
+      &(tevp->etime)));
+     else sprintf(s2, "%s (on detect)", __to_timstr(__xs, &__simtime));
+     __tr_msg(
+      " DEL, PEND AT %s PULSE <OV=NSV=%s, OSV=%s SHOWING X AT %s MAYBE SWITCHED>\n",
+      __to_timstr(s1, &(tevp->etime)), __to_gonam(vs1, gp, __old_gateval),
+      __to_gonam(vs2, gp, tevp->outv), s2);
+
+     if (__showe_onevent)
+      { tevp->outv = get_showcancele_val(gp); return; }
+
+     /* immediate assign then cancel */
+on_detect_show_x:
+     __new_gateval = get_showcancele_val(gp);
+     if (tevp->gev_acc) acc_evchg_gate_outwire(gp);
+     else change_gate_outwire(gp);
+     /* newly scheduled to same so no event */
+     tevp->te_cancel = TRUE;
+     __inertial_cancels++;
+     gp->schd_tevs[__inum] = -1;
+     return;
+    }
+   /* newly scheduled to same (pulse) so no event */
+   tevp->te_cancel = TRUE;
+   __inertial_cancels++;
+   gp->schd_tevs[__inum] = -1;
+   /* SJM 01/21/02 - msg unclear since new sched value was missing */
+   __tr_msg(" DEL, PEND, PULSE, INERTIAL CANCEL AT %s <OV=%s, OSV=%s NSV=%s>\n",
+    __to_timstr(s1, &(tevp->etime)), __to_gonam(vs1, gp, __old_gateval),
+    __to_gonam(vs2, gp, tevp->outv), __to_gonam(vs3, gp, __new_gateval));
+   return;
+  }
+
+ /* new schedule to same value case */
+ /* know that delay same and later so just discard new event */
+ /* done silently here - trace message only */
+ if (tevp->outv == (byte) __new_gateval)
+  {
+   __tr_msg(
+    " DEL, MODEL ANOMALLY IGNORE SCHED TO SAME <OSV=NSV=%s> OLD AT %s NEW %s\n",
+    __to_gonam(vs1, gp, __new_gateval), __to_timstr(s1, &(tevp->etime)),
+    __to_timstr(s2, &schtim));
+   return;
+  }
+
+ /* normal inertial reschedule */
+ if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+  emit_pulsewarn(gp, tevp, &(tevp->etime), &schtim, "unstable");
+
+ if (__show_cancel_e)
+  {
+   if (__showe_onevent) __to_timstr(s2, &schtim);
+   else __to_timstr(s2, &__simtime);
+   if (__showe_onevent) sprintf(s1, "%s (on event)", __to_timstr(__xs,
+    &(tevp->etime)));
+   else sprintf(s1, "%s (on detect)", __to_timstr(s1, &__simtime));
+   __tr_msg(
+    " DEL, PEND AT %s, UNSTABLE <OV=%s, OSV=%s, NSV=%s SHOWING X AT %s MAYBE SWITCHED>\n",
+    __to_timstr(s1, &(tevp->etime)), __to_gonam(vs1, gp, __old_gateval),
+    __to_gonam(vs2, gp, tevp->outv), __to_gonam(vs3, gp, __new_gateval), s2);
+
+   if (__showe_onevent) { tevp->outv = get_showcancele_val(gp); return; }
+   goto on_detect_show_x;
+  }
+
+ __tr_msg(" DEL, PEND, UNSTABLE RESCHD <OV=%s, OSV=%s AT %s, NSV=%s AT %s>\n",
+  __to_gonam(vs1, gp, __old_gateval),
+  __to_gonam(vs2, gp, tevp->outv), __to_timstr(s1, &(tevp->etime)),
+  __to_gonam(vs3, gp, __new_gateval), __to_timstr(s2, &schtim));
+ tevpi = reschedule_1gev(tevpi, gdel, schtim, __new_gateval, FALSE);
+}
+
+/*
+ * compute show cancel x value depending on gate class and strength
+ *
+ * idea is to change event change to value but time still start of
+ * region after place where gate may or may not have switched
+ */
+static word32 get_showcancele_val(struct gate_t *gp)
+{
+ int32 nd_stren = FALSE;
+
+ switch ((byte) gp->g_class) {
+  /* these never have strength value */
+  case GC_LOGIC: case GC_UDP:
+   if (gp->g_hasst) nd_stren = TRUE;
+   break;
+  case GC_BUFIF: nd_stren = TRUE; break;
+  case GC_MOS: case GC_CMOS:
+   /* LOOKATME - since mos gates pass strength for now driving strong x */
+   /* maybe could take strength from input? and leave z */
+   return(ST_STRONGX);
+  /* for tranif input spike sched. only, x is turned off (0) */
+  case GC_TRANIF: return(0);
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ /* notice no need to correct for possible highz strength since value x */
+ /* SJM 08/07/01 - this works because with val x need both 0 and 1 strens */
+ if (nd_stren) return((gp->g_stval << 2) | 3);
+ return(3);
+}
+
+/*
+ * emit an object name for tracing with path
+ * cannot use __xs in here
+ */
+static char *to_evtronam(char *s, char *onam, struct itree_t *teitp,
+ struct task_t *tskp)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ sprintf(s, "%s.%s", __msg_blditree(s2, teitp, tskp), __schop(s1, onam));
+ return(s);
+}
+
+/*
+ * schedule 1 gate event
+ * expects __new_gateval to contain value to schedule to
+ */
+static i_tev_ndx schedule_1gev(register struct gate_t *gp, word64 gdel,
+ word64 schtim, int32 is_acc)
+{
+ register i_tev_ndx tevpi;
+ register struct tev_t *tevp;
+
+ alloc_tev_(tevpi, TE_G, __inst_ptr, schtim);
+ if (gdel == 0ULL)
+  {
+   /* this is #0, but must still build tev */
+   if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+   else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+  }
+ else __insert_event(tevpi);
+
+ gp->schd_tevs[__inum] = tevpi;
+ tevp = &(__tevtab[tevpi]);
+ tevp->tu.tegp = gp;
+ /* if logic or udp, no strength, event processing assign will handle */
+ /* if bufif, mos or cmos, know has strength, if tranif conducting state */
+ tevp->outv = (byte) __new_gateval;
+ /* acc. store only if gate is acc. and no conn. wire delay (resist off) */
+ /* is acc T only if called from acc routine because acc routine never */
+ /* possible for real resistive mos or tran */
+ /* for mos with delay, can get here with g pdst on but is acc off */
+ tevp->gev_acc = (is_acc && !gp->g_pdst);
+ return(tevpi);
+}
+
+/*
+ * take event and new value and either update if time same or cancel and
+ * create new event if later
+ */
+static i_tev_ndx reschedule_1gev(i_tev_ndx tevpi, word64 gdel, word64 newtim,
+ word32 newoutv, int32 is_acc)
+{
+ struct tev_t *tevp;
+
+ tevp = &(__tevtab[tevpi]);
+ /* if del == 0 (pnd0), will always be same time reschedule */
+ if (gdel == 0ULL)
+  {
+   /* new value replaces old - must also be in event */
+   __newval_rescheds++;
+   tevp->outv = (byte) newoutv;
+   return(tevpi);
+  }
+
+ /* case 3c-3 - more in future, cancel and reschedule */
+ tevp->te_cancel = TRUE;
+ __inertial_cancels++;
+ tevpi = schedule_1gev(tevp->tu.tegp, gdel, newtim, is_acc);
+ tevp->outv = (byte) newoutv;
+ return(tevpi);
+}
+
+/*
+ * emit the pulse (inertial reschedule) warning if not turned off
+ * types are drives for normal spike and unstable for change that does not
+ * do anything but interfere with transition
+ */
+static void emit_pulsewarn(struct gate_t *gp, struct tev_t *tevp,
+ word64 *etim, word64 *newetim, char *sptnam)
+{
+ char s1[RECLEN], s2[RECLEN], s3[10], s4[10], s5[10];
+
+ /* must turn on spike analysis */
+ if (__show_cancel_e)
+  {
+   if (__showe_onevent) strcpy(s1, " - edge event to x");
+   else strcpy(s1, " - now detect to x");
+  }
+ else strcpy(s1, "");
+
+ sprintf(s2, "old %s, scheduled %s, new %s%s",
+  __to_gonam(s3, gp, __old_gateval), __to_gonam(s4, gp, tevp->outv),
+  __to_gonam(s5, gp, __new_gateval), s1);
+ /* notice spike means new and old the same */
+ __gfwarn(592, gp->gsym->syfnam_ind, gp->gsym->sylin_cnt,
+  "%s gate %s.%s %s (edge at %s replaced by new at %s) - %s",
+  gp->gmsym->synam, __msg2_blditree(s1, tevp->teitp), gp->gsym->synam,
+   sptnam, __to_timstr(__xs, etim), __to_timstr(__xs2, newetim), s2);
+}
+
+word32 __pow3tab[] = { 1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049 };
+
+/*
+ * process a gate change event - new level has reached output
+ * know thing connected to gate output is 1 bit (bit select if needed)
+ * but maybe has strength
+ */
+static void process_gatechg_ev(register struct tev_t *tevp)
+{
+ register struct gate_t *gp;
+
+ /* notice event here emitted in change gate outwire */
+ gp = tevp->tu.tegp;
+ __new_gateval = tevp->outv;
+ if (__ev_tracing) emit_gev_trace(gp, tevp);
+ gp->schd_tevs[__inum] = -1;
+ /* this handle added the 1 bit net change */
+ if (tevp->gev_acc) acc_evchg_gate_outwire(gp);
+ else change_gate_outwire(gp);
+}
+
+/*
+ * accelerated routine for assigning a xl type simple gate event
+ *
+ * if assigned to net fi>1 (maybe from run time vpi_put_value) or has
+ * delay can not use accelerated event processing
+ * this requires new value in new gateval global
+ */
+static void acc_evchg_gate_outwire(register struct gate_t *gp)
+{
+ register struct expr_t *xp;
+ register word32 uwrd, ngav, ngbv;
+ register struct net_t *lhsnp;
+ int32 biti, gwid;
+ word32 igav, igbv;
+
+ __immed_assigns++;
+ ngav = __new_gateval & 1L;
+ ngbv = __new_gateval >> 1;
+ xp = gp->gpins[0];
+ uwrd = (word32) gp->gstate.bp[__inum];
+ if ((gwid = gp->gpnum) < 3)
+  {
+   /* update state with computed output value is bits 1 and 3 */
+   uwrd = uwrd & ~(0xaL);
+   uwrd |= ((ngav << 1) | (ngbv << 3));
+  }
+ else
+  {
+   /* mask off separated value bits to update output value in uwrd */
+   uwrd = uwrd & ~(1L << (gwid - 1)) & ~(1L << (2*gwid - 1));
+   /* works because ngav and ngbv exactly 1 low bit */
+   uwrd |= ((ngav << (gwid - 1)) | (ngbv << (2*gwid - 1)));
+  }
+ gp->gstate.bp[__inum] = (byte) uwrd;
+
+ /* accelerated assign to pin 0 (output) */
+ if (xp->optyp == ID)
+  {
+   lhsnp = xp->lu.sy->el.enp;
+   if (lhsnp->frc_assgn_allocated)
+    {
+     igav = ngav; igbv = ngbv;
+     if (!__correct_forced_newwireval(lhsnp, &igav, &igbv))
+      goto try_trace;
+    }
+   /* here since avoiding value store, need to add net change el. */
+   chg_st_scalval_(lhsnp->nva.bp, ngav, ngbv);
+   if (__lhs_changed) record_nchg_(lhsnp);
+  }
+ else
+  {
+   lhsnp = xp->lu.x->lu.sy->el.enp;
+   biti = (int32) __contab[xp->ru.x->ru.xvi];
+   /* if the 1 bit is forced nothing to do else normal assign */
+   if (lhsnp->frc_assgn_allocated
+    && __forced_inhibit_bitassign(lhsnp, xp->lu.x, xp->ru.x)) goto try_trace;
+   /* notice this adds the net chg element if needed */
+   __chg_st_bit(lhsnp, biti, ngav, ngbv);
+  }
+try_trace:
+ if (__ev_tracing) trace_chg_gateout(gp, xp);
+}
+
+/*
+ * emit gate event process trace message
+ */
+static void emit_gev_trace(struct gate_t *gp, struct tev_t *tevp)
+{
+ char s1[RECLEN], s2[RECLEN], vs1[10];
+
+ __evtr_resume_msg();
+ if (gp->gpins[0]->x_multfi) strcpy(s2, "this driver of multiple:");
+ else strcpy(s2, "the fi=1 driver:");
+ __tr_msg("-- %s gate %s processing store event to output, %s %s\n",
+  gp->gmsym->synam, to_evtronam(s1, gp->gsym->synam, tevp->teitp,
+  (struct task_t *) NULL), s2, __to_gonam(vs1, gp, __new_gateval));
+}
+
+/*
+ * add a net change record when entire net changes(usually scalar)
+ *
+ * add to end of next pass, netchg list elements
+ * notice this needs itstk of target wire for xmr
+ */
+extern void __add_nchglst_el(register struct net_t *np)
+{
+ register struct nchglst_t *nchglp;
+
+ if (__nchgfreelst == NULL)
+  nchglp = (struct nchglst_t *) __my_malloc(sizeof(struct nchglst_t));
+ else
+  {
+   nchglp = __nchgfreelst;
+   __nchgfreelst = __nchgfreelst->nchglnxt;
+
+   /* DBG LINUX ADDME ??? */
+   /* chk_nchgnlst(__nchgfreelst); */
+   /* --- */
+  }
+
+ /* only turn on bit if all changed, each subrange goes on by itself */
+ nchglp->chgnp = np;
+ nchglp->nchg_itp = __inst_ptr;
+ nchglp->bi1 = -1;
+ nchglp->delayed_mipd = FALSE;
+
+ /* all needed change info for this time slot now records */
+ np->nchgaction[__inum] |= NCHG_ALL_CHGED;
+
+ nchglp->nchglnxt = NULL;
+ /* LOOKATME - maybe add dummy list element on front to avoid comparison */
+ if (__nchg_futend != NULL)
+  { __nchg_futend->nchglnxt = nchglp; __nchg_futend = nchglp; }
+ else __nchg_futhdr = __nchg_futend = nchglp;
+
+ /* DBG remove --- */
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg("-- added net change element %s\n",
+    __to_evtrwnam(__xs, np, -1, -1, __inst_ptr));
+  }
+ /* --- */
+}
+
+/*
+ * add a net change record select range (usually bit) changed
+ *
+ * add to end of next pass, netchg list elements
+ * notice this needs inst. loc of target wire for xmr
+ */
+extern void __add_select_nchglst_el(register struct net_t *np, register int32 i1,
+ register int32 i2)
+{
+ register struct nchglst_t *nchglp;
+
+ if (__nchgfreelst == NULL)
+  nchglp = (struct nchglst_t *) __my_malloc(sizeof(struct nchglst_t));
+ else
+  {
+   nchglp = __nchgfreelst;
+   __nchgfreelst = __nchgfreelst->nchglnxt;
+   /* DBG LINUX ADDME */
+   /* chk_nchgnlst(__nchgfreelst); */
+   /* --- */
+  }
+
+ /* only turn on bit if all changed, each subrange goes on by itself */
+ nchglp->chgnp = np;
+ nchglp->nchg_itp = __inst_ptr;
+ nchglp->bi1 = i1;
+ nchglp->bi2 = i2;
+
+ /* here since range not marked as all changed so will match ranges */
+
+ /* link on end since good heuristic to process in change order */
+ nchglp->nchglnxt = NULL;
+ /* LOOKATME - maybe add dummy list element on front to avoid comparison */
+ if (__nchg_futend != NULL)
+  { __nchg_futend->nchglnxt = nchglp; __nchg_futend = nchglp; }
+ else __nchg_futhdr = __nchg_futend = nchglp;
+
+ /* DBG remove ---
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg("-- added net change element %s\n",
+    __to_evtrwnam(__xs, np, i1, i2, __inst_ptr));
+  }
+ --- */
+}
+
+/*
+ * add a dumpvars change element
+ * only called first time for entire net in time slot
+ */
+extern void __add_dmpv_chglst_el(struct net_t *np)
+{
+ register struct dvchgnets_t *dvchgp;
+
+ if (__dv_netfreelst == NULL)
+   dvchgp = (struct dvchgnets_t *) __my_malloc(sizeof(struct dvchgnets_t));
+ else
+  {
+   dvchgp = __dv_netfreelst;
+   __dv_netfreelst = __dv_netfreelst->dvchgnxt;
+  }
+ /* indicate for this time slot inst of var already changed once */
+ np->nchgaction[__inum] &= ~(NCHG_DMPVNOTCHGED);
+ /* set the net and link the change on the front */
+ dvchgp->dvchg_np = np;
+ dvchgp->dvchg_itp = __inst_ptr;
+
+ /* link on front since order does not matter */
+ dvchgp->dvchgnxt = __dv_chgnethdr;
+ __dv_chgnethdr = dvchgp;
+ /* must indicate need for end of slot dv processing */
+ __slotend_action |= SE_DUMPVARS;
+}
+
+/*
+ * assign gate output to driven wire
+ * this assumes __new_gateval previously set
+ * works for both 8 bit strength and 2 bit non strength values
+ *
+ * notice simultaneously when changing wire (or scheduling if wire has delay)
+ * must store gate state output - needed since when evaluating driver for
+ * gate with delay need previous until actual store
+ */
+static void change_gate_outwire(register struct gate_t *gp)
+{
+ register word32 *wp;
+ register struct expr_t *xp;
+ register int32 bi, wi;
+ int32 schd_wire, nins, srep;
+ hword *hwp;
+ word32 av, bv;
+ byte sb2, *sbp;
+ word32 uwrd;
+ struct xstk_t *xsp;
+
+ __immed_assigns++;
+ xp = gp->gpins[0];
+ switch ((byte) gp->g_class) {
+  case GC_LOGIC:
+   /* SJM 02/07/01 - remove st gstate out routine since only for logic */
+   /* this removes inner loop case stmt */
+
+   /* must store new gate value into state here - value does not have stren */
+   nins = gp->gpnum - 1;
+   if (nins > 15) srep = SR_VEC; else srep = SR_PVEC;
+   /* FIXME - why are these not wrd? */
+   av = ((word32) __new_gateval) & 1;
+   bv = ((word32) __new_gateval) >> 1;
+   gate_st_bit(gp->gstate, nins + 1, nins, srep, av, bv);
+   break;
+  case GC_UDP:
+   /* new gateval for udp does not have strength - maybe added in store */
+   /* tricky part for wide udp's - must update running signature if present */
+   __cur_udp = gp->gmsym->el.eudpp;
+   nins = __cur_udp->numins;
+   bi = 2*nins;
+   /* comb means no state - edge always has state */
+   if (__cur_udp->u_wide)
+    {
+     wp = &(gp->gstate.wp[2*__inum]);
+     /* update running 2nd state signature word32 */
+     if (__cur_udp->utyp != U_COMB)
+      {
+       /* need to access old gate value (out about to change) */
+       /* since for event schedule will not be stored */
+       /* during initialize this will be meaningless 0 */
+       __old_gateval = (wp[0] >> (2*nins)) & 3L;
+
+       /* correct running index of output since part of state if not comb. */
+       /* num ins is index of state */
+       /* subtract off old contribution of state output */
+       wp[1] -= ((__old_gateval == 3) ? 2 : __old_gateval)*__pow3tab[nins];
+       /* add in new contribution of state output */
+       wp[1] += ((__new_gateval == 3) ? 2 : __new_gateval)*__pow3tab[nins];
+      }
+     /* update first value word32 */
+     wp[0] &= ~(3L << bi);
+     wp[0] |= (__new_gateval << bi);
+    }
+   /* do the the gate state output store */
+   /* udp state stored as nins 2 bit vals + out/state 2 bits */
+   else
+    {
+     hwp = &(gp->gstate.hwp[__inum]);
+     /* -- RELASE remove
+     if (__debug_flg && __ev_tracing)
+      __tr_msg("-- st udp out old %x\n", *hwp);
+     -- */
+     *hwp &= ~(3 << bi);
+     *hwp |= (hword) (__new_gateval << bi);
+     /* -- RELEASE remove ---
+     if (__debug_flg && __ev_tracing)
+      __tr_msg(" new %x\n", *hwp);
+     -- */
+    }
+   break;
+  case GC_BUFIF:
+   /* store new gate val into bufif state - here must merge in stren */
+   hwp = &(gp->gstate.hwp[__inum]);
+   hwp[0] &= ~(0xff << 4);
+   hwp[0] |= ((hword) (__new_gateval << 4));
+   goto do_hasstren_assign;
+  case GC_MOS:
+   /* store new gate val into mos state */
+   wp = &(gp->gstate.wp[__inum]);
+   wp[0] &= ~(0xff << 16);
+   wp[0] |= (__new_gateval << 16);
+   goto do_hasstren_assign;
+  case GC_CMOS:
+   /* store new gate val into cmos state */
+   wp = &(gp->gstate.wp[__inum]);
+   wp[0] &= ~(0xff << 24);
+   wp[0] |= (__new_gateval << 24);
+
+do_hasstren_assign:
+   /* then assign - here strength variable and new gateval has strength */
+   if (xp->x_multfi) __mdr_assign_or_sched(xp);
+   else
+    {
+     if (xp->lhsx_ndel && !__wire_init) schd_wire = TRUE;
+     else schd_wire = FALSE;
+
+     /* 07/08/00 - if gate (always 1 bit) drives wider vec must initialize */
+     /* other bits to z since only has 1 driver */
+     push_xstk_(xsp, 4*xp->szu.xclen);
+     sbp = (byte *) xsp->ap;
+     set_byteval_(sbp, xp->szu.xclen, ST_HIZ);
+     /* set the low bit */
+     sbp[0] = (byte) __new_gateval;
+     __exec_conta_assign(xp, (word32 *) sbp, (word32 *) NULL, schd_wire);
+     __pop_xstk();
+    }
+   goto done;
+  case GC_TRANIF:
+   /* out wire here is conducting state from 3rd input */
+   /* SJM 12/13/00 - serious malloc bug was using bit ofset */
+   wi = get_wofs_(2*__inum);
+   bi = get_bofs_(2*__inum);
+   /* 2 bits give conducting state */
+   if (__new_gateval == 2) __new_gateval = 3;
+   gp->gstate.wp[wi] &= ~(3L << bi);
+   gp->gstate.wp[wi] |= (__new_gateval << bi);
+   if (__ev_tracing)
+    {
+     __tr_msg("-- relaxing %s in switch channel\n",
+      __gstate_tostr(__xs, gp, TRUE));
+    }
+   /* tranif enable changed must evaluate channel */
+   /* LOOKATME think this only needs to be called if from/to 0, x same as 1 */
+   /* SJM 04/11/00 - put back so immediately perturb both terminal vertices */
+   __immed_eval_trifchan(gp);
+   return;
+  /* tran can never get here */
+  default: __case_terr(__FILE__, __LINE__);
+ }
+
+ /* store gate or udp where value maybe needs constant strength added */
+ /* gate state now updated, must assign to wire or schedule assign */
+ if (xp->x_multfi) __mdr_assign_or_sched(xp);
+ else
+  {
+   /* even though decl. no need for z extend since 1 bit max. wide */
+   if (xp->lhsx_ndel && !__wire_init) schd_wire = TRUE;
+   else schd_wire = FALSE;
+   /* notice lhs cannot be concat here and know source and dest 1 bit */
+   if (xp->x_stren)
+    {
+     /* here any strength constant */
+     /* notice always need to add strength logic gate cannot drive z */
+     if (__new_gateval == 2) sb2 = 2;
+     else
+      {
+       /* notice tran that uses g st val for mark never goes here */
+       uwrd = __new_gateval | (gp->g_stval << 2);
+       uwrd = (word32) __stren_map_tab[uwrd];
+       sb2 = (byte) uwrd;
+      }
+     /* 07/08/00 - if gate (always 1 bit) drives wider vec must initialize */
+     /* other bits to z since only has 1 driver */
+     push_xstk_(xsp, 4*xp->szu.xclen);
+     sbp = (byte *) xsp->ap;
+     set_byteval_(sbp, xp->szu.xclen, ST_HIZ);
+     /* set the low bit */
+     sbp[0] = sb2;
+     __exec_conta_assign(xp, (word32 *) sbp, (word32 *) NULL, schd_wire);
+     __pop_xstk();
+    }
+   else
+    {
+     av = __new_gateval & 1L;
+     bv = __new_gateval >> 1;
+     /* assign needed although only bit select or 1 bit wire, can be xmr */
+     __exec_conta_assign(xp, &av, &bv, schd_wire);
+    }
+  }
+
+done:
+ /* SJM 11/27/00 - know out changed, state has been updated and strength */
+ /* competition done to set new wire value - this call back monitors the */
+ /* gate state so it does ont matter if after wire changed */
+ if (__have_vpi_gateout_cbs)
+  {
+   int32 gi, tevpi;
+
+   gi = gp - __inst_mod->mgates;
+   if (__inst_mod->mgateout_cbs != NULL && __inst_mod->mgateout_cbs[gi] != NULL
+    && (tevpi = __inst_mod->mgateout_cbs[gi][__inum]) != -1)
+    {
+     __exec_vpi_gateoutcbs(tevpi);
+    }
+  }
+
+ if (__ev_tracing) trace_chg_gateout(gp, xp);
+}
+
+/*
+ * trace message after change gate outwire
+ */
+static void trace_chg_gateout(struct gate_t *gp, struct expr_t *xp)
+{
+ char s1[RECLEN], s2[RECLEN], vs1[10], vs2[10];
+
+ if (xp->lhsx_ndel && !__wire_init) strcpy(vs1, "schedule");
+ else strcpy(vs1, "assign");
+ if (gp->g_class == GC_UDP) strcpy(vs2, "udp"); else strcpy(vs2, "gate");
+ __tr_msg("-- %s %s event output %s, %s to %s\n", vs1,
+  __gstate_tostr(__xs, gp, TRUE), vs2, __to_gassign_str(s1, xp),
+  __msgexpr_tostr(s2, xp));
+}
+
+/* SJM 02/07/01 - removed st gstate out routine - moved only used logic */
+
+/*
+ * store into coded wp of length blen at biti for current instance
+ * that is stored according to srep format from low 2 bits of rgap
+ * notice bits are separated into a and b parts in gate representation
+ *
+ * this differs from lhs bit select in accessing value for current instance
+ * and adjusting place to select from according to storage representation
+ * cannot be used to access array or strength value and called
+ * with know good index (not -1)
+ * this is for logic gates only
+ */
+static void gate_st_bit(union pck_u pckv, int32 blen, int32 biti, int32 srep,
+ register word32 av, register word32 bv)
+{
+ register word32 uwrd, ouwrd;
+ word32 *rap;
+ int32 wlen;
+
+ /* this is same as full value store - biti 0 or will not get here */
+ switch ((byte) srep) {
+  case SR_SCAL: gate_st_scalval(pckv.wp, av, bv); return;
+  case SR_VEC:
+   wlen = wlen_(blen);
+   /* rap is base of vector for current inst */
+   rap = &(pckv.wp[2*wlen*__inum]);
+   __lhsbsel(rap, biti, av);
+   __lhsbsel(&(rap[wlen]), biti, bv);
+   return;
+  case SR_PVEC:
+   /* SJM 12/19/99 - notice gates still packed into bp, hwp, wp not just word32 */
+   ouwrd = get_packintowrd_(pckv, __inum, blen);
+   uwrd = ouwrd & ~(1L << biti) & ~(ouwrd & (1L << (blen + biti)));
+   uwrd |= ((av & 1L) << biti) | ((bv & 1L) << (blen + biti));
+   if (uwrd != ouwrd)
+    {
+     st_packintowrd_(pckv, __inum, uwrd, blen);
+    }
+   return;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * store a gate packed into 2 bits scalar
+ * coded as 2 contiguous bits per instance
+ * assuming shift by 0 legal and gets right answer in C
+ */
+static void gate_st_scalval(register word32 *wp, register word32 av,
+ register word32 bv)
+{
+ register int32 bi;
+ int32 dbi, dwi;
+
+ bi = 2*__inum;
+ dwi = get_wofs_(bi);
+ dbi = get_bofs_(bi);
+ wp[dwi] &= ~(3L << dbi);
+ wp[dwi] |= ((av | (bv << 1)) << dbi);
+}
+
+/*
+ * change input i part of gstate vector for mos style gate
+ * strens passed thru so must load with stren even if driver no stren
+ * returns false if new input value is same as old
+ * this requires correct cur. itp
+ */
+static int32 chg_mos_instate(register struct gate_t *gp, word32 i)
+{
+ register word32 uwrd;
+ register struct expr_t *ndp;
+ register byte *sbp;
+ struct xstk_t *xsp;
+
+ uwrd = gp->gstate.wp[__inum];
+ /* split because change scheduled or assigned if only strength changed */
+ if (i == 1)
+  {
+   ndp = gp->gpins[1];
+   /* if port a reg cannot have strength, this will add strong */
+   xsp = __ndst_eval_xpr(ndp);
+   sbp = (byte *) xsp->ap;
+   __new_inputval = sbp[0];
+   __pop_xstk();
+   __old_inputval = uwrd & 0xffL;
+   if (__new_inputval == __old_inputval) return(FALSE);
+   uwrd &= ~0xffL;
+   uwrd |= __new_inputval;
+  }
+ else
+  {
+   /* control input should not have strength but if does ignored */
+   xsp = __eval_xpr(gp->gpins[2]);
+   __new_inputval = (xsp->ap[0] & 1L) | ((xsp->bp[0] & 1L) << 1);
+   __pop_xstk();
+   __old_inputval = (uwrd >> 8) & 3L;
+   if (__new_inputval == __old_inputval) return(FALSE);
+   uwrd &= ~(3L << 8);
+   uwrd |= (__new_inputval << 8);
+  }
+ gp->gstate.wp[__inum] = uwrd;
+ return(TRUE);
+}
+
+/*
+ * change input i part of gstate vector for cmos 2 ctrl input style gate
+ * strens passed thru so must load with stren even if driver no stren
+ * returns false if new input value is same as old
+ * this requires correct cur. itp
+ *
+ * format is 3 8 bit values (0th input data, 1 nmos in, 2 pmos in, 3 output)
+ * but only 2 bits of 1st and 2nd control inputs used
+ * notice input starts at 1 because output is pos. 0
+ */
+static int32 chg_cmos_instate(register struct gate_t *gp, word32 i)
+{
+ register word32 uwrd;
+ register byte *sbp;
+ register struct expr_t *ndp;
+ register struct xstk_t *xsp;
+
+ uwrd = gp->gstate.wp[__inum];
+ /* split because change scheduled or assigned if only strength changed */
+ if (i == 1)
+  {
+   ndp = gp->gpins[1];
+   xsp = __ndst_eval_xpr(ndp);
+   sbp = (byte *) xsp->ap;
+   __new_inputval = sbp[0];
+   __pop_xstk();
+   __old_inputval = uwrd & 0xffL;
+   if (__new_inputval == __old_inputval) return(FALSE);
+   uwrd &= ~0xffL;
+   uwrd |= __new_inputval;
+  }
+ else
+  {
+   /* control inputs should not have strength but if does removed */
+   xsp = __eval_xpr(gp->gpins[i]);
+   __new_inputval = (xsp->ap[0] & 1L) | ((xsp->bp[0] & 1L) << 1);
+   __pop_xstk();
+   if (i == 2)
+    {
+     /* n ctrl bits 15-8 */
+     __old_inputval = (uwrd >> 8) & 3L;
+     if (__new_inputval == __old_inputval) return(FALSE);
+     uwrd &= ~(3L << 8);
+     uwrd |= (__new_inputval << 8);
+    }
+   else
+    {
+     /* p ctrl bits 23-16 */
+     __old_inputval = (uwrd >> 16) & 3L;
+     if (__new_inputval == __old_inputval) return(FALSE);
+     uwrd &= ~(3L << 16);
+     uwrd |= (__new_inputval << 16);
+    }
+  }
+ gp->gstate.wp[__inum] = uwrd;
+ return(TRUE);
+}
+
+/*
+ * TRANIF EVALUATION ROUTINES
+ */
+
+/*
+ * evaluate tranif when third enable port changes
+ */
+extern void __eval_tranif_ld(register struct gate_t *gp, register int32 i)
+{
+ int32 out_chg;
+
+ /* DBG remove */
+ if (i != 2) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ /* third in chged - schedule (if needed) conducting state chg */
+ /* must always go through scheduling code for spike analysis */
+ eval_tranif_onoff(gp);
+ /* out_chg T if conducting state changed */
+ out_chg = (__new_gateval != __old_gateval);
+ /* must evaluate both sides */
+ if (gp->g_delrep == DT_NONE)
+  { if (out_chg) change_gate_outwire(gp); return; }
+ prop_gatechg(gp, out_chg, FALSE);
+}
+
+/*
+ * handle on (conducting) state checking and change for input state
+ *
+ * here for delay case gate value is pending conducting state (1 on, 0 off)
+ * actual current conducting state is same as stored output wire value
+ *
+ * stored conducting state corrected for tranif1 and tranif0 (value
+ * computed then reversed depnding on if1 or if0)
+ */
+static void eval_tranif_onoff(struct gate_t *gp)
+{
+ register int32 wi, bi;
+ register word32 cval;
+ register struct xstk_t *xsp;
+ int32 gateid;
+
+ wi = get_wofs_(2*__inum);
+ bi = get_bofs_(2*__inum);
+ /* step 1: access old value */
+ cval = gp->gstate.wp[wi];
+ /* this is conducting state independent of if0 or if1 */
+ __old_gateval = (cval >> bi) & 3L;
+ /* step 2: compute new conducting value */
+ xsp = __eval_xpr(gp->gpins[2]);
+ __new_inputval = (xsp->ap[0] & 1L) | ((xsp->bp[0] & 1L) << 1);
+ if (__new_inputval == 2) __new_inputval = 3;
+ __pop_xstk();
+ gateid = gp->gmsym->el.eprimp->gateid;
+ /* exactly 4 types of tranif gates */
+ if (gateid == G_TRANIF1 || gateid == G_RTRANIF1)
+  __new_gateval = __new_inputval;
+ else
+  { __new_gateval = (__new_inputval == 0) ? 1
+   : ((__new_inputval == 1) ? 0 : __new_inputval);
+  }
+}
+
+/*
+ * CONTINOUS ASSIGN EVENT ROUTINES
+ */
+
+/*
+ * load of changed wire is >1 bit conta rhs needs to be evaluated and
+ * if delay scheduled else assigned and lhs added to net changes
+ *
+ * current itree element never changes in here
+ * for now evaluating and scheduling - no optimization
+ *
+ * know rhs real illegal here since cannot assign to wire
+ *
+ * all computations done with non strength values since strength
+ * added from conta type if needed when assigning to strength wire
+ *
+ * no pulse/glitch analysis here just inertial algorithm because
+ * continuous assigns do not correspond to silicon rather modeling convention
+ */
+extern void __eval_conta_rhs_ld(register struct net_pin_t *npp)
+{
+ register struct xstk_t *xsp, *xsp2;
+ register struct conta_t *cap;
+ int32 cv, cv2, schd_wire;
+ int32 lhswlen, orhslen, lhslen;
+ byte *sbp;
+ word64 cadel, schtim;
+ i_tev_ndx tevpi;
+ struct expr_t *lhsxp;
+ struct xstk_t *xsp3;
+ struct conta_t *mast_cap;
+
+ if (__ev_tracing) { evtr_eval_conta_rhs_ld(npp); return; }
+
+ /* SJM 09/18/02 - no separate per bit NP type, just check for pb sim on */
+ mast_cap = npp->elnpp.ecap;
+ /* get pattern never decomposd per bit */
+ if (mast_cap->lhsx->getpatlhs) { __process_getpat(mast_cap); return; }
+
+ if (mast_cap->ca_pb_sim) cap = &(mast_cap->pbcau.pbcaps[npp->pbi]);
+ else cap = mast_cap;
+ /* know getpat never has delay */
+ lhsxp = cap->lhsx;
+ lhslen = cap->lhsx->szu.xclen;
+ /* this pushes rhs new maybe to be scheduled value onto expression stack */
+ xsp = __eval_xpr(cap->rhsx);
+
+ /* here rhs must be z with fixed conta strength merged in if present */
+ if (xsp->xslen != lhslen)
+  {
+   orhslen = xsp->xslen;
+
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp->xslen > lhslen) __narrow_sizchg(xsp, lhslen);
+   else if (xsp->xslen < lhslen)
+    {
+     if (cap->rhsx->has_sign) __sgn_xtnd_widen(xsp, lhslen);
+     else __sizchg_widen(xsp, lhslen);
+    }
+
+   /* SJM 07/09/03 - now understand XL algorithm to mimic - for conta */
+   /* semantics requires rhs non stren eval with 0 widening then add stren */
+   /* SJM 05/10/04 init x widending not related to new signed widening */
+   if (__wire_init) __fix_widened_toxs(xsp, orhslen);
+  }
+
+ /* case 1: no delay assign */
+ /* since 1 bit handled as gate, not checking for no change - just assign */
+ /* also rhs eval. is driver (i.e. not stored) */
+ if (mast_cap->ca_delrep == DT_NONE)
+  {
+   __immed_assigns++;
+   /* in here deals with saved driver - if any lhs bits fi>1 all must be */
+   /* SJM 09/28/02 - know if master fi>1 all per bit will be */
+   if (lhsxp->x_multfi)
+    {
+     /* this packs if possible */
+     __st_perinst_val(cap->ca_drv_wp, lhslen, xsp->ap, xsp->bp);
+     __mdr_assign_or_sched(lhsxp);
+    }
+   else
+    {
+     /* here do not need drv and do not need schd driver, rhs is driver */
+     if (lhsxp->lhsx_ndel && !__wire_init) schd_wire = TRUE;
+     else schd_wire = FALSE;
+     if (lhsxp->x_stren)
+      {
+       /* convert to strength bytes forms - add in driven from ca */
+       push_xstk_(xsp2, 4*lhslen);
+       sbp = (byte *) xsp2->ap;
+       __st_standval(sbp, xsp, cap->ca_stval);
+       if (lhsxp->optyp == LCB) __stren_exec_ca_concat(lhsxp, sbp, schd_wire);
+       else __exec_conta_assign(lhsxp, xsp2->ap, xsp2->bp, schd_wire);
+       __pop_xstk();
+      }
+     else
+      {
+       if (lhsxp->optyp == LCB)
+        __exec_ca_concat(lhsxp, xsp->ap, xsp->bp, schd_wire);
+       else __exec_conta_assign(lhsxp, xsp->ap, xsp->bp, schd_wire);
+      }
+    }
+   __pop_xstk();
+   return;
+  }
+
+ /* case 2: has delay */
+ lhswlen = wlen_(lhslen);
+ /* xsp2 is currently driving (old) value and must exist */
+ /* DBG remove ---
+ if (cap->ca_drv_wp.wp == NULL) __arg_terr(__FILE__, __LINE__);
+ -- */
+
+ push_xstk_(xsp2, lhslen);
+ __ld_perinst_val(xsp2->ap, xsp2->bp, cap->ca_drv_wp, lhslen);
+ tevpi = cap->caschd_tevs[__inum];
+ cv = memcmp(xsp2->ap, xsp->ap, 2*lhswlen*WRDBYTES);
+ __pop_xstk();
+ /* case 2a: short circuit case no event and new and old same */
+ if (tevpi == -1 && cv == 0) { __pop_xstk(); return; }
+
+ /* compute delay - know at least one bit changed */
+ __new_gateval = 1L;
+ /* if 4v delay, must set new_gateval for use in delay selection */
+ /* notice modified LRM if left hand side all x's, minimum delay is used */
+ if (mast_cap->ca_4vdel)
+  {
+   if (mast_cap->ca_pb_sim)
+    {
+     struct xstk_t *mast_xsp;
+
+     /* if 4v delay, must always eval entire conta rhs to select delay */
+     mast_xsp = __eval_xpr(mast_cap->rhsx);
+     if (vval_is0_(mast_xsp->ap, lhslen))
+      {
+       if (vval_is0_(mast_xsp->bp, lhslen)) __new_gateval = 0L;
+       else if (__vval_is1(mast_xsp->bp, lhslen)) __new_gateval = 2L;
+      }
+     else if (__vval_is1(mast_xsp->ap, lhslen)
+      && __vval_is1(mast_xsp->bp, lhslen)) { __new_gateval = 3L; }
+     __pop_xstk();
+    }
+   else
+    {
+     if (vval_is0_(xsp->ap, lhslen))
+      {
+       if (vval_is0_(xsp->bp, lhslen)) __new_gateval = 0L;
+       else if (__vval_is1(xsp->bp, lhslen)) __new_gateval = 2L;
+      }
+     else if (__vval_is1(xsp->ap, lhslen) && __vval_is1(xsp->bp, lhslen))
+      { __new_gateval = 3L; }
+    }
+  }
+ /* this may use new gateval global to select delay */
+ /* SJM 09/28/02 - delay same for all so stored in master */
+ __get_del(&cadel, mast_cap->ca_du, mast_cap->ca_delrep);
+ schtim = __simtime + cadel;
+
+ /* case 2b: no pending event and different */
+ if (tevpi == -1)
+  {
+   /* case 1b: new value to schedule */
+   /* know xsp is lhs width */
+   schedule_1caev(cap, cadel, schtim, xsp);
+   __pop_xstk();
+   return;
+  }
+
+ push_xstk_(xsp3, lhslen);
+ __ld_perinst_val(xsp3->ap, xsp3->bp, cap->schd_drv_wp, lhslen);
+ /* compare currently scheduled to to new to be scheduled */
+ /* if same do nothing since already schedule to right value and know */
+ /* value will be later */
+ cv2 = memcmp(xsp3->ap, xsp->ap, 2*lhswlen*WRDBYTES);
+ __pop_xstk();
+ if (cv2 == 0) { __pop_xstk(); return; }
+
+ /* case 2c: pending event - no spike analysis for >1 bit contas */
+ /* case 2c-1 - new and old the same - cancel */
+ if (cv == 0)
+  {
+   __tevtab[tevpi].te_cancel = TRUE;
+    __inertial_cancels++;
+   cap->caschd_tevs[__inum] = -1;
+  }
+ /* case 2c-2 - new and old differ - reschedule latest input change */
+ /* notice even for modeling anomally where latest input change leads to */
+ /* earlier output event, use latest input change */
+ else reschedule_1caev(tevpi, cadel, schtim, xsp);
+
+ __pop_xstk();
+}
+
+/*
+ * event tracing version of eval conta rhs
+ */
+static void evtr_eval_conta_rhs_ld(struct net_pin_t *npp)
+{
+ int32 cv, schd_wire;
+ int32 lhswlen, orhslen, lhslen;
+ byte *sbp;
+ word64 cadel, schtim;
+ i_tev_ndx tevpi;
+ struct tev_t *tevp;
+ struct conta_t *cap, *mast_cap;
+ struct xstk_t *xsp, *xsp2, *xsp3;
+ struct expr_t *lhsxp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[RECLEN], s5[RECLEN];
+
+ /* SJM 09/18/02 - no separate per bit NP type, just check for pb tab */
+ mast_cap = npp->elnpp.ecap;
+ /* know getpat never has delay and never decomposed per bit */
+ if (mast_cap->lhsx->getpatlhs) { __process_getpat(mast_cap); return; }
+
+ if (mast_cap->ca_pb_sim) cap = &(mast_cap->pbcau.pbcaps[npp->pbi]);
+ else cap = mast_cap;
+ lhsxp = cap->lhsx;
+
+ if (mast_cap->ca_pb_sim)
+  {
+   __tr_msg("-- %s RHS bit %d changed:\n",
+    __to_evtrcanam(__xs2, mast_cap, __inst_ptr), npp->pbi);
+  }
+ else
+  {
+   __tr_msg("-- %s RHS changed:\n",
+    __to_evtrcanam(__xs2, mast_cap, __inst_ptr));
+  }
+ lhslen = cap->lhsx->szu.xclen;
+ xsp = __eval_xpr(cap->rhsx);
+
+ /* here rhs must be z with fixed conta strength merged in if present */
+ if (xsp->xslen != lhslen)
+  {
+   orhslen = xsp->xslen;
+
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp->xslen > lhslen) __narrow_sizchg(xsp, lhslen);
+   else if (xsp->xslen < lhslen)
+    {
+     if (cap->rhsx->has_sign) __sgn_xtnd_widen(xsp, lhslen);
+     else __sizchg_widen(xsp, lhslen);
+    }
+   /* SJM 07/09/03 - now understand XL algorithm to mimic - if rhs is reg */
+   /* or reg type expr, must widen with 0's (automatic) if net with zs */
+   /* wire init is special case */
+   /* SJM 05/10/04 init x widending not related to new signed widening */
+   if (__wire_init) __fix_widened_toxs(xsp, orhslen);
+  }
+
+ /* case 1: no delay assign */
+ /* since 1 bit handled as gate, not checking for no change - just assign */
+ if (mast_cap->ca_delrep == DT_NONE)
+  {
+   __immed_assigns++;
+   __tr_msg(" NODEL <NV=%s>\n",
+    __regab_tostr(s1, xsp->ap, xsp->bp, lhslen, BHEX, FALSE));
+   /* in here deals with saved driver */
+
+   /* SJM 09/28/0-2 - know if master fi>1 all per bit will be */
+   if (lhsxp->x_multfi)
+    {
+     __st_perinst_val(cap->ca_drv_wp, lhslen, xsp->ap, xsp->bp);
+     __mdr_assign_or_sched(lhsxp);
+    }
+   else
+    {
+     /* here do not need drv and do not need schd driver, rhs is driver */
+     if (lhsxp->lhsx_ndel && !__wire_init) schd_wire = TRUE;
+     else schd_wire = FALSE;
+     if (lhsxp->x_stren)
+      {
+       /* convert to strength bytes forms - add in driven from ca */
+       push_xstk_(xsp2, 4*lhslen);
+       sbp = (byte *) xsp2->ap;
+       /* stren val also in PB */
+       __st_standval(sbp, xsp, cap->ca_stval);
+       if (lhsxp->optyp == LCB) __stren_exec_ca_concat(lhsxp, sbp, schd_wire);
+       /* SJM 03/30/99 - was storing value without strength added */
+       else __exec_conta_assign(lhsxp, xsp2->ap, xsp2->bp, schd_wire);
+       __pop_xstk();
+      }
+     else
+      {
+       if (lhsxp->optyp == LCB)
+        __exec_ca_concat(lhsxp, xsp->ap, xsp->bp, schd_wire);
+       else __exec_conta_assign(lhsxp, xsp->ap, xsp->bp, schd_wire);
+      }
+    }
+   __pop_xstk();
+   return;
+  }
+
+ /* case 2: has delay */
+ /* this is current (old) driving value */
+ lhswlen = wlen_(lhslen);
+ push_xstk_(xsp2, lhslen);
+ __ld_perinst_val(xsp2->ap, xsp2->bp, cap->ca_drv_wp, lhslen);
+ tevpi = cap->caschd_tevs[__inum];
+ cv = memcmp(xsp2->ap, xsp->ap, 2*lhswlen*WRDBYTES);
+ /* case 2a: short circuit case no event and new and old same */
+ if (tevpi == -1 && cv == 0)
+  {
+   __tr_msg(" DEL, NOCHG <OV=%s>\n",
+    __regab_tostr(s1, xsp2->ap, xsp2->bp, lhslen, BHEX, FALSE));
+   __pop_xstk();
+   __pop_xstk();
+   return;
+  }
+
+ /* compute delay */
+ __new_gateval = 1L;
+ /* if 4v delay, must set new gateval for use in delay selection */
+ /* SJM 09/28/02 - now match non evtr 4v case */
+ if (mast_cap->ca_4vdel)
+  {
+   if (mast_cap->ca_pb_sim)
+    {
+     struct xstk_t *mast_xsp;
+
+     /* if 4v delay, must always eval entire conta rhs to select delay */
+     mast_xsp = __eval_xpr(mast_cap->rhsx);
+     if (vval_is0_(mast_xsp->ap, lhslen))
+      {
+       if (vval_is0_(mast_xsp->bp, lhslen)) __new_gateval = 0L;
+       else if (__vval_is1(mast_xsp->bp, lhslen)) __new_gateval = 2L;
+      }
+     else if (__vval_is1(mast_xsp->ap, lhslen)
+      && __vval_is1(mast_xsp->bp, lhslen)) { __new_gateval = 3L; }
+     __pop_xstk();
+    }
+   else
+    {
+     if (vval_is0_(xsp->ap, lhslen))
+      {
+       if (vval_is0_(xsp->bp, lhslen)) __new_gateval = 0L;
+       else if (__vval_is1(xsp->bp, lhslen)) __new_gateval = 2L;
+      }
+     else if (__vval_is1(xsp->ap, lhslen) && __vval_is1(xsp->bp, lhslen))
+      { __new_gateval = 3L; }
+    }
+  }
+ /* this may use new gateval global to select delay */
+ __get_del(&cadel, mast_cap->ca_du, mast_cap->ca_delrep);
+ schtim = __simtime + cadel;
+
+ /* case 2b: no pending event and different */
+ if (tevpi == -1)
+  {
+   /* case 1b: new value to schedule */
+   __tr_msg(" DEL, SCHD AT %s <OV=%s, NSV=%s>\n",
+    __to_timstr(s1, &schtim),
+    __regab_tostr(s2, xsp2->ap, xsp2->bp, lhslen, BHEX, FALSE),
+    __regab_tostr(s3, xsp->ap, xsp->bp, lhslen, BHEX, FALSE));
+
+   /* know xsp is lhs width */
+   schedule_1caev(cap, cadel, schtim, xsp);
+   __pop_xstk();
+   __pop_xstk();
+   return;
+  }
+
+ /* case 2c: pending event - no spike analysis for >1 bit contas */
+ tevp = &(__tevtab[tevpi]);
+ push_xstk_(xsp3, lhslen);
+ __ld_perinst_val(xsp3->ap, xsp3->bp, cap->schd_drv_wp, lhslen);
+
+ /* compare currently scheduled to to new to be scheduled */
+ /* if same do nothing since already schedule to right value and know */
+ /* value will be later */
+ if (memcmp(xsp3->ap, xsp->ap, 2*lhswlen*WRDBYTES) == 0)
+  {
+   __tr_msg(
+    " DEL, MODEL ANOMALLY IGNORE SCHED TO SAME <OSV=NSV=%s> OLD AT %s NEW %s\n",
+    __regab_tostr(s1, xsp->ap, xsp->bp, lhslen, BHEX, FALSE),
+    __to_timstr(s2, &(tevp->etime)), __to_timstr(s3, &schtim));
+   goto done;
+  }
+
+ /* case 2c-1-a - new and old the same - remove inertial pulse */
+ if (cv == 0)
+  {
+   /* cancel pending and return */
+   __tr_msg(" DEL, PEND, SAME <OV=NSV=%s, OSV=%s AT %s INERTIAL CANCEL>\n",
+    __regab_tostr(s1, xsp->ap, xsp->bp, lhslen, BHEX, FALSE),
+    __regab_tostr(s2, xsp3->ap, xsp3->bp, lhslen, BHEX, FALSE),
+    __to_timstr(s3, &(tevp->etime)));
+   /* cancel */
+   tevp->te_cancel = TRUE;
+   __inertial_cancels++;
+   cap->caschd_tevs[__inum] = -1;
+   goto done;
+  }
+ /* case 2c-1-b - new and old differ */
+ __tr_msg(
+  " DEL, PEND, RESCHD <OV=%s, OSV=%s AT %s, NSV=%s AT %s REPLACES>\n",
+  __regab_tostr(s1, xsp2->ap, xsp2->bp, lhslen, BHEX, FALSE),
+  __regab_tostr(s2, xsp3->ap, xsp3->bp, lhslen, BHEX, FALSE),
+  __to_timstr(s5, &(tevp->etime)),
+  __regab_tostr(s3, xsp->ap, xsp->bp, lhslen, BHEX, FALSE),
+  __to_timstr(s4, &schtim));
+
+ /* reschedule by replacing (if same time) or cancelling */
+ reschedule_1caev(tevpi, cadel, schtim, xsp);
+
+done:
+ __pop_xstk();
+ __pop_xstk();
+ __pop_xstk();
+}
+
+/*
+ * emit an continous assign locator
+ * must make sure s at least IDLEN + MSG TRUNC LEN
+ */
+extern char *__to_evtrcanam(char *s, struct conta_t *cap,
+ struct itree_t *teitp)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ sprintf(s, "continuous assign in %s %s", __msg2_blditree(s1, teitp),
+  __bld_lineloc(s2, cap->casym->syfnam_ind, cap->casym->sylin_cnt));
+ return(s);
+}
+
+/*
+ * schedule 1 conta event
+ * know schd_xsp width is exactly lhs width
+ */
+static void schedule_1caev(struct conta_t *cap, word64 cadel,
+ word64 schtim, struct xstk_t *schd_xsp)
+{
+ register i_tev_ndx tevpi;
+
+ alloc_tev_(tevpi, TE_CA, __inst_ptr, schtim);
+ if (cadel == 0ULL)
+  {
+   /* this is #0, but must still build tev */
+   if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+   else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+  }
+ else __insert_event(tevpi);
+
+ cap->caschd_tevs[__inum] = tevpi;
+ __tevtab[tevpi].tu.tecap = cap;
+ __st_perinst_val(cap->schd_drv_wp, schd_xsp->xslen, schd_xsp->ap,
+  schd_xsp->bp);
+}
+
+/*
+ * take ca event and new value and either update if time same or cancel and
+ * create new event if later
+ */
+static void reschedule_1caev(i_tev_ndx tevpi, word64 cadel,
+ word64 newtim, struct xstk_t *schd_xsp)
+{
+ struct tev_t *tevp;
+ struct conta_t *cap;
+
+ tevp = &(__tevtab[tevpi]);
+ /* if del == 0 (pnd0), will always be same time reschedule */
+ cap = tevp->tu.tecap;
+ if (cadel == 0ULL)
+  {
+   /* new scheduled value replaces old */
+   __newval_rescheds++;
+   /* know length must be the same */
+   __st_perinst_val(cap->schd_drv_wp, schd_xsp->xslen, schd_xsp->ap,
+    schd_xsp->bp);
+   return;
+  }
+ /* cancel */
+ tevp->te_cancel = TRUE;
+ __inertial_cancels++;
+ /* this will change the scheduled field so no need to set to nil */
+ schedule_1caev(cap, cadel, newtim, schd_xsp);
+}
+
+/*
+ * process a continous assign actual assignment (end of delay ev triggered)
+ * 1 bit continuous assign are processed as gates per Verilog semantics
+ * and not seen here
+ *
+ * will only get here if delay >= 0 (maybe #0)
+ * SJM 09/28/02 - for rhs concat decomposed into PB, event ptr is PB
+ */
+static void process_conta_ev(register struct tev_t *tevp)
+{
+ register struct xstk_t *xsp, *xsp2;
+ register struct conta_t *cap;
+ int32 schd_wire, lhslen;
+ byte *sbp;
+ struct expr_t *lhsxp;
+
+ cap = tevp->tu.tecap;
+ lhsxp = cap->lhsx;
+ lhslen = cap->lhsx->szu.xclen;
+
+ push_xstk_(xsp, lhslen);
+ __ld_perinst_val(xsp->ap, xsp->bp, cap->schd_drv_wp, lhslen);
+ if (__ev_tracing)
+  {
+   struct conta_t *cap2;
+
+   __evtr_resume_msg();
+   if (cap->ca_pb_el) cap2 = cap->pbcau.mast_cap; else cap2 = cap;
+   __to_evtrcanam(__xs, cap2, tevp->teitp);
+   __regab_tostr(__xs2, xsp->ap, xsp->bp, lhslen, BHEX, FALSE);
+   if (lhsxp->x_multfi)
+    __tr_msg("-- %s event this driver of multiple:\n   %s\n", __xs, __xs2);
+   else __tr_msg("-- %s event the fi=1 driver: %s\n", __xs, __xs2);
+  }
+ /* move value from scheduled to driver wp - never store constant strength */
+ /* has delay so will always have ca drv wp */
+ /* store scheduled value into driving value */
+ __st_perinst_val(cap->ca_drv_wp, lhslen, xsp->ap, xsp->bp);
+
+ if (lhsxp->x_multfi) __mdr_assign_or_sched(lhsxp);
+ else
+  {
+   /* here do not need drv and do not need schd driver, rhs is driver */
+   if (lhsxp->lhsx_ndel && !__wire_init) schd_wire = TRUE;
+   else schd_wire = FALSE;
+
+   if (lhsxp->x_stren)
+    {
+     /* convert to strength bytes forms - add in driven from ca */
+     /* know all widths exactly  required lhs width */
+     push_xstk_(xsp2, 4*lhslen);
+     sbp = (byte *) xsp2->ap;
+     /* notice stren value also in each per bit, just not delay */
+     __st_standval(sbp, xsp, cap->ca_stval);
+     if (lhsxp->optyp == LCB) __stren_exec_ca_concat(lhsxp, sbp, schd_wire);
+     else __exec_conta_assign(lhsxp, xsp2->ap, xsp2->bp, schd_wire);
+     __pop_xstk();
+    }
+   else
+    {
+     if (lhsxp->optyp == LCB)
+      __exec_ca_concat(lhsxp, xsp->ap, xsp->bp, schd_wire);
+     else __exec_conta_assign(lhsxp, xsp->ap, xsp->bp, schd_wire);
+    }
+  }
+ __pop_xstk();
+ cap->caschd_tevs[__inum] = -1;
+ /* can just leave scheduled wire value - nothing to free */
+}
+
+/*
+ * process a wire delay event - know this is always 1 bit
+ * non inout path dest. scheduled wire changes processed here also
+ *
+ * since r,f or path delays will have different delays and inertial
+ * conditions for every bit
+ * know for scalar bi 0 not -1
+ *
+ * could possibly optimize one delay form
+ * will only get here if wire has delay > 0 (or #0)
+ * also know path source or destination can never have wire delay
+ *
+ * notice when wire changes must see if really changes by doing
+ * fi>1 competition of right type using scheduled plus current
+ * then know scheduled value really changed
+ */
+static void process_wire_ev(register struct tev_t *tevp)
+{
+ register int32 bi;
+ register struct net_t *np;
+ register byte *sbp;
+ word32 nval;
+ struct rngdwir_t *dwirp;
+
+ np = tevp->tu.tenp->tenu.np;
+ bi = tevp->tu.tenp->nbi;
+ /* DBG remove ---
+ if (bi < 0) __misc_terr(__FILE__, __LINE__);
+ --- */
+
+ /* free wire event auxialiary field here since bit and wire extracted */
+ __my_free((char *) tevp->tu.tenp, sizeof(struct tenp_t));
+ tevp->tu.tenp = NULL;
+
+ nval = tevp->outv;
+ if (__ev_tracing)
+  {
+   char s1[RECLEN], s2[RECLEN];
+
+   __evtr_resume_msg();
+   if (np->n_isapthdst) strcpy(s2, " (path destination)");
+   else strcpy(s2, "");
+   __tr_msg("-- processing delay wire %s%s store event, value %s\n",
+    __to_evtrwnam(__xs, np, bi, bi, tevp->teitp), s2,
+     __to_vvnam(s1, (word32) nval));
+  }
+ dwirp = np->nu.rngdwir;
+ dwirp->wschd_pbtevs[np->nwid*tevp->teitp->itinum + bi] = -1;
+
+ /* inhibit if active force */
+ if (np->frc_assgn_allocated && force_inhibit_wireassign(np, bi, tevp->teitp))
+  return;
+
+ __push_itstk(tevp->teitp);
+
+ /* store bit into wire - value is after any multi-fi competition */
+ /* this add net chg element if needed */
+ if (np->n_stren)
+  {
+   if (tevp->te_trdecay)
+    __gfwarn(649, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+     "charge on node %s.%s has decayed", __msg2_blditree(__xs, __inst_ptr),
+     np->nsym->synam);
+
+   /* get strength wire address */
+   get_stwire_addr_(sbp, np);
+   if (sbp[bi] != nval)
+    {
+     sbp[bi] = nval;
+     /* know change, record if needed */
+     record_sel_nchg_(np, bi, bi);
+    }
+  }
+ else __chg_st_bit(np, bi, nval & 1L, (nval >> 1) & 1L);
+ __pop_itstk();
+}
+
+/*
+ * process a a non blocking procedural assign event - do the assign
+ * here just assign - no inertial - each just overwrites
+ *
+ * SJM 08/08/99 - fixed so lhs indices evaluated at schedule time not
+ * event proces time to match LRM and XL
+ */
+static void process_nbpa_ev(struct tev_t *tevp)
+{
+ register word32 *wp;
+ register struct expr_t *con_lhsxp;
+ register struct st_t *stp;
+ int32 wlen;
+ struct tenbpa_t *tenbp;
+
+ __push_itstk(tevp->teitp);
+ tenbp = tevp->tu.tenbpa;
+ wp = tenbp->nbawp;
+ stp = tenbp->nbastp;
+
+ /* SJM 08/08/99 - need to assign to copied lhs expr with select indices */
+ /* (possibly many if lhs concatenate) replaced by constants */
+ /* SJM PUTMEBACK */
+ con_lhsxp = tenbp->nblhsxp;
+ if (con_lhsxp == NULL) con_lhsxp = stp->st.spra.lhsx;
+
+ wlen = wlen_(con_lhsxp->szu.xclen);
+ if (__ev_tracing)
+  {
+   char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[RECLEN];
+
+   __tr_msg("-- nb event assign in %s %s of %s to %s at %s\n",
+    __msg2_blditree(s1, tevp->teitp), __bld_lineloc(s2,
+     tenbp->nbastp->stfnam_ind, tenbp->nbastp->stlin_cnt),
+    __xregab_tostr(s3, wp, &wp[wlen], con_lhsxp->szu.xclen, stp->st.spra.rhsx),
+    __msgexpr_tostr(s4, con_lhsxp), __to_timstr(__xs, &__simtime));
+  }
+
+ /* SJM 05/19/04 - complex procedural assign needs stmt file/line context */
+ /* for error messages such as out of range - do not need to save since */
+ /* no statement context in event processing - this is exception */
+ __slin_cnt = stp->stlin_cnt;
+ __sfnam_ind = stp->stfnam_ind;
+
+ /* do assign - know if lhs expr copied, widith still same */
+ __exec2_proc_assign(con_lhsxp, wp, &(wp[wlen]));
+
+ /* final step is freeing contents */
+ __my_free((char *) wp, 2*wlen*WRDBYTES);
+ /* if needed to copy lhs expr., now free */
+ if (tenbp->nblhsxp != NULL) __free_xtree(tenbp->nblhsxp);
+
+ __my_free((char *) tevp->tu.tenbpa, sizeof(struct tenbpa_t));
+ tevp->tu.tenbpa = NULL;
+ __pop_itstk();
+}
+
+/*
+ * print out evnet trace time - not in event trace message
+ */
+extern void __evtr_resume_msg(void)
+{
+ char s1[RECLEN];
+
+ if (__last_evtrtime != __simtime)
+  {
+   /* this should go through time format ? */
+   __tr_msg("\n<<< event tracing at time %s\n", __to_timstr(s1, &__simtime));
+   __last_evtrtime = __simtime;
+  }
+}
+
+/*
+ * process a special getpattern form continous assigment
+ * know left of rhsx is $getpattern symbol and right is var. array index
+ *
+ * notice this is a special immediate overriding assign and does not handle
+ * multi-fi wire properties or wire delays or strengths
+ *
+ * should probably try to optimize special 64 bit case too
+ * point of this is to optimized for known fixed form
+ *
+ * could keep old getpattern value and build index of change and bit
+ * select to change those
+ * cannot be xmr
+ */
+extern void __process_getpat(struct conta_t *cap)
+{
+ register int32 bi;
+ register struct expr_t *catx;
+ register word32 cbita, cbitb;
+ int32 i, wlen, ubits;
+ word32 tmpa, tmpb;
+ struct expr_t *idndp, *lhsxp, *rhsxp;
+ struct xstk_t *xsp;
+ struct net_t *np;
+
+ /* know rhs is variable array index */
+ /* rhs is get pattern function call */
+ lhsxp = cap->lhsx;
+ rhsxp = cap->rhsx;
+ xsp = __eval_xpr(rhsxp->ru.x->lu.x);
+ /* this is except to convert to lhs width - extra array bits ignored or */
+ /* lhs just not filled */
+
+ /* if out of range or x, value will be changed to x */
+
+ if (__ev_tracing)
+  {
+   __evtr_resume_msg();
+   __tr_msg("-- $getpattern %s processed\n",
+    __to_evtrcanam(__xs, cap, __inst_ptr));
+  }
+
+ /* wider than 1 word32 case */
+ wlen = wlen_(lhsxp->szu.xclen);
+ ubits = ubits_(lhsxp->szu.xclen);
+ catx = lhsxp->ru.x;
+ bi = (ubits == 0) ? WBITS - 1: ubits - 1;
+ for (i = wlen - 1; i >= 0; i--)
+  {
+   tmpa = xsp->ap[i];
+   tmpb = xsp->bp[i];
+   /* know need prop. turned off after last propagation (off here) */
+   for (; bi >= 0; catx = catx->ru.x, bi--)
+    {
+     if (catx == NULL) goto done;
+
+     idndp = catx->lu.x;
+     np = idndp->lu.sy->el.enp;
+
+     cbita = (tmpa >> bi) & 1L;
+     cbitb = (tmpb >> bi) & 1L;
+     chg_st_scalval_(np->nva.bp, cbita, cbitb);
+
+     /* know lhs get pat concat elements are scalars */
+     if (__lhs_changed) record_nchg_(np);
+    }
+   bi = WBITS - 1;
+   if (catx == NULL) break;
+  }
+done:
+ __immed_assigns++;
+ __pop_xstk();
+}
+
+/*
+ * emit an netname for tracing with path if needed
+ * for ev. know never task/func. part of xmr reference
+ */
+extern char *__to_evtrwnam(char *s, struct net_t *np, int32 bi1, int32 bi2,
+ struct itree_t *teitp)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ __msg2_blditree(s1, teitp);
+ strcat(s1, ".");
+ strcat(s1, __schop(s2, np->nsym->synam));
+
+ if (bi1 == -1 || !np->n_isavec) strcpy(s, s1);
+ else if (bi1 == bi2) sprintf(s, "%s[%d]", s1, __unnormalize_ndx(np, bi1));
+ else sprintf(s, "%s[%d:%d]", s1, __unnormalize_ndx(np, bi1),
+  __unnormalize_ndx(np, bi2));
+ return(s);
+}
+
+/*
+ * emit an MIPD port name for tracing with path if needed
+ *
+ * port can be only 1 bit always number from hight to low so no normalize
+ */
+extern char *__to_evtrpnam(char *s, struct mod_pin_t *mpp, int32 bi,
+ struct itree_t *teitp)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ __msg2_blditree(s1, teitp);
+ strcat(s1, ".");
+ __schop(s2, __to_mpnam(__xs, mpp->mpsnam));
+ strcat(s1, s2);
+
+ if (bi == -1 || mpp->mpwide == 1) strcpy(s, s1);
+ else sprintf(s, "%s[%d]", s1, bi);
+ return(s);
+}
+
+/*
+ * for one bit, know some bits forced inhibit assign if this bit forced
+ * here do not need to worry about some bits only forced from range
+ * this is only for wire where 1 bit per bit*inst product
+ */
+static int32 force_inhibit_wireassign(struct net_t *np, register int32 biti,
+ struct itree_t *itp)
+{
+ register struct qcval_t *frc_qcp;
+ int32 nd_itpop, rv;
+
+ if (itp != NULL) { __push_itstk(itp); nd_itpop = TRUE; }
+ else nd_itpop = FALSE;
+ frc_qcp =  &(np->nu2.qcval[__inum*np->nwid + biti]);
+ if (frc_qcp->qc_active) rv = TRUE; else rv = FALSE;
+ if (nd_itpop) __pop_itstk();
+ return(rv);
+}
+
+/*
+ * process a path dest. tran (inout) wire delay internal hard driver
+ * change event
+ *
+ * for inout path. know the one driver changed previously and path delayed
+ * update of hard driver internal tran channel value for the wire
+ * any other change of path will cause event cancel and new schedule
+ * so fact that the drivers if evaled will be new value still works
+ *
+ * since r,f or path delays will have different delays and inertial
+ * conditions for every bit, know for scalar bi 0 not -1
+ */
+static void process_trpthdst_ev(register struct tev_t *tevp)
+{
+ register int32 bi;
+ register struct net_t *np;
+ register byte *sbp;
+ struct traux_t *trap;
+ word32 nval, av, bv;
+ struct rngdwir_t *dwirp;
+ struct xstk_t *xsp;
+
+ /* notice event here emitted in change gate outwire */
+ np = tevp->tu.tenp->tenu.np;
+ bi = tevp->tu.tenp->nbi;
+ /* DBG remove ---
+ if (bi < 0) __misc_terr(__FILE__, __LINE__);
+ --- */
+
+ /* free wire event auxialiary field here since bit and wire extracted */
+ __my_free((char *) tevp->tu.tenp, sizeof(struct tenp_t));
+ tevp->tu.tenp = NULL;
+
+ nval = tevp->outv;
+ if (__ev_tracing)
+  {
+   char s1[RECLEN];
+
+   __evtr_resume_msg();
+   __tr_msg(
+    "-- processing inout path dest. %s driven value update event, value %s\n",
+    __to_evtrwnam(__xs, np, bi, bi, tevp->teitp),
+     __to_vvnam(s1, (word32) nval));
+  }
+ dwirp = np->nu.rngdwir;
+ dwirp->wschd_pbtevs[np->nwid*tevp->teitp->itinum + bi] = -1;
+
+ trap = np->ntraux;
+ __push_itstk(tevp->teitp);
+ /* update hard driver stored value and re-eval tran channel if needed */
+ if (np->n_stren)
+  {
+   /* get strength wire address */
+   sbp = &(trap->trnva.bp[__inum*np->nwid]);
+   if (sbp[bi] == nval) goto done;
+   sbp[bi] = nval;
+  }
+ else
+  {
+   if (!np->n_isavec)
+    {
+     ld_scalval_(&av, &bv, trap->trnva.bp);
+     if (nval == (av | (bv << 1))) goto done;
+     /* SJM 07/16/01 - typo was storing old val so tr chan value never chgs */
+     /* need to store new non stren value not old */
+     /* ??? wrong - st_scalval_(trap->trnva.bp, av, bv); */
+     st2_scalval_(trap->trnva.bp, nval);
+    }
+   else
+    {
+     push_xstk_(xsp, np->nwid);
+     __ld_perinst_val(xsp->ap, xsp->bp, trap->trnva, np->nwid);
+     av = rhsbsel_(xsp->ap, bi);
+     bv = rhsbsel_(xsp->bp, bi);
+     if (nval == (av | (bv << 1))) { __pop_xstk(); goto done; }
+     __lhsbsel(xsp->ap, bi, (nval & 1L));
+     __lhsbsel(xsp->bp, bi, ((nval >> 1) & 1L));
+     __st_perinst_val(trap->trnva, np->nwid, xsp->ap, xsp->bp);
+     __pop_xstk();
+    }
+  }
+ /* if some but not this bit in tran channel, just assign */
+ /* SJM - 03/15/01 - know bit not -1 since schedules as 0 for scalar */
+ __eval_tran_1bit(np, bi);
+done:
+ __pop_itstk();
+}
+
+/*
+ * ROUTINES TO PROCESS BEHAVIORAL EVENTS
+ */
+
+/* table for converting 4 bit (oonn) edge pair to edge value byte */
+/* table treats edge with z as x here */
+byte __epair_tab[] =
+ { NOEDGE, EDGE01, EDGE0X, EDGE0X, EDGE10, NOEDGE, EDGE1X, EDGE1X,
+   EDGEX0, EDGEX1, NOEDGE, NOEDGE, EDGEX0, EDGEX1, NOEDGE, NOEDGE };
+
+/*
+ * after net changed net (wire or reg) progagate to all dces wire drives
+ * bit range passed and used to eliminate fan-out for other bits here
+ * all ranges here normalized high to low form
+ * notice will never get to event trigger through this path (through cause)
+ *
+ * inst. ptr here is place np changed (i.e. for XMR define itree loc)
+ * know npi1 >= npi2 since normalized internally
+ */
+extern void __wakeup_delay_ctrls(register struct net_t *np, register int32 npi1,
+ register int32 npi2)
+{
+ register struct dcevnt_t *dcep;
+ register word32 *wp;
+ int32 nd_itpop, oneinst, tevpi, i1;
+ word32 oval, nval;
+ byte emask;
+ struct delctrl_t *dctp;
+ struct fmonlst_t *fmonp;
+ struct fmselst_t *fmsep;
+ struct dce_expr_t *dcexp;
+
+ for (dcep = np->dcelst; dcep != NULL; dcep = dcep->dcenxt)
+  {
+   /* --- DBG remove ---
+   if (__inst_ptr == NULL) __misc_terr(__FILE__, __LINE__);
+   --- */
+
+   /* filter one instance forms before case */
+   if (dcep->dce_1inst && dcep->dce_matchitp != __inst_ptr) continue;
+
+   switch ((byte) dcep->dce_typ) {
+    case DCE_RNG_INST:
+     /* SJM 11/25/02 - notice can't be turned off/on */
+     dctp = dcep->st_dctrl;
+     /* all of wire changed match */
+     if (npi1 == -1) goto do_event_ctrl;
+     /* dce is range DCE range, know dci1 cannot be -1 */
+     if (dcep->dci1 == -2)
+      {
+       /* SJM 10/12/04 - because contab realloced, must be ndx base of IS */
+       wp = &(__contab[dcep->dci2.xvi]);
+       i1 = (int32) wp[2*__inum];
+       /* change must be inside range to match */
+       if (i1 > npi1 || i1 < npi2) continue;
+      }
+     else
+      {
+       /* SJM 06/26/04 - FIXME ??? ### isn't else needed here ??? */
+       /* eliminate if changed bit do not overlap range */
+       /* if low chged above high or high chged below low, eliminate */
+       if (npi2 > dcep->dci1 || npi1 < dcep->dci2.i) continue;
+      }
+     goto do_event_ctrl;
+    case DCE_INST:
+     /* notice dce that is entire wire always matches changed range */
+     dctp = dcep->st_dctrl;
+
+do_event_ctrl:
+     nd_itpop = FALSE;
+     /* first see if variable really changed (plus edge filtering) */
+     oval = nval = 3;
+     /* if no chg record, then array or reg entire wire so know changed */
+     /* know for any wire even scalar, will exist */
+     /* LOOKATME - filtering even for DOWN XMR insts that do not match? */
+     if (dcep->prevval.wp != NULL)
+      {
+       /* also eliminate if event control range or wire did not change */
+       /* for xmr and/or collpase - look in target itree where dce attached */
+       /* for non dce expr form, sets old and new values for edge detection */
+       oneinst = (dcep->dce_1inst) ? TRUE : FALSE;
+       if (!np->n_isavec)
+        {
+         /* SJM 06/29/04 - simplified - always use stren version for scalar */
+         if (!scal_stfilter_dce_chg(np, dcep, &oval, &nval, oneinst))
+          goto dce_done;
+        }
+       else
+        {
+         if (!np->n_stren)
+          {
+           if (!filter_dce_chg(np, dcep, &oval, &nval, oneinst))
+            goto dce_done;
+          }
+         else
+          {
+           if (!stfilter_dce_chg(np, dcep, &oval, &nval, oneinst))
+            goto dce_done;
+          }
+        }
+      }
+     /*
+      * idea for normal event control dce:
+      * during prep: first for xmr trace from ref to target (place where wire)
+      *
+      * here when triggering (i.e. wakeup and schedule thread)
+      * if xmr to on target place to wake up, for multiply
+      * instantiated down will be one dce for each down inst. - when up wire
+      * changes need to match one right dce itree loc which is done by
+      * comparing against when match move down to xmr move from target back
+      * to xmr ref.
+      */
+     /* if one inst form (know matches) move to reference itree loc. */
+     if (dcep->dce_1inst)
+      { __push_itstk(dcep->dce_refitp); nd_itpop = TRUE; }
+     /* for xmr know target wire changed @(i1.i2.i3.i4.w)  w in dest. */
+     else if (dcep->dce_xmrtyp != XNP_LOC)
+      {
+       /* SJM 04/17/03 - if not right instance do not process */
+       if (!__match_push_targ_to_ref(dcep->dce_xmrtyp, dcep->dceu.dcegrp))
+        continue;
+       nd_itpop = TRUE;
+      }
+
+     /* if armed (i.e. evctrl active) normal processing */
+     /* notice current thread (init/always) may differ from dctp thread */
+     /* so current thread must not be used here */
+     if ((tevpi = dctp->dceschd_tevs[__inum]) != -1)
+      {
+       /* RELEASE remove ---
+       {
+        struct tev_t *tevp;
+
+        tevp = &(__tevtab[tevpi]);
+        if (tevp->tetyp < 1 || tevp->tetyp > 14)
+         __misc_terr(__FILE__, __LINE__);
+       }
+       --- */
+       /* filter out if wrong edge - know if has edge prev val set */
+       /* unless dce expr also set (non nul) */
+       if (dcep->dce_edge)
+        {
+         /* eval. expr - know at ref. (not var. chg) itree loc. */
+         if ((dcexp = dcep->dce_expr) != NULL)
+          {
+           /* if XMR dce, already at ref itree loc*/
+           if (!filter_edge_expr(dcexp, &oval, &nval)) goto dce_done;
+           /* nval and oval set for edge checking below */
+          }
+
+         /* even though only pos and neg legal here use general signature */
+         /* dce edgval is 1 bit per edge type table - epair tab maps to bit */
+         emask = __epair_tab[nval | (oval << 2)];
+         /* if no bits in common, no match */
+         if (((byte) dcep->dce_edgval & emask) == 0) goto dce_done;
+        }
+       /* last: after move to ref inst, need to match itree loc for iact */
+       /* need edge check before here because update old eval */
+       if (dctp->dc_iact && dcep->iact_itp != __inst_ptr) goto dce_done;
+
+       /* 10/27/00 SJM - if repeat form check and decrement repeat count */
+       /* and if not counted down to 0 yet, do nothing (filter out) */
+       if (dctp->repcntx != NULL)
+        {
+         /* REMOVEME AGAIN 04/01/02 ??? */
+         /* DBG remove --- */
+         if (__debug_flg)
+          {
+           __dbg_msg(
+            "+++ now %s repeated edge for net %s (inst %s) count %d\n",
+            __to_timstr(__xs2, &__simtime), np->nsym->synam,
+            __msg2_blditree(__xs, __inst_ptr),
+            (int32) dctp->dce_repcnts[__inum] - 1);
+          }
+         /* --- */
+         /* SJM 04/02/02 since word32, any positive still do not trigger */
+         if (--dctp->dce_repcnts[__inum] != 0) goto dce_done;
+        }
+       trigger_evctrl(dctp, tevpi);
+      }
+
+dce_done:
+     if (nd_itpop) __pop_itstk();
+     continue;
+    case DCE_RNG_MONIT:
+     /* no -2 IS form since 1 active monit from 1 itree place only */
+     /* if enire wire changed, always match */
+     if (npi1 != -1 && (npi1 < dcep->dci2.i || npi2 > dcep->dci1)) continue;
+     /*FALLTHRU */
+    case DCE_MONIT:
+     /* SJM 11/25/02 - only check off for ones that can be off */
+     if (dcep->dce_off) continue;
+
+     /* notice these work by storing old and new values */
+     if (dcep->dce_matchitp != __inst_ptr) continue;
+     /* fmon nil for the one monitor in design */
+     if (dcep->dceu2.dce_fmon == NULL) __slotend_action |= SE_MONIT_TRIGGER;
+     else
+      {
+       fmonp = dcep->dceu2.dce_fmon;
+       /* if already activated, nothing to do */
+       if (fmonp->fmse_trig == NULL)
+        {
+         /* allocate new se fmon */
+         if (__fmse_freelst == NULL)
+          fmsep = (struct fmselst_t *) __my_malloc(sizeof(struct fmselst_t));
+         else
+          {
+           fmsep = __fmse_freelst;
+           __fmse_freelst = __fmse_freelst->fmsenxt;
+          }
+         fmsep->fmsenxt = NULL;
+         fmsep->fmon = fmonp;
+
+         /* link it on list */
+         if (__fmonse_hdr == NULL) __fmonse_hdr = fmsep;
+         else __fmonse_end->fmsenxt = fmsep;
+         __fmonse_end = fmsep;
+         /* mark triggered */
+         fmonp->fmse_trig = fmsep;
+         __slotend_action |= SE_FMONIT_TRIGGER;
+        }
+      }
+     continue;
+    case DCE_RNG_QCAF:
+     if (dcep->dce_off) continue;
+     /* no -2 IS form since 1 active from 1 itree place only */
+     /* if enire wire changed, always match */
+     if (npi1 != -1 && (npi1 < dcep->dci2.i || npi2 > dcep->dci1)) continue;
+     /*FALLTHRU */
+    case DCE_QCAF:
+     if (dcep->dce_off) continue;
+     if (dcep->dce_matchitp != __inst_ptr) continue;
+     /* do not care which rhs wire changed must eval and assign all */
+     __assign_qcaf(dcep);
+     continue;
+    case DCE_RNG_PVC:
+     /* SJM 07/24/00 - must turn off PLI 1.0 PV dces from inside self */
+     if (dcep->dce_off) continue;
+
+     /* no -2 IS form since 1 active from 1 itree place only */
+     /* if enire wire changed, always match */
+     if (npi1 != -1 && (npi1 < dcep->dci2.i || npi2 > dcep->dci1)) continue;
+     /*FALLTHRU */
+    case DCE_PVC:
+     /* SJM 07/24/00 - must turn off PLI 1.0 PV dces from inside self */
+     if (dcep->dce_off) continue;
+
+     /* notice tf PV change always per instance */
+     if (dcep->dce_matchitp != __inst_ptr) continue;
+
+     /* must check to make sure psel assign changed bits in actual range */
+     oval = nval = 3;
+     /* if no chg record, then array or reg entire wire so know changed */
+     /* one dce for each different inst and location of _tf call */
+     if (dcep->prevval.wp != NULL)
+      {
+       if (np->n_stren)
+        { if (!stfilter_dce_chg(np, dcep, &oval, &nval, TRUE)) continue; }
+       else
+        { if (!filter_dce_chg(np, dcep, &oval, &nval, TRUE)) continue; }
+      }
+     /* do not care which rhs wire changed must eval and assign all */
+     __pvc_call_misctf(dcep);
+     continue;
+    case DCE_RNG_CBVC:
+     /* SJM 07/24/00 - must turn off PLI 1.0 PV dces from inside self */
+     if (dcep->dce_off) continue;
+
+     /* callback value change but dce contents differ */
+     /* no -2 IS form since 1 active from 1 itree place only */
+     /* if enire wire changed, always match */
+     if (npi1 != -1 && (npi1 < dcep->dci2.i || npi2 > dcep->dci1)) continue;
+     /*FALLTHRU */
+    case DCE_CBVC:
+     /* SJM 07/24/00 - must turn off PLI 1.0 PV dces from inside self */
+     if (dcep->dce_off) continue;
+
+     if (dcep->dce_matchitp != __inst_ptr) continue;
+     /* DBG remove ---
+     if (__debug_flg && np->n_stren)
+      {
+       int32 dwid;
+       byte *sbp;
+       char s1[RECLEN];
+
+       get_stwire_addr_(sbp, np);
+       -* SJM 06/03/02 - was wrongly checking dci2 *-
+       if (dcep->dci1 == -2) __misc_terr(__FILE__, __LINE__);
+
+       if (dcep->dci1 != -1)
+        {
+         sbp = &(sbp[dcep->dci2.i]);
+         dwid = (dcep->dci1 - dcep->dci2.i) + 1;
+         sprintf(s1, "%s[%d:%d]", np->nsym->synam, dcep->dci1, dcep->dci2.i);
+        }
+       else { dwid = np->nwid; strcpy(s1, np->nsym->synam); }
+       __dbg_msg("CBVC: %s strength value %s (old %s)\n", s1,
+        __st_regab_tostr(__xs, sbp, dwid),
+        __st_regab_tostr(__xs2, dcep->prevval.bp, dwid));
+      }
+     else
+      {
+       struct xstk_t *xsp, *xsp2;
+
+       push_xstk_(xsp, np->nwid);
+       __ld_wire_val(xsp->ap, xsp->bp, np);
+
+       if (dcep->prevval.wp != NULL)
+        {
+         -* know have current instance here *-
+         push_xstk_(xsp2, np->nwid);
+         __ld_perinst_val(xsp2->ap, xsp2->bp, dcep->prevval, np->nwid);
+         __regab_tostr(__xs2, xsp2->ap, xsp2->bp, xsp2->xslen, BHEX, FALSE);
+         __pop_xstk();
+        }
+       else strcpy(__xs2, "**none**");
+
+       __dbg_msg("CBVC: value %s (old %s)\n",
+        __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE), __xs2);
+       __pop_xstk();
+      }
+     --- */
+
+     oval = nval = 3;
+     /* if no chg record, then array or reg entire wire so know changed */
+     /* one dce for each different inst and location of _tf call */
+     if (dcep->prevval.wp != NULL)
+      {
+       if (!np->n_isavec)
+        {
+         /* 05/20/00 - SJM - following LRM vi vpi stren report st chg */
+         /* user passed non stren val request to vpi_ cb call back */
+         if (!np->n_stren || dcep->dce_nomonstren)
+          {
+           /* SJM 06/29/04 - simplified - always use stren version for scal */
+           if (!scal_stfilter_dce_chg(np, dcep, &oval, &nval, TRUE))
+            continue;
+          }
+         else
+          {
+           /* need strength changes too */
+            if (!vccb_scal_standval_filter(np, dcep, &oval, &nval, TRUE))
+             continue;
+          }
+        }
+       else
+        {
+         if (!np->n_stren)
+          { if (!filter_dce_chg(np, dcep, &oval, &nval, TRUE)) continue; }
+         else
+          {
+           /* 05/20/00 - SJM - following LRM vi vpi stren report st chg */
+           /* user passed non stren val request to vpi_ cb call back */
+           if (dcep->dce_nomonstren)
+            {
+             if (!stfilter_dce_chg(np, dcep, &oval, &nval, TRUE)) continue;
+            }
+           else
+            {
+             /* need strength changes too */
+             if (!vccb_vec_standval_filter(np, dcep, &oval, &nval, TRUE))
+              continue;
+            }
+          }
+        }
+      }
+     /* need one call back for every change */
+
+     /* SJM 07/24/00 - must run with this call back turned off in case */
+     /* call back c code does put value to reg because change propagation */
+     /* for regs must be immediate */
+     /* notice will never get here unless dce on */
+     dcep->dce_off = TRUE;
+
+     __cbvc_callback(dcep->dceu.dce_cbp, dcep->dceu.dce_cbp->cb_hp);
+
+     /* SJM 07/24/00 - unless user turned off with vpi control turn back on */
+     /* user may turn off in value change call back routine */
+     if (!dcep->dceu.dce_cbp->cb_user_off) dcep->dce_off = FALSE;
+     continue;
+
+    /* these are used only in vpi_ for force/release call backs */
+    case DCE_CBF: case DCE_RNG_CBF: case DCE_CBR: case DCE_RNG_CBR:
+     continue;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+  }
+}
+
+/*
+ * evaluate, set edge new and old and filter for dce change - non xmr case
+ */
+static int32 filter_edge_expr(register struct dce_expr_t *dcexp, word32 *oval,
+ word32 *nval)
+{
+ register word32 nav, nbv;
+ register struct xstk_t *xsp;
+ word32 av, bv;
+
+ /* evaluate expr. to get current edge in ref. context */
+ xsp = __eval_xpr(dcexp->edgxp);
+ /* extract low bit in case wide */
+ nav = xsp->ap[0] & 1L;
+ nbv = xsp->bp[0] & 1L;
+ /* SJM 08/07/00 - now done with pushed expr value */
+ __pop_xstk();
+
+ *nval = nav | (nbv << 1);
+ ld_scalval_(&av, &bv, dcexp->bp);
+ *oval = av | (bv << 1);
+ /* if variable does not effect expr. value, no edge */
+ if (nval == oval) return(FALSE);
+ st_scalval_(dcexp->bp, nav, nbv);
+ return(TRUE);
+}
+
+/*
+ * trigger an armed event control for current itree loc.
+ * changes pending delay control event and thread resume event, and links in
+ *
+ * itree loc. must match and for xmr/col. is ref. itree loc.
+ * know will not see if event delay control not active (armed)
+ */
+static void trigger_evctrl(struct delctrl_t *dctp, register i_tev_ndx tevpi)
+{
+ register struct tev_t *tevp;
+
+ tevp = &(__tevtab[tevpi]);
+ /* getting here means dctrl event triggered */
+ /* DBG remove --- */
+ if (__debug_flg && __st_tracing)
+  {
+   struct st_t *stp;
+
+   if (tevp->tetyp == TE_NBPA)
+    {
+     stp = tevp->tu.tenbpa->nbastp;
+     __tr_msg(
+      "-- scheduling NB event control assign for now line %s (itree=%s)\n",
+      __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt),
+      __inst_ptr->itip->isym->synam);
+    }
+   else
+    {
+     stp = tevp->tu.tethrd->thnxtstp;
+     __tr_msg(
+      "-- scheduling event control resume for now line %s (chg in thd=%s, itree=%s)\n",
+      __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt),
+       tevp->tu.tethrd->th_itp->itip->isym->synam,
+      __inst_ptr->itip->isym->synam);
+    }
+  }
+ /* --- */
+
+ /* must schedule wakeup since no way to interupt current context */
+ /* which may not be procedural threads */
+ tevp->etime = __simtime;
+ /* armed event and now resume event already associated with thread */
+ /* restart thread already set - must add to front for interactive */
+ if (tevp->tetyp != TE_NBPA)
+  {
+   __add_ev_to_front(tevpi);
+   dctp->dceschd_tevs[__inum] = -1;
+   /* in case disable, indicate suspended on ev thrd no suspend to disable */
+   tevp->tu.tethrd->th_dctp = NULL;
+  }
+ /* else add to #0 for non blocking assign */
+ else
+  {
+   /* LOOKATME - is this right */
+   /* here ok to have list of events (non inertial) */
+   /* know at least 1 event, remove head schedule for now after trigger */
+   dctp->dceschd_tevs[__inum] = tevp->tenxti;
+   if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+   else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+
+   /* works because no new tevs that could cause realloc called */
+   __tevtab[tevpi].tenxti = -1;
+   /* this now looks like normal delay control nb */
+   tevp->tu.tenbpa->nbdctp = NULL;
+  }
+}
+
+/*
+ * stren filter non monit dce for real change - return F if not changed
+ *
+ * needed because may assign to range but monitor bit in range did not chged
+ * also if edge operator (not chaange) sets the oval and nval
+ * dce put on target
+ *
+ * oneinst for cases where must load right inst of wire but only one inst
+ * for dce
+ *
+ * this is for change operator not %v so value not strength change used
+ */
+static int32 stfilter_dce_chg(register struct net_t *np,
+ register struct dcevnt_t *dcep, word32 *oval, word32 *nval, int32 oneinst)
+{
+ register int32 bi;
+ register byte *dcesbp, *nsbp;
+ int32 dcewid, i1, i2;
+ byte dcev, nv;
+
+ /* SJM 05/08/03 - stren can't be expr since eval of expr removes stren */
+ /* DBG remove -- */
+ if (dcep->dce_expr != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ dcewid = __get_dcewid(dcep, np);
+ /* get dce value ptr (for iact per instance so from 0th) */
+ if (oneinst) dcesbp = dcep->prevval.bp;
+ else dcesbp = &(dcep->prevval.bp[__inum*dcewid]);
+
+ __get_cor_range(dcep->dci1, dcep->dci2, &i1, &i2);
+ /* point to wire value */
+ get_stwire_addr_(nsbp, np);
+ /* since LRM allows vector - this automatically accesses low bit */
+ if (i1 != -1) nsbp = &(nsbp[i1]);
+
+ /* only need to set values for edge if complicated need expr form */
+ if (dcep->dce_edge)
+  {
+   if ((dcev = (dcesbp[0] & 3)) == (nv = (nsbp[0] & 3))) return(FALSE);
+   *oval = dcev;
+   *nval = nv;
+   /* update the prevval for next wire change */
+   dcesbp[0] = nsbp[0];
+   return(TRUE);
+  }
+
+ /* all change operators here (%v handled elsewhere) are value only */
+ for (bi = 0; bi < dcewid; bi++)
+  { if ((dcesbp[bi] & 3) != (nsbp[bi] & 3)) goto not_same_val; }
+ return(FALSE);
+
+not_same_val:
+ /* old value comes from internally stored prev. val, new is value of wire */
+ /* copy from nbsp to dcesbp */
+ memcpy(dcesbp, nsbp, dcewid);
+ return(TRUE);
+}
+
+/*
+ * vector stren and value filter for vpi_ stren only val chg call back
+ * return F if not changed
+ *
+ * needed because may assign to range but monitor bit in range did not chged
+ * also if edge operator (not chaange) sets the oval and nval
+ * dce put on target
+ *
+ * 06/06/00 - SJM - new routine to filter vpi vec stren only chg
+ */
+static int32 vccb_vec_standval_filter(register struct net_t *np,
+ register struct dcevnt_t *dcep, word32 *oval, word32 *nval, int32 oneinst)
+{
+ register byte *dcesbp, *nsbp;
+ int32 dcewid, i1, i2;
+ byte dcev, nv;
+
+ /* SJM 05/08/03 - stren can't be expr since eval of expr removes stren */
+ /* DBG remove -- */
+ if (dcep->dce_expr != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ dcewid = __get_dcewid(dcep, np);
+ /* get dce value ptr (for iact per instance so from 0th) */
+ if (oneinst) dcesbp = dcep->prevval.bp;
+ else dcesbp = &(dcep->prevval.bp[__inum*dcewid]);
+
+ __get_cor_range(dcep->dci1, dcep->dci2, &i1, &i2);
+ /* point to wire value */
+ get_stwire_addr_(nsbp, np);
+ /* since LRM allows vector - this automatically accesses low bit */
+ if (i1 != -1) nsbp = &(nsbp[i1]);
+
+ /* only need to set values for edge if complicated need expr form */
+ /* for edges only low bit */
+ /* LOOKATME - think edges can't happen here */
+ if (dcep->dce_edge)
+  {
+   if ((dcev = dcesbp[0]) == (nv = nsbp[0])) return(FALSE);
+   *oval = dcev & 3;
+   *nval = nv & 3;
+   /* update the prevval for next wire change */
+   dcesbp[0] = nsbp[0];
+   return(TRUE);
+  }
+
+ /* call back happens if only strength changes */
+ if (memcmp((char *) nsbp, (char *) dcesbp, dcewid) == 0) return(FALSE);
+ memcpy(dcesbp, nsbp, dcewid);
+ return(TRUE);
+}
+
+/*
+ * vpi_ scalar val chg stren and value filter (report stren only chges)
+ * return F if not changed
+ *
+ * 06/06/00 - SJM - new routine to filter vpi scalar stren only chg
+ */
+static int32 vccb_scal_standval_filter(register struct net_t *np,
+ register struct dcevnt_t *dcep, word32 *oval, word32 *nval, int32 oneinst)
+{
+ register byte *dcesbp, *nsbp;
+ byte dcev, nv;
+
+ /* SJM 05/08/03 - stren can't be expr since eval of expr removes stren */
+ /* DBG remove -- */
+ if (dcep->dce_expr != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* get dce value ptr (for iact per instance so from 0th) */
+ if (oneinst) dcesbp = dcep->prevval.bp;
+ else dcesbp = &(dcep->prevval.bp[__inum]);
+
+ /* point to wire value */
+ get_stwire_addr_(nsbp, np);
+ /* if values same, no edge or no change */
+ if ((dcev = dcesbp[0]) == (nv = nsbp[0])) return(FALSE);
+ dcesbp[0] = nsbp[0];
+
+ /* only need to set values for edge if complicated need expr form */
+ /* but need value without strength for edge */
+ if (dcep->dce_edge) { *oval = dcev & 3; *nval = nv & 3; }
+
+ return(TRUE);
+}
+
+/*
+ * filter non monit dce for actual change - return F if not changed
+ * called from decl itree contextfor XMR
+ *
+ * needed because may assign to range but monitor bit in range did not chged
+ * also if edge operator (not change) sets the oval and nval
+ * know wire changed so "new" prevval is wire value
+ */
+static int32 filter_dce_chg(register struct net_t *np,
+ register struct dcevnt_t *dcep, word32 *oval, word32 *nval, int32 oneinst)
+{
+ int32 dcewid, i1, i2, rv;
+ register struct xstk_t *dcexsp, *nxsp;
+
+ dcewid = __get_dcewid(dcep, np);
+ /* load dce current value */
+ push_xstk_(dcexsp, dcewid);
+ /* if only one inst prev. val. is from 0th inst but wire from rigth inst */
+ if (oneinst)
+  {
+   /* need some model so use current itree's although need inst 1 for eval */
+   /* first move from inst about to be pushed on top of */
+   __push_wrkitstk(__inst_mod, 0);
+   __ld_perinst_val(dcexsp->ap, dcexsp->bp, dcep->prevval, dcewid);
+   __pop_wrkitstk();
+  }
+ else __ld_perinst_val(dcexsp->ap, dcexsp->bp, dcep->prevval, dcewid);
+
+ /* load wire value */
+ push_xstk_(nxsp, dcewid);
+ __get_cor_range(dcep->dci1, dcep->dci2, &i1, &i2);
+ __ld_wire_sect(nxsp->ap, nxsp->bp, np, i1, i2);
+ if (cmp_vval_(dcexsp->ap, nxsp->ap, dcewid) == 0 &&
+  (cmp_vval_(dcexsp->bp, nxsp->bp, dcewid) == 0)) { rv = FALSE; goto done; }
+
+ /* only need to set values for edge if complicated need expr form */
+ if (dcep->dce_edge)
+  {
+   /* old value comes from internally stored preval, new is value of wire */
+   *oval = (dcexsp->ap[0] & 1L) | ((dcexsp->bp[0] << 1) & 2L);
+   *nval = (nxsp->ap[0] & 1L) | ((nxsp->bp[0] << 1) & 2L);
+  }
+ /* if one instance store into that 0th inst (only) loc. */
+ if (oneinst)
+  {
+   /* need itree loc. - use current mod - save before pushing on top */
+   __push_wrkitstk(__inst_mod, 0);
+   __st_perinst_val(dcep->prevval, dcewid, nxsp->ap, nxsp->bp);
+   __pop_wrkitstk();
+  }
+ else __st_perinst_val(dcep->prevval, dcewid, nxsp->ap, nxsp->bp);
+ rv = TRUE;
+done:
+ __pop_xstk();
+ __pop_xstk();
+ return(rv);
+}
+
+/*
+ * scalar stren filter non monit dce for real change
+ * return F if not changed
+ *
+ * changes are always value only - monit %v strength handles in monit
+ * as special case
+ */
+static int32 scal_stfilter_dce_chg(register struct net_t *np,
+ register struct dcevnt_t *dcep, word32 *oval, word32 *nval, int32 oneinst)
+{
+ register byte *dcesbp, *nsbp;
+ byte dcev, nv;
+
+ /* get dce value ptr (for iact per instance so from 0th) */
+ if (oneinst) dcesbp = dcep->prevval.bp;
+ else dcesbp = &(dcep->prevval.bp[__inum]);
+
+ /* point to wire value */
+ get_stwire_addr_(nsbp, np);
+ /* if values same, no edge or no change */
+ if ((dcev = (dcesbp[0] & 3)) == (nv = (nsbp[0] & 3))) return(FALSE);
+ dcesbp[0] = nsbp[0];
+
+ /* only need to set values for edge if complicated need expr form */
+ if (dcep->dce_edge) { *oval = dcev; *nval = nv; }
+
+ /* LOOKATME - could fix %v strength only change on value here */
+ /* if knew which dce was not %v and dcewid is number of bytes since stren */
+
+ return(TRUE);
+}
+
+/*
+ * TIMING CHECK SIMULATION ROUTINES
+ */
+
+/*
+ * process some time change record net pin record
+ * action depends on npp subtype
+ * these are always 1 bit only (bsel, scalar or can be low bit of vector)
+ */
+extern void __process_npp_timofchg(struct net_t *np,
+ register struct net_pin_t *npp)
+{
+ register int32 ii;
+ register struct tchg_t *tchgp;
+ int32 i1;
+ word32 new_eval, old_eval, av, bv;
+ word64 chgtim, reftim;
+ struct tchk_t *tcp;
+ struct chktchg_t *chktcp;
+ struct itree_t *downitp;
+ struct npaux_t *npauxp;
+ struct spcpth_t *newpthp;
+
+ /* notice because load bit of scalar works for entire wire get bit 0 */
+ if ((npauxp = npp->npaux) == NULL) i1 = 0; else i1 = npauxp->nbi1;
+ /* all but in module need this correction */
+ downitp = NULL;
+ if (npp->npproctyp != NP_PROC_INMOD)
+  {
+   /* know np is wire npp is on and one under itree stack is wire inst */
+   /* current itree loc. here is loc. of ref. */
+   downitp = __inst_ptr;
+   __pop_itstk();
+  }
+ __ld_bit(&av, &bv, np, i1);
+ new_eval = av | (bv << 1);
+ if (downitp != NULL) __push_itstk(downitp);
+
+ /* know inst ptr does not change in here */
+ ii = __inum;
+ switch (npp->chgsubtyp) {
+  case NPCHG_TCSTART:
+   /* notice reference event always recorded */
+   /* $period does not have reference event net pin change element */
+   tchgp = npp->elnpp.etchgp;
+   tcp = tchgp->chgu.chgtcp;
+   if (!filter_bitchange(new_eval, tchgp->oldval, tcp->startedge,
+    tcp->startcondx)) break;
+   tchgp->lastchg[ii] = __simtime;
+   if (__debug_flg && __ev_tracing)
+    {
+     char s1[RECLEN], s2[RECLEN];
+
+     if (npp->npproctyp != NP_PROC_INMOD) bld_xmrsrc_ref(s1, np);
+     else sprintf(s1, "%s.%s", __msg2_blditree(__xs, __inst_ptr),
+      np->nsym->synam);
+
+     __tr_msg("## wire %s recording %s (line %s) reference event at %s\n", s1,
+      __to_tcnam(__xs, tcp->tchktyp),
+      __bld_lineloc(s2, tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt),
+      __to_timstr(__xs2, &__simtime));
+
+      bld_srcfilter_ref(s2, FALSE, tcp->startedge, tcp->startcondx);
+      if (strcmp(s2, "") != 0) __tr_msg("   %s\n", s2);
+    }
+   break;
+  case NPCHG_TCCHK:
+   chktcp = npp->elnpp.echktchgp;
+   tchgp = chktcp->startchgp;
+   tcp = tchgp->chgu.chgtcp;
+   /* this returns F if condition or edge does not match */
+   if (!filter_bitchange(new_eval, chktcp->chkoldval, tcp->chkedge,
+    tcp->chkcondx)) break;
+
+   reftim = tchgp->lastchg[ii];
+   /* filter out initialize changes - need real change for timing check */
+   if (reftim == 0ULL)
+    {
+     /* first during run change for period recorded but no violation */
+     if (tcp->tchktyp == TCHK_PERIOD) tchgp->lastchg[ii] = __simtime;
+     break;
+    }
+   /* also if already on list for now, do not add again */
+   chgtim = chktcp->chklastchg[ii];
+   if (chgtim != __simtime)
+    {
+     add_tchk_chged(chktcp);
+     /* possibly better to only record for "record before check" case */
+     chktcp->chklastchg[ii] = __simtime;
+
+     if (__debug_flg && __ev_tracing)
+      {
+       char s1[RECLEN], s2[RECLEN];
+
+       if (npp->npproctyp != NP_PROC_INMOD) bld_xmrsrc_ref(s1, np);
+       else sprintf(s1, "%s.%s", __msg2_blditree(__xs, __inst_ptr),
+        np->nsym->synam);
+
+       __tr_msg("## wire %s recording %s (line %s) data event at %s\n", s1,
+        __to_tcnam(__xs, tcp->tchktyp),
+        __bld_lineloc(s2, tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt),
+        __to_timstr(__xs2, &__simtime));
+
+        bld_srcfilter_ref(s2, FALSE, tcp->chkedge, tcp->chkcondx);
+        if (strcmp(s2, "") != 0) __tr_msg("   %s\n", s2);
+      }
+     /* if repeated edge during same time - use 1st of this time as ref. */
+    }
+   /* SJM 10/10/04 - was wrongly setting ref even change time when repeated */
+   /* check event changes during same time */
+   break;
+  case NPCHG_PTHSRC:
+   tchgp = npp->elnpp.etchgp;
+   newpthp = tchgp->chgu.chgpthp;
+   /* special case code if no path edge or cond - also always record ifnone */
+   /* because must be simple path */
+   if (newpthp->pth_ifnone || (newpthp->pthedge == NOEDGE
+    && newpthp->pthcondx == NULL))
+    {
+     ld_scalval_(&av, &bv, tchgp->oldval);
+     old_eval = (av | (bv << 1));
+     if (new_eval == old_eval) break;
+     /* always save new value to old because value changed */
+     st2_scalval_(tchgp->oldval, new_eval);
+    }
+   else
+    {
+     if (!filter_bitchange(new_eval, tchgp->oldval, newpthp->pthedge,
+      newpthp->pthcondx)) break;
+    }
+   tchgp->lastchg[ii] = __simtime;
+   if ((__debug_flg && __ev_tracing) || __pth_tracing)
+    {
+     char s1[RECLEN], s2[RECLEN];
+
+     if (npp->npproctyp != NP_PROC_INMOD) bld_xmrsrc_ref(s1, np);
+     else sprintf(s1, "%s.%s", __msg2_blditree(__xs, __inst_ptr),
+      np->nsym->synam);
+
+     /* notice cannot identify by delay since do not know old/new value */
+     __tr_msg("## wire %s recording path (line %s) source change at %s\n", s1,
+      __bld_lineloc(s2, newpthp->pthsym->syfnam_ind,
+      newpthp->pthsym->sylin_cnt), __to_timstr(__xs, &__simtime));
+
+     bld_srcfilter_ref(s2, newpthp->pth_ifnone, newpthp->pthedge,
+      newpthp->pthcondx);
+     if (strcmp(s2, "") != 0) __tr_msg("   %s\n", s2);
+    }
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * build xmr source net instance reference
+ */
+static void bld_xmrsrc_ref(char *s, struct net_t *np)
+{
+ sprintf(s, "%s.%s (xmr from %s)",
+  __msg2_blditree(__xs, __itstk[__itspi - 1]), np->nsym->synam,
+  __msg2_blditree(__xs2, __inst_ptr));
+}
+
+/*
+ * build path source filter (ifnone, or edge and/or condition)
+ */
+static void bld_srcfilter_ref(char *s, word32 pthifnone, word32 cedge,
+ struct expr_t *cxp)
+{
+ int32 has_edge;
+ struct xstk_t *xsp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ has_edge = FALSE;
+ strcpy(s, "");
+ if (pthifnone) strcpy(s, "CONDITION: ifnone)");
+ else
+  {
+   if (cedge != NOEDGE)
+    {
+     sprintf(s1, "EDGE: %s", __to_edgenam(s2, cedge));
+     strcpy(s, s1);
+     has_edge = TRUE;
+    }
+   if (cxp != NULL)
+    {
+     xsp = __eval_xpr(cxp);
+     sprintf(s1, "CONDITION: %s TRUE value %s", __msgexpr_tostr(s2, cxp),
+      __regab_tostr(s3, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+     /* SJM 08/30/99 - for edge trace was not popping stack */
+     __pop_xstk();
+     if (has_edge) strcat(s, ", and ");
+     strcat(s, s1);
+    }
+  }
+}
+
+/*
+ * return T if bit changed (must pass all filters to change
+ * because new edge value already computed (in up), need down itree here
+ */
+static int32 filter_bitchange(register word32 new_eval, register byte *oldbp,
+ register word32 signat, struct expr_t *condx)
+{
+ register word32 old_eval;
+ word32 av, bv;
+ int32 epair;
+ struct xstk_t *xsp;
+
+ ld_scalval_(&av, &bv, oldbp);
+ old_eval = (av | (bv << 1));
+
+ /* first filter: this bit did not change */
+ if (new_eval == old_eval) return(FALSE);
+ /* always save new value to old */
+ st2_scalval_(oldbp, new_eval);
+
+ /* second filter if has edge - only change if matching edge */
+ if (signat != 0)
+  {
+   /* build edge 4 bit index */
+   epair = __epair_tab[new_eval | (old_eval << 2)];
+   /* if any edge table bit is 1, then found edge */
+   if ((signat & epair) == 0) return(FALSE);
+  }
+ /* third filter &&& cond or sdpd or edge sensitive path */
+ if (condx != NULL)
+  {
+   /* only eliminate if evaluates to 0 - x/z condition match */
+   xsp = __eval2_xpr(condx);
+   /* timing check condition expressions must be 1 bit - use low */
+   /* fastest to just always mask */
+   /* LRM requires anything but explicit false (0) is T */
+   /* for === operators never x/z (only 1 or 0) possible so always works */
+   /* === illegal in SDPDs so never a problem */
+   /* for nondeterministic x or z is always T on paths or tchks */
+
+   if ((xsp->ap[0] & 1L) == 0L && (xsp->bp[0] & 1L) == 0L)
+    { __pop_xstk(); return(FALSE); }
+   __pop_xstk();
+  }
+ return(TRUE);
+}
+
+/*
+ * add a timing check to end of now data change routines
+ * for processing at end of time slot (required by semantics)
+ */
+static void add_tchk_chged(struct chktchg_t *chkchgp)
+{
+ struct tc_pendlst_t *tcpendp;
+
+ /* get a list element from somewhere */
+ if (__tcpendfreelst == NULL)
+  tcpendp = (struct tc_pendlst_t *) __my_malloc(sizeof(struct tc_pendlst_t));
+ else
+  {
+   tcpendp = __tcpendfreelst;
+   __tcpendfreelst = __tcpendfreelst->tc_plnxt;
+  }
+ tcpendp->tc_chkchgp = chkchgp;
+ tcpendp->tc_itp = __inst_ptr;
+ tcpendp->tc_plnxt = NULL;
+
+ /* link on end since need batch movement of all to free list */
+ if (__tcpendlst_end != NULL)
+  { __tcpendlst_end->tc_plnxt = tcpendp; __tcpendlst_end = tcpendp; }
+ else
+  {
+   __tcpendlst_hdr = __tcpendlst_end = tcpendp;
+   __slotend_action |= SE_TCHK_VIOLATION;
+  }
+}
+
+/*
+ * routine to process all timing check violations at end of time slot
+ * LOOKATME - this is maybe wrong because of recording of data event order?
+ */
+static void process_all_tchk_violations(void)
+{
+ register struct tc_pendlst_t *tcpendp;
+ word64 diff, lim1, lim2, reftim;
+ struct tchk_t *tcp, *tcp2;
+ struct chktchg_t *chktcp;
+ struct tchg_t *chgp;
+ char s1[RECLEN], s2[RECLEN];
+
+ for (tcpendp = __tcpendlst_hdr; tcpendp != NULL; tcpendp = tcpendp->tc_plnxt)
+  {
+   __push_itstk(tcpendp->tc_itp);
+   chktcp = tcpendp->tc_chkchgp;
+   chgp = chktcp->startchgp;
+   tcp = chgp->chgu.chgtcp;
+   reftim = chgp->lastchg[__inum];
+   diff = __simtime - reftim;
+   /* notice no edge globals set but error before here if not simple delay */
+   if (!tcp->tc_supofsuphld && !tcp->tc_recofrecrem)
+    __get_del(&lim1, tcp->tclim_du, tcp->tc_delrep);
+   lim2 = 0ULL;
+
+   switch ((byte) tcp->tchktyp) {
+    case TCHK_SETUP:
+     if (tcp->tc_supofsuphld)
+      {
+       /* added setup of setup hold needs limit from 1st lim of setuphold */
+       /* because must be able to change both delays during sim */
+       tcp2 = (struct tchk_t *) tcp->tclim_du.pdels;
+       __get_del(&lim1, tcp2->tclim_du, tcp2->tc_delrep);
+      }
+     /* for setup if simultaneous change no violation */
+     /* setup of setuphold also here with reversed for setup conns/lim1 */
+     if (diff >= lim1 || diff == 0ULL) break;
+
+emit_msg:
+     bld_tchk_srcdump(__xs, tcp, &reftim, &__simtime, &lim1, &lim2);
+     __gfwarn(566, tcp->tcsym->syfnam_ind, tcp->tcsym->sylin_cnt,
+      "timing violation in %s (diff. %s)\n %s",
+      __msg2_blditree(s1, __inst_ptr), __to_timstr(s2, &diff), __xs);
+     /* toggle notify reg if present */
+     if (tcp->ntfy_np != NULL) process_notify(tcp->ntfy_np);
+     if (__have_vpi_actions) __vpi_tchkerr_trycall(tcp, __inst_ptr);
+     break;
+    case TCHK_SETUPHOLD:
+     /* this is hold part of setup hold */
+     __get_del(&lim2, tcp->tclim2_du, tcp->tc_delrep2);
+     /* 2nd limit is hold part */
+     lim1 = lim2;
+     /* AIV 09/15/04 - difference of 0 must not cause check - see hold */
+     if (diff < lim1 && diff != 0ULL) goto emit_msg;
+     break;
+    case TCHK_HOLD:
+     /* AIV 09/15/04 - difference of 0 must not cause check */
+     if (diff < lim1 && diff != 0ULL) goto emit_msg;
+     break;
+    case TCHK_WIDTH:
+     /* opposite edge data event less than limit after 1st edge ref., err */
+     /* if time less than threshold, ignore very narrow pulses */
+     /* if no threshold, will be set to 0, if same as threshold still err */
+     if (tcp->tc_haslim2) __get_del(&lim2, tcp->tclim2_du, tcp->tc_delrep2);
+     else lim2 = 0ULL;
+
+     /* ignore pulse width (ok) if less than lim2 (threshold) */
+     /* ? think LRM says if occur simultaneously no change (threshhold 0) */
+     if (diff < lim1 && diff >= lim2) goto emit_msg;
+     break;
+    case TCHK_PERIOD:
+     /* same edge data event less than limit after 1st edge ref. */
+     /* period error if clock period too narrow, no threshold */
+     /* no separate reference event */
+     /* must set reference event to now even if no violation */
+     chgp->lastchg[__inum] = __simtime;
+
+     /* notice if edge repeated in time slot, it is timing violation */
+     if (diff < lim1) goto emit_msg;
+     break;
+    case TCHK_SKEW:
+     /* if data event (2nd) more than limit after ref. 1st => err */
+     /* skew error if date event too long after reference event */
+     /* i.e. too much skew (lateness) of arriving signal */
+     /* SJM 04/13/04 - if backward should be opposite of PERIOD above */
+     if (diff > lim1) goto emit_msg;
+     break;
+    case TCHK_RECREM:
+     /* this is removal part of recrem */
+     __get_del(&lim2, tcp->tclim2_du, tcp->tc_delrep2);
+     /* 2nd limit is hold part */
+     lim1 = lim2;
+     if (diff < lim1 && diff != 0ULL) goto emit_msg;
+     break;
+    case TCHK_RECOVERY:
+     /* SJM 01/16/04 - terminals reversed for rec part of recrem */
+     if (tcp->tc_recofrecrem)
+      {
+       /* added setup of setup hold needs limit from 1st lim of setuphold */
+       /* because must be able to change both delays during sim */
+       tcp2 = (struct tchk_t *) tcp->tclim_du.pdels;
+       __get_del(&lim1, tcp2->tclim_du, tcp2->tc_delrep);
+      }
+
+     /* if data event (2nd clock) occurs too soon after 1st (clear edge) */
+     /* recovery like hold but error if reference event not edge */
+     /* recovery err if clock happens too soon after clear or preset edge */
+     if (diff < lim1 && diff != 0ULL) goto emit_msg;
+     break;
+    case TCHK_REMOVAL:
+     /* if data event (2nd clock) does not occur soon enough after 1st */
+     /* (clear edge) - removal like setup but error if reference event not */
+     /* edge - removal err if clock happens too soon after clear or preset */
+     /* edge */
+     /* AIV 07/09/04 - removal test was reversed - was > but needs to be < */
+     if (diff < lim1 && diff != 0ULL) goto emit_msg;
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+   __pop_itstk();
+  }
+ /* must move all processed to front of free list */
+ __tcpendlst_end->tc_plnxt = __tcpendfreelst;
+ __tcpendfreelst = __tcpendlst_hdr;
+ __tcpendlst_hdr = __tcpendlst_end = NULL;
+}
+
+/* LOOKATME - to match OVISIM x goes to 1 not 0 */
+static word32 ntfy_toggle_tab[] = {1, 0, 2, 1};
+
+/*
+ * process notify
+ */
+static void process_notify(struct net_t *np)
+{
+ struct xstk_t *xsp;
+ word32 val;
+
+ push_xstk_(xsp, np->nwid);
+ __ld_wire_val(xsp->ap, xsp->bp, np);
+ /* DBG remove */
+ if (xsp->xslen != 1) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ val = xsp->ap[0] | (xsp->bp[0] << 1);
+ val = ntfy_toggle_tab[val];
+ xsp->ap[0] = val & 1L;
+ xsp->bp[0] = (val >> 1) & 1L;
+ __chg_st_val(np, xsp->ap, xsp->bp);
+ __pop_xstk();
+}
+
+/*
+ * build a timing check source dump string with constants
+ *
+ * notice for setuphold (hold part) lim1 is correct lim2
+ */
+static char *bld_tchk_srcdump(char *s, struct tchk_t *tcp, word64 *tim1,
+ word64 *tim2, word64 *lim1, word64 *lim2)
+{
+ int32 nd_rpar;
+ char s1[RECLEN];
+
+ __cur_sofs = 0;
+ /* indicate whether setup or hold */
+ if (tcp->tchktyp == TCHK_SETUPHOLD) __adds("hold(of setuphold)");
+ else if (tcp->tc_supofsuphld) __adds("setup(of setuphold)");
+ else if (tcp->tchktyp == TCHK_RECREM) __adds("removal(of recrem)");
+ else if (tcp->tc_recofrecrem) __adds("recovery(of recrem)");
+ else __adds(__to_tcnam(s1, tcp->tchktyp));
+
+ __adds("(");
+ if (tcp->startedge != NOEDGE || tcp->startcondx != NULL)
+  { addch_('('); nd_rpar = TRUE; }
+ else nd_rpar = FALSE;
+ if (tcp->startedge != NOEDGE)
+  { __adds(__to_edgenam(s1, tcp->startedge)); addch_(' '); }
+ __adds(__msgexpr_tostr(s1, tcp->startxp));
+ if (tcp->startcondx != NULL)
+  { __adds(" &&& "); __adds(__msgexpr_tostr(s1, tcp->startcondx));  }
+ if (nd_rpar) addch_(')');
+ addch_(':');
+ __adds(__to_timstr(s1, tim1));
+
+ __adds(", ");
+ if (tcp->chkedge != NOEDGE || tcp->chkcondx != NULL)
+  { addch_('('); nd_rpar = TRUE; }
+ else nd_rpar = FALSE;
+ if (tcp->chkedge != NOEDGE)
+  { __adds(__to_edgenam(s1, tcp->chkedge)); addch_(' '); }
+ __adds(__msgexpr_tostr(s1, tcp->chkxp));
+ if (tcp->chkcondx != NULL)
+  { __adds(" &&& "); __adds(__msgexpr_tostr(s1, tcp->chkcondx));  }
+ if (nd_rpar) addch_(')');
+ addch_(':');
+ __adds(__to_timstr(s1, tim2));
+
+ __adds(", ");
+ __adds(__to_timstr(s1, lim1));
+
+ if ((tcp->tchktyp == TCHK_WIDTH || tcp->tchktyp == TCHK_PERIOD)
+  && *lim2 != 0ULL)
+  { __adds(", "); __adds(__to_timstr(s1, lim2)); }
+ __adds(");");
+ __trunc_exprline(MSGTRUNCLEN, FALSE);
+ strcpy(s, __exprline);
+ __cur_sofs = 0;
+ return(s);
+}
+
+/*
+ * ROUTINES TO INITIALIZE BEFORE START OF SIMULATION
+ * TRICKY BEGINNING OF TIME 0 PROPOGATION HERE
+ */
+
+/*
+ * initialization just before simulation start
+ * need a dummy thread for functions on rhs of contas
+ *
+ * notice can execute statements from called conta rhs functions in here
+ */
+extern void __init_sim(void)
+{
+ char *sav_fnam;
+
+ /* this is never called for resets, so initialize to no resets */
+ __reset_count = 0;
+ /* just set this to some value - task exec. always sets again */
+ __reset_value = 0;
+
+ init_stime();
+ sav_fnam = __in_fils[0];
+ __in_fils[0] = __pv_stralloc("**initialize none**");
+
+ /* do not emit new message at time 0 since initialize time */
+ __last_trtime = 0ULL;
+ __last_evtrtime = 0ULL;
+
+ __suspended_thd = NULL;
+ __suspended_itp = NULL;
+ __cur_thd = NULL;
+ /* current inst. stack needs nil on bottom for debugging and must be empty */
+ /* DBG remove -- */
+ if (__itspi != -1) __misc_terr(__FILE__, __LINE__);
+ if (__inst_ptr != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* must leave instance stack exactly as is - cannot initialize */
+ init_wires();
+ __pv_stlevel = 0;
+
+ /* initialize dumpvars state */
+ __dv_calltime = 0ULL;
+ __dv_seen = FALSE;
+ __dv_state = DVST_NOTSETUP;
+ __dv_dumplimit_size = 0;
+ __dv_chgnethdr = NULL;
+ __dv_netfreelst = NULL;
+ __dv_hdr = __dv_end = NULL;
+ __dv_isall_form = FALSE;
+
+ __in_fils[0] = sav_fnam;
+ /* debugger source files go through last library file */
+ __last_srcf = __last_lbf;
+ /* putting any $input files on end since last_inf only needed for $input */
+ /* from now on */
+ /* resetting does not effect this */
+ __last_inf = __last_lbf;
+
+ /* last step is to setup interactive environment */
+ /* needed since interactive setup stuff can be in source */
+ __init_interactive();
+ if (__slotend_action != 0) __misc_terr(__FILE__, __LINE__);
+ __slotend_action = 0;
+ __run_state = SS_SIM;
+}
+
+/*
+ * initial simulation time and variables
+ */
+static void init_stime(void)
+{
+ register int32 i;
+ struct telhdr_t *telp;
+
+ /* initialize the simulation realloced event table */
+ /* because fibronacci growth start with small value */
+
+ /* notice for now fixed size timing wheel */
+ /* initialize timing wheel headers to no events but need place holder */
+ /* allocate timing wheel - allow variable sizing - should adjust from ts */
+ __twhsize = TWHINITSIZE;
+
+ /* need to allocate extra fence */
+ __twheel = (struct telhdr_t **)
+  __my_malloc((__twhsize + 1) *sizeof(struct telhdr_t *));
+
+ /* include extra fence in loop */
+ for (i = 0; i <= __twhsize; i++)
+  {
+   __twheel[i] = telp = (struct telhdr_t *)
+    __my_malloc(sizeof(struct telhdr_t));
+   telp->te_hdri = telp->te_endi = -1;
+   telp->num_events = 0;
+  }
+ /* this is fence */
+ __twheel[__twhsize]->num_events = -1;
+ /* just need some good value here */
+ __twheel[__twhsize]->te_hdri = -1;
+
+ __simtime = 0ULL;
+ __cur_te_hdri = __cur_te_endi = -1;
+ __p0_te_hdri = __p0_te_endi = -1;
+ /* SJM 07/05/05 - also initialize non block current time after pnd0 queue */
+ __nb_te_hdri = __nb_te_endi = -1;
+
+ __tedpfreelst = NULL;
+ __teputvfreelst = NULL;
+ /* init overflow q */
+ __topi = 0;
+ __btqroot = NULL;
+
+ /* whetime is end of wheel time */
+ /* works because __twsize never bigger than 2*31 */
+ __whetime = (word64) (__twhsize - 1);
+ __num_twhevents = 0;
+ __num_ovflqevents = 0;
+ __num_proc_tevents = __num_cancel_tevents = 0;
+ __inertial_cancels = __newval_rescheds = 0;
+ __proc_thrd_tevents = 0;
+ __num_netchges = 0;
+ __num_switch_vtxs_processed = 0;
+ __immed_assigns = 0;
+ __strobe_hdr = __strobe_end = __strb_freelst = NULL;
+ __monit_active = TRUE;
+ __monit_dcehdr = NULL;
+ __fmon_hdr = __fmon_end = NULL;
+ __fmonse_hdr = __fmonse_end = __fmse_freelst = NULL;
+ __nchg_futend = __nchg_futhdr = __nchgfreelst = NULL;
+ /* SJM 08/16/03 - now need to start with lhs changed off */
+ __lhs_changed = FALSE;
+ __tcpendlst_end = __tcpendlst_hdr = __tcpendfreelst = NULL;
+ __dltevfreelst = NULL;
+ __cur_thd = NULL;
+ /* tf one way pending event free list */
+ __ltevfreelst = NULL;
+ __wrkevtab = NULL;
+ __last_wevti = -1;
+ __size_wrkevtab = 0;
+}
+
+/*
+ * after debugger :rerun command - do initialization
+ */
+extern void __reinit_sim(void)
+{
+ char *sav_fnam;
+
+ /* another reset - needed first in case init code uses $reset_count */
+ __reset_count++;
+
+ /* for catching problems with incorrectly reset dces */
+ /* DBG remove ---
+ chk_schd_dces();
+ --- */
+
+ reinit_stime();
+
+ sav_fnam = __in_fils[0];
+ __in_fils[0] = __pv_stralloc("**initialize none**");
+
+ /* no time 0 messages */
+ __last_trtime = 0ULL;
+ __last_evtrtime = 0ULL;
+
+ /* current inst. stack needs nil on bottom for debugging */
+ __cur_thd = NULL;
+ __suspended_thd = NULL;
+ __suspended_itp = NULL;
+ /* must empty stack since may have been called from running code */
+ __itspi = -1;
+ __itstk[0] = NULL;
+ __inst_ptr = NULL;
+ __inst_mod = NULL;
+
+ /* must leave instance stack exactly as is - cannot initialize */
+ init_wires();
+ __pv_stlevel = 0;
+
+ /* reinitialize dumpvars state */
+ __dv_calltime = 0ULL;
+ __dv_seen = FALSE;
+ __dv_state = DVST_NOTSETUP;
+ __dv_dumplimit_size = 0;
+ __dv_chgnethdr = NULL;
+ __dv_hdr = __dv_end = NULL;
+ __dv_isall_form = FALSE;
+
+ /* free and maybe close open command file - for reset will use start cmd_s */
+ if (__cmd_s != NULL)
+  {
+   __my_fclose(__cmd_s);
+   __cmd_s = NULL;
+   __my_free(__cmd_fnam, strlen(__cmd_fnam) + 1);
+   __cmd_fnam = NULL;
+  }
+
+ __in_fils[0] = sav_fnam;
+
+ /* interactive environment must be left as is */
+ __slotend_action = 0;
+
+ /* things initialized in pv that need to be re-initialized */
+ __next_dvnum = 0;
+ /* reset interactive run state */
+ __pending_enter_iact = FALSE;
+ __iact_reason = IAER_UNKN;
+ /* this will cause any -i file to be read on first iact entry */
+ __ia_entered = FALSE;
+ __cur_sofs = 0;
+ __xspi = __itspi = __fcspi = -1;
+ __inst_ptr = NULL;
+ /* reinit $scope must start at first top level module */
+ __scope_ptr = __it_roots[0];
+ __scope_tskp = NULL;
+ __run_state = SS_SIM;
+}
+
+/*
+ * reinitial simulation time and variables
+ */
+static void reinit_stime(void)
+{
+ __simtime = 0ULL;
+ __cur_te_hdri = __cur_te_endi = -1;
+ __p0_te_hdri = __p0_te_endi = -1;
+ /* SJM 07/05/05 - also initialize non block current time after pnd0 queue */
+ __nb_te_hdri = __nb_te_endi = -1;
+
+ /* works because __twsize never bigger than 2*31 */
+ __whetime = (word64) (__twhsize - 1);
+ __num_twhevents = 0;
+ __num_ovflqevents = 0;
+ __num_proc_tevents = __num_cancel_tevents = 0;
+ __inertial_cancels = __newval_rescheds = 0;
+ __proc_thrd_tevents = 0;
+ __num_netchges = 0;
+ __immed_assigns = 0;
+ __strobe_hdr = __strobe_end = NULL;
+ __monit_active = TRUE;
+ __monit_dcehdr = NULL;
+ __fmon_hdr = __fmon_end = NULL;
+ /* here leave the free list to reuse storage from there */
+ __fmonse_hdr = __fmonse_end = NULL;
+
+ /* SJM 08/16/03 - now need to start with lhs changed off */
+ __lhs_changed = FALSE;
+
+ /* notice must leave free lists - will begin by allocating from there */
+ __nchg_futend = __nchg_futhdr = NULL;
+ __tcpendlst_end = __tcpendlst_hdr = NULL;
+ __cur_thd = NULL;
+
+ /* must leave tevtab timing queue - free added o free list */
+ /* num used stays same */
+}
+
+/*
+ * initialize by scheduling a wire change for every wire driver
+ * needs empty timing wheel header for delay 0 scheduling
+ *
+ * this needs to be run with all wire delays disabled
+ * no PLI interaction here and run in SS_RESET or SS_LOAD run state
+ */
+static void init_wires(void)
+{
+ int32 ii;
+
+ __wire_init = TRUE;
+ /* go through list of 1 inst. corresponding to each top level module */
+ /* ignore all delays in propagating from lhs's to rhs's */
+ __nchg_futend = __nchg_futhdr = NULL;
+ __initalw_thrd_hdr = NULL;
+
+ /* SJM - 05/24/00 - must not process var changes until 0 normal #0 pt. */
+ /* if (__nchg_futhdr != NULL) process_all_netchgs(); */
+
+ for (ii = 0; ii < __numtopm; ii++)
+  {
+   init_itinsts(__it_roots[ii]);
+   /* even though top modules can be linked by xmrs, do here can at worst */
+   /* cause a few extra events to be processed from xmrs */
+   /* SJM - 05/24/00 - must not process var changes until 0 normal #0 pt. */
+   /* if (__nchg_futhdr != NULL) process_all_netchgs(); */
+  }
+
+ /* SJM 04/11/01 - initializing tran channels after drivers propagated */
+ /* hard drivers as possible have changed */
+ __init_all_trchans();
+
+ __wire_init = FALSE;
+ if (__ev_tracing)
+  __tr_msg("\n>>>> wire initialization complete <<<<<\n");
+}
+
+/*
+ * initialize all wires and threads in one itree instance
+ * know that when storage for all wires allocated, also initialized
+ *
+ * algorithm is to evaluate every cont. assign (including cross module ports)
+ * and gate/udp and schedule wire change at some point
+ * this adds all no delay to netchg list and all delays are scheduledo
+ * with pnd0's going on pnd0 list
+ *
+ * also allocate and schedules all behavioral initial/always threads
+ * notice behavior force/assign can only occur during time 0 or later
+ */
+static void init_itinsts(struct itree_t *up_itp)
+{
+ register int32 gi, pbi;
+ int32 cai, ii;
+ struct conta_t *cap;
+ struct mod_t *mdp;
+ struct itree_t *itp;
+
+ if (__debug_flg)
+  {
+   __dbg_msg("== initializing wires in %s\n", __msg2_blditree(__xs, up_itp));
+  }
+ /* on entry know unprocessed net change list empty */
+ mdp = up_itp->itip->imsym->el.emdp;
+ __push_itstk(up_itp);
+ /* schedule all behavioral threads for this instance */
+ init_sched_thd(mdp);
+
+ /* evaluate and schedule all gates in instance */
+ for (gi = 0; gi < mdp->mgnum; gi++) gate_initeval(&(mdp->mgates[gi]));
+
+ /* and all contas */
+ for (cap = mdp->mcas, cai = 0; cai < mdp->mcanum; cai++, cap++)
+  {
+   /* SJM 09/28/02 - need to initialize the PB separated contas */
+   if (cap->ca_pb_sim)
+    {
+     /* SJM 08/08/03 - for per bit sim form, need 2nd arg master conta */
+     for (pbi = 0; pbi < cap->lhsx->szu.xclen; pbi++)
+      { conta_initeval(&(cap->pbcau.pbcaps[pbi]), cap); }
+    }
+   else conta_initeval(cap, cap);
+  }
+ __pop_itstk();
+
+ for (ii = 0; ii < mdp->minum; ii++)
+  {
+   itp = &(up_itp->in_its[ii]);
+   /* force downward cross port continuous assign for inputs and inouts */
+   __init_instdownport_contas(up_itp, itp);
+
+   /* process depth first down one instance */
+   init_itinsts(itp);
+
+   /* force upward from down (after its processed) output/inout contas */
+   __init_instupport_contas(itp);
+  }
+}
+
+/*
+ * build thread and schedule time 0 event for each initial always block
+ * just goes into time 0 current time event list as if time move from -1
+ *
+ * if initial/always statement is named block will have unnamed block
+ * put around it by here
+ *
+ * this requires cur. itp to be set to current place in itree
+ */
+static void init_sched_thd(struct mod_t *mdp)
+{
+ register struct ialst_t *ialp;
+ struct thread_t *thp;
+ i_tev_ndx tevpi;
+ struct telhdr_t *tw0;
+ struct st_t *stp, *stp2;
+
+ /* each element in ia sts list is a possibly added unnamed begin block */
+ /* each separate intial/always must be its own thread */
+ /* because one blocking does not block others */
+ for (ialp = mdp->ialst; ialp != NULL; ialp = ialp->ialnxt)
+  {
+   /* build the initial/always thread */
+   /* build the event and allocate assoc. thread */
+   alloc_tev_(tevpi, TE_THRD, __inst_ptr, __tim_zero);
+   stp = ialp->iastp;
+
+   thp = __alloc_thrd();
+   thp->th_ialw = TRUE;
+   __cur_thd = thp;
+   thp->thenbl_sfnam_ind = ialp->ia_first_ifi;
+   thp->thenbl_slin_cnt = ialp->ia_first_lini;
+   /* caller must alloc any event type specific fields, cannot assume NULL */
+   __tevtab[tevpi].tu.tethrd = thp;
+   thp->thnxtstp = stp;
+   thp->thpar = NULL;
+   thp->th_itp = __inst_ptr;
+   /* link on sequential list for rerun freeing */
+   if (__initalw_thrd_hdr == NULL) __initalw_thrd_hdr = thp;
+   else
+    {
+     thp->thright = __initalw_thrd_hdr;
+     __initalw_thrd_hdr->thleft = thp;
+     __initalw_thrd_hdr = thp;
+    }
+
+   /* this just causes all initial and always 1st statements to happen */
+   /* at time 0 - know thnxtstp is just list of statements */
+   if (__ev_tracing)
+    {
+     stp2 = __tevtab[tevpi].tu.tethrd->thnxtstp;
+     if (stp2 == NULL)
+      {
+       __tr_msg(
+        "-- adding initial machine code thread for init/always at %s\n",
+        __bld_lineloc(__xs, ialp->ia_first_ifi, ialp->ia_first_lini));
+      }
+     else
+      {
+       __tr_msg("-- adding initial procedural start at statement %s\n",
+        __bld_lineloc(__xs, stp2->stfnam_ind, stp2->stlin_cnt));
+      }
+    }
+
+   tw0 = __twheel[0];
+   if (tw0->te_hdri == -1) tw0->te_hdri = tw0->te_endi = tevpi;
+   else { __tevtab[tw0->te_endi].tenxti = tevpi; tw0->te_endi = tevpi; }
+   tw0->num_events += 1;
+   __num_twhevents++;
+   __cur_thd = NULL;
+  }
+}
+
+/*
+ * initialize gate by evaluating all inputs, changing wire if needed,
+ * and if wire changed, propagate changes
+ * called once for every gate in itree
+ */
+static void gate_initeval(struct gate_t *gp)
+{
+ int32 i, gid;
+
+ /* evaluate gate - even if no change assign (this stores state) */
+ /* if input value same, nothing to do */
+ switch ((byte) gp->g_class) {
+  case GC_LOGIC: init_logic_gate(gp); break;
+  case GC_UDP: init_udp(gp); break;
+  case GC_BUFIF: init_bufif_gate(gp); break;
+  case GC_MOS:
+   chg_mos_instate(gp, 1);
+   chg_mos_instate(gp, 2);
+
+   gid = gp->gmsym->el.eprimp->gateid;
+   /* note here input change routine and eval separate */
+   /* eval always evals even if new and old input are the same */
+   if (gid == G_NMOS) __eval_nmos_gate(gp->gstate.wp[__inum]);
+   else if (gid == G_RNMOS) __eval_rnmos_gate(gp->gstate.wp[__inum]);
+   else if (gid == G_PMOS) __eval_pmos_gate(gp->gstate.wp[__inum]);
+   else if (gid == G_RPMOS) __eval_rpmos_gate(gp->gstate.wp[__inum]);
+   else __case_terr(__FILE__, __LINE__);
+   break;
+  case GC_CMOS:
+   chg_mos_instate(gp, 1);
+   chg_mos_instate(gp, 2);
+   chg_mos_instate(gp, 3);
+   /* note here input change routine and eval separate */
+   /* eval always evals even if new and old input are the same */
+   __eval_cmos_gate(gp);
+   break;
+  case GC_PULL:
+   /* each port is pull wire */
+   /* this is needed since probably all drivers tristate at time 0 */
+   /* but pull must start at time 0 */
+   /* notice no output here so starts at 0 not 1 (normally 0 output) */
+   for (i = 0; i < (int32) gp->gpnum; i++)
+    __mdr_assign_or_sched(gp->gpins[i]);
+   if (__debug_flg)
+    {
+     __dbg_msg("-- all connections of pull %s evalutated for initialization\n",
+     to_evtronam(__xs, gp->gsym->synam, __inst_ptr,
+      (struct task_t *) NULL));
+    }
+   return;
+  case GC_TRANIF: init_tranif_gate(gp); return;
+  /* nothing to do for trans */
+  case GC_TRAN: return;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+
+ if (__debug_flg && __ev_tracing)
+  {
+   char s1[RECLEN];
+
+   if (gp->g_class == GC_UDP) strcpy(s1, "udp"); else strcpy(s1, "gate");
+   /* notice during wire init all wire delays off */
+   __tr_msg("-- %s %s %s assign initialized to state:\n",
+    gp->gmsym->synam, s1, to_evtronam(__xs, gp->gsym->synam, __inst_ptr,
+     (struct task_t *) NULL));
+   __tr_msg("   %s\n", __gstate_tostr(__xs, gp, FALSE));
+  }
+ /* must always immediately assign to wire */
+ change_gate_outwire(gp);
+}
+
+/*
+ * initialize udps
+ * 1) evaluate all udp input exprs in case constant (update wide signature)
+ * 2) if has initial value, set new gate value to initial and do not eval
+ * 3) if no initial value, force evaluate to get new gate value
+ * for sequential use combinatorial table
+ *
+ * for wide this updates signature to x that is then adjusted by
+ * storing gate output that always happens during init.
+ *
+ * notice that for gpins, 0 is output and first input is 1
+ * but values in upd state word32 are input 0 in low 2 bits, and high (maybe
+ * output if sequential) in high 2 bits
+ */
+static void init_udp(struct gate_t *gp)
+{
+ register int32 i;
+ int32 nins;
+ hword *hwp;
+ word32 wide_ival, new_inputval, *wp;
+ int32 out_chg;
+ struct xstk_t *xsp;
+ extern word32 __to_noztab[];
+ extern word32 __to_uvaltab[];
+
+ __cur_udp = gp->gmsym->el.eudpp;
+ /* for level, this includes state */
+ nins = __cur_udp->numins;
+ if (!__cur_udp->u_wide)
+  {
+   /* here can ingore old state (if present) since just over-written */
+   hwp = &(gp->gstate.hwp[__inum]);
+   /* eval and store all inputs in case constant expr. */
+   for (i = 0; i < nins; i++)
+    {
+     xsp = __eval_xpr(gp->gpins[i + 1]);
+     new_inputval = __to_noztab[(xsp->ap[0] & 1L) | ((xsp->bp[0] & 1L) << 1)];
+     __pop_xstk();
+     /* know z will always cause new input value */
+     /* change the input */
+     hwp[0] &= ~(3L << (2*i));
+     hwp[0] |= ((hword) new_inputval << (2*i));
+     /* -- RELEASE remove ---
+     if (__debug_flg)
+      __dbg_msg("-- udp init after %dth input hwp=%lx\n", i, hwp[0]);
+     -- */
+    }
+   /* -- RELEASE remove --
+   if (__debug_flg)
+    __dbg_msg("-- narrow before init eval: hwp=%lx\n", hwp[0]);
+   -- */
+  }
+ else
+  {
+   /* in wide, case need 2nd running value index word32 */
+   wp = &(gp->gstate.wp[2*__inum]);
+   for (i = 0; i < nins; i++)
+    {
+     /* remove signature contribution from initialized value */
+     wide_ival = __to_uvaltab[((wp[0] >> (2*i)) & 3L)];
+     wp[1] -= wide_ival*__pow3tab[i];
+
+     xsp = __eval_xpr(gp->gpins[i + 1]);
+     /* think evaluate can be wide thing that must be truncated */
+     new_inputval = __to_noztab[(xsp->ap[0] & 1L) | ((xsp->bp[0] & 1L) << 1)];
+     __pop_xstk();
+     wp[0] &= ~(3L << (2*i));
+     wp[0] |= (new_inputval << (2*i));
+
+     /* add in new input signature value */
+     wide_ival = __to_uvaltab[new_inputval];
+     wp[1] += wide_ival*__pow3tab[i];
+    }
+   /* -- RELEASE remove ---
+   if (__debug_flg)
+     __dbg_msg("-- wide before init eval: w0=%lx, w1=%lu\n", wp[0], wp[1]);
+   -- */
+  }
+ /* know combinatorial will never have initial value */
+ if (__cur_udp->ival == NO_VAL)
+  {
+   /* change old input 0 to force evaluation - new replace set wrong */
+   if (!__cur_udp->u_wide)
+    {
+     hwp = &(gp->gstate.hwp[__inum]);
+     new_inputval = (word32) (hwp[0] & 3L);
+     if (new_inputval == 0) new_inputval = 3; else new_inputval = 0;
+     hwp[0] &= ~(3L);
+     hwp[0] |= (hword) new_inputval;
+    }
+   else
+    {
+     wp = &(gp->gstate.wp[2*__inum]);
+     new_inputval = wp[0] & 3L;
+     /* subtract out old signature contribution */
+     wide_ival = __to_uvaltab[new_inputval];
+     wp[1] -= wide_ival*__pow3tab[0];
+
+     if (new_inputval == 0) new_inputval = 2; else new_inputval = 0;
+     wp[0] &= ~(3L);
+     wp[0] |= new_inputval;
+
+     /* add in new input signature value */
+     wide_ival = __to_uvaltab[new_inputval];
+     wp[1] += wide_ival*__pow3tab[0];
+    }
+   /* this sets new gate value */
+   __eval_udp(gp, 1, &out_chg, FALSE);
+  }
+ else __new_gateval = __cur_udp->ival;
+ /* caller will store or schedule store into output connection */
+}
+
+/*
+ * initialize logic gate by evaluating all inputs then forcing eval of
+ * logic gate - not for buf and mos types gates
+ */
+static void init_logic_gate(struct gate_t *gp)
+{
+ register int32 i;
+ int32 srep, nins;
+ int32 out_chg;
+ struct xstk_t *xsp;
+
+ if (gp->gpnum > 16) srep = SR_VEC; else srep = SR_PVEC;
+
+ /* tricky part must - make sure input 0 does not eval the same */
+ /* simply invert b bit of input 0 result */
+ nins = gp->gpnum - 1;
+ for (i = 0; i < nins; i++)
+  {
+   xsp = __eval_xpr(gp->gpins[i + 1]);
+   xsp->ap[0] &= 1L;
+   xsp->bp[0] &= 1L;
+   if (i == 0) xsp->bp[0] = (~xsp->bp[0]) & 1L;
+   gate_st_bit(gp->gstate, (int32) gp->gpnum, i, srep, xsp->ap[0], xsp->bp[0]);
+   __pop_xstk();
+  }
+ /* know reevaluating 1st input will result in new value so will eval. */
+ __eval_logic_gate(gp, 1, &out_chg);
+ /* wire assign in caller */
+}
+
+/*
+ * initialize a bufif style gate
+ * evaluate both inputs and change gate state for data to opposite
+ *
+ * storage: low 2 bits data in, next 2 control in - next 8 out strength
+ * stored as half word
+ */
+static void init_bufif_gate(struct gate_t *gp)
+{
+ int32 out_chg;
+ hword *hwp;
+ struct xstk_t *xsp;
+
+ hwp = &(gp->gstate.hwp[__inum]);
+ xsp = __eval_xpr(gp->gpins[1]);
+ xsp->ap[0] &= 1L;
+ xsp->bp[0] &= 1L;
+ /* invert to force eval */
+ xsp->bp[0] = (~xsp->bp[0]) & 1L;
+ hwp[0] &= ~3L;
+ hwp[0] |= ((hword) (xsp->ap[0] | (xsp->bp[0] << 1)));
+ __pop_xstk();
+
+ xsp = __eval_xpr(gp->gpins[2]);
+ xsp->ap[0] &= 1L;
+ xsp->bp[0] &= 1L;
+ hwp[0] &= ~(3L << 2);
+ hwp[0] |= ((hword) ((xsp->ap[0] | (xsp->bp[0] << 1)) << 2));
+ __pop_xstk();
+ /* eval. 1st input in gpins - index 1 */
+ __eval_bufif_gate(gp, 1, &out_chg);
+}
+
+/*
+ * initialize the state of a tranif gate by evaluating control input
+ * here must evaluate input and store into state
+ * for tran, do not need any initialization
+ */
+static void init_tranif_gate(struct gate_t *gp)
+{
+ register word32 cval;
+ int32 conducting, gateid, bi, wi;
+ struct xstk_t *xsp;
+
+ /* first initialize conducting state */
+ xsp = __eval_xpr(gp->gpins[2]);
+ conducting = (xsp->ap[0] & 1L) | ((xsp->bp[0] & 1L) << 1);
+ if (conducting == 2) conducting = 3;
+ __pop_xstk();
+ gateid = gp->gmsym->el.eprimp->gateid;
+ /* for if0s, 0 turns on (1), 1 of (0) */
+ if (gateid == G_TRANIF0 || gateid == G_RTRANIF0)
+  {
+   if (conducting == 0) conducting = 1;
+   else if (conducting == 1) conducting = 0;
+  }
+
+ /* immediate change to conducting state during initialization */
+ bi = get_bofs_(2*__inum);
+ wi = get_wofs_(2*__inum);
+ cval = gp->gstate.wp[wi];
+ cval &= ~(3L << bi);
+ cval |= (conducting << bi);
+ gp->gstate.wp[wi] = cval;
+
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg("-- %s %s 3rd input evaluated - initial conducting: %s\n",
+    gp->gmsym->synam, to_evtronam(__xs, gp->gsym->synam, __inst_ptr,
+    (struct task_t *) NULL), (conducting == 1) ? "*ON*"
+     : ((conducting == 0) ? "*OFF*" : "*UNKNOWN*"));
+  }
+}
+
+/*
+ * evaluate continous assign to initialize lhs
+ * notice ignore conta delay here but use wire delay
+ *
+ * SJM 09/28/02 - for per bit rhs concat contas, caller passed decomposed PB
+ */
+static void conta_initeval(struct conta_t *cap, struct conta_t *mast_cap)
+{
+ int32 lhslen, orhslen;
+ byte *sbp;
+ struct xstk_t *xsp, *xsp2;
+ struct expr_t *xp, *lhsxp;
+ struct sy_t *syp;
+
+ /* do not need to set lhs here before schedule changed */
+ xp = cap->rhsx;
+ lhsxp = cap->lhsx;
+ /* if rhs normal function must call it in case of constant args */
+ /* but $getpattern must just assign right width x's since index probably */
+ /* out of range at this point */
+ if (xp->optyp == FCALL)
+  {
+   syp = xp->lu.x->lu.sy;
+   /* know getpat conta form never has rhsval wp or driver wp */
+   /* rule is that $getpattern with unknown index is x's */
+   if (syp->sytyp == SYM_SF && syp->el.esyftbp->syfnum == STN_GETPATTERN)
+    {
+     lhslen = lhsxp->szu.xclen;
+     push_xstk_(xsp, lhslen);
+     /* IN - getpattern with unknown index (like at init) return x value */
+     one_allbits_(xsp->ap, lhslen);
+     one_allbits_(xsp->bp, lhslen);
+
+     /* know all getpat lhs wires fi == 1 and no wire delay and no stren */
+     __exec_ca_concat(lhsxp, xsp->ap, xsp->bp, FALSE);
+     __pop_xstk();
+     return;
+    }
+  }
+
+ lhslen = lhsxp->szu.xclen;
+ xsp = __eval_xpr(xp);
+ if (xsp->xslen != lhslen)
+  {
+   orhslen = xsp->xslen;
+
+   /* SJM 09/29/03 - change to handle sign extension and separate types */
+   if (xsp->xslen > lhslen) __narrow_sizchg(xsp, lhslen);
+   else if (xsp->xslen < lhslen)
+    {
+     if (xp->has_sign) __sgn_xtnd_widen(xsp, lhslen);
+     else __sizchg_widen(xsp, lhslen);
+    }
+   /* during initialization widen to x not 0 */
+
+   /* SJM 05/19/04 - remove see below must widen rhs expr using 0's */
+   /* --
+   if (orhslen < xsp->xslen)
+    {
+     if (__wire_init) __fix_widened_toxs(xsp, orhslen);
+    }
+   -- */
+  }
+
+ /* fi == 1 and no delay contas have no driver state stored */
+ if (cap->ca_drv_wp.wp != NULL)
+  {
+   /* SJM - 02/18/03 - remove - since above does same change so never exec */
+   /* --- REMOVED
+   if (xsp->xslen != lhslen)
+    {
+     orhslen = xsp->xslen;
+
+     -* SJM 09/29/03 - change to handle sign extension and separate types *-
+     if (xsp->xslen > lhslen) __narrow_sizchg(xsp, lhslen);
+     else if (xsp->xslen < lhslen)
+      {
+       if (xp->has_sign) __sgn_xtnd_widen(xsp, lhslen);
+       else __sizchg_widen(xsp, lhslen);
+      }
+
+     __fix_widened_toxs(xsp, orhslen);
+    }
+   -- */
+   __st_perinst_val(cap->ca_drv_wp, lhslen, xsp->ap, xsp->bp);
+  }
+ if (__debug_flg && __ev_tracing)
+  {
+   char s1[RECLEN];
+
+   /* notice even if delay wire, off during wire initialization */
+   strcpy(s1, "assigned");
+   __tr_msg("-- %s %s initial value %s\n", s1,
+    __to_evtrcanam(__xs, mast_cap, __inst_ptr),
+    __regab_tostr(__xs2, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
+  }
+
+ /* notice multi-fi case assume new driving value already assigned */
+ /* this will add any conta driving strength if needed from ca drv wp */
+ if (lhsxp->x_multfi) __mdr_assign_or_sched(lhsxp);
+ else
+  {
+   /* notice wire delays including specify paths off during wire init */
+   if (lhsxp->x_stren)
+    {
+     push_xstk_(xsp2, 4*lhslen);
+     sbp = (byte *) xsp2->ap;
+     __st_standval(sbp, xsp, cap->ca_stval);
+     if (lhsxp->optyp == LCB) __stren_exec_ca_concat(lhsxp, sbp, FALSE);
+     /* SJM 03/30/99 - was storing value without strength added */
+     else __exec_conta_assign(lhsxp, xsp2->ap, xsp2->bp, FALSE);
+     __pop_xstk();
+    }
+   else
+    {
+     if (lhsxp->optyp == LCB)
+      __exec_ca_concat(lhsxp, xsp->ap, xsp->bp, FALSE);
+     else __exec_conta_assign(lhsxp, xsp->ap, xsp->bp, FALSE);
+    }
+  }
+ __pop_xstk();
+}
+
+/*
+ * MEDIUM LEVEL SCHEDULING MECHANISM ROUTINES
+ */
+
+/*
+ * insert event in timing wheel or overflow q (know event after now)
+ */
+extern void __insert_event(register i_tev_ndx tevpi)
+{
+ register int32 schtwi;
+ register struct tev_t *tevp;
+ register struct telhdr_t *telp;
+ word64 schtim, t;
+
+ tevp = &(__tevtab[tevpi]);
+ schtim = tevp->etime;
+ /* because of wrap around event up to __twhsize - 1 fit in timing wheel */
+ /* notice borrow possible here - but index always fit in 1 word32 */
+ t = schtim - __simtime;
+ /* schtwi here is number of timing wheel slots to scheduled event */
+ schtwi = (int32) (t & WORDMASK_ULL);
+
+ /* if event would go in timing wheel if it were at 0, then goes in */
+ /* but may need to wrap around */
+ if (schtwi < __twhsize && t < 0x7fffffffULL)
+  {
+   /* wrap around table if needed */
+   if ((schtwi += __cur_twi) >= __twhsize) schtwi %= __twhsize;
+   /* ??? DBG add ---
+   if (__debug_flg && __ev_tracing)
+    {
+     word64 t2;
+     char s1[RECLEN], s2[RECLEN];
+
+     t = (word64) (__twhsize - 1);
+     t2 = __whetime - t;
+     __tr_msg(
+      ".. adding %s event to timing wheel based at %s for time %s (schtwi=%d, cur_twi=%d)\n",
+      __to_tetyp(__xs, tevp->tetyp), __to_timstr(s1, &t2),
+      __to_timstr(s2, &schtim), schtwi, __cur_twi);
+    }
+   --- */
+
+   telp = __twheel[schtwi];
+    /* know tevp next field is nil */
+   if (telp->te_hdri == -1) telp->te_hdri = telp->te_endi = tevpi;
+   else
+    {
+     if (tevp->vpi_onfront)
+      { tevp->tenxti = telp->te_hdri; telp->te_hdri = tevpi; }
+     else
+      { __tevtab[telp->te_endi].tenxti = tevpi; telp->te_endi = tevpi; }
+    }
+   telp->num_events += 1;
+   __num_twhevents++;
+  }
+ else add_ovfetim(schtim, tevpi, tevp);
+}
+
+/*
+ * routine to allocate event - non macro for debugging
+ * the b zero initializes all flags to off
+ */
+/* DBG ??? remove --- */
+extern i_tev_ndx __alloc_tev(int32 etyp, struct itree_t *itp, word64 absetime)
+{
+  register struct tev_t *tevp__;
+  register i_tev_ndx tevpi;
+
+  if (__tefreelsti != -1)
+   { tevpi = __tefreelsti; __tefreelsti = __tevtab[__tefreelsti].tenxti; }
+  else
+   {
+    if (++__numused_tevtab >= __size_tevtab) __grow_tevtab();
+    tevpi = __numused_tevtab;
+   }
+  tevp__ = &(__tevtab[tevpi]);
+  /* LOOKATME - maybe zeroing to init bit fields unportable */
+  memset(tevp__, 0, sizeof(struct tev_t));
+  tevp__->tetyp = etyp;
+  tevp__->teitp = itp;
+  tevp__->etime = absetime;
+  tevp__->tenxti = -1;
+  return(tevpi);
+}
+/*  --- */
+
+/*
+ * grow the tev table by reallocating
+ *
+ * BEWARE - because of growth by reallocating tevp ptrs can only
+ * be used as tmps between calls to alloc tev macro
+ *
+ * notice this increases table size when no free and next to used at
+ * end of table, after grow caller increases num used value
+ */
+extern void __grow_tevtab(void)
+{
+ int32 osize, nsize;
+
+ osize = __size_tevtab*sizeof(struct tev_t);
+ __size_tevtab += (__size_tevtab/2);
+ nsize = __size_tevtab*sizeof(struct tev_t);
+ __tevtab = (struct tev_t *) __my_realloc((char *) __tevtab, osize, nsize);
+
+ /* DBG remove --- UNDO */
+ if (__debug_flg)
+  __dbg_msg("+++ fixed event table grew from %d bytes to %d\n", osize, nsize);
+ /* --- */
+}
+
+/*
+ * normally unused droutine for debugging
+ */
+static void chk_tev_list(register i_tev_ndx tevpi)
+{
+ struct tev_t *tevp;
+
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+  {
+   tevp = &(__tevtab[tevpi]);
+   if (tevp->tetyp < 1 || tevp->tetyp > 14) __misc_terr(__FILE__, __LINE__);
+  }
+}
+
+/*
+ * normally unused routine for checking pending scheduled dce events
+ * UNUSED
+ */
+/* ---
+static void chk_schd_dces(void)
+{
+ register int32 ni;
+ register struct mod_t *mdp;
+ register struct task_t *tskp;
+ struct net_t *np;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++)
+    {
+     if (np->dcelst == NULL) continue;
+     chk_1nschd_dce(np, mdp);
+    }
+   for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+    {
+     for (ni = 0, np = &(tskp->tsk_regs[0]); ni < tskp->trnum; ni++, np++)
+      {
+       if (np->dcelst == NULL) continue;
+       chk_1nschd_dce(np, mdp);
+      }
+    }
+  }
+}
+-- */
+
+/*
+ * check one static scheduled dce
+ * UNUSED
+ */
+/* ---
+static void chk_1nschd_dce(struct net_t *np, struct mod_t *mdp)
+{
+ register struct dcevnt_t *dcep;
+ register int32 ii;
+ i_tev_ndx tevpi;
+ struct delctrl_t *dctp;
+
+ for (dcep = np->dcelst; dcep != NULL; dcep = dcep->dcenxt)
+  {
+   if (dcep->dce_typ != DCE_RNG_INST && dcep->dce_typ != DCE_INST)
+     continue;
+   dctp = dcep->st_dctrl;
+   if (dctp->dceschd_tevs == NULL)
+    __cvsim_msg("*** net %s dcep no dceschd_tevs\n", np->nsym->synam);
+   for (ii = 0; ii < mdp->flatinum; ii++)
+    {
+     if ((tevpi = dctp->dceschd_tevs[__inum]) != -1)
+      __cvsim_msg("*** net %s inst num. %s dceschd_tevs index %d set\n",
+       np->nsym->synam, ii, tevpi);
+     if (__tevtab[tevpi].tetyp < 1 || __tevtab[tevpi].tetyp > 14)
+      __misc_terr(__FILE__, __LINE__);
+    }
+  }
+}
+--- */
+
+/*
+ * ROUTINES TO IMPLEMENT TIME FLOW
+ */
+
+static int32 move_to_time0(void)
+{
+ register struct telhdr_t *twp;
+
+ __simtime++;
+ twp = __twheel[++__cur_twi];
+ __cur_te_hdri = twp->te_hdri;
+ __cur_te_endi = twp->te_endi;
+ return(TRUE);
+}
+
+/*
+ * move to next time slot
+ * return FALSE if no events pending (i.e. all done)
+ * know both normal and pound 0 event lists empty from last time
+ *
+ * when done, events to process at current time ready to be processed
+ * and __cur_te_hdr and __cur_te_end point to the now event queue
+ */
+static int32 move_time(void)
+{
+ register struct telhdr_t *twp;
+ word64 tmp;
+
+ /* -- DBG remove
+ if (__btqroot != NULL) dmp_btree(__btqroot);
+ dmp_twheel();
+ --- */
+
+ __simtime++;
+ /* normal case, find event in timing wheel */
+ /* DBG remove ---
+ if (__num_twhevents < 0) __misc_terr(__FILE__, __LINE__);
+ --- */
+ if (__num_twhevents == 0) goto move_gap;
+again:
+ /* --- DBG remove chk_event_consist(); */
+
+ twp = __twheel[++__cur_twi];
+ /* hit sentinel */
+ if (twp->num_events == -1) goto at_twend;
+ if (twp->te_hdri == -1) { __simtime++; goto again; }
+ __cur_te_hdri = twp->te_hdri;
+ __cur_te_endi = twp->te_endi;
+ goto got_event;
+
+ /* move all events whose time is < new sim time + twh size to time wheel */
+ /* copy header of timing q to timing wheel */
+ /* if no events in overflow q nothing to do here */
+ /* this reduces number of overflow events and increases __twheel events */
+at_twend:
+ tmp = (word64) (__twhsize - 1);
+ __whetime = __simtime + tmp;
+ __cur_twi = -1;
+ /* events still in timing wheel, if ovflow empty, must advance wheel */
+ if (__btqroot != NULL) ovflow_into_wheel();
+ /* DBG remove -- */
+ if (__debug_flg && __ev_tracing)
+  {
+   word64 t;
+
+   tmp = (word64) __twhsize;
+   t = __whetime - tmp + 1;
+   /* whe time is end of timing wheel time */
+   __tr_msg(".. timing wheel base moved to %s\n", __to_timstr(__xs, &t));
+  }
+ /* --- */
+ /* know timing wheel not empty or will not get to at twend */
+ goto again;
+
+ /* handle gap in timing wheel - know wheel currently empty */
+move_gap:
+ if (__btqroot == NULL) return(FALSE);
+ __simtime = __btqroot->btltim;
+ tmp = (word64) (__twhsize - 1);
+ __whetime = __simtime + tmp;
+ /* DBG remove */
+ if (__whetime <= __simtime)
+  {
+   __pv_terr(338,
+    "scheduled event causes 64 bit time overflow - contact vendor");
+  }
+ /* -- */
+ ovflow_into_wheel();
+ /* DBG remove -- */
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg(".. event gap - jumping to %s\n", __to_timstr(__xs, &__simtime));
+  }
+ /* -- */
+ /* know at least one event in timing wheel */
+ __cur_twi = -1;
+ goto again;
+got_event:
+ /* getting to here means have event - better always happen */
+ /* --- DBG remove --
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg(
+    ".. dumping current pending event list for time %s (%ld events):\n",
+    __to_timstr(__xs, &__simtime), twp->num_events);
+   dmp_events(twp->te_hdri);
+   __dmp_event_tab();
+  }
+ -- */
+ return(TRUE);
+}
+
+/*
+ * check a timing wheel to make sure number of events consistent
+ */
+static void chk_event_consist(void)
+{
+ register int32 twi;
+ int32 num_whevents;
+
+ for (num_whevents = 0, twi = 0;; twi++)
+  {
+   /* use sentinel for end */
+   if (__twheel[twi]->num_events == -1) break;
+   num_whevents += __twheel[twi]->num_events;
+  }
+
+ /* DBG remove --- */
+ if (__num_twhevents != num_whevents) __misc_terr(__FILE__, __LINE__);
+ if (__btqroot == NULL)
+  { if (__num_ovflqevents != 0) __misc_terr(__FILE__, __LINE__); }
+ else { if (__num_ovflqevents == 0) __misc_terr(__FILE__, __LINE__); }
+ /* --- */
+}
+
+/*
+ * adding event tevp to overflow tree at time etim
+ * will never see #0 form here and always add exactly 1 event
+ */
+static void add_ovfetim(word64 etim, i_tev_ndx tevpi, struct tev_t *tevp)
+{
+ struct bt_t *btp, *splthdr, *new_splthdr;
+ struct telhdr_t *telpp;
+
+ __num_ovflqevents++;
+ /* ---
+ if (__debug_flg && __ev_tracing)
+  {
+   word64 tmp, t;
+   char s1[RECLEN];
+
+   tmp = (word64) __twhsize;
+   t = __whetime - tmp + 1;
+   __tr_msg(
+    ".. adding event after timing wheel based at %s for time %s (ovfl. num. %d)\n",
+    __to_timstr(s1, &t), __to_timstr(__xs, &(tevp->etime)), __num_ovflqevents);
+  }
+ --- */
+ /* empty tree */
+ if (__btqroot == NULL)
+  {
+   __btqroot = alloc_btnod(BTNORM);
+   __btqroot->btnfill = 1;
+   btp = alloc_btnod(BTFRNGE);
+   __max_level = 1;
+   __btqroot->ofsu.btofs = btp;
+   __btqroot->btltim = etim;
+
+   btp->ofsu.telp = telpp = (struct telhdr_t *)
+    __my_malloc(sizeof(struct telhdr_t));
+   telpp->te_hdri = telpp->te_endi = tevpi;
+   telpp->num_events = 1;
+   btp->btltim = etim;
+   btp->btnxt = NULL;
+   btp->btnfill = 1;
+   return;
+  }
+
+ /* search down tree to find fringe node that new time gets found or */
+ /* insert in */
+ splthdr = find_fringe(etim);
+
+ /* insert somewhere in fringe - know goes within range or on ends */
+ /* if found and did not need to insert, done */
+ if ((new_splthdr = insert_fringe(splthdr, etim, tevpi)) == NULL)
+  return;
+
+ /* if inserted at front must update 1 up from fringe path */
+ if (splthdr != new_splthdr)
+  {
+   btp = __btndhdrstk[__topi];
+   btp->ofsu.btofs = new_splthdr;
+  }
+
+ /* if not did not grow to be too wide, done */
+ if (new_splthdr->btnfill < BTREEMAXWID) return;
+ /* this uses path set in find_fringe to split and grow tree upwards */
+ splitinsert_nonfringe();
+}
+
+/*
+ * allocate a btree node of type bntyp
+ */
+static struct bt_t *alloc_btnod(int32 btyp)
+{
+ struct bt_t *btp;
+
+ btp = (struct bt_t *) __my_malloc(sizeof(struct bt_t));
+ btp->bttyp = btyp;
+ btp->btnfill = 0;
+ btp->btltim = 0ULL;
+ btp->ofsu.btofs = NULL;
+ btp->btnxt = NULL;
+ return(btp);
+}
+
+/*
+ * find fringe multiple element node that etim goes in or divides or will be
+ * found in
+ * return header node of fringe node as list and set __topi to 1 less than
+ * fringe - stack does not contain fringe node
+ *
+ * notice just stops when hits fringe - does not stack fringe node because
+ * maybe be on front of list that is multikey nod or after end
+ */
+static struct bt_t *find_fringe(word64 etim)
+{
+ register struct bt_t *btp;
+ struct bt_t *hdrbtp, *last_btp;
+
+ /* stack special size 1 root node */
+ __btndhdrstk[0] = __btndstk[0] = __btqroot;
+ hdrbtp = __btqroot->ofsu.btofs;
+ /* must handle case of fringe immediately under root */
+ __topi = 0;
+ if (hdrbtp->bttyp == BTFRNGE) return(hdrbtp);
+
+ for (__topi = 0;;)
+  {
+   /* stack 1 down header of linked node */
+   __btndhdrstk[++__topi] = last_btp = hdrbtp;
+   for (btp = hdrbtp->btnxt; btp != NULL; btp = btp->btnxt)
+    {
+     /* true here means path selects last btp node */
+     if (etim < btp->btltim) break;
+     last_btp = btp;
+    }
+   __btndstk[__topi] = last_btp;
+   hdrbtp = last_btp->ofsu.btofs;
+   /* notice top of stack is one above fringe node */
+   if (hdrbtp->bttyp == BTFRNGE) break;
+  }
+ return(hdrbtp);
+}
+
+/*
+ * insert a fringe node into a fringe node list
+ * this is simple linear linked list insert
+ *
+ * if needs to allocate new node puts event into new telhdr node
+ * else adds to end of right list
+ * return new fringe header node ptrif added else NULL if found
+ * even if found still adds time event to found time event header
+ *
+ * notice fringe node (with pointer to telhdr) never stacked on path list
+ */
+static struct bt_t *insert_fringe(struct bt_t *frnghdr, word64 etim,
+ i_tev_ndx tevpi)
+{
+ register int32 i;
+ register struct bt_t *btp;
+ int32 goes_onend;
+ struct bt_t *last_btp, *btpnew;
+ struct telhdr_t *telp;
+
+ goes_onend = FALSE;
+ for (last_btp = NULL, btp = frnghdr; btp != NULL; btp = btp->btnxt)
+  {
+   if (etim > btp->btltim) { last_btp = btp; continue; }
+
+   /* found place */
+   if (etim == btp->btltim)
+    {
+     telp = btp->ofsu.telp;
+     if (telp->te_hdri == -1) telp->te_hdri = telp->te_endi = tevpi;
+     else
+      {
+       if (__tevtab[tevpi].vpi_onfront)
+        { __tevtab[tevpi].tenxti = telp->te_hdri; telp->te_hdri = tevpi; }
+       else { __tevtab[telp->te_endi].tenxti = tevpi; telp->te_endi = tevpi; }
+      }
+     telp->num_events += 1;
+     return(NULL);
+    }
+
+do_add:
+   /* allocate new fringe node */
+   telp = (struct telhdr_t *) __my_malloc(sizeof(struct telhdr_t));
+   telp->te_hdri = telp->te_endi = tevpi;
+   telp->num_events = 1;
+
+   btpnew = alloc_btnod(BTFRNGE);
+   btpnew->btltim = etim;
+   btpnew->ofsu.telp = telp;
+
+   /* goes past end - insert after last_btp */
+   if (goes_onend)
+    { last_btp->btnxt = btpnew; btpnew->btnxt = NULL; }
+   else
+    {
+     /* insert before btp */
+     if (last_btp == NULL)
+      {
+       btpnew->btnxt = btp;
+       btpnew->btnfill = frnghdr->btnfill;
+       frnghdr->btnfill = 0;
+       frnghdr = btpnew;
+
+       /* this is tricky case since btpnew time less than all header nodes */
+       /* in tree - fix using header node path */
+       for (i = __topi; i >= 0; i--) __btndhdrstk[i]->btltim = etim;
+      }
+     else { btpnew->btnxt = btp; last_btp->btnxt = btpnew; }
+    }
+   frnghdr->btnfill = frnghdr->btnfill + 1;
+   return(frnghdr);
+  }
+ goes_onend = TRUE;
+ goto do_add;
+}
+
+/*
+ * insert fringe node that gets split into non fringe upward parent node
+ * keep propagating wide nodes up to root
+ * know must split fringe node or will not get here
+ *
+ * know __topi stack of path that got to this fringe node
+ * but top is one up from fringe node
+ */
+static void splitinsert_nonfringe(void)
+{
+ register int32 i;
+ register struct bt_t *btp;
+ int32 stki;
+ struct bt_t *parbtp, *parhdr, *splt1, *splt2, *last_btp, *splt2par;
+
+ /* notice fringe node not stacked, top of stack is parent of fringe */
+ splt1 = __btndstk[__topi]->ofsu.btofs;
+ last_btp = NULL;
+ for (stki = __topi;;)
+  {
+   /* split too wide node into 2 - max must be divisible by 2 */
+   /* know at least 1 node here */
+   for (btp = splt1, i = 0; i < BTREEMAXWID/2; i++)
+    { last_btp = btp; btp = btp->btnxt; }
+   last_btp->btnxt = NULL;
+   splt2 = btp;
+   splt1->btnfill = BTREEMAXWID/2;
+   splt2->btnfill = BTREEMAXWID/2;
+
+   /* construct non fringe node to link splt2 node list onto */
+   splt2par = alloc_btnod(BTNORM);
+   splt2par->btltim = splt2->btltim;
+   splt2par->ofsu.btofs = splt2;
+
+   /* parent nodes of path used to descend to fringe */
+   parbtp = __btndstk[stki];
+   parhdr = __btndhdrstk[stki];
+   /* up 1 level is special root node - must increase tree height */
+   if (stki == 0)
+    {
+     /* allocate new added level parbtp (same as header for root) */
+     parbtp = alloc_btnod(BTNORM);
+     parbtp->btltim = splt1->btltim;
+     parbtp->ofsu.btofs = splt1;
+     parbtp->btnfill = 2;
+     parbtp->btnxt = splt2par;
+     parhdr->ofsu.btofs = parbtp;
+     splt2par->btnxt = NULL;
+     /* this is only way max. tree level can increase */
+     __max_level++;
+     return;
+    }
+   /* on sun += does not work for bit fields */
+   parhdr->btnfill = parhdr->btnfill + 1;
+
+   splt2par->btnxt = parbtp->btnxt;
+   parbtp->btnxt = splt2par;
+   if (parhdr->btnfill < BTREEMAXWID) break;
+   stki--;
+   splt1 = __btndstk[stki]->ofsu.btofs;
+  }
+}
+
+/*
+ * LOW LEVEL OVERFLOW QUEUE TO TIMING WHEEL ROUTINES
+ */
+
+/*
+ * depth first move of nodes to timing wheel
+ */
+static void ovflow_into_wheel(void)
+{
+ int32 stki;
+ struct bt_t *btphdr;
+
+ /* if leftmost time in overflow tree past wheel end time, nothing to do */
+ if (__btqroot->btltim > __whetime) return;
+
+ __btndhdrstk[0] = __btndstk[0] = __btqroot;
+ btphdr = __btqroot->ofsu.btofs;
+ for (__topi = 0;;)
+  {
+   __btndhdrstk[++__topi] = btphdr;
+   /* DBG remove ---
+   if (__debug_flg && __ev_tracing)
+    {
+     word64 t, tmp;
+
+     tmp = (word64) __twhsize;
+     t = (__whetime - tmp) + 1;
+     __tr_msg(
+      ".. time queue move to wheel based at %s descending to level %d\n",
+      __to_timstr(__xs, &t), __topi);
+    }
+   -- */
+   /* case 1 - descended down to fringe node */
+   if (btphdr->bttyp == BTFRNGE)
+    {
+     divide_fringe_node(btphdr);
+     break;
+    }
+   divide_internal_node(btphdr);
+   /* move down one level from new divide node */
+   btphdr = __btndstk[__topi]->ofsu.btofs;
+  }
+ /* must set min times of list hdr nodes */
+ /* since do not know new and left times until hit fringe */
+ if (__btqroot == NULL) return;
+
+ if (__btqroot != NULL)
+  {
+   for (stki = __topi; stki > 0; stki--)
+    __btndstk[stki - 1]->btltim = __btndstk[stki]->btltim;
+  }
+ /* finally remove any size one nodes at top */
+ for (;;)
+  {
+   btphdr = __btqroot->ofsu.btofs;
+   if (btphdr->bttyp == BTFRNGE || btphdr->btnfill != 1) return;
+   if (__debug_flg && __ev_tracing)
+    {
+     __tr_msg(".. removing redundant size 1 node under root\n");
+    }
+   __btqroot->ofsu.btofs = btphdr->ofsu.btofs;
+   __my_free((char *) btphdr, sizeof(struct bt_t));
+   btphdr = NULL;
+  }
+}
+
+/*
+ * divide a fringe node
+ */
+static void divide_fringe_node(struct bt_t *btphdr)
+{
+ register struct bt_t *btp, *btp2;
+ int32 cnum;
+ struct bt_t *btptmp;
+
+ /* fringe node low time cannot be larger than wheel end */
+ if (btphdr->btltim > __whetime) __misc_terr(__FILE__, __LINE__);
+
+ /* case 1 (illegal): all of fringe node remains in tree */
+ cnum = btphdr->btnfill - 1;
+ for (btp = btphdr->btnxt; btp != NULL; btp = btp->btnxt)
+  {
+   if (btp->btltim > __whetime)
+    {
+     /* case 2: from 2nd to nth is first node of new tree after removal */
+     /* remove all nodes up to btp */
+     for (btp2 = btphdr; btp2 != btp;)
+      {
+       btptmp = btp2->btnxt;
+       mv_to_wheel(btp2->btltim, btp2->ofsu.telp);
+       /* SJM 03/07/01 - always fringe, must free telp too */
+       __my_free((char *) btp2->ofsu.telp, sizeof(struct telhdr_t));
+       __my_free((char *) btp2, sizeof(struct bt_t));
+       btp2 = btptmp;
+      }
+     /* fixup tree */
+     __btndstk[__topi] = __btndhdrstk[__topi] = btp;
+     btp->btnfill = cnum;
+     __btndhdrstk[__topi - 1]->ofsu.btofs = btp;
+     __btndhdrstk[__topi - 1]->btltim = btp->btltim;
+     return;
+    }
+   cnum--;
+  }
+ /* case 3 - all fringe nodes go in timing wheel */
+ /* remove all nodes */
+ for (btp = btphdr; btp != NULL;)
+  {
+   btptmp = btp->btnxt;
+   mv_to_wheel(btp->btltim, btp->ofsu.telp);
+   /* AIV 05/21/04 - miss one here, must free telp too */
+   __my_free((char *) btp->ofsu.telp, sizeof(struct telhdr_t));
+   __my_free((char *) btp, sizeof(struct bt_t));
+   btp = btptmp;
+  }
+ /* remove know 1 up empty and propagate empties up */
+ remove_empty_upwards();
+}
+
+/*
+ * divide internal node
+ */
+static void divide_internal_node(struct bt_t *btphdr)
+{
+ register struct bt_t *btp;
+ int32 cnum;
+ struct bt_t *last_btp, *btp2, *btptmp;
+
+ /* case 1 (impossible) - all of tree past timing wheel */
+ /* internal node low time cannot be larger than wheel end */
+ if (btphdr->btltim > __whetime) __misc_terr(__FILE__, __LINE__);
+
+ cnum = btphdr->btnfill - 1;
+ last_btp = btphdr;
+ for (btp = btphdr->btnxt; btp != NULL; btp = btp->btnxt)
+  {
+   if (btp->btltim > __whetime)
+    {
+got_divide:
+     /* case 2: from 2nd to nth is first node of new tree after removal */
+     /* remove all subtrees up to last_btp (divide node) */
+     for (btp2 = btphdr; btp2 != last_btp;)
+      {
+       btptmp = btp2->btnxt;
+       mv_subtree_towheel(btp2->ofsu.btofs);
+       __my_free((char *) btp2, sizeof(struct bt_t));
+       btp2 = btptmp;
+      }
+     /* fixup tree - last_btp is divide node */
+     last_btp->btnfill = cnum + 1;
+     __btndstk[__topi] = last_btp;
+     __btndhdrstk[__topi] = last_btp;
+     __btndstk[__topi - 1]->ofsu.btofs = last_btp;
+     __btndstk[__topi - 1]->btltim = last_btp->btltim;
+     return;
+    }
+   cnum--;
+   last_btp = btp;
+  }
+ /* case 3 - divide not is last node in tree */
+ goto got_divide;
+}
+
+/*
+ * when leaf empty (size == 0) must remove upward
+ */
+static void remove_empty_upwards(void)
+{
+ register struct bt_t *btp;
+ struct bt_t *last_btp, *rembtp;
+ int32 stki, stki2;
+
+ /* case 1, if only root is above now empty fringe - remove all of tree */
+ if (__topi == 1)
+  {
+empty_tree:
+   __my_free((char *) __btqroot, sizeof(struct bt_t));
+
+   /* SJM 05/26/04 - notice root node is special case no telp multi */
+   /* element not, instead just a pointer to a btp */
+   __btqroot = NULL;
+   return;
+  }
+ /* case 2, need to remove at least fringe */
+ /* first - chain upwards of size 1 nodes that get removed */
+ for (stki = __topi - 1; stki > 0; stki--)
+  {
+   /* this can never be fringe since fringe not in btndstk */
+   if (__btndhdrstk[stki]->btnfill != 1) goto got_nonremove;
+   __my_free((char *) __btndstk[stki], sizeof(struct bt_t));
+   __btndstk[stki] = NULL;
+  }
+ goto empty_tree;
+
+got_nonremove:
+ /* know that node at level stki stays */
+ /* step 1: link out node */
+ /* step 1a: find predecessor of linked out node if exists */
+ rembtp = __btndstk[stki];
+ /* case 2a: header node is removed */
+ if (rembtp == __btndhdrstk[stki])
+  {
+   /* know node following rembtp exists */
+   __btndhdrstk[stki - 1]->ofsu.btofs = rembtp->btnxt;
+   __btndstk[stki] = rembtp->btnxt;
+   __btndstk[stki]->btnfill = __btndhdrstk[stki]->btnfill - 1;
+   __btndhdrstk[stki] = __btndstk[stki];
+  }
+ /* case 2b: non header removed */
+ else
+  {
+   /* find predecessor of removed node since it is now node stack */
+   last_btp = NULL;
+   for (btp = __btndhdrstk[stki]; btp != rembtp; btp = btp->btnxt)
+    last_btp = btp;
+   __btndhdrstk[stki]->btnfill -= 1;
+
+   /* case 2b1: last node removed */
+   if (rembtp->btnxt == NULL)
+    {
+     /* last_btp is one before removed node */
+     __btndstk[stki] = last_btp;
+ 
+     /* SJM 08/02/01 - add if to keep lint happy */
+     if (last_btp != NULL) last_btp->btnxt = NULL;
+    }
+   /* case 2b2: internal node removed */
+   else
+    {
+     __btndstk[stki] = rembtp->btnxt;
+     /* SJM 08/02/01 - add if to keep lint happy */
+     if (last_btp != NULL) last_btp->btnxt = rembtp->btnxt;
+    }
+  }
+ /* notice __btndstk that points to rembtp - has new value (moved down) */
+ __my_free((char *) rembtp, sizeof(struct bt_t));
+ /* finally, work upwards to fringe updating __btndstk */
+ /* notice even if only fringe removed, this will change ndstk for fringe */
+ for (stki2 = stki + 1; stki2 <= __topi; stki2++)
+  __btndstk[stki2] = __btndstk[stki2 - 1]->ofsu.btofs;
+}
+
+/*
+ * move an entire subtree to timing wheel and free subtree
+ * not called for fringe nodes
+ */
+static void mv_subtree_towheel(struct bt_t *btphdr)
+{
+ register struct bt_t *btp;
+ struct bt_t *btp2;
+
+ for (btp = btphdr; btp != NULL;)
+  {
+   btp2 = btp->btnxt;
+
+   if (btp->bttyp == BTFRNGE)
+    {
+     mv_to_wheel(btp->btltim, btp->ofsu.telp);
+     /* SJM 03/07/01 - only fringe node has telp than needs to be freed */
+     __my_free((char *) btp->ofsu.telp, sizeof(struct telhdr_t));
+    }
+   else mv_subtree_towheel(btp->ofsu.btofs);
+
+   /* always free the node */
+   __my_free((char *) btp, sizeof(struct bt_t));
+   btp = btp2;
+  }
+}
+
+/*
+ * move an event header te lst to timing wheel
+ */
+static void mv_to_wheel(word64 etim, struct telhdr_t *telp)
+{
+ int32 twslot;
+ word64 tmp;
+ struct telhdr_t *twlp;
+
+ /* removing fringe node that should stay at time */
+ if (etim > __whetime) __misc_terr(__FILE__, __LINE__);
+ /* ---
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg(".. moving time queue to wheel based at time %s\n",
+    __to_timstr(__xs, &etim));
+  }
+ --- */
+
+ /* add overflow q to correct wheel slot - must go on front */
+ /* because of wrapping later events already on wheel element */
+ /* sim time + 1 is 0th timing wheel position */
+ tmp = etim - __simtime;
+ twslot = (int32) (tmp & WORDMASK_ULL);
+
+ /* notice, there will always be at least one entry on overflow q */
+ /* list or will not get here - cancelled events just marked */
+ /* add to end if timing wheel slot already has events */
+ /* DBG remove  --- */
+ if (twslot < 0 || twslot > __twhsize) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ twlp = __twheel[twslot];
+ /* DBG remove  --- */
+ if (twlp == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* twlp points to current wheel events - telp to list to move on end */
+ if (twlp->te_hdri == -1)
+  {
+   twlp->te_hdri = telp->te_hdri;
+   twlp->te_endi = telp->te_endi;
+   twlp->num_events = telp->num_events;
+  }
+ else
+  {
+   /* splice onto end and set new end - leave front as is */
+   __tevtab[twlp->te_endi].tenxti = telp->te_hdri;
+   twlp->te_endi = telp->te_endi;
+   twlp->num_events += telp->num_events;
+  }
+ __num_twhevents += telp->num_events;
+ __num_ovflqevents -= telp->num_events;
+ if (__num_ovflqevents < 0) __misc_terr(__FILE__, __LINE__);
+}
+
+/*
+ * find btree node after or same as tim
+ *
+ * LOOKATME - why is this not called
+ */
+static struct telhdr_t *tfind_btnode_after(struct bt_t *btphdr, word64 tim)
+{
+ register struct bt_t *btp;
+ struct telhdr_t *telp;
+
+ if (btphdr->bttyp == BTFRNGE)
+  {
+   for (btp = btphdr; btp != NULL; btp = btp->btnxt)
+    { if (btp->btltim >= tim) return(btp->ofsu.telp); }
+   return(NULL);
+  }
+ for (btp = btphdr; btp != NULL; btp = btp->btnxt)
+  {
+   if ((telp = tfind_btnode_after(btp->ofsu.btofs, tim)) != NULL)
+    return(telp);
+  }
+ return(NULL);
+}
+
+/*
+ * Q DEBUGGING ROUTINES
+ */
+
+/*
+ * dump all events in timing wheel
+ * only called if debug flag on
+ */
+static void dmp_twheel(void)
+{
+ register int32 twi;
+ int32 e_num, totenum;
+
+ __dbg_msg("<< timing wheel that ends at %s\n", __to_timstr(__xs, &__whetime));
+ for (twi = 0, totenum = 0;; twi++)
+  {
+   /* use sentinel for end */
+   if (__twheel[twi]->num_events == -1) break;
+   e_num = dmp_events(__twheel[twi]->te_hdri);
+   totenum += e_num;
+   /* DBG remove ---
+   __dbg_msg("--index %d %d counted events and %d stored--\n", twi,
+    e_num, __twheel[twi]->num_events);
+   ---*/
+  }
+ __dbg_msg("<< total counted wheel events %d, overflow %d, wheel stored %d\n",
+  totenum, __num_ovflqevents, __num_twhevents);
+}
+
+/*
+ * dump event list
+ */
+static int32 dmp_events(register i_tev_ndx tevpi)
+{
+ int32 e_num;
+ /* char s1[20], s2[RECLEN]; */
+
+ for (e_num = 0; tevpi != -1; tevpi = __tevtab[tevpi].tenxti, e_num++)
+  {
+   /* --
+   struct tev_t *tevp;
+
+   tevp = &(__tevtab[tevpi]);
+   __dbg_msg("^^%s event index %d in inst. %s at %s cancel=%d\n",
+    __to_tetyp(s1, tevp->tetyp), tevpi, __msg2_blditree(s2, tevp->teitp),
+    __to_timstr(__xs, &__simtime), tevp->te_cancel);
+   -- */
+  }
+ return(e_num);
+}
+
+/*
+ * dump event table and free list
+ */
+extern void __dmp_event_tab(void)
+{
+ register int32 ei;
+ struct tev_t *tevp;
+ char s1[RECLEN];
+
+ /* dump all allocated events */
+ __dbg_msg("*** DUMPING EVENT TABLE *** (high used %d)\n",
+  __numused_tevtab);
+ for (ei = 0; ei <= __numused_tevtab; ei++)
+  {
+   tevp = &(__tevtab[ei]);
+   __dbg_msg("^^%s (%d) event index %d next %d\n",
+    __to_tetyp(s1, tevp->tetyp), tevp->tetyp, ei, tevp->tenxti);
+  }
+ if (__tefreelsti != -1)
+  {
+   __dbg_msg("*** DUMPING FREE LIST ***\n");
+   for (ei = __tefreelsti; ei != -1; ei = __tevtab[ei].tenxti)
+    {
+     tevp = &(__tevtab[ei]);
+     __dbg_msg("^^%s (%d) free event index %d next %d\n",
+      __to_tetyp(s1, tevp->tetyp), tevp->tetyp, ei, tevp->tenxti);
+    }
+  }
+}
+
+/*
+ * dump a levelized tree
+ */
+static void dmp_btree(struct bt_t *btphdr)
+{
+ register int32 i;
+
+ if (__btqroot == NULL)
+  {
+   if (__debug_flg && __ev_tracing)
+    __dbg_msg("--empty tree--\n");
+   return;
+  }
+ for (i = 0; i <= __max_level; i++)
+  {
+   __nd_level = i;
+   dmp2_btree(btphdr, 0);
+  }
+}
+
+/*
+ * dump a btree to standard output depth first using large linked b nodes
+ */
+static void dmp2_btree(struct bt_t *btphdr, int32 level)
+{
+ register struct bt_t *btp;
+
+ if (level > __nd_level) return;
+ dmp_btnode(btphdr, level);
+ if (btphdr->bttyp == BTFRNGE) return;
+ for (btp = btphdr; btp != NULL; btp = btp->btnxt)
+  dmp2_btree(btp->ofsu.btofs, level + 1);
+}
+
+/*
+ * dump a btree node
+ * for now assume fits on one line
+ */
+static void dmp_btnode(struct bt_t *btp, int32 level)
+{
+ struct bt_t *btp1;
+ int32 first_time;
+ char s1[RECLEN];
+
+ if (__nd_level != level) return;
+ if (btp->bttyp == BTFRNGE) strcpy(s1, "fringe");
+ else strcpy(s1, "internal");
+
+ __outlinpos = 0;
+ __dbg_msg("level %d %s node size %u:", level, s1, btp->btnfill);
+ first_time = TRUE;
+ for (btp1 = btp; btp1 != NULL; btp1 = btp1->btnxt)
+  {
+   if (btp1->bttyp == BTFRNGE)
+    {
+     if (first_time) first_time = FALSE; else __dbg_msg(", ");
+     __dbg_msg("time %s(events %d)", __to_timstr(s1, &(btp1->btltim)),
+      btp1->ofsu.telp->num_events);
+    }
+   else
+    {
+     if (first_time) first_time = FALSE; else __dbg_msg(", ");
+     __dbg_msg("time %s", __to_timstr(s1, &(btp1->btltim)));
+    }
+  }
+ __dbg_msg("\n");
+ __outlinpos = 0;
+}
+
+/*
+ * free subtree of overflow event queue btree
+ * know always passed leftmost of multiple node node
+ * and btphdr never nil, caller must check for empty tree
+ */
+extern void __free_btree(struct bt_t *btphdr)
+{
+ register struct bt_t *btp, *btp2;
+
+ /* at bottom of tree this nodes and all right siblings fringe nodes */
+ if (btphdr->bttyp == BTFRNGE)
+  {
+    for (btp = btphdr; btp != NULL;)
+     {
+      btp2 = btp->btnxt;
+      /* because freeing telp record, know contents freed */
+      /* events freed by just marking all of tev tab unused */
+      __free_telhdr_tevs(btp->ofsu.telp);
+      __my_free((char *) btp->ofsu.telp, sizeof(struct telhdr_t));
+      __my_free((char *) btp, sizeof(struct bt_t));
+     btp = btp2;
+    }
+   return;
+  }
+ /* if one node non fringe, all non fringe */
+ for (btp = btphdr; btp != NULL;)
+  {
+   btp2 = btp->btnxt;
+   __free_btree(btp->ofsu.btofs);
+   __my_free((char *) btp, sizeof(struct bt_t));
+   btp = btp2;
+  }
+}
+
+
+/*
+ * free list of tevs - either btree node or timing wheel list
+ *
+ * normally add entire period's events to free list - this is for reset only
+ * because when an event is processed guts (if any) freed so can link on
+ * free list but here need to free guts too
+ */
+extern void __free_telhdr_tevs(register struct telhdr_t *telp)
+{
+ register i_tev_ndx tevpi, tevp2i;
+
+ for (tevpi = telp->te_hdri; tevpi != -1;)
+  {
+   tevp2i = __tevtab[tevpi].tenxti;
+   __free_1tev(tevpi);
+   tevpi = tevp2i;
+  }
+ /* this is needed for timing wheel since, telp not freed */
+ telp->te_hdri = telp->te_endi = -1;
+ telp->num_events = 0;
+}
+
+/*
+ * free 1 event - may need to free auxiliary since will never be processed
+ * freeing just puts on front of ev free list
+ */
+extern void __free_1tev(i_tev_ndx tevpi)
+{
+ int32 wlen;
+ word32 *wp;
+ struct tev_t *tevp;
+ struct tenbpa_t *tenbp;
+ struct tedputp_t *tedp;
+ struct teputv_t *tepvp;
+
+ tevp = &(__tevtab[tevpi]);
+ switch ((byte) tevp->tetyp) {
+  case TE_WIRE: case TE_BIDPATH: case TE_MIPD_NCHG:
+   if (tevp->tu.tenp != NULL)
+    __my_free((char *) tevp->tu.tenp, sizeof(struct tenp_t));
+   break;
+  case TE_NBPA:
+   /* for non #0 original freed here but no tenbpa - moved to new */
+   if ((tenbp = tevp->tu.tenbpa) == NULL) break;
+
+   wp = tenbp->nbawp;
+   wlen = wlen_(tenbp->nbastp->st.spra.lhsx->szu.xclen);
+   __my_free((char *) wp, 2*wlen*WRDBYTES);
+   /* if needed to copy lhs expr., now free */
+   if (tenbp->nblhsxp != NULL) __free_xtree(tenbp->nblhsxp);
+   __my_free((char *) tevp->tu.tenbpa, sizeof(struct tenbpa_t));
+   break;
+  case TE_TFPUTPDEL:
+   if ((tedp = tevp->tu.tedputp) == NULL) break;
+   tevp->tu.tedputp = NULL;
+   tedp->tedtfrp =  (struct tfrec_t *) __tedpfreelst;
+   __tedpfreelst = tedp;
+   break;
+  case TE_VPIPUTVDEL: case TE_VPIDRVDEL:
+   if ((tepvp = tevp->tu.teputvp) == NULL) break;
+   tevp->tu.teputvp = NULL;
+   tepvp->np =  (struct net_t *) __teputvfreelst;
+   __teputvfreelst = tepvp;
+   break;
+  /* for these either no auxiliary rec., or must stay, or free with handle */
+  case TE_THRD: case TE_G: case TE_CA: case TE_TFSETDEL: case TE_SYNC:
+  case TE_VPICBDEL:
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+
+ /* ** DBG remove --
+ memset(tevp, 0, sizeof(struct tev_t));
+ __dbg_msg("--- free tev at %x\n", tevp);
+ --- */
+ __tevtab[tevpi].tenxti = __tefreelsti;
+ __tefreelsti = tevpi;
+}
+
diff --git a/src/v_src.c b/src/v_src.c
new file mode 100644
index 0000000..c4cee4b
--- /dev/null
+++ b/src/v_src.c
@@ -0,0 +1,6175 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * source reading of module items except for specify and udps
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static void decl_instconns(struct mod_t *);
+static void dcl_iconn_wires(struct cell_t *, struct expr_t *);
+static void freeze_mod_syms(struct symtab_t *, struct symtab_t *);
+static void travfreeze_syms(register struct tnode_t *);
+static void travfreeze_lowsymtab(register struct symtab_t *);
+static void bld_mdpin_table(struct mod_t *);
+static int32 rd_modhdr(struct mod_t *);
+static int32 rd_hdrpnd_parmdecls(void);
+static int32 rd_portref(void);
+static void set_ioprtnets(struct expr_t *);
+static int32 rd_list_of_ports_decl(struct mod_t *);
+static int32 rd_modbody(void);
+static int32 rd_iodecl(word32);
+static void add_net_attr(struct net_t *, int32);
+static int32 rd_vardecl(word32);
+static void chk_capwdecl_strens(word32);
+static void chk_drvstren(word32);
+static int32 rd_oparamdels(struct paramlst_t **);
+static int32 do_wdecl_assgn(struct sy_t *, struct paramlst_t *, int32);
+static int32 rdbld_mod_varinitlst(struct sy_t *);
+static int32 is_decl_err(struct sy_t *, word32, word32);
+static void set_reg_widths(word32, struct expr_t **, struct expr_t **);
+static int32 chkset_wdrng(struct net_t *, struct expr_t *, struct expr_t *);
+static int32 cmp_rng(struct expr_t *, struct expr_t *, struct expr_t *,
+ struct expr_t *);
+static int32 rd_verstrens(void);
+static int32 rd_1verstren(int32 *);
+static int32 is_tokstren(int32);
+static int32 rd_opt_param_array_rng(struct expr_t **, struct expr_t **,
+ int32);
+static struct net_t *chkadd_array_param(char *, int32, int32, int32,
+ struct expr_t *, struct expr_t *, struct expr_t *, struct expr_t *);
+static void cnvt_to_pdecl(struct xstk_t *, struct expr_t *, struct net_t *,
+ char *);
+static void unwind_param_array_constructor(struct expr_t *);
+static void chk1_arrinit_expr(struct expr_t *, char *, int32);
+static int32 rd_contassign(void);
+static struct conta_t *add_conta(struct expr_t *, struct expr_t *, int32,
+ int32);
+static int32 rd_eventdecl(int32);
+static int32 rd_paramdecl(int32);
+static int32 rd_dfparam_stmt(void);
+static struct dfparam_t *alloc_dfpval(void);
+static int32 rd_task(void);
+static word32 to_tasksytyp(int32);
+static int32 rd_taskvardecl(word32, int32, char *);
+static struct net_t *decl_taskvar(word32, struct expr_t *, struct expr_t *);
+static struct task_pin_t *alloc_tskpin(void);
+static int32 rd_func(void);
+static void add_funcretdecl(char *, word32, struct expr_t *,
+ struct expr_t *, int32);
+static int32 rd_inst(char *);
+static void add_cell_attr(struct cell_t *);
+static int32 rd_pull_stren(char *, int32 *);
+static struct namparam_t *rd_npndparams(void);
+static struct namparam_t *rd1_namedparam(void);
+static struct namparam_t *copy_namparamlst(struct namparam_t *);  
+static int32 rd_iports(char *);
+static int32 rd_cpin_conn(void);
+static char *alloc_cpnam(char *);
+static struct cell_pin_t *alloc_memcpins(void);
+static struct cell_t *add_cell(char *);
+static struct cell_t *alloc_memcell(void);
+static void init_task(struct task_t *);
+static int32 rd_tf_list_of_ports_decl(struct task_t *, char *);
+
+/* extern prototypes (maybe defined in this module) */
+extern char *__pv_stralloc(char *);
+extern char *__my_malloc(int32);
+extern struct mod_t *__alloc_mod(struct sy_t *);
+extern void __init_mod(struct mod_t *, struct sy_t *);
+extern int32 __xpr_has_param(struct expr_t *);
+extern struct ncomp_t *__alloc_arrncomp(void);
+extern char *__prt_kywrd_vtok(void);
+extern char *__prt_vtok(void);
+extern void __freeze_1symtab(struct symtab_t *);
+extern struct sy_t *__get_sym_env(char *);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern struct sy_t *__decl_sym(char *, struct symtab_t *);
+extern struct sy_t *__bld_loc_symbol(int32, struct symtab_t *, char *,
+ char *);
+extern struct sy_t *__find_sym(char *);
+extern struct net_t *__add_net(struct sy_t *);
+extern struct net_t *__decl_wirereg(word32, struct expr_t *,
+ struct expr_t *, struct sy_t *);
+extern struct sy_t *__add_modsym(char *);
+extern char *__to_ptnam(char *, word32);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_wtnam2(char *, word32);
+extern char *__to_wrange(char *, struct net_t *);
+extern char *__get_vkeynam(char *, int32);
+extern char *__to_sytyp(char *, word32);
+extern char *__msgtox_wrange(char *, struct expr_t *, struct expr_t *);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char *__pregab_tostr(char *, word32 *, word32 *, struct net_t *);
+extern char *__to_stren_nam(char *, int32, int32);
+extern word32 __fr_stren_nam(int32);
+extern struct symtab_t *__alloc_symtab(int32);
+extern struct mod_pin_t *__alloc_modpin(void);
+extern struct tnode_t *__vtfind(char *, struct symtab_t *);
+extern struct namparam_t *__alloc_namparam(void);
+extern struct paramlst_t *__copy_dellst(struct paramlst_t *);
+extern struct expr_t *__bld_rng_numxpr(word32, word32, int32);
+extern struct st_t *__alloc_stmt(int32);
+extern struct st_t *__alloc2_stmt(int32, int32, int32);
+extern struct delctrl_t *__alloc_dctrl(void);
+extern char *__to_splt_nam(char *, int32);
+extern struct st_t *__rd_stmt(void);
+extern struct paramlst_t *__alloc_pval(void);
+extern struct task_t *__alloc_task(struct sy_t *);
+extern struct expr_t *__gen_wireid_expr(struct sy_t *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern struct xstk_t *__eval2_xpr(struct expr_t *);
+extern struct xstk_t *__src_rd_eval_xpr(struct expr_t *);
+extern word32 __to_cap_size(int32);
+extern struct expr_t *__copy_expr(struct expr_t *);
+extern struct expr_t *__alloc_newxnd(void);
+extern void __get_vtok(void);
+extern int32 __rd_moddef(struct symtab_t *, int32);
+extern struct gref_t *__alloc_grtab(struct gref_t *, int32);
+extern int32 __rd_udpdef(struct symtab_t *);
+extern int32 __vskipto_modend(int32);
+extern int32 __vskipto_lofp_end(void);
+extern int32 __vskipto2_lofp_end(void);
+extern void __add_sym(char *, struct tnode_t *);
+extern int32 __rd_decl_rng(struct expr_t **, struct expr_t **);
+extern int32 __chk_redef_err(char *, struct sy_t *, char *, word32);
+extern void __remove_undef_mod(struct sy_t *);
+extern void __my_free(char *, int32);
+extern int32 __vskipto2_any(int32, int32);
+extern int32 __vskipto3_any(int32, int32, int32);
+extern int32 __vskipto4_any(int32, int32, int32, int32);
+extern void __unget_vtok(void);
+extern int32 __col_parenexpr(int32);
+extern int32 __col_connexpr(int32);
+extern void __bld_xtree(int32);
+extern int32 __rd_spfy(struct mod_t *);
+extern int32 __fr_wtnam(int32);
+extern int32 __vskipto_any(int32);
+extern int32 __col_rangeexpr(void);
+extern int32 __is_capstren(int32);
+extern int32 __col_comsemi(int32);
+extern void __set_numval(struct expr_t *, word32, word32, int32);
+extern int32 __col_lval(void);
+extern int32 __col_newparamrhsexpr(void);
+extern int32 __col_lofp_paramrhsexpr(void);
+extern int32 __bld_tsk(char *, int32);
+extern int32 __rd_tfdecls(char *);
+extern int32 __bld_expnode(void);
+extern void __set_xtab_errval(void);
+extern int32 __col_delexpr(void);
+extern int32 __vskipto3_modend(int32, int32, int32);
+extern void __set_opempty(int32);
+extern void __free_xtree(struct expr_t *);
+extern void __free2_xtree(struct expr_t *);
+extern int32 __src_rd_chk_paramexpr(struct expr_t *, int32);
+extern int32 __rd_opt_param_vec_rng(struct expr_t **, struct expr_t **,
+ int32);
+extern int32 __chk_paramexpr(struct expr_t *, int32);
+extern void __eval_param_rhs_tonum(struct expr_t *);
+extern int32 __nd_ndxnum(struct expr_t *, char *, int32);
+extern struct net_t *__add_param(char *, struct expr_t *, struct expr_t *);
+extern void __init_stmt(struct st_t *, int32);
+
+extern int32 __expr_has_glb(struct expr_t *);
+extern int32 __isleaf(struct expr_t *);
+extern struct expr_t *__dup_concat(int32, struct expr_t *);
+extern struct expr_t *__find_catend(struct expr_t *);
+extern void __free_namedparams(struct namparam_t *);
+extern struct cell_t *__alloc_cell(struct sy_t *);
+extern struct cell_pin_t *__alloc_cpin(int32);
+extern void __add_syp_to_undefs(struct sy_t *);
+extern void __src_rd_cnv_stk_fromreg_toreal(struct xstk_t *, int32);
+extern void __src_rd_cnv_stk_fromreal_toreg32(struct xstk_t *);
+extern void __sizchgxs(struct xstk_t *, int32);  
+extern void __narrow_sizchg(register struct xstk_t *, int32);
+extern void __sizchg_widen(register struct xstk_t *, int32);
+extern void __sgn_xtnd_widen(struct xstk_t *, int32);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern int32 __allocfill_cval_new(word32 *, word32 *, int32);
+extern int32 __alloc_shareable_cval(word32, word32, int32);
+extern int32 __alloc_shareable_rlcval(double);
+extern char *__to1_stren_nam(char *, int32, int32);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern int32 __cmp_xpr(struct expr_t *, struct expr_t *);
+extern struct attr_t *__rd_parse_attribute(struct attr_t *);
+extern void __cnv_stk_fromreg_toreal(struct xstk_t *, int32);
+extern void __cnv_stk_fromreal_toreg32(struct xstk_t *);
+
+
+extern void __cv_msg(char *, ...);
+extern void __crit_msg(char *, ...);
+extern void __pv_ferr(int32, char *, ...);
+extern void __pv_fwarn(int32, char *, ...);
+extern void __gfinform(int32, word32, int32, char *, ...);
+extern void __finform(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __pv_terr(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __misc_fterr(char *, int32);
+
+/*
+ * read one top level module or udp definition
+ * expects a keyword to have been read and reads end of module
+ *
+ * upon return current token must be endmodule/primitive or eof or
+ * one before module/primitive
+ */
+extern void __rd_ver_mod(void)
+{
+ switch ((byte) __toktyp) {
+  case TEOF: return;
+  case MACROMODULE:
+   __get_vtok();
+   __finform(423, "macromodules not expanded - %s translated as module",
+    __token);
+   goto rd_def;
+  case MODULE:
+   /* know these will either die with eof or have read end mod/prim */
+   /* or have skipped on error so next token read is mod/prim */
+   __get_vtok();
+rd_def:
+   __rd_moddef(NULL, FALSE);
+   break;
+  case PRIMITIVE:
+   /* because library must check for unresolved, get name before call */
+   __get_vtok();
+   __rd_udpdef(NULL);
+   break;
+  case GENERATE:
+   __pv_ferr(3549, "generate feature not implemented in this version");
+   __vskipto_modend(ENDGENERATE); 
+   break;
+  default:
+   __pv_ferr(975, "module or primitive keyword expected - %s read",
+    __prt_vtok());
+   /* for common extra ;, will move to module and back up 1 */
+   /* otherwise will skip to eof */  
+   __vskipto_modend(ENDMODULE);
+ }
+}
+
+/*
+ * cfg form of read ver mod 
+ *
+ * SJM FIXME ??? - why is this different version needed 
+ */
+extern void __rd_cfg_ver_mod(void)
+{
+ switch ((byte) __toktyp) {
+  case TEOF: return;
+  case MACROMODULE:
+   __get_vtok();
+   __finform(423, "macromodules not expanded - %s translated as module",
+    __token);
+   __get_vtok();
+   break;
+  case MODULE:
+   /* know these will either die with eof or have read end mod/prim */
+   /* or have skipped on error so next token read is mod/prim */
+   __get_vtok();
+   break;
+  case PRIMITIVE:
+   /* because library must check for unresolved, get name before call */
+   __get_vtok();
+   break;
+  default:
+   __pv_ferr(975, "module or primitive keyword expected - %s read",
+    __prt_vtok());
+   /* for common extra ;, will move to module and back up 1 */
+   /* otherwise will skip to eof */  
+ }
+}
+
+/*
+ * MODULE DEFINITION ROUTINES
+ */
+
+/*
+ * read a module definition
+ * 
+ * if reading config, put module name in passed config lib el sym table 
+ * upon return current token must be synced to file level token
+ * return F if parse errors, T even if other errors
+ */
+extern int32 __rd_moddef(struct symtab_t *cfg_sytab, int32 isconfig)
+{
+ struct sy_t *syp;
+ struct symtab_t *sp_sytp;
+ struct mod_t *mdp;
+ struct tnode_t *tnp;
+
+ __lofp_port_decls = FALSE;
+ /* DBG remove --- */
+ if (__top_sti != 0) __misc_terr(__FILE__, __LINE__);
+ if (__inst_mod != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* these are couner for use in building object names */
+ __cp_num = __conta_num = 1;
+
+ /* notice that Verilog keywords are reserved words */
+ if (__toktyp != ID)
+  {
+no_read:
+   __pv_ferr(976, "module name expected - %s read", __prt_kywrd_vtok());
+   __vskipto_modend(ENDMODULE);
+   return(FALSE);
+  }
+ 
+ /* SJM 01/07/04 - if module in config library file, put into its mod sy tab */
+ if (cfg_sytab != NULL) 
+  {
+   tnp = __vtfind(__token, cfg_sytab);
+   /* dups already checked for */
+   /* DBG remove -- */
+   if (!__sym_is_new) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   __add_sym(__token, tnp);
+   (cfg_sytab->numsyms)++;
+   syp = tnp->ndp;
+  }
+ else syp = __add_modsym(__token);
+
+ if (syp == NULL) goto no_read;
+ syp->cfg_needed = FALSE;
+ syp->sytyp = SYM_M;
+
+ mdp = __alloc_mod(syp);
+ syp->el.emdp = mdp;
+ /* AIV 05/24/04 - need to set flag to get rid of highest level mods */
+ /* that are scanned but never used in configs */
+ mdp->m_inconfig = isconfig;
+ /* this is where module definition actually resolved */
+ syp->sydecl = TRUE;
+ /* need place where udp declared */
+ syp->syfnam_ind = __cur_fnam_ind;
+ syp->sylin_cnt = __lin_cnt;
+
+ /* if saw attribute before reading latest module keyword save */
+ /* as string - evaled during pass 2 fixup */ 
+ if (__wrk_attr.attr_seen)
+  {
+   /* here only one string possible - on serious error returns nil */
+   /* if returns non nil, at least some attr_specs good */
+   mdp->mattrs = __rd_parse_attribute(&__wrk_attr);
+   /* SJM 07/30/01 - this is work read value, but now done with it */
+   __my_free(__wrk_attr.attrnam, __attr_line_len + 1);
+   __wrk_attr.attr_seen = FALSE;
+  } 
+ __push_wrkitstk(mdp, 0);
+
+ /* must also allocate the new symbol table */
+ __inst_mod->msymtab = __alloc_symtab(TRUE);
+ /* module symbol table always outermost */
+ __inst_mod->msymtab->sytpar = NULL;
+ /* link symbol table back to module symbol */
+ __inst_mod->msymtab->sypofsyt = syp;
+
+ /* set list ends for elements that must be kept in order */
+ __end_cp = NULL; __end_tbp = NULL; __end_paramnp = NULL;
+ __end_ca = NULL; __end_ialst = NULL; __end_dfp = NULL;
+ __end_impparamnp = NULL;
+ __end_mod_varinitlst = NULL; 
+ __cur_declobj = MODULE;
+ __mod_specparams = 0;
+ /* initialize symbol table stack so module on bottom */
+ /* replaces previous module symbol table so no need to pop here */
+ /* system names now in separate symbol table and separated by $ prefix */
+ __top_sti = 0;
+ __venviron[0] = __inst_mod->msymtab;
+
+ /* do not need to build type until entire module read */
+ /* if these return F, know needed to skip to file level mod/prim */
+ if (!rd_modhdr(__inst_mod)) goto bad_end;
+ if (!rd_modbody()) goto bad_end;
+
+ /* if error will not get linked in - this quarentees source order */
+ if (__end_mdp == NULL) __modhdr = __inst_mod;
+ else __end_mdp->mnxt = __inst_mod;
+ __end_mdp = __inst_mod;
+
+ /* current module now always one root of symbol table tree */
+ /* declare wire names used in inst. conns. as 1 bit wires */
+ decl_instconns(__inst_mod);
+ /* here may have no specparams but symbol because of syntax error */
+ /* in common attempt to use defparams as specparams error */
+ if (__inst_mod->mspfy != NULL && __inst_mod->mspfy->spfsyms != NULL)
+  sp_sytp = __inst_mod->mspfy->spfsyms;
+ else sp_sytp = NULL;
+ freeze_mod_syms(__inst_mod->msymtab, sp_sytp);
+ bld_mdpin_table(__inst_mod);
+
+ /* copy wrk gr table to module's gr table */ 
+ if (__grwrknum > 0)
+  {
+   __inst_mod->mgrtab = __alloc_grtab(__grwrktab, __grwrknum);
+   __inst_mod->mgrnum = __grwrknum;
+   __grwrknum = 0; 
+  }
+
+ __last_libmdp = __inst_mod;
+ __pop_wrkitstk();
+ return(TRUE);
+
+bad_end:
+ /* need to free storage so no inst. will find this type */
+ /* assuming could not stay synced while reading */
+ if (__mod_specparams > 0) sp_sytp = __inst_mod->mspfy->spfsyms;
+ else sp_sytp = NULL;
+ freeze_mod_syms(__inst_mod->msymtab, sp_sytp);
+ /* make undeclared */
+ syp->sydecl = FALSE;
+ __pop_wrkitstk();
+ return(TRUE);
+}
+
+/*
+ * add the module name symbol to symbol table
+ */
+extern struct sy_t *__add_modsym(char *nam)
+{
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+
+ tnp = __vtfind(nam, __modsyms);
+ /* this is define before use in source file case */
+ if (__sym_is_new)
+  {
+   __add_sym(nam, tnp);
+   (__modsyms->numsyms)++;
+   syp = tnp->ndp;
+  }
+ else
+  {
+   /* path impossible for copy mod splitting */
+   syp = tnp->ndp;
+   if (!__chk_redef_err(nam, syp, "module", SYM_M)) return(NULL);
+   /* chk fail means never in module undef list */
+   __remove_undef_mod(syp);
+  }
+ syp->sytyp = SYM_M;
+ return(syp);
+}
+
+/*
+ * remove a module from the undef list and count
+ * module now resolved
+ */
+extern void __remove_undef_mod(struct sy_t *syp)
+{
+ struct undef_t *undefp;
+
+ /* repeated use of "module [name]" with no definition will cause */
+ /* lots of syntax error but also will have no module to remove */
+ if (!syp->syundefmod) return;
+
+ /* DBG remove -- */
+ if (syp->sydecl) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ undefp = syp->el.eundefp;
+ __undef_mods--; 
+ /* case 1, removing head */ 
+ if (undefp == __undefhd)
+  {
+   if (undefp == __undeftail)
+    { 
+     __undefhd = __undeftail = NULL;
+     if (__undef_mods != 0) __misc_terr(__FILE__, __LINE__);
+    }
+   else { __undefhd = undefp->undefnxt; __undefhd->undefprev = NULL; }
+  }
+ /* case 2, removing tail - know at least 2 elements */
+ else if (undefp == __undeftail)
+  {
+   /* SJM 06/03/2002 - added extra fields for 64 bit clean - no sharing */
+   __undeftail = undefp->undefprev;
+   __undeftail->undefnxt = NULL;
+  }
+ /* case 3, removing internal */
+ else
+  {
+   undefp->undefprev->undefnxt = undefp->undefnxt;
+   undefp->undefnxt->undefprev = undefp->undefprev;
+  }
+ syp->syundefmod = FALSE;
+ syp->el.eundefp = NULL;
+}
+
+/*
+ * allocate a new module
+ */
+extern struct mod_t *__alloc_mod(struct sy_t *syp)
+{
+ struct mod_t *mdp;
+
+ mdp = (struct mod_t *) __my_malloc(sizeof(struct mod_t));
+ __init_mod(mdp, syp);
+ return(mdp);
+}
+
+/*
+ * allocate a new module
+ */
+extern void __init_mod(struct mod_t *mdp, struct sy_t *syp)
+{
+ mdp->msym = syp;
+ mdp->mod_last_lini = -1;
+ mdp->mod_last_ifi = -1;
+ mdp->msymtab = NULL;
+ mdp->mod_cfglbp = NULL; 
+ mdp->minstnum = 0;
+ mdp->mhassts = FALSE;
+ mdp->msplit = FALSE;
+ mdp->mpndsplit = FALSE;
+ mdp->mhassplit = FALSE;
+ mdp->mgone = FALSE;
+ mdp->msplitpth = FALSE;
+ mdp->mwiddetdone = FALSE;
+ mdp->mhas_widthdet = FALSE;
+ mdp->mhas_indir_widdet = FALSE;
+ mdp->mgiarngdone = FALSE;
+ mdp->mpndprm_ingirng = FALSE;
+ mdp->mpnd_girng_done = FALSE;
+ mdp->mhasisform = FALSE;
+ /* default is 1 ns.(time unit) with 0 digits percision */
+ mdp->mtime_units = __cur_units;
+ /* normally just round (0 frac. digits of precision) */
+ /* module precision is mtime units plus mtime units */
+ mdp->mtime_prec = __cur_prec;
+ mdp->mno_unitcnv = FALSE;
+ if (__in_cell_region) { mdp->m_iscell = TRUE; __design_has_cells = TRUE; }
+ else mdp->m_iscell = FALSE;
+ mdp->m_hascells = FALSE;
+ mdp->mod_hasdvars = FALSE;
+ mdp->mod_dvars_in_src = FALSE;
+ mdp->mod_dumiact = FALSE;
+ mdp->mod_rhs_param = FALSE;
+ mdp->mod_hasbidtran = FALSE;
+ mdp->mod_hastran = FALSE;
+ mdp->mod_gatetran = FALSE;
+ mdp->mod_1bcas = FALSE;
+ mdp->mod_has_mipds = FALSE;
+ mdp->mod_parms_gd = FALSE;
+ mdp->mod_lofp_decl = FALSE;
+ /* values not used by cver but set so vpi_ routines can return */
+ mdp->mod_dfltntyp = (word32) __dflt_ntyp;
+ mdp->mod_uncdrv =  (word32) __unconn_drive;
+ mdp->mhas_frcassgn = FALSE;
+ mdp->flatinum = 0;
+ mdp->mpnum = 0;
+ mdp->miarr = NULL; 
+ mdp->mpins = NULL;
+ mdp->mgates = NULL;
+ mdp->mgarr = NULL;
+ mdp->minum = 0;
+ mdp->mgnum = 0;
+ mdp->mcas = NULL;
+ mdp->mcanum = 0;
+ mdp->minsts = NULL;
+ mdp->miarr = NULL;
+ mdp->mnets = NULL;
+ mdp->mnnum = 0;
+ mdp->mtotvarnum = 0;
+ mdp->mprms = NULL;
+ mdp->mprmnum = 0;
+ mdp->moditps = NULL;
+ mdp->mnxt = NULL;
+
+ mdp->mattrs = NULL;
+ mdp->mvarinits = NULL;
+ mdp->mgateout_cbs = NULL;
+
+ mdp->ialst = NULL;
+ mdp->mtasks = NULL;
+
+ mdp->mexprtab = NULL;
+ mdp->mexprnum = 0;
+
+ mdp->msttab = NULL;
+ mdp->mstnum = 0;
+
+ mdp->mgrtab = NULL;
+ mdp->mgrnum = 0;
+
+ mdp->mspfy = NULL;
+ mdp->mndvcodtab = NULL;
+ /* LOOKATME - could convert to compile time only struct */
+ mdp->mversno = 0;
+ mdp->lastinum = 0;
+ mdp->mlpcnt = -1;
+ mdp->mlevnxt = NULL;
+ mdp->mspltmst = NULL;
+ mdp->mpndspltmst = NULL;
+ mdp->mcells = NULL;
+ mdp->smpins = NULL;
+ mdp->iploctab = NULL;
+ mdp->mdfps = NULL;
+}
+
+/*
+ * NET LIST FIX UP ROUTINES CALLED DURING INPUT PROCESSING
+ */
+
+/*
+ * declare all undeclared wires connected to module insts and gates
+ */
+static void decl_instconns(struct mod_t *mdp)
+{
+ register struct cell_t *cp;
+ register struct cell_pin_t *cpp;
+
+ /* at this point all mod. insts., and gates on cell list */
+ /* SJM 03/25/99 - all gate ports including control must be declared imp. */ 
+ for (cp = mdp->mcells; cp != NULL; cp = cp->cnxt)
+  {
+   if (cp->cmsym == NULL) continue;
+   
+   for (cpp = cp->cpins; cpp != NULL; cpp = cpp->cpnxt)
+    {
+     /* this should always be at least 'bx by here */
+     /* change to special unc. indicator and check/fix here */
+     /* cell port connections lost */
+     if (cpp->cpxnd == NULL) __misc_terr(__FILE__, __LINE__);
+    
+     dcl_iconn_wires(cp, cpp->cpxnd);
+    }
+  }
+}
+
+/*
+ * declare all undeclared wires mentioned in inst. conns implicitly
+ * anything in inst. port expr. implictly declared if not declared
+ * even index of bit select and everything in concatenate
+ */
+static void dcl_iconn_wires(struct cell_t *cp, struct expr_t *ndp)
+{
+ switch ((byte) ndp->optyp) {
+  case NUMBER: case REALNUM: case OPEMPTY: break;
+  /* global are not declared in this module */
+  case GLBREF: break;
+  case ID:
+   {
+    struct net_t *np;
+    struct sy_t *syp;
+
+    syp = ndp->lu.sy;
+    if (syp->sydecl || syp->sytyp != SYM_N) break;
+
+    np = syp->el.enp;
+    /* must not implicitly declare I/O port */
+    if (np->iotyp != NON_IO) break;
+    syp->sydecl = TRUE;
+    syp->sy_impldecl = TRUE;
+    syp->syfnam_ind = cp->csym->syfnam_ind;
+    syp->sylin_cnt = cp->csym->sylin_cnt;
+    np->iotyp = NON_IO;
+    /* type for undeclared is default net types */
+    np->ntyp = __dflt_ntyp;
+    np->nu.ct->n_iotypknown = TRUE;
+    np->nu.ct->n_rngknown = FALSE;
+    np->nu.ct->n_impldecl = TRUE;
+    np->nu.ct->n_wirtypknown = TRUE;
+    __gfinform(419, syp->syfnam_ind, syp->sylin_cnt,
+     "%s %s implicitly declared here from use in instance or gate connection",
+      __to_wtnam(__xs, np), np->nsym->synam);
+   }
+   break;
+  default:
+   /* know will not get here unless operator */
+   if (ndp->lu.x != NULL) dcl_iconn_wires(cp, ndp->lu.x);
+   if (ndp->ru.x != NULL) dcl_iconn_wires(cp, ndp->ru.x);
+   break;
+ }
+}
+
+/*
+ * freeze module symbols and all enclosed symbol tables
+ * treee form of tables free during fixup by freeing the tn blocks
+ * notice sp_sytp can be nil but not sytp
+ */
+static void freeze_mod_syms(struct symtab_t *sytp,
+ struct symtab_t *sp_sytp)
+{
+ /* since only system tasks and interpretive level symbols in level 0 */
+ /* do not look for global there */
+ sytp->sytpar = NULL;
+
+ if (sytp->numsyms == 0) sytp->stsyms = NULL;
+ else __freeze_1symtab(sytp);
+
+ /* if needed also freeze specify specparam symbol table */
+ if (sp_sytp != NULL)
+  {
+   /* symbol table empty if spec params all numbers - works since */
+   /* back annotation is to slot not spec param */
+   if (sp_sytp->numsyms == 0) sp_sytp->stsyms = NULL;
+   else __freeze_1symtab(sp_sytp);
+  }
+ /* notice no top level symbol but contained symbols possible */
+ if (sytp->sytofs != NULL) travfreeze_lowsymtab(sytp->sytofs);
+}
+
+/*
+ * freeze one non empty symbol table
+ */
+extern void __freeze_1symtab(struct symtab_t *sytp)
+{
+ int32 bytes;
+
+ /* DBG remove */
+ if (!sytp->freezes) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ bytes = sytp->numsyms*sizeof(struct sy_t *);
+ __wrkstab = (struct sy_t **) __my_malloc(bytes);
+ __last_sy = -1;
+ travfreeze_syms(sytp->n_head);
+ sytp->stsyms = __wrkstab;
+ sytp->n_head = NULL;
+ /* non mod symbol table size wrong */
+ if (__last_sy + 1 != sytp->numsyms) __misc_terr(__FILE__, __LINE__);
+}
+
+/*
+ * traversal in sorted preorder
+ */
+static void travfreeze_syms(register struct tnode_t *tnp)
+{
+ if (tnp->lp != NULL) travfreeze_syms(tnp->lp);
+ __wrkstab[++__last_sy] = tnp->ndp;
+ if (tnp->rp != NULL) travfreeze_syms(tnp->rp);
+}
+
+/*
+ * depth first symbol table tree traversal across offspring
+ */
+static void travfreeze_lowsymtab(register struct symtab_t *sytp)
+{
+ for (; sytp != NULL; sytp = sytp->sytsib)
+  {
+   if (sytp->numsyms == 0) sytp->stsyms = NULL;
+   else __freeze_1symtab(sytp);
+   if (sytp->sytofs != NULL) travfreeze_lowsymtab(sytp->sytofs);
+  }
+}
+
+/*
+ * convert list of module ports to array of ptrs to module ports
+ * need so port can be accessed from its index
+ * port order is list order that came from header list of ports
+ */
+static void bld_mdpin_table(struct mod_t *mdp)
+{
+ register int32 pi;
+ register struct mod_pin_t *mpp;
+ int32 pnum;
+ struct mod_pin_t *mphdr, *mpp2;
+
+ if ((pnum = mdp->mpnum) == 0) return;
+ mphdr = (struct mod_pin_t *) __my_malloc(pnum*sizeof(struct mod_pin_t));
+ for (pi = 0, mpp = mdp->mpins; mpp != NULL; mpp = mpp->mpnxt, pi++)
+  {
+   mphdr[pi] = *mpp;
+   mphdr[pi].mpnxt = NULL;
+  }
+ /* now free all old ports - contents copied - and need to keep expr */
+ for (mpp = mdp->mpins; mpp != NULL;) 
+  {
+   mpp2 = mpp->mpnxt;
+   __my_free((char *) mpp, sizeof(struct mod_pin_t));
+   mpp = mpp2;
+  }
+ mdp->mpins = mphdr;
+}
+
+/*
+ * check for and emit a redefinition error
+ */
+extern int32 __chk_redef_err(char *nam, struct sy_t *syp,
+ char *newtnam, word32 styp)
+{
+ if (!syp->sydecl)
+  {
+   /* when see mod or udp, assume mod - may turn out to be udp and no err */
+   if (syp->sytyp == SYM_M && styp == SYM_UDP) return(TRUE);
+  }
+
+ if (syp->sytyp != styp)
+  {
+   __pv_ferr(977, "cannot redefine %s as a %s - previous type was %s at %s",
+    nam, newtnam, __to_sytyp(__xs, syp->sytyp), __bld_lineloc(__xs2,
+    syp->syfnam_ind, syp->sylin_cnt));
+   return(FALSE);
+  }
+ if (syp->sydecl)
+  {
+   __pv_ferr(978, "cannot redefine %s %s - previous definition %s",
+    newtnam, nam, __bld_lineloc(__xs, syp->syfnam_ind, syp->sylin_cnt));
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * process an the module header iolist
+ * must read leading ( or (empty ;) and reads trailing ;
+ *
+ * if return T, even if error parsing can continue in module
+ * sometimes guesses that continuing ok, error caught by next routine
+ */
+static int32 rd_modhdr(struct mod_t *mp)
+{
+ struct mod_pin_t *mpp, *last_mpp;
+
+ /* empty I/O list legal */
+ __get_vtok();
+
+ /* P1364 2001 allows #(list of normal parameter decls) here that allows */
+ /* param decls in addition to body param decls */
+ if (__toktyp == SHARP)
+  {
+   /* if error and sync failed, know synced to module level item */
+   if (!rd_hdrpnd_parmdecls()) goto ret_end;
+  }
+ 
+ if (__toktyp == SEMI) return(TRUE);
+ /* norma end reads ending rpar but on error mayhave synced to lpar */
+ if (__toktyp != LPAR) __get_vtok();
+
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(979, 
+    "module header list of ports initial left parenthesis expected - %s read",
+    __prt_vtok());
+   if (__vskipto2_any(RPAR, SEMI)) 
+    {
+     if (__toktyp == RPAR) __get_vtok();
+     /* if not semi, assume semi left out - if bad, next rout. will catch */
+     if (__toktyp != SEMI) __unget_vtok();
+     return(TRUE);
+    }
+ret_end:
+   switch ((byte) __syncto_class) {
+    case SYNC_FLEVEL: return(FALSE);
+    case SYNC_MODLEVEL: return(TRUE);
+    /* should never sync to statement up here */
+    case SYNC_STMT:
+     __vskipto_modend(ENDMODULE);
+     return(FALSE);
+    default: __case_terr(__FILE__, __LINE__);
+   }
+  }
+ __get_vtok();
+ if (__toktyp == RPAR)
+  {
+do_end:
+   __get_vtok();
+do_end2:
+   if (__toktyp == SEMI) return(TRUE);
+
+   __pv_ferr(980,
+    "module header list of ports end semicolon expected - %s read",
+    __prt_vtok());
+   __unget_vtok();
+   return(TRUE);
+  }
+
+ /* SJM 05/23/04 - branch point for separate list of port decl header form */
+ if (__toktyp == INPUT || __toktyp == OUTPUT || __toktyp == INOUT)
+  {
+   /* reads ending ; after ) - also sets flags that prevents further */
+   /* port decls that would be legal for port name (explicit too) forms */
+   if (!rd_list_of_ports_decl(mp)) goto ret_end;
+   if (__toktyp == RPAR) __get_vtok();
+   goto do_end2;
+  }
+
+ for (last_mpp = NULL;;)
+  {
+   /* this declares the symbols in the header */
+
+   /* SJM 08/30/00 - need to ignore ,, and not count as a port in hdr def. */
+   if (__toktyp == COMMA)
+    {
+     __pv_fwarn(3103,
+      "empty ,, in module header port definition list ignored - not used in ordered instance connection list"); 
+     goto nxt_port;
+    }
+   if (__toktyp == RPAR)
+    {
+     __pv_fwarn(3103,
+      "empty ,) in module header port definition list ignored"); 
+     goto do_end;
+    } 
+
+   if (!rd_portref())
+    {
+     /* on error ignore this port and move on to next */
+do_resync:
+     if (__vskipto3_any(COMMA, SEMI, RPAR)) 
+      {
+       /* port effectively not seen - error emitted already */
+       if (__toktyp == COMMA) goto nxt_port;
+       if (__toktyp == RPAR) goto do_end;
+       break;
+      }
+     goto ret_end;
+    }
+
+   /* assume unvectored 1 bit port */
+   mpp = __alloc_modpin();
+   /* think possiblity unnamed ports can appear here */
+   if (strcmp(__portnam, "") == 0) mpp->mpsnam = NULL;
+   else mpp->mpsnam = __pv_stralloc(__portnam);
+   mpp->mp_explicit = (__mpref_explicit) ? TRUE : FALSE;
+
+   if (last_mpp == NULL) mp->mpins = mpp; else last_mpp->mpnxt = mpp;
+   last_mpp = mpp;
+   mpp->mpref = __root_ndp;
+   /* count number of ports */
+   (mp->mpnum)++;
+   if (mp->mpnum >= MAXNUMPORTS)
+    {
+     __pv_ferr(314, "INTERNAL FATAL - module has more than %d ports - contact Pragmatic C",
+      MAXNUMPORTS);
+     (mp->mpnum)--; 
+    }
+
+   if (__toktyp == RPAR) goto do_end;
+   if (__toktyp != COMMA)
+    {
+     __pv_ferr(984,
+      "module header comma expected - %s read", __prt_vtok());
+     goto do_resync;
+    }
+nxt_port:
+   __get_vtok();
+  }
+ return(TRUE);
+}
+
+/*
+ * read the module define #(param decl list) parameter delcarations
+ * know the leading # read and reads one past ending ')' (probably '(')
+ *
+ * format is: module xx #([parameter decl list], ...) (port list) ...
+ * notice that only legal for module definitions
+ */
+static int32 rd_hdrpnd_parmdecls(void)
+{
+ __get_vtok();
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(984,
+    "module header #([parameter decl], ..) form starting left paren expected - %s read",
+    __prt_vtok());
+   if (!__vskipto3_any(RPAR, LPAR, SEMI)) return(FALSE);
+   return(TRUE);
+  }
+ __get_vtok();
+ for (;;)
+  {
+   if (__toktyp == RPAR) return(TRUE);
+   if (__toktyp != PARAMETER)
+    {
+     if (!__vskipto4_any(PARAMETER, COMMA, RPAR, SEMI)) return(FALSE);
+     if (__toktyp == PARAMETER) continue;
+     if (__toktyp == COMMA) { __get_vtok(); continue; }
+     if (__toktyp == RPAR || __toktyp == SEMI) return(TRUE);
+    }
+
+   if (!rd_paramdecl(TRUE)) return(FALSE);
+  }
+}
+
+/*
+ * read module header port .[port name]([port expr.]) or [port expr.] form
+ * know 1st token name read and reads one past end , or ) if no error
+ * if no error, expression in root_ndp
+ *
+ * medium level - caller syncs if returns error F
+ */
+static int32 rd_portref(void)
+{
+ int32 nd_rpar;
+
+ if (__toktyp == DOT)
+  {
+   __mpref_explicit = TRUE;
+   __get_vtok();
+   if (__toktyp != ID)
+    {
+     __pv_ferr(985, "module definition header name of port expected - %s read",
+      __prt_kywrd_vtok());
+     return(FALSE);
+    }
+   strcpy(__portnam, __token);
+   __get_vtok();
+   if (__toktyp != LPAR)
+    {
+     __pv_ferr(986,
+     "module definition header .[port]([port expr.]) form left parenthesis expected - %s read",
+      __prt_vtok());
+     return(FALSE);
+    }
+   nd_rpar = TRUE;
+   /* read collect the expression that must end with ) only */
+   __get_vtok();
+   /* this cannot be empty */
+   if (__toktyp == RPAR)
+    { 
+     __finform(3004,
+      "empty module definition header explicit form () port expression no effect");
+     __last_xtk = 0;
+     __set_opempty(0);
+    }
+   else 
+    {
+     if (!__col_parenexpr(-1)) return(FALSE);
+    }
+  }
+ else
+  {
+   __mpref_explicit = FALSE;
+   nd_rpar = FALSE;
+   strcpy(__portnam, "");
+   /* read/collect expression that must end with ) or , */
+   /* know 1st token of expression read */
+   if (!__col_connexpr(-1)) return(FALSE);
+  }
+ /* build the tree, copy/allocate nodes, sets root_ndp to its root */
+ __bld_xtree(0);
+ /* must set all net like things as IO ports */
+ set_ioprtnets(__root_ndp);
+
+ if (!nd_rpar)
+  {
+   struct expr_t *idx;
+
+   /* for unnamed port is simple id, that is port name */
+   if (__root_ndp->optyp == ID) idx = __root_ndp;
+   else if (__root_ndp->optyp == LSB || __root_ndp->optyp == PARTSEL)
+    idx = __root_ndp->lu.x;
+   else idx = NULL;
+   if (idx != NULL) strcpy(__portnam, idx->lu.sy->synam);
+  }
+ else 
+  {
+   if (__toktyp != RPAR)
+    {
+     __pv_ferr(988,
+     "module definition header named port form right parenthesis expected - %s read",
+      __prt_vtok());
+     return(FALSE);
+    }
+   __get_vtok();
+  }
+ return(TRUE);
+}
+
+/*
+ * mark all nets in I/O port expression as I/O of unknown direction
+ * can be arbitrary expressions here because not yet checked 
+ */
+static void set_ioprtnets(struct expr_t *ndp)
+{
+ struct sy_t *syp;
+
+ if (__isleaf(ndp))
+  {
+   if (ndp->optyp == ID)
+    {
+     syp = ndp->lu.sy;
+     /* module header wire %s declaration inconsistent */
+     /* DBG remove -- */
+     if (syp->sytyp != SYM_N)
+      {
+       __pv_ferr(684,
+        "I/O port definition %s name %s type %s illegal - must be a net",
+        __msgexpr_tostr(__xs, ndp), syp->synam, __to_sytyp(__xs2, syp->sytyp));
+       syp->sytyp = SYM_N;
+      }
+     /* --- */
+     syp->el.enp->iotyp = IO_UNKN;
+    }
+   return;
+  }
+ if (ndp->lu.x != NULL) set_ioprtnets(ndp->lu.x);
+ if (ndp->ru.x != NULL) set_ioprtnets(ndp->ru.x);
+}
+
+/*
+ * allocate a module pin (port) element
+ */
+extern struct mod_pin_t *__alloc_modpin(void)
+{
+ struct mod_pin_t *mpp;
+
+ mpp = (struct mod_pin_t *) __my_malloc(sizeof(struct mod_pin_t));
+ mpp->mpsnam = NULL;
+ mpp->mptyp = IO_UNKN;
+ /* gets set and used only for bidirects */ 
+ mpp->mp_explicit = FALSE;
+ mpp->mp_jmpered = FALSE;
+ mpp->inout_unc = FALSE;
+ mpp->assgnfunc_set = FALSE;
+ mpp->has_mipd = FALSE;
+ mpp->has_scalar_mpps = FALSE;
+
+ /* assume 1 for prim */
+ mpp->mpwide = 1;
+ /* expression for .[name]({...}) form but usually same internal net */
+ mpp->mpref = NULL;
+ mpp->mpattrs = NULL;
+ mpp->mpfnam_ind = __cur_fnam_ind;
+ mpp->mplin_cnt = __lin_cnt;
+ mpp->mpaf.mpp_upassgnfunc = NULL;
+ mpp->pbmpps = NULL;
+ mpp->mpnxt = NULL;
+ return(mpp);
+}
+
+/*
+ * ROUTINES TO READ AND ADD LIST OF PORTS STYLE HEADER PORT DECLATIONS 
+ */
+
+/*
+ * read list of header port declarations
+ * new alternative ANSII style port header decl form added to 2001 LRM
+ *
+ * first port type keyword read and reads ending );
+ *
+ * if return T, even if error parsing can continue in module
+ * on error must sync to semi and back up one - mod item which just returns
+ */
+static int32 rd_list_of_ports_decl(struct mod_t *mp)
+{
+ int32 first_time, wtyp, ptyp, attr_ttyp, has_attr, decl_signed;
+ struct sy_t *syp;
+ struct net_t *np;
+ struct expr_t *x1, *x2, *ox1, *ox2;
+ struct mod_pin_t *mpp, *last_mpp;
+ char s1[RECLEN];
+
+ ptyp = -1;
+ /* even if syntax error, T once a port type keyword appears in hdr */
+ mp->mod_lofp_decl = TRUE;
+ __lofp_port_decls = TRUE;
+
+ last_mpp = NULL;
+ for (;;)
+  {
+   /* attribute collected by scanner - but need to save so associates with */
+   /* right port */
+   if (__attr_prefix)
+    {
+     __wrk_attr.attr_tok = __toktyp;
+     __wrk_attr.attr_seen = TRUE;
+     /* for now this is unparsed entire attr. string */
+     __wrk_attr.attrnam = __pv_stralloc(__attrwrkstr);
+     __wrk_attr.attr_fnind = __attr_fnam_ind;
+     __wrk_attr.attrlin_cnt = __attr_lin_cnt;
+    }
+   else __wrk_attr.attr_seen = FALSE;
+
+   attr_ttyp = __toktyp;
+   if (__toktyp == INPUT) ptyp = IO_IN;
+   else if (__toktyp == OUTPUT) ptyp = IO_OUT;
+   else if (__toktyp == INOUT) ptyp = IO_BID;
+   else __case_terr(__FILE__, __LINE__); 
+
+   __get_vtok();
+
+   /* defaults to wire if net type omitted - can be var/reg type */
+   if ((wtyp = __fr_wtnam(__toktyp)) != -1) __get_vtok();
+   else wtyp = N_WIRE;
+
+   if (wtyp == N_INT || wtyp == N_REAL) decl_signed = TRUE;
+   else decl_signed = FALSE;
+
+   /* vectored or scalared keywords never appear in port decls */
+   if (__toktyp == SIGNED)
+    {
+     decl_signed = TRUE;
+     if (wtyp == N_TIME || wtyp == N_INT || wtyp == N_REAL || wtyp == N_EVENT) 
+      {
+       __pv_ferr(3423,
+        "signed keyword illegal when task or function variable type %s",
+        __to_wtnam2(s1, wtyp));
+      }
+     __get_vtok();
+    }
+
+   /* even if error if 1 past ending ] continue */
+   if (!__rd_decl_rng(&ox1, &ox2))
+    {
+     /* bad decl - but if sync to new I/O port direction, caller will cont */
+     if (!__vskipto_lofp_end()) return(FALSE); 
+     if (__toktyp == RPAR) { __get_vtok(); return(TRUE); } 
+     /* semi read */
+     return(TRUE);
+    }
+
+   /* use local has attr flag so can turn glb seen off before return */
+   if (__wrk_attr.attr_seen)
+    { has_attr = TRUE; __wrk_attr.attr_seen = FALSE; }
+   else has_attr = FALSE;
+
+   x1 = x2 = NULL;
+   for (first_time = TRUE;;)
+    {
+     if (__toktyp != ID)
+      {
+       __pv_ferr(992, "list of port form %s port name expected - %s read",
+        __to_ptnam(s1, ptyp), __prt_kywrd_vtok());
+
+       if (__vskipto2_lofp_end())
+        {
+         if (__toktyp == SEMI) return(TRUE);
+         if (__toktyp == RPAR) { __get_vtok(); return(TRUE); }
+         /* only other possibility is the port name separating comma */
+         continue;
+        }
+       /* can't recover (resync) from error - synced to module item */
+       return(FALSE);
+      }
+
+     if ((syp = __get_sym_env(__token)) != NULL)
+      {
+       __pv_ferr(3418, "list of port form %s port name %s redeclared", 
+        __to_ptnam(s1, ptyp), __token);
+       goto nxt_port;
+      }
+
+     if (first_time) { x1 = ox1; x2 = ox2; first_time = FALSE; } 
+     else
+      {
+       if (x1 == NULL) x1 = x2 = NULL;
+       else { x1 = __copy_expr(ox1); x2 = __copy_expr(ox2); }
+      }
+
+     /* first declare the port's wire/reg */
+     if ((np = __decl_wirereg(wtyp, x1, x2, NULL)) == NULL) goto nxt_port;
+
+     /* if previously used will be treated as reg - must set to compatible */
+     /* wire type if declared as time or int32 */
+     np->ntyp = wtyp;
+     syp = np->nsym;
+
+     /* if saw an (* *) attribute for module item token, seen on */
+     if (has_attr)
+      {
+       /* this add to net's attr list on end if also net decl first */
+       add_net_attr(np, attr_ttyp);
+      }
+
+     /* SJM 10/02/03 - signed can be turned on either in port or wire decl */ 
+     if (decl_signed) np->n_signed = TRUE;
+
+     np->iotyp = ptyp;
+     /* for list of ports mod header decl form, all info in hdr decl */ 
+     np->nu.ct->n_iotypknown = TRUE;
+
+     syp->sydecl = TRUE;
+     /* need I/O decl. place not header or wire decl. */
+     syp->syfnam_ind = __cur_fnam_ind;
+     syp->sylin_cnt = __lin_cnt;
+
+     /* then add the port to the port list - know port and net name same */
+     mpp = __alloc_modpin();
+     mpp->mpsnam = __pv_stralloc(np->nsym->synam);
+     mpp->mp_explicit = FALSE;
+
+     if (last_mpp == NULL) mp->mpins = mpp; else last_mpp->mpnxt = mpp;
+     last_mpp = mpp;
+
+     /* name of port still in token - expr here always ID */
+     __last_xtk = -1;
+     if (!__bld_expnode()) __set_xtab_errval();
+     __bld_xtree(0);
+     mpp->mpref = __root_ndp;
+
+     /* count number of ports */
+     (mp->mpnum)++;
+     if (mp->mpnum >= MAXNUMPORTS)
+      {
+       __pv_ferr(314,
+        "INTERNAL FATAL - module has more than %d ports - contact Pragmatic C",
+        MAXNUMPORTS);
+       (mp->mpnum)--; 
+      }
+
+nxt_port:
+     __get_vtok();
+     if (__toktyp == RPAR) return(TRUE);
+
+     if (__toktyp != COMMA)
+      {
+       __pv_ferr(995,
+        "list of ports form declaration list comma or right paren expected - %s read",
+        __prt_vtok());
+       /* try to resync */
+       if (!__vskipto_lofp_end()) return(FALSE); 
+       if (__toktyp == COMMA) goto nxt_net;
+       /* misplaced semi or sync to rpar */
+       return(TRUE);
+      }
+nxt_net:
+     __get_vtok();
+     if (__toktyp == INPUT || __toktyp == OUTPUT || __toktyp == INOUT)  
+      break;
+    }
+  }
+ __misc_terr(__FILE__, __LINE__);
+ return(TRUE);
+}
+
+/*
+ * MODULE ITEM ROUTINES
+ */
+
+/*
+ * read module body and process the various module items
+ * know __inst_mod points to current module structure
+ * know module port list end ; read
+ *
+ * if returns T must be synced on end mod 
+ */
+static int32 rd_modbody(void)
+{
+ int32 rv, iattyp, ialcnt, iafnind, wtyp;
+ struct st_t *stp;
+ struct ialst_t *ialp;
+ char typnam[IDLEN];
+
+ for (;;)
+  {
+   /* routines called in switch expected to read ending ; or token */
+   __get_vtok();
+   /* SJM 03/20/00 - save attribute info for mod items */
+   if (__attr_prefix)
+    {
+     __wrk_attr.attr_tok = __toktyp;
+     __wrk_attr.attr_seen = TRUE;
+     /* for now this is unparsed entire attr. string */
+     __wrk_attr.attrnam = __pv_stralloc(__attrwrkstr);
+     __wrk_attr.attr_fnind = __attr_fnam_ind;
+     __wrk_attr.attrlin_cnt = __attr_lin_cnt;
+    }
+   else __wrk_attr.attr_seen = FALSE;
+
+   switch((byte) __toktyp) {
+    case TEOF:
+     __pv_ferr(989, "endmodule missing");
+     return(FALSE);
+    case INPUT:
+     if (!rd_iodecl(IO_IN))
+      {
+moditem_resync:
+       /* on error - reset attribute prefix state */
+       __wrk_attr.attr_seen = FALSE;
+       switch ((byte) __syncto_class) {
+        case SYNC_FLEVEL: return(FALSE);
+        case SYNC_MODLEVEL: break;
+	/* if sync. to statement assume initial left out */
+        case SYNC_STMT:
+         /* here must clear any pushed back */
+         if (__lasttoktyp != UNDEF) __get_vtok(); 
+	 /*FALLTHRU */
+        case SYNC_TARG:
+	 iattyp = INITial;
+         iafnind= __cur_fnam_ind;
+         ialcnt = __lin_cnt;
+	 goto moditem_stmt;
+        default: __case_terr(__FILE__, __LINE__);
+       }
+      }
+     continue;
+    case OUTPUT:
+     if (!rd_iodecl(IO_OUT)) goto moditem_resync;
+     continue;
+    case INOUT:
+     if (!rd_iodecl(IO_BID)) goto moditem_resync;
+     continue;
+    case EVENT:
+     if (!rd_eventdecl(FALSE)) goto moditem_resync;
+     continue;
+    case INITial:
+    case ALWAYS:
+     iafnind = __cur_fnam_ind;
+     ialcnt = __lin_cnt;
+     iattyp = __toktyp;
+     __get_vtok();
+     /* statement must synchronize */
+moditem_stmt:
+     if ((stp = __rd_stmt()) != NULL)
+      {
+       ialp = (struct ialst_t *) __my_malloc(sizeof(struct ialst_t));
+       ialp->iatyp = iattyp;
+       ialp->iastp = stp;
+       ialp->ia_first_ifi = iafnind;
+       ialp->ia_first_lini = ialcnt;
+       ialp->ia_last_ifi = __cur_fnam_ind;
+       ialp->ia_last_lini = __lin_cnt;
+       ialp->ialnxt = NULL;
+
+       if (__end_ialst == NULL) __inst_mod->ialst = ialp;
+       else __end_ialst->ialnxt = ialp;
+       __end_ialst = ialp;
+      }
+     else goto moditem_resync;
+     continue;
+    case ASSIGN:
+     if (!rd_contassign()) goto moditem_resync;
+     continue;
+    case PARAMETER:
+     if (!rd_paramdecl(FALSE)) goto moditem_resync;
+     continue;
+    case DEFPARAM:
+     if (!rd_dfparam_stmt()) goto moditem_resync;
+     continue;
+    case SPECIFY:
+     if (!__rd_spfy(__inst_mod)) goto moditem_resync;
+     continue;
+    case TASK:
+     __cur_declobj = TASK;
+     rv = rd_task();
+     __cur_declobj = MODULE;
+     if (!rv) goto moditem_resync;
+     continue;
+    case FUNCTION:
+     __cur_declobj = TASK;
+     rv = rd_func();
+     __cur_declobj = MODULE;
+     if (!rv) goto moditem_resync;
+     continue;
+    case ENDMODULE:
+     /* save end so can put in module's end souce range fields */
+     __inst_mod->mod_last_lini = __lin_cnt;
+     __inst_mod->mod_last_ifi = __cur_fnam_ind;
+
+     /* catch common extra ; error here */
+     __get_vtok();
+     if (__toktyp == SEMI)
+      __pv_ferr(999, "semicolon following endmodule illegal"); 
+     else __unget_vtok();
+     break;
+    case ENDPRIMITIVE:
+     /* but assume still in sync */
+     __pv_ferr(990, "module definitition cannot end with endprimitive");
+     break;
+    case GENERATE:
+     /* AIV 06/27/05 - catch generate */
+     __pv_ferr(3549, "generate feature not implemented in this version");
+     if (!__vskipto_modend(ENDGENERATE)) break;
+     continue;
+    default:
+     if ((wtyp = __fr_wtnam(__toktyp)) != -1)
+      {
+       /* false here means out of sync - must skip rest of module */
+       /* if T will have skipped to semi */
+       if (!rd_vardecl((word32) wtyp)) goto moditem_resync;
+       /* needed to add attribute to every net in list - can now reset */
+       __wrk_attr.attr_seen = FALSE;
+       continue;
+      }
+     /* must be instance (udp, gate, module instantiation) */
+     if (__toktyp != ID)
+      {
+       __pv_ferr(991, "module type, gate or udp name expected - %s read",
+        __prt_kywrd_vtok());
+       /* can only sync to ; here - else need names to decl. */
+       if (!__vskipto_any(SEMI)) goto moditem_resync;
+       break;
+      }
+     strcpy(typnam, __token);
+     if (!rd_inst(typnam)) goto moditem_resync;
+     /* needed to add attr to every instance, now can reset attr seen */ 
+     __wrk_attr.attr_seen = FALSE;
+     continue;
+   }
+   break;
+  }
+ return(TRUE);
+}
+
+/*
+ * MODULE DECLARATION ROUTINES
+ */
+
+/*
+ * process an I/O or wire declaration
+ * mostly sets the iotyp field
+ * I/O decl. does not declare symbol even though wire decl. not required
+ */
+static int32 rd_iodecl(word32 typ)
+{
+ int32 first_time, ttyp, has_attr, decl_signed, is_complete, wtyp;
+ struct sy_t *syp;
+ struct net_t *np;
+ struct expr_t *x1, *x2, *ox1, *ox2;
+ char s1[RECLEN];
+
+ wtyp = -1;
+ decl_signed = FALSE;
+ is_complete = FALSE;
+ /* vectored or scalared keywords only appear on wire decls */
+ __get_vtok();
+ if (__toktyp == SIGNED)
+  {
+   decl_signed = TRUE;
+   __get_vtok();
+  }
+ /* AIV 07/20/04 port decl can now contain net type making it complete  */
+ else if ((wtyp = __fr_wtnam(__toktyp)) != -1)
+  {
+    /* if complete set the flag set the type */
+    is_complete = TRUE;
+    __get_vtok();
+    /* must check for sign again */
+    if (__toktyp == SIGNED)
+     {
+      decl_signed = TRUE;
+      __get_vtok();
+     }
+   }
+  /* type defaults to reg if undefined */
+  else wtyp = N_REG;
+
+ /* even if error if 1 past ending ] continue */
+ if (!__rd_decl_rng(&ox1, &ox2))
+  {
+   /* ignore decl but continue with mod. item */
+   if (!__vskipto2_any(SEMI, RSB)) return(FALSE); 
+   if (__toktyp == SEMI) return(TRUE);
+   __get_vtok();
+  }
+ /* use local has attr flag so can turn glb seen of before return */
+ if (__wrk_attr.attr_seen) { has_attr = TRUE; __wrk_attr.attr_seen = FALSE; }
+ else has_attr = FALSE;
+ x1 = x2 = NULL;
+ for (first_time = TRUE;;)
+  {
+   if (__toktyp != ID)
+    {
+     __pv_ferr(992, "%s port name expected - %s read", __to_ptnam(s1, typ),
+      __prt_kywrd_vtok());
+     /* need token and symbol and cannot parse */
+     return(__vskipto_any(SEMI));
+    }
+
+   /* any port decl illegal if hdr list of port form used */
+   if (__lofp_port_decls)
+    {
+     __pv_ferr(3421,
+      "%s declaration of \"%s\" illegal - module uses list of ports declaration form",
+     __to_ptnam(s1, typ), __prt_kywrd_vtok());
+     goto nxt_port; 
+    }
+
+   /* 3 ways to not be in I/O port header list */
+   /* know only one symbol level here */
+   /* also know must be defined since added when header read */
+   if ((syp = __get_sym_env(__token)) == NULL)
+    {
+not_a_port:
+     __pv_ferr(993,
+     "%s declaration of \"%s\" illegal - not in module header list of ports",
+      __to_ptnam(s1, typ), __token);
+     goto nxt_port;
+    }
+   if (syp->sytyp != SYM_N) goto not_a_port;
+   np = syp->el.enp;
+
+   /* SJM 10/02/03 - signed can be turned on either in port or wire decl */ 
+   if (decl_signed) np->n_signed = TRUE;
+
+   /* when module header list of ports read, port set to IO_UNKN */
+   if (np->iotyp == NON_IO) goto not_a_port;
+
+   /* header port changed when I/O port decl. seen */
+   if (np->nu.ct->n_iotypknown)
+    {
+     __pv_ferr(994, "I/O port %s previously declared as %s", __token,
+      __to_ptnam(s1, np->iotyp));
+    }
+   else
+    {
+     np->iotyp = typ;
+     np->nu.ct->n_iotypknown = TRUE;
+    }
+
+   /* if saw an (* *) attribute for module item token, seen on */
+   if (has_attr)
+    {
+     if (typ == IO_IN) ttyp = INPUT; else if (typ == IO_OUT) ttyp = OUTPUT;
+     else ttyp = INOUT;
+
+     /* this add to net's attr list on end if also net decl first */
+     add_net_attr(np, ttyp);
+    }
+
+   if (first_time) { x1 = ox1; x2 = ox2; first_time = FALSE; } 
+   else
+    {
+     if (x1 == NULL) x1 = x2 = NULL;
+     else { x1 = __copy_expr(ox1); x2 = __copy_expr(ox2); }
+    }
+   if (!chkset_wdrng(np, x1, x2)) goto nxt_port;
+
+   /* 2 cases, if so far only appeared in port header wirtypknown F */
+   /* and need to set as wire not reg (default for ports), else already set */
+   /* but notice if set, type still not known just implicitly wire */
+   if (is_complete)
+    {
+     np->ntyp = wtyp;
+     /* must make as  */
+     np->nu.ct->n_iscompleted = TRUE;
+    }
+   else if (!np->nu.ct->n_wirtypknown) np->ntyp = N_WIRE;
+
+   syp->sydecl = TRUE;
+   /* need I/O decl. place not header or wire decl. */
+   syp->syfnam_ind = __cur_fnam_ind;
+   syp->sylin_cnt = __lin_cnt;
+
+nxt_port:
+   __get_vtok();
+   if (__toktyp == SEMI) break;
+   if (__toktyp != COMMA)
+    {
+     __pv_ferr(995,
+      "I/O port declaration list comma or semicolon expected - %s read",
+      __prt_vtok());
+     /* try to resync */
+     if (!__vskipto2_any(COMMA, SEMI)) return(FALSE); 
+     if (__toktyp == COMMA) goto nxt_var;
+     break;
+    }
+nxt_var:
+   __get_vtok();
+  }
+ return(TRUE);
+}
+
+/*
+ * read a decl range (either reg, wire, array, or gate/inst)
+ * know possible for range present [ read and reads one past end ]
+ * this fills exprs that are evaluated later
+ *
+ * on error caller handles skipping
+ * x1 and x2 only point to non nil if succeeds
+ */
+extern int32 __rd_decl_rng(struct expr_t **x1, struct expr_t **x2)
+{
+ *x1 = *x2 = NULL;
+
+ if (__toktyp == LSB) 
+  {
+   if (!__col_rangeexpr())
+    {
+     /* error, but structure right */
+     if (__toktyp == RSB) { __get_vtok(); return(TRUE); }
+     return(FALSE);
+    }
+   __bld_xtree(0);
+   __get_vtok();
+   /* this really is number range */
+   if (__root_ndp->optyp != PARTSEL)
+    __pv_ferr(998, "illegal declaration range expression");
+   else { *x1 = __root_ndp->ru.x->lu.x; *x2 = __root_ndp->ru.x->ru.x; }
+  }
+ return(TRUE);
+}
+
+/*
+ * add a net attribute 
+ * SJM - 03/20/00 - if I/O decl attrs really net attrs for port net
+ */
+static void add_net_attr(struct net_t *np, int32 ttyp)
+{
+ register struct attr_t *attrp, *new_attrp, *last_attrp;
+
+ /* need to set token type so each parsed attr_spec has right tok type */
+ __wrk_attr.attr_tok = ttyp;
+ 
+ /* return nil on error */
+ if ((new_attrp = __rd_parse_attribute(&__wrk_attr)) != NULL)
+  { 
+   if (np->nattrs == NULL) np->nattrs = new_attrp;
+   else
+    {
+     /* linear search not problem because only 2 decls possible */
+     last_attrp = NULL;
+     /* move to tail of list */
+     for (attrp = np->nattrs; attrp != NULL; attrp = attrp->attrnxt) 
+      { last_attrp = attrp; }
+     /* SJM 08/02/01 - add if to keep lint happy */
+     if (last_attrp != NULL) last_attrp->attrnxt = new_attrp;
+    }
+  }
+ __my_free(__wrk_attr.attrnam, __attr_line_len + 1);
+ __wrk_attr.attr_seen = FALSE;
+}
+
+/*
+ * [wire type] [charge or drive stren] [range] [delay] [list of variables]
+ * [charge strength] is ([cap. size])
+ */
+
+/*
+ * read and process a wire/reg/time/int/real variable declaration
+ * know wire type read and reads final semi
+ * semantic routines detect errors later
+ * tricky because wires can also be continuous assignments
+ * capacitor strength indicated by v_stren1 = NO_STREN
+ *
+ * if returns F synced to next module, else synced to SEMI
+ */
+static int32 rd_vardecl(word32 wtyp)
+{
+ int32 first_time, split_state, decl_signed, has_attr;
+ struct expr_t *x1, *x2, *ox1, *ox2, *xm1, *xm2;
+ struct sy_t *syp;
+ struct net_t *np;
+ struct paramlst_t *pmphdr;
+ char s1[RECLEN];
+
+ pmphdr = NULL;
+ __v0stren = __v1stren = NO_STREN;
+ if (wtyp == N_INT || wtyp == N_REAL) decl_signed = TRUE;
+ else decl_signed = FALSE;
+ 
+ __get_vtok();
+ if (__toktyp == LPAR)
+  {
+   __get_vtok();
+   /* normal use of strengths if for wire assign net decl form */
+   if (!rd_verstrens())
+    {
+     if (!__vskipto2_any(RPAR, SEMI)) return(FALSE);
+     if (__toktyp == RPAR) { __get_vtok(); goto rd_rng; }
+     return(TRUE);
+    }
+   /* if error strength turned off */
+   chk_capwdecl_strens(wtyp);
+  }
+
+rd_rng:
+ split_state = SPLT_DFLT;
+ if (__toktyp == VECTORED) { __get_vtok(); split_state = SPLT_VECT; }
+ else if (__toktyp == SCALARED) { split_state = SPLT_SCAL; __get_vtok(); }
+
+ if (__toktyp == SIGNED)
+  {
+   decl_signed = TRUE;
+   if (wtyp == N_TIME || wtyp == N_INT || wtyp == N_REAL || wtyp == N_EVENT) 
+    {
+     __pv_ferr(3423,
+      "signed keyword illegal when variable type %s", __to_wtnam2(s1, wtyp));
+    }
+   __get_vtok();
+  }
+ if (!__rd_decl_rng(&ox1, &ox2))
+  {
+   if (!__vskipto2_any(SEMI, RSB)) return(FALSE); 
+   if (__toktyp == SEMI) return(TRUE);
+   /* on success this reads one past ] */
+   __get_vtok();
+  } 
+ if (split_state != SPLT_DFLT)
+  {
+   char s2[RECLEN];
+
+   /* SJM 07/19/02 - notice only one of these errors can be emitted */
+   if (wtyp >= NONWIRE_ST)
+    {
+     __pv_ferr(997,
+      "%s keyword illegal for type \"%s\"", __to_splt_nam(s1, split_state),
+      __to_wtnam2(s2, wtyp));
+     split_state = SPLT_DFLT; 
+     ox1 = ox2 = NULL;
+    }
+   else if (ox1 == NULL)
+    {
+     __pv_ferr(996, "%s keyword required following range missing",
+      __to_splt_nam(s1, split_state));
+     split_state = SPLT_DFLT; 
+    }
+  }
+ if (ox1 != NULL)
+  {
+   if (wtyp == N_INT || wtyp == N_TIME || wtyp == N_REAL || wtyp == N_EVENT)
+    {
+     __pv_ferr(1002, "%s %s vector range illegal", __to_wtnam2(s1, wtyp),
+      __token);
+     ox1 = ox2 = NULL;
+    }
+  }
+ /* leave scalar with SPLT_DFLT state */
+ /* returning F means must try to skip to semi */ 
+ if (__toktyp == SHARP)
+  {
+   if (!rd_oparamdels(&pmphdr))
+    {
+bad_end:
+     return(__vskipto_any(SEMI));
+    } 
+  }
+
+ /* use local has attr flag so can turn glb seen of before return */
+ if (__wrk_attr.attr_seen) { has_attr = TRUE; __wrk_attr.attr_seen = FALSE; }
+ else has_attr = FALSE;
+ /* know ox1 and ox2 contain statement decl range */ 
+ for (first_time = TRUE;;)
+  {
+   /* save line count since for conta form need lhs var location */
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1001, "wire or reg declaration wire name expected - %s read",
+      __prt_kywrd_vtok());
+     /* must move over this token in case it is vendor 1 keyword */
+     __get_vtok();
+     goto bad_end;
+    }
+  
+  /* if hdr list of port form used, decls giving additional info illegal */
+  if ((syp = __get_sym_env(__token)) != NULL && syp->sytyp == SYM_N
+   && syp->el.enp->iotyp != NON_IO)
+   {
+    if (__lofp_port_decls || syp->el.enp->nu.ct->n_iscompleted)
+     {
+      if (__lofp_port_decls)
+       {
+        __pv_ferr(3421,
+         "%s declaration of port \"%s\" illegal - module uses list of ports declarations form",
+         __to_wtnam2(s1, wtyp), __prt_kywrd_vtok());
+       }
+      else
+       {
+        __pv_ferr(3424,
+         "%s declaration of port \"%s\" illegal - net type is previously defined",
+         __to_wtnam2(s1, wtyp), __prt_kywrd_vtok()); 
+       }
+
+      /* ignore rest of declaration - should resync if no syntax error */
+      if (!__vskipto2_any(COMMA, SEMI)) return(FALSE); 
+      if (__toktyp == SEMI) return(TRUE);
+      goto nxt_wire;
+     }
+   }
+
+   /* set implied range for time and integer */
+   /* each time through need to call this to make copy */
+   if (ox1 == NULL) set_reg_widths(wtyp, &x1, &x2);
+   else if (first_time) { x1 = ox1; x2 = ox2; }
+   else { x1 = __copy_expr(ox1); x2 = __copy_expr(ox2); }
+
+   /* must skip to ending ; here since cannot decl. any of list */
+   /* and lack information to read rest of this decl. */ 
+   if ((np = __decl_wirereg(wtyp, x1, x2, NULL)) == NULL)
+    {
+     /* resync at , or ; - should succeed */
+try_resync:
+     if (!__vskipto2_any(COMMA, SEMI)) return(FALSE); 
+     if (__toktyp == SEMI) return(TRUE);
+     goto nxt_wire;
+    }
+   /* if previously used will be treated as reg - must set to compatible */
+   /* wire type if declared as time or int32 */
+   np->ntyp = wtyp;
+   syp = np->nsym;
+
+   /* SJM - 03/20/00 - save wire decl attrs */
+   /* if saw an (* *) attribute for module item token, seen on */
+   if (has_attr)
+    {
+     /* add to end if I/O decl seen first for ports - still on net not port */
+     add_net_attr(np, WIRE);
+    }
+
+   /* different array range expr. for every array */
+   __get_vtok();
+   if (!__rd_decl_rng(&xm1, &xm2))
+    {
+     if (!__vskipto2_any(SEMI, RSB)) return(FALSE); 
+     if (__toktyp == SEMI) return(TRUE);
+     __get_vtok();
+    }
+   if (xm1 != NULL && (wtyp < NONWIRE_ST || wtyp == N_EVENT))
+    {
+     __pv_ferr(1003, "%s %s cannot be an array", __to_wtnam2(s1, wtyp),
+      syp->synam);
+     xm1 = xm2 = NULL;
+    }
+   if (pmphdr != NULL && wtyp >= NONWIRE_ST)
+    {
+     __pv_ferr(1004,
+      "%s %s not a wire - cannot have delay(s)", __to_wtnam2(s1, wtyp),
+      syp->synam);
+     pmphdr = NULL;
+    }
+   if (xm1 != NULL)
+    { np->n_isarr = TRUE; np->nu.ct->ax1 = xm1; np->nu.ct->ax2 = xm2; }
+   np->nu.ct->n_spltstate = split_state;
+
+   /* SJM 10/02/03 - now signed keyword or int real implies signed */
+   /* must not turn off since if port and turned on there, stays on */
+   if (decl_signed) np->n_signed = TRUE;
+
+   /* AIV 09/29/04 - now if there is an = not necessarily a cont assgn */
+   /* could be a variable initialization i.e. integer i = 12; */
+   if (__toktyp == EQ)
+    {
+     if (np->ntyp >= NONWIRE_ST)
+      {
+       /* cannot init an array - illegal syntax */
+       if (np->n_isarr)  
+        {
+         __pv_ferr(3429,
+          "variable assign initialize form illegal for %s - arrays cannot be initialized",
+          syp->synam); 
+         goto try_resync;
+        }
+       if (!rdbld_mod_varinitlst(syp)) goto try_resync;
+      }
+     else if (!do_wdecl_assgn(syp, pmphdr, first_time)) goto try_resync;
+    }
+   else
+    {
+     /* copying delay list here since gets freed and converted later */
+     if (first_time) np->nu.ct->n_dels_u.pdels = pmphdr;
+     else np->nu.ct->n_dels_u.pdels = __copy_dellst(pmphdr);
+     /* know strength good or will be turned off by here */
+     if (__v0stren != NO_STREN)
+      {
+       if (wtyp == N_TRIREG)
+        {
+         /* know capacitor strength already checked */
+         np->n_capsiz = __to_cap_size(__v0stren);
+        } 
+       else chk_drvstren(wtyp);
+      }
+     /* set trireg default to medium (always needed) */
+     else if (wtyp == N_TRIREG) np->n_capsiz = CAP_MED;  
+    }
+
+nxt_wire:
+   if (first_time) first_time = FALSE;
+   if (__toktyp == SEMI) break;
+   if (__toktyp != COMMA)
+    {
+     __pv_ferr(1005,
+      "wire declaration comma separator or semicolon expected - %s read",
+      __prt_vtok());
+     /* try to resync */
+     if (!__vskipto2_any(COMMA, SEMI)) return(FALSE); 
+     if (__toktyp == SEMI) break;
+    }
+   __get_vtok();
+   first_time = FALSE;
+  }
+ return(TRUE);
+}
+
+/*
+ * check cap. wire declaration strength - no strength appeared
+ */
+static void chk_capwdecl_strens(word32 wtyp)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ if (!__is_capstren(__v0stren))
+  {
+   if (wtyp == N_TRIREG)
+    {
+     __pv_ferr(1006,
+      "trireg wire declaration non capacitor size strength %s illegal",
+      __to_stren_nam(s1, __v0stren, __v1stren));
+     __v0stren = __v1stren = NO_STREN;
+    }
+   return;
+  }
+ /* know this is cap. strenght */
+ if (wtyp != N_TRIREG)
+  {
+   __pv_ferr(1007,
+   "non trireg wire type %s declaration has illegal capacitor size strength \"%s\"",
+    __to_wtnam2(s1, wtyp), __to_stren_nam(s2, __v0stren, __v1stren));
+   __v0stren = __v1stren = NO_STREN;
+  }
+}
+
+/*
+ * know non assign wire decl. has strength - emit error
+ */
+static void chk_drvstren(word32 wtyp)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ /* SJM 04/17/03 - must not use stren to string routine if not set in src */
+ if (__v0stren == 0 || __v1stren == 0)
+  {
+   __pv_ferr(1008,
+    "%s declaration required tow driving strengths not present in non wire assign form",
+    __to_wtnam2(s1, wtyp));
+  }
+ else
+  {
+   __pv_ferr(1008,
+    "%s declaration driving strength \"%s\" illegal in non wire assign form",
+     __to_wtnam2(s1, wtyp), __to_stren_nam(s2, __v0stren, __v1stren));
+  }
+ __v0stren = __v1stren = NO_STREN;
+}
+
+
+/*
+ * get old style only implicit # type parameters i.e. delay expr. list
+ *
+ * know # read (if needs to be present) and reads one past end
+ * builds a parameter/delay list and returns pointer to header
+ * this routine for # form and path delay () list (no #) only
+ * specparam and deparam rhs no # or ( ok
+ * error if #() 
+ *
+ * this routine returns F on sync error - caller must resync
+ * but in places with known delimiter attempt to resync to delim 
+ */
+static int32 rd_oparamdels(struct paramlst_t **pmphdr)
+{
+ struct paramlst_t *pmp, *last_pmp;
+
+ *pmphdr = NULL;
+ /* this is #[number] or #id - not (..) form - min:typ:max requires () */
+ /* for path delay will never see this form */
+ __get_vtok();
+ if (__toktyp != LPAR)
+  {
+   /* notice must surround m:t:m with () */
+   if (__toktyp != ID && __toktyp != NUMBER && __toktyp != REALNUM)
+    {
+     __pv_ferr(1049,
+     "non parenthesized delay parameter name or number expected - %s read",
+      __prt_kywrd_vtok());
+     return(FALSE);
+    }
+   __last_xtk = -1;
+   /* on error, set as error expr. - maybe since param should be 0 */
+   if (!__bld_expnode()) __set_xtab_errval();
+   /* here does the allocating */
+   __bld_xtree(0);
+   pmp = __alloc_pval();
+   pmp->plxndp = __root_ndp;
+   pmp->pmlnxt = NULL;
+   *pmphdr = pmp;
+  }
+ else
+  {
+   /* #(...) form */
+   for (last_pmp = NULL;;)
+    {
+     __get_vtok();
+     if (!__col_delexpr())
+      {
+       if (!__vskipto3_modend(COMMA, RPAR, SEMI)) return(FALSE);
+       if (__toktyp == SEMI) return(FALSE);
+      }       
+     __bld_xtree(0);
+     pmp = __alloc_pval();
+     pmp->plxndp = __root_ndp;
+
+     /* link on front */
+     if (last_pmp == NULL) *pmphdr = pmp; else last_pmp->pmlnxt = pmp;
+     last_pmp = pmp;
+
+     if (__toktyp == COMMA) continue;
+     if (__toktyp == RPAR) break;
+     /* should never happen - sync on err above, if does give up */
+     __pv_ferr(1050,
+      "delay parameter list comma or right parenthesis expected - %s read",
+      __prt_vtok());
+     return(FALSE);
+    }
+  }
+ __get_vtok();
+ return(TRUE);
+}
+
+/*
+ * allocate a # style parameter value (also for specify delays)
+ */
+extern struct paramlst_t *__alloc_pval(void)
+{
+ struct paramlst_t *pmp;
+
+ pmp = (struct paramlst_t *) __my_malloc(sizeof(struct paramlst_t));
+ pmp->plxndp = NULL;
+ pmp->pmlnxt = NULL;
+ return(pmp);
+}
+
+/*
+ * process a wire decl. assign
+ * notice # delays and strengths are put into globals
+ * also notice wire values in this case moved here no wire delay
+ */
+static int32 do_wdecl_assgn(struct sy_t *syp, struct paramlst_t *pmphdr,
+ int32 first_time)
+{
+ struct conta_t *cap;
+ struct expr_t *lhs_ndp;
+ int32 sfnind, slcnt;
+
+ /* need lhs wire as location of conta */
+ sfnind = syp->syfnam_ind;
+ slcnt = __lin_cnt;
+ /* wire decl. form continuous assignment */
+ /* generate expression from node that is simply wire name */
+ lhs_ndp = __gen_wireid_expr(syp);
+ /* collect rhs and build expression tree */
+ __get_vtok();
+ if (!__col_comsemi(-1)) return(FALSE);
+ __bld_xtree(0);
+ cap = add_conta(lhs_ndp, __root_ndp, sfnind, slcnt);
+ /* uses wire decl delay and strength */
+ if (first_time) cap->ca_du.pdels = pmphdr;
+ else cap->ca_du.pdels = __copy_dellst(pmphdr);
+ if (__v0stren != NO_STREN) 
+  {
+   cap->ca_hasst = TRUE;
+   cap->ca_stval = ((__v0stren << 3) | __v1stren) & 0x3f;
+  }
+ return(TRUE);
+}
+
+/*
+ * read the initialize to expr and add to mod's var init list 
+ * format example: reg r = 12;
+ *
+ * build the net and expr pair lists here - check to make sure constant
+ * expr during fixup and initialize as first sim step in pv_sim
+ *
+ * notice can't check the constant expr here since parameter decl may 
+ * follow in source order
+ */
+static int32 rdbld_mod_varinitlst(struct sy_t *syp)
+{
+ struct varinitlst_t *initp;
+
+ /* collect rhs and build expression tree */
+ __get_vtok();
+ if (!__col_comsemi(-1)) return(FALSE);
+ __bld_xtree(0);
+
+ initp = (struct varinitlst_t *) __my_malloc(sizeof(struct varinitlst_t));
+ initp->init_syp = syp;
+ initp->init_xp = __root_ndp;
+ initp->varinitnxt = NULL;
+
+ if (__end_mod_varinitlst == NULL) __inst_mod->mvarinits = initp;
+ else __end_mod_varinitlst->varinitnxt = initp;
+ __end_mod_varinitlst = initp;
+
+ return(TRUE);
+}
+
+/*
+ * add the wire type decl. symbol and associated wire/reg
+ *
+ * caller must set wire type after checking for duplicates
+ * for declares only at top level
+ * need null ranges for real, width set later or special case
+ * returns null on error
+ * x1 and x2 passed must be copies for multiple decls in one stmt case 
+ *
+ * for non vendor 1 specific dsyp will always be nil
+ */
+extern struct net_t *__decl_wirereg(word32 wtyp, struct expr_t *x1,
+ struct expr_t *x2, struct sy_t *dsyp)
+{
+ struct net_t *np;
+ struct sy_t *syp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ /* this find and sets type for already read and processed I/O port decl. */
+ syp = __decl_sym(__token, __venviron[0]);
+ if (__sym_is_new)
+  {
+   np = __add_net(syp);
+   np->iotyp = NON_IO;
+   np->ntyp = wtyp;
+   if (x1 != NULL)
+    { np->n_isavec = TRUE; np->nu.ct->nx1 = x1; np->nu.ct->nx2 = x2; }
+  }
+ else
+  {
+   if (syp->sytyp != SYM_N)
+    {
+     __pv_ferr(1028,
+      "cannot declare %s as %s - previously declared as %s at %s",
+      syp->synam, __to_wtnam2(s2, wtyp), __to_wtnam2(s1, syp->sytyp),
+      __bld_lineloc(__xs, syp->syfnam_ind, syp->sylin_cnt));
+     return(NULL);
+    }
+
+   /* wire/reg decl. after I/O decl. may set range */
+   np = syp->el.enp;
+   /* need special handling for module I/O ports - declared in header, */
+   /* I/O direction and maybe wire */
+   if (np->iotyp != NON_IO)
+    {
+     /* if wire decl. for I/O port use it */
+     /* any wire type, reg, int32, and time ok here, but not real or event */
+     if (wtyp == N_REAL || wtyp == N_EVENT)
+      {
+       __pv_ferr(1009,
+        "%s port %s %s illegal", __to_ptnam(s1, np->iotyp), syp->synam,
+        __to_wtnam2(s2, wtyp));
+       return(NULL);
+      }
+     /* this only has meaning for I/O port redecls */
+     if (np->nu.ct->n_wirtypknown)
+      {
+       if (dsyp == NULL)
+        {
+         __pv_ferr(1010,
+          "%s port %s previously declared as %s cannot be %s",
+	  __to_ptnam(s1, np->iotyp), syp->synam, __to_wtnam(s2, np),
+	  __to_wtnam2(s3, wtyp));
+        }
+       else
+        {
+         __pv_ferr(1010,
+          "%s port %s previously declared as %s - unknown: %s",
+	  __to_ptnam(s1, np->iotyp), syp->synam, __to_wtnam(s2, np),
+          dsyp->synam);
+        }
+       return(NULL);
+      }
+     np->ntyp = wtyp;
+    }
+   else
+    {
+     if (is_decl_err(syp, SYM_N, wtyp)) return(NULL);
+     /* must set wire type - may override guessed wire type from use */  
+     np->ntyp = wtyp;
+    }
+   if (!chkset_wdrng(np, x1, x2)) return(NULL);
+   np->nu.ct->n_wirtypknown = TRUE;
+  }
+ /* port header wire, require I/O port dir. decl., else this is decl. */
+ if (np->iotyp == NON_IO)
+  {
+   syp->sydecl = TRUE;
+   /* even if used before, must set to declaration place */
+   syp->syfnam_ind = __cur_fnam_ind;
+   syp->sylin_cnt = __lin_cnt;
+  }
+ return(np);
+}
+
+/*
+ * allocate a new net for a symbol that is just seen for first time
+ */
+extern struct net_t *__add_net(struct sy_t *syp)
+{
+ struct net_t *np;
+
+ np = (struct net_t *) __my_malloc(sizeof(struct net_t));
+ np->nsym = syp;
+ /* allocate during compilation part - free and change to storage later */
+ np->nrngrep = NX_CT;
+ np->nu.ct = (struct ncomp_t *) __alloc_arrncomp();
+ /* also initialize */
+ np->nu.ct->nx1 = np->nu.ct->nx2 = NULL;
+ np->nu.ct->ax1 = np->nu.ct->ax2 = NULL;
+ np->nu.ct->n_pb_drvtyp = NULL;
+ np->nu.ct->n_drvtyp = DRVR_NONE;
+ np->nu.ct->n_dels_u.pdels = NULL;
+ np->nu.ct->n_iotypknown = FALSE;
+ np->nu.ct->n_wirtypknown = FALSE;
+ np->nu.ct->n_rngknown = FALSE;
+ np->nu.ct->n_impldecl = FALSE;
+ np->nu.ct->n_in_giarr_rng = FALSE;
+ np->nu.ct->n_onrhs = FALSE;
+ np->nu.ct->n_onlhs = FALSE;
+ np->nu.ct->n_2ndonlhs = FALSE;
+ np->nu.ct->num_prtconns = 0;
+ /* this is default implies word32 a/b type also for reals */
+ np->srep = SR_VEC;
+
+ /* fields for parameters only */
+ np->nu.ct->n_widthdet = FALSE;
+ np->nu.ct->n_indir_widthdet = FALSE;
+ np->nu.ct->p_specparam = FALSE;
+ np->nu.ct->p_rhs_has_param = FALSE;
+ np->nu.ct->p_locparam = FALSE;
+ np->nu.ct->p_setby_defpnd = FALSE;
+ np->nu.ct->prngdecl = FALSE;
+ np->nu.ct->ptypdecl = FALSE;
+ np->nu.ct->psigndecl = FALSE;
+ np->nu.ct->parm_srep = SR_VEC;
+ np->nu.ct->pbase = BNONE;
+ np->nu.ct->pstring = FALSE;
+
+ /* init fields for comiled sim */
+ np->nu.ct->frc_assgn_in_src = FALSE;
+ np->nu.ct->monit_in_src = FALSE;
+ np->nu.ct->dmpv_in_src = FALSE;
+
+ /* assumes normal wire e when in header these will be changed */
+ np->iotyp = NON_IO;
+ np->n_isaparam = FALSE;
+ np->n_isavec = FALSE;
+ np->nwid = 0;
+ np->n_isarr = FALSE;
+ /* cap. strength of non cap. strength strong is no cap. strength */
+ np->n_capsiz = CAP_NONE;
+ np->n_signed = FALSE;
+ np->nu.ct->n_iscompleted = FALSE;
+ np->nu.ct->n_spltstate = SPLT_DFLT;
+ /* this gets sets in v_prep if vector - vectored is scalared */
+ np->vec_scalared = TRUE;
+ np->n_stren = FALSE;
+ np->n_mark = FALSE;
+ np->n_multfi = FALSE;
+ np->n_isapthsrc = FALSE;
+ np->n_isapthdst = FALSE;
+ np->n_hasdvars = FALSE;
+ np->n_onprocrhs = FALSE;
+ np->n_gone = FALSE;
+ np->nchg_nd_chgstore = FALSE;
+ np->nchg_has_dces = FALSE;
+ np->nchg_has_lds = FALSE;
+ /* 03/21/01 - these are fields from removed separate optim table */ 
+ np->frc_assgn_allocated = FALSE;
+ np->dmpv_in_src = FALSE;
+ np->monit_in_src = FALSE;
+ np->n_onrhs = FALSE;
+ np->n_onlhs = FALSE;
+ np->n_drvtyp = DRVR_NONE;
+ np->dcelst = NULL;
+ np->ndrvs = NULL;
+ np->nlds = NULL;
+ np->ntraux = NULL;
+ np->nchgaction = NULL;
+ np->vpi_ndrvs = NULL;
+ np->regwir_putv_tedlst = NULL;
+ np->nva.wp = NULL;
+ np->nu2.nnxt = NULL;
+ np->nattrs = NULL;
+ syp->sytyp = SYM_N;
+ syp->el.enp = np;
+ /* assume reg */
+ np->ntyp = N_REG;
+ return(np);
+}
+
+/*
+ * allocate a ncomp element from a preallocated block for fast freeing
+ */
+extern struct ncomp_t *__alloc_arrncomp(void)
+{
+ struct ncablk_t *ncabp;
+ struct ncomp_t *ncmp;
+
+ if (__ncablk_nxti == -1)
+  {
+   ncabp = (struct ncablk_t *) __my_malloc(sizeof(struct ncablk_t));
+   ncabp->ancmps = (struct ncomp_t *) __my_malloc(BIG_ALLOC_SIZE);
+   ncabp->ncablknxt = __hdr_ncablks;
+   __hdr_ncablks = ncabp;
+   __ncablk_nxti = 0;
+  }
+ ncmp = (struct ncomp_t *) &(__hdr_ncablks->ancmps[__ncablk_nxti]);
+ if (++__ncablk_nxti > ((BIG_ALLOC_SIZE/sizeof(struct ncomp_t)) - 1))
+  __ncablk_nxti = -1;
+ return(ncmp);
+}
+
+/*
+ * print message and return true if declaration error
+ * called for declaration when symbol is not new
+ * for symbols that are like variables
+ */
+static int32 is_decl_err(struct sy_t *syp, word32 dclsytyp,
+ word32 dclwtyp)
+{
+ struct net_t *np;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (syp->sytyp == SYM_N) np = syp->el.enp; else np = NULL;
+ /* symbol already declared */
+ /* see if declaration repeated */
+ if (syp->sydecl || syp->sytyp != dclsytyp)
+  {
+   /* current symbol */
+   if (np != NULL) __to_wtnam(s1, np); else __to_sytyp(s1, syp->sytyp);
+   /* declared type */
+   if (dclsytyp == SYM_N) __to_wtnam2(s2, dclwtyp);
+   else __to_sytyp(s2, dclsytyp);
+
+   if (syp->sydecl) strcpy(s3, "declared"); else strcpy(s3, "used");
+   __pv_ferr(1014, "%s %s previously %s as %s at %s", s2, syp->synam,
+    s3, s1, __bld_lineloc(__xs, syp->syfnam_ind, syp->sylin_cnt));
+   return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * set a register width
+ */
+static void set_reg_widths(word32 wtyp, struct expr_t **x1,
+ struct expr_t **x2)
+{
+ word32 rhigh;
+
+ if (wtyp == N_INT) rhigh = WBITS - 1;
+ else if (wtyp == N_TIME) rhigh = TIMEBITS - 1;
+ else if (wtyp == N_REAL) rhigh = REALBITS - 1; 
+ else { *x1 = NULL; *x2 = NULL; return; }
+ *x1 = __bld_rng_numxpr(rhigh, 0L, WBITS);
+ *x2 = __bld_rng_numxpr(0L, 0L, WBITS);
+}
+
+/*
+ * for constant predefined ranges need to build a number expr. 
+ * so param substitution and folding will work but do nothing
+ *
+ * LOOKATME - siz must be <= WBITS so why pass it 
+ */
+extern struct expr_t *__bld_rng_numxpr(word32 av, word32 bv, int32 siz)
+{
+ struct expr_t *ndp;
+
+ /* this also initializes node */
+ ndp = __alloc_newxnd();
+ __set_numval(ndp, av, bv, siz);
+ return(ndp);
+}
+
+/*
+ * check and possibly set wire range
+ */
+static int32 chkset_wdrng(struct net_t *np, struct expr_t *x1,
+ struct expr_t *x2)
+{
+ int32 cval;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ /* know range - either previous I/O or wire decl. with range */
+ if (np->nu.ct->n_rngknown)
+  {
+   if (x1 == NULL) return(TRUE);
+   if (np->nu.ct->nx1 != NULL)
+    cval = cmp_rng(x1, x2, np->nu.ct->nx1, np->nu.ct->nx2);
+   else cval = 1;
+   if (cval != 0)
+    {
+     __to_wrange(s2, np);
+     __pv_fwarn(568,
+     "%s port %s declaration range %s mismatch with port range %s",
+      __to_wtnam(s1, np), np->nsym->synam,
+      __msgtox_wrange(s3, x1, x2), s2);
+    }
+   return(TRUE);
+  }
+ if (x1 != NULL)
+  {
+   np->nu.ct->n_rngknown = TRUE;
+   np->n_isavec = TRUE;
+   np->nu.ct->nx1 = x1;
+   np->nu.ct->nx2 = x2;
+  }
+ return(TRUE);
+}
+
+/*
+ * compare 2 range exprs during compilation - before params known
+ * equal if same known numbers (or numeric expr.) or if exprs the same
+ */
+static int32 cmp_rng(struct expr_t *x1, struct expr_t *x2,
+ struct expr_t *nx1, struct expr_t *nx2)
+{
+ if (!__cmp_xpr(x1, nx1)) return(1);
+ if (!__cmp_xpr(x2, nx2)) return(1);
+ return(0);
+}
+
+/*
+ * compare 2 expressions for identicalness
+ * if incorrect real, same and error caught later
+ */
+extern int32 __cmp_xpr(struct expr_t *nx, struct expr_t *ox)
+{
+ int32 retval, owlen, nwlen;
+ word32 *owp, *nwp;
+
+ switch ((byte) nx->optyp) { 
+  case NUMBER:
+   if (ox->optyp != NUMBER) return(FALSE);
+   owlen = wlen_(ox->szu.xclen); 
+   nwlen = wlen_(nx->szu.xclen); 
+   /* since implied assignment to 32 bit value - just use low words */
+   owp = &(__contab[ox->ru.xvi]); 
+   nwp = &(__contab[nx->ru.xvi]); 
+   if (owp[0] != nwp[0]) return(FALSE); 
+   if (owp[owlen] != nwp[nwlen]) return(FALSE);
+   break;
+  case ID:
+   /*FALLTHRU */
+  case GLBREF:
+   if (ox->lu.sy != nx->lu.sy) return(FALSE);
+   break;
+  default:
+   if (ox->optyp != nx->optyp) return(FALSE);
+   retval = TRUE;
+   if (ox->lu.x != NULL) retval = __cmp_xpr(nx->lu.x, ox->lu.x); 
+   if (!retval) return(FALSE);
+   if (ox->ru.x != NULL) retval = __cmp_xpr(nx->ru.x, ox->ru.x); 
+   return(retval);
+ }
+ return(TRUE);
+}
+
+/*
+ * get optional strengths
+ * know first strength read and reads one past ending )
+ * can be cap size or strength pair - because of cont. assignments gets
+ * checked later
+ * set globals __v0stren and __v1stren
+ */
+static int32 rd_verstrens(void)
+{
+ int32 strentyp;
+
+ __v0stren = __v1stren = NO_STREN;
+ /* this sets __v0stren and __v1stren F means structural problem */
+ if (!rd_1verstren(&strentyp)) return(FALSE);
+ /* returned T and 2nd strength null means cap. size */
+ if (strentyp == CAP_STREN) { __get_vtok(); return(TRUE); }
+ if (__toktyp == RPAR)
+  {
+   __pv_ferr(1015,
+    "required 2nd drive strength missing - %s read", __prt_vtok());
+   return(FALSE);
+  }
+
+ /* know comma read to get here */
+ __get_vtok();
+ if (!rd_1verstren(&strentyp)) return(FALSE);
+ if (__toktyp == COMMA)
+  {
+   __pv_ferr(1016, "strength list has more than 2 strengths");
+   return(FALSE);
+  }
+ __get_vtok();
+ if (__v0stren == NO_STREN || __v1stren == NO_STREN)
+  {
+   __pv_ferr(1017, "0 or 1 transition strength repeated (other missing)");
+   if (__v0stren == NO_STREN) __v0stren = __v1stren;
+   else __v1stren = __v0stren;
+  }
+ if (__v0stren == ST_HIGHZ && __v1stren == ST_HIGHZ)
+  {
+   __pv_ferr(1018, "(highz0, highz1) strength illegal");
+   __v0stren = __v1stren = NO_STREN;
+  }
+ else if (__v0stren == ST_STRONG && __v1stren == ST_STRONG)
+  {
+   __finform(424,
+    "explicit (strong0, strong1) removed to speed up simulation"); 
+   __v0stren = __v1stren = NO_STREN;
+  }
+ return(TRUE);
+}
+
+
+/*
+ * get 1 strength - know leading '(' and strength read
+ * reads ending ')' or ',', sets __v1stren and __v0stren
+ *
+ * notice this returns symbolic constant that is strength type set either
+ * __v0stren or __v1stren depending on token type
+ * returns F on token error else F, if bad sets to none
+ */
+static int32 rd_1verstren(int32 *strentyp)
+{
+ int32 strenval;
+
+ *strentyp = NO_STREN;
+ if ((*strentyp = is_tokstren(__toktyp)) == CAP_STREN)
+  {
+   strenval = __fr_stren_nam(__toktyp);
+   __get_vtok();
+   if (__toktyp != RPAR)
+    {
+     __pv_ferr(1019, "trireg charge strength ending ')' expected - %s read",
+      __prt_vtok());
+     return(FALSE);
+    }
+   __v0stren = strenval;
+   return(TRUE);
+  }
+ if (*strentyp == LOW_STREN)
+  {
+   if (__v0stren != NO_STREN)
+    __pv_fwarn(569, "both strengths are 0 transition - 2nd changed");
+   __v0stren = __fr_stren_nam(__toktyp);
+  }
+ else if (*strentyp == HIGH_STREN)
+  {
+   if (__v1stren != NO_STREN)
+    __pv_fwarn(569, "both strengths are 1 transition - 2nd changed");
+   __v1stren = __fr_stren_nam(__toktyp);
+  }
+ else
+  {
+   __pv_ferr(1020, "expected strength missing - %s read", __prt_vtok());
+   return(FALSE);
+  }
+ __get_vtok();
+ if (__toktyp != COMMA && __toktyp != RPAR)
+  {
+   __pv_ferr(1021,
+    "strength not followed by comma or right parenthesis - %s read",
+    __prt_vtok());
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * determine if token type strength and whether 0 or 1 group
+ */
+static int32 is_tokstren(int32 ttyp)
+{
+ switch ((byte) ttyp) {
+  case SUPPLY0: case STRONG0: case PULL0: case WEAK0: case HIGHZ0:
+   return(LOW_STREN);
+  case SUPPLY1: case STRONG1: case PULL1: case WEAK1: case HIGHZ1:
+   return(HIGH_STREN);
+  case SMALL: case MEDIUM: case LARGE:
+   return(CAP_STREN);
+ }
+ return(NO_STREN);
+}
+
+/*
+ * read the parameter statement (declares the parameter)
+ * form: parameter [name] = [value], [name] = [value], ...;
+ * where name is a simple id and [value] is a constant expr.
+ *
+ * no # or () around delay in parameter decl. but min:typ:max form
+ * needs () since rhs is constant expr. in grammar not mintypmax expr.
+ *
+ * if returns F synced to next module, else synced to SEMI
+ *
+ * also reads vendor1 specific param types
+ *
+ * SJM 10/07/03 - add optional signed declaration - following normal
+ * rule for parameter typing, if signed not present determined from rhs
+ *
+ * SJM 05/25/04 - added new P1364 module #(<param decl>, ...) form but only 
+ * for modules parameter declarations and unlike header list of ports both
+ * types can be combined 
+ */
+static int32 rd_paramdecl(int32 is_hdr_form)
+{
+ int32 ptyp_decl, prng_decl, pwtyp, pwid, r1, r2, wlen;
+ int32 psign_decl; 
+ word32 *wp;
+ struct expr_t *dx1, *dx2, *x1, *x2, *ax1, *ax2;
+ struct net_t *np;
+ struct xstk_t *xsp;
+ char paramnam[IDLEN], ptnam[RECLEN];
+
+ strcpy(ptnam, "parameter");
+
+ dx1 = dx2 = x1 = x2 = ax1 = ax2 = NULL;
+ ptyp_decl = FALSE; 
+ prng_decl = FALSE;
+ pwtyp = -1;
+ pwid = 0;
+ psign_decl = FALSE; 
+ __get_vtok();
+ if (__toktyp == SIGNED)
+  {
+   psign_decl = TRUE;
+   __get_vtok();
+  }
+
+ /* case 1: range but not decl type */
+ if (__toktyp == LSB)
+  {
+   /* also check to make sure ranges are non x/z 32 bit values */
+   if (!__rd_opt_param_vec_rng(&dx1, &dx2, is_hdr_form)) return(FALSE);
+   if (dx1 == NULL || dx2 == NULL) goto rd2_param_list;
+
+   r1 = (int32) __contab[dx1->ru.xvi];
+   r2 = (int32) __contab[dx2->ru.xvi];
+   pwid = (r1 >= r2) ? r1 - r2 + 1 : r2 - r1 + 1; 
+   pwtyp = N_REG;
+   x1 = dx1; x2 = dx2;
+   prng_decl = TRUE;
+   /* DBG remove --- */
+   if (x1 == NULL) goto rd_param_list;
+   /* --- */
+   /* know parameter name read */
+   goto rd2_param_list;
+  }
+
+ /* if next token not optional - if range, implied reg type */ 
+ if ((pwtyp = __fr_wtnam(__toktyp)) == -1)
+  {
+   pwtyp = N_REG;
+   x1 = dx1; x2 = dx2;
+   /* implied decl as range */  
+   if (x1 != NULL) ptyp_decl = TRUE;
+   goto rd2_param_list; 
+  }
+ else
+  {
+   if (pwtyp == N_EVENT || pwtyp < NONWIRE_ST)
+    {
+     __pv_ferr(685, "%s declaration illegal type %s", ptnam, __prt_vtok());
+     x1 = x2 = NULL;
+     pwtyp = N_REG;
+     goto rd_param_list;
+    }
+
+   ptyp_decl = TRUE; 
+   switch ((byte) pwtyp) {
+    case N_REAL:
+     pwid = REALBITS;
+     goto chk_norng;
+    case N_TIME:
+     pwid = TIMEBITS;
+     goto chk_norng;
+    case N_INT:
+     pwid = WBITS;
+chk_norng:
+     if (dx1 != NULL)
+      {
+       __pv_ferr(686, "%s declaration range illegal for opt_type %s",
+        ptnam, __to_wtnam2(__xs, (word32) pwtyp));
+      }
+     x1 = __bld_rng_numxpr(pwid - 1, 0L, WBITS);
+     x2 = __bld_rng_numxpr(0L, 0L, WBITS);
+     prng_decl = FALSE;
+     break;
+    default:
+     __case_terr(__FILE__, __LINE__);
+     return(FALSE);
+   }
+  }
+
+rd_param_list:
+ __get_vtok();
+rd2_param_list:
+ /* SJM 10/06/03 - signed keyword not allowed with var types */
+ if (psign_decl && (pwtyp == N_TIME || pwtyp == N_INT || pwtyp == N_REAL))
+  {
+   __pv_ferr(3423,
+    "signed keyword illegal when parameter variable type %s",
+    __to_wtnam2(__xs, pwtyp));
+   psign_decl = FALSE;
+  }
+
+ /* if ptyp decl F, then must attempt to determine param type from rhs */ 
+ for (;;)
+  {
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1023,
+      "%s declaration parameter name expected - %s read", ptnam,
+      __prt_kywrd_vtok());
+bad_end:
+     /* part of delay expression may have been built */
+     if (!is_hdr_form)
+      {
+       if (!__vskipto2_any(COMMA, SEMI)) return(FALSE);
+       if (__toktyp == COMMA) { __get_vtok(); continue; }
+      }
+     else
+      {
+       if (!__vskipto2_any(COMMA, RPAR)) return(FALSE); 
+       if (__toktyp == COMMA) { __get_vtok(); continue; }
+      }
+     return(TRUE);
+    }
+   strcpy(paramnam, __token);
+
+   /* notice the initial value is required */
+   __get_vtok();
+   /* parameter arrays now but only declarator present legal */
+   /* also range for arrays must be repeated for each one */ 
+   if (__toktyp == LSB)
+    {
+     /* also check to make sure ranges are non x/z 32 bit values */
+     if (!rd_opt_param_array_rng(&ax1, &ax2, is_hdr_form)) return(FALSE);
+    }
+   if (ax1 != NULL && !ptyp_decl)
+    {
+     __pv_ferr(687,
+      "parameter array %s illegal - explicit type declaration required for parameter arrays",
+      paramnam); 
+     /* notice not freeing expr. memory on syntax error */ 
+     ax1 = ax2 = NULL;
+    }
+
+   if (__toktyp != EQ)
+    {
+     __pv_ferr(1024,
+      "%s declaration equal expected - %s read", ptnam, __prt_vtok());
+     goto bad_end;
+    }
+
+   /* notice initial value required */
+   __get_vtok();
+   /* this can collect array construct that will look like concat */
+   if (is_hdr_form)
+    {
+     /* SJM 05/26/04 - new module decl #(list of param decls) form needs */
+     /* different collect routine because semi illegal */
+     if (!__col_lofp_paramrhsexpr()) goto bad_end;
+    }
+   else
+    {
+     if (!__col_newparamrhsexpr()) goto bad_end;
+    }
+   __bld_xtree(0);
+
+   if (__has_top_mtm)
+    {
+     __pv_fwarn(652,
+      "%s %s declaration min:typ:max expression needs parentheses under 1364 - unportable",
+      ptnam, paramnam);
+    }
+
+   /* handle parameter arrays as special case */
+   if (ax1 != NULL)
+    {
+     /* warning if parameter array used */
+     __pv_fwarn(643,
+      "parameter array %s enhancement - not part of P1364 standard",
+      paramnam);
+     /* notice range and type for all in possible param list but */
+     /* array range and initializer different for each */
+     /* if error returns nil and try to resync */
+     if ((np = chkadd_array_param(paramnam, pwtyp, pwid, psign_decl, x1, x2,
+       ax1, ax2))
+       == NULL) goto bad_end;
+
+     goto nxt_param;
+    }
+
+
+   /* checking rhs does no evaluation but set sizes and checks for */
+   /* only params that are defined previously in module */
+   /* SJM 10/06/03 - rd chk paramexpr routine set expr signed bit */
+   if (__expr_has_glb(__root_ndp) || !__src_rd_chk_paramexpr(__root_ndp, 0))
+    {
+     __pv_ferr(1025,
+      "%s %s declaration right hand side \"%s\" error - defined %ss and constants only",
+      ptnam, paramnam, __msgexpr_tostr(__xs, __root_ndp), ptnam);
+     /* need to still add value of x to prevent further errors */
+     __free2_xtree(__root_ndp);
+     __root_ndp->szu.xclen = WBITS;
+     __set_numval(__root_ndp, ALL1W, ALL1W, WBITS);  
+     /* SJM 03/15/00 - on err if decl as real - must convert to non real */
+     if (pwtyp == N_REAL) pwtyp = N_REG;
+    }
+
+   /* check and links on modules parameter list */
+   /* when rhs expr. evaluated, if real will change */
+   /* LOOKATME - problem with all params in list sharing range xprs? */ 
+   /* SJM 01/24/00 - works since for globalparam runs in virt glb param mod */
+   if ((np = __add_param(paramnam, x1, x2)) == NULL) return(FALSE);
+
+   /* require that at this point all param rhs expressions are numbers */
+   /* know possible and needed for copying and later defparam assign */
+   /* rule from LRM is that all param initial values known when first read */
+   xsp = __src_rd_eval_xpr(__root_ndp);
+
+   /* case parameter type declared - maybe convert - must eval before here */
+   /* if range, implied pwtyp set to reg type */
+   if (ptyp_decl || prng_decl)
+    {
+     if (pwtyp == N_REAL)
+      {
+       np->ntyp = N_REAL; 
+       np->n_signed = TRUE;
+       np->nwid = REALBITS;
+       np->nu.ct->pbase = BDBLE;
+       if (!__root_ndp->is_real)
+        __src_rd_cnv_stk_fromreg_toreal(xsp, (__root_ndp->has_sign == 1));
+      }
+     else
+      {
+       np->ntyp = pwtyp;
+       /* if declared always know width */
+       np->nwid = pwid;
+       if (np->ntyp == N_INT || (np->ntyp == N_REG && psign_decl))
+        np->n_signed = TRUE;
+
+       /* even if declared use rhs expr. for param ncomp expr formats */
+       if (__root_ndp->is_string) np->nu.ct->pstring = TRUE;
+       np->nu.ct->pbase = __root_ndp->ibase;
+
+       /* convert declared param type real rhs to int/reg */
+       if (__root_ndp->is_real)
+        {
+         __src_rd_cnv_stk_fromreal_toreg32(xsp);
+         np->nu.ct->pbase = BDEC;
+        }
+       /* xsp always right width for parameter net width */
+       if (xsp->xslen != pwid) __sizchgxs(xsp, pwid);
+
+       /* SJM 09/29/03 - change to handle sign extension and separate types */
+       if (xsp->xslen != pwid) __narrow_sizchg(xsp, pwid);
+       else if (xsp->xslen < pwid)
+        {
+         if (__root_ndp->has_sign) __sgn_xtnd_widen(xsp, pwid);
+         else __sizchg_widen(xsp, pwid);
+        }
+      }
+    }
+   else
+    {
+     /* no parameter range given or will not get here */ 
+     if (__root_ndp->is_real)
+      {
+       np->ntyp = N_REAL;
+       np->n_signed = TRUE;
+      }
+     else
+      {
+       np->ntyp = N_REG;
+       /* SJM 10/06/03 - no range or var type but signed may be present */
+       if (psign_decl) np->n_signed = TRUE;
+       else
+        {
+         if (__root_ndp->has_sign) np->n_signed = TRUE;
+        }
+      }
+
+     np->nwid = __root_ndp->szu.xclen;
+     if (np->nwid > 1)
+      {
+       np->n_isavec = TRUE;
+       np->vec_scalared = TRUE;
+       np->nu.ct->nx1 = __bld_rng_numxpr(np->nwid - 1, 0L, WBITS);
+       np->nu.ct->nx2 = __bld_rng_numxpr(0L, 0L, WBITS);
+      }
+     /* always true for real and int32 - maybe true from others */
+     if (__root_ndp->is_string) np->nu.ct->pstring = TRUE;
+     /* this works because param expr checking always sets ibase */ 
+     np->nu.ct->pbase = __root_ndp->ibase;
+    }
+
+   if (ptyp_decl) np->nu.ct->ptypdecl = TRUE;
+   if (prng_decl) np->nu.ct->prngdecl = TRUE;
+   if (psign_decl) np->nu.ct->psigndecl = TRUE;
+   if (__xpr_has_param(__root_ndp)) 
+    {
+     np->nu.ct->p_rhs_has_param = TRUE;
+     __inst_mod->mod_rhs_param = TRUE;
+    }
+
+   /* using ncomp delay union to store original expresssion - set first */
+   np->nu.ct->n_dels_u.d1x = __root_ndp;
+   np->nu.ct->parm_srep = SR_PXPR;
+
+   /* value must be evaluated to constant expr - since may need to */
+   /* change to IS form */
+   /* assign the value as SR PNUM form because now always "declared" - has */
+   /* kown type so can store as net value */
+   wlen = wlen_(xsp->xslen);
+   wp = (word32 *) __my_malloc(2*WRDBYTES*wlen);
+   memcpy(wp, xsp->ap, 2*wlen*WRDBYTES);
+   np->nva.wp = wp;
+   np->srep = SR_PNUM;
+   __pop_xstk();
+
+
+   if (__debug_flg)
+    {
+     char s1[RECLEN], s2[RECLEN], *chp;
+     
+     strcpy(s1, "");
+     strcpy(s2, "");
+     if (__root_ndp->is_real) strcpy(s1, "real ");
+     else 
+      {
+       sprintf(s2, " width %d", __root_ndp->szu.xclen);
+       if (__root_ndp->is_string) strcpy(s1, "string ");
+       else if (__root_ndp->has_sign) strcpy(s1, "signed ");
+      }
+     /* SJM 04/20/00 - changed so uses param type for printing */
+     /* SJM 05/24/00 - trim leading spaces */
+     __pregab_tostr(__xs, wp, &(wp[wlen]), np);
+     for (chp = __xs;; chp++) { if (*chp != ' ') break; }
+     __dbg_msg(
+      "%s%s %s defined at **%s(%d) has initial value %s%s\n", s1,
+      ptnam, paramnam, __cur_fnam, __lin_cnt, chp, s2);
+    }
+
+nxt_param:
+   if (is_hdr_form)
+    {
+     if (__toktyp == RPAR) break;
+     if (__toktyp != COMMA)
+      {
+       __pv_ferr(1026,
+        "%s module header form declaration right paren or comma expected - %s read",
+        ptnam, __prt_vtok());
+       if (!__vskipto2_any(COMMA, RPAR)) return(FALSE); 
+       if (__toktyp == RPAR) break;
+      }
+    }
+   else
+    {
+     if (__toktyp == SEMI) break;
+     if (__toktyp != COMMA)
+      {
+       __pv_ferr(1026,
+        "%s declaration semicolon or comma separator expected - %s read",
+        ptnam, __prt_vtok());
+       if (!__vskipto2_any(COMMA, SEMI)) return(FALSE); 
+       if (__toktyp == SEMI) break;
+      }
+    }
+   __get_vtok();
+   if (is_hdr_form)
+    {
+     /* if , followed by ID, part of list else new parameter decl */
+     if (__toktyp == PARAMETER) break;
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * return T if parameter define rhs expr contains any param
+ *
+ * set ncomp rhs has param bit causes re-eval of param value 
+ * to use new pound and defparam values if changed
+ */
+extern int32 __xpr_has_param(struct expr_t *ndp)
+{
+ struct sy_t *syp;
+ struct net_t *np;
+ struct expr_t *fandp;
+
+ switch ((byte) ndp->optyp) { 
+  case NUMBER: case REALNUM: case ISNUMBER: case ISREALNUM: return(FALSE);
+  case ID:
+   syp = ndp->lu.sy;
+   if (!syp->sydecl || syp->sytyp != SYM_N) return(FALSE);
+   np = syp->el.enp; 
+   if (np->n_isaparam) return(TRUE);
+   return(FALSE);
+  case GLBREF: return(FALSE);
+  case FCALL:
+   for (fandp = ndp->ru.x; fandp != NULL; fandp = fandp->ru.x)
+    {
+     /* LOOKATME - even if real param not allowed arg to const systf */
+     /* can be real */
+     if (__xpr_has_param(fandp->lu.x)) return(TRUE);
+    }
+   return(FALSE);
+ } 
+ if (ndp->lu.x != NULL) if (__xpr_has_param(ndp->lu.x)) return(TRUE);
+ if (ndp->ru.x != NULL) if (__xpr_has_param(ndp->ru.x)) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * version of chk paramexpr that is called for parameters during
+ * source input 
+ */
+extern int32 __src_rd_chk_paramexpr(struct expr_t *ndp, int32 xwid)
+{
+ int32 rv, sav_sfnam_ind, sav_slin_cnt;
+
+ /* SJM 10/01/99 - improve error location for param checking */
+ /* chk param expr needs sim locations set - set temporary guess here */
+ sav_sfnam_ind = __sfnam_ind;
+ sav_slin_cnt = __slin_cnt;
+ __sfnam_ind = __cur_fnam_ind;
+ __slin_cnt = __lin_cnt;
+
+ rv = __chk_paramexpr(ndp, xwid);
+
+ __sfnam_ind = sav_sfnam_ind;
+ __slin_cnt = sav_slin_cnt;
+
+ return(rv);
+}
+
+/*
+ * read a parameter vector declaration range 
+ *
+ * know [ read and reads one past ]
+ */
+extern int32 __rd_opt_param_vec_rng(struct expr_t **ax1, struct expr_t **ax2,
+ int32 is_hdr_form)
+{
+ int32 rngerr;
+ struct expr_t *x1, *x2;
+ char ptnam[RECLEN], s1[RECLEN];
+
+ if (__cur_declobj == SPECIFY) strcpy(ptnam, "specparam");
+ strcpy(ptnam, "parameter");
+
+ *ax1 = *ax2 = NULL;
+ rngerr = FALSE;
+ if (!__rd_decl_rng(&x1, &x2))
+  {
+   if (!is_hdr_form)
+    {
+     if (!__vskipto2_any(SEMI, RSB)) return(FALSE); 
+     if (__toktyp == SEMI) return(TRUE);
+    }
+   else
+    {
+     if (!__vskipto3_any(COMMA, RPAR, RSB)) return(FALSE); 
+     if (__toktyp != RSB) return(TRUE);
+    }
+   rngerr = TRUE; 
+   __get_vtok();
+   goto done;
+  }
+ if (__expr_has_glb(x1) || !__src_rd_chk_paramexpr(x1, 0))
+  {
+   __pv_ferr(1025,
+    "%s declaration first range \"%s\" illegal - defined %ss and constants only",
+    ptnam, __msgexpr_tostr(__xs, x1), ptnam);
+   rngerr = TRUE;
+  }
+ else
+  {
+   /* because of previous check, this can not fail */
+   __eval_param_rhs_tonum(x1);
+   sprintf(s1, "%s declaration first range", ptnam);
+   if (!__nd_ndxnum(x1, s1, TRUE)) rngerr = TRUE;
+  }
+ if (__expr_has_glb(x2) || !__chk_paramexpr(x2, 0))
+  {
+   __pv_ferr(1025,
+    "%s declaration second range \"%s\" illegal - defined %ss and constants only",
+    ptnam, __msgexpr_tostr(__xs, x2), ptnam);
+   rngerr = TRUE;
+  }
+ else
+  {
+   /* because of previous check, this can not fail */
+   __eval_param_rhs_tonum(x2);
+   sprintf(s1, "%s declaration second range", ptnam);
+   if (!__nd_ndxnum(x2, s1, TRUE)) rngerr = TRUE;
+  }
+
+done:
+ if (rngerr)
+  {
+   if (x1 != NULL) __free_xtree(x1);
+   if (x2 != NULL) __free_xtree(x2);
+   x1 = x2 = NULL;
+  }
+ *ax1 = x1;
+ *ax2 = x2;
+ return(TRUE);
+}
+
+/*
+ * read a parameter array declaration range 
+ *
+ * know [ read and reads one past ]
+ */
+static int32 rd_opt_param_array_rng(struct expr_t **ax1, struct expr_t **ax2,
+ int32 is_hdr_form)
+{
+ int32 rngerr;
+ struct expr_t *x1, *x2;
+ 
+ rngerr = FALSE;
+ if (!__rd_decl_rng(&x1, &x2) || x1 == NULL || x2 == NULL)
+  {
+   if (!is_hdr_form)
+    {
+     if (!__vskipto2_any(SEMI, RSB)) return(FALSE); 
+     if (__toktyp == SEMI) return(TRUE);
+    }
+   else
+    {
+     if (!__vskipto3_any(COMMA, RPAR, RSB)) return(FALSE); 
+     if (__toktyp != RSB) return(TRUE);
+    }
+   rngerr = TRUE;
+   __get_vtok();
+   goto done;
+  }
+ /* one past possible ] read */
+ /* convert ranges to constant index */
+ if (__expr_has_glb(x1) || !__src_rd_chk_paramexpr(x1, 0))
+  {
+   __pv_ferr(1025,
+    "parameter array declaration first range \"%s\" illegal - defined parameters and constants only",
+    __msgexpr_tostr(__xs, x1));
+   rngerr = TRUE;
+  }
+ else
+  {
+   /* because of previous check, this can not fail */
+   __eval_param_rhs_tonum(x1);
+   if (!__nd_ndxnum(x1, "parameter array declaration first range", TRUE))
+     rngerr = TRUE;
+  }
+ if (__expr_has_glb(x2) || !__src_rd_chk_paramexpr(x2, 0))
+  {
+   __pv_ferr(1025,
+    "parameter array declaration second range \"%s\" illegal - defined parameters and constants only",
+    __msgexpr_tostr(__xs, x2));
+   rngerr = TRUE;
+  }
+ else
+  {
+   /* because of previous check, this can not fail */
+   __eval_param_rhs_tonum(x2);
+   if (!__nd_ndxnum(x2, "parameter array declaration second range", TRUE))
+    rngerr = TRUE;
+  }
+done:
+ if (rngerr)
+  {
+   if (x1 != NULL) __free_xtree(x1);
+   if (x2 != NULL) __free_xtree(x2);
+   x1 = x2 = NULL;
+  }
+ *ax1 = x1;
+ *ax2 = x2;
+ return(TRUE);
+}
+     
+/*
+ * routine to check and declare array param 
+ *
+ * also sets initial array value
+ * know cur mod set when this is called
+ */
+static struct net_t *chkadd_array_param(char *paramnam, int32 pwtyp, int32 pwid,
+ int32 psign, struct expr_t *x1, struct expr_t *x2, struct expr_t *ax1,
+  struct expr_t *ax2)
+{
+ register int32 ai;
+ word32 *wp;
+ int32 unnorm_ai, r1, r2, awid, wlen;
+ int32 initerr, some_str, all_str;
+ struct expr_t *catndp, *xp, **avalxtab;
+ struct net_t *np;
+ struct xstk_t *xsp;
+ char s1[RECLEN];
+
+ if (__root_ndp->optyp != LCB)
+  {
+   __pv_ferr(688,
+    "parameter %s array initial value %s not array constructor ({} concatenate) ",
+    paramnam, __msgexpr_tostr(__xs, x2));
+   return(NULL);
+  }
+ /* build table of parameters */
+ r1 = (int32) __contab[ax1->ru.xvi];
+ r2 = (int32) __contab[ax2->ru.xvi];
+ /* number of cells in array */
+ awid = (r1 >= r2) ? r1 - r2 + 1 : r2 - r1 + 1; 
+ avalxtab = (struct expr_t **) __my_malloc(awid*sizeof(struct expr_t *));
+ for (ai = 0; ai < awid; ai++) avalxtab[ai] = NULL;
+
+ /* first step unwind array constructor repeats */
+ unwind_param_array_constructor(__root_ndp);
+ if (__debug_flg)
+  {
+   __dbg_msg("parameter %s declare array initializer unwound to: %s\n", 
+   paramnam, __msgexpr_tostr(__xs, __root_ndp));
+  }
+
+ /* fill table of expressions */
+ catndp = __root_ndp->ru.x;
+ /* first is internal high cell */
+ initerr = FALSE;
+ for (ai = awid - 1; catndp != NULL; catndp = catndp->ru.x)
+  {
+   unnorm_ai = (r1 >= r2) ? (r2 + ai) : (r2 - ai);
+   xp = catndp->lu.x;
+   /* DBG remove --- */
+   if (xp->optyp == CATREP) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   chk1_arrinit_expr(xp, paramnam, unnorm_ai);
+   if (ai < 0) 
+    {
+     __pv_ferr(689,
+      "parameter array initializer at %s[%d] %s illegal - fills past end",
+      paramnam, unnorm_ai, __msgexpr_tostr(__xs, xp));
+     initerr = TRUE;
+     continue;
+    }
+   avalxtab[ai] = __copy_expr(xp); 
+   ai--; 
+  }
+ /* finally check to make sure fill width correct */
+ if (ai >= 0)
+  {
+   __pv_ferr(689,
+    "parameter array %s initializer width %d illegal - only %d filled",
+    paramnam, awid, ai + 1);
+   return(NULL);
+  }
+ /* do not add unless initializer good */
+ if (initerr) return(NULL);
+
+ /* know all cells in aval xtab filled - add param - must be declared */
+ if ((np = __add_param(paramnam, x1, x2)) == NULL) return(NULL); 
+
+ np->nu.ct->ax1 = ax1; 
+ np->nu.ct->ax2 = ax2; 
+ np->n_isarr = TRUE;
+ /* index of this cannot be used in pound params */
+ np->nu.ct->p_locparam = TRUE;
+ np->srep = SR_PNUM;
+
+ if (pwtyp == N_REAL)
+  {
+   np->ntyp = N_REAL;
+   np->n_signed = TRUE;
+   np->nwid = REALBITS;
+   np->nu.ct->pbase = BDBLE;
+  }
+ else
+  {
+   np->ntyp = pwtyp;
+   /* if declared always know width */
+   np->nwid = pwid;
+   if (np->ntyp == N_INT) np->n_signed = TRUE;
+   else
+    {
+     if (psign && np->ntyp != N_TIME) np->n_signed = TRUE; 
+    }
+
+   /* if some but not all strings needs warning */
+   for (some_str = FALSE, all_str = TRUE, ai = awid - 1; ai >= 0; ai--)
+    {
+     if (avalxtab[ai]->is_string) some_str = TRUE;
+     else all_str = FALSE;
+    }
+   if (some_str && !all_str)
+    {
+     __pv_fwarn(615,
+      "parameter array %s some but not all cells initialized to strings - strings treated as numbers",
+      paramnam);
+    }
+   if (all_str) np->nu.ct->pstring = TRUE;
+   np->nu.ct->pbase = __root_ndp->ibase;
+  }
+ /* allocate and fill parameter array - never packed */
+
+ /* allocate and fill parameter array */
+ wlen = wlen_(np->nwid);
+ np->nva.wp = (word32 *) __my_malloc(2*WRDBYTES*awid*wlen);
+ for (ai = awid - 1; ai >= 0; ai--)
+  {
+   unnorm_ai = (r1 >= r2) ? (r2 + ai) : (r2 - ai);
+   xsp = __src_rd_eval_xpr(avalxtab[ai]);
+   sprintf(s1, "parameter array cell %s[%d] initializer", np->nsym->synam,
+    unnorm_ai); 
+   /* afer here know xsp width match declared parameter width */
+   cnvt_to_pdecl(xsp, avalxtab[ai], np, s1); 
+   wp = &(np->nva.wp[2*wlen*ai]);
+   memcpy(wp, xsp->ap, 2*wlen*WRDBYTES);
+   __pop_xstk();
+  }
+
+ /* save expression that is original array constructor expression */
+ np->nu.ct->n_dels_u.d1x = __root_ndp;
+ np->nu.ct->parm_srep = SR_PXPR;
+
+ /* free expression table */
+ for (ai = awid - 1; ai >= 0; ai--) __free_xtree(avalxtab[ai]);
+ __my_free((char *) avalxtab, awid*sizeof(struct expr_t *));
+
+ if (__debug_flg)
+  {
+   if (np->ntyp == N_REAL)
+    sprintf(s1, "[%d:%d] cell real array", r1, r2);
+   else if (pwtyp == N_INT)
+    sprintf(s1, "[%d:%d] cell integer array", r1, r2);
+   else
+    {
+     sprintf(s1, " [%d:%d] cell %d bit reg array", r1, r2, np->nwid);
+     if (np->nu.ct->pstring) strcat(s1, " [string]");
+     else if (np->n_signed && pwtyp != N_INT) strcat(s1, " [signed]");
+    }
+   __dbg_msg("%s parameter %s defined at **%s(%d):\n", s1, paramnam,
+    __cur_fnam, __lin_cnt);
+   for (ai = awid - 1; ai >= 0; ai--)
+    {
+     unnorm_ai = (r1 >= r2) ? (r2 + ai) : (r2 - ai);
+     
+     wp = &(np->nva.wp[2*wlen*ai]);
+     __dbg_msg("  %s[%d] = %s\n", paramnam, unnorm_ai, __pregab_tostr(__xs,
+      wp, &(wp[wlen]), np));
+    }
+  }
+ return(np);
+}
+
+/*
+ * special xstk conversion routine where must convert to declared size
+ *
+ * this converts to type and size of param - new algorithm assumes
+ * that parameters are somehow declared (possibly from initial rhs expr)
+ */
+static void cnvt_to_pdecl(struct xstk_t *xsp, struct expr_t *xrhs,
+ struct net_t *np, char *innam)
+{
+ char s1[RECLEN];
+
+ /* DBG remove -- */
+ if (!np->n_isaparam) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+
+ if (np->ntyp == N_REAL)
+  { 
+   if (!xrhs->is_real)
+    {
+     if (xrhs->szu.xclen == WBITS && xrhs->has_sign) strcpy(s1, "integer");
+     else sprintf(s1, "%d bit register", xrhs->szu.xclen);
+     __gfinform(486, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+      "parameter %s in %s assign required conversion from %s to real",
+      np->nsym->synam, innam, s1); 
+
+     __cnv_stk_fromreg_toreal(xsp, (xrhs->has_sign == 1));
+    }
+  }
+ else 
+  { 
+   /* know param is non real */ 
+   if (xrhs->is_real)
+    {
+     if (np->nwid == WBITS && np->n_signed) strcpy(s1, "integer");
+     else sprintf(s1, "%d bit register", np->nwid);
+
+     __gfinform(487, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+      "parameter %s in %s assign required conversion from real to %s",
+      np->nsym->synam, innam, s1); 
+
+     __cnv_stk_fromreal_toreg32(xsp);
+    }
+   /* but it may have wrong width - in new algorithm param assigns */
+   if (xsp->xslen != np->nwid)
+    {
+     __gfinform(488, np->nsym->syfnam_ind, np->nsym->sylin_cnt,
+      "parameter %s in %s assign required width change from %d to %d",
+      np->nsym->synam, innam, xsp->xslen, np->nwid); 
+     /* key always convert to declared */
+
+     /* SJM 09/29/03 - change to handle sign extension and separate types */
+     if (xsp->xslen > np->nwid) __narrow_sizchg(xsp, np->nwid);
+     else if (xsp->xslen < np->nwid)
+      {
+       if (xrhs->has_sign) __sgn_xtnd_widen(xsp, np->nwid);
+       else __sizchg_widen(xsp, np->nwid);
+      }
+    }
+  }
+}
+
+/*
+ * check and unwind array constructor
+ *
+ * this will create normal array constructor from repeat count form
+ * when done concatenate is one level with catreps removed
+ */
+static void unwind_param_array_constructor(struct expr_t *ndp)
+{
+ if (__isleaf(ndp)) return;
+
+ /* array constructor (concatenate) unwinding must be done bottom up */
+ if (ndp->lu.x != NULL) { unwind_param_array_constructor(ndp->lu.x); }
+ if (ndp->ru.x != NULL) { unwind_param_array_constructor(ndp->ru.x); }
+
+ /* node is top of concatenate with all sub concatenates simplified */
+ if (ndp->optyp == LCB)
+  {
+   register struct expr_t *ndp2;
+   struct expr_t *last_ndp2, *end_ndp;
+
+   last_ndp2 = ndp;
+   for (ndp2 = ndp->ru.x; ndp2 != NULL; ndp2 = ndp2->ru.x)
+    {
+     struct expr_t *lop;
+
+     lop = ndp2->lu.x;
+     /* notice ,, form illegal in concatentate */
+     switch ((byte) lop->optyp) {
+      case NUMBER: case REALNUM:
+       break;
+      case LCB:
+       {
+        /* nested concatenate - splice up one level */
+        last_ndp2->ru.x = lop->ru.x;
+	/* find rightmost element - know always there */
+	end_ndp = __find_catend(lop);
+	/* if rightmost up one node will make null */
+	end_ndp->ru.x = ndp2->ru.x;
+	/* end of new chain is new last */
+	last_ndp2 = end_ndp;
+       }
+       continue;
+      case CATREP:
+       {
+        int32 repval;
+	struct expr_t *dupndp;
+	struct xstk_t *xsp;
+
+        if (__src_rd_chk_paramexpr(lop->lu.x, 0))
+	 {
+	  xsp = __src_rd_eval_xpr(lop->lu.x);
+	  if (xsp->xslen > WBITS)
+	   {
+            if (!vval_is0_(&(xsp->ap[1]), xsp->xslen - WBITS) 
+             || !vval_is0_(&(xsp->bp[1]), xsp->xslen - WBITS)
+	     || xsp->bp[0] != 0L) goto bad_rep;
+	   }
+          else if (xsp->bp[0] != 0) goto bad_rep;
+	  repval = (int32) xsp->ap[0];
+          if (repval == 1) 
+           __finform(442,
+            "array constructore repeat value of 1 has no effect");
+	 }
+        else
+	 {
+bad_rep:
+          __pv_ferr(814,
+           "array constructor repeat value %s not an integral constant expression",
+	   __msgexpr_tostr(__xs, lop->lu.x));
+          repval = 1;
+         }
+
+	__pop_xstk();
+        /* know the rhs thing must be a concatenate */
+        dupndp = __dup_concat(repval, lop->ru.x->ru.x);
+
+        /* nested concatenate - splice up one level */
+        last_ndp2->ru.x = dupndp;
+        /* find rightmost element - know always there */
+	end_ndp = __find_catend(dupndp);
+
+	/* if rightmost up one node will make null */
+	end_ndp->ru.x = ndp2->ru.x;
+	/* end of new chain is new last */
+	last_ndp2 = end_ndp;
+       }
+       continue;
+      }
+     /* NUMBER or other means move last down tree one */
+     last_ndp2 = ndp2;
+    }
+  }
+}
+
+/*
+ * check one array initializer expression
+ */
+static void chk1_arrinit_expr(struct expr_t *xp, char *paramnam, int32 ai)
+{
+ if (__expr_has_glb(xp) || !__src_rd_chk_paramexpr(xp, 0))
+  {
+   __pv_ferr(1025,
+    "parameter array initializer cell %s[%d] \"%s\" illegal - parameters and constants only",
+    paramnam, ai, __msgexpr_tostr(__xs, xp));
+   /* need to still add value of x to prevent further errors */
+   __free2_xtree(xp);
+   xp->szu.xclen = WBITS;
+   __set_numval(xp, ALL1W, ALL1W, WBITS);  
+  }
+}
+
+/*
+ * return T if expression has any global reference
+ */
+extern int32 __expr_has_glb(struct expr_t *xp)
+{
+ if (__isleaf(xp))
+  {
+   if (xp->optyp == GLBREF) return(TRUE);
+   return(FALSE);
+  }
+ if (xp->lu.x != NULL) { if (__expr_has_glb(xp->lu.x)) return(TRUE); }  
+ if (xp->ru.x != NULL) { if (__expr_has_glb(xp->ru.x)) return(TRUE); }
+ return(FALSE);
+}
+
+/*
+ * routine to evaluate parameters or defparam rhs and produce constant
+ *
+ * this expects itree location to be set but no IS forms allowed by here
+ * know rhs legal (only params and constants)
+ * this freezes any parameter, # param or defparam to number from now on
+ */
+extern void __eval_param_rhs_tonum(struct expr_t *ndp)
+{ 
+ int32 wlen, is_str, xbase;
+ double d1;
+ struct xstk_t *xsp;
+
+ if (ndp->is_string) is_str = TRUE; else is_str = FALSE;
+ xbase = ndp->ibase;
+ 
+ /* possibly different expr. */
+ switch ((byte) ndp->optyp) {  
+  case NUMBER: case REALNUM: break;
+  /* IS forms can only be created by # or defparam assignments later */
+  /* can never be in source */ 
+  case ISNUMBER: case ISREALNUM: __arg_terr(__FILE__, __LINE__); break;
+ default:
+  if (ndp->optyp == ID && ndp->lu.sy->el.enp->n_isaparam)
+   {
+    is_str = ndp->lu.sy->el.enp->nu.ct->pstring;
+    xbase = ndp->lu.sy->el.enp->nu.ct->pbase;
+   }
+  else if (ndp->optyp == LCB) is_str = TRUE;
+  xsp = __src_rd_eval_xpr(ndp);
+  __free2_xtree(ndp);
+  wlen = wlen_(xsp->xslen);
+  if (xsp->xslen <= WBITS)
+   {
+    if (ndp->is_real)
+     {
+      memcpy(&d1, xsp->ap, sizeof(double)); 
+      ndp->ru.xvi = __alloc_shareable_rlcval(d1);
+     }
+    else
+     {
+      ndp->ru.xvi = __alloc_shareable_cval(xsp->ap[0], xsp->bp[0], xsp->xslen);
+     }
+   }
+  else
+   {
+    ndp->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, wlen);
+   }
+  __pop_xstk();
+  /* notice string from rhs param expr. impossible */
+  if (ndp->is_real) ndp->optyp = REALNUM;
+  else
+   {
+    ndp->optyp = NUMBER;
+    /* notice leave rest of ndp fields the same */
+    ndp->is_string = is_str;
+   }
+  ndp->ibase = xbase;
+ } 
+}
+
+/*
+ * add newly declared parameter - better not be already defined
+ * called from parameter declaration item only
+ * range must be passed because of parameter "v[h:l] =" form (not yet in) 
+ *
+ * uses initial expressions to set wire type - defparam can change
+ * but one type for all instance
+ *
+ * this is for both parameters and specparams indicated by current decl obj
+ * for specparam top of scope symbol table stack is special symbol table
+ * just for specparams - no other symbols legal
+ *
+ * code that reads parameter arrays calls this then sets fields it
+ */
+extern struct net_t *__add_param(char *nam, struct expr_t *x1,
+ struct expr_t *x2)
+{
+ int32 is_spec;
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+ struct net_t *np;
+ char s1[RECLEN], ptypnam[RECLEN]; 
+
+ if (__cur_declobj == SPECIFY)
+  { is_spec = TRUE; strcpy(ptypnam, "specparam"); } 
+ else
+  {
+   is_spec = FALSE;
+   strcpy(ptypnam, "parameter");
+  }
+ /* just look in local scope here since parameter decl. must be local */
+ tnp = __vtfind(nam, __venviron[__top_sti]);
+ if (__sym_is_new)
+  {
+   __add_sym(nam, tnp);
+   /* notice still need to update total symbol count */
+   (__venviron[__top_sti]->numsyms)++;
+   syp = tnp->ndp;
+   /* this initializes ncomp for all net forms including params */
+   np = __add_net(syp);
+  }
+ else
+  {
+   syp = tnp->ndp;
+   if (syp->sytyp == SYM_N) np = syp->el.enp; else np = NULL;
+   if (!syp->sydecl)
+    {
+     /* is previously used as net, then ok */
+     if (syp->sytyp != SYM_N)
+      {
+       __pv_ferr(1027,
+        "cannot declare %s %s - previously used as %s at %s", 
+        nam, ptypnam, __to_sytyp(s1, syp->sytyp), __bld_lineloc(__xs,
+        syp->syfnam_ind, syp->sylin_cnt));
+       return(NULL);
+      }
+    }
+   else
+    {
+     /* this needs to be explicit to include param wire types */
+     if (np != NULL) __to_wtnam2(s1, np->ntyp);
+     else __to_sytyp(s1, syp->sytyp);
+     __pv_ferr(1028, "cannot declare %s %s - previously declared as %s at %s",
+      nam, ptypnam, s1, __bld_lineloc(__xs, syp->syfnam_ind,
+      syp->sylin_cnt));
+     return(NULL);
+    }
+   /* know will be wire to get to be declared here */
+   syp->syfnam_ind = __cur_fnam_ind;
+   syp->sylin_cnt = __lin_cnt;
+  }
+ syp->sydecl = TRUE;
+
+ /* change to proper type of wire even if already used */
+ /* io type for parameter unused instead used for wire type */
+ np->iotyp = NON_IO;
+ np->n_isaparam = TRUE;
+ if (is_spec) np->nu.ct->p_specparam = TRUE;
+ 
+ /* if has range know is vector */ 
+ if (x1 != NULL) { np->n_isavec = TRUE; np->vec_scalared = TRUE; }
+ np->nu.ct->nx1 = x1;
+ np->nu.ct->nx2 = x2;
+
+ /* notice already linked into wire list - must also link into param list */
+ /* link on end to preserve order */
+ if (__cur_declobj == MODULE)
+  {
+   /* module parameter declaration */
+   if (__end_paramnp == NULL) __inst_mod->mprms = np;
+   else __end_paramnp->nu2.nnxt = np;
+   __end_paramnp = np;
+  }
+ else if (__cur_declobj == SPECIFY)
+  {
+   if (__end_msprms == NULL) __cur_spfy->msprms = np;
+   else __end_msprms->nu2.nnxt = np;
+   __end_msprms = np;
+  }
+ else if (__cur_declobj == TASK)
+  {
+   if (__end_tskparamnp == NULL) __cur_tsk->tsk_prms = np;
+   else __end_tskparamnp->nu2.nnxt = np;
+   __end_tskparamnp = np;
+  }
+ else __case_terr(__FILE__, __LINE__); 
+ return(np);
+}
+
+/*
+ * read a continuous assign module item
+ * assign statement read and reads ending ;
+ * return F if cannot sync to ending ;, if F will be sync to next mod/prim
+ * list of assignments allowed here
+ */
+static int32 rd_contassign(void)
+{
+ struct expr_t *lhsndp, *rhsndp;
+ struct paramlst_t *pmphdr;
+ struct conta_t *cap;
+ int32 first_time, sfnind, slcnt;
+
+ /* must read drive strength and delay */
+ pmphdr = NULL;
+ __v0stren = __v1stren = NO_STREN;
+
+ __get_vtok();
+ if (__toktyp == LPAR)
+  {
+   __get_vtok();
+   if (!rd_verstrens())
+    {
+     if (!__vskipto2_any(RPAR, SEMI)) return(FALSE);
+     if (__toktyp == RPAR) { __get_vtok(); goto rd_parms; }
+     return(TRUE);
+    }
+  }
+
+rd_parms:
+ if (__toktyp == SHARP)
+  {
+   if (!rd_oparamdels(&pmphdr))
+    {
+bad_end:
+     return(__vskipto_any(SEMI));
+    }
+  }
+ for (first_time = TRUE;;)
+  {
+   sfnind = __cur_fnam_ind;
+   slcnt = __lin_cnt;
+   /* collect lhs */
+   if (!__col_lval()) goto bad_end;
+   __bld_xtree(0);
+
+   lhsndp = __root_ndp;
+   __get_vtok();
+   if (!__col_comsemi(-1)) goto bad_end;
+   __bld_xtree(0);
+   rhsndp = __root_ndp;
+   cap = add_conta(lhsndp, rhsndp, sfnind, slcnt);
+   if (first_time) cap->ca_du.pdels = pmphdr;
+   else cap->ca_du.pdels = __copy_dellst(pmphdr);
+
+   if (__v0stren != NO_STREN)
+    {
+     cap->ca_hasst = TRUE;
+     cap->ca_stval = ((__v0stren << 3) | __v1stren) & 0x3f;
+    }
+   if (__toktyp == SEMI) break;
+   if (__toktyp != COMMA) 
+    {
+     /* try to sync to next list el. if present */
+     if (!__vskipto2_any(COMMA, SEMI)) return(FALSE);
+     if (__toktyp == SEMI) break;
+    }
+   first_time = FALSE;
+   __get_vtok();
+  }
+ return(TRUE);
+}
+
+/*
+ * add a continuous assignment form cell
+ * even if lhs 1 bit stored in non gate form here
+ */
+static struct conta_t *add_conta(struct expr_t *lhsndp,
+ struct expr_t *rhsndp, int32 sfnind, int32 slcnt)
+{
+ struct conta_t *cap;
+ struct sy_t *syp;
+
+ syp = __bld_loc_symbol(__conta_num, __venviron[0], "assgn",
+  "continuous assign");
+ syp->sytyp = SYM_CA;
+ /* this is place of declaration */
+ syp->syfnam_ind = sfnind;
+ syp->sylin_cnt = slcnt;
+ syp->sydecl = TRUE;
+
+ cap = (struct conta_t *) __my_malloc(sizeof(struct conta_t));
+ cap->casym = syp;
+ syp->el.ecap = cap;
+ cap->ca_hasst = FALSE;
+ cap->ca_stval = ST_STRVAL;
+ cap->ca_delrep = DT_CMPLST;
+ cap->ca_du.pdels = NULL; 
+ cap->ca_4vdel = FALSE;
+ cap->ca_gone = FALSE;
+ cap->ca_pb_sim = FALSE;
+ cap->ca_pb_el = FALSE;
+ cap->lhsx = lhsndp;
+ cap->rhsx = rhsndp;
+ cap->caschd_tevs = NULL; 
+ cap->ca_drv_wp.wp = NULL;
+ cap->schd_drv_wp.wp = NULL;
+ /* SJM 12/19/04 - when chk contas done - contas now tab of size m ca num */
+ /* removed nxt field from conta type - can be in pbca's built in prp pass */
+ cap->pbcau.canxt = NULL;
+ /* link on to list */
+ if (__end_ca == NULL) __inst_mod->mcas = cap;
+ else __end_ca->pbcau.canxt = cap;
+ __end_ca = cap;
+ __conta_num++;
+ return(cap);
+}
+
+/*
+ * read an event declaration
+ *
+ * parsing routine to read and declare an event decl (can't be array/vec)
+ * need to declare as task var if reading task/func/named block
+ */
+static int32 rd_eventdecl(int32 reading_tsk)
+{
+ int32 first_time, has_attr;
+ struct net_t *np;
+
+ /* use local has attr flag so can turn glb seen of before return */
+ if (__wrk_attr.attr_seen) { has_attr = TRUE; __wrk_attr.attr_seen = FALSE; }
+ else has_attr = FALSE;
+ for (first_time = TRUE;;)
+  {
+   __get_vtok();
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1029,
+      "event declaration event name expected - %s read", __prt_kywrd_vtok());
+     goto try_resync;
+    }
+   /* since no range, if fails just try next one*/
+   if (reading_tsk) np = decl_taskvar(N_EVENT, NULL, NULL);
+   else np = __decl_wirereg(N_EVENT, NULL, NULL, NULL);
+
+   /* SJM - 03/20/00 - save wire decl attrs */
+   if (has_attr)
+    {
+     /* until Verilog 2000 will not see also event port attrs */
+     if (np != NULL) add_net_attr(np, EVENT);
+    }
+
+   if (first_time) first_time = FALSE;
+
+   __get_vtok();
+   if (__toktyp == SEMI) break;
+   if (__toktyp != COMMA)
+    {
+     __pv_ferr(1033,
+      "event declaration comma or semicolon separator expected - %s read",
+      __prt_vtok());
+     /* try to resync */
+try_resync:
+     if (!__vskipto2_any(COMMA, SEMI)) return(FALSE); 
+     if (__toktyp == SEMI) break;
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * allocate a statement entry
+ * for empty statement (;) never get here
+ */
+extern struct st_t *__alloc_stmt(int32 styp)
+{
+ struct st_t *stp;
+ struct for_t *frp;
+ struct qconta_t *qcafs;
+
+ stp = (struct st_t *) __my_malloc(sizeof(struct st_t));
+ __init_stmt(stp, styp);
+ (__inst_mod->mstnum)++; 
+
+ /* DBG remove --
+ if (__debug_flg)
+  {
+    extern char *__to_sttyp(char *, word32);
+
+    __dbg_msg("AT %s %s - STMT ALLOC (%s)\n",
+     __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt),
+     __inst_mod->msym->synam, __to_sttyp(__xs2, styp));
+  }
+ --- */
+ /* DBG remove --
+ if (__debug_flg)
+  {
+   extern char *__to_sttyp(char *, unsigned);
+
+   __dbg_msg("%04d: AT %s %s - STMT ALLOC (%s)\n",
+    __inst_mod->mstnum - 1, __bld_lineloc(__xs, stp->stfnam_ind,
+    stp->stlin_cnt), __inst_mod->msym->synam, __to_sttyp(__xs2, styp));
+  }
+ --- */
+ /* ALTERNATE DBG remove --
+ if (__debug_flg)
+  {
+   extern char *__to_sttyp(char *, unsigned);
+
+   __dbg_msg("AT %s %s - STMT ALLOC %04d (%s)\n",
+    __bld_lineloc(__xs, stp->stfnam_ind, stp->stlin_cnt),
+    __inst_mod->msym->synam, __inst_mod->mstnum - 1, __to_sttyp(__xs2, styp));
+  }
+ --- */
+
+ switch ((byte) styp) {
+  /* null just has type value and NULL pointer */
+  case S_NULL: case S_STNONE: break;
+  case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA: case S_NBPROCA:
+   stp->st.spra.lhsx = NULL;
+   stp->st.spra.rhsx = NULL;
+   break;
+  case S_IF:
+   stp->st.sif.condx = NULL;
+   stp->st.sif.thenst = NULL;
+   stp->st.sif.elsest = NULL;
+   break;
+  case S_CASE:
+   stp->st.scs.castyp = UNDEF;
+   stp->st.scs.maxselwid = 0;
+   stp->st.scs.csx = NULL;
+   stp->st.scs.csitems = NULL;
+   break;
+  case S_REPEAT:
+   stp->st.srpt.repx = NULL;
+   stp->st.srpt.reptemp = NULL;
+   stp->st.srpt.repst = NULL;
+   break;
+  case S_FOREVER:
+  case S_WHILE:
+   stp->st.swh.lpx = NULL;
+   stp->st.swh.lpst = NULL;
+   break;
+  case S_WAIT:
+   stp->st.swait.lpx = NULL;
+   stp->st.swait.lpst = NULL;
+   stp->st.swait.wait_dctp = __alloc_dctrl();
+   break;
+  case S_FOR:
+   frp = (struct for_t *) __my_malloc(sizeof(struct for_t));
+   stp->st.sfor = frp;
+   frp->forassgn = NULL;
+   frp->fortermx = NULL;
+   frp->forinc = NULL;
+   frp->forbody = NULL;
+   break;
+  case S_DELCTRL:
+   stp->st.sdc = __alloc_dctrl();
+   break;
+  case S_NAMBLK:
+   stp->st.snbtsk = NULL;
+   break;
+  case S_UNBLK:
+   stp->st.sbsts = NULL;
+   break;
+  case S_UNFJ:
+   stp->st.fj.fjstps = NULL;
+   stp->st.fj.fjlabs = NULL;
+   break;
+  case S_TSKCALL:
+   stp->st.stkc.targs = NULL;
+   stp->st.stkc.tsksyx = NULL;
+   stp->st.stkc.tkcaux.trec = NULL;
+   break;
+  case S_QCONTA:
+   /* SJM 06/23/02 - since pre-building dce for qcaf need more fields */
+   qcafs = (struct qconta_t *) __my_malloc(sizeof(struct qconta_t));
+   stp->st.sqca = qcafs;
+   qcafs->qcatyp = UNDEF;
+   qcafs->regform = FALSE;
+   qcafs->qclhsx = NULL;
+   qcafs->qcrhsx = NULL;
+   qcafs->rhs_qcdlstlst = NULL;
+   break;
+  case S_QCONTDEA:
+   stp->st.sqcdea.qcdatyp = UNDEF;
+   stp->st.sqcdea.qcdalhs = NULL;
+   break;
+  case S_CAUSE:
+   stp->st.scausx = NULL;
+   break;
+  case S_DSABLE:
+   stp->st.sdsable.dsablx = NULL;
+   stp->st.sdsable.func_nxtstp = NULL;
+   break;
+  /* statement added for execution */
+  case S_REPSETUP:
+   /* union field unused */
+   stp->st.scausx = NULL;
+   break;
+  case S_REPDCSETUP:
+   /* union field unused */
+   stp->st.scausx = NULL;
+   break;
+  case S_GOTO:
+   stp->st.sgoto = NULL;
+   break;
+  default: __case_terr(__FILE__, __LINE__);
+  }
+ return(stp);
+}
+
+/*
+ * initialize stmt
+ */
+extern void __init_stmt(struct st_t *stp, int32 styp)
+{
+ stp->stlin_cnt = __lin_cnt;
+ stp->stfnam_ind = __cur_fnam_ind;
+ stp->stmttyp = styp;
+ stp->st_unbhead = FALSE;
+ /* notice this always has the statement type even if break point not set */
+ stp->rl_stmttyp = styp;
+ stp->strb_seen_now = FALSE;
+ stp->lpend_goto = FALSE;
+ stp->dctrl_goto = FALSE;
+ stp->lstend_goto = FALSE;
+ stp->st_schd_ent = FALSE;
+ stp->lpend_goto_dest = FALSE;
+ /* assume if non blocking need the sched tev table */
+ stp->stnxt = NULL;
+}
+
+/*
+ * allocate and initialize a delay control record
+ */
+extern struct delctrl_t *__alloc_dctrl(void)
+{
+ struct delctrl_t *dctp;
+
+ dctp = (struct delctrl_t *) __my_malloc(sizeof(struct delctrl_t));
+ dctp->dctyp = DC_NONE;
+ dctp->dc_iact = FALSE;
+ dctp->dc_delrep = DT_CMPLST;
+ dctp->dc_nblking = FALSE;
+ dctp->implicit_evxlst = FALSE;
+ dctp->dc_du.pdels = NULL;
+ dctp->repcntx = NULL;
+ dctp->dceschd_tevs = NULL;
+ dctp->actionst = NULL;
+ /* this is allocated during prep - nil for now */
+ dctp->dce_repcnts = NULL;
+ return(dctp);
+}
+
+/*
+ * variant of alloc stmt that takes "real" location as args
+ */
+extern struct st_t *__alloc2_stmt(int32 styp, int32 fnind, int32 lcnt)
+{
+ int32 sav_fnami, sav_flini;
+ struct st_t *stp;
+
+ sav_fnami = __cur_fnam_ind;
+ sav_flini = __lin_cnt;
+ __cur_fnam_ind = fnind;
+ __lin_cnt = lcnt;
+
+ stp = __alloc_stmt(styp);
+
+ __cur_fnam_ind = sav_fnami;
+ __lin_cnt = sav_flini;
+ return(stp);
+}
+
+/*
+ * DEFPARAM READING ROUTINES
+ */
+
+/*
+ * read the parameter defparam statement
+ * assigns values to this or other params
+ * form: defparam [hieriarch path or id] = [param. value expr.], ... ;
+ *
+ * if returns F synced to next mod/prim else synced to ;
+ * list of assignments allowed here
+ */
+static int32 rd_dfparam_stmt(void)
+{
+ struct dfparam_t *dfpp;
+ struct expr_t *lhsndp;
+
+ for (;;)	
+  {
+   __get_vtok();
+   /* notice only for lhs not right */
+   if (!__col_lval())
+    {
+     /* part of lhs may have been built */
+     if (!__vskipto3_any(EQ, COMMA, SEMI)) return(FALSE);
+     if (__toktyp == EQ) goto do_rhs; 
+     if (__toktyp == COMMA) continue;
+     return(TRUE);
+    }
+do_rhs:
+   __bld_xtree(0);
+   lhsndp = __root_ndp;
+   if (lhsndp->optyp != ID && lhsndp->optyp != GLBREF)
+    {
+     __pv_ferr(1034, "defparam lvalue %s not identifier or hierarchical path",
+      __msgexpr_tostr(__xs, lhsndp));
+    }
+   /* know = read */
+   __get_vtok();
+   if (!__col_comsemi(-1))
+    {
+err_cont:
+     if (!__vskipto2_any(COMMA, SEMI)) return(FALSE);
+     if (__toktyp == COMMA) continue;
+     return(TRUE);
+    }
+   __bld_xtree(0);
+
+   /* checking rhs does no evaluation but set sizes and checks for only */
+   /* numbers and previously defined in source order parameters */
+   /* defparam rhs params must be defined previously in module */
+   /* notice must be converted to number immediately else can have */
+   /* circular dependency */
+   /* LRM requires source order definition before use */
+   /* SJM 08/07/96 */
+   if (__expr_has_glb(__root_ndp) || !__src_rd_chk_paramexpr(__root_ndp, 0))
+    {
+     __pv_ferr(1025,
+      "defparam right hand side \"%s\" illegal - parameters and constants only",
+      __msgexpr_tostr(__xs, __root_ndp));
+     /* need to still add value of x to prevent further errors */
+     __free2_xtree(__root_ndp);
+     __root_ndp->szu.xclen = WBITS;
+     __set_numval(__root_ndp, ALL1W, ALL1W, WBITS);  
+    }
+   /* SJM 01/27/04 - must leave as rhs expr since just gets evaled */
+   /* bug if convert when downward propagation of defparams used on rhs */
+   /* of other defparams used */
+
+   /* notice cannot check rhs here since defparam statement rhs can be */
+   /* any local parameter(possibly defined later in source) from LRM */ 
+   dfpp = alloc_dfpval();
+   dfpp->dfpxlhs = lhsndp;
+   dfpp->dfpxrhs = __root_ndp;
+   dfpp->in_mdp = __inst_mod;
+
+   /* must always put on end of list - order important */
+   /* since reading in source order list stays in source order */
+   /* within each module */
+   if (__end_dfp == NULL) __inst_mod->mdfps = dfpp;
+   else __end_dfp->dfpnxt = dfpp;
+   __end_dfp = dfpp;
+
+   /* can be comma separated assignment list */
+   if (__toktyp == SEMI) break;
+   if (__toktyp != COMMA)
+    {
+     __pv_ferr(1039,
+      "defparam semicolon or comma separator expected - %s read",
+      __prt_vtok());
+     goto err_cont;
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * allocate a module defparam structure for later processing
+ */
+static struct dfparam_t *alloc_dfpval(void)
+{
+ struct dfparam_t *dfpp;
+
+ dfpp = (struct dfparam_t *) __my_malloc(sizeof(struct dfparam_t));
+ dfpp->dfpxlhs = NULL;
+ dfpp->dfpxrhs = NULL;
+ dfpp->in_mdp = NULL;
+ dfpp->dfpfnam_ind = __cur_fnam_ind;
+ dfpp->dfplin_cnt = __lin_cnt;
+ dfpp->dfp_local = FALSE;
+ dfpp->dfp_rooted = FALSE;
+ dfpp->dfp_done = FALSE;
+ dfpp->dfp_mustsplit = FALSE;
+ dfpp->dfp_has_idents = FALSE;
+ dfpp->dfp_checked = FALSE;
+ dfpp->dfpnxt = NULL;
+
+ dfpp->dfpiis = NULL;
+ dfpp->last_dfpi = -1;
+ dfpp->gdfpnam = NULL;
+ dfpp->targsyp = NULL;
+ dfpp->idntmastdfp = NULL;
+ dfpp->idntnxt = NULL;
+ dfpp->rooted_dfps = NULL;
+ dfpp->dfptskp = NULL;
+ return(dfpp);
+}
+
+/*
+ * TASK DEFINITION ROUTINES
+ * here because uses common declaration code
+ */
+
+/*
+ * process a task definition
+ * know task or function keyword read, reads the endtask
+ * no F return on error, since either build d.s. or not
+ */
+static int32 rd_task(void)
+{
+ struct st_t *stp;
+
+ __lofp_port_decls = FALSE;
+ __get_vtok();
+ if (__toktyp != ID)
+  {
+   __pv_ferr(1130, "task name expected - %s read", __prt_kywrd_vtok());
+sync_to_endtask:
+   /* could change to dummy tsk name and continue here */
+   /* but for now must find ENDTASK or skip to module level item */
+   if (__vskipto_modend(ENDTASK)) return(TRUE);
+   __syncto_class = SYNC_FLEVEL;
+   return(FALSE);
+  }
+ /* FALSE means previously defined - must not read */
+ if (!__bld_tsk(__token, TASK)) goto sync_to_endtask;
+  
+ __get_vtok();
+ if (__toktyp == LPAR)
+  {
+   /* if couldn't sync to end of list of tf decls list ); */
+   if (!rd_tf_list_of_ports_decl(__cur_tsk, "task"))
+    {
+     switch ((byte) __syncto_class) {
+      case SYNC_FLEVEL: case SYNC_MODLEVEL: return(FALSE);
+      case SYNC_STMT: __get_vtok(); goto more_stmts;
+      default: __case_terr(__FILE__, __LINE__);
+     }
+    }
+   if (__toktyp == RPAR) __get_vtok();
+  }
+ if (__toktyp != SEMI)
+  {
+   __pv_ferr(1131,
+    "task declaration name not followed by semicolon - %s read",
+    __prt_vtok());
+  }
+ else __get_vtok();
+
+ /* first decl. type token read */
+ if (!__rd_tfdecls("task")) return(FALSE);
+more_stmts:
+ if ((stp = __rd_stmt()) == NULL)
+  {
+   switch ((byte) __syncto_class) {
+    case SYNC_FLEVEL: case SYNC_MODLEVEL: return(FALSE);
+    case SYNC_STMT: __get_vtok(); goto more_stmts;
+    case SYNC_TARG: break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+  }
+ /* only one task statement */
+ __cur_tsk->tskst = stp;
+ __get_vtok();
+ if (__toktyp != ENDTASK)
+  {
+   __pv_ferr(1132, "endtask expected - %s read", __prt_vtok());
+   /* must free task symbol table on error */
+   if (__top_sti > 0) __top_sti = 0;
+   /* this will sync to next module item if possible */
+   return(__vskipto_any(ENDTASK));
+  }
+ __cur_tsk->tsk_last_lini = __lin_cnt;
+ __cur_tsk->tsk_last_ifi = __cur_fnam_ind;
+
+ __get_vtok();
+ if (__toktyp == SEMI)
+  __pv_ferr(999, "semicolon following endtask illegal"); 
+ else __unget_vtok();
+ /* if error will not get linked in to module's task list */
+ if (__end_tbp == NULL) __inst_mod->mtasks = __cur_tsk;
+ else __end_tbp->tsknxt = __cur_tsk;
+ __end_tbp = __cur_tsk;
+ /* symbols no longer accessible */
+ __top_sti--;
+ return(TRUE);
+}
+
+/*
+ * build a task structure from declaration (label block/task/function)
+ * expects task name and return task symbol - __cur_tsk set to inited task
+ * notice that this does not link task into task chain
+ */
+extern int32 __bld_tsk(char *tnam, int32 tsktok)
+{
+ int32 tstyp;
+ struct symtab_t *upsyt;
+ struct sy_t *syp;
+ char s1[RECLEN], s2[RECLEN];
+
+ if (*tnam == '$')
+  {
+   __pv_ferr(1133, "system function or task %s cannot be redefined", tnam);
+   return(FALSE);
+  }
+ tstyp = to_tasksytyp(tsktok);
+ 
+ /* must be find sym since if redefines something higher error */
+ syp = __find_sym(tnam);
+ if (!__sym_is_new)
+  {
+   /* if disable caused decl. as task, change to named block */
+   if (syp->sytyp == SYM_TSK && tstyp == SYM_LB) syp->sytyp = SYM_LB;
+   if (syp->sydecl || syp->sytyp != tstyp)
+    {
+     __pv_ferr(1134,
+     "%s definition of \"%s\" illegal - previously defined as %s at %s",
+      __get_vkeynam(s1, tsktok), __token, __to_sytyp(s2, syp->sytyp),
+      __bld_lineloc(__xs, syp->syfnam_ind, syp->sylin_cnt));
+     return(FALSE);
+    }
+  }
+ /* possibilities include named block fork and join */
+ syp->sytyp = tstyp;
+ __cur_tsk = __alloc_task(syp);
+ /* all different task types still point to etskp element */
+ syp->el.etskp = __cur_tsk;
+ syp->sydecl = TRUE;
+ syp->syfnam_ind = __cur_fnam_ind;
+ syp->sylin_cnt = __lin_cnt;
+
+ /* must also allocate the new symbol table */
+ __cur_tsk->tsksymtab = __alloc_symtab(TRUE);
+ __cur_tsk->tsktyp = tsktok;
+ /* link symbol table to object it is symbol of */
+ __cur_tsk->tsksymtab->sypofsyt = syp;
+ /* set list ends for elements that must be kept in order */
+ __end_tpp = NULL;
+ __end_tskparamnp = NULL;
+ __venviron[++__top_sti] = __cur_tsk->tsksymtab;
+
+ /* link in symbol table structure */
+ upsyt = __venviron[__top_sti - 1];
+ __cur_tsk->tsksymtab->sytpar = upsyt;
+ if (upsyt->sytofs == NULL) upsyt->sytofs = __cur_tsk->tsksymtab;
+ /* link on front */
+ else
+  {
+   __cur_tsk->tsksymtab->sytsib = upsyt->sytofs;
+   upsyt->sytofs = __cur_tsk->tsksymtab;
+  }
+ return(TRUE);
+}
+
+/*
+ * convert one of the task token types to corresponding symbol type
+ */
+static word32 to_tasksytyp(int32 ttyp)
+{
+ int32 styp;
+
+ styp = SYM_UNKN;
+ switch ((byte) ttyp) {
+  case TASK: styp = SYM_TSK; break;
+  case FUNCTION: styp = SYM_F; break;
+  case FORK: case Begin: styp = SYM_LB; break;
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(styp);
+}
+
+/*
+ * allocate a new task
+ */
+extern struct task_t *__alloc_task(struct sy_t *syp)
+{
+ struct task_t *tskp;
+
+ tskp = (struct task_t *) __my_malloc(sizeof(struct task_t));
+ init_task(tskp);
+ tskp->tsksyp = syp;
+ return(tskp);
+}
+
+/*
+ * initialize a task 
+ */
+static void init_task(struct task_t *tskp)
+{
+ tskp->tsksyp = NULL;
+ tskp->tsk_last_lini = -1;
+ tskp->tsk_last_ifi = -1;
+ tskp->tsktyp = UNDEF;
+ tskp->t_used = FALSE;
+ tskp->thas_outs = FALSE;
+ tskp->thas_tskcall = FALSE;
+ tskp->fhas_fcall = FALSE;
+ tskp->tf_lofp_decl = FALSE;
+ tskp->tsksymtab = NULL;
+ tskp->st_namblkin = NULL;
+ tskp->tskpins = NULL;
+ tskp->tsk_prms = NULL;
+ tskp->tprmnum = 0;
+ tskp->tsk_regs = NULL;
+ tskp->trnum = 0;
+ tskp->tskst = NULL;
+ tskp->tsknxt = NULL;
+ tskp->tthrds = NULL;
+}
+
+/*
+ * ROUTINES TO READ AND ADD LIST OF PORTS STYLE TASK/FUNC HEADER PORT DECLS 
+ */
+
+/*
+ * read list of task/func header port declarations
+ * new alternative ANSII style port header decl form added to 2001 LRM
+ *
+ * initial ( read and reads ending );
+ * think now () form legal
+ *
+ * if return T, even if error parsing can continue in module
+ * on error must sync to end of tf list of decls ')' - if not returns F
+ * and sets sync class to right place to continue in t/f
+ * may also sync to ; on error with T return
+ */
+static int32 rd_tf_list_of_ports_decl(struct task_t *tskp, char *tftypnam)
+{
+ int32 first_time, wtyp, ptyp, attr_ttyp, has_attr, decl_signed;
+ struct sy_t *syp;
+ struct net_t *np;
+ struct expr_t *x1, *x2, *ox1, *ox2;
+ struct task_pin_t *tpp;
+ char s1[RECLEN];
+
+ ptyp = -1;
+ /* even if syntax error, T once a port type keyword appears in hdr */
+ tskp->tf_lofp_decl = TRUE;
+ __lofp_port_decls = TRUE;
+
+ __get_vtok();
+ for (;;)
+  {
+   if (__toktyp == RPAR)
+    {
+     __pv_fwarn(3136,
+      "%s %s header list of ports decl form - but list of ports empty",
+      tftypnam, tskp->tsksyp->synam);
+     /* assuming this forces list of ports header form */ 
+     return(TRUE);
+    }
+
+   if (__toktyp != INPUT && __toktyp != OUTPUT && __toktyp != INOUT)
+    {
+     __pv_ferr(3422, "%s list of ports form port direction expected - %s read",
+      tftypnam, __prt_kywrd_vtok());
+     if (!__vskipto_lofp_end()) return(FALSE); 
+     return(TRUE);
+    }
+
+   /* attribute collected by scanner - but need to save so associates with */
+   /* right port */
+   if (__attr_prefix)
+    {
+     __wrk_attr.attr_tok = __toktyp;
+     __wrk_attr.attr_seen = TRUE;
+     /* for now this is unparsed entire attr. string */
+     __wrk_attr.attrnam = __pv_stralloc(__attrwrkstr);
+     __wrk_attr.attr_fnind = __attr_fnam_ind;
+     __wrk_attr.attrlin_cnt = __attr_lin_cnt;
+    }
+   else __wrk_attr.attr_seen = FALSE;
+
+   attr_ttyp = __toktyp; 
+   if (__toktyp == INPUT) ptyp = IO_IN;
+   else if (__toktyp == OUTPUT) ptyp = IO_OUT;
+   else if (__toktyp == INOUT) ptyp = IO_BID;
+   else __case_terr(__FILE__, __LINE__); 
+
+   __get_vtok();
+
+   /* defaults to reg if net type omitted - can be var/reg type */
+   if ((wtyp = __fr_wtnam(__toktyp)) != -1) __get_vtok();
+   else wtyp = N_REG;
+
+   if (wtyp == N_INT || wtyp == N_REAL) decl_signed = TRUE;
+   else decl_signed = FALSE;
+   /* vectored or scalared keywords never appear in port decls */
+
+   if (__toktyp == SIGNED)
+    {
+     decl_signed = TRUE;
+     if (wtyp == N_TIME || wtyp == N_INT || wtyp == N_REAL
+      || wtyp == N_EVENT) 
+      {
+       __pv_ferr(3423,
+        "signed keyword illegal when task or function variable has type %s",
+        __to_wtnam2(s1, wtyp));
+      }
+     __get_vtok();
+    }
+
+   /* even if error if 1 past ending ] continue */
+   if (!__rd_decl_rng(&ox1, &ox2))
+    {
+     /* bad decl - but if sync to new I/O port direction, caller will cont */
+     if (!__vskipto_lofp_end()) return(FALSE); 
+     if (__toktyp == RPAR) return(TRUE); 
+     /* semi read */
+     return(TRUE);
+    }
+
+   /* use local has attr flag so can turn glb seen off before return */
+   if (__wrk_attr.attr_seen)
+    { has_attr = TRUE; __wrk_attr.attr_seen = FALSE; }
+   else has_attr = FALSE;
+
+   x1 = x2 = NULL;
+   for (first_time = TRUE;;)
+    {
+     if (__toktyp != ID)
+      {
+       __pv_ferr(992,
+        "%s header list of port form %s port name expected - %s read",
+        tftypnam, __to_ptnam(s1, ptyp), __prt_kywrd_vtok());
+
+       if (__vskipto2_lofp_end())
+        {
+         if (__toktyp == SEMI) return(TRUE);
+         if (__toktyp == RPAR) { __get_vtok(); return(TRUE); }
+         /* only other possibility is the port name separating comma */
+         continue;
+        }
+       /* can't recover (resync) from error - synced to module item */
+       return(FALSE);
+      }
+
+     /* SJM 05/25/04 - must just search for redeclare in tf sym tab */
+     if ((syp = __get_sym(__token, __venviron[__top_sti])) != NULL)
+      {
+       __pv_ferr(3418,
+        "%s header list of ports form %s port name %s redeclared", 
+        tftypnam, __to_ptnam(s1, ptyp), __token);
+       goto nxt_port;
+      }
+
+     if (first_time) { x1 = ox1; x2 = ox2; first_time = FALSE; } 
+     else
+      {
+       if (x1 == NULL) x1 = x2 = NULL;
+       else { x1 = __copy_expr(ox1); x2 = __copy_expr(ox2); }
+      }
+
+     /* first declare the port's wire/reg */
+     if ((np = decl_taskvar(wtyp, x1, x2)) == NULL) goto nxt_port;
+
+     /* if previously used will be treated as reg - must set to compatible */
+     /* wire type if declared as time or int32 */
+     syp = np->nsym;
+
+     /* if saw an (* *) attribute for module item token, seen on */
+     if (has_attr)
+      {
+       /* this add to net's attr list on end if also net decl first */
+       add_net_attr(np, attr_ttyp);
+      }
+
+     /* SJM 10/02/03 - signed can be turned on either in port or wire decl */ 
+     if (decl_signed) np->n_signed = TRUE;
+     np->iotyp = ptyp;
+
+     /* alloc port and add to end of list - order here crucial */
+     tpp = alloc_tskpin();
+     tpp->tpsy = syp;
+     tpp->trtyp = ptyp;
+
+     /* although with hdr list of ports form list known, for other form */
+     /* don't know task/func ports until end of task/func */ 
+     if (__end_tpp == NULL) __cur_tsk->tskpins = tpp;
+     else __end_tpp->tpnxt = tpp;
+     __end_tpp = tpp;
+
+nxt_port:
+     __get_vtok();
+     if (__toktyp == RPAR) return(TRUE);
+
+     if (__toktyp != COMMA)
+      {
+       __pv_ferr(995,
+        "%s list of ports form declaration list comma or right paren expected - %s read",
+        tftypnam, __prt_vtok());
+       /* try to resync */
+       if (!__vskipto_lofp_end()) return(FALSE); 
+       if (__toktyp == COMMA) goto nxt_var;
+       /* misplaced semi or sync to rpar */
+       return(TRUE);
+      }
+nxt_var:
+     __get_vtok();
+     if (__toktyp == INPUT || __toktyp == OUTPUT || __toktyp == INOUT)  
+      break;
+    }
+  }
+ __misc_terr(__FILE__, __LINE__);
+ return(TRUE);
+}
+
+/*
+ * read task declarations
+ * notice in any kind of task, function, or named block, decls come first
+ * with one statement at end
+ * expects first token to have been read and reads start of 1st statement
+ */
+extern int32 __rd_tfdecls(char *tftypnam)
+{
+ word32 wtyp, pntyp;
+
+ for (;;)
+  {
+   /* routines called in switch expected to read ending ; or token */
+   switch((byte) __toktyp) {
+    case TEOF:
+     __pv_ferr(1135, "%s unexpected EOF", tftypnam);
+     return(FALSE);
+    case PARAMETER:
+     /* this add to symbol table and list */
+     /* notice for these, if error but synced to ;, still returns T */
+     if (!rd_paramdecl(FALSE)) 
+      {
+tfdecl_sync:
+       switch ((byte) __syncto_class) {
+        case SYNC_FLEVEL: return(FALSE);
+        case SYNC_MODLEVEL: break;
+        /* statement follows task decls */
+        case SYNC_STMT: return(TRUE);
+        case SYNC_TARG: break;
+        default: __case_terr(__FILE__, __LINE__);
+       }
+      }
+     break;
+    case INOUT:
+     pntyp = IO_BID;
+     goto decl_port;
+    case OUTPUT:
+     pntyp = IO_OUT;
+     goto decl_port;
+    case INPUT: 
+     pntyp = IO_IN;
+decl_port:
+     if (!rd_taskvardecl(pntyp, TRUE, tftypnam)) goto tfdecl_sync;
+     break;
+    case REG:
+     wtyp = N_REG;
+do_tfwdecl:
+     if (!rd_taskvardecl(wtyp, FALSE, tftypnam)) goto tfdecl_sync;
+     break;
+    case TIME: wtyp = N_TIME; goto do_tfwdecl;
+    case INTEGER: wtyp = N_INT; goto do_tfwdecl;
+    case REAL: case REALTIME: wtyp = N_REAL; goto do_tfwdecl;
+    case EVENT:
+     if (!rd_eventdecl(TRUE)) goto tfdecl_sync;
+     break;
+    default:
+     /* assume start of statement */
+     goto decl_end;
+   }
+   __get_vtok();
+  }
+decl_end:
+ return(TRUE);
+}
+
+/*
+ * read and process a task reg/time/int/real declaration
+ * know reg type read and reads final semi
+ */
+static int32 rd_taskvardecl(word32 regwtyp, int32 is_io, char *tftypnam)
+{
+ int32 decl_signed, first_time, ttyp, has_attr;
+ word32 wtyp;
+ struct sy_t *syp;
+ struct net_t *np;
+ struct task_pin_t *tpp;
+ struct expr_t *x1, *x2, *ox1, *ox2, *xa1, *xa2;
+ char s1[RECLEN], s2[RECLEN];
+
+ ttyp = __toktyp;
+ if (is_io) wtyp = N_REG; else wtyp = regwtyp;
+ /* SJM 10/02/03 - need sign bit for reals even though always signed */
+ if (wtyp == N_INT || wtyp == N_REAL) decl_signed = TRUE;
+ else decl_signed = FALSE;
+ __get_vtok();
+
+ if (__toktyp == SIGNED)
+  {
+   decl_signed = TRUE;
+   if (wtyp == N_TIME || wtyp == N_INT || wtyp == N_REAL || wtyp == N_EVENT) 
+    {
+     __pv_ferr(3423,
+      "signed keyword illegal when task or function variable type %s",
+      __to_wtnam2(s1, wtyp));
+    }
+   __get_vtok();
+  }
+
+ if (!__rd_decl_rng(&ox1, &ox2))
+  {
+   if (!__vskipto2_any(SEMI, RSB)) return(FALSE); 
+   if (__toktyp == SEMI) return(TRUE);
+   __get_vtok();
+  }
+ if (ox1 != NULL)
+  {
+   if (wtyp == N_INT || wtyp == N_TIME || wtyp == N_REAL
+    || wtyp == N_EVENT)
+    {
+     __pv_ferr(1142, "%s %s %s vector range illegal", tftypnam,
+      __to_wtnam2(s1, wtyp), __token);
+     x1 = x2 = NULL;
+    }
+  }
+ /* use local has attr flag so can turn glb seen of before return */
+ if (__wrk_attr.attr_seen) { has_attr = TRUE; __wrk_attr.attr_seen = FALSE; }
+ else has_attr = FALSE;
+ for (first_time = TRUE;;)
+  {
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1140, "%s declaration name of reg expected - %s read",
+      tftypnam, __prt_kywrd_vtok());
+bad_end:
+     return(__vskipto_any(SEMI));
+    }
+
+   /* any port decl illegal - new ones or re-decls */
+   if (__lofp_port_decls)
+    {
+     if (is_io)
+      {
+       __pv_ferr(3421,
+       "port declaration of \"%s\" illegal - list of ports declaration form used",
+       __prt_kywrd_vtok());
+       /* if I/O decl, know read entire decl, i.e. can't be array */
+       goto nxt_var; 
+      }
+     else
+      {
+       if (((syp = __get_sym_env(__token)) != NULL) && syp->sytyp == SYM_N
+        && syp->el.enp->iotyp != NON_IO)
+        {
+         __pv_ferr(3421,
+          "%s declaration of port \"%s\" illegal - %s uses list of ports declarations form",
+          __to_wtnam2(s1, wtyp), __prt_kywrd_vtok(), tftypnam);
+
+         /* here may need to skip the possible array decl */
+         if (!__vskipto2_any(COMMA, SEMI)) return(FALSE); 
+         if (__toktyp == SEMI) return(TRUE);
+         goto nxt_var;
+        }
+      }
+    }
+
+   /* each time through need to call this to make copy */
+   if (ox1 == NULL) set_reg_widths(wtyp, &x1, &x2);
+   else if (first_time) { x1 = ox1; x2 = ox2; first_time = FALSE; }
+   else { x1 = __copy_expr(ox1); x2 = __copy_expr(ox2); }
+
+   /* this handles all normal wire setting and checking */
+   if ((np = decl_taskvar(wtyp, x1, x2)) == NULL)
+    {     
+     /* if no np, cannot read possible declaration - must skip over it */
+     if (__toktyp == LSB)
+      {
+       if (!__vskipto2_any(SEMI, RSB)) return(FALSE); 
+       if (__toktyp == SEMI) return(TRUE);
+       __get_vtok();
+      } 
+     goto nxt_var;
+    }
+   syp = np->nsym;
+
+   /* SJM - 03/20/00 - save reg decl attrs */
+   /* if saw an (* *) attribute for module item token, seen on */
+   if (has_attr) add_net_attr(np, ttyp);
+
+   __get_vtok();
+   /* notice task/function ports do not allow array syntax */
+   /* also notice no strength or wire delay syntax */
+   if (is_io) xa1 = xa2 = NULL;
+   else
+    {
+     if (!__rd_decl_rng(&xa1, &xa2))
+      {
+       if (!__vskipto2_any(SEMI, RSB)) return(FALSE); 
+       if (__toktyp == SEMI) return(TRUE);
+       __get_vtok();
+      }
+     if (xa1 != NULL && wtyp == N_EVENT)
+      {
+       __pv_ferr(1143, "%s %s %s cannot be a array", tftypnam,
+        __to_wtnam2(s1, wtyp), syp->synam);
+       xa1 = xa2 = NULL;
+      }
+    }
+   if (xa1 != NULL)
+    { np->n_isarr = TRUE; np->nu.ct->ax1 = xa1; np->nu.ct->ax2 = xa2; }
+   if (decl_signed) np->n_signed = TRUE;
+
+   if (is_io)
+    {
+     /* check for repeated I/O decls - wrong */
+     if (np->iotyp != NON_IO)
+      {
+       if (np->iotyp == regwtyp)
+        {
+         __pv_fwarn(574, "%s %s port declaration of \"%s\" repeated",
+	  tftypnam, __to_ptnam(s1, regwtyp), syp->synam);
+	}
+       else
+        {
+         __pv_ferr(1144, "%s %s port %s previously declared as %s port",
+          tftypnam, __to_ptnam(s1, regwtyp), syp->synam,
+          __to_ptnam(s2, np->iotyp));
+	 goto nxt_var;
+        }
+      }
+     np->iotyp = regwtyp;
+     /* alloc port and add to end of list - order here crucial */
+     tpp = alloc_tskpin();
+     tpp->tpsy = syp;
+     tpp->trtyp = regwtyp;
+     if (__end_tpp == NULL) __cur_tsk->tskpins = tpp;
+     else __end_tpp->tpnxt = tpp;
+     __end_tpp = tpp;
+    }
+
+nxt_var:
+   if (__toktyp == SEMI) break;
+   if (__toktyp != COMMA)
+    {
+     __pv_ferr(1145,
+      "%s reg declaration list comma or semicolon expected - %s read",
+      tftypnam, __prt_vtok());
+     goto bad_end;
+    }
+   __get_vtok();
+  }
+ return(TRUE);
+}
+
+/*
+ * add the task variable type decl. symbol and associated reg
+ * caller must set reg type after checking for duplicates
+ * returns null on error
+ */
+static struct net_t *decl_taskvar(word32 wtyp, struct expr_t *x1,
+ struct expr_t *x2)
+{
+ struct net_t *np;
+ struct sy_t *syp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ syp = __decl_sym(__token, __venviron[__top_sti]);
+ if (__sym_is_new)
+  {
+   np = __add_net(syp);
+   np->iotyp = NON_IO;
+   if (x1 != NULL)
+    {
+     np->nu.ct->n_rngknown = TRUE;
+     np->n_isavec = TRUE;
+     np->nu.ct->nx1 = x1;
+     np->nu.ct->nx2 = x2;
+    }
+   np->ntyp = wtyp;
+   syp->sydecl = TRUE;
+   /* even if used before, must set to declaration place */
+   syp->syfnam_ind = __cur_fnam_ind;
+   syp->sylin_cnt = __lin_cnt;
+  }
+ else
+  {
+   if (syp->sytyp != SYM_N)
+    {
+     __pv_ferr(1028,
+      "cannot declare %s as %s - previously declared as %s at %s",
+      syp->synam, __to_wtnam2(s2, wtyp), __to_wtnam2(s1, syp->sytyp),
+      __bld_lineloc(__xs, syp->syfnam_ind, syp->sylin_cnt));
+     return(NULL);
+    }
+   /* wire/reg decl. after I/O decl. may set range */
+   np = syp->el.enp;
+   /* need special handling for I/O ports - declared in header, */
+   /* I/O direction and maybe wire */
+   if (np->iotyp != NON_IO)
+    {
+     /* task vars can be anthing providing output is lhs */
+     /* this only has meaning for I/O port redecls */
+     if (np->nu.ct->n_wirtypknown)
+      {
+       __pv_ferr(1146, "%s port %s previously declared as %s cannot be %s",
+	__to_ptnam(s1, np->iotyp), syp->synam, __to_wtnam(s2, np),
+	__to_wtnam2(s3, wtyp));
+       /* must cause skipping because no np */
+       return(NULL);
+      }
+    }
+   else { if (is_decl_err(syp, SYM_N, wtyp)) return(NULL); }
+   np->ntyp = wtyp;
+   if (!chkset_wdrng(np, x1, x2)) return(NULL);
+   np->nu.ct->n_wirtypknown = TRUE;
+
+   /* if I/O decl follows reg decl, symbol uses I/O decl. place */
+   if (np->iotyp != NON_IO)
+    {
+     syp->sydecl = TRUE;
+     /* even if used before, must set to declaration place */
+     syp->syfnam_ind = __cur_fnam_ind;
+     syp->sylin_cnt = __lin_cnt;
+    }
+  }
+ return(np);
+}
+
+/*
+ * allocate a task pin (port) list element
+ */
+static struct task_pin_t *alloc_tskpin(void)
+{
+ struct task_pin_t *tpp;
+
+ tpp = (struct task_pin_t *) __my_malloc(sizeof(struct task_pin_t));
+ tpp->tpsy = NULL;
+ tpp->trtyp = NON_IO;
+ tpp->tpnxt = NULL;
+ return(tpp);
+}
+
+/*
+ * process a function definition
+ * keyword function reads and reads decl. and final endfunction
+ * no F return on error since either build d.s. or not
+ */
+static int32 rd_func(void)
+{
+ int32 frwtyp, decl_signed;
+ word32 rhigh;
+ struct st_t *stp;
+ struct expr_t *x1, *x2, *dx1, *dx2;
+
+ __lofp_port_decls = FALSE;
+ dx1 = dx2 = NULL;
+ decl_signed = FALSE;
+ __get_vtok();
+ if (__toktyp == SIGNED)
+  {
+   decl_signed = TRUE;
+   __get_vtok();
+  }
+
+ if (__toktyp == LSB)
+  {
+   if (!__rd_decl_rng(&dx1, &dx2))
+    {
+     if (!__vskipto2_any(SEMI, RSB)) return(FALSE); 
+     if (__toktyp == SEMI) return(TRUE);
+     __get_vtok();
+    }
+  } 
+ /* if not a wire - assume next token is func. name (if not error below) */
+ /* this is 1 bit wire if not range */
+ if ((frwtyp = __fr_wtnam(__toktyp)) == -1)
+  { frwtyp = N_REG; x1 = dx1; x2 = dx2; }
+ else
+  {
+   if (frwtyp == N_EVENT || frwtyp < NONWIRE_ST)
+    {
+     __pv_ferr(1141, "function cannot return type %s", __prt_vtok());
+     frwtyp = N_REG;
+     x1 = x2 = NULL;
+     goto get_funcnam;
+    }
+  switch ((byte) frwtyp) {
+   case N_REAL:
+    rhigh = REALBITS - 1;
+    goto chk_norng;
+   case N_INT:
+    rhigh = WBITS - 1;
+chk_norng:
+    if (dx1 != NULL)
+     {
+      __pv_ferr(1149,
+       "function returning %s range illegal", __to_wtnam2(__xs,
+       (word32) frwtyp));
+     }
+    x1 = __bld_rng_numxpr(rhigh, 0L, WBITS);
+    x2 = __bld_rng_numxpr(0L, 0L, WBITS);
+    break;
+   case N_TIME:
+    rhigh = TIMEBITS - 1;
+    goto chk_norng;
+   default:
+    __case_terr(__FILE__, __LINE__);
+    return(FALSE);
+  }
+  __get_vtok();
+ }
+
+get_funcnam:
+ if (__toktyp != ID)
+  {
+   __pv_ferr(1148, "function name expected - %s read", __prt_kywrd_vtok());
+no_sym:
+   if (__vskipto_modend(ENDFUNCTION)) return(TRUE);
+   __syncto_class = SYNC_FLEVEL;
+   return(FALSE);
+  }
+ if (!__bld_tsk(__token, FUNCTION)) goto no_sym;
+ 
+ if (decl_signed && (frwtyp == N_TIME || frwtyp == N_INT || frwtyp == N_REAL)) 
+  {
+   __pv_ferr(3423,
+    "signed keyword illegal when function declaration return type %s",
+    __to_wtnam2(__xs, frwtyp));
+  }
+ if (frwtyp == N_INT || frwtyp == N_REAL) decl_signed = TRUE;
+ add_funcretdecl(__token, (word32) frwtyp, x1, x2, decl_signed);
+
+ __get_vtok();
+ if (__toktyp == LPAR)
+  {
+   /* if couldn't sync to end of list of tf decls list ); */
+   if (!rd_tf_list_of_ports_decl(__cur_tsk, "function"))
+    {
+     switch ((byte) __syncto_class) {
+      case SYNC_FLEVEL: case SYNC_MODLEVEL: return(FALSE);
+      case SYNC_STMT: __get_vtok(); goto more_stmts;
+      default: __case_terr(__FILE__, __LINE__);
+     }
+    }
+   if (__toktyp == RPAR) __get_vtok();
+  }
+
+ if (__toktyp != SEMI)
+  {
+   __pv_ferr(1153,
+    "function declaration name not followed by semicolon - %s read",
+    __prt_vtok());
+  }
+ else __get_vtok();
+
+ if (!__rd_tfdecls("function")) return(FALSE); 
+more_stmts:
+ if ((stp = __rd_stmt()) == NULL)
+  {
+   /* only get here on error */
+   if (__toktyp == ENDFUNCTION)
+    {
+     __get_vtok();
+     if (__toktyp == SEMI)
+      __pv_ferr(999, "semicolon following endfunction illegal"); 
+     else __unget_vtok();
+     return(TRUE);
+    }
+   switch ((byte) __syncto_class) {
+    case SYNC_FLEVEL: case SYNC_MODLEVEL: return(FALSE);
+    /* legally only 1 stmt - but try to parse all */
+    case SYNC_STMT:
+     __get_vtok();
+     goto more_stmts;
+    case SYNC_TARG: break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+  }
+ __cur_tsk->tskst = stp;
+ __get_vtok();
+ if (__toktyp != ENDFUNCTION)
+  {
+   __pv_ferr(1154, "endfunction expected - %s read", __prt_vtok());
+   /* if missing endfunction, need to deallocate symbol table */
+   if (__top_sti > 0) __top_sti = 0;
+   return(__vskipto_any(ENDFUNCTION));
+  }
+ /* set line of end */
+ __cur_tsk->tsk_last_lini = __lin_cnt;
+ __cur_tsk->tsk_last_ifi = __cur_fnam_ind;
+
+ /* if error will not get linked in to module's task list */
+ /* notice functions get linked in task order on module task list */
+ if (__end_tbp == NULL) __inst_mod->mtasks = __cur_tsk;
+ else __end_tbp->tsknxt = __cur_tsk;
+ __end_tbp = __cur_tsk;
+ /* symbols no longer accessible */
+ __top_sti--;
+ return(TRUE);
+}
+
+/*
+ * add implicit first output port return value decl. to task d.s.
+ */
+static void add_funcretdecl(char *rvnam, word32 frwtyp,
+ struct expr_t *x1, struct expr_t *x2, int32 decl_signed)
+{
+ struct sy_t *syp;
+ struct net_t *np;
+ struct task_pin_t *tpp;
+
+ /* notice symbol already in one up task decl. also name of port */
+ syp = __decl_sym(rvnam, __venviron[__top_sti]);
+ /* function declaration symbol table inconsisent */
+ if (!__sym_is_new) __misc_fterr(__FILE__, __LINE__);
+
+ np = __add_net(syp);
+ if (x1 != NULL)
+  {
+   np->nu.ct->n_rngknown = TRUE;
+   np->n_isavec = TRUE;
+   np->nu.ct->nx1 = x1;
+   np->nu.ct->nx2 = x2;
+  }
+ np->iotyp = IO_OUT;
+ np->ntyp = frwtyp;
+ np->nu.ct->n_rngknown = TRUE;
+ np->nu.ct->n_iotypknown = TRUE;
+ np->nu.ct->n_wirtypknown = TRUE;
+ if (decl_signed) np->n_signed = TRUE; else np->n_signed = FALSE;
+
+ syp->sydecl = TRUE;
+ syp->syfnam_ind = __cur_fnam_ind;
+ syp->sylin_cnt = __lin_cnt;
+
+ /* alloc port and add to end of list - order here crucial */
+ tpp = alloc_tskpin();
+ tpp->tpsy = syp;
+ tpp->trtyp = IO_OUT;
+ if (__end_tpp == NULL) __cur_tsk->tskpins = tpp;
+ else __end_tpp->tpnxt = tpp;
+ __end_tpp = tpp;
+}
+
+/*
+ * INSTANCE READING ROUTINES
+ */
+
+/*
+ * [module type] [# param list] [inst] ([mod connections]) ;
+ * [udp/prim type] [strength] [#param list] [inst] ([prim. conn.]);
+ */
+
+/*
+ * read an instance - treat as if not yet defined or resolved
+ * module type name read, reads final ;
+ * at this point do not know if instance, gate or udp
+ * return F if synced to next mod/prim else T if synced to ; even if err
+ */
+static int32 rd_inst(char *typnam)
+{
+ int32 first_time, has_iname, strenval, has_attr;
+ struct cell_t *cp;
+ struct sy_t *syp;
+ struct tnode_t *tnp;
+ struct namparam_t *nprmhdr; 
+ struct expr_t *x1, *x2;
+ char s1[IDLEN];
+
+ nprmhdr = NULL;
+ first_time = TRUE;
+ __v0stren = __v1stren = NO_STREN;
+ has_iname = TRUE;
+ x1 = x2 = NULL;
+
+ /* must go here because for gate maybe no inam */
+ /* use local has attr flag so can turn glb seen of before return */
+ if (__wrk_attr.attr_seen) { has_attr = TRUE; __wrk_attr.attr_seen = FALSE; }
+ else has_attr = FALSE;
+
+ if (*typnam == '$')
+  {
+   __pv_ferr(1042,
+   "instance/gate type \"%s\" cannot begin with $ - reserved for system tasks",
+    typnam);
+bad_end:
+   return(__vskipto_any(SEMI));
+  }
+ __get_vtok();
+ if (__toktyp == LPAR)
+  {
+   __get_vtok();
+   if (is_tokstren(__toktyp) == NO_STREN)
+    {
+     sprintf(s1, "__gate$$%d", __cp_num);
+     has_iname = FALSE;
+     goto no_inam;
+    }
+   /* need special strength read routine for pull */
+   if (strcmp(typnam, "pullup") == 0 || strcmp(typnam, "pulldown") == 0)
+    {
+     if (!rd_pull_stren(typnam, &strenval)) goto bad_stren;
+
+     /* here syntax good but strength values illegal - assume strong */
+     /* error already emitted */
+     if (strenval == NO_STREN)
+      {
+       if (strcmp(typnam, "pullup") == 0) strenval = STRONG1;
+       else strenval = STRONG0;
+      }
+     /* LOOKATME - both strength must be same and right selected one */
+     /* since simualtion uses low 3 bits of strength value */ 
+     __v0stren = __v1stren = strenval;  
+     __get_vtok();
+     goto rd_parms;
+    }
+
+   if (!rd_verstrens())
+    {
+bad_stren:
+     if (!__vskipto2_any(RPAR, SEMI)) return(FALSE);
+     if (__toktyp == RPAR) { __get_vtok(); goto rd_parms; }
+     /* bad strengths do not provide any punctuation to sync to */
+     return(TRUE);
+    }
+  }
+
+rd_parms:
+ if (__toktyp == SHARP)
+  {
+   if ((nprmhdr = rd_npndparams()) == NULL) goto bad_end;
+  }
+ else nprmhdr = NULL;
+
+ for (;;)
+  {
+   if (__toktyp == LPAR)
+    {
+     /* name is [module name]$[unique number] */
+     sprintf(s1, "__gate$$%d", __cp_num);
+     has_iname = FALSE;
+    }
+   else
+    {
+     if (__toktyp != ID)
+      {
+       __pv_ferr(1043, "instance/gate name for type \"%s\" expected - %s read",
+        typnam, __prt_kywrd_vtok());
+       /* resyncing of comma list of same type insts not port lists */ 
+       if (!__vskipto2_any(COMMA, SEMI)) return(FALSE); 
+       if (__toktyp == SEMI) return(TRUE);
+       __get_vtok();
+       continue;
+      }
+     strcpy(s1, __token);
+     __get_vtok();
+     /* new arrays of gates/instances [h:l] becomes "_"[number] suffix later */
+     /* if no range, this just returns T and sets x1 and x2 to nil */
+     /* if range, sets x1, x2 and reads one past ] */
+     if (!__rd_decl_rng(&x1, &x2))
+      {
+       if (!__vskipto2_any(SEMI, RSB)) return(FALSE); 
+       if (__toktyp == SEMI) return(TRUE);
+       __get_vtok();
+      }
+     if (__toktyp != LPAR)
+      {
+       __pv_ferr(1044,
+        "instance/gate \"%s\" type \"%s\" connection list expected - %s read",
+  	s1, typnam, __prt_vtok());
+        goto bad_end;     
+      }
+    }
+   __get_vtok();
+no_inam:
+   /* if port errors just inst. with no ports */
+   if ((cp = add_cell(s1)) != NULL)
+    {
+     /* no checking for type sep. name space - if never decled err later */
+     tnp = __vtfind(typnam, __modsyms);
+     if (__sym_is_new)
+      {
+       __add_sym(typnam, tnp);
+       (__modsyms->numsyms)++;
+       syp = tnp->ndp;
+       syp->sytyp = SYM_M;
+       /* getting here means module/udp referenced before defined */
+       /* and only place mod/udp can be seen */
+       __add_syp_to_undefs(syp);
+      }
+     else syp = tnp->ndp;
+     /* AIV 06/01/04 - mark all as not in config - config processing */ 
+     /* will mark as true later */ 
+     syp->cfg_needed = FALSE;
+     /* instance must be named, error caught only after lib. processed */
+     /* using inst. num that is unused until design wide checking */
+     if (has_iname) cp->c_named = TRUE;
+     if (x1 != NULL) { cp->cx1 = x1; cp->cx2 = x2; } 
+
+     cp->cmsym = syp;
+     if (first_time) cp->c_nparms = nprmhdr;
+     else cp->c_nparms = copy_namparamlst(nprmhdr);
+     if (__v0stren != NO_STREN) 
+      {
+       cp->c_hasst = TRUE;
+       cp->c_stval = ((__v0stren << 3) | __v1stren) & 0x3f;
+      }
+    }
+   /* if synced to ;, T even if errors */ 
+   if (!rd_iports(s1)) return(TRUE);
+   if (cp != NULL) cp->cpins = __cphdr;
+
+   /* if saw an (* *) attribute for module item token, seen on */
+   if (has_attr)
+    {
+     if (cp != NULL) add_cell_attr(cp);
+    }
+
+   __get_vtok();
+   if (__toktyp == SEMI) break;
+   first_time = FALSE;
+   if (__toktyp == COMMA) { __get_vtok(); continue; }
+
+   __pv_ferr(1048,
+   "instance or gate terminal list ending semicolon or comma missing - %s read",
+    __prt_vtok());
+   /* must find a semi to continue */
+   goto bad_end;
+  }
+ return(TRUE);
+}
+
+/*
+ * add an inst attribute 
+ */
+static void add_cell_attr(struct cell_t *cp)
+{
+ /* DBG remove -- */
+ if (cp->cattrs != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* need to set token type so each parsed attr_spec has right tok type */
+ __wrk_attr.attr_tok = MODULE;
+
+ /* return nil on error */
+ cp->cattrs = __rd_parse_attribute(&__wrk_attr);
+ /* SJM 07/30/01 - this is work read value, but now done with it */
+ __my_free(__wrk_attr.attrnam, __attr_line_len + 1);
+ __wrk_attr.attr_seen = FALSE;
+}
+
+/*
+ * read the pull strength
+ * know leading '(' and strength read, reads optional second , stren and
+ * then ending ')' or just ending ')'
+ * on F return trys to sync to ending ')' or ';'
+ *
+ * SJM 10/01/99 - allow both 0 and 1 strength where unused one dropped 
+ * required by 1999 LRM
+ *
+ * where two strengths given, drops unused one here
+ * know ehen called first token is some kind of strength
+ */
+static int32 rd_pull_stren(char *pullnam, int32 *strenval)
+{
+ int32 st1typ, st1val, st2val, st2typ, err_seen; 
+ int32 strentyp, strenval1, strenval2;
+
+ err_seen = FALSE;
+ st1typ = st2typ = strentyp = NO_STREN;
+ st1val = st2val = TOK_NONE;
+ *strenval = NO_STREN;
+ /* know 1st required */
+ st1val = __toktyp;
+ if ((st1typ = is_tokstren(__toktyp)) == CAP_STREN || st1typ == NO_STREN)
+  {
+   __pv_ferr(1032, "%s strength %s non driving or illegal", pullnam,
+    __prt_vtok());  
+   st1typ = NO_STREN;
+   err_seen = TRUE;
+  }
+
+ __get_vtok();
+ if (__toktyp == COMMA)
+  {
+   /* second strength present */
+   __get_vtok();
+   st2val = __toktyp;
+   if ((st2typ = is_tokstren(__toktyp)) == CAP_STREN || st2typ == NO_STREN)
+    {
+     __pv_ferr(1032, "%s second strength %s non driving or illegal", pullnam,
+      __prt_vtok());  
+     st2typ = NO_STREN;
+     err_seen = TRUE;
+    }
+   __get_vtok();
+  }
+ if (__toktyp != RPAR)
+  {
+   __pv_ferr(1031, "%s strength ending ')' expected - %s read", pullnam,
+    __prt_vtok());
+   return(FALSE);
+  }
+ if (err_seen) return(TRUE);
+
+ /* know one or two strengths read and legal */
+ /* case 1: old only one strength form - check to make sure right type */
+ if (st2typ == NO_STREN)
+  {
+   strentyp = st1typ; 
+   /* map from strength token to strength constant value */
+   *strenval = __fr_stren_nam(st1val);
+   if (strcmp(pullnam, "pullup") == 0)
+    {
+     if (strentyp == LOW_STREN) 
+      {
+       __pv_fwarn(608,
+        "%s single strength form low (0) strength %s should be high (1) - changed", 
+        pullnam, __to1_stren_nam(__xs, *strenval, st1typ));
+      }
+    } 
+   else
+    {
+     if (strentyp == HIGH_STREN) 
+      {
+       __pv_fwarn(608,
+        "%s single strength form high (1) strength %s should be low (0) - changed", 
+        pullnam, __to1_stren_nam(__xs, *strenval, st1typ));
+      }
+    }
+   if (*strenval == ST_HIGHZ)
+    {
+     __pv_ferr(1018,
+      "highz strength illegal for single strength form %s gate",
+      pullnam);
+     strentyp = NO_STREN;
+     *strenval = NO_STREN;
+    }
+   return(TRUE);
+  }
+ /* case 2 */
+ /* make sure not both 0 strens and not both 1 strens */
+ if (st1typ == LOW_STREN && st2typ == LOW_STREN)
+  {
+   __pv_ferr(1032, "%s two strength form both strengths low (0)", pullnam);
+   return(TRUE);
+  }
+ if (st1typ == LOW_STREN && st2typ == LOW_STREN)
+  {
+   __pv_ferr(1032, "%s two strength form both strengths high (1)", pullnam);
+   return(TRUE);
+  }
+ /* map from strength token to strength constant value for both */
+ strenval1 = __fr_stren_nam(st1val);
+ strenval2 = __fr_stren_nam(st2val);
+ if (strenval1 == ST_HIGHZ || strenval2 == ST_HIGHZ)
+  {
+   __pv_ferr(1018, "highz strength illegal as either strength for %s gate",
+    pullnam);
+   strentyp = NO_STREN;
+   *strenval = NO_STREN;
+   return(TRUE);
+  }
+ /* select right strength from two */
+ if (strcmp(pullnam, "pullup") == 0)
+  {
+   if (st1typ == LOW_STREN) *strenval = strenval2; else *strenval = strenval1;
+  }
+ else
+  {
+   if (st1typ == HIGH_STREN) *strenval = strenval2; else *strenval = strenval1;
+  }
+ return(TRUE);
+}
+
+/*
+ * read a new style instance only old implicit or new explicit param form
+ *
+ * know # read and reads one past list ending ) - maybe only one and no ()
+ * must also read new style for gates since until types resolved do not
+ * know if gate or instance - error during fixup in new style for gate/udp
+ */
+static struct namparam_t *rd_npndparams(void)
+{
+ int32 prm_err;
+ struct namparam_t *npmphdr, *npmp, *last_npmp;
+
+ __get_vtok();
+ /* case 1: old #[one token] case */
+ if (__toktyp != LPAR)
+  {
+   /* notice must surround m:t:m with () */
+   if (__toktyp != ID && __toktyp != NUMBER && __toktyp != REALNUM)
+    {
+     __pv_ferr(1049,
+     "non parenthesized pound parameter one element identifier or number expected - %s read",
+      __prt_kywrd_vtok());
+     return(NULL);
+    }
+   __last_xtk = -1;
+   /* on error, set as error expr. - maybe since param should be 0 */
+   if (!__bld_expnode()) __set_xtab_errval();
+   /* here does the allocating */
+   __bld_xtree(0);
+   npmphdr = __alloc_namparam();
+   npmphdr->pxndp = __root_ndp;
+   npmphdr->prmfnam_ind = __cur_fnam_ind;
+   npmphdr->prmlin_cnt = __lin_cnt;
+   __get_vtok();
+   return(npmphdr);
+  }
+ 
+ /* case 2: #(...) - either , list (no empties) or explicit form */
+ for (npmphdr = NULL, last_npmp = NULL, prm_err = FALSE;;)
+  {
+   __get_vtok();
+
+   /* read the pound parameter (maybe new explicit form) and one token past */
+   /* illegal forms caught during fix up */
+   if ((npmp = rd1_namedparam()) == NULL) goto bad_skipend;
+   if (npmphdr == NULL) npmphdr = npmp; else last_npmp->nprmnxt = npmp;
+   last_npmp = npmp;
+
+   if (__toktyp == RPAR) break;
+   if (__toktyp == COMMA) continue;
+
+   __pv_ferr(1051, "pound parameter list comma or ) expected - %s read ",
+    __prt_vtok());
+
+bad_skipend:
+   prm_err = TRUE;
+   if (!__vskipto3_any(RPAR, COMMA, SEMI)) return(FALSE); 
+   if (__toktyp == COMMA) { __get_vtok(); continue; }
+   /* if ) or ; done and synced to right place */
+   if (__toktyp == SEMI) __unget_vtok();
+   break;
+  }
+ __get_vtok();
+
+ if (prm_err)
+  {
+   if (npmphdr != NULL) __free_namedparams(npmphdr);
+   return(NULL);
+  }
+ return(npmphdr);
+}
+
+/*
+ * read one instance (cell) or gate param (may have new named form)
+ *
+ * know 1st token read and reads punctuation after , or )
+ * returns built named param record 
+ *
+ * on error returns nil, caller (not in this routine) tries to resync
+ * on , and read next param * but on .[id](<some error> ..., this trys
+ * to resync to list ending ) 
+ *
+ * LOOKATME - allowing ,, form
+ */
+static struct namparam_t *rd1_namedparam(void)
+{
+ int32 namedparam_form, slcnt, sfnind;
+ struct namparam_t *npmp;
+ char nam[IDLEN];
+
+ slcnt = __lin_cnt;
+ sfnind = __cur_fnam_ind;
+ if (__toktyp == DOT)
+  {
+   __get_vtok();
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1052, "name of pound param expected - %s read",
+      __prt_kywrd_vtok());
+     return(NULL);
+    }
+   strcpy(nam, __token);
+   __get_vtok();
+   if (__toktyp != LPAR)
+    {
+     __pv_ferr(1053,
+      "pound param explicitly named form left parenthesis expected - %s read",
+      __prt_vtok());
+     return(NULL);
+    }
+   /* 1st token in expr. must be read */
+   __get_vtok();
+   /* explicit param name .[param]() for unc. is legal */
+   if (__toktyp == RPAR)
+    {
+     __last_xtk = 0;
+     __set_opempty(0);
+    }
+   else
+    {
+     /* need to collect delay expr. because min-typ-max without () ok */
+     if (!__col_delexpr()) return(NULL);
+    }
+   namedparam_form = TRUE;
+  }
+ else
+  {
+   namedparam_form = FALSE;
+   /* (, - ,, and ,) all legal */
+   if (__toktyp == COMMA || __toktyp == RPAR)
+    {  __last_xtk = 0; __set_opempty(0); }
+   else
+    {
+     /* need to collect delay expr. because min-typ-max without () ok */
+     if (!__col_delexpr()) return(NULL);
+    }
+  }
+ /* build the tree, copy/allocate nodes, sets __root_ndp to its root */
+ /* this must be a constant expr but checked later - this will decl */
+ __bld_xtree(0);
+
+ if (namedparam_form)
+  {
+   if (__toktyp != RPAR)
+    {
+     __pv_ferr(1055,
+      "explicitly named pound param form right parenthesis expected - %s read",
+      __prt_vtok());
+     return(NULL);
+    }
+   __get_vtok();
+   /* LOOKATME - why is this check here - think no longer needed */
+   /* but catching user or PLI sys function here does not hurt */
+   if (__root_ndp->optyp == FCALL )
+    {
+     struct sy_t *syp; 
+
+     /* only built in sysfuncs allowed - const args checked later */
+     syp = __root_ndp->lu.x->lu.sy;
+     if (syp->sytyp == SYM_SF && syp->el.esyftbp->tftyp == SYSF_BUILTIN)
+      goto named_ok;
+
+     __pv_ferr(1055,
+      "explicitly named pound param %s illegal -  not required .[name]([value])",
+      __msgexpr_tostr(__xs, __root_ndp));
+     return(NULL);
+    }
+  }
+named_ok:
+ npmp = __alloc_namparam();
+ npmp->pxndp = __root_ndp;
+ if (namedparam_form) npmp->pnam = __pv_stralloc(nam);
+ else npmp->pnam = NULL;
+ npmp->prmfnam_ind = sfnind;
+ npmp->prmlin_cnt = slcnt;
+ return(npmp);
+}
+
+/*
+ * free list of named param records
+ */
+extern void __free_namedparams(struct namparam_t *npmphdr)
+{
+ register struct namparam_t *npmp, *npmp2;
+ int32 slen;
+
+ for (npmp = npmphdr; npmp != NULL;)
+  {
+   npmp2 = npmp->nprmnxt;
+   
+   /* expr. may be nil, when freeing after expr. copied */
+   if (npmp->pxndp != NULL) __free_xtree(npmp->pxndp);
+   if (npmp->pnam != NULL)
+    {
+     slen = strlen(npmp->pnam);
+     __my_free((char *) npmp->pnam, slen + 1); 
+    }
+   __my_free((char *) npmp, sizeof(struct namparam_t));
+
+   npmp = npmp2;
+  }
+}
+
+/*
+ * add module symbol (possibly later changed to udp) to undef list
+ */
+extern void __add_syp_to_undefs(struct sy_t *syp)
+{
+ struct undef_t *undefp;
+
+ undefp = (struct undef_t *) __my_malloc(sizeof(struct undef_t));
+ undefp->msyp = syp;
+ undefp->undefnxt = NULL;
+ undefp->dfi = -1;
+ undefp->modnam = NULL; 
+ syp->syundefmod = TRUE;
+ syp->el.eundefp = undefp;
+ 
+ if (__undeftail == NULL)
+  {
+   __undeftail = __undefhd = undefp;
+   undefp->undefprev = NULL;
+  }
+ else 
+  {
+   undefp->undefprev = __undeftail;
+   __undeftail->undefnxt = undefp;
+   __undeftail = undefp;
+  } 
+ __undef_mods++;
+}
+
+/*
+ * copy possibly named param list 
+ *
+ * only needed during instance reading because converted to dellst form
+ * when module copying needed
+ */
+static struct namparam_t *copy_namparamlst(struct namparam_t *old_npmp)  
+{
+ register struct namparam_t *npmphdr, *npmp, *onpmp, *last_npmp;
+ 
+ if (old_npmp == NULL) return(NULL);
+
+ npmphdr = NULL;
+ last_npmp = NULL;
+ for (onpmp = old_npmp; onpmp != NULL; onpmp = onpmp->nprmnxt)
+  {
+   npmp = (struct namparam_t *) __my_malloc(sizeof(struct namparam_t));
+   /* since mallocing, need to fill all fields */
+   npmp->prmfnam_ind = onpmp->prmfnam_ind;
+   npmp->prmlin_cnt = onpmp->prmlin_cnt;
+   npmp->pxndp = __copy_expr(onpmp->pxndp);
+   if (onpmp->pnam != NULL) npmp->pnam = __pv_stralloc(onpmp->pnam);
+   else npmp->pnam = NULL;
+   npmp->nprmnxt = NULL;
+
+   if (last_npmp == NULL) npmphdr = npmp; else last_npmp->nprmnxt = npmp;
+   last_npmp = npmp;
+  }
+ return(npmphdr);
+}
+
+/*
+ * allocate and initialize a inst/gate pound param record
+ */
+extern struct namparam_t *__alloc_namparam(void)
+{
+ struct namparam_t *npmp;
+
+ npmp = (struct namparam_t *) __my_malloc(sizeof(struct namparam_t));
+ npmp->pxndp = NULL;
+ npmp->prmfnam_ind = 0;
+ npmp->prmlin_cnt = -1;
+ npmp->pnam = NULL;
+ npmp->nprmnxt = NULL;
+ return(npmp);
+}
+
+/*
+ * make a copy of a param list
+ * know at copy point delay is DT_CMPLST list
+ */
+extern struct paramlst_t *__copy_dellst(struct paramlst_t *oplp)
+{
+ register struct paramlst_t *plp;
+ struct paramlst_t *nplphdr, *nplp, *last_nplp;
+
+ if (oplp == NULL) return(NULL);
+
+ nplphdr = NULL;
+ for (last_nplp = NULL, plp = oplp; plp != NULL; plp = plp->pmlnxt)
+  {
+   nplp = __alloc_pval();
+   nplp->plxndp = __copy_expr(plp->plxndp);
+   if (last_nplp == NULL) nplphdr = nplp; else last_nplp->pmlnxt = nplp;
+   nplp->pmlnxt = NULL;
+   last_nplp = nplp;
+  }
+ return(nplphdr);
+}
+
+/*
+ * read instance ports - probably no module def. at this point
+ * know 1st token of port expr. read and reads final )
+ */
+static int32 rd_iports(char *inam)
+{
+ for (__cphdr = NULL;;)
+  {
+   /* read the cell-pin reference and one token past */
+   /* illegal forms caught during fix up */
+   if (!rd_cpin_conn()) goto bad_trynxt;
+
+   if (__toktyp == RPAR) break;
+   if (__toktyp == COMMA) { __get_vtok(); continue; }
+   __pv_ferr(1051,
+    "instance/gate %s port connection list comma or ) expected - %s read ",
+    inam, __prt_vtok());
+
+bad_trynxt:
+   if (!__vskipto3_any(RPAR, COMMA, SEMI)) return(FALSE); 
+   if (__toktyp == COMMA) { __get_vtok(); continue; }
+   /* if ) or ; done and synced to right place */
+   if (__toktyp == SEMI) __unget_vtok();
+   break;
+  }
+ return(TRUE);
+}
+
+/*
+ * read an instance port connection
+ * know 1st token read and reads punctuation after , or )
+ * then adds to end of global cell pin list header __cphdr
+ *
+ * on error returns F, caller tries to resync on , and read next port
+ * but on .[id](<some error> ..., this trys to resync to port ending ) 
+ */
+static int32 rd_cpin_conn(void)
+{
+ int32 namedport_form;
+ struct cell_pin_t *cpp;
+
+ if (__toktyp == DOT)
+  {
+   __get_vtok();
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1052,
+      "instance/gate connection name of port expected - %s read",
+      __prt_kywrd_vtok());
+     return(FALSE);
+    }
+   strcpy(__portnam, __token);
+   __get_vtok();
+   if (__toktyp != LPAR)
+    {
+     __pv_ferr(1053,
+      "explicit port name form left parenthesis expected - %s read",
+      __prt_vtok());
+     return(FALSE);
+    }
+   /* 1st token in expr. must be read */
+   __get_vtok();
+   /* instance connection .[port]() for unc. is legal */
+   if (__toktyp == RPAR)
+    {
+     __last_xtk = 0;
+     __set_opempty(0);
+     /* need to leave right paren in token since checked for later */
+    }
+   else
+    {
+     if (!__col_parenexpr(-1)) 
+      {
+       /* if can resync to ) move to next tok - then caller resyncs again */
+       if (__vskipto_modend(RPAR)) __get_vtok();
+       return(FALSE);
+      }
+    }
+   namedport_form = TRUE;
+  }
+ else
+  {
+   namedport_form = FALSE;
+   /* (, - ,, and ,) all legal */
+   if (__toktyp == COMMA || __toktyp == RPAR)
+    {  __last_xtk = 0; __set_opempty(0); }
+   else { if (!__col_connexpr(-1)) return(FALSE); }
+  }
+ /* this declares undeclared wire */
+ /* build the tree, copy/allocate nodes, sets __root_ndp to its root */
+ __bld_xtree(0);
+
+ if (namedport_form)
+  {
+   if (__toktyp != RPAR)
+    {
+     __pv_ferr(1055,
+      "instance explicit named port form right parenthesis expected - %s read",
+      __prt_vtok());
+     if (__vskipto_modend(RPAR)) { __get_vtok(); return(TRUE); } 
+     return(FALSE);
+    }
+   __get_vtok();
+  }
+ /* this save the global portnam as a string if present */
+ cpp = __alloc_cpin(namedport_form);
+ cpp->cpxnd = __root_ndp;
+ if (__cphdr == NULL) __cphdr = cpp; else __cpp_last->cpnxt = cpp;
+ __cpp_last = cpp;
+
+ return(TRUE);
+}
+
+/*
+ * allocate a cell pin - fill mostly from global data
+ */
+extern struct cell_pin_t *__alloc_cpin(int32 has_name)
+{
+ struct cell_pin_t *cpp;
+
+ cpp = alloc_memcpins();
+ if (has_name) cpp->pnam = alloc_cpnam(__portnam);
+ else cpp->pnam = NULL;
+ cpp->cplin_cnt = __lin_cnt;
+ cpp->cpfnam_ind = __cur_fnam_ind;
+ cpp->cpxnd = NULL;
+ cpp->cpnxt = NULL;
+
+ return(cpp);
+}
+
+/*
+ * allocate a string element a preallocated block for fast freeing
+ */
+static char *alloc_cpnam(char *s)
+{
+ char *cp;
+ int32 slen, rem, real_size;
+ struct cpnblk_t *cpnbp;
+
+ slen = strlen(s) + 1;
+ if ((rem = slen % 4) != 0) real_size = slen + 4 - rem;
+ else real_size = slen;
+
+ if ((__hdr_cpnblks->cpn_start_sp + real_size + 4) >= 
+  __hdr_cpnblks->cpn_end_sp)
+  {
+   cpnbp = (struct cpnblk_t *) __my_malloc(sizeof(struct cpnblk_t));
+   cpnbp->cpnblknxt = __hdr_cpnblks;
+   __hdr_cpnblks = cpnbp;
+   cpnbp->cpnblks = cpnbp->cpn_start_sp = __my_malloc(BIG_ALLOC_SIZE);
+   cpnbp->cpn_end_sp = cpnbp->cpn_start_sp + BIG_ALLOC_SIZE - 16;
+  }
+ cp = __hdr_cpnblks->cpn_start_sp;
+ __hdr_cpnblks->cpn_start_sp += real_size;
+ strcpy(cp, s);
+ return(cp);
+}
+
+/*
+ * allocate a ncomp element from a preallocated block for fast freeing
+ */
+static struct cell_pin_t *alloc_memcpins(void)
+{
+ struct cppblk_t *cppbp;
+ struct cell_pin_t *cpp;
+
+ if (__cppblk_nxti == -1)
+  {
+   cppbp = (struct cppblk_t *) __my_malloc(sizeof(struct cppblk_t));
+   cppbp->cppblks = (struct cell_pin_t *) __my_malloc(BIG_ALLOC_SIZE);
+   cppbp->cppblknxt = __hdr_cppblks;
+   __hdr_cppblks = cppbp;
+   __cppblk_nxti = 0;
+  }
+ cpp = (struct cell_pin_t *) &(__hdr_cppblks->cppblks[__cppblk_nxti]);
+ if (++__cppblk_nxti > ((BIG_ALLOC_SIZE/sizeof(struct cell_pin_t)) - 1))
+  __cppblk_nxti = -1;
+ return(cpp);
+}
+
+/*
+ * add cell - better not be already defined at module top level
+ * at this point both gates and module instances cells
+ * cells always declared at top level
+ */
+static struct cell_t *add_cell(char *inam)
+{
+ struct cell_t *cp;
+ struct sy_t *syp;
+ char s1[RECLEN];
+
+ __cp_num++;
+ syp = __decl_sym(inam, __venviron[0]);
+ if (__sym_is_new)
+  {
+treat_as_new:
+   syp->sytyp = SYM_I;
+   cp = __alloc_cell(syp);
+   syp->el.ecp = cp;
+
+   syp->sydecl = TRUE;
+    /* this is place of declaration */
+   syp->syfnam_ind = __cur_fnam_ind;
+   syp->sylin_cnt = __lin_cnt;
+
+   /* must link on end to preserve inst. order */
+   if (__end_cp == NULL) __inst_mod->mcells = cp;
+   else __end_cp->cnxt = cp;
+   __end_cp = cp;
+   return(cp);
+  }
+ /* since symbol may be used as down 1 xmr in some system tasks */
+ /* if not declared just assume is instance - checked later */
+ if (syp->sytyp != SYM_I) 
+  {
+   if (syp->sydecl) 
+    {
+     __pv_ferr(1056, "instance/gate name %s previously declared as %s at %s",
+      syp->synam, __to_sytyp(s1, syp->sytyp),
+      __bld_lineloc(__xs, syp->syfnam_ind, syp->sylin_cnt));
+    }
+   else goto treat_as_new;
+  }
+ else __pv_ferr(1057, "instance/gate name %s repeated - previous %s",
+  syp->synam, __bld_lineloc(__xs, syp->syfnam_ind, syp->sylin_cnt));
+ return(NULL);
+}
+
+/*
+ * allocate the cell - at this point can be gate, udp or inst.
+ */
+extern struct cell_t *__alloc_cell(struct sy_t *syp)
+{
+ struct cell_t *cp;
+
+ /* alloc the element */
+ cp = alloc_memcell();
+ /* initialize contents union by zeroing all bytes of entire cell */
+ cp->csym = syp;
+ /* need to fill module type later */
+ cp->cmsym = NULL;
+ cp->cnxt = NULL;
+ cp->c_hasst = FALSE;
+ cp->c_stval = ST_STRVAL; 
+ cp->cp_explicit = FALSE;
+ cp->c_named = FALSE;
+ cp->c_iscell = FALSE;
+ cp->cx1 = cp->cx2 = NULL;
+ cp->c_nparms = NULL;
+ cp->cattrs = NULL;
+ cp->cpins = NULL;
+ return(cp);
+}
+
+/*
+ * allocate a ncomp element from a preallocated block for fast freeing
+ */
+static struct cell_t *alloc_memcell(void)
+{
+ struct cpblk_t *cpbp;
+ struct cell_t *cp;
+
+ if (__cpblk_nxti == -1)
+  {
+   cpbp = (struct cpblk_t *) __my_malloc(sizeof(struct cpblk_t));
+   cpbp->cpblks = (struct cell_t *) __my_malloc(BIG_ALLOC_SIZE);
+   cpbp->cpblknxt = __hdr_cpblks;
+   __hdr_cpblks = cpbp;
+   __cpblk_nxti = 0;
+  }
+ cp = (struct cell_t *) &(__hdr_cpblks->cpblks[__cpblk_nxti]);
+ if (++__cpblk_nxti > ((BIG_ALLOC_SIZE/sizeof(struct cell_t)) - 1))
+  __cpblk_nxti = -1;
+ return(cp);
+}
diff --git a/src/v_src2.c b/src/v_src2.c
new file mode 100644
index 0000000..58dbc5b
--- /dev/null
+++ b/src/v_src2.c
@@ -0,0 +1,4967 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * second source module for statement reading and expressions parsing
+ * tasks in src 3
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static struct st_t *rd_block(int32, int32);
+static struct st_t *convert_to_fork(struct st_t *);
+static int32 rd_lstofsts(int32, struct st_t **, int32, int32);
+static struct st_t *rd_namblock(int32, int32, int32, int32);
+static struct st_t *rd_if(void);
+static struct st_t *rd_case(int32);
+static struct st_t *rd_loop(int32);
+static struct st_t *rd_for(void);
+static struct st_t *rd_cause(void);
+static struct st_t *rd_disable(void);
+static struct expr_t *find_bldxpr_tfsy(char *, int32);
+static struct st_t *rd_wireassign(int32);
+static struct st_t *rd_wiredeassign(int32);
+static struct st_t *rd_taske_or_proc_assign(void);
+static struct st_t *rd_dctrl_st(void);
+static struct expr_t *rd_delctrl(int32 *, int32 *);
+static int32 col2_lval(void);
+static int32 col_dctrl_xmr(void);
+static int32 col_evctrlexpr(void);
+static void init_gref(struct gref_t *, char *);
+static struct expr_t *parse_qcexpr(void);
+static void xskip_toend(void);
+static struct expr_t *parse_boolorop(void);
+static struct expr_t *parse_boolandop(void);
+static struct expr_t *parse_borop(void);
+static struct expr_t *parse_bxorop(void);
+static struct expr_t *parse_bandop(void);
+static struct expr_t *parse_eqop(void);
+static struct expr_t *parse_ltgtop(void);
+static struct expr_t *parse_shop(void);
+static struct expr_t *parse_addop(void);
+static struct expr_t *parse_mulop(void);
+static struct expr_t *parse_unopterm(void);
+static void skip_3valend(void);
+static int32 is_unop(word32);
+static struct expr_t *parse_term(void);
+static int32 decl_id_inexpr(struct expr_t *, struct expridtab_t *);
+static struct expr_t *parse_concat(void);
+static struct expr_t *parse_select(struct expr_t *);
+static struct expr_t *parse_glbref(struct expr_t *, struct expridtab_t *);
+static struct expr_t *bld_1cmp_global(struct expr_t *, struct expridtab_t *);
+static char *alloc_glbndp_tostr(struct expr_t *);
+static void grow_grtab(void);
+static struct expr_t *parse_fcall(struct expr_t *, struct expridtab_t *, int32);
+static int32 chk_decl_func(int32 *, struct expr_t *, struct expridtab_t *);
+static void cnvt_forw_tfcall_1cmpglb(struct expr_t *, char *, int32, int32);
+static struct expr_t *parse_evexpr(void);
+static void grow_exprtab(void);
+static struct expr_t *my_xndalloc(void);
+static struct expr_t *alloc_xtnd(int32);
+static void set2_opempty(struct expr_t *);
+static char *to_xndnam(char *, int32 xndi);
+static word32 get_hash(word32 *, word32 *, int32);
+
+/* extern prototypes (maybe defined in this module) */
+extern char *__pv_stralloc(char *);
+extern char *__my_malloc(int32);
+extern char *__my_realloc(char *, int32, int32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char *__prt_vtok(void);
+extern char *__prt_kywrd_vtok(void);
+extern struct sy_t *__get_sym_env(char *);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern struct sy_t *__decl_sym(char *, struct symtab_t *);
+extern struct net_t *__add_net(struct sy_t *);
+extern char *__to_idnam(struct expr_t *);
+extern char *__to_sytyp(char *, word32);
+extern struct st_t *__alloc_stmt(int32);
+extern char *__get_vkeynam(char *, int32);
+extern void __find_matchendblk(int32, int32);
+extern void __find_matchendcase(void);
+extern int32 __col_caseexpr(void);
+extern struct exprlst_t *__alloc_xprlst(void);
+extern struct csitem_t *__alloc_csitem(void);
+extern char *__to_opname(word32);
+extern struct paramlst_t *__alloc_pval(void);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern char *__bld_lineloc(char *, word32, int32);
+extern struct gref_t *__bld_glbref(struct expr_t *, int32, int32);
+extern struct expr_t *__alloc_newxnd(void);
+extern void __get_vtok(void);
+extern void __unget_vtok(void);
+extern int32 __vskipto_any(int32);
+extern int32 __vskipto2_any(int32, int32);
+extern int32 __vskipto3_any(int32, int32, int32);
+extern int32 __vskipto4_any(int32, int32, int32, int32);
+extern int32 __bld_tsk(char *, int32);
+extern int32 __rd_tfdecls(char *);
+extern void __set_xtab_errval(void);
+extern void __bld_xtree(int32);
+extern void __bld_evxtree(void);
+extern int32 __col_parenexpr(int32);
+extern int32 __col_lval(void);
+extern int32 __col_comsemi(int32);
+extern void __resolve_glbnam(struct gref_t *);
+extern void __fill_grp_targu_fld(struct gref_t *);
+extern void __set_opempty(int32);
+extern int32 __col_connexpr(int32);
+extern int32 __bld_expnode(void);
+extern void __init_xnd(struct expr_t *);
+extern void __set_numval(struct expr_t *, word32, word32, int32);
+extern void __my_free(char *, int32);
+extern void __free2_xtree(struct expr_t *);
+extern struct st_t *__rd_tskenable(char *, struct expr_t *, int32);
+extern void __setup_contab(void);
+extern int32 __alloc_shareable_cval(word32, word32, int32);
+extern int32 __alloc_shareable_rlcval(double);
+extern int32 __alloc_is_cval(int32);
+extern int32 __allocfill_cval_new(word32 *, word32 *, int32);
+extern char *__alloc_vval_to_cstr(word32 *, int32, int32, int32);
+extern void __grow_contab(int32);
+extern struct expridtab_t *__alloc_expridnd(char *);
+extern struct expr_t *__alloc_exprnd(void);
+
+extern void __pv_ferr(int32, char *, ...);
+extern void __pv_fwarn(int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __my_fprintf(FILE *, char *, ...);
+extern void __fterr(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __misc_fterr(char *, int32);
+extern void __ia_err(int32 id_num, char *s, ...);
+
+extern struct opinfo_t __opinfo[];
+extern word32 __masktab[];
+
+/*
+ * STATEMENT PROCESSING ROUTINES
+ */
+
+/*
+ * read statement 
+ * expects 1st token read and reads ending ; or end or del. ctrl.
+ * statement routines allocate and return statement - caller links it in
+ *
+ * this routine cannot skip, but if it calls rd_stmt must handle skipping
+ */
+extern struct st_t *__rd_stmt(void)
+{
+ struct st_t *stp;
+
+ __saverr_cnt = __pv_err_cnt;
+ stp = NULL;
+ /* statement routines for bracketed statements will have skipped to end */
+ switch ((byte) __toktyp) {
+  case IF:
+   if ((stp = rd_if()) == NULL) return(NULL);
+   break;
+  case Begin:
+   /* will have skipped to block end on error */
+   /* if possible this returns list of statements instead of block */
+   if ((stp = rd_block(Begin, END)) == NULL) return(NULL);
+   break;
+  case FORK:
+   if ((stp = rd_block(FORK, JOIN)) == NULL) return(NULL);
+   break;
+  case SEMI:
+   stp = __alloc_stmt(S_NULL);
+   break;
+  case CASE: case CASEX: case CASEZ:
+   if ((stp = rd_case(__toktyp)) == NULL) return(NULL);
+   break;
+  case FOREVER: case WHILE: case WAIT: case REPEAT:
+   /* notice no repeat form del ctrls since repeat keyword indicates stmt */
+   if ((stp = rd_loop(__toktyp)) == NULL) return(NULL);
+   break;
+  case FOR:
+   if ((stp = rd_for()) == NULL) return(NULL);
+   break;
+  case SHARP: case AT:
+   if ((stp = rd_dctrl_st()) == NULL) return(NULL);
+   break;
+  case DISABLE:
+   if ((stp = rd_disable()) == NULL) return(NULL);
+   break;
+  case CAUSE:
+   if ((stp = rd_cause()) == NULL) return(NULL);
+   break;
+  case ASSIGN:
+   if ((stp = rd_wireassign(ASSIGN)) == NULL) return(NULL);
+   break;
+  case DEASSIGN:
+   if ((stp = rd_wiredeassign(DEASSIGN)) == NULL) return(NULL);
+   break;
+  case FORCE:
+   if ((stp = rd_wireassign(FORCE)) == NULL) return(NULL);
+   break;
+  case RELEASE:
+   if ((stp = rd_wiredeassign(RELEASE)) == NULL) return(NULL);
+   break;
+  /* these are resync error conditions - must handle out of sync to end */
+  case ENDTASK:
+  case ENDFUNCTION:
+  case ENDSPECIFY:
+   __pv_ferr(1060, "module item end bracket problem - %s read",
+    __prt_vtok());
+   /* SJM 01/18/1999 - must stay at module level end to try to finish */ 
+   /* item gracefully */
+   /* ??? __get_vtok(); */
+   __syncto_class = SYNC_MODLEVEL;
+   return(NULL);
+  case ENDCASE:
+  case END:
+  case JOIN:
+   __syncto_class = SYNC_STMT;
+bad_struct:
+   __pv_ferr(1061, "statement structure end bracket problem - %s read",
+    __prt_vtok());
+   __get_vtok();
+   return(NULL);
+  case ENDMODULE:
+  case ENDPRIMITIVE:
+  case ENDTABLE:
+   __syncto_class = SYNC_FLEVEL;
+   goto bad_struct;
+
+  /* non keyword - only 2 possibilities */
+  case ID: case LCB:
+   /* exactly 2 things can start proc lhs [id (glb ref)] = , {...} = */
+   /* also task enable [id (glb ref)](... legal - nothing else */
+   if ((stp = rd_taske_or_proc_assign()) == NULL) return(NULL);
+   break;
+  default:
+   __pv_ferr(1062, "statement starting token expected - %s read",
+    __prt_vtok());
+   /* must advance one token here else end = uu; never advances */
+   __get_vtok();
+   __vskipto_any(SEMI);
+   return(NULL);
+ }
+ return(stp);
+}
+
+/*
+ * read a sequential or fork/join block
+ * begin/fork read, reads end
+ * notice for unnamed begin-end block will return list of stmts
+ * with first have unb head turned on 
+ */
+static struct st_t *rd_block(int32 btok, int32 endbtok)
+{
+ int32 slcnt, sfnind;
+ struct st_t *stp, *hdstp;
+
+ slcnt = __lin_cnt;
+ sfnind = __cur_fnam_ind;
+ __get_vtok();
+ if (__toktyp == COLON)
+  {
+   if (__iact_state)
+    {
+     /* cannot catch this later because no declarations in interactive */
+     __pv_err_cnt++;
+     __ia_err(1431, "named blocks illegal in interactive mode");
+     return(NULL);
+    }
+   /* task without params embedded in statement list */
+   __cur_declobj = TASK;
+   stp = rd_namblock(btok, endbtok, slcnt, sfnind);
+   __cur_declobj = MODULE;
+   return(stp);
+  }
+ /* first step is to read list of statements in block */
+ /* if all statements in error will look like empty statement */
+ if (!rd_lstofsts(endbtok, &hdstp, __lin_cnt, __cur_fnam_ind)) return(NULL);
+ if (btok == Begin)
+  {
+   if (hdstp != NULL)
+    {
+     hdstp->st_unbhead = TRUE;
+     /* correct to line of begin */
+     /* ---
+     hdstp->stfnam_ind = sfnind;
+     hdstp->stlin_cnt = slcnt;
+     -- */
+    }
+   return(hdstp);
+  }
+ /* this can never return nil */ 
+ stp = convert_to_fork(hdstp);
+ /* correct to line of fork */
+ /* SJM ??? UNDO FOR RELEASE ---
+ stp->stfnam_ind = sfnind;
+ stp->stlin_cnt = slcnt;
+ --- */
+ return(stp);
+}
+
+/*
+ * convert a statement list to a fork-join statement
+ * 
+ * at this point st nxt fields point to next in list
+ * converts to table where nexts all empty and nil at end of table
+ */
+static struct st_t *convert_to_fork(struct st_t *hdstp)
+{
+ register int32 fji;
+ register struct st_t *stp;
+ int32 num_fjs;
+ struct st_t *stp2, *fjstp;
+
+ /* first count how many */
+ for (num_fjs = 0, stp = hdstp; stp != NULL; stp = stp->stnxt)
+  {
+   /* SJM 09/24/01 - for assign followed by for pair count as one */
+   if (stp->stmttyp == S_FORASSGN) continue;
+   num_fjs++;
+  }
+
+ /* know this is fork-join (never named) */
+ fjstp = __alloc_stmt(S_UNFJ);
+ /* one extra for nil fence at end */ 
+ fjstp->st.fj.fjstps = (struct st_t **)
+  __my_malloc((num_fjs + 1)*sizeof(struct st_t *));
+ fjstp->st.fj.fjlabs = (int32 *) __my_malloc((num_fjs + 1)*sizeof(int32));
+
+ /* fill table of ptrs to stmts */
+ /* for now leaving begin-end as unnamed block - not making st. list */ 
+ /* even if empty (because of error) need body as NULL statement */ 
+ for (stp = hdstp, fji = 0; fji < num_fjs; fji++)
+  {
+   /* SJM 09/24/01 - for for need both S FOR ASSIGN and for as one "block" */
+   /* since unnamed begin end blocks are just lists, works */
+   /* notice other setup inserted not inserted by here so can ignore */
+   if (stp->stmttyp == S_FORASSGN)
+    {
+     stp2 = stp->stnxt->stnxt;
+     fjstp->st.fj.fjstps[fji] = stp;
+     fjstp->st.fj.fjlabs[fji] = -1;
+     stp->stnxt->stnxt = NULL;
+    }
+   else
+    {
+     stp2 = stp->stnxt;
+     fjstp->st.fj.fjstps[fji] = stp;
+     fjstp->st.fj.fjlabs[fji] = -1;
+     /* fork-join is exactly one statement - unnamed block if begin-end */
+     stp->stnxt = NULL;
+    }
+   stp = stp2;
+  }
+ /* set ending fence */
+ fjstp->st.fj.fjstps[num_fjs] = NULL;
+ fjstp->st.fj.fjlabs[num_fjs] = -1;
+ return(fjstp);
+}
+
+/*
+ * read a statement list ending with block end token
+ * for contents of block, know block begin and optional label read
+ * reads block end token
+ * must use local variables since recursively nested blocks legal
+ */
+static int32 rd_lstofsts(int32 endbtok, struct st_t **stpp, int32 slcnt,
+ int32 sfnind)
+{
+ struct st_t *stp, *last_stp, *unbstp;
+
+ /* block body statements may be missing i.e begin end ok */
+ last_stp = NULL;
+ if (__toktyp == endbtok)
+  {
+   stp = __alloc_stmt(S_STNONE);
+   stp->stfnam_ind = sfnind;
+   stp->stlin_cnt = slcnt;
+   *stpp = stp;
+   return(TRUE);
+  }
+ for (*stpp = NULL;;)
+  {
+   /* on error, this attempts to read to 1 before next statement token */
+   /* this expects 1st token of statement to have been read */
+   if ((stp = __rd_stmt()) == NULL)
+    {
+     if (__syncto_class == SYNC_STMT || __syncto_class == SYNC_TARG)
+      {
+       __get_vtok();
+       if (__toktyp == TEOF)
+        { __syncto_class = SYNC_FLEVEL; return(FALSE); }
+       continue;
+      }
+     /* know hit module or file level thing - think unresyncable */
+     return(FALSE);
+    }
+   /* if statement is unnamed block, change normal list to unnamed block */ 
+   /* need since in list next already used */
+   /* but need lists for blocks normally so can insert gotos, etc. */
+   if (stp->st_unbhead)
+    {
+     unbstp = __alloc_stmt(S_UNBLK);
+     unbstp->st.sbsts = stp;
+     unbstp->stfnam_ind = sfnind;
+     unbstp->stlin_cnt = slcnt;
+     stp = unbstp;
+    }
+   /* try to parse as much as possible even if errors */
+   if (last_stp == NULL) *stpp = stp; else last_stp->stnxt = stp;
+   /* for returns 2 statement list - since reading list just 1 longer */
+   if (stp->stmttyp == S_FORASSGN) last_stp = stp->stnxt; 
+   else last_stp = stp;
+   __get_vtok();
+   if (__toktyp == endbtok) break;
+  }
+ return(TRUE);
+}
+
+/*
+ * read a named block
+ * know : read and reads block end token
+ * notice named block linked on task list and from stmt
+ * also notice body is pointer to statement that may or may not be list
+ */
+static struct st_t *rd_namblock(int32 btok, int32 endbtok, int32 slcnt,
+ int32 sfnind)
+{
+ struct task_t *sav_cur_tsk;
+ struct st_t *hdstp, *stp;
+
+ __get_vtok();
+ if (__toktyp != ID)
+  {
+   __pv_ferr(1063, "block label expected - %s read - skipped",
+     __prt_kywrd_vtok());
+   /* here just assume left out */
+   strcpy(__token, "**filler**");
+   __toktyp = ID;
+   __unget_vtok();
+  }
+ /* save cur. task - since recursively called and on stack nesting, works */
+ sav_cur_tsk = __cur_tsk;
+
+ /* this increments top sti and changes current task */
+ /* if error here, must give up - find like level end */
+ if (!__bld_tsk(__token, btok))
+  {
+   __find_matchendblk(btok, endbtok);
+   return(NULL);
+  }
+ /* illegal I/O decls here caught later */
+ __get_vtok();
+ /* allocate even though wasted if error since need line no. */
+ stp = __alloc_stmt(S_NAMBLK);
+ /* correct to line of begin */
+ stp->stlin_cnt = slcnt;
+ stp->stfnam_ind = sfnind;
+
+ /* statement has a task body as it data */
+ stp->st.snbtsk = __cur_tsk;
+ /* also fill back ptr to the one location named block task in */ 
+ __cur_tsk->st_namblkin = stp;
+
+ /* continues through all decls - even if error, if F then must give up */
+ /* T possible on error if hit statement */
+ if (!__rd_tfdecls("named block"))
+  {
+   __find_matchendblk(btok, endbtok);
+bad_end:
+   __top_sti--;
+   __cur_tsk = sav_cur_tsk;
+   return(NULL);
+  } 
+ /* according to grammar this must be a statement list */
+ /* format is begin/fork : [name] [decls?] [stmt list] end/join */
+ /* this will have sync to end of block - or mod/file level thing */
+ if (!rd_lstofsts(endbtok, &hdstp, sfnind, slcnt)) goto bad_end;
+ __cur_tsk->tsk_last_lini = __lin_cnt;
+ __cur_tsk->tsk_last_ifi = __cur_fnam_ind;
+
+ /* symbols no longer accessible */
+ __top_sti--;
+ if (btok == Begin) __cur_tsk->tskst = hdstp;
+ else __cur_tsk->tskst = convert_to_fork(hdstp);
+
+ /* must link named block on task list */
+ if (__end_tbp == NULL) __inst_mod->mtasks = __cur_tsk;
+ else __end_tbp->tsknxt = __cur_tsk;
+ __end_tbp = __cur_tsk;
+
+ __cur_tsk = sav_cur_tsk;
+ /* statement here is the pointer to the task */
+ return(stp);
+}
+
+/*
+ * find a matching end block (end or join)
+ */
+extern void __find_matchendblk(int32 btok, int32 endbtok)
+{
+ int32 blklev = 0;
+
+ for (;;)
+  {
+   if (__syncto_class != SYNC_STMT) return;
+   if (__vskipto2_any(btok, endbtok))
+    {
+     if (__toktyp == endbtok) { if (blklev <= 0) return; blklev--; }
+     else blklev++;
+    }
+  }
+}
+
+/*
+ * read if statement - if keyword read, reads statement end token
+ */
+static struct st_t *rd_if(void)
+{
+ struct st_t *stp, *thenstp, *elsestp;
+ struct expr_t *ifxnd;
+ int32 slcnt, sfnind;
+
+ slcnt = __lin_cnt;
+ sfnind = __cur_fnam_ind;
+ __get_vtok();
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(1064, "if not followed by required left parenthesis - %s read",
+    __prt_vtok());
+sync_xpr:
+   __vskipto3_any(RPAR, ELSE, SEMI);
+   if (__syncto_class == SYNC_TARG)
+    {
+     __set_xtab_errval();
+     __bld_xtree(0);
+     ifxnd = __root_ndp;
+     if (__toktyp == RPAR) goto rd_then;
+     thenstp = __alloc_stmt(S_NULL);
+     if (__toktyp == ELSE) goto rd_else;
+     /* skipped to ; */
+     goto maybe_else;
+    }
+   if (__syncto_class == SYNC_STMT)
+    {
+     __set_xtab_errval();
+     __bld_xtree(0);
+     ifxnd = __root_ndp;
+     goto rd_then;
+    }
+   /* something completely out of place */
+   __get_vtok();
+   return(NULL);
+  }
+ __get_vtok();
+ /* collection routines that fail must emit error */
+ if (!__col_parenexpr(-1))
+  {
+   goto sync_xpr;
+  }
+ /* need to build and save expr */
+ __bld_xtree(0);
+ ifxnd = __root_ndp;
+
+rd_then:
+ __get_vtok();
+ if ((thenstp = __rd_stmt()) == NULL)
+  {
+   if (__syncto_class == SYNC_STMT || (__syncto_class == SYNC_TARG
+    && __toktyp == SEMI))
+    {
+     thenstp = __alloc_stmt(S_NULL);
+     goto maybe_else;
+    }
+   /* anything else - return and caller syncs */
+   return(NULL);
+  } 
+maybe_else:
+ __get_vtok();
+ if (__toktyp == ELSE)
+  {
+rd_else:
+   __get_vtok();
+   if ((elsestp = __rd_stmt()) == NULL) return(NULL);
+  }
+ /* should try to get rid of this unget */
+ else
+  {
+   /* unget needed because routines expect to read 1st st. token */
+   if (__iact_state) 
+    {
+     __pv_err_cnt++; 
+     __ia_err(1432, "interactive if statement required else missing");
+     return(NULL);
+    }
+   __unget_vtok();
+   elsestp = NULL;
+  }
+ stp = __alloc_stmt(S_IF);
+ /* correct to line of if */
+ stp->stlin_cnt = slcnt;
+ stp->stfnam_ind = sfnind;
+
+ stp->st.sif.condx = ifxnd;
+ stp->st.sif.thenst = thenstp;
+ stp->st.sif.elsest = elsestp;
+ return(stp);
+}
+
+/*
+ * know case/casex,casez keyword read and reads endcase
+ */
+static struct st_t *rd_case(int32 casttyp)
+{
+ struct st_t *casp, *dflsp, *stp;
+ struct csitem_t *cip, *last_cip, *csihdr, *dflt_csip;
+ struct expr_t *csndp;
+ struct exprlst_t *csixhdr, *xplp, *last_xplp;
+ int32 slcnt, sfnind;
+
+ slcnt = __lin_cnt;
+ sfnind = __cur_fnam_ind;
+
+ __get_vtok();
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(1065,
+    "case statement selection expression left parenthesis expected - %s read",
+    __prt_vtok());
+bad_csx:
+   if (__vskipto2_any(RPAR, SEMI)) { __set_xtab_errval(); goto bld_csx; }
+   return(NULL);
+  }
+ __get_vtok();
+ if (!__col_parenexpr(-1)) goto bad_csx;
+bld_csx:
+ __bld_xtree(0);
+ csndp = __root_ndp;
+ for (last_cip = NULL, csihdr = NULL, dflsp = NULL;;)
+  {
+   __get_vtok();
+   switch ((byte) __toktyp) {
+    case ENDCASE: goto bld_case;
+    case DEFAULT:
+do_dflt:
+     __get_vtok();
+     if (__toktyp == COLON) __get_vtok();
+     if (dflsp != NULL)
+      __pv_ferr(1067, "more than one case default item not permitted");
+     if ((dflsp = __rd_stmt()) == NULL)
+      {
+       if (__vskipto_any(SEMI)) continue;
+       /* here must skip to endcase of right level and return */
+give_up:
+       __find_matchendcase();
+       return(NULL);
+      }
+     continue;
+    default:
+     /* expr. collection will fail if not required one expr. */
+     for (last_xplp = NULL, csixhdr = NULL;;)
+      {
+more_xprs:
+       if (!__col_caseexpr())
+        {
+         if (__vskipto3_any(COLON, SEMI, COMMA))
+          {
+           if (__toktyp == SEMI) goto nxt_case;
+           __set_xtab_errval();
+          }
+         else goto give_up;
+        }
+       __bld_xtree(0);
+       /* allocate and link in the expression list item */
+       xplp = __alloc_xprlst();
+       xplp->xp = __root_ndp;
+       if (last_xplp == NULL) csixhdr = xplp; else last_xplp->xpnxt = xplp;
+       last_xplp = xplp;
+
+       if (__toktyp != COMMA) break;
+       __get_vtok();
+      }
+     if (__toktyp != COLON)
+      {
+       __pv_ferr(1068, "case item expression list colon expected - %s read",
+        __prt_vtok());
+       if (__vskipto3_any(COLON, SEMI, COMMA))
+        {
+         if (__toktyp == SEMI) continue;
+         if (__toktyp == COLON) goto do_cstmt;
+         goto more_xprs;
+        }
+       else goto give_up;
+      }
+do_cstmt:
+     __get_vtok();
+     /* ; null statement ok here */
+     if ((casp = __rd_stmt()) == NULL)
+      {
+       if (__vskipto2_any(SEMI, DEFAULT))
+        {
+         if (__toktyp == DEFAULT) goto do_dflt;
+         continue;
+        }
+       else goto give_up;  
+      }
+     /* allocate and link in the case item element */
+     cip = __alloc_csitem();
+     cip->csixlst = csixhdr;
+     cip->csist = casp;
+     if (last_cip == NULL) csihdr = cip; else last_cip->csinxt = cip;
+     last_cip = cip;
+   }
+nxt_case:;
+  }
+bld_case:
+ stp = __alloc_stmt(S_CASE);
+ /* correct to line of case */
+ stp->stlin_cnt = slcnt;
+ stp->stfnam_ind = sfnind;
+
+ stp->st.scs.castyp = casttyp;
+ stp->st.scs.csx = csndp;
+
+ /* SJM 08/27/99 - change so no default in case rec but first on item list */
+ dflt_csip = __alloc_csitem();
+ dflt_csip->csixlst = NULL;
+ /* no default: indicated by first nil */
+ if (dflsp != NULL) dflt_csip->csist = dflsp; else dflt_csip->csist = NULL;
+
+ /* link onto front of list */
+ dflt_csip->csinxt = csihdr;
+ stp->st.scs.csitems = dflt_csip;
+ return(stp);
+}
+
+/*
+ * find a matching endcase
+ */
+extern void __find_matchendcase(void)
+{
+ int32 caselev = 0;
+ for (;;)
+  {
+   if (__syncto_class != SYNC_STMT) return;
+   if (__vskipto4_any(ENDCASE, CASE, CASEX, CASEZ))
+    {
+     if (__toktyp == ENDCASE) { if (caselev <= 0) return; caselev--; }
+     else caselev++;
+    }
+   else return;
+  }
+}
+
+/*
+ * allocate an expression list element
+ */
+extern struct exprlst_t *__alloc_xprlst(void)
+{
+ struct exprlst_t *xplp;
+
+ xplp = (struct exprlst_t *) __my_malloc(sizeof(struct exprlst_t));
+ xplp->xp = NULL;
+ xplp->xpnxt = NULL;
+ return(xplp);
+}
+
+/*
+ * allocate a case item - case statement is list of case items
+ */
+extern struct csitem_t *__alloc_csitem(void)
+{
+ struct csitem_t *cip;
+
+ cip = (struct csitem_t *) __my_malloc(sizeof(struct csitem_t));
+ cip->csixlst = NULL;
+ cip->csist = NULL;
+ cip->csinxt = NULL;
+ return(cip);
+}
+
+/*
+ * read a simple (non for) loop statement
+ */
+static struct st_t *rd_loop(int32 ttyp)
+{
+ struct st_t *stp, *repstp;
+ struct expr_t *loopx;
+ char s1[RECLEN];
+
+ /* notice this is done at 1st statement so no line number fix up */
+ if (ttyp == REPEAT) stp = __alloc_stmt(S_REPEAT);
+ else if (ttyp == WAIT) stp = __alloc_stmt(S_WAIT); 
+ else stp = __alloc_stmt(S_WHILE);
+ loopx = NULL;
+ repstp = NULL;
+
+ switch ((byte) ttyp) {
+  case FOREVER:
+   /* first build proc assign */
+   stp->stmttyp = S_FOREVER;
+   loopx = NULL;
+   __get_vtok();
+   if ((repstp = __rd_stmt()) == NULL) return(NULL);
+   break;
+  case REPEAT: 
+   stp->stmttyp = S_REPEAT;
+   goto get_expr;
+  case WHILE:
+   stp->stmttyp = S_WHILE;
+   goto get_expr;
+  case WAIT:
+   stp->stmttyp = S_WAIT;
+    /* here because wait expression globals need special xmrtype fields */
+get_expr:
+   __get_vtok();
+   if (__toktyp != LPAR)
+    {
+     __pv_ferr(1070,
+      "%s loop statement conditional expression not preceded by left parenthesis - %s read",
+      __get_vkeynam(s1, ttyp), __prt_vtok());
+sync_lpx:
+     if (__vskipto2_any(SEMI, RPAR))
+      {
+       if (__toktyp == RPAR) {  __set_xtab_errval(); goto bldx; }
+       __syncto_class = SYNC_STMT;
+      }
+     /* here have synced to beginning of next statement */
+     return(NULL);
+    }
+   __get_vtok();
+   if (!__col_parenexpr(-1)) goto sync_lpx;
+bldx:
+   __bld_xtree(0);
+   loopx = __root_ndp;
+   __get_vtok();
+   if ((repstp = __rd_stmt()) == NULL) return(NULL);
+   break;
+   default: __case_terr(__FILE__, __LINE__);
+  }
+ /* repeat tmp per inst. storage filed not set till preparation phase */
+ if (stp->stmttyp == S_REPEAT)
+  { stp->st.srpt.repx = loopx; stp->st.srpt.repst = repstp; }
+ else if (stp->stmttyp == S_WAIT)
+  { stp->st.swait.lpx = loopx; stp->st.swait.lpst = repstp; }
+ else { stp->st.swh.lpx = loopx; stp->st.swh.lpst = repstp; }
+ return(stp);
+}
+
+/*
+ * read a for statement
+ * know for token read and reads end of for body
+ * notice this returns 2 statement short list (since unnamed begin 
+ * returns list - this always is ok)
+ */
+static struct st_t *rd_for(void)
+{
+ struct for_t *frs;
+ struct st_t *stp, *inita, *inca, *forbd;
+ struct expr_t *lhsndp, *rhsndp, *stopndp;
+ int32 slcnt, sfnind;
+
+ slcnt = __lin_cnt;
+ sfnind = __cur_fnam_ind;
+
+ /* must read expressions separately for assigns */
+ /* first build initialization assign */
+ __get_vtok();
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(1071,
+    "for statement left parenthesis expected - %s read", __prt_vtok());
+bad_for:
+   if (__vskipto2_any(RPAR, SEMI))
+    {
+     if (__toktyp == SEMI) { inita = __alloc_stmt(S_NULL); goto bldtrmx; }
+    }
+rd_forst:
+   /* if module or file level item, just return caller will resync */
+   if (__syncto_class == SYNC_STMT || __syncto_class == SYNC_TARG)
+    {
+     __get_vtok();
+     __rd_stmt();
+    }
+   return(NULL);
+  }
+ __get_vtok();
+ /* collect lhs to = */
+ if (!__col_lval()) goto bad_for;
+ __bld_xtree(0);
+ lhsndp = __root_ndp;
+ __get_vtok();
+ if (!__col_comsemi(-1)) goto bad_for;
+ if (__toktyp != SEMI)
+  {
+   __pv_ferr(1076,
+    "for statement initial assignment ending semicolon expected - %s read",
+    __prt_vtok());
+   __vskipto_any(RPAR);
+   goto rd_forst;
+  }
+
+ __bld_xtree(0);
+ rhsndp = __root_ndp;
+ /* build proc assign */
+ inita = __alloc_stmt(S_FORASSGN);
+ inita->st.spra.lhsx = lhsndp;
+ inita->st.spra.rhsx = rhsndp;
+
+ /* build termination expression */
+bldtrmx:
+ __get_vtok();
+ if (!__col_comsemi(-1))
+  {
+   if (__vskipto2_any(RPAR, SEMI))
+    {
+     if (__toktyp == SEMI) { __set_xtab_errval(); goto bldcondx; } 
+    }
+   goto rd_forst;
+  }
+ if (__toktyp != SEMI)
+  {
+   __pv_ferr(1078,
+    "for statement termination expression ending semicolon expected - %s read",
+    __prt_vtok());
+   __vskipto_any(RPAR);
+   goto rd_forst;
+  }
+
+bldcondx:
+ __bld_xtree(0);
+ stopndp = __root_ndp;
+
+ /* collect assignment ending in ) */
+ __get_vtok();
+ /* collect lhs to = - this can only end with = */
+ if (!__col_lval())
+  {
+bad2_for:
+   if (__vskipto_any(RPAR)) { inca = __alloc_stmt(S_NULL); goto do_body; }
+   goto rd_forst;
+  }
+   
+ __bld_xtree(0);
+ lhsndp = __root_ndp;
+ __get_vtok();
+ if (!__col_parenexpr(-1)) goto bad2_for;
+ __bld_xtree(0);
+ rhsndp = __root_ndp;
+
+ /* build proc assign */
+ inca = __alloc_stmt(S_PROCA);
+ inca->st.spra.lhsx = lhsndp;
+ inca->st.spra.rhsx = rhsndp;
+
+do_body:
+ __get_vtok();
+ if ((forbd = __rd_stmt()) == NULL) return(NULL);
+
+ stp = __alloc_stmt(S_FOR);
+ /* correct to line of for */
+ stp->stlin_cnt = slcnt;
+ stp->stfnam_ind = sfnind;
+
+ frs = stp->st.sfor;
+ frs->forassgn = inita;
+ frs->fortermx = stopndp;
+ frs->forinc = inca;
+ frs->forbody = forbd;
+ /* notice for assign (initializer) inserted before for but for assgn */
+ /* still points back to it */
+ inita->stnxt = stp;
+ return(inita);
+}
+
+/*
+ * read a -> cause statement, know -> read and read ending ;
+ */
+static struct st_t *rd_cause(void)
+{
+ struct st_t *stp;
+ struct sy_t *syp;
+
+ __get_vtok();
+ if (!__col_comsemi(-1))
+  {
+skp_end:
+   __vskipto_any(SEMI);
+   return(NULL);
+  }
+ if (__toktyp != SEMI)
+  {
+   __pv_ferr(1072, "cause statement semicolon expected - %s read",
+    __prt_vtok());
+   goto skp_end;
+  }
+ __bld_xtree(0);
+ /* this error does not effect synchronization */
+ if (__root_ndp->optyp != ID && __root_ndp->optyp != GLBREF)
+  __pv_ferr(1073, "cause statement event name expected");
+ if (__toktyp == ID)
+  {
+   syp = __root_ndp->lu.sy;
+   /* if net wire and not declared, convert to event wire */
+   if (syp->sytyp == SYM_N && !syp->sydecl) syp->el.enp->ntyp = N_EVENT;
+   /* declaration errors caught later */
+  }
+ stp = __alloc_stmt(S_CAUSE);
+ stp->st.scausx = __root_ndp;
+ return(stp);
+}
+
+/*
+ * read a disable statement - must be check later
+ * know disable read
+ */
+static struct st_t *rd_disable(void)
+{
+ struct st_t *stp;
+ struct expr_t *dsxndp;
+ struct expridtab_t *xidp;
+ 
+ __get_vtok();
+ if (!__col_comsemi(-1))
+  {
+   __vskipto_any(SEMI);
+   return(NULL);
+  }
+ if (__toktyp != SEMI)
+  {
+   __pv_ferr(1129, "disable statement semicolon expected - %s read",
+    __prt_vtok());
+   return(NULL);
+  }
+ /* tricky code for simple local just ID task/named block disable */
+ /* can not parse because will be found incorrectly as local wire */
+ /* this is side effect of stupid xmr as expression new feature */
+ /* ending fence undef not yet added because bld xtree not called */ 
+ if (__last_xtk == 0 && __exprtab[0]->optyp == ID)
+  {
+   /* must allocate name of task or fixup if previously used */
+   xidp = __expr_idtab[0];
+   if ((dsxndp = find_bldxpr_tfsy(xidp->idnam, UNDEF)) == NULL) return(NULL);
+
+   /* also can't disable funcs - because run in no time but caught later */
+   stp = __alloc_stmt(S_DSABLE);
+   stp->st.sdsable.dsablx = dsxndp;
+   return(stp);
+  }
+ /* this must be xmr - because xmr now expressions must parse to construct */
+ __bld_xtree(0);
+ dsxndp = __root_ndp;
+ if (dsxndp->optyp != GLBREF)
+  {
+   __pv_ferr(1074,
+    "disable statement hierarchical named block or task name reference expected - %s read",
+    __msgexpr_tostr(__xs, dsxndp));
+   return(NULL);
+  }
+ stp = __alloc_stmt(S_DSABLE);
+ stp->st.sdsable.dsablx = dsxndp;
+ return(stp);
+}
+
+/*
+ * find (and maybe add) task symbol - only called for enable/disable
+ * know definition at top mod level and non gref
+ * may get here on named block disable (tfsytyp UNDEF) or enable
+ */
+static struct expr_t *find_bldxpr_tfsy(char *nam, int32 tfsytyp)
+{
+ struct expr_t *enable_ndp;
+ struct sy_t *syp;
+
+ /* if id declared in currently accessible name evironment use it */
+ if ((syp = __get_sym_env(nam)) != NULL)
+  {
+   /* if disable must check in disable statement fixup */
+   if (tfsytyp != UNDEF)
+    {
+     /* error if declared or used as non task */
+     /* illegal to enable or disable a function */
+     switch ((byte) syp->sytyp) {
+      case SYM_F: case SYM_I: case SYM_M: case SYM_PRIM: case SYM_UDP:
+      case SYM_N: case SYM_DEF:
+       {
+	char s1[RECLEN], s2[RECLEN];
+
+        if (syp->sydecl) strcpy(s1, "declared"); else strcpy(s1, "used");
+        __to_sytyp(s2, syp->sytyp);
+        __pv_ferr(963, "task or named block %s previously %s as %s at %s",
+	 syp->synam, s1, s2, __bld_lineloc(__xs, syp->syfnam_ind,
+         syp->sylin_cnt));
+        return(NULL);
+       }
+     }
+    }
+   /* rest of fields gets filled later - notice no width not in expr */
+   enable_ndp = __alloc_newxnd();
+   enable_ndp->optyp = ID;
+   enable_ndp->lu.sy = syp;
+   return(enable_ndp);
+  }
+ /* error if not declared in interactive command input */
+ if (__iact_state)
+  {
+   __pv_err_cnt++;
+   __ia_err(1435, "task or named block %s undeclared", nam);
+   return(NULL);
+  }
+
+ enable_ndp = __alloc_newxnd();
+ enable_ndp->optyp = ID;
+
+ /* here building the enable so just need to pass place holder - for fcall */
+ /* need the parsed expr where its insides are changed to xmr */
+ cnvt_forw_tfcall_1cmpglb(enable_ndp, nam, __cur_fnam_ind, __lin_cnt); 
+ return(enable_ndp);
+}
+
+/*
+ * read proc. quasi-cont assign - normal wire assign but only enable when
+ * time token moves here, force for wires and 2nd level of qc assign
+ */
+static struct st_t *rd_wireassign(int32 qcattyp)
+{
+ struct st_t *stp;
+ struct expr_t *lhsndp, *rhsndp;
+
+ /* allocate at top (wastes storage on error) to get line no. right */
+ stp = __alloc_stmt(S_QCONTA);
+ /* collect lhs to = */
+ __get_vtok();
+ if (!__col_lval())
+  {
+bad_qassgn:
+   __vskipto_any(SEMI);
+   return(NULL);
+  }
+ __bld_xtree(0);
+ /* must check later to make sure lvalue */
+ lhsndp = __root_ndp;
+
+ __get_vtok();
+ if (!__col_comsemi(-1)) goto bad_qassgn;
+ if (__toktyp != SEMI)
+  {
+   char s1[RECLEN];
+
+   if (qcattyp == FORCE) strcpy(s1, "force");
+   else if (qcattyp == ASSIGN) strcpy(s1, "quasi-continuous assign");
+   else __case_terr(__FILE__, __LINE__);
+
+   __pv_ferr(1076, "%s statement ending semicolon expected - %s read", s1,
+    __prt_vtok());
+   goto bad_qassgn;
+  }
+ __bld_xtree(0);
+ rhsndp = __root_ndp;
+
+ /* build quasi cont. assign */
+ stp->st.sqca->qcatyp = qcattyp;
+ /* assume reg. form - requried for assign/deassign */
+ stp->st.sqca->regform = TRUE;
+ stp->st.sqca->qclhsx = lhsndp;
+ stp->st.sqca->qcrhsx = rhsndp;
+ stp->st.sqca->rhs_qcdlstlst = NULL;
+ return(stp);
+}
+
+/*
+ * read wire deassign/release (difference is force arg. can be wire)
+ * form is deassign/release [lvalue];
+ */
+static struct st_t *rd_wiredeassign(int32 qcdeattyp)
+{
+ struct st_t *stp;
+
+ /* allocate at top (wastes storage on error) to get line no. right */
+ stp = __alloc_stmt(S_QCONTDEA);
+ /* collect lhs to = */
+ __get_vtok();
+ if (!__col_comsemi(-1))
+  {
+skp_end:
+   __vskipto_any(SEMI);
+   return(NULL);
+  }
+ if (__toktyp == COMMA)
+  {
+   char s1[RECLEN];
+
+   __pv_ferr(1077, "%s statement ending semicolon expected - %s read",
+    __get_vkeynam(s1, qcdeattyp), __prt_vtok());
+   goto skp_end;
+  }
+ __bld_xtree(0);
+
+ /* build quasi cont. assign */
+ stp->st.sqcdea.qcdatyp = qcdeattyp;
+ /* assume reg. form */
+ stp->st.sqcdea.regform = TRUE;
+ stp->st.sqcdea.qcdalhs = __root_ndp;
+ return(stp);
+}
+
+/*
+ * read and build task enable or procedural assignment statement
+ *
+ * expects 1st lhs element (ID or '{')to have been read
+ * reads stmt ending ;
+ * 
+ * for assign builds blocking or non blocking rhs del ctrl assign
+ * uses 1st token as location for both delay control and action stmt
+ *
+ * notice for assign not read here - lhs and rhs read separately 
+ * notice recovery here can just be skip to ; [if correct must appear]
+ */
+static struct st_t *rd_taske_or_proc_assign(void)
+{
+ int32 dtyp, is_nb, slcnt, sfnind, is_evctl_impl;
+ struct st_t *stp, *dcstp;
+ struct expr_t *lhsndp, *rhsndp, *delxndp, *repcntx;
+ struct delctrl_t *dctp;
+ struct paramlst_t *pmp;
+ char s1[IDLEN];
+
+ slcnt = __lin_cnt;
+ sfnind = __cur_fnam_ind;
+
+ /* collect lhs to '=' or '(' or ';' (for task enable) else fails */
+ if (!col2_lval())
+  {
+bad_assgn:
+   __vskipto_any(SEMI);
+   return(NULL);
+  }
+ /* case 1: ID task enable, not parsed need special task sy decl */
+ if (__toktyp == LPAR || __toktyp == SEMI)
+  { 
+   if (__last_xtk != 0 || __exprtab[0]->optyp != ID) goto try_parsing;
+   /* on error returns nil and that is also returned from here */ 
+   /* notice must copy expr idtab value because overwritten by parsing */
+   strcpy(s1, __expr_idtab[0]->idnam);
+   stp = __rd_tskenable(s1, NULL, FALSE);
+   return(stp);
+  }
+
+try_parsing:
+ __bld_xtree(0);
+ lhsndp = __root_ndp;
+ /* case 1a: xmr task enable */
+ if (__toktyp == LPAR || __toktyp == SEMI)
+  {
+   /* error if enable anything but xmr */
+   if (lhsndp->optyp != GLBREF)
+    { 
+     __pv_ferr(1086,
+      "attempted task enable of %s - maybe assignment = missing",
+      __msgexpr_tostr(__xs, lhsndp));
+     goto bad_assgn;
+    }
+   stp = __rd_tskenable(NULL, lhsndp, TRUE);
+   return(stp);
+  }
+ 
+ /* case 2: assign */
+ /* for now block procedural assignment not supported */
+ if (__toktyp == RELLE) is_nb = TRUE; else is_nb = FALSE;
+ /* must check later to make sure lvalue */
+
+ __get_vtok();
+
+ /* handle optional rhs delay control */
+ /* 10/27/00 SJM - add support for rhs repeat delay control forms */ 
+ repcntx = NULL;
+ if (__toktyp == REPEAT)
+  {
+   __get_vtok();
+   /* surrounding parentheses required by syntax */
+   if (__toktyp != LPAR)
+    {
+     __pv_ferr(3413,
+      "repeat event control count expression beginning left parenthesis expected - %s read",  
+       __prt_vtok());
+     goto bad_assgn;
+    }
+   __get_vtok();
+   /* this read trailing left parenthsis - here syncing only to ; */
+   if (!__col_parenexpr(-1)) goto bad_assgn;
+
+   __bld_xtree(0);
+   repcntx = __root_ndp;
+   /* read the delay control so can sync to normal rhs event control case */
+   __get_vtok();
+   if (__toktyp != AT)
+    {
+     __pv_ferr(3414,
+      "repeat event control count expression not followed by event control at sign - %s read",  
+      __prt_vtok());
+     goto bad_assgn;
+    }
+   /* set flag and fall thru - now same as normal rhs event control */
+  }
+ 
+ dtyp = DC_NONE;
+ if (__toktyp == SHARP || __toktyp == AT)
+  {
+   /* know this reads one past end of delay control */
+   if ((delxndp = rd_delctrl(&dtyp, &is_evctl_impl)) == NULL)
+    {
+     if (dtyp == DC_EVENT && is_evctl_impl)
+      {
+       __pv_ferr(3427,
+        "right hand side event control implicit form @(*) illegal");
+      }
+     goto bad_assgn;
+    }
+   if (dtyp == DC_EVENT) dtyp = DC_RHSEVENT;
+   else if (dtyp == DC_DELAY) dtyp = DC_RHSDELAY;
+  }
+ else delxndp = NULL;
+
+ /* this reads end ; */
+ if (!__col_comsemi(-1)) goto bad_assgn;
+ if (__toktyp != SEMI)
+  {
+   __pv_ferr(1078,
+    "assignment statement ending semicolon expected - %s read", __prt_vtok());
+   goto bad_assgn;
+  }
+
+ __bld_xtree(0);
+ rhsndp = __root_ndp;
+
+ /* first build proc assign */
+ if (!is_nb)
+  {
+   if (dtyp == DC_RHSEVENT || dtyp == DC_RHSDELAY)
+    stp = __alloc_stmt(S_RHSDEPROCA);
+   else stp = __alloc_stmt(S_PROCA);
+  }
+ else stp = __alloc_stmt(S_NBPROCA);
+ stp->st.spra.lhsx = lhsndp;
+ stp->st.spra.rhsx = rhsndp;
+ stp->stlin_cnt = slcnt;
+ stp->stfnam_ind = sfnind;
+
+ if (delxndp == NULL) return(stp);
+
+ dcstp = __alloc_stmt(S_DELCTRL);
+ dcstp->stlin_cnt = slcnt;
+ dcstp->stfnam_ind = sfnind;
+
+ dctp = dcstp->st.sdc;
+ dctp->dctyp = dtyp;
+ dctp->dc_delrep = DT_CMPLST;
+ pmp = __alloc_pval();
+ pmp->plxndp = delxndp; 
+ dctp->dc_du.pdels = pmp;
+ /* 10/28/00 SJM - only indication of rep form is repeat cnt expr non nil */
+ dctp->repcntx = repcntx;
+ /* 06/11/02 SJM - need to indicate non blocking rhs ev ctrl in dc evnt */  
+ if (is_nb) dctp->dc_nblking = TRUE;
+
+ dctp->dceschd_tevs = NULL;
+
+ dctp->actionst = stp;
+ return(dcstp);
+}
+
+/*
+ * read a task enable (call) statement
+ *
+ *  '(' or ';' (if no args read and reads ending ;
+ * need special parsing for system task since ,, form legal there
+ */
+extern struct st_t *__rd_tskenable(char *tknam, struct expr_t *glbndp,
+ int32 is_glbenable)
+{
+ register int32 i;
+ int32 rd_semi, nd_glb_conv;
+ struct sy_t *syp;
+ struct st_t *stp;
+ struct tskcall_t *tkcp;
+ struct expr_t *last_fcomxp, *lop;
+ struct expr_t *enable_ndp;
+ struct systsk_t *stbp;
+
+ rd_semi = FALSE;
+ nd_glb_conv = FALSE;
+ stbp = NULL;
+ /*  case 1: parsed global ref enable */
+ if (is_glbenable)
+  {
+   stp = __alloc_stmt(S_TSKCALL);
+   tkcp = &(stp->st.stkc);
+   /* notice there is no tkexp lu. sy here */
+   tkcp->tsksyx = glbndp;
+   tknam = glbndp->ru.grp->gnam;
+   goto get_args;
+  }
+
+ /* DBG remove --- */
+ if (tknam == NULL) __arg_terr(__FILE__, __LINE__);
+ /* --- */ 
+ /* case 2 simple ID enable - not parsed */
+ if (*tknam == '$')
+  {
+   /* look up in special system func. and task symbol table */
+   if ((syp = __get_sym(tknam, __syssyms)) == NULL)
+    {
+     /* this is completely unknown case */
+     __pv_ferr(1083,
+      "task enable of unknown system task or undefined PLI task \"%s\"",
+      tknam);
+     goto err_end;
+    }
+   stbp = syp->el.esytbp;
+   if (syp->sytyp != SYM_STSK)
+    {
+     __pv_ferr(1080, "task enable of system function \"%s\" illegal",
+      syp->synam);
+     goto err_end;
+    }
+   /* systam task table inconsistent - value is 0 */
+   if (stbp->stsknum == 0) __misc_fterr(__FILE__, __LINE__);
+
+   /* need location for xmr type setting */
+   switch (stbp->stsknum) {
+    case STN_MONITOR: case STN_MONITORB: case STN_MONITORH: case STN_MONITORO:
+     if (__iact_state && __optimized_sim)
+      {
+opt_dbg_illegal:
+       /* SJM 01/02/03 - can't call $dumpvars system task from iact */
+       /* from interactive debugger if -O on */
+       __pv_ferr(2901,
+        "system task %s can't be called from debugger when optimizer on - run without -O",
+        syp->synam);
+       goto err_end;
+      }
+     break;
+    /* these can have module/inst. ending xmrs */
+    case STN_DUMPVARS:
+     if (__iact_state && __optimized_sim) goto opt_dbg_illegal;
+     nd_glb_conv = TRUE;
+     break;
+    case STN_SDF_ANNOTATE:
+    case STN_PRINTTIMESCALE: case STN_SCOPE: case STN_LIST:
+     nd_glb_conv = TRUE;
+     break;
+    default:
+     /* PLI system tasks/functions always allow XMR's */
+     if (stbp->stsknum >= BASE_VERIUSERTFS
+      && (int32) stbp->stsknum <= __last_systf) nd_glb_conv = TRUE;
+     break;
+   }
+   enable_ndp = __alloc_newxnd();
+   enable_ndp->optyp = ID;
+   enable_ndp->lu.sy = syp;
+  }
+ else
+  {
+   /* if user task not declared must add to symbol table */
+   /* return of NULL to here on error - message already written */
+   if ((enable_ndp = find_bldxpr_tfsy(tknam, SYM_TSK)) == NULL)
+    {
+err_end:
+     __vskipto_any(SEMI);
+     return(NULL);
+    }
+  }
+ /* build the task enable statement */
+ stp = __alloc_stmt(S_TSKCALL);
+ tkcp = &(stp->st.stkc);
+ tkcp->tsksyx = enable_ndp;
+
+get_args:
+ tkcp->targs = NULL;
+ /* no arguments */
+ if (__toktyp == SEMI) goto done;
+
+ /* build argument expressions in a list */
+ __get_vtok();
+ /* at this point ,, form ok (legal for system tasks? */
+ for (last_fcomxp = NULL, i = 0;; i++)
+  {
+   /* ,, or ,) need to be check/fixed later */
+   /* for display and other system task legal, but for user task error */
+   if (__toktyp == COMMA || __toktyp == RPAR)
+    {
+     /* for xmr task enable, point to gnam - need for sys task testing */
+     /* error messages */
+     if (*tknam != '$')
+      {
+       __pv_ferr(1081,
+        "user task %s enable empty '()' or ',,' argument form illegal (pos. %d)",
+        tknam, i + 1);
+       /* if error build rhs x, cannot be op empty for non system task */
+       __set_xtab_errval();
+      }
+     else { __last_xtk = 0; __set_opempty(0); }
+     goto do_parse;
+    }
+   /* by case code to allow special forms, made globals here */
+   if (nd_glb_conv)
+    {
+     switch (stbp->stsknum) {
+      /* for dumpvars all but 1st argument can be special form */
+      case STN_DUMPVARS:
+       if (i != 0) __allow_scope_var = TRUE;
+       break; 
+      case STN_SDF_ANNOTATE:
+       if (i == 1) __allow_scope_var = TRUE;
+       break;
+      /* case where all inst. forms */
+      case STN_SCOPE: case STN_LIST: case STN_PRINTTIMESCALE:
+       __allow_scope_var = TRUE;
+       break;
+      default:
+       /* any argument to PLI system task can be xmr */
+       if (stbp->stsknum >= BASE_VERIUSERTFS
+        && (int32) stbp->stsknum <= __last_systf)
+        {
+         __allow_scope_var = TRUE;
+        }
+       else __case_terr(__FILE__, __LINE__);
+     }
+    }
+   /* either path here turns off allowing scope var */
+   if (!__col_connexpr(-1))
+    {
+     __allow_scope_var = FALSE;
+     if (__vskipto3_any(COMMA, RPAR, SEMI))     
+      { if (__toktyp == SEMI) rd_semi = TRUE; }
+     else goto err_end;
+     /* if error build rhs x, then parse */
+     __set_xtab_errval();
+    }
+
+do_parse:
+   __bld_xtree(0);
+   /* parsing in bld xtree used this flag to allow inst. ending global */
+   /* so now must turn off in case turned on */
+   __allow_scope_var = FALSE;
+
+   /* first arg. done for dumpvars - rest special inst xmr or wire form */
+   lop = __alloc_newxnd();
+   lop->optyp = FCCOM;
+   lop->ru.x = NULL;
+   lop->lu.x = __root_ndp;
+
+   if (last_fcomxp == NULL) tkcp->targs = lop; else last_fcomxp->ru.x = lop;
+   last_fcomxp = lop;
+   /* some kind of error, seen ;, all done - probably more errors */
+   if (__toktyp == rd_semi) goto done;
+   if (__toktyp == RPAR) break;
+   __get_vtok();
+  }
+ /* assume just left out */
+ __get_vtok();
+ if (__toktyp != SEMI)
+  {
+   __pv_ferr(1084,
+    "task enable statement semicolon expected - %s read", __prt_vtok());
+  }
+done:
+ return(stp);
+}
+
+/*
+ * read a delay/event control statement (non rhs)
+ */
+static struct st_t *rd_dctrl_st(void)
+{
+ int32 dtyp, slcnt, sfnind, is_evctl_impl;
+ struct st_t *dcstp, *stp;
+ struct expr_t *delxndp;
+ struct delctrl_t *dctp;
+ struct paramlst_t *pmp;
+
+ slcnt = __lin_cnt;
+ sfnind = __cur_fnam_ind;
+ is_evctl_impl = FALSE;
+ /* this reads one past one control or one past ending ) */
+ /* only NULL error if cannot sync to following stmt */
+ if ((delxndp = rd_delctrl(&dtyp, &is_evctl_impl)) == NULL)
+  {
+   /* SJM 06/01/04 - @(*) or @* forms - have nil delxndp but still bld */
+   if (!is_evctl_impl) return(NULL);
+  }
+ dcstp = __alloc_stmt(S_DELCTRL);
+ /* fix up so statement location starts with delay control not action stmt */
+ dcstp->stlin_cnt = slcnt;
+ dcstp->stfnam_ind = sfnind;
+
+ dctp = dcstp->st.sdc;
+ dctp->dctyp = dtyp;
+ dctp->dc_delrep = DT_CMPLST;
+ pmp = __alloc_pval();
+ pmp->plxndp = delxndp; 
+ dctp->dc_du.pdels = pmp;
+ dctp->dceschd_tevs = NULL;
+ /* SJM 06/01/04 - in this case del xndp nil - build ev list during fixup */
+ dctp->implicit_evxlst = is_evctl_impl; 
+
+ /* if begin-end block will return statement list */
+ if ((stp = __rd_stmt()) == NULL) return(NULL);
+ /* need some statement here even if it is only NULL statement */
+ /* delay control on block turned into delay control on st. list */
+ dctp->actionst = stp;
+ return(dcstp);
+}
+
+/*
+ * read a delay control @ or # read - builds expression and type
+ * know first token read and reads one past ending token
+ *
+ * this must have skipped past delay control to stmt if possible 
+ */
+static struct expr_t *rd_delctrl(int32 *dtyp, int32 *ev_impl)
+{
+ struct expr_t *ndp;
+
+ *ev_impl = FALSE;
+ /* read one after except for non parenthesized ID because there need to */
+ /* read one ahead to see if xmr */
+ if (__toktyp == SHARP) *dtyp = DC_DELAY;
+ else
+  {
+   *dtyp = DC_EVENT;
+   __canbe_impl_evctrl = TRUE; 
+  }
+ __get_vtok();
+
+ if (__toktyp == LPAR)
+  {
+   /* if @(* that looks like attribute to scanner - glb canbe impl evctrl */
+   /* on will prevent seeing as atrribute since attrs illegal here */
+   __get_vtok();
+   __canbe_impl_evctrl = FALSE;
+
+   if (*dtyp == DC_DELAY)
+    {
+     /* undeclared names treated as wires - maybe changed to event later */
+     /* need to surround with () in expr. so m:t:m parses ok */
+     /* but need to use actual surrounding for parse indicators */
+     __last_xtk = -1;
+     ndp = __alloc_exprnd();
+     ndp->optyp = LPAR;
+     /* if no error, surround with parentheseses and parse as normal */
+     if (!__col_parenexpr(0))
+      {
+       __pv_ferr(1278, "delay control expression error");
+
+       __vskipto_any(RPAR);
+       if (__syncto_class == SYNC_TARG || __syncto_class == SYNC_STMT) 
+        {
+bad_dctrl:
+         /* this is 1 bit x - cannot be op empty */
+         __set_xtab_errval();
+         __get_vtok();
+         goto bld_evx;
+        }
+       __get_vtok();
+       return(NULL);
+      }
+     ndp = __alloc_exprnd();
+     ndp->optyp = RPAR;
+    }
+   else
+    {
+     if (__toktyp == TIMES) 
+      {
+       __get_vtok();
+       if (__toktyp != RPAR)
+        {
+         __pv_ferr(3428, "implicit @(*) event control form illegal - %s read",
+          __prt_vtok());
+         __vskipto_any(RPAR);
+         if (__syncto_class == SYNC_TARG || __syncto_class == SYNC_STMT) 
+          return(NULL);
+         else { __get_vtok(); return(NULL); }
+        }
+       *ev_impl = TRUE;
+       __get_vtok();
+       return(NULL);
+      }  
+
+     /* event control cannot have added surrounding () because of evor */
+     if (!col_evctrlexpr())
+      {
+       __pv_ferr(1087, "event control expression error");
+       /* if possible, now ready to read statement */
+       __vskipto_any(RPAR);
+       if (__syncto_class == SYNC_TARG || __syncto_class == SYNC_STMT) 
+        goto bad_dctrl; 
+       __get_vtok();
+       return(NULL);
+      }
+    }
+   /* on any non error surrounding () case, read one after end ) */
+   __get_vtok();
+  }
+ else
+  {
+   /* turn off glb to prevent seeing @(* as scanner attribute */
+   __canbe_impl_evctrl = FALSE;
+
+   /* simple case can be one name form */
+   /* should really check to see if next token can start stmt */
+   __last_xtk = -1;
+   /* this declares ID as wire - maybe later declared to be event */
+   /* LOOKATME - could collect xmr without surrounding () by */
+   /* looking for each .ID(optional [...]) after first */ 
+   switch ((byte) __toktyp) {
+    case NUMBER: case REALNUM: case ID: break;
+    /* only create IS number at param assign */ 
+    case TIMES:
+     /* AIV 07/21/04 - handle @* without () */
+     *ev_impl = TRUE;
+      __get_vtok();
+     return(NULL);
+    case ISNUMBER: case ISREALNUM:
+    /* here on error, assume right structure but 1 thing wrong */
+     __arg_terr(__FILE__, __LINE__);
+     break;
+    default:
+     /* one token after delay/event control case - no sync possible */
+     __pv_ferr(1088,
+     "non parenthesized delay/event control not identifier or number - %s read",
+      __prt_vtok());
+     goto bad_dctrl;
+    }
+   if (__toktyp == ID)
+    {
+     /* even if simple ID (i.e. always) this reads one past end */
+     if (!col_dctrl_xmr()) goto bad_dctrl;
+    }
+   else
+    {
+     if (!__bld_expnode()) goto bad_dctrl;
+     __get_vtok(); 
+    }
+  }
+bld_evx:
+ if (*dtyp == DC_EVENT) __bld_evxtree(); else __bld_xtree(0);
+ return(__root_ndp);
+}
+
+/*
+ * collect a delay or event control variable
+ *
+ * know @ or # and following ID read - done unless part of XMR
+ * after ID can have optional select [..] then if not dot done else read
+ * next component - collected XMR later parsed into glbref
+ *
+ * know ID read and reads one past end of XMR (if not simple ID)
+ * also emits error on non ID or GLBREF - select at end illegal - need ()
+ */
+static int32 col_dctrl_xmr(void)
+{
+ int32 sblevel;
+
+ __last_xtk = -1;
+ if (!__bld_expnode()) goto bad_end;
+ for (;;)
+  {
+   /* each time hear know ID read and added to exprtab */
+   __get_vtok();
+   if (__toktyp == LSB) 
+    {
+     if (!__bld_expnode()) goto bad_end;
+     for (sblevel = 0;;)
+      {
+       __get_vtok();
+       if (__toktyp == TEOF || __toktyp == SEMI)
+        {
+         __pv_ferr(1082,
+          "illegal token %s in delay or event control global variable",
+          __prt_vtok());
+         goto bad_end;
+        }
+       if (__toktyp == LSB) sblevel++;
+       else if (__toktyp == RSB)
+        {
+         if (sblevel <= 0) break;
+         sblevel--; 
+        }
+       if (!__bld_expnode()) goto bad_end;
+      }
+     if (!__bld_expnode()) goto bad_end;
+     __get_vtok();
+     if (__toktyp != DOT)
+      {
+       __pv_ferr(1075,
+        "delay or event control global variable contains select - must surround with parentheses");
+       goto bad_end;
+      }
+    }
+   /* anything after component but dot ends and not collected */
+   /* works because this reads one past end */
+   if (__toktyp != DOT) return(TRUE); 
+   if (!__bld_expnode()) goto bad_end;
+   /* read required ID after DOT */ 
+   __get_vtok();
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1058,
+      "delay/event control hierarchical reference identifier must follow dot - %s read", 
+      __prt_kywrd_vtok());
+    }
+   if (!__bld_expnode()) goto bad_end;
+  }
+
+bad_end:
+ __set_xtab_errval();
+ return(FALSE);
+}
+
+/*
+ * EXPRESSION COLLECTION ROUTINES
+ * these return FALSE and 1'bx on error - caller must emit err
+ */
+
+/*
+ * collect delay expr. make 0 if error - will never make it to fixup so ok
+ * this collects and adds surrounding parenthesis - need for possible
+ * min:typ:max with surrounding ()
+ * but otherwise is identical to collect connecting expr.
+ * expects 1st token to have been read
+ */
+extern int32 __col_delexpr(void)
+{
+ struct expr_t *ndp;
+
+ __last_xtk = -1;
+ ndp = __alloc_exprnd();
+ ndp->optyp = LPAR;
+ /* if no error, surround with parentheseses and parse as normal */
+ if (!__col_connexpr(0))
+  {
+bad_del:
+   __set_xtab_errval();
+   /* need constant 32 bit 0 here */
+   __exprtab[0]->szu.xclen = WBITS;
+   __exprtab[0]->ru.xvi = __alloc_shareable_cval(0, 0, WBITS);
+   return(FALSE);
+  }
+ /* if col conn T, then know at least 1 token */
+ if (__last_xtk == 1 && __exprtab[1]->optyp == OPEMPTY)
+  {
+   __pv_ferr(1095, "empty delay expression illegal");
+   goto bad_del;
+  }
+ ndp = __alloc_exprnd();
+ ndp->optyp = RPAR;
+ return(TRUE);
+}
+
+
+/*
+ * collect parm or specparam rhs parameter value
+ * this collects and adds surrounding parenthesis
+ * needed for possible min:typ:max with surrounding ()
+ * but otherwise is identical to collect comsemi
+ * expects 1st token to have been read
+ * 
+ * on error sets value to 0 not x - is this right? 
+ * if this is used where only ; can end, caller must check for and emit err
+ */
+extern int32 __col_paramrhsexpr(void)
+{
+ struct expr_t *ndp;
+
+ __last_xtk = -1;
+ ndp = __alloc_exprnd();
+ ndp->optyp = LPAR;
+ /* if no error, surround with parentheseses and parse as normal */
+ if (!__col_comsemi(0))
+  {
+   __set_xtab_errval();
+   /* need constant 32 bit 0 here */
+   __exprtab[0]->szu.xclen = WBITS;
+   __exprtab[0]->ru.xvi = __alloc_shareable_cval(0, 0, WBITS);
+   return(FALSE);
+  }
+ ndp = __alloc_exprnd();
+ ndp->optyp = RPAR;
+ return(TRUE);
+}
+
+/*
+ * collect paren surround expression and leave tree in __exprtab[0]
+ * expects 1st expr. token to have been read (after '(') reads end token
+ * need to reuse or move nodes here to tree
+ * surrounding parentheses not included
+ */
+extern int32 __col_parenexpr(int32 start_xtk)
+{
+ int32 parlevel;
+
+ /* this is illegal () case */
+ if (__toktyp == RPAR)
+  {
+   __pv_ferr(1089, "empty parentheses ending expression illegal");
+bad_end:
+   /* notice cannot free here since in __exprtab (links just overwritten) */
+   /* also make look like empty expr. */
+   __set_xtab_errval();
+   return(FALSE);
+  }
+ parlevel = 0;
+ if (__toktyp == LPAR) parlevel++;
+
+ for (__last_xtk = start_xtk;;)
+  {
+   if (!__bld_expnode()) goto bad_end;
+   __get_vtok();
+   if (__toktyp == LPAR) parlevel++;
+   else if (__toktyp == RPAR)
+    {
+     if (parlevel > 0) parlevel--; else break;
+    }
+   else if (__toktyp == TEOF || __toktyp == SEMI)
+    {
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1090, "illegal token %s in parenthesis ending expression",
+       __prt_vtok());
+     goto bad_end;
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * collect event expr - for new VER 2001 , as alternative to evor legal
+ * same as collect paren expr except commas allowed and special
+ * ev or comma token substituted
+ *
+ * expects 1st expr. token to have been read (after '(') reads end token
+ *
+ * know implicit @* and @(*) never seen here
+ * need to reuse or move nodes here to tree
+ */
+static int32 col_evctrlexpr(void)
+{
+ int32 parlevel, catlevel;
+
+ __last_xtk = -1;
+ /* this is illegal () case */
+ if (__toktyp == RPAR)
+  {
+   __pv_ferr(1089, "empty parentheses ending expression illegal");
+bad_end:
+   /* notice cannot free here since in __exprtab (links just overwritten) */
+   /* also make look like empty expr. */
+   __set_xtab_errval();
+   return(FALSE);
+  }
+ parlevel = catlevel = 0;
+ if (__toktyp == LPAR) parlevel++;
+
+ for (;;)
+  {
+   /* SJM 06/01/04 - this is unusual ',' just like event "or" but different */
+   /* expr node op typ */
+   /* bld expnode can't see comma because mashes error recovery */
+   if (__toktyp == COMMA && catlevel == 0) __toktyp = OPEVCOMMAOR;
+   if (!__bld_expnode()) goto bad_end;
+
+   __get_vtok();
+   switch ((byte) __toktyp) {
+    case LCB: catlevel++; break;
+    case RCB: catlevel--; break;
+    case LPAR: parlevel++; break;
+    case RPAR:
+     /* only non nested rpar can cause correct exit */
+     if (parlevel > 0) { parlevel--; break; }
+     goto done;
+    default:
+     if (__toktyp == TEOF || __toktyp == SEMI)
+      {
+       if (__pv_err_cnt <= __saverr_cnt)
+        {
+         __pv_ferr(1090, "illegal token %s in parenthesis ending expression",
+          __prt_vtok());
+        }
+       goto bad_end;
+      }
+    } 
+  }
+done:
+ return(TRUE);
+}
+
+/*
+ * collect a range expression
+ * expects first token ([) to have been read and reads ending ] token
+ * includes ] in expression
+ */
+extern int32 __col_rangeexpr(void)
+{
+ int32 brklevel;
+ struct expr_t *ndp;
+
+ /* must add dummy symbol so range parses as x[cexpr:cexpr] */
+ __last_xtk = -1;
+ ndp = __alloc_exprnd();
+ ndp->optyp = ID;
+ /* need dummy to fill id table - not used and overwritten each time */ 
+ /* this checked for during term parsing and not decled */ 
+ __alloc_expridnd("[]");
+ /* node for already read [ */
+ if (!__bld_expnode()) goto bad_end;
+
+ for (brklevel = 0;;)
+  {
+   __get_vtok();
+   if (__toktyp == LSB) brklevel++;
+   else if (__toktyp == RSB)
+    {
+     if (brklevel <= 0)
+      {
+       if (__last_xtk == 1)
+        {
+         __pv_ferr(1097, "select range empty form ([]) illegal");
+         goto bad_end;
+        }
+       /* ending ] must be part of expression */
+       if (!__bld_expnode()) goto bad_end;
+       break;
+      }
+     else brklevel--;
+    }
+   else if (__toktyp == TEOF || __toktyp == SEMI)
+    {
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1091, "illegal token %s in select range expression",
+       __prt_vtok());
+     
+bad_end:
+     /* must be 1 bit x not unc. */
+     __set_xtab_errval();
+     __last_xtk = 0;
+     return(FALSE);
+    }
+   if (!__bld_expnode()) goto bad_end;
+  }
+ return(TRUE);
+}
+
+/*
+ * collect an inst., port header, function call, delay, cat expr. or
+ * instance pound parameter list
+ *
+ * expects 1st token to be read and read ending token
+ * ends with ) or ,
+ * allows full expressions but also used for param subset exprs.
+ * need start_xtk for delay params where min:typ:max does not need (),
+ * scheme adds surrounding () and then calls normal bld_xtree
+ * for each comma sep.  * piece
+ * normal start of expr. is -1
+ */
+extern int32 __col_connexpr(int32 start_xtk)
+{
+ int32 parlevel, catlevel;
+
+ /* ,, or ,) form ok here - if not caller will check */
+ if (__toktyp == COMMA || __toktyp == RPAR)
+  { __last_xtk = start_xtk + 1; __set_opempty(__last_xtk); return(TRUE); }
+
+ for (__last_xtk = start_xtk, parlevel = 0, catlevel = 0;;)
+  {
+   switch ((byte) __toktyp) {
+    case LPAR: parlevel++; break;
+    case LCB: catlevel++; break;
+    case RPAR:
+     if (parlevel <= 0 && catlevel <= 0) return(TRUE); else parlevel--;
+     break;
+   case RCB:
+    catlevel--;
+    break;
+   case COMMA:
+    if (parlevel <= 0 && catlevel <= 0) return(TRUE);
+    break;
+   case TEOF:
+   case SEMI:
+    if (__pv_err_cnt <= __saverr_cnt)
+     __pv_ferr(1092, "illegal token %s in expression list", __prt_vtok());
+    goto bad_end;
+   }
+   if (!__bld_expnode()) goto bad_end;
+   __get_vtok();
+  }
+
+bad_end:
+ __set_xtab_errval();
+ return(FALSE);
+}
+
+/*
+ * collect something from an assignment list rhs
+ * expects 1st token of assignment rhs expr to have been read
+ * rhs expr. can have (..) function calls and concatenates
+ * also (..) delay triples 
+ *
+ * reads trailing , or ;
+ * empty here will not collect - error
+ */
+extern int32 __col_comsemi(int32 last_xti)
+{
+ int32 parlevel, catlevel;
+
+ __last_xtk = last_xti; 
+ for (parlevel = 0, catlevel = 0;;)
+  {
+   switch ((byte) __toktyp) {
+    case LPAR: parlevel++; break;
+    case RPAR: parlevel--; break;
+    case LCB: catlevel++; break;
+    case RCB: catlevel--; break;
+    case SEMI:
+chk_empty:
+     /* empty = ; form illegal */
+     if (__last_xtk == last_xti) 
+      {
+       __pv_ferr(1106, "right hand side expression missing");
+       goto bad_end;
+      }
+     return(TRUE);
+    case COMMA:
+     if (parlevel <= 0 && catlevel <= 0) goto chk_empty;
+     break;
+    case TEOF:
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1093, "illegal token %s in right hand side expression",
+       __prt_vtok());
+     goto bad_end;
+   }
+   if (!__bld_expnode()) goto bad_end;
+   __get_vtok();
+  }
+
+bad_end:
+ /* replace entire expression with 1 bit x - not op empty */
+ __set_xtab_errval();
+ return(FALSE);
+}
+
+/*
+ * new parameter format collect param (not specify) rhs expr
+ *
+ * expects 1st token of assignment rhs expr to have been read
+ * and reads one past end , or ;
+ *
+ * for mismatched nesting parse will catch error
+ */
+extern int32 __col_newparamrhsexpr(void)
+{
+ int32 parlevel, catlevel;
+ struct expr_t *ndp;
+
+ __last_xtk = -1; 
+ ndp = __alloc_exprnd();
+ ndp->optyp = LPAR;
+ for (parlevel = 0, catlevel = 0;;)
+  {
+   switch ((byte) __toktyp) {
+    case LPAR: parlevel++; break;
+    case RPAR: parlevel--; break;
+    case LCB: catlevel++; break;
+    case RCB: catlevel--; break;
+    case SEMI:
+chk_empty:
+     /* empty = ; form illegal */
+     if (__last_xtk == -1) 
+      {
+       __pv_ferr(1106, "right hand side expression missing");
+       goto bad_end;
+      }
+     ndp = __alloc_exprnd(); 
+     ndp->optyp = RPAR;
+     return(TRUE);
+    case COMMA:
+     if (parlevel <= 0 && catlevel <= 0) goto chk_empty;
+     break;
+    case TEOF:
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1093,
+       "illegal token %s in parameter right hand side expression",
+       __prt_vtok());
+     goto bad_end;
+   }
+   if (!__bld_expnode()) goto bad_end;
+   __get_vtok();
+  }
+
+bad_end:
+ /* replace entire expression with 1 bit x - not op empty */
+ __set_xtab_errval();
+ return(FALSE);
+}
+
+/*
+ * ver 2001 #(list of param decls) form format collect param rhs expr
+ *
+ * expects 1st token of assignment rhs expr to have been read
+ * and reads one past end , or )
+ *
+ * for mismatched nesting parse will catch error
+ */
+extern int32 __col_lofp_paramrhsexpr(void)
+{
+ int32 parlevel, catlevel;
+ struct expr_t *ndp;
+
+ __last_xtk = -1; 
+ ndp = __alloc_exprnd();
+ ndp->optyp = LPAR;
+ for (parlevel = 0, catlevel = 0;;)
+  {
+   switch ((byte) __toktyp) {
+    case LPAR: parlevel++; break;
+    case LCB: catlevel++; break;
+    case RCB: catlevel--; break;
+    case RPAR:
+     if (parlevel <= 0 && catlevel <= 0) goto chk_empty;
+     else parlevel--;
+     break;
+    case COMMA:
+     if (parlevel <= 0 && catlevel <= 0)
+      {
+chk_empty:
+       /* empty = ) form illegal */
+       if (__last_xtk == -1) 
+        {
+         __pv_ferr(1106, "right hand side expression missing");
+         goto bad_end;
+        }
+       ndp = __alloc_exprnd(); 
+       ndp->optyp = RPAR;
+       return(TRUE);
+      }
+     break;
+    case TEOF: case SEMI:
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1093,
+       "illegal token %s in parameter right hand side expression",
+       __prt_vtok());
+     goto bad_end;
+   }
+   if (!__bld_expnode()) goto bad_end;
+   __get_vtok();
+  }
+
+bad_end:
+ /* replace entire expression with 1 bit x - not op empty */
+ __set_xtab_errval();
+ return(FALSE);
+}
+
+/*
+ * collect an lvalue (all but procedural assign lhs)
+ * expects 1st token of assignment lhs expr to have been read and reads
+ * trailing =
+ *
+ * must emit error on 1st extra right parenthesis or will get error line
+ * wrong - also if returns F must emit error
+ */
+extern int32 __col_lval(void)
+{
+ int32 parlevel;
+
+ parlevel = 0;
+ for (__last_xtk = -1;;)
+  {
+   switch ((byte) __toktyp) {
+    case TEOF: case SEMI:
+     {
+maybe_err:
+      __pv_ferr(1094,
+       "illegal token %s in lvalue - probable missing = or assign to function call",
+       __prt_vtok());
+      goto bad_end;
+     }
+    case EQ:
+     if (__last_xtk == -1)
+      {
+       /* empty = ; form illegal */
+       __pv_ferr(1096, "assignment lvalue missing");
+       goto bad_end;
+      }
+     return(TRUE);
+    case LPAR: parlevel++; break;
+    case RPAR:
+     if (--parlevel < 0) goto maybe_err;
+     break;
+   }
+   if (!__bld_expnode()) goto bad_end;
+   __get_vtok();
+  }
+
+bad_end:
+ __set_xtab_errval();
+ return(FALSE);
+}
+
+/*
+ * collect a procedural assignment lvalue (can end with <= non blocking
+ * procedural assignment symbol or ( for task enable)
+ *
+ * expects 1st token of assignment lhs expr to have been read and reads
+ * trailing '(' or ';' (no argumnet form), or '=' or '<=' for assign
+ */
+static int32 col2_lval(void)
+{
+ int32 sblevel, cblevel;
+
+ sblevel = cblevel = 0;
+ /* set flag for bld expnode error recovery - must be off when done */
+ __expr_is_lval = TRUE;
+ for (__last_xtk = -1;;)
+  {
+   switch ((byte) __toktyp) {
+    case TEOF:
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1099,
+       "illegal token %s in procedural assign lvalue or task enable",
+        __prt_vtok());
+     goto bad_end;
+    case EQ:
+     /* = can not appear in lhs because relational never '=' */
+chk_emp:
+     if (__last_xtk == -1)
+      {
+       /* empty lhs "= <rhs side>" form illegal */
+       __pv_ferr(1117, "empty assignment or task enable lvalue illegal");
+       goto bad_end;
+      }
+     __expr_is_lval = FALSE;
+     return(TRUE);
+    case SEMI:
+     /* no argument task enable "$stop;" - must not be empty */
+     /* ; is error correction marker - can not be nested in anything */
+     goto chk_emp;
+    case RELLE:
+     if (sblevel == 0 && cblevel == 0) goto chk_emp;
+     break;
+    case LPAR:
+     if (sblevel == 0 && cblevel == 0) goto chk_emp;
+     break;
+    case LSB: sblevel++; break;
+    case RSB: sblevel--; break;
+    case LCB: cblevel++; break;
+    case RCB: cblevel--; break;
+   }
+   if (!__bld_expnode()) goto bad_end;
+   __get_vtok();
+  }
+
+bad_end:
+ __expr_is_lval = FALSE;
+ __set_xtab_errval();
+ return(FALSE);
+}
+
+/*
+ * read a case expression list that ends with : or ,
+ * also reads DEFAULT and ENDCASE expressions
+ * expects 1st token to be read and reads ending token
+ * but it is not included
+ */
+extern int32 __col_caseexpr(void)
+{
+ int32 parlevel, collevel, sblevel, cblevel;
+
+ parlevel = collevel = sblevel = cblevel = 0;
+ for (__last_xtk = -1;;)
+  {
+   switch ((byte) __toktyp) {
+    case QUEST: collevel++; break;
+    case COLON:
+     /* ? token must be followed by : for ?: expression */
+     if (collevel > 0) collevel--;
+     else if (sblevel <= 0) goto good_end;
+     break;
+    case LSB: sblevel++; break;
+    case RSB: sblevel--; break;
+    case LCB: cblevel++; break; 
+    case RCB: cblevel--; break;
+    case LPAR: parlevel++; break;
+    case RPAR: parlevel--; break;
+    case COMMA:
+     if (parlevel <= 0 && cblevel <= 0) goto good_end;
+     break;
+    case TEOF:
+    case SEMI:
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1101, "illegal token %s in case item expression",
+       __prt_vtok());
+bad_end:
+     __set_xtab_errval();
+     return(FALSE);
+   }
+   if (!__bld_expnode()) goto bad_end;
+   __get_vtok();
+  }
+good_end:
+ if (__last_xtk == -1)
+  {
+   /* empty form illegal */
+   __pv_ferr(1098, "case expression list missing");
+   goto bad_end;
+  }
+ return(TRUE);
+}
+
+/*
+ * build an expression tree node from current token
+ * always places it in next free place in __exprtab
+ * reuses storage so bld_xtree must allocate nodes
+ *
+ * puts ID name in expr_idtab that is changed to symbol in
+ * parse term routine (either ID or xmr component)
+ *
+ * 'or' in expression always evor
+ * anything part of expression goes through here
+ */
+extern int32 __bld_expnode(void)
+{
+ int32 wlen;
+ struct opinfo_t *oip;
+ struct expr_t *ndp;
+
+ ndp = __alloc_exprnd();
+ switch ((byte) __toktyp) {
+  case ID:
+   /* if can be inst. ref, assume global fix later */
+   /* notice anthing in this case but id and glb wrong - caught later */
+   if (strcmp(__token, "or") == 0) { ndp->optyp = OPEVOR; break; }
+   ndp->optyp = ID;
+   __alloc_expridnd(__token);
+   break;
+  case POSEDGE:
+   ndp->optyp = OPPOSEDGE;
+   break;
+  case NEGEDGE:
+   ndp->optyp = OPNEGEDGE;
+   break;
+  case OPEVCOMMAOR:
+   ndp->optyp = OPEVCOMMAOR; 
+   break;
+  case NUMBER:
+   /* notice scanner only returns number */  
+   ndp->optyp = NUMBER;
+   ndp->szu.xclen = __itoklen;
+   if (__itoksized) ndp->unsiznum = FALSE; else ndp->unsiznum = TRUE;
+
+   /* only true for decimal without 'd even 'd[num] is word32 */
+   /* SJM 10/02/03 - scanner sets if signed - depends on new 2001 LRM rules */ 
+   if (__itok_signed) ndp->has_sign = TRUE;
+
+   ndp->ibase = (word32) __itokbase;
+   ndp->sizdflt = (__itoksizdflt) ? TRUE : FALSE;
+   /* Verilog values are really word32 bit patterns */
+
+   wlen = wlen_(__itoklen);
+   if (__itoklen <= WBITS)
+    {
+     /* always sets value - if not sharable uses non sharable alloc cval */
+     ndp->ru.xvi = __alloc_shareable_cval(__acwrk[0], __bcwrk[0], __itoklen);
+    }
+   else
+    {
+     ndp->ru.xvi = __allocfill_cval_new(__acwrk, __bcwrk, wlen);
+    }
+   break;
+  case REALNUM:
+   /* num storage pted to by a part - usually (except xstk) no b part */ 
+   ndp->optyp = REALNUM;
+   ndp->szu.xclen = REALBITS;
+   ndp->ibase = BDBLE;
+   ndp->is_real = TRUE;
+   ndp->has_sign = TRUE;
+   /* LOOKATME - SIZE assuming size of real is 8 bytes here */
+   ndp->ru.xvi = __alloc_shareable_rlcval(__itok_realval);
+   break;
+  case LITSTR:
+   /* string copied to alloced storage and filled */
+   ndp->optyp = NUMBER;
+   ndp->szu.xclen = __itoklen;
+
+   wlen = wlen_(__itoklen);
+   ndp->ru.xvi = __allocfill_cval_new(__acwrk, __bcwrk, wlen);
+   ndp->is_string = TRUE;
+   ndp->unsiznum = FALSE;
+   ndp->has_sign = FALSE;
+   break;
+  case TEOF:
+   /* since no error recovery in interactive - this is finish path */
+   /* caller sets to error expression */ 
+   ndp->optyp = BADOBJ;
+   return(FALSE);
+  default:
+   if (__toktyp > LASTOP)
+    {
+     /* keywords can not be in or end expressions */
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1104,
+       "illegal token %s in expression - probable missing semicolon",
+       __prt_vtok());
+     return(FALSE);
+    }
+   /* build an operator node */
+   oip = &(__opinfo[__toktyp]);
+   if (oip->opclass == NOTANOP)
+    {
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1105, "illegal punctuation %s in expression",
+      __prt_vtok());
+     return(FALSE);
+    }
+   /* build an operator node */
+   ndp->optyp = __toktyp;
+  }
+ return(TRUE);
+}
+
+#define HASHTABSIZ 3011     /* prime number size of consts hash table */
+#define HASHSEED 0x371546dc    /* seed of first word of the hash table */
+
+
+/*
+ * setup the constant tables
+ *
+ * allocate design wide constant table - so fixed constants at bottom
+ * BEWARE - since constant table is design and reallocated must always ndx
+ * allocate initial small constant table - grows when needed
+ */ 
+extern void __setup_contab(void)
+{
+ register int32 i, j;
+
+ __contabwsiz = 400;
+ __contab = (word32 *) __my_malloc(__contabwsiz*sizeof(word32));
+ /* 0th and 1st unused - marker to catch errors */
+ for (i = 0; i < 4; i++) __contab[i] = ALL1W;
+ /* 3rd is one bit z */
+ __contab[4] = 0;
+ __contab[5] = 1;
+ /* 4th is 1 bit x */
+ __contab[6] = 1;
+ __contab[7] = 1;
+ /* 5th is 32 bit z */
+ __contab[8] = 0;
+ __contab[9] = ALL1W;
+ /* 6th is 32 bit x */
+ __contab[10] = ALL1W;
+ __contab[11] = ALL1W;
+
+ for (i = 12, j = 0; i <= 12 + 2*128; i += 2, j++)
+  {
+   __contab[i] = j; 
+   __contab[i + 1] = 0;
+  }
+ /* also need build in special contab index for opempty */
+ /* all rhs igen expr eval OP EMPTY nodes point to this */
+ __opempty_contabi = 270;
+ __contab[270] = ' ';
+ __contab[271] = 0;
+ __contabwi = 272;
+
+ __contab_hash = (struct contab_info_t **)
+  __my_malloc(HASHTABSIZ*sizeof(struct contab_info_t *));
+ memset(__contab_hash, 0, HASHTABSIZ*sizeof(struct contab_info_t *));
+
+}
+ 
+/* some local use only constant for fixed con table locations */
+#define FIXCON_1BITZ 4
+#define FIXCON_1BITX 6
+#define FIXCON_32BITZ 8
+#define FIXCON_32BITX 10
+#define NONXZ_CONBASE 12
+
+/*
+ * sharable (non IS form) any 32 bit or any 32 or less 0 
+ * plus some non x/z low values
+ */
+extern int32 __alloc_shareable_cval(word32 aval, word32 bval, int32 bwid)
+{
+ int32 wi;
+
+ if (bwid == 1)
+  {
+   if (bval == 0) goto do_nonxz;
+   if (aval == 0) return(FIXCON_1BITZ);
+   return(FIXCON_1BITX);
+  }
+  
+ if (bval == ALL1W) 
+  {
+   if (bwid != WBITS) goto do_alloc;
+   if (aval == 0) return(FIXCON_32BITZ);
+   if (aval == ALL1W) return(FIXCON_32BITX);
+   goto do_alloc;
+  }
+ if (bval != 0) goto do_alloc;
+do_nonxz:
+ if (aval <= 128) return(NONXZ_CONBASE + 2*aval);
+
+do_alloc:
+ aval &= __masktab[bwid];
+ bval &= __masktab[bwid];
+ wi = __allocfill_cval_new(&(aval), &(bval), 1);
+ return(wi); 
+}
+
+/*
+ * allocate a constant value in design wide constant table
+ *
+ * now only for IS forms where must allocate big region and can't use
+ * hashing to share because each inst must be filled with mem copy
+ *
+ * wlen is really wlen times no. of instances in IS form - multiply by
+ * 2 works since need b parts for each inst
+ * know a and b parts contiguous
+ */
+extern int32 __alloc_is_cval(int32 wlen)
+{
+ int32 wi;
+
+ if (__contabwi + 2*wlen >= __contabwsiz) __grow_contab(2*wlen);
+ wi = __contabwi;
+ __contabwi += 2*wlen;
+ return(wi);
+}
+
+/*
+ * sharable (non IS form) for real constants
+ * SJM 05/03/05 - now reals go into hashed part of contab
+ */
+extern int32 __alloc_shareable_rlcval(double d1)
+{
+ int32 wi;
+ word32 rword[2];
+
+ memcpy(&(rword), &(d1), sizeof(double)); 
+ /* notice word length is 1 since reals have no b part */
+ wi = __allocfill_cval_new(&(rword[0]), &(rword[1]), 1);
+ return(wi); 
+}
+
+/*
+ * new version of allocate a constant value in design wide constant table
+ * notice passing word len but need room for 2*wlen for b part
+ *
+ * that uses hashing to prevent too much growth of contab during
+ * non blocking assign realloc and also just a better algorithm
+ */
+extern int32 __allocfill_cval_new(word32 *ap, word32 *bp, int32 wlen)
+{
+ register word32 hti;
+ register struct contab_info_t *cip;
+ int32 wi, bytsiz;
+ word32 *wp;
+
+ hti = get_hash(ap, bp, wlen);
+ bytsiz = wlen*WRDBYTES;
+ if ((cip = __contab_hash[hti]) != NULL)
+  {
+   for (; cip != NULL; cip = cip->cnxt)
+    {
+     if (cip->cwid != wlen) continue;
+
+     wp = &(__contab[cip->xvi]);
+     if (memcmp(wp, ap, bytsiz) == 0 && memcmp(&(wp[wlen]), bp, bytsiz) == 0) 
+       return(cip->xvi);
+    }
+  }
+
+ if (__contabwi + 2*wlen >= __contabwsiz) __grow_contab(2*wlen);
+ wi = __contabwi;
+ __contabwi += 2*wlen;
+ memcpy(&(__contab[wi]), ap, bytsiz);
+ memcpy(&(__contab[wi + wlen]), bp, bytsiz);
+
+ cip = (struct contab_info_t *) __my_malloc(sizeof(struct contab_info_t));
+ cip->xvi = wi;
+ cip->cwid = wlen;
+ /* put on front */ 
+ cip->cnxt = __contab_hash[hti];
+ __contab_hash[hti] = cip;
+ return(wi);
+}
+
+/*
+ * hash function
+ */
+static word32 get_hash(word32 *ap, word32 *bp, int32 wlen)
+{
+ register int32 wi;
+ word32 hval;
+
+ hval = ap[0] * HASHSEED;
+ for (wi = 1; wi < wlen; wi++)
+  {
+   hval ^= (ap[wi] ^ bp[wi]);
+  }
+ hval += wlen;
+ return(hval % HASHTABSIZ);
+}
+
+/*
+ * grow design wide constant table
+ *
+ * when growing, grow with current needed words in case IS array large  
+ * all sizes are in words because need word32 alignment
+ */
+extern void __grow_contab(int32 ndwrds)
+{
+ int32 old_ctabsiz, obsize, nbsize;
+ 
+ old_ctabsiz = __contabwsiz;
+ obsize = __contabwsiz*sizeof(word32);
+ /* fibronacci growth */
+ __contabwsiz = 3*(old_ctabsiz + ndwrds)/2; 
+ nbsize = __contabwsiz*sizeof(word32);
+ __contab = (word32 *) __my_realloc((char *) __contab, obsize, nbsize);
+}
+
+
+/*
+ * EXPRESSION PROCESSING CODE
+ */
+
+/*
+ * operator table
+ * SPECOP means requires separate case entry and special processing
+ * BEWARE - this table requires operator number k to be on row k
+ */
+struct opinfo_t __opinfo[] = {
+ /* place holders since using token number used as index into op table */
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "00E" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "idE" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "bnE" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "nE" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "inE" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "rE" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "irE" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "sE" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "giE" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "rmE" },
+ /* 10 */
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "rmE" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "rmE" },
+ /* notice ; now 12 */
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, ";" },
+ { SPECOP, NOTREALOP, NOTPTHOP, WIDSUM, "," },
+ { SPECOP, NOTREALOP, PTHOP, WIDNONE, ":" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "#" },
+ /* left grouping operators treated specially */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDNONE, "(" },  /* ( function call op. */
+ { SPECOP, NOTREALOP, PTHOP, WIDNONE, ")" },    /* ) RPAR */
+ { SPECOP, NOTREALOP, PTHOP, WIDNONE, "[" },    /* [ LSB */
+ { SPECOP, NOTREALOP, PTHOP, WIDNONE, "]" },    /* ] RSB */
+ /* 20 */
+ { BINOP, NOTREALOP, PTHOP, WIDSUM, "{" },      /* { LCB - empty rght but bin */
+ { SPECOP, NOTREALOP, PTHOP, WIDNONE, "}" },    /* } RCB */
+ { SPECOP, NOTREALOP, PTHOP, WIDNONE, "." },    /* . DOT */
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "@" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "->" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "=" },
+ /* unary ops */
+ /* LOOKATME - this is not really self determined result context determines */
+ /* but does not fit in pattern so always checked for */ 
+ { UNOP, NOTREALOP, PTHOP, WIDMAX, "~" },       /* ~ BITNOT - self determine */
+ { UNOP, REALOP, PTHOP, WIDONE, "!" },          /* ! NOT */
+ { RUNOP, REALOP, NOTPTHOP, WIDONE, "!" },      /* ! REALNOT */
+ /* both unary and binary */
+ { BOTHOP, NOTREALOP, PTHOP, WIDMAX, "^~" },    /* REDXNOR - must be ^~ */
+ /* 30 */
+ { BOTHOP, REALOP, NOTPTHOP, WIDMAX, "+" },     /* + PLUS */
+ { BOTHOP, REALOP, NOTPTHOP, WIDMAX, "-" },     /* - MINUS (un fixed to self)*/
+ { BOTHOP, NOTREALOP, PTHOP, WIDMAX, "&" },     /* & BITREDAND */
+ { BOTHOP, NOTREALOP, PTHOP, WIDMAX, "|" },     /* | BITREDOR */
+ { BOTHOP, NOTREALOP, PTHOP, WIDMAX, "^" },     /* ^ BITREDXOR */
+ { RBOTHOP, REALOP, NOTPTHOP, WIDMAX, "-" },     /* + REALINUS */
+ /* binary operators */
+ { BINOP, REALOP, NOTPTHOP, WIDMAX, "*" },      /* * TIMES */
+ { BINOP, REALOP, NOTPTHOP, WIDMAX, "/" },      /* / DIV */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDMAX, "%" },   /* % MOD */
+ { BINOP, REALOP, NOTPTHOP, WIDENONE, ">=" },   /* >= RELGE */
+ /* 40 */
+ { BINOP, REALOP, NOTPTHOP, WIDENONE, ">" },    /* > RELGT */
+ { BINOP, REALOP, NOTPTHOP, WIDENONE, "<=" },   /* <= RELLE (not assgn) */
+ { BINOP, REALOP, NOTPTHOP, WIDENONE, "<" },    /* < RELLT */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDENONE, "===" }, /* === RELCEQ */
+ { BINOP, REALOP, PTHOP, WIDENONE, "==" },      /* == RELEQ */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDENONE, "!==" }, /* !== RELCNEQ */
+ { BINOP, REALOP, PTHOP, WIDENONE, "!=" },      /* != RELNEQ */
+ { BINOP, REALOP, PTHOP, WIDONE, "&&" },        /* && BOOLAND */
+ { BINOP, REALOP, PTHOP, WIDONE, "||" },        /* || BOOLOR */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDLEFT, "<<" }, /* << SHIFTL */
+ /* 50 */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDLEFT, "<<<" }, /* <<< ASHIFTL */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDLEFT, ">>" }, /* >> SHIFTR */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDLEFT, ">>>" }, /* >>> ASHIFTR */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDONE, "*>" },  /* *> FPTHCON */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDONE, "=>" },  /* => PPTHCON */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDONE, "&&&" }, /* TCHK &&& (cond. event) */
+ { RBINOP, REALOP, NOTPTHOP, WIDMAX, "+" },     /* + REALPLUS */ 
+ { RBINOP, REALOP, NOTPTHOP, WIDMAX, "*" },     /* * REALTIMES */ 
+ { RBINOP, REALOP, NOTPTHOP, WIDMAX, "/" },     /* / REALDIV */ 
+ { RBINOP, REALOP, NOTPTHOP, WIDENONE, ">" },   /* > REALRELGT */
+ /* 60 */
+ { RBINOP, REALOP, NOTPTHOP, WIDENONE, ">=" },  /* >= REALRELGE */
+ { RBINOP, REALOP, NOTPTHOP, WIDENONE, "<" },   /* < REALRELLT */
+ { RBINOP, REALOP, NOTPTHOP, WIDENONE, "<=" },  /* <= REALRELLE */
+ { RBINOP, REALOP, NOTPTHOP, WIDENONE, "==" },  /* == REALRELEQ */
+ { RBINOP, REALOP, NOTPTHOP, WIDENONE, "!=" },  /* != REALRELEQ */
+ { RBINOP, REALOP, NOTPTHOP, WIDONE, "&&" },    /* && REALBOOLAND */
+ { RBINOP, REALOP, NOTPTHOP, WIDONE, "||" },    /* != REALBOOLOR */
+ /* tree will be left of : will be (cond)?(1st expr) and right will be */
+ /* 2nd must be fixed, need for a[x?y:z:...] */
+ /* width is max of operators (i.e. narrow must be padded) */
+ { SPECOP, REALOP, PTHOP, WIDMAX, "?" },        /* ? QUEST (lhs part of ?:) */
+ { SPECOP, NOTREALOP, PTHOP, WIDMAX, "?:" },    /* : QCOL (rhs part of ?:)  */
+ { SPECOP, NOTREALOP, PTHOP, WIDSELF, "PARTSEL" },/* [ PARTSEL (2 val sel) */
+ /* 70 */
+ { BINOP, NOTREALOP, PTHOP, WIDSUM, "CATCOMMA" }, /* , part of { } */
+ /* probably should have real quad op. for these */
+ { BINOP, NOTREALOP, PTHOP, WIDSELF, "CATREP" },  /* [num]{ } concat repeat */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDSELF, "FCALL OP" }, /* function call */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDSELF, "LIST COMMA" },/* , of fcall () list*/
+ /* only legal in event expressions */
+ { SPECOP, NOTREALOP, NOTPTHOP, WIDONE, "or" },   /* OR event or */
+ { SPECOP, NOTREALOP, NOTPTHOP, WIDONE, "," },    /* , event or as comma */
+ /* these are normal unaries except semantics only operand of evor */
+ { UNOP, NOTREALOP, NOTPTHOP, WIDONE, "posedge " }, /* OPPOSEDGE ev prefix */
+ { UNOP, NOTREALOP, NOTPTHOP, WIDONE, "negedge " }, /* OPNEGEDGE ev prefix */
+ /* this do not use table - handle in code */
+ { SPECOP, REALOP, NOTPTHOP, WIDMAX, "?" },     /* REALREALQUEST (lhs of ?:) */
+ { SPECOP, REALOP, NOTPTHOP, WIDMAX, "?" },     /* REALREGQUEST (lhs of ?:) */
+ /* 80 */
+ { SPECOP, REALOP, NOTPTHOP, WIDMAX, "?:" },    /* REGREALQCOL (rhs of ?:) */
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "rmE" }, /* GLBREF */
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "rmE" }, /* GLBPATH */
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "XMR ID" }, /* XMRID */
+ { BINOP, NOTREALOP, NOTPTHOP, WIDSELF, "XMR LIST COMMA" },/* XMR comma */
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "EXPR END" },
+ { NOTANOP, NOTREALOP, NOTPTHOP, WIDNONE, "TEOF" },
+};
+
+/*
+ * convert expression table to expression tree
+ * for specparam may start at 1 instead of 0 if not min:typ:max form
+ */
+extern void __bld_xtree(int32 start_xndi)
+{
+ struct expr_t *ndp;
+
+ /* add end of expression fence */
+ __has_top_mtm = FALSE;
+ ndp = __alloc_exprnd();
+ ndp->optyp = UNDEF;
+ __xndi = start_xndi;
+ __saverr_cnt = __pv_err_cnt;
+ /* __xndi should point to last token which is added UNDEF fence */
+ if ((__root_ndp = parse_qcexpr()) == NULL || __xndi != __last_xtk)
+  {
+   /* if for some reason, empty exprs (no error), emit some kind of err */
+   if (__saverr_cnt == __pv_err_cnt)
+    {
+     if (__xndi > __last_xtk)
+      __pv_ferr(1108, "expression missing required operator or operand");
+     else if (__xndi < __last_xtk)
+      {
+       if (__exprtab[__xndi]->optyp == COMMA)
+        __pv_ferr(1111,
+         "expression list illegal - check for missing ')' or extra ','"); 
+       else __pv_ferr(1109, "expression illegal token [%s]",
+        to_xndnam(__xs, __xndi));
+      }
+     else
+      {
+       __pv_ferr(1110, "expression parse error at token [%s]",
+	to_xndnam(__xs, __xndi));
+      }
+    }
+   /* notice by here already moved to allocated nodes from exprtab */   
+   __root_ndp = __alloc_newxnd();
+   __set_numval(__root_ndp, 1L, 1L, 1);
+  }
+}
+
+/*
+ * EXPRESSION PARSING ROUTINES
+ */
+
+/*
+ * parse an expression that can contain ?: operators
+ *
+ * ?: is lowest precedence - everything has stronger attraction 
+ */
+static struct expr_t *parse_qcexpr(void)
+{
+ struct expr_t *ndp, *qcndp, *tndp, *fndp;
+
+ /* handle most common cases without parsing */
+ /* before parsing bld xtree always places end marker - undef at end */
+ /* so last xtk here is one past end i.e. 1 for ID */
+ /* also because not yet parsed part select operator still LSB */ 
+ if (__last_xtk == 1
+  || (__last_xtk == 3 && __exprtab[1]->optyp == LSB)
+  || (__last_xtk == 6 && __exprtab[1]->optyp == LSB
+     && __exprtab[3]->optyp == COLON))
+  {
+   qcndp = parse_term();
+   return(qcndp);
+  }
+
+ /* DBG need special case code, just set __last_xtk == 1 term */
+ /* routine leaves __xndi at next place to look */
+ if ((qcndp = parse_boolorop()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ if (ndp->optyp == QUEST)
+  {
+   ndp = alloc_xtnd(__xndi);
+   ndp->lu.x = qcndp;
+   qcndp = ndp;
+   __xndi++;
+   /* this can be recursive since no left recursion problem for ?: */
+   /* this forces right to left grouping since reduces right then backs */
+   /* up recursion tree to build reduced pieces from left */
+   if ((tndp = parse_qcexpr()) == NULL)
+    {
+bad_qcexpr:
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1112, "?: parse error at token [%s]", to_xndnam(__xs,
+       __xndi));
+     /* move x ndi to end */
+     xskip_toend();
+
+     /* on error here make a 1 bit x this is part of longer expr. */
+     ndp = alloc_xtnd(__xndi);
+     __set_numval(ndp, 1L, 1L, 1);
+     return(ndp);
+    }
+   ndp = __exprtab[__xndi];
+   if (ndp->optyp != COLON) goto bad_qcexpr;
+   ndp = alloc_xtnd(__xndi);
+   ndp->optyp = QCOL;
+   qcndp->ru.x = ndp;
+   ndp->lu.x = tndp;
+   __xndi++;
+   if ((fndp = parse_qcexpr()) == NULL) goto bad_qcexpr;
+   ndp->ru.x = fndp;
+  }
+ return(qcndp);
+}
+
+/*
+ * skip past 1 expression node of node type ndtyp
+ * this is needed
+ */
+static void xskip_toend(void)
+{
+ struct expr_t *ndp;
+
+ for (;;__xndi++)
+  {
+   /* never skip past expr. ending fence */
+   ndp = __exprtab[__xndi];
+   if (ndp->optyp == UNDEF) break;
+  }
+}
+
+/*
+ * parse boolean or (||) operators
+ * precdence one up from lowest
+ */
+static struct expr_t *parse_boolorop(void)
+{
+ int32 savi;
+ struct expr_t *ndp, *rhsndp, *leftopndp;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_boolandop()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ for (;;)
+  {
+   if (ndp->optyp == BOOLOR)
+    {
+     savi = __xndi;
+     __xndi++;
+     /* treat [term [op] error] as term - could improve recovery here */
+     if ((rhsndp = parse_boolandop()) == NULL) break;
+     /* this makes sure optyp right */
+     ndp = alloc_xtnd(savi);
+     ndp->lu.x = leftopndp;
+     ndp->ru.x = rhsndp;
+     leftopndp = ndp;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * parse boolean and (&&) operators
+ */
+static struct expr_t *parse_boolandop(void)
+{
+ int32 savi;
+ struct expr_t *ndp, *rhsndp, *leftopndp;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_borop()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ for (;;)
+  {
+   if (ndp->optyp == BOOLAND)
+    {
+     savi = __xndi;
+     __xndi++;
+     if ((rhsndp = parse_borop()) == NULL) break;
+
+     /* this makes sure optyp right */
+     ndp = alloc_xtnd(savi);
+     ndp->lu.x = leftopndp;
+     ndp->ru.x = rhsndp;
+     leftopndp = ndp;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * parse bit wise or operators
+ */
+static struct expr_t *parse_borop(void)
+{
+ int32 savi;
+ struct expr_t *ndp, *rhsndp, *leftopndp;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_bxorop()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ for (;;)
+  {
+   if (ndp->optyp == BITREDOR)
+    {
+     /* fence and must check at binary bit wise | for following un red | */
+     if (__exprtab[__xndi + 1]->optyp == BITREDOR)
+      {
+       __pv_fwarn(564,
+	"[expr] | |[expr] invalid - unary should be surrounded by parentheses");
+      }
+     savi = __xndi;
+     __xndi++;
+     if ((rhsndp = parse_bxorop()) == NULL) break;
+     /* this makes sure optyp right */
+     ndp = alloc_xtnd(savi);
+     ndp->lu.x = leftopndp;
+     ndp->ru.x = rhsndp;
+     leftopndp = ndp;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * parse bit wise xor operators
+ */
+static struct expr_t *parse_bxorop(void)
+{
+ int32 savi;
+ struct expr_t *ndp, *rhsndp, *leftopndp;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_bandop()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ for (;;)
+  {
+   if (ndp->optyp == BITREDXOR || ndp->optyp == REDXNOR)
+    {
+     savi = __xndi;
+     __xndi++;
+     /* treat [term [op] error] as term */
+     if ((rhsndp = parse_bandop()) == NULL) break;
+     /* this makes sure optyp right */
+     ndp = alloc_xtnd(savi);
+     ndp->lu.x = leftopndp;
+     ndp->ru.x = rhsndp;
+     leftopndp = ndp;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * parse bit wise and operators
+ */
+static struct expr_t *parse_bandop(void)
+{
+ int32 savi;
+ struct expr_t *ndp, *rhsndp, *leftopndp;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_eqop()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ for (;;)
+  {
+   if (ndp->optyp == BITREDAND)
+    {
+     /* notice when see binary & must see if following unary red. & */
+     /* know fence always present */
+     if (__exprtab[__xndi + 1]->optyp == BITREDAND)
+      {
+       __pv_fwarn(564,
+	"[expr] & &[expr] invalid - unary should be surrounded by parentheses");
+      }
+     savi = __xndi;
+     __xndi++;
+     if ((rhsndp = parse_eqop()) == NULL) break;
+     /* this makes sure optyp right */
+     ndp = alloc_xtnd(savi);
+     ndp->lu.x = leftopndp;
+     ndp->ru.x = rhsndp;
+     leftopndp = ndp;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * parse equal not equal operators
+ */
+static struct expr_t *parse_eqop(void)
+{
+ int32 savi;
+ struct expr_t *ndp, *rhsndp, *leftopndp;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_ltgtop()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ for (;;)
+  {
+   if (ndp->optyp == RELEQ || ndp->optyp == RELNEQ || ndp->optyp == RELCEQ
+    || ndp->optyp == RELCNEQ)
+    {
+     savi = __xndi;
+     __xndi++;
+     if ((rhsndp = parse_ltgtop()) == NULL) break;
+     /* this makes sure optyp right */
+     ndp = alloc_xtnd(savi);
+     ndp->lu.x = leftopndp;
+     ndp->ru.x = rhsndp;
+     leftopndp = ndp;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * parse a less than or greater than type op
+ */
+static struct expr_t *parse_ltgtop(void)
+{
+ int32 savi;
+ struct expr_t *ndp, *rhsndp, *leftopndp;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_shop()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ for (;;)
+  {
+   if (ndp->optyp == RELLT || ndp->optyp == RELLE || ndp->optyp == RELGT
+    || ndp->optyp == RELGE)
+    {
+     savi = __xndi;
+     __xndi++;
+     if ((rhsndp = parse_shop()) == NULL) break;
+     /* this makes sure optyp right */
+     ndp = alloc_xtnd(savi);
+     ndp->lu.x = leftopndp;
+     ndp->ru.x = rhsndp;
+     leftopndp = ndp;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * parse a shift type op
+ */
+static struct expr_t *parse_shop(void)
+{
+ int32 savi;
+ struct expr_t *ndp, *rhsndp, *leftopndp;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_addop()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ for (;;)
+  {
+   if (ndp->optyp == SHIFTL || ndp->optyp == SHIFTR
+    || ndp->optyp == ASHIFTL || ndp->optyp == ASHIFTR)
+    {
+     savi = __xndi;
+     __xndi++;
+     if ((rhsndp = parse_addop()) == NULL) break;
+     /* this makes sure optyp right */
+     ndp = alloc_xtnd(savi);
+     ndp->lu.x = leftopndp;
+     ndp->ru.x = rhsndp;
+     leftopndp = ndp;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * parse a add type op
+ */
+static struct expr_t *parse_addop(void)
+{
+ int32 savi;
+ /* struct expr_t *ndp, *lhsndp, *rhsndp, *opndp, *last_opndp; */
+ struct expr_t *ndp, *rhsndp, *leftopndp;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_mulop()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ /* last_opndp = NULL; */
+ for (;;)
+  {
+   if (ndp->optyp == PLUS || ndp->optyp == MINUS)
+    {
+     savi = __xndi;
+     __xndi++;
+     if ((rhsndp = parse_mulop()) == NULL) break;
+     /* this makes sure optyp right */
+     ndp = alloc_xtnd(savi);
+     ndp->lu.x = leftopndp;
+     ndp->ru.x = rhsndp;
+     leftopndp = ndp;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * parse a mult/div type op
+ */
+static struct expr_t *parse_mulop(void)
+{
+ int32 savi;
+ struct expr_t *ndp, *rhsndp, *leftopndp;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_unopterm()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ for (;;)
+  {
+   if (ndp->optyp == TIMES || ndp->optyp == DIV || ndp->optyp == MOD)
+    {
+     savi = __xndi;
+     __xndi++;
+     if ((rhsndp = parse_unopterm()) == NULL) break;
+     /* this makes sure optyp right */
+     ndp = alloc_xtnd(savi);
+     ndp->lu.x = leftopndp;
+     ndp->ru.x = rhsndp;
+     leftopndp = ndp;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * parse [un. op] <term>
+ * expects __xndi to point to next place in expr. and moves to 1 after end
+ *
+ * parens here surround subexpressions not fcall
+ */
+static struct expr_t *parse_unopterm(void)
+{
+ int32 sav_xndi;
+ struct expr_t *ndp, *ndp2, *unopndp, *lastndp;
+
+ lastndp = NULL;
+ unopndp = NULL;
+ ndp = __exprtab[__xndi];
+ switch ((byte) ndp->optyp) {
+  /* notice real number can not start with . (.33 illegal) */
+  case ID: case NUMBER: case REALNUM: return(parse_term());
+  case LPAR:
+do_parens:
+   sav_xndi = __xndi++;
+   if ((ndp2 = parse_qcexpr()) == NULL) return(NULL);
+   ndp = __exprtab[__xndi];
+   /* any time in ( expr. may be (expr:expr:expr) form */
+   /* only parsable because all 3 required if : present */
+   if (ndp->optyp == COLON)
+    {
+     struct expr_t *minxndp, *nomxndp;
+
+     minxndp = ndp2;
+     __xndi++;
+     if ((ndp2 = parse_qcexpr()) == NULL)
+      {
+mintyp_err:
+       if (__pv_err_cnt <= __saverr_cnt)
+        __pv_ferr(1113, "mintypmax expression error at token [%s]",
+         to_xndnam(__xs, __xndi));
+       /* must skip one past 3 value form ending ) */
+       skip_3valend();
+       return(NULL);
+      }
+     nomxndp = ndp2;
+     ndp = __exprtab[__xndi];
+     if (ndp->optyp != COLON) goto mintyp_err;
+     __xndi++;
+     if ((ndp2 = parse_qcexpr()) == NULL) goto mintyp_err;
+     ndp = __exprtab[__xndi];
+     if (ndp->optyp != RPAR) goto mintyp_err;
+     if (__mintypmax_sel == DEL_MIN) ndp2 = minxndp;
+     else if (__mintypmax_sel == DEL_TYP) ndp2 = nomxndp;
+     __xndi++;
+     if (sav_xndi == 0) __has_top_mtm = TRUE;
+     goto unop_ret;
+    }
+   /* either eox or ) seen or will not get here */
+   if (ndp->optyp != RPAR)
+    {
+     __pv_ferr(1113,
+      "expression primary or mintypmax expression ending ) expected - %s read",
+      to_xndnam(__xs, __xndi));
+     return(NULL);
+    }
+   __xndi++;
+   goto unop_ret;
+ }
+ if (is_unop(ndp->optyp))
+  {
+rep_unops:
+   if (ndp->optyp != PLUS)
+    {
+     ndp = alloc_xtnd(__xndi);
+     ndp->ru.x = NULL;
+     if (lastndp == NULL) unopndp = ndp; else lastndp->lu.x = ndp;
+     lastndp = ndp;
+    }
+
+   ndp2 = __exprtab[++__xndi];
+   if (ndp2->optyp == LPAR) goto do_parens;
+   /* unary operator chain */
+   if (is_unop(ndp2->optyp))
+    {
+     ndp = ndp2;
+     goto rep_unops;
+    }
+
+   if ((ndp2 = parse_term()) == NULL) return(NULL);
+   /* add to end of possible linear unary operator chain */
+unop_ret:
+   if (lastndp == NULL) unopndp = ndp2; else lastndp->lu.x = ndp2;
+   return(unopndp);
+  }
+ return(parse_term());
+}
+
+/*
+ * on error in 3 value expression must skip to eox or 1 past same level )
+ */
+static void skip_3valend(void)
+{
+ int32 paren_level;
+
+ for (paren_level = 0; __xndi <= __last_xtk; __xndi++)
+  {
+   switch ((byte) __exprtab[__xndi]->optyp) {
+    case UNDEF: return;
+    case LPAR: paren_level++; break;
+    case RPAR:
+     if (paren_level == 0) { __xndi++; return; }
+     else paren_level--;
+   }
+  }
+}
+
+/*
+ * return T if expression node is a unary operator that does not require
+ * special processing
+ */
+static int32 is_unop(word32 otyp)
+{
+ struct opinfo_t *opip;
+
+ opip = &(__opinfo[otyp]);
+ if (opip->opclass == UNOP || opip->opclass == BOTHOP) return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * parse a terminal 
+ *
+ * expects __xndi at current place and leaves __xndi index one
+ * past end of terminal
+ *
+ * notice Verilog terminals need special routine - too complicated
+ * to parse using grammar 
+ *
+ * here can use expridtab and exprtab as arguments to routine because
+ * these are not overwritten but globals that parsing marches through
+ *
+ * no error recovery because already have collected only expr
+ */
+static struct expr_t *parse_term(void)
+{
+ struct expr_t *ndp, *ndp2, *idndp, *glbndp;
+ struct sy_t *syp;
+ struct expridtab_t *xidp;
+
+ /* some kind of terminal */
+ ndp = __exprtab[__xndi];
+ switch ((byte) ndp->optyp) {
+  case NUMBER: case REALNUM: case OPEMPTY:
+   /* 06/22/00 - SJM - if 2 numeric tokens in a row assume sized num */ 
+   /* FIXME - need error recovery here - indicate 2nd is part of 2 tok num */
+   if (__exprtab[__xndi + 1]->optyp == NUMBER)
+    {
+     struct expr_t *ndp3;
+
+     ndp3 = __exprtab[__xndi + 1];
+     if (!ndp->unsiznum || ndp->ibase != BDEC || ndp3->unsiznum
+      || ndp3->sizdflt) goto not_2tok_num;
+     __xndi++;
+    }
+
+not_2tok_num:
+   /* this copies any constant value from __exprtab[] */
+   ndp = alloc_xtnd(__xndi);
+   __xndi++;
+   return(ndp);
+  case LCB:
+   ndp2 = parse_concat();
+   return(ndp2);
+  case ID:
+   idndp = alloc_xtnd(__xndi);
+   xidp = __expr_idtab[__xndi];
+   /* DBG remove --- */
+   if (xidp == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   /* move one past ID */
+   __xndi++;
+   ndp = __exprtab[__xndi];
+
+   /* special case determine and return no argument sys fcall */
+   /* system function no args legal - $ no ( implies function call */
+   /* for range expr. ndp sy == NULL true */
+   /* ID that is system func call, can not be glb. ref. */
+   /* LOOKATME - can access functions start with $ - think not */
+   if (xidp->idnam[0] == '$' && ndp->optyp != LPAR)
+    {
+     if ((syp = __get_sym(xidp->idnam, __syssyms)) == NULL)
+      {
+       __pv_ferr(683,
+        "call of unknown built-in or unregistered PLI system function %s illegal - for dynamic, register generic place holder",
+        xidp->idnam);
+       return(NULL); 
+      }
+     /* attempt to call ID starting with $ (must be system task?) illegal */
+     if (syp->sytyp != SYM_SF)
+      {
+       __pv_ferr(681,
+        "illegal call of system task %s - only functions calleable",
+        syp->synam);
+       return(NULL); 
+      }
+
+     idndp->lu.sy = syp;
+     /* error if system function used in xmr */
+     if (ndp->optyp == DOT)
+      {
+       __pv_ferr(1127,
+        "call of system function %s followed by '.' -  illegal hierarchical reference",
+        idndp->lu.sy->synam);
+       return(NULL);
+      }
+     ndp2 = __alloc_newxnd();
+     ndp2->optyp = FCALL;
+     ndp2->lu.x = idndp;
+     ndp2->ru.x = NULL;
+     return(ndp2);
+    }
+
+
+   /* if system func with args, continue to normal fcall */
+   if (ndp->optyp == LSB)
+    {
+     /* inst array ref. then fix global resolution code to make select */
+     /* on error returns nil - can not parse possible rest of expr */
+     if ((ndp2 = parse_select(idndp)) == NULL) return(NULL);
+
+     /* xndi one past end of select - xmr is special case */ 
+     /* routine will not add path components to current sym table */
+     if (__exprtab[__xndi]->optyp == DOT)
+      {
+       if ((glbndp = parse_glbref(ndp2, xidp)) == NULL) return(NULL);
+       if (__exprtab[__xndi]->optyp != LPAR) return(glbndp); 
+
+       /* xmr followed by ( is function call - 1st comp. inst arr case */
+       /* can not be system func and therefore '(' required */ 
+       ndp2 = parse_fcall(glbndp, NULL, TRUE);
+       return(ndp2);
+      }
+     /* part select never legal for one comp array of insts select */ 
+     if (__allow_scope_var && ndp2->optyp == LSB)
+      {
+       /* if already declared as net t in current env., know not glb */
+       /* must also be net - since net is never xmr */
+       if ((syp = __get_sym_env(xidp->idnam)) != NULL && syp->sytyp == SYM_N)
+        goto do_decl;
+
+       /* notice this can not fail - make ID into global ref. */
+       return(bld_1cmp_global(ndp2, xidp));
+      }
+
+do_decl:
+     /* not xmr - declare the ID symbol */
+     if (!decl_id_inexpr(idndp, xidp)) return(NULL);
+     return(ndp2);
+    }
+   if (ndp->optyp == LPAR)
+    {
+
+     /* fcall can be xmr, handle in global parsing routine */ 
+     /* this works because user function (no $ first char) must have args */
+     ndp2 = parse_fcall(idndp, xidp, FALSE);
+     return(ndp2);
+    }
+   /* simple ID - current location one after ID */
+   /* non special terminal - next is lower precedence rest of expr */
+   if (__exprtab[__xndi]->optyp == DOT)
+    {
+     if ((glbndp = parse_glbref(idndp, xidp)) == NULL) return(NULL);
+
+     if (__exprtab[__xndi]->optyp != LPAR) return(glbndp);
+
+     /* xmr followed by ( is function call - non inst array 1st comp case */
+     ndp2 = parse_fcall(glbndp, NULL, TRUE);
+     return(ndp2);
+    }  
+   if (__allow_scope_var)
+    {
+     /* notice this can not fail - make ID into global ref. */
+     return(bld_1cmp_global(idndp, xidp));
+    }
+
+   if (!decl_id_inexpr(idndp, xidp)) return(NULL);
+   return(idndp);
+  case DOT:
+   /* need exact error for ID that starts with . */
+   __pv_ferr(1128,
+    "hierarchical reference or real constant initial '.' illegal");
+   return(NULL);
+  default:
+   if (__pv_err_cnt <= __saverr_cnt)
+    __pv_ferr(1116, "expression terminal expected - %s read",
+     to_xndnam(__xs, __xndi));
+  }
+ return(NULL);
+}
+
+
+/*
+ * routine to find symbol in symbol table adding if needed
+ *
+ * must not call until ID known not to be part of xmr
+ * name of variable taken from expr id nam global table
+ */
+static int32 decl_id_inexpr(struct expr_t *ndp, struct expridtab_t *xidp)
+{ 
+ struct sy_t *syp;
+ struct net_t *np;
+
+ /* routine never called for function call or task enable */
+ /* DBG remove --- */
+ if (xidp->idnam[0] == '$') __arg_terr(__FILE__, __LINE__);
+ /* --- */
+
+ ndp->lu.x = NULL;
+ /* since parse range as select with dummy var leave sy field nil for "[]" */
+ if (xidp->idnam[0] == '[') return(TRUE); 
+
+ if ((syp = __get_sym_env(xidp->idnam)) == NULL)
+  {
+   /* undeclared specify declared as net var in current sym tab */
+   if (__cur_declobj == SPECIFY)
+    syp = __decl_sym(xidp->idnam, __venviron[__top_sti]);
+   /* undeclared var. declared at module level because task/block */
+   /* declaration must come first and therefore will be declared */
+   else 
+    {
+     if (__iact_state)
+      {
+       /* interactive statement - all variables must be declared */
+       /* for $dumpvars will avoid this code and jump to assume glb */
+       __pv_err_cnt++;
+       if (strcmp(xidp->idnam, "") == 0)
+        {
+         __ia_err(1436,
+          "escaped identifier empty - probable white space before escaped continuation new line");
+        }
+       else __ia_err(1436, "variable %s not declared", xidp->idnam);
+       return(FALSE);
+      }
+     else syp = __decl_sym(xidp->idnam, __venviron[0]);
+    }
+
+   np = __add_net(syp);
+   /* assume register - this is forward decl */
+   /* even if in specify assume wire and fix up when declared */
+   np->ntyp = N_REG;
+   syp->sylin_cnt = xidp->idlin_cnt;
+   syp->syfnam_ind = xidp->idfnam_ind;
+  }
+ ndp->lu.sy = syp;
+ return(TRUE);
+}
+
+/*
+ * find a a system task/func symbol (know name starts with $)
+ * must be system function or task (maybe PLI)
+ *
+ * notice no special processing of scale arg. since must be var.
+ * in module from which scale taken
+ */
+static struct sy_t *find_systf_sym(struct expridtab_t *xidp)
+{
+ struct sy_t *syp;
+
+ /* look up in system task/func symbol table - must be there*/
+ /* PLI redefine legal and will be in this symbol table */
+ if ((syp = __get_sym(xidp->idnam, __syssyms)) == NULL)
+  {
+   if (__expr_is_lval)
+    __gferr(1102, xidp->idfnam_ind, xidp->idlin_cnt,
+     "enable of unknown system task or undefined PLI task %s",
+     xidp->idnam);
+   else
+    __gferr(1102, xidp->idfnam_ind, xidp->idlin_cnt,
+     "call of unknown system or undefined PLI function %s",
+     xidp->idnam);
+   return(NULL);
+  }
+ /* if lvalue, must be system table enable */
+ if (__expr_is_lval)
+  { 
+   if (syp->sytyp != SYM_STSK)
+    { 
+     __gferr(1100, xidp->idfnam_ind, xidp->idlin_cnt,
+      "attempt to enable (not call) system function %s", xidp->idnam);
+     return(NULL);
+    }
+  }
+ else
+  {
+   if (syp->sytyp != SYM_SF)
+    {
+     __gferr(1103, xidp->idfnam_ind, xidp->idlin_cnt,
+      "call of system task %s illegal", xidp->idnam);
+     return(NULL);
+    }
+  }
+ return(syp);
+}
+
+/*
+ * parse a concatenate
+ * know current expr. token is leading { and points to one after }
+ * on non error (non NULL)  return
+ *
+ * form is: {el, el, ..., el}, where el. is <expr.>, { concat, or
+ * <expr> concat
+ *
+ * must be optimized after building tree
+ * for now optimize just remove one element concatenates and dups
+ * rep concat. form
+ */
+static struct expr_t *parse_concat(void)
+{
+ struct expr_t *ndp, *ndp2, *argndp, *last_ndp;
+ struct expr_t *lop;
+
+ ndp2 = alloc_xtnd(__xndi);
+ __xndi++;
+ ndp2->lu.x = NULL;
+
+ for (last_ndp = NULL;;)
+  {
+   if ((argndp = parse_qcexpr()) == NULL) return(NULL);
+add_to_tree:
+   ndp = __exprtab[__xndi];
+
+   /* processing depends on thing after 1st concat el. */
+   switch ((byte) ndp->optyp) {
+    case COMMA:
+     /* build node since at least one more concat element */
+     lop = __alloc_newxnd();
+     lop->optyp = CATCOM;
+     if (last_ndp == NULL) ndp2->ru.x = lop; else last_ndp->ru.x = lop;
+     lop->lu.x = argndp;
+     last_ndp = lop;
+     /* must skip over comma */
+     __xndi++;
+     break;
+    case RCB:
+     /* done - notice last CATCOM node has NULL right pointer */
+     lop = __alloc_newxnd();
+     lop->optyp = CATCOM;
+     if (last_ndp == NULL) ndp2->ru.x = lop; else last_ndp->ru.x = lop;
+     lop->lu.x = argndp;
+     lop->ru.x = NULL;
+     __xndi++;
+     return(ndp2);
+    case LCB:
+     {
+      struct expr_t *repndp, *catndp;
+
+      repndp = argndp;
+      if ((catndp = parse_concat()) == NULL) return(NULL);
+
+      argndp = __alloc_newxnd();
+      argndp->optyp = CATREP;
+      argndp->lu.x = repndp;
+      argndp->ru.x = catndp;
+     }
+     goto add_to_tree;
+    default:
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1119,
+       "nested concatenate or comma separator expected - %s read",
+       to_xndnam(__xs, __xndi));
+     /* as special case for concat, must skip to } if possible */
+     __vskipto_any(RCB);
+     return(NULL);
+    }
+  }
+}
+
+/*
+ * parse a select 
+ * copies into malloced storage and return select expr subtree
+ * know id ndp already copied to malloced storage
+ *
+ * [ read - reads one past ending ] 
+ */
+static struct expr_t *parse_select(struct expr_t *idndp)
+{
+ struct expr_t *ndp, *sel_ndp, *i1ndp, *i2ndp;
+
+ /* build (alloc and copy) select sub expression root */
+ sel_ndp = alloc_xtnd(__xndi);
+ __xndi++;
+ /* side effect of parsing sub expression is advancing global x ndi */
+ /* returned i1ndp is malloced not built in __exprtab */
+ if ((i1ndp = parse_qcexpr()) == NULL) return(NULL);
+ sel_ndp->lu.x = idndp;
+ ndp = __exprtab[__xndi];
+ if (ndp->optyp == RSB)
+  {
+   sel_ndp->ru.x = i1ndp;
+   __xndi++;
+   /* next may be dot (handled as term by caller) or rest of expr */
+   return(sel_ndp);
+  }
+ /* part select - if illegal in context caller must detect */
+ if (ndp->optyp != COLON)
+  {
+   if (__pv_err_cnt <= __saverr_cnt)
+    __pv_ferr(1114,
+     "bit/part select expression : or ] separator expected - %s read",
+     to_xndnam(__xs, __xndi));
+   /* if T, current is one past ending ] */
+   return(NULL);
+  }
+ /* part select after : */
+ __xndi++;
+ if ((i2ndp = parse_qcexpr()) == NULL) return(NULL);
+ ndp = __exprtab[__xndi];
+ if (ndp->optyp != RSB)
+  {
+   if (__pv_err_cnt <= __saverr_cnt)
+    __pv_ferr(1115,
+     "part select expression ending ] expected - %s read",
+     to_xndnam(__xs, __xndi));
+   return(NULL);
+  }
+ sel_ndp->optyp = PARTSEL;
+ ndp = alloc_xtnd(__xndi);
+ ndp->optyp = COLON;
+ sel_ndp->ru.x = ndp;
+ ndp->lu.x = i1ndp;
+ ndp->ru.x = i2ndp;
+ /* move one past RSB if possible */
+ if (__xndi < __last_xtk) __xndi++;
+ /* part select never xmr */
+ return(sel_ndp);
+}
+
+/*
+ * parse and and build global record for xmr
+ *
+ * current expr table node is one past id (dot or [) when called
+ * reads one past end of xmr
+ * argument is xmr first component expression and id name tab element
+ * returns expression that may be select (if var tail is select)
+ *
+ * allowing constant selects for arrays of instances and gates  
+ * for say a[a+b].b.c.w[kk], w[kk] is bit select of variable 
+ * for xmr instance allowed context - gets fixed up to instance
+ *
+ * changes IDs where unparsed name in expr id tab move to
+ * expr node with special XMRID node type
+ */
+static struct expr_t *parse_glbref(struct expr_t *cmp1_ndp,
+ struct expridtab_t *cmp1_xidp)
+{
+ int32 is_sel;
+ struct expr_t *ndp, *glbndp, *last_cmp;
+ struct expr_t *idndp, *ndp2, *cmp_ndp; 
+ struct expridtab_t *xidp;
+ struct gref_t *grp;
+
+ /* expr. has top level global then each xmr comma left points to id */
+ /* or select for inst or gate array */
+ glbndp = __alloc_newxnd();
+ glbndp->optyp = GLBREF;
+ glbndp->ru.x = __alloc_newxnd();
+ glbndp->ru.x->optyp = XMRCOM;
+ glbndp->ru.x->lu.x = cmp1_ndp;
+
+ if (cmp1_ndp->optyp == LSB)
+  {
+   /* select already parsed and bsel expr. built */
+   /* cmp ndp ru field set to idnam for first comp. of global */  
+   cmp1_ndp->lu.x->ru.qnchp = __pv_stralloc(cmp1_xidp->idnam);
+   /* current xndi now one past end of select */ 
+   cmp1_ndp->lu.x->optyp = XMRID;
+  }
+ else if (cmp1_ndp->optyp == ID)
+  {
+   /* unused ru field used for name, lu.sy to xmr dest. filled later */
+   cmp1_ndp->ru.qnchp = __pv_stralloc(cmp1_xidp->idnam);
+   cmp1_ndp->optyp = XMRID;
+  }
+ else if (cmp1_ndp->optyp != DOT)
+  {
+   /* notice here gnam no build and rest of gref expr no read */
+   __pv_ferr(682, "hierarchical reference contains illegal operator %s",
+    __to_opname(cmp1_ndp->optyp));
+   return(NULL);
+  }
+
+ /* DBG remove --- */
+ if (__exprtab[__xndi]->optyp != DOT) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* last comp is always right tree end expr. comp */
+ last_cmp = glbndp->ru.x;
+ /* know this will be dot at start */
+ for (;;)
+  {
+   /* move one past dot */ 
+   __xndi++;
+   ndp = __exprtab[__xndi];
+   
+   /* only use of dot in expr is for xmr - must be followed by ID */
+   if (ndp->optyp != ID) 
+    {
+     __pv_ferr(1136,
+      "hierarchical reference '.' separator not followed by identifier: %s read",
+      to_xndnam(__xs, __xndi));
+     return(NULL);
+    }
+   idndp = alloc_xtnd(__xndi);
+   xidp = __expr_idtab[__xndi];
+   /* DBG remove --- */
+   if (xidp == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   /* move past identifier to dot separator or [ select - any other end */
+   __xndi++;
+   ndp = __exprtab[__xndi];
+   /* assume not a end of xmr select */ 
+   is_sel = FALSE;
+   /* access possible select - if not select add ID */ 
+   if (ndp->optyp == LSB)
+    {
+     /* cmp ndp copied to malloced storage */
+     /* in select non xmr expressions added to sym table since */
+     /* they exist in reference context */
+     if ((cmp_ndp = parse_select(idndp)) == NULL) return(NULL);
+     /* current xndi now one past end of select */ 
+     cmp_ndp->lu.x->ru.qnchp = __pv_stralloc(xidp->idnam);
+     cmp_ndp->lu.x->optyp = XMRID;
+     /* move to next which must be dot after ending ] */
+     ndp = __exprtab[__xndi];
+     if (!__allow_scope_var) is_sel = TRUE;
+     /* inst. part select inside xmrs illegal */
+     if (cmp_ndp->optyp == PARTSEL && ndp->optyp == DOT)
+      {
+       __pv_ferr(682,
+        "hierarchical reference part select of array of instances illegal");
+       return(NULL);
+      }
+    } 
+   /* know seen ID not followed by . - done */ 
+   else 
+    {
+     /* simple ID component (maybe at end) */ 
+     cmp_ndp = idndp;
+     cmp_ndp->ru.qnchp = __pv_stralloc(xidp->idnam);
+     cmp_ndp->optyp = XMRID;
+    }
+
+   if (ndp->optyp != DOT)
+    {
+     /* end of xmr - not followed by dot - must be end of expr */ 
+     if (!is_sel)
+      {
+       /* end is simple ID but must not be added to symbol table */
+       ndp2 = __alloc_newxnd();
+       ndp2->optyp = XMRCOM;
+       ndp2->lu.x = cmp_ndp;
+       ndp2->ru.x = NULL;
+       last_cmp->ru.x = ndp2; 
+      }
+     else
+      {
+       /* need to add comp ID to end as ID not select because select of xmr */
+       ndp2 = __alloc_newxnd();
+       ndp2->optyp = XMRCOM;
+       ndp2->lu.x = cmp_ndp->lu.x;
+       ndp2->ru.x = NULL;
+       last_cmp->ru.x = ndp2;
+
+       cmp_ndp->lu.x = glbndp;
+       glbndp = cmp_ndp;
+      }
+     break;
+    }
+
+   /* if followed by '.', add to tail of xmr expr and get next cmp */
+   ndp2 = __alloc_newxnd();
+   ndp2->optyp = XMRCOM;
+   /* know cmp ndp copied to malloced storage */ 
+   ndp2->lu.x = cmp_ndp;
+   ndp2->ru.x = NULL;
+   last_cmp->ru.x = ndp2; 
+   last_cmp = ndp2;
+  } 
+ /* tail component is select - assume wire - i.e. not part of inst arr */ 
+ /* rare inst. allowd context fixed up later by caller if needed */
+ /* cmp ndx rotated to become top of select expr. */
+ /* first add ID part of select to end of xmr */
+ if (is_sel)
+  {
+   grp = __bld_glbref(glbndp->lu.x, cmp1_xidp->idfnam_ind,
+    cmp1_xidp->idlin_cnt);
+  }
+ else
+  {
+   /* know x ndi pointing to one past end of xmr */
+   grp = __bld_glbref(glbndp, cmp1_xidp->idfnam_ind, cmp1_xidp->idlin_cnt);
+  }
+
+ /* for interactive now can resolve global (case for ID in expr.) */
+ if (__iact_state)
+  { __resolve_glbnam(grp); __fill_grp_targu_fld(grp); }
+ return(glbndp);
+}
+
+/*
+ * IDs when allow scope var on (scope system task contexts) make globals
+ *
+ * during resolution will be converted back to wires if needed
+ * for these special contexts since need scope ref. even if net with
+ * same name instance takes precedence (conflict can be labeled block
+ * local variable versus task name)
+ */
+static struct expr_t *bld_1cmp_global(struct expr_t *ndp,
+ struct expridtab_t *xidp)
+{
+ struct expr_t *glbndp, *cmp_ndp;
+ struct gref_t *grp;
+
+ /* build the one component */ 
+ cmp_ndp = ndp;
+ if (ndp->optyp == ID)
+  {
+   cmp_ndp->ru.qnchp = __pv_stralloc(xidp->idnam);
+   cmp_ndp->optyp = XMRID;
+  }
+ else
+  {
+   /* build the one component as select form */ 
+   cmp_ndp = ndp;
+   cmp_ndp->lu.x->optyp = XMRID;
+   cmp_ndp->lu.x->ru.qnchp = __pv_stralloc(xidp->idnam);
+  }
+
+ /* build the top level global */
+ glbndp = __alloc_newxnd();
+ glbndp->optyp = GLBREF;
+ glbndp->ru.x = __alloc_newxnd();
+ glbndp->ru.x->optyp = XMRCOM;
+ glbndp->ru.x->lu.x = cmp_ndp;
+
+ grp = __bld_glbref(glbndp, xidp->idfnam_ind, xidp->idlin_cnt);
+
+ /* for interactive now can resolve global (case for ID in expr.) */
+ if (__iact_state)
+  {
+   /* if really local since dumpvars illegal, caller emits error */
+   __resolve_glbnam(grp);
+   if (!grp->gr_gone && !grp->gr_err) __fill_grp_targu_fld(grp);
+  }
+ return(glbndp);
+}
+
+/*
+ * build a global reference entry in work table and convert glb ref ndp
+ *
+ * later work table is copied into right size allocated mod table
+ *
+ * at this build point, only link if from expression
+ * caller must set line and file location
+ */
+extern struct gref_t *__bld_glbref(struct expr_t *glbndp, int32 gfnam_ind,
+ int32 glin_cnt)
+{
+ struct gref_t *grp;
+ struct expr_t *glbpth_ndp;
+ char *gnam;
+
+ /* convert global expr to name */
+ /* for inst/gate arrays later will free and regenerate with const indices */
+ /* notice gnam malloced because xmr expr. can be long here */
+ /* and malloced to exact size of string (plus room for ending \0) */
+ gnam = alloc_glbndp_tostr(glbndp);
+
+ if ((++__grwrknum) >= __grwrktabsiz) grow_grtab();   
+ grp = &(__grwrktab[__grwrknum - 1]);
+
+ /* SJM 03/19/00 - gnam malloced above, now linked onto grp - must not free */
+ init_gref(grp, gnam);
+ grp->grfnam_ind = gfnam_ind;
+ grp->grflin_cnt = glin_cnt;
+
+ /* first save global as path expr. then convert to gref */
+ /* must use glbref because that expr. is linked correctly in source stmts */
+ glbpth_ndp = glbndp->ru.x; 
+ grp->gxndp = glbndp;
+ grp->gxndp->ru.grp = grp;
+
+ /* link global reference as XMR expr. off of gref */ 
+ grp->glbref = __alloc_newxnd();
+ grp->glbref->optyp = GLBPTH;
+ grp->glbref->ru.x = glbpth_ndp;
+
+ /* lu.x gets filled later with destination symbol (of net usually) */
+ /* DBG remove --- */
+ if (grp->gxndp->lu.x != NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* accessed through symbol field to gref */
+ if (__allow_scope_var) grp->gr_inst_ok = TRUE;
+ if (__iact_state)
+  {
+   /* for interact global, current scope determines */
+   if (__scope_tskp != NULL) grp->grsytp = __scope_tskp->tsksymtab;
+   else grp->grsytp = __scope_ptr->itip->imsym->el.emdp->msymtab;
+   grp->gin_mdp = __scope_ptr->itip->imsym->el.emdp;
+   /* for interactive will be resolved when expression parsed */ 
+  }
+ else
+  {
+   /* this is the symbol table gref appears in */
+   grp->grsytp = __venviron[__top_sti];
+   grp->gin_mdp = __inst_mod;
+  }
+ return(grp);
+}
+
+/*
+ * grow global gref work table
+ */
+static void grow_grtab(void)
+{
+ int32 old_grtsiz, osize, nsize;
+
+ old_grtsiz = __grwrktabsiz;
+ osize = old_grtsiz*sizeof(struct gref_t);
+ __grwrktabsiz = (3*__grwrktabsiz)/2; 
+ nsize = __grwrktabsiz*sizeof(struct gref_t);
+ __grwrktab = (struct gref_t *) __my_realloc((char *) __grwrktab, osize,
+  nsize);
+}
+
+/*
+ * generate a name for a global refence
+ *
+ * uses msg expr to string mechanism for instance array selects
+ * does not assume select is constant expression
+ *
+ * LOOKATME - assume xmr component name ID[<expr>] is name and
+ * therefore expression plus ID must be less the ID max length
+ */
+static char *alloc_glbndp_tostr(struct expr_t *glbndp)
+{ 
+ register struct expr_t *gcmp_ndp, *ndp;
+ int32 slen, glen, gstrsiz;
+ char *chp, *gnam, s1[IDLEN];
+
+ /* DBG remove --- */
+ if (glbndp->optyp != GLBREF) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ /* this is starting size only - can grow */
+ gstrsiz = IDLEN;
+ gnam = __my_malloc(gstrsiz);
+ /* must move right down tree one to get first component */
+ for (gcmp_ndp = glbndp->ru.x, glen = 0;;) 
+  {
+   ndp = gcmp_ndp->lu.x;
+   if (ndp->optyp == XMRID) chp = ndp->ru.qnchp;
+   else if (ndp->optyp == LSB || ndp->optyp == PARTSEL)
+    {
+     /* build the <id>[<expr>] expression as string */
+     /* works because XMRID nodes know to dmp expr */
+     chp = __msgexpr_tostr(s1, ndp);
+    }
+   else { __arg_terr(__FILE__, __LINE__); return(NULL); }
+
+   /* DBG LINT remove -- */
+   if (chp == NULL) __misc_terr(__FILE__, __LINE__);
+   /* -- */
+
+   slen = strlen(chp); 
+   /* add room for '.' separator */
+   if (glen != 0) slen++;
+   /* need room for one final \0 to end string */
+   if (glen + slen + 1 >= gstrsiz) 
+    {
+     gnam = __my_realloc(gnam, gstrsiz, gstrsiz + IDLEN);
+     gstrsiz += IDLEN;
+    }
+   if (glen == 0) strcpy(gnam, chp);
+   else { gnam[glen] = '.'; strcpy(&(gnam[glen + 1]), chp); } 
+   glen += slen;
+
+   if ((gcmp_ndp = gcmp_ndp->ru.x) == NULL) break;
+   /* DBG remove --- */
+   if (gcmp_ndp->optyp != XMRCOM) __arg_terr(__FILE__, __LINE__);
+   /* --- */   
+  }
+ gnam[glen] = '\0';
+ /* realloc to exact string size */
+ if (glen + 1 != gstrsiz)
+  {
+   gnam = __my_realloc(gnam, gstrsiz, glen + 1);
+  }
+ return(gnam);
+}
+
+/*
+ * convert glb ref expression into string
+ *
+ * when first read now since do not know index constant expression values  
+ * is printed name - fixed later to use number indices
+ */
+
+/*
+ * allocate a input phase global ref. record
+ *
+ * BEWARE - gnam must be malloced not fixed string
+ */
+static void init_gref(struct gref_t *grp, char *gnam)
+{
+ grp->gnam = gnam;
+ grp->gr_err = FALSE;
+ /* assume in decl. code */
+ grp->upwards_rel = FALSE;
+ grp->is_upreltsk = FALSE;
+ grp->is_rooted = FALSE;
+ grp->path_has_isel = FALSE;
+ grp->pathisel_done = FALSE;
+ grp->gr_inst_ok = FALSE;
+ grp->gr_defparam = FALSE; 
+ grp->gr_gone = FALSE;
+
+ grp->gxndp = NULL;
+ grp->glbref = NULL;
+ grp->grsytp = NULL;
+ grp->targmdp = NULL;
+ grp->targtskp = NULL;
+ grp->grfnam_ind = 0;
+ grp->grflin_cnt = 0;
+ grp->grcmps = NULL;
+ grp->grxcmps = NULL;
+ grp->last_gri = -1;
+ grp->targu.targitp = NULL;
+ grp->targsyp = NULL;
+ grp->spltgrp = NULL;
+}
+
+/*
+ * parse a function call
+ * called when ( seen immediately after
+ * know __xndi points to ( and moves one past ending )
+ * ,, form legal for system functions but not user - caught elsewhere
+ */
+static struct expr_t *parse_fcall(struct expr_t *fcall_ndp,
+ struct expridtab_t *xidp, int32 is_glb)
+{
+ int32 is_sysfunc;
+ struct expr_t *ndp, *fchdrx, *argndp, *last_ndp, *lop;
+
+ is_sysfunc = FALSE;
+ /* for non global function call, check symbol type and add if needed */ 
+ if (!is_glb)
+  {
+   /* only fails if interactive and unable to find - stmt parser handles */
+   /* error skipping */
+   if (!chk_decl_func(&is_sysfunc, fcall_ndp, xidp)) return(NULL);
+  }
+ else
+  {
+   /* because can not tell if select of last component is from wire */
+   /* error if global is select - no other checking possible here */
+   if (fcall_ndp->optyp != GLBREF)
+    {
+     __pv_ferr(1137,
+      "hierarchical function call name %s illegal select",
+      __msgexpr_tostr(__xs, fcall_ndp));
+     return(NULL);
+    }
+  }
+
+ fchdrx = alloc_xtnd(__xndi);
+ fchdrx->optyp = FCALL;
+ fchdrx->lu.x = fcall_ndp;
+ __xndi++;
+ ndp = __exprtab[__xndi];
+ if (ndp->optyp == RPAR && !is_sysfunc)
+  {
+   __pv_ferr(1120,
+   "Verilog user defined function call requires at least one argument - () illegal");
+   return(NULL);
+  }
+ /* now checking moved 1 past 1st token of 1st expr. */
+ /* expr. structure identical to concatenate , present even for 1 arg. */
+ /* can trace through br x rights until NULL */
+ /* task port list for functs has extra 1st ret. argument but not expr. */
+ for (last_ndp = fchdrx;;)
+  {
+   ndp = __exprtab[__xndi];
+   /* case 1: empty expr. only allowed for built-in or PLI sysfuncs */
+   if (ndp->optyp == COMMA || ndp->optyp == RPAR)
+    {
+     if (!is_sysfunc)
+      {
+       __pv_ferr(1121,
+        "user function %s call empty ',,' argument form illegal",
+        __to_idnam(fcall_ndp));
+       argndp = __alloc_newxnd();
+       /* user function error, make 1 bit x */
+       __set_numval(argndp, 1L, 1L, 1);
+      }
+     else
+      { 
+       /* must allocate new xnode because need both ,'s of ,, */
+       argndp = __alloc_newxnd();
+       argndp->optyp = OPEMPTY;
+       argndp->folded = TRUE;
+      }
+    }
+   else
+    {
+     /* case 2: actual expr */
+     /* case 2a: PLI system function - xmr arguments legal for any arg */ 
+     if (is_sysfunc)
+      {
+       struct sy_t *syp;
+       struct sysfunc_t *sfbp;
+
+       syp = fcall_ndp->lu.sy;
+       sfbp = syp->el.esyftbp;
+
+       /* XMR's (scope args) legal for built-in system functions */
+       /* but can never be function scope since functions always called */
+       if (sfbp->syfnum >= BASE_VERIUSERTFS)
+        {
+         if (sfbp->syfnum > __last_systf) __misc_terr(__FILE__, __LINE__);
+
+         /* PLI user defined system function - must allow */
+         __allow_scope_var = TRUE;
+        }
+       /* turning on allow scope global - turns on conversion in here */
+       if ((argndp = parse_qcexpr()) == NULL)
+        {
+         __allow_scope_var = FALSE;
+         return(NULL);
+        }
+       /* must turn off allowing scope for both paths thru ifs */
+       __allow_scope_var = FALSE;
+      }
+     else
+      {
+       /* case 2b: use defined (non sysf or PLI sysf)  function */
+       /* SJM 07/26/99 - was return FALSE but same NULL */
+       if ((argndp = parse_qcexpr()) == NULL) return(NULL);
+
+        /* DBG remove ---
+        if (__debug_flg)
+         __dbg_msg("ARG FCALL: %s\n", __msgexpr_tostr(__xs, argndp));
+        --- */
+      } 
+    }
+
+   ndp = __exprtab[__xndi];
+   if (ndp->optyp != RPAR && ndp->optyp != COMMA)
+    {
+     if (__pv_err_cnt <= __saverr_cnt)
+      __pv_ferr(1122,
+       "function call argument , or ) separator expected - %s read",
+       __to_opname(ndp->optyp));
+     return(NULL);
+    }
+   lop = __alloc_newxnd();
+   lop->optyp = FCCOM;
+   lop->ru.x = NULL;
+   lop->lu.x = argndp;
+   last_ndp->ru.x = lop;
+   last_ndp = lop;
+   __xndi++;
+   if (ndp->optyp == RPAR) break;
+  }
+ /* DBG remove ---
+ if (__debug_flg)
+  __dbg_msg("FCALL: %s\n", __msgexpr_tostr(__xs, fchdrx));
+ --- */
+ return(fchdrx);
+}
+
+/*
+ * check and declare a non xmr function call expression
+ *
+ * know ID and following '(' read - must find or maybe add func symbol
+ * xidp ok here since only declaring no movement in symbol table
+ */
+static int32 chk_decl_func(int32 *is_sysfunc, struct expr_t *idndp,
+ struct expridtab_t *xidp)
+{
+ struct sy_t *syp;
+ char s1[RECLEN];
+
+ *is_sysfunc = FALSE;
+ /* if starts with '$' must be system function */
+ if (xidp->idnam[0] == '$')
+  {
+   if ((syp = find_systf_sym(xidp)) == NULL) return(FALSE);
+   idndp->lu.sy = syp;
+   *is_sysfunc = TRUE;
+   return(TRUE);
+  }
+ /* SJM 02/01/05 - change to use tf undef work symtab - for uprel 1 cmp glb */
+ /* look up to see if previously declared as function or used as func */
+ if ((syp = __get_sym(xidp->idnam, __venviron[0])) == NULL)
+  {
+   /* for interactive must already be declared or error */
+   if (__iact_state)
+    {
+     /* interactive statement - all variables must be declared */
+     /* for $dumpvars will avoid this code and jump to assume glb */
+     __pv_err_cnt++;
+     __ia_err(1436, "function %s not declared", xidp->idnam);
+     return(FALSE);
+    }
+   /* SJM 02/01/05 - must assume 1 comp XMR - if declared later will be */
+   /* changed back in resolv local path routine */
+   cnvt_forw_tfcall_1cmpglb(idndp, xidp->idnam, xidp->idfnam_ind,
+    xidp->idlin_cnt);
+   return(TRUE);
+  }
+ /* if already in symbol table as wire error - used as wire */
+ idndp->lu.sy = syp;
+
+ /* if declared (or just seen) but not as fcall error */
+ if (syp->sytyp != SYM_F)
+  {
+   if (syp->sydecl)
+    {
+     __pv_ferr(1123,
+      "%s called as function but symbol declared with type %s",
+      __to_idnam(idndp), __to_sytyp(s1, syp->sytyp));
+    }
+   else
+    {
+     __pv_ferr(1123,
+      "%s called as function but symbol previously used with type %s",
+      __to_idnam(idndp), __to_sytyp(s1, syp->sytyp));
+    }
+   /* return T since can continue parsing with wrong type symbol */ 
+  }
+ return(TRUE);
+}
+
+/*
+ * routine to build func call 1 comp global for forward refs
+ *
+ * special case because must convert top node to xmr and make left
+ * offspring newly allocated with same contents
+ *
+ * needed because f([args]) may be upward relative xmr to f in above
+ * module - can't tell so any function call use before declares must
+ * be assumed to be XMRs - will get changed back if decl later in mod
+ */
+static void cnvt_forw_tfcall_1cmpglb(struct expr_t *ndp, char *tfnam, 
+ int32 fnam_ind, int32 lin_cnt)
+{
+ struct expr_t *cmp_ndp, sav_xnod;
+ struct gref_t *grp;
+
+ /* DBG remove -- */
+ if (ndp->optyp != ID) __misc_terr(__FILE__, __LINE__);
+ /* -- */
+
+ sav_xnod = *ndp;
+ ndp->optyp = GLBREF;
+ ndp->ru.x = __alloc_newxnd();
+ ndp->ru.x->optyp = XMRCOM;
+ cmp_ndp = __alloc_newxnd();
+ *cmp_ndp = sav_xnod;
+ ndp->ru.x->lu.x = cmp_ndp;
+ ndp->ru.x->ru.x = NULL;
+
+ cmp_ndp->ru.qnchp = __pv_stralloc(tfnam);
+ cmp_ndp->optyp = XMRID;
+
+ grp = __bld_glbref(ndp, fnam_ind, lin_cnt);
+}
+
+/*
+ * convert event expression table to expression tree
+ */
+extern void __bld_evxtree(void)
+{
+ struct expr_t *ndp;
+
+ /* add end of expression fence */
+ ndp = __alloc_exprnd();
+ ndp->optyp = UNDEF;
+ __xndi = 0;
+ if ((__root_ndp = parse_evexpr()) == NULL || __xndi != __last_xtk)
+  {
+   if (__pv_err_cnt <= __saverr_cnt)
+    __pv_ferr(1124, "event expression error at token [%s]",
+     to_xndnam(__xs, __xndi));
+   __root_ndp = __alloc_newxnd();
+   __set_numval(__root_ndp, 1L, 1L, 1);
+  }
+ /* if (__debug_flg) __dbg_msg(__msgexpr_tostr(__xs, __root_ndp)); */
+}
+
+/*
+ * parse a specialized event expression
+ */
+static struct expr_t *parse_evexpr(void)
+{
+ struct expr_t *ndp, *ndp2, *ndp3, *ndp4, *rhsndp, *leftopndp;
+
+ /* SJM 08/22/00 - need to separate of possible leading pos/neg edge */
+ /* because they apply to entire rest of expr to end or ev or */
+ ndp = __exprtab[__xndi];
+ if (ndp->optyp == OPPOSEDGE || ndp->optyp == OPNEGEDGE)
+  {
+   ndp3 = alloc_xtnd(__xndi);
+   __xndi++;
+  }
+ else ndp3 = NULL;
+
+ /* routine leaves __xndi at next place to look */
+ if ((leftopndp = parse_qcexpr()) == NULL) return(NULL);
+ if (ndp3 != NULL) { ndp3->lu.x = leftopndp; leftopndp = ndp3; }
+
+ ndp = __exprtab[__xndi];
+ for (;;)
+  {
+   if (ndp->optyp == OPEVOR || ndp->optyp == OPEVCOMMAOR)
+    {
+     ndp2 = alloc_xtnd(__xndi);
+     __xndi++;
+
+     /* SJM 08/22/00 - need to separate of possible leading pos/neg edge */
+     /* because they apply to entire rest of expr to end or ev or */
+     ndp4 = __exprtab[__xndi]; 
+     if (ndp4->optyp == OPPOSEDGE || ndp4->optyp == OPNEGEDGE)
+      {
+       ndp3 = alloc_xtnd(__xndi);
+      __xndi++;
+      }
+     else ndp3 = NULL;
+
+     if ((rhsndp = parse_qcexpr()) == NULL) break;
+     if (ndp3 != NULL) { ndp3->lu.x = rhsndp; rhsndp = ndp3; }
+
+     /* this makes sure optyp right */
+     ndp2->lu.x = leftopndp;
+     ndp2->ru.x = rhsndp;
+     leftopndp = ndp2;
+     ndp = __exprtab[__xndi];
+    }
+   else break;
+  }
+ return(leftopndp);
+}
+
+/*
+ * LOW LEVEL EXPRESSION NODE ROUTINES
+ */
+
+/*
+ * convert a symbol into a expression 
+ *
+ * easy because all the normal work of parse term for ID is  
+ * declaring symbol
+ */
+extern struct expr_t *__gen_wireid_expr(struct sy_t *syp)
+{
+ struct expr_t *ndp;
+
+ ndp = __alloc_newxnd();
+ ndp->lu.sy = syp;
+ ndp->optyp = ID;
+ return(ndp);
+} 
+
+/*
+ * allocate an expression node in fixed current expr. array
+ *
+ * this sets node type to be operator
+ * if used as number must have a/b val allocated
+ * when allocated for expr. allocated a/b values used
+ */
+extern struct expr_t *__alloc_exprnd(void)
+{
+ struct expr_t *ndp;
+
+ /* SJM 11/22/01 - can't use fixed operator precedence xpr tab */
+ /* need malloced for very large bus concatenates */
+ if (++__last_xtk >= __exprtabsiz - 1) grow_exprtab();
+ if ((ndp = __exprtab[__last_xtk]) == NULL)
+  {
+   ndp = my_xndalloc();
+   __exprtab[__last_xtk] = ndp;
+  }
+ __init_xnd(ndp);
+ return(ndp);
+}
+
+/*
+ *
+ * grow exprtab used during operator precedence expr tab * parsing
+ *
+ * can realloc because contains ptr's to malloced expr nodes where
+ * node but not table is linked together to form run time expr
+ *
+ * but notice expr id table must increased to same size to avoid
+ * overflow check
+ * 
+ * SJM 10/22/01
+ */
+static void grow_exprtab(void)
+{
+ register int32 i;
+ int32 old_xtabsiz, osize, nsize;
+
+ old_xtabsiz = __exprtabsiz;
+ osize = old_xtabsiz*sizeof(struct expr_t *);
+ __exprtabsiz = (3*__exprtabsiz)/2; 
+ nsize = __exprtabsiz*sizeof(struct expr_t *);
+ __exprtab = (struct expr_t **) __my_realloc((char *) __exprtab,
+  osize, nsize);
+ for (i = old_xtabsiz - 1; i < __exprtabsiz; i++) __exprtab[i] = NULL;
+
+ /* also must grow expr id table */
+ osize = old_xtabsiz*sizeof(struct expridtab_t *);
+ nsize = __exprtabsiz*sizeof(struct expridtab_t *);
+ __expr_idtab = (struct expridtab_t **)
+  __my_realloc((char *) __expr_idtab, osize, nsize);
+ for (i = old_xtabsiz - 1; i < __exprtabsiz; i++) __expr_idtab[i] = NULL;
+}
+
+/*
+ * allocate a expr ID table entry
+ */
+extern struct expridtab_t *__alloc_expridnd(char *idnam)
+{
+ int32 slen;
+ struct expridtab_t *xidp;
+
+ if ((xidp = __expr_idtab[__last_xtk]) == NULL)
+  { 
+   xidp = (struct expridtab_t *) __my_malloc(sizeof(struct expridtab_t));
+   __expr_idtab[__last_xtk] = xidp;  
+   xidp->idnam = NULL;
+   xidp->idfldwid = 0;
+  }
+ slen = strlen(idnam); 
+ if (slen + 1 > xidp->idfldwid) 
+  {
+   /* guess 2x so prevent increase by one byte allocs */
+   xidp->idnam = __my_malloc(2*slen + 1);
+   xidp->idfldwid = 2*slen + 1;
+  }
+ strcpy(xidp->idnam, idnam);
+ xidp->idlin_cnt = __lin_cnt;
+ xidp->idfnam_ind = __cur_fnam_ind;
+ return(xidp);
+}
+
+/*
+ * allocate an expr node 
+ */
+static struct expr_t *my_xndalloc(void)
+{
+ struct expr_t *ndp;
+
+ ndp = (struct expr_t *) __my_malloc(sizeof(struct expr_t));
+ ndp->optyp = UNDEF;
+ if (__inst_mod != NULL) (__inst_mod->mexprnum)++;
+ return(ndp);
+}
+
+/*
+ * allocate a copy of __exprtab node in malloced storage
+ * this uses the allocated values in the __exprtab node
+ *
+ * numeric values never changed because __exprtab node just points to
+ * atokptr and btokptr and those values moved to malloced node
+ */
+static struct expr_t *alloc_xtnd(int32 ndi)
+{
+ struct expr_t *ndp, *ndp2;
+
+ /* xtnd out of range */
+ if (ndi < 0 || ndi > __last_xtk) __misc_terr(__FILE__, __LINE__);
+ ndp = my_xndalloc();
+ ndp2 = __exprtab[ndi];
+ *ndp = *ndp2;
+ return(ndp);
+}
+
+/*
+ * initialize a new node - assume expression node for now
+ */
+extern void __init_xnd(struct expr_t *ndp)
+{
+ ndp->optyp = UNDEF;
+ ndp->has_sign = FALSE;
+ ndp->rel_ndssign = FALSE;
+ ndp->is_string = FALSE;
+ /* unless simple decimal, must be sized */
+ ndp->unsiznum = FALSE;
+ ndp->ibase = BHEX;
+ ndp->sizdflt = FALSE;
+ ndp->is_real = FALSE;
+ ndp->cnvt_to_real = FALSE;
+ ndp->unsgn_widen = FALSE;
+ ndp->consubxpr = FALSE;
+ ndp->consub_is = FALSE;
+ ndp->folded = FALSE;
+ ndp->getpatlhs = FALSE;
+ ndp->ind_noth0 = FALSE;   /* assume h:0 form */
+ ndp->x_multfi = FALSE;
+ ndp->tf_isrw = FALSE;
+ ndp->x_islhs = FALSE;
+ ndp->locqualnam = FALSE;
+ ndp->lhsx_ndel = FALSE;
+ ndp->x_stren = FALSE;
+ ndp->unc_pull = NO_UNCPULL; 
+ ndp->szu.xclen = 0;
+ ndp->lu.x = ndp->ru.x = NULL;
+}
+
+/*
+ * allocate and initialize new expression node (may be table)
+ * this initializes a node so if copied to number will have value alloced
+ */
+extern struct expr_t *__alloc_newxnd(void)
+{
+ struct expr_t *ndp;
+
+ ndp = my_xndalloc();
+ __init_xnd(ndp);
+ return(ndp);
+}
+
+/*
+ * run time (during sim or xform) allocate new xnode
+ * does not get copied to mod's expr table
+ */
+extern struct expr_t *__sim_alloc_newxnd(void)
+{
+ struct expr_t *ndp;
+
+ ndp = (struct expr_t *) __my_malloc(sizeof(struct expr_t));
+ ndp->optyp = UNDEF;
+ __init_xnd(ndp);
+ return(ndp);
+}
+
+/*
+ * set an collection routine exprtab entry to x
+ * this must be called for empty expr. tab - all fields reclaimed
+ */
+extern void __set_xtab_errval(void)
+{ 
+ __last_xtk = 0;
+ __init_xnd(__exprtab[0]);
+ __set_numval(__exprtab[0], 1L, 1L, 1);
+}
+
+/*
+ * set an collection routine exprtab entry to 0 - for specify
+ * this must be called for empty expr. tab - all fields reclaimed
+ */
+extern void __set_0tab_errval(void)
+{ 
+ __last_xtk = 0;
+ __set_numval(__exprtab[0], 0L, 0L, 1);
+}
+
+/*
+ * free an expression tree
+ * notice cannot free symbols or wires pointed to by these nodes
+ * ndp now points to garbage - caller must unlink
+ */
+extern void __free_xtree(struct expr_t *ndp)
+{
+ if (ndp == NULL) return;
+ /* first free underneath */
+ __free2_xtree(ndp);
+ /* then node itself */
+ __my_free((char *) ndp, sizeof(struct expr_t));
+}
+
+/*
+ * free all nodes under expression node and free number if needed
+ * notice cannot free symbols or wires pointed to by these nodes
+ * expects __inst_mod to be set if form is IS
+ * caller to reuse ndp must change fields
+ * 
+ * notice freeing here assumes that all nodes have both a and b parts
+ */
+extern void __free2_xtree(struct expr_t *ndp)
+{
+ switch ((byte) ndp->optyp) {
+  case NUMBER: case REALNUM: case OPEMPTY:
+   ndp->ru.xvi = -1;
+   return;
+  case ISNUMBER: case ISREALNUM:
+   /* LOOKATME - unable to free IS constant value parts - is this leak? */
+   ndp->ru.xvi = -1;
+   return;
+  case ID:
+   ndp->lu.sy = NULL;
+   return;
+  case GLBREF:
+   ndp->lu.sy = NULL;
+   /* globals free elsewhere - through glogal list */ 
+   ndp->ru.grp = NULL;
+   return;
+  case XMRID:
+   __my_free(ndp->ru.qnchp, strlen(ndp->ru.qnchp) + 1);
+   /* DBG remove --- */
+   ndp->ru.x = NULL;
+   /* --- */
+   return;
+  /* fall thru for GLBPTH that has no contents - just subexprs under */
+ }
+ if (ndp->lu.x != NULL) __free_xtree(ndp->lu.x);
+ if (ndp->ru.x != NULL) __free_xtree(ndp->ru.x);
+}
+
+/*
+ * build an unc. expression - may have width set to 1 for now - know later
+ * before calling must free exprtab and anything pointed to __root_ndp
+ */
+extern void __bld_unc_expr(void)
+{
+ __root_ndp = __alloc_newxnd();
+ set2_opempty(__root_ndp);
+}
+
+/*
+ * this build a 1 token empty expr that may or may not be parsed
+ * this is for 1 bit expression
+ *
+ * this does not free partially built x trees - caller must free if needed
+ */
+extern void __set_opempty(int32 ndi)
+{
+ __init_xnd(__exprtab[ndi]);
+ set2_opempty(__exprtab[ndi]);
+}
+
+/*
+ * version of set opempty that is passed allocated expr. value
+ */
+static void set2_opempty(struct expr_t *ndp)
+{
+ ndp->optyp = OPEMPTY;
+ ndp->folded = TRUE;
+ ndp->szu.xclen = 1;
+ /* if unconnected drive active, must set in node */
+ if (__unconn_drive != TOK_NONE)
+  {
+   ndp->unc_pull = (__unconn_drive == PULL0) ? UNCPULL0 : UNCPULL1;
+   ndp->x_stren = TRUE;
+   /* must force propogating strengths up and down */
+   /* but maybe no wire marked as strength */
+   __design_no_strens = FALSE;
+  }
+}
+
+/*
+ * set an already allocated leaf node (no subnodes) to a numeric value
+ * only for <= WBITS values and node must be new - know previous alloc num
+ *
+ * notice this must not change __root_ndp
+ */
+extern void __set_numval(struct expr_t *ndp, word32 av, word32 bv, int32 blen)
+{
+ ndp->optyp = NUMBER;
+ if (blen <= WBITS) 
+  {
+   ndp->ru.xvi = __alloc_shareable_cval(av, bv, blen);
+  }
+ else __case_terr(__FILE__, __LINE__);
+ ndp->szu.xclen = blen;
+ if (bv == 0) ndp->ibase = BDEC;
+}
+
+/*
+ * print an expression node for error messages
+ * must be wide enough for id
+ * this is a routine that uses wr to exprline routines so cannot be
+ * called to add to exprline - must use disp of expr. routine
+ *
+ * BEWARE - can only be called during expression reading because needs
+ *          __exprtab and __expridtab
+ */
+static char *to_xndnam(char *s, int32 xndi)
+{
+ int32 wlen;
+ word32 *ap, *bp;
+ struct expr_t *ndp;
+ struct expridtab_t *xidp;
+ char s1[2*IDLEN], s2[RECLEN];
+
+ ndp = __exprtab[xndi];
+ switch ((byte) ndp->optyp) {
+  case ID:
+   xidp = __expr_idtab[xndi];
+   if (xidp == NULL || strcmp(xidp->idnam, "") == 0)
+    { strcpy(s, "**range**"); return(s); }
+   sprintf(s1, "IDENTIFIER: %s", xidp->idnam);
+   break;
+   /* LOOKATME - can GLBREF occur here */
+  case NUMBER:
+  case ISNUMBER:
+   ap = &(__contab[ndp->ru.xvi]);
+   wlen = wlen_(ndp->szu.xclen);
+   bp = &ap[wlen];
+   sprintf(s1, "NUMBER: %s", __regab_tostr(s2, ap, bp, ndp->szu.xclen,
+    BHEX, FALSE));
+   break;
+  case REALNUM: case ISREALNUM:
+   /* LOOKATME - better to just format as double */ 
+   /* just pass a part for both here */ 
+   ap = &(__contab[ndp->ru.xvi]);
+   sprintf(s1, "REAL: %s", __regab_tostr(s2, ap, ap, ndp->szu.xclen, BDBLE,
+    FALSE));
+   break;
+  case OPEMPTY:
+   strcpy(s, "<EMPTY>");
+   return(s);
+  case UNDEF:
+   strcpy(s, "<EXPR END>");
+   return(s);
+  default:
+   strcpy(s, __to_opname(ndp->optyp)); return(s);
+ }
+ if ((int32) strlen(s1) >= RECLEN - 1) s1[RECLEN - 1] = '\0';
+ strcpy(s, s1);
+ return(s);
+}
diff --git a/src/v_src3.c b/src/v_src3.c
new file mode 100644
index 0000000..d794657
--- /dev/null
+++ b/src/v_src3.c
@@ -0,0 +1,6620 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * third source module reads tasks/functions, udps and specify section
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#if defined(__CYGWIN32__) || defined(__SVR4)
+#include <sys/stat.h>
+#endif
+
+#if defined(__CYGWIN32__) || defined(__SVR4) || defined(__hpux)
+#include <dirent.h>
+#else
+#include <sys/dir.h>
+#endif
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+/* REMOVEME - no longer supporting SunOS - maybe needed for hpux? */
+#if defined(__sparc) && !defined(__SVR4)  
+extern int32 tolower(int32);
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+/* local prototypes */
+static struct udp_t *alloc_udp(struct sy_t *);
+static int32 rd_udp_hdr(struct udp_t *);
+static int32 rd_udp_decls(void);
+static int32 rd_udp_init(struct udp_t *);
+static int32 chkcnt_uports(struct udp_t *);
+static int32 rd_udp_table(struct udp_t *);
+static void str_tolower(char *, char *);
+static int32 cvrt_udpedges(char *, char *);
+static int32 to_udp_levsym(char);
+static int32 chk_comb_udpline(char *, struct udp_t *, int32 *);
+static int32 chk_sequdpline(char *, struct udp_t *, int32 *);
+static char to_edgech(int32);
+static int32 is_edgesym(char);
+static char *to_codedge_line(char *, char *);
+static void extra_chk_edgeudp(struct udp_t *);
+static char *to_udp_prtnam(struct udp_t *, int32);
+static void dmp_udp_lines(FILE *, struct udp_t *);
+static struct spfy_t *alloc_spfy(void);
+static int32 rd_specparamdecl(void);
+static void assign_1specparam(struct net_t *, struct expr_t *, int32, int32);
+static int32 rd_delay_pth(void);
+static struct exprlst_t *rd_pthtermlst(void);
+static int32 col_pthexpr(void);
+static int32 rd_pathdelaylist(struct paramlst_t **);
+static void init_spcpth(struct spcpth_t *);
+static int32 rd_setup_or_hold_tchk(word32);
+static int32 rd_tchk_part(word32, struct tchk_t *, struct expr_t **);
+static int32 rd_setuphold_tchk(void);
+static int32 rd_recrem_tchk(void);
+static int32 rd_width_tchk(void);
+static int32 rd_period_tchk(void);
+static int32 rd_skew_recov_rem_tchk(word32);
+static int32 rd_nochg_tchk(void);
+static int32 rd_tchk_selector(int32 *, struct expr_t **, struct expr_t **);
+static int32 rd_edges(int32 *);
+static struct sy_t *rd_notifier(void);
+static struct attr_t *chk_dup_attrs(struct attr_t *);
+static void rd1_cfg_file(FILE *);
+static void rd_cfg_library(FILE *);
+static struct libel_t *rd_cfg_fspec_list(FILE *, int32);
+static void rd_cfg_cfg(FILE *);
+static int32 chk_libid(char *);
+static int32 chk_escid(char *);
+static void init_rule(struct cfgrule_t *);
+static int32 extract_design_nam(char *, char *, char *);
+static int32 bld_inst_xmr_comptab(char *);
+static void grow_bind_comps(void);
+static int32 extract_libcell_nam(char *, char *, char *);
+static int32 rd_use_clause(FILE *, char *, char *, int32 *);
+static int32 extract_use_nam(char *, char *, int32 *, char *);
+static struct cfgnamlst_t *rd_liblist(FILE *);
+
+static void init_cfglib(struct cfglib_t *);
+static void init_cfg(struct cfg_t *);
+static int32 cfg_skipto_semi(int32, FILE *);
+static int32 cfg_skipto_comma_semi(int32, FILE *);
+static int32 cfg_skipto_semi_endconfig(int32, FILE *);
+static int32 cfg_skipto_eof(int32, FILE *);
+
+static void expand_dir_pats(struct cfglib_t *, struct libel_t *, char *);
+static void expand_hier_files(struct cfglib_t *, struct libel_t *, 
+ struct xpndfile_t *);
+static void match_dir_pats(struct libel_t *, struct xpndfile_t *, char *, 
+ char *, int32, int32);
+static void movedir_match_dir_pats(struct libel_t *, struct xpndfile_t *); 
+static void find_hier(struct libel_t *, struct xpndfile_t *, char *, char *);
+static int32 match_hier_name(struct xpndfile_t *, char *);
+static int32 match_wildcard_str(char *, struct xpndfile_t *);
+static void expand_libel(struct libel_t *, char *);
+static int32 expand_single_hier(struct cfglib_t *, struct libel_t *, char *);
+static int32 has_wildcard(char *);
+static void prep_cfg_vflist(void);
+static void dump_config_info(void);
+static void dump_lib_expand(void);
+static int32 bind_cfg_design(struct cfg_t *, int32);
+static struct cfglib_t *find_cfglib(char *);
+static void free_undef_list(void);
+static void bind_cells_in1mod(struct cfg_t *, struct cfglib_t *,
+ struct mod_t *);
+static int32 try_match_rule(struct cfglib_t *, struct cell_t *,
+ struct cfgrule_t *);
+static void build_rule_error(struct cfg_t *, struct cfglib_t *, 
+struct cfgrule_t *);
+static int32 bind_liblist_rule(struct cfg_t *, struct cell_t *,
+ struct cfgrule_t *);
+static int32 bind_use_rule(struct cfg_t *, struct cfglib_t *, struct cell_t *,
+ struct cfgrule_t *);
+static struct cfg_t *fnd_cfg_by_name(char *);
+static void bind_cells_inside(struct cfg_t *, struct cell_t *,
+ struct mod_t *, struct cfglib_t *);
+static struct mod_t *find_cell_in_cfglib(char *, struct cfglib_t *);
+static int32 open_cfg_lbfil(char *);
+static void rd_cfg_srcfil(struct libel_t *);
+static int32 init_chk_cfg_sytab(struct libel_t *, char *);
+static void free_unused_cfgmods(void);
+static void partially_free_mod(struct mod_t *);
+static void add_cfg_libsyms(struct cfglib_t *);
+static void add_cfgsym(char *, struct tnode_t *);
+
+/* extern prototypes (maybe defined in this module) */
+extern char *__pv_stralloc(char *);
+extern char *__my_malloc(int32);
+extern char *__my_realloc(char *, int32 , int32);
+extern void __my_free(char *, int32);
+extern char *__prt_vtok(void);
+extern char *__prt_kywrd_vtok(void);
+extern char *__to_uvvnam(char *, word32);
+extern char *__to_tcnam(char *, word32);
+extern char *__to_sytyp(char *, word32);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern struct sy_t *__decl_sym(char *, struct symtab_t *);
+extern struct sy_t *__bld_loc_symbol(int32, struct symtab_t *, char *, char *);
+extern struct exprlst_t *__alloc_xprlst(void);
+extern struct tnode_t *__vtfind(char *, struct symtab_t *);
+extern struct symtab_t *__alloc_symtab(int32);
+extern struct expr_t *__alloc_newxnd(void);
+extern struct mod_pin_t *__alloc_modpin(void);
+extern struct paramlst_t *__alloc_pval(void);
+extern struct expr_t *__bld_rng_numxpr(word32, word32, int32);
+extern int32 __vskipto_modend(int32);
+extern void __add_sym(char *, struct tnode_t *);
+extern int32 __chk_redef_err(char *, struct sy_t *, char *, word32);
+extern void __remove_undef_mod(struct sy_t *);
+extern void __get_vtok(void);
+extern void __unget_vtok(void);
+extern void __dmp_udp(FILE *, struct udp_t *);
+extern int32 __udp_vskipto_any(int32);
+extern int32 __udp_vskipto2_any(int32, int32);
+extern int32 __udp_vskipto3_any(int32, int32, int32);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern void __wrap_puts(char *, FILE *);
+extern void __wrap_putc(int32, FILE *);
+extern void __nl_wrap_puts(char *, FILE *);
+extern int32 __fr_tcnam(char *);
+extern int32 __spec_vskipto_any(int32);
+extern int32 __spec_vskipto2_any(int32, int32);
+extern int32 __spec_vskipto3_any(int32, int32, int32);
+extern int32 __rd_opt_param_vec_rng(struct expr_t **, struct expr_t **, int32);
+extern int32 __col_paramrhsexpr(void);
+extern int32 __col_connexpr(int32);
+extern int32 __col_comsemi(int32);
+extern void __bld_xtree(int32);
+extern int32 __src_rd_chk_paramexpr(struct expr_t *, int32);
+extern void __set_numval(struct expr_t *, word32, word32, int32);
+extern struct net_t *__add_param(char *, struct expr_t *, struct expr_t *);
+extern int32 __col_parenexpr(int32);
+extern int32 __bld_expnode(void);
+extern void __set_xtab_errval(void);
+extern int32 __col_delexpr(void);
+extern int32 __vskipto3_modend(int32, int32, int32);
+extern void __init_tchk(struct tchk_t *, word32);
+extern void __set_0tab_errval(void);
+extern void __free_xtree(struct expr_t *);
+extern void __free2_xtree(struct expr_t *);
+extern void __skipover_line(void);
+extern int32 __my_getlin(register char *);
+extern int32 __pop_vifstk(void);
+extern int32 __open_sfil(void);
+extern void __do_include(void);
+extern void __do_foreign_lang(void);
+extern void __exec_vpi_langlinecbs(char *, char *, int32);
+extern int32 __notokenize_skiplines(char *);
+extern char *__bld_lineloc(char *, word32, int32);
+extern char *__match_cdir(char *, char *);
+extern int32 __exec_rdinserted_src(char *);
+extern void __push_vinfil(void);
+extern void __rd_ver_mod(void);
+extern int32 __expr_has_glb(struct expr_t *);
+extern struct xstk_t *__eval2_xpr(struct expr_t *);
+extern void __sizchgxs(struct xstk_t *, int32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern void __cnv_stk_fromreal_toreg32(struct xstk_t *);
+extern void __eval_param_rhs_tonum(struct expr_t *);
+extern int32 __cmp_xpr(struct expr_t *, struct expr_t *);
+extern FILE *__tilde_fopen(char *, char *);
+extern int32 __get_cfgtok(FILE *);
+extern int32 __vskipto_modend(int32);
+extern void __grow_infils(int32);
+extern int32 __rd_cfg(void);
+extern char *__to_cfgtoknam(char *, int32);
+extern void __my_fclose(FILE *);
+extern void __expand_lib_wildcards(void);
+extern void __process_cdir(void);
+extern int32 __rd_moddef(struct symtab_t *, int32);
+extern int32 __vskipto2_modend(int32, int32);
+extern char *__cfg_lineloc(char *s, char *, int32);
+extern char *__schop(char *, char *);
+extern void __sym_addprims(void);
+
+extern void __cv_msg(char *s, ...);
+extern void __finform(int32, char *, ...);
+extern void __pv_ferr(int32, char *, ...);
+extern void __pv_fwarn(int32, char *, ...);
+extern void __gfinform(int32, word32, int32, char *, ...);
+extern void __gfwarn(int32, word32, int32, char *, ...);
+extern void __gferr(int32, word32, int32, char *, ...);
+extern void __ia_err(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __pv_terr(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __fterr(int32, char *, ...);
+extern void __misc_terr(char *, int32);
+extern void __misc_fterr(char *, int32);
+extern void __pv_err(int32, char *, ...);
+extern void __pv_warn(int32, char *, ...);
+
+/*
+ * UDP PROCESSING ROUTINES
+ */
+
+/*
+ * process a udp definition
+ * added to end of list of udps with header __udphead
+ * name of udp has already been read
+ * notice there is a separate design wide list of udps
+ *
+ * primitive keyword read and reads endprimitive
+ */
+extern int32 __rd_udpdef(struct symtab_t *cfg_sytab)
+{
+ int32 retval, initlcnt, initsfnind;
+ struct udp_t *udpp;
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+ char *cp;
+
+ initlcnt = 0;
+ initsfnind = 0;
+ /* notice that Verilog keywords are reserved words */
+ retval = TRUE;
+ /* for now must be able to declare to continue syntax checking */
+ if (__toktyp != ID)
+  {
+   __pv_ferr(1155, "udp name expected - %s read", __prt_kywrd_vtok());
+skip_end:
+   retval = __vskipto_modend(ENDPRIMITIVE);
+   return(retval);
+  }
+ cp = __token;
+
+ if (cfg_sytab != NULL)
+  {
+   tnp = __vtfind(__token, cfg_sytab);
+   /* dups already checked for */
+   /* DBG remove -- */
+   if (!__sym_is_new) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   __add_sym(__token, tnp);
+   (cfg_sytab->numsyms)++;
+   syp = tnp->ndp;
+  }
+ else
+  {
+   tnp = __vtfind(cp, __modsyms);
+   if (__sym_is_new)
+    {
+     __add_sym(__token, tnp);
+     (__modsyms->numsyms)++;
+     syp = tnp->ndp;
+    }
+   else
+    {
+     syp = tnp->ndp;
+     /* if previously guessed as module, will just change */
+     if (!__chk_redef_err(__token, syp, "udp", SYM_UDP)) goto skip_end;
+     /* chk fail means never in module undef list */
+     __remove_undef_mod(syp);
+    }
+  } 
+ syp->sytyp = SYM_UDP;
+ udpp = alloc_udp(syp);
+ syp->el.eudpp = udpp;
+ syp->sydecl = TRUE;
+ /* need place where udp declared */
+ syp->syfnam_ind = __cur_fnam_ind;
+ syp->sylin_cnt = __lin_cnt;
+
+ /* must also allocate the new symbol table */
+ /* udps have no internal structure, sym table discarded when done */
+ udpp->usymtab = __alloc_symtab(FALSE);
+ __cur_udp = udpp;
+ /* link symbol table back to module symbol */
+ udpp->usymtab->sypofsyt = syp;
+
+ /* do not need to build type until entire module read */
+ /* any return here means skipped to endprimitive or next file level */
+ if (!rd_udp_hdr(udpp)) return(FALSE);
+ if (!rd_udp_decls()) return(FALSE);
+ if (__toktyp == INITial)
+  {
+   initlcnt = __lin_cnt;
+   initsfnind = __cur_fnam_ind;
+   if (!rd_udp_init(udpp)) return(FALSE);
+   __get_vtok();
+   if (__toktyp != TABLE)
+    {
+     __pv_ferr(1156, "udp table section missing - %s read", __prt_vtok());
+     goto skip_end;
+    }
+  }
+ /* sets type to U_LEVEL if not combinatorial - edge type detected later */
+ if (!chkcnt_uports(udpp)) retval = FALSE;
+ if ((int32) udpp->numstates >= __ualtrepipnum) udpp->u_wide = TRUE;
+ else udpp->u_wide = FALSE;
+
+ /* this reads the endprimitive */
+ if (!rd_udp_table(udpp)) return(FALSE);
+ if (udpp->utyp == U_COMB && udpp->ival != NO_VAL)
+  {
+   __gferr(1157, initsfnind, initlcnt,
+    "combinatorial udp %s cannot have initial value", syp->synam);
+   udpp->ival = NO_VAL;
+  }
+
+ __get_vtok();
+ if (__toktyp != ENDPRIMITIVE)
+  {
+   __pv_ferr(1158,
+    "udp endprimitive keyword expected - %s read", __prt_vtok());
+   goto skip_end;
+  }
+ if (!retval) return(TRUE);
+
+ /* catch common extra ; error here */
+ __get_vtok();
+ if (__toktyp == SEMI)
+  __pv_ferr(1152, "semicolon following endprimitive illegal"); 
+ else __unget_vtok();
+
+ extra_chk_edgeudp(udpp);
+
+ /* notice if error before here not added to list */ 
+ if (__udp_last == NULL) __udphead = udpp; else __udp_last->udpnxt = udpp;
+ __udp_last = udpp;
+ if (__debug_flg) __dmp_udp(stdout, udpp);
+ return(TRUE);
+}
+
+/*
+ * allocate a udp
+ */
+static struct udp_t *alloc_udp(struct sy_t *syp)
+{
+ struct udp_t *udpp;
+
+ udpp = (struct udp_t *) __my_malloc(sizeof(struct udp_t));
+ udpp->usym = syp;
+ udpp->usymtab = NULL;
+ udpp->upins = NULL;
+ udpp->utyp = U_COMB;
+ udpp->numins = 0;
+ udpp->numstates = 0;
+ udpp->u_used = FALSE;
+ udpp->u_wide = FALSE;
+ /* initial value - assume none that becomes 1'bx for level */
+ udpp->ival = NO_VAL;
+ udpp->utlines = NULL;
+ udpp->udpnxt = NULL;
+ udpp->utab = NULL;
+ udpp->uidnum = 0;
+ return(udpp);
+}
+
+/*
+ * read the udp header
+ * only simple variable names allowed in this header
+ * reads ending ;
+ * handles skipping - 
+ */
+static int32 rd_udp_hdr(struct udp_t *udpp)
+{
+ struct mod_pin_t *upp, *last_upp;
+ struct sy_t *syp;
+
+ /* empty I/O list illegal */
+ __get_vtok();
+ if (__toktyp == SEMI)
+  {
+   __pv_ferr(1162, "required udp header list of ports missing");
+   return(TRUE);
+  }
+
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(1164,
+    "udp header list of ports initial left parenthesis expected - %s read",
+    __prt_vtok());
+   if (__udp_vskipto2_any(RPAR, SEMI)) 
+    {
+     if (__toktyp == RPAR) __get_vtok();
+     /* if not semi, assume semi left out - if bad, next rout. will catch */
+     if (__toktyp != SEMI) __unget_vtok();
+     return(TRUE);
+    }
+ret_end:
+   if (__syncto_class == SYNC_FLEVEL) return(FALSE);
+   else return(TRUE);
+  }
+ __get_vtok();
+ if (__toktyp == RPAR)
+  {
+   __pv_ferr(1165, "empty udp header list of ports () form illegal");
+do_end:
+   __get_vtok();
+   if (__toktyp == SEMI) return(TRUE);
+   __pv_ferr(980,
+    "module header list of ports end semicolon expected - %s read",
+    __prt_vtok());
+   __unget_vtok();
+   return(TRUE);
+  }
+ for (last_upp = NULL;;)
+  {
+   /* this declares the symbols in the header */
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1166, "udp port variable name expected - %s read",
+      __prt_kywrd_vtok());
+do_resync:
+     if (__udp_vskipto3_any(COMMA, SEMI, RPAR)) 
+      {
+       /* port effectively not seen - error emitted already */
+       if (__toktyp == COMMA) goto nxt_port;
+       if (__toktyp == RPAR) goto do_end;
+       return(TRUE);
+      }
+     goto ret_end;
+    }
+   syp = __decl_sym(__token, __cur_udp->usymtab);
+   /* must fill in connection to port still */
+   if (__sym_is_new) syp->sytyp = SYM_N;
+   else
+    {
+     __pv_ferr(1167,
+      "udp port %s repeated in header list of ports", syp->synam);
+     goto nxt_port;
+    }
+   upp = __alloc_modpin();
+   upp->mptyp = IO_UNKN;
+   upp->mpsnam = syp->synam;
+   upp->mpref = NULL;
+   syp->el.empp = upp;
+
+   if (last_upp == NULL) udpp->upins = upp; else last_upp->mpnxt = upp;
+   last_upp = upp;
+
+nxt_port:
+   __get_vtok();
+   if (__toktyp == RPAR)
+    {
+     __get_vtok();
+     if (__toktyp == SEMI) break;
+     __pv_ferr(1168,
+      "udp header list of ports ending semicolon expected - %s read",
+      __prt_vtok());
+     goto do_end;
+    }
+   if (__toktyp != COMMA)
+    {
+     __pv_ferr(1169,
+      "udp header comma or semicolon separator expected - %s read",
+      __prt_vtok());
+     goto do_resync;
+    }
+   __get_vtok();
+  }
+ return(TRUE);
+}
+
+/*
+ * read the udp declarations
+ * must read first port type and reads following initial or table
+ * eliminates illegal vector ports by not parsing
+ */
+static int32 rd_udp_decls(void)
+{
+ struct mod_pin_t *mpp;
+ struct sy_t *syp;
+ int32 outdecl_seen, regdecl_seen;
+
+ regdecl_seen = outdecl_seen = FALSE;
+ for (;;)
+  {
+again:
+   __get_vtok();
+   if (__toktyp == INITial || __toktyp == TABLE) break;
+   switch ((byte) __toktyp) {
+    case INPUT:
+     for (;;)
+      {
+       __get_vtok();
+       if (__toktyp != ID)
+        {
+         __pv_ferr(1170, "udp input port name expected - %s read",
+          __prt_kywrd_vtok());
+sync_in:
+         if (__udp_vskipto2_any(COMMA, SEMI)) 
+          {
+           /* port effectively not seen - error emitted already */
+           if (__toktyp == COMMA) continue;
+           goto again;
+          }
+         if (__syncto_class == SYNC_FLEVEL) return(FALSE);
+         else goto again;
+        }
+       if ((syp = __get_sym(__token, __cur_udp->usymtab)) == NULL)
+        {
+not_in_port:
+          __pv_ferr(1173,
+           "udp input declaration of \"%s\" - non header input port", __token);
+         goto nxt_port;
+        }
+       if (syp->sytyp != SYM_N)
+        {
+bad_sytab:
+         /* udp symbol table inconsistent */
+         __misc_fterr(__FILE__, __LINE__);
+        }
+       mpp = syp->el.empp;
+       if (syp->sydecl || mpp->mptyp != IO_UNKN) goto not_in_port;
+       mpp->mptyp = IO_IN;
+       syp->sydecl = TRUE;
+
+nxt_port:
+       __get_vtok();
+       if (__toktyp == SEMI) break;
+       if (__toktyp == COMMA) continue;
+       __pv_ferr(1174,
+        "udp port declaration comma or semicolon separator expected - %s read",
+        __prt_vtok());
+       goto sync_in;
+      }
+     break;
+    case OUTPUT:
+     if (outdecl_seen)
+      {
+       __pv_ferr(1178, "only one udp output port declaration permitted");
+       __get_vtok();
+       goto end_out_port;
+      }
+     outdecl_seen = TRUE;
+
+      __get_vtok();
+     if (__toktyp != ID)
+      {
+       __pv_ferr(1179, "udp output port name expected - %s read",
+        __prt_kywrd_vtok());
+sync_out:
+       if (__udp_vskipto_any(SEMI)) return(TRUE); 
+       if (__syncto_class == SYNC_FLEVEL) return(FALSE);
+       else goto again;
+      }
+     if ((syp = __get_sym(__token, __cur_udp->usymtab)) == NULL)
+      {
+not_out_port:
+       __pv_ferr(1180,
+        "udp output port declaration of \"%s\" that is not in header port list",
+        __token);
+       goto end_out_port;
+      }
+     if (syp->sytyp != SYM_N) goto bad_sytab;
+     mpp = syp->el.empp;
+     /* NON_IO means already declared as reg so nothing to do */
+     if (mpp->mptyp != NON_IO)
+      {
+       if (syp->sydecl || mpp->mptyp != IO_UNKN) goto not_out_port;
+       mpp->mptyp = IO_OUT;
+       syp->sydecl = TRUE;
+      }
+end_out_port:
+     __get_vtok();
+     if (__toktyp != SEMI)
+      {
+       __pv_ferr(1181,
+        "udp output declaration not followed by semicolon - %s read",
+        __prt_vtok());
+       goto sync_out;
+      }
+     break;
+    case REG:
+     if (regdecl_seen)
+      {
+       __pv_ferr(1182, "only one udp reg declaration permitted");
+       __get_vtok();
+       goto end_reg;
+      }
+     regdecl_seen = TRUE;
+     __get_vtok();
+     if (__toktyp != ID)
+      {
+       __pv_ferr(1183,
+        "udp reg declaration output port name expected - %s read",
+        __prt_kywrd_vtok());
+sync_reg:
+       if (__udp_vskipto_any(SEMI)) return(TRUE); 
+       if (__syncto_class == SYNC_FLEVEL) return(FALSE);
+       else goto again;
+      }
+     if ((syp = __get_sym(__token, __cur_udp->usymtab)) == NULL)
+      {
+not_reg_port:
+       __pv_ferr(1184,
+        "udp reg declaration of \"%s\" that is not in header port list",
+        __token);
+       goto end_reg;
+      }
+     if (syp->sytyp != SYM_N) goto bad_sytab;
+     mpp = syp->el.empp;
+     if (mpp->mptyp == IO_OUT) mpp->mptyp = NON_IO;
+     else
+      {
+       /* if not output must be undeclared */
+       if (syp->sydecl || mpp->mptyp != IO_UNKN) goto not_reg_port;
+       mpp->mptyp = NON_IO;
+      }
+end_reg:
+     __get_vtok();
+     if (__toktyp != SEMI)
+      {
+       __pv_ferr(1187,
+        "udp output reg declaration ending semicolon expected - %s read",
+        __prt_vtok());
+       goto sync_reg;
+      }
+     break;
+    default:
+     __pv_ferr(1188,
+      "udp declaration I/O declaration keyword expected - %s read",
+      __prt_vtok());
+    return(FALSE);
+   }
+  }
+ return(TRUE);
+}
+
+/*
+ * read the one optional initial statement for the one udp output
+ * know initial read - format is intial [output term] = [1 bit const]
+ * complicated because no mechanism for conversion from 32 1 bit vals
+ */
+static int32 rd_udp_init(struct udp_t *udpp)
+{
+ int32 blen;
+
+ __get_vtok();
+ if (__toktyp != ID) goto bad_init;
+ __get_vtok();
+ if (__toktyp != EQ) goto bad_init;
+ __get_vtok();
+ if (__toktyp != NUMBER) goto bad_init;
+ __get_vtok();
+ if (__toktyp != SEMI) goto bad_init;
+ if (__itoklen > WBITS)
+  {
+   blen = __itoklen - WBITS;
+   if (!vval_is0_(&(__acwrk[1]), blen)) goto bad_val; 
+   if (!vval_is0_(&(__bcwrk[1]), blen)) goto bad_val; 
+  }
+ /* this must be a 1 bit value but wider with all zero's ok */
+ if (__acwrk[0] == 0L && __bcwrk[0] == 0L) udpp->ival = 0;
+ else if (__acwrk[0] == 1L && __bcwrk[0] == 0L)
+  udpp->ival = 1;
+ else if (__acwrk[0] == 0L && __bcwrk[0] == 1L)
+  {
+   __pv_fwarn(576, "udp initial value 1'bz illegal - changed to 1'bx");
+   udpp->ival = 3;
+  }
+ else if (__acwrk[0] == 1L && __bcwrk[0] == 1L) udpp->ival = 3;
+ else
+  {
+bad_val:
+   __pv_ferr(1191, "udp initial value must be one of: 0, 1, 1'bx - %s read",
+    __prt_vtok());
+   udpp->ival = NO_VAL;
+  }
+ return(TRUE);
+
+bad_init:
+ __pv_ferr(1192, "udp initial statement syntax error");
+ if (__udp_vskipto_any(SEMI)) return(TRUE);
+ if (__syncto_class == SYNC_FLEVEL) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * check and count number of ports and set to default sequential if needed
+ * number of ports in number of inputs (+ 1 if level or edge)
+ * udp type number udp inputs and type set here
+ * error if header port not declared
+ * return FALSE on error
+ */
+static int32 chkcnt_uports(struct udp_t *udpp)
+{
+ register struct mod_pin_t *mpp;
+ int32 retval;
+ int32 unumins, unumstates;
+
+ mpp = udpp->upins;
+ retval = TRUE;
+ if (mpp->mptyp == IO_IN)
+  {
+   __gferr(1193, udpp->usym->syfnam_ind, udpp->usym->sylin_cnt,
+    "first udp header port %s not the output", mpp->mpsnam);
+   retval = FALSE;
+  }
+ unumins = unumstates = 0;
+ if (mpp->mptyp == NON_IO) { udpp->utyp = U_LEVEL; unumstates++; }
+
+ mpp = mpp->mpnxt;
+ for (; mpp != NULL; mpp = mpp->mpnxt)
+  {
+   if (mpp->mptyp != IO_IN)
+    {
+     __gferr(1194, udpp->usym->syfnam_ind, udpp->usym->sylin_cnt,
+      "after first udp port %s must be an input", mpp->mpsnam);
+     retval = FALSE;
+    }
+   unumins++;
+  }
+ udpp->numins = unumins;
+ udpp->numstates = unumins + unumstates;
+ if (udpp->numins > MAXUPRTS)
+  {
+   __gferr(1195, udpp->usym->syfnam_ind, udpp->usym->sylin_cnt,
+    "udp definition has %d ports - maximum allowed is %d",
+    udpp->numins, MAXUPRTS);
+   retval = FALSE;
+  }
+ return(retval);
+}
+
+/*
+ * read the udp table
+ * know table keyword read and reads endtable
+ * when done udp lines are array of chars of length numins + 1 (for out)
+ * numins includes state for non combinatorial
+ *
+ * if edge, 1 allowed edge, char in line is 2nd plus uledinum index of edge
+ * and ultabsel is 1st (maybe wildcard) - need to convert back to r/f abbrev.
+ */
+static int32 rd_udp_table(struct udp_t *udpp)
+{
+ int32 ulcnt, has_wcard, ulfnam_ind;
+ struct utline_t *utlp, *last_utlp;
+ char uline[RECLEN], coduline[RECLEN], s1[RECLEN];
+
+ __letendnum_state = TRUE;
+ /* initialized for malformed ; only line - error caught later */
+ ulfnam_ind = __cur_fnam_ind;
+ ulcnt = __lin_cnt;
+
+ for (last_utlp = NULL;;)
+  {
+   __get_vtok();
+   if (__toktyp == ENDTABLE) break;
+   strcpy(uline, "");
+   for (;;)
+    {
+     if (__toktyp == SEMI) goto end_line;
+
+     /* need beginning of udp entry line no. */
+     ulfnam_ind = __cur_fnam_ind;
+     ulcnt = __lin_cnt;
+     switch ((byte) __toktyp) {
+      case LPAR: strcat(uline, "("); break;
+      case RPAR: strcat(uline, ")"); break;
+      case QUEST: strcat(uline, "?"); break;
+      case MINUS: strcat(uline, "-"); break;
+      case TIMES: strcat(uline, "*"); break;
+      case COLON: strcat(uline, ":"); break;
+      /* this requires that even non sized numbers stored in token */
+      /* works because ' not legal in udp table line */
+      case ID: strcat(uline, __token); break;
+      /* SJM 03/20/00 - must assemble from num token for numbers */
+      case NUMBER: strcat(uline, __numtoken); break;
+      default:
+       __pv_ferr(1198, "invalid udp table line symbol %s", __prt_vtok());
+       if (__udp_vskipto_any(SEMI)) continue;
+       if (__toktyp == ENDTABLE) goto done;
+       if (__syncto_class == SYNC_FLEVEL) goto bad_end;
+       __vskipto_modend(ENDPRIMITIVE);
+bad_end:
+       __letendnum_state = FALSE;
+       return(FALSE);
+     }
+     __get_vtok();
+    }
+end_line:
+   /* at this point line collected and contains only 1 char values and punct */
+   /* utyp only U_COMB if does not have reg declaration */
+   if (udpp->utyp == U_COMB)
+    {
+     __cur_utabsel = NO_VAL;
+     __cur_ueipnum = NO_VAL;
+     str_tolower(coduline, uline);
+     if (!chk_comb_udpline(coduline, udpp, &has_wcard)) goto bad_end;
+    }
+   else
+    {
+     str_tolower(s1, uline);
+     /* edge temporarily converted to 0x80 form */
+     if (!cvrt_udpedges(coduline, s1)) return(FALSE);
+     /* edge converted to 1st char __cur_utabsel plus 2nd char here in uline */
+     __cur_utabsel = NO_VAL;
+     if (!chk_sequdpline(coduline, udpp, &has_wcard)) continue;
+    }
+   utlp = (struct utline_t *) __my_malloc(sizeof(struct utline_t));
+   utlp->tline = __pv_stralloc(coduline);
+   utlp->ullen = (word32) strlen(coduline);
+   utlp->ulhas_wcard = (has_wcard) ? TRUE : FALSE;
+   utlp->uledinum = __cur_ueipnum;
+   utlp->utabsel = __cur_utabsel;
+   utlp->utlfnam_ind = ulfnam_ind;
+   utlp->utlin_cnt = ulcnt;
+   utlp->utlnxt = NULL;
+   if (last_utlp == NULL) udpp->utlines = utlp; else last_utlp->utlnxt = utlp;
+   last_utlp = utlp;
+  }
+done:
+ __letendnum_state = FALSE;
+ return(TRUE);
+}
+
+static void str_tolower(char *to, char *from)
+{
+ while (*from)
+  {
+   if (isupper(*from)) *to++ = (char) tolower(*from); else *to++ = *from;
+   from++;
+  }
+ *to = '\0';
+}
+
+/*
+ * convert (..) form edges to one coded char - real edge processing
+ * in check seqential udp line routine
+ * edge has high bit on and then bits 5-3 is e1 and 2-0 is e2
+ *
+ * know all legal upper case edges converted to lower case before called
+ * first step in udp table line checking - edge abbreviation not seen here
+ */
+static int32 cvrt_udpedges(char *culine, char *uline)
+{
+ register char *culp, *ulp;
+ char *chp, ech1, ech2;
+ int32 ie1, ie2, no_err;
+ char s1[RECLEN];
+
+ no_err = FALSE;
+ for (no_err = TRUE, ulp = uline, culp = culine;;)
+  {
+   switch (*ulp) {
+    case '\0': *culp = '\0'; goto done;
+    case '(':
+     ech1 = *(++ulp);
+     if ((ie1 = to_udp_levsym(ech1)) == -1)
+      {
+       __pv_ferr(1202,
+        "udp table line edge first symbol '%c' not a level symbol", ech1);
+edge_err:
+       no_err = FALSE;
+       /* making error into (? ?) edge */
+       *culp++ = (char) (0x80 + (UV_Q << 3) + UV_Q);
+       if ((chp = strchr(ulp, ')')) == NULL) { *culp = '\0'; return(no_err); }
+       ulp = ++chp;
+       continue;
+      }
+     ech2 = *(++ulp);
+     if ((ie2 = to_udp_levsym(ech2)) == -1)
+      {
+       __pv_ferr(1203,
+        "udp table line edge second symbol '%c' not a level symbol", ech2);
+       goto edge_err;
+      }
+     if (*(++ulp) != ')')
+      {
+       __pv_ferr(1204,
+        "udp table line edge symbol closing ')' expected - %c read", *ulp);
+       goto edge_err;
+      }
+     /* edge has high bit on and bits 5-3 is e1 and 2-0 is e2 */
+     *culp++ = (char) (0x80 | (ie1 << 3) | ie2);
+     ulp++;
+     break;
+    default:
+     *culp++ = *ulp++;
+    }
+  }
+done:
+ if (__debug_flg)
+  __dbg_msg("&&& converted from %s to %s\n", uline, to_codedge_line(s1,
+   culine));
+ return(no_err);
+}
+
+/*
+ * return value of level symbol (-1 if not level symbol)
+ */
+static int32 to_udp_levsym(char ch)
+{
+ switch (ch) {
+  case '0': return(UV_0);
+  case '1': return(UV_1);
+  case 'x': return(UV_X);
+  case '?': return(UV_Q);
+  case 'b': return(UV_B);
+ }
+ return(-1);
+}
+
+/*
+ * check coded combinatorial udp uline
+ */
+static int32 chk_comb_udpline(char *uline, struct udp_t *udpp,
+ int32 *has_wcard)
+{
+ register char *chp;
+ int32 ins;
+ char ch;
+
+ *has_wcard = FALSE;
+ /* separate off ending :[output] */
+ if ((chp = strrchr(uline, ':')) == NULL)
+  {
+   __pv_ferr(1205,
+    "combinatorial udp line expected ':' output separator missing");
+   return(FALSE);
+  }
+ *chp++ = '\0';
+ ch = *chp++;
+ if (ch == '-')
+  {
+   __pv_ferr(1206,
+    "combinatorial udp line '-' output symbol illegal - has no state");
+   return(FALSE);
+  }
+ if (ch != '0' && ch != '1' && ch != 'x')
+  {
+   __pv_ferr(1207,
+    "combinatorial udp line output symbol (%x) '%c' illegal", ch, ch);
+   return(FALSE);
+  }
+ if (*chp != '\0')
+  {
+   __pv_ferr(1208,
+    "combinatorial udp line has second output symbol '%c' - only one allowed",
+    *chp);
+   return(FALSE);
+  }
+ /* check inputs - up to rightmost : */
+ for (chp = uline, ins = 0; *chp != '\0'; chp++, ins++)
+  {
+   switch (*chp) {
+    case '(': case 'r': case 'f': case 'p': case 'n': case '*':
+     __pv_ferr(1209, "edge symbol %c illegal in combinatorial udp line", *chp); 
+     return(FALSE);
+   }
+   if (to_udp_levsym(*chp) == -1)
+    {
+     __pv_ferr(1213,
+      "combinatorial udp line input symbol '%c' (position %d) not a level symbol",
+      *chp, ins + 1);
+     return(FALSE);
+    }
+   if (ins >= 254)
+    {
+     __pv_ferr(1214,
+      "udp has so many inputs (%d) - it cannot be checked", 254); 
+     return(FALSE);
+    }
+   if (*chp == 'b' || *chp == '?') *has_wcard = TRUE;
+  }
+ if (ins != udpp->numins)
+  {
+   __pv_ferr(1215,
+    "combinatorial udp line wrong number of input symbols (%d) - should be %d",
+    ins, udpp->numins);
+   return(FALSE);
+  }
+ /* finally add output as last symbol */
+ *chp++ = ch;
+ *chp = '\0';
+ return(TRUE);
+}
+
+/*
+ * check coded sequential upd uline
+ * know all (..) edge convert to 1 char by here (0x80 on)
+ * if no edge __cur_ueipnum has value NO_VAL
+ * old 0x80 bit on form edge converted to 1st as __cur_utabsel, 2nd as char 
+ * unless edge wildcard (i.e. r,f,n, etc.) in which case has edge wildcard
+ */
+static int32 chk_sequdpline(char *uline, struct udp_t *udpp,
+ int32 *has_wcard)
+{
+ register char *chp;
+ char ch1, ch2;
+ int32 ins, t1;
+
+ *has_wcard = FALSE;
+ /* separate off : before previous state :[prev. state]:[output] */
+ if ((chp = strchr(uline, ':')) == NULL)
+  {
+   __pv_ferr(1216,
+    "sequential udp line expected colon before old state symbol missing");
+   return(FALSE);
+  }
+ /* end uline */
+ *chp = '\0';
+ chp++;
+ /* ch1 is state symbol and -1 means not 1 of legasl 0,1,x,?,b */
+ ch1 = *chp++;
+ if (to_udp_levsym(ch1) == -1)
+  {
+   __pv_ferr(1218,
+    "sequential udp line state level symbol '%c' illegal", ch1);
+   return(FALSE);
+  }
+ /* state can be wildcard but not edge */
+ if (ch1 == 'b' || ch1 == '?') *has_wcard = TRUE;
+ if (*chp++ != ':')
+  {
+   __pv_ferr(1219,
+    "sequential udp line expected colon before output symbol missing");
+   return(FALSE);
+  }
+ /* ch2 is output symbol */
+ ch2 = *chp++;
+ if (ch2 != '0' && ch2 != '1' && ch2 != 'x' && ch2 != '-')
+  {
+   __pv_ferr(1221, "sequential udp line output symbol '%c' illegal", ch2);
+   return(FALSE);
+  }
+ if (*chp != '\0')
+  {
+   __pv_ferr(1222,
+    "sequential udp line has extra output symbol '%c' - only one allowed",
+    *chp);
+   return(FALSE);
+  }
+ /* previous state and output done, finally check inputs */
+ __cur_utabsel = NO_VAL;
+ __cur_ueipnum = NO_VAL;
+ for (chp = uline, ins = 0; *chp != '\0'; chp++, ins++)
+  {
+   /* know if edge, already checked - wild card only for level sensitive */
+   if (is_edgesym(*chp))
+    {
+     if (__cur_ueipnum != NO_VAL)
+      {
+       __pv_ferr(1223,
+       "sequential udp line has more than one edge symbol (second input %d)",
+        ins + 1);
+       return(FALSE);
+      }
+     __cur_ueipnum = ins;
+     if ((*chp & 0x80) != 0)
+      {
+       /* know if (..) edge then both letters are edge symbols */
+       /* edge has high bit on and then bits 5-3 is ie1 and 2-0 is ie2 */
+       t1 = *chp & 0x7f;
+       *chp = to_edgech(t1 & 0x7);
+       __cur_utabsel = to_edgech((t1 >> 3) & 0x7);
+       if ((__cur_utabsel == '0' && *chp == '0')
+        || (__cur_utabsel == '1' && *chp == '1')
+        || (__cur_utabsel == 'x' && *chp == 'x'))
+        {
+         __pv_ferr(1224,
+          "sequential udp line edge (%c%c) (input %d) illegal - no transition",
+          __cur_utabsel, *chp, __cur_ueipnum + 1);
+         return(FALSE);
+        }
+      }
+     else if (*chp == 'r') { __cur_utabsel = '0'; *chp = '1'; }
+     else if (*chp == 'f') { __cur_utabsel = '1'; *chp = '0'; }
+     /* if special edge abbrev. but not r or f make both edges have abbrev. */
+     else __cur_utabsel = *chp;
+     continue;
+    }
+   if (to_udp_levsym(*chp) == -1)
+    {
+     __pv_ferr(1225,
+      "sequential udp line symbol '%c' (input %d) not edge or level", *chp,
+      ins + 1);
+     return(FALSE);
+    }
+   if (*chp == 'b' || *chp == '?') *has_wcard = TRUE;
+  }
+ if (ins != udpp->numstates - 1 || ins != udpp->numins)
+  {
+   __pv_ferr(1226,
+    "sequential udp line wrong number of input symbols (%d) - should be %d",
+    ins, udpp->numins - 1);
+   return(FALSE);
+  }
+ /* finally add previous state input and next state output as last 2 */
+ *chp++ = ch1;
+ *chp++ = ch2;
+ *chp = '\0';
+ if (__cur_ueipnum != NO_VAL) udpp->utyp = U_EDGE;
+ return(TRUE);
+}
+
+/*
+ * convert edge 4 bit encoding to normal level edge symbol
+ */
+static char to_edgech(int32 encodee)
+{
+ switch ((byte) encodee) {
+  case UV_0: return('0');
+  case UV_1: return('1');
+  case UV_X: break;
+  case UV_Q: return('?');
+  case UV_B: return('b');
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return('x');
+}
+
+/*
+ * return T if symbol is an edge symbol (code 0x80 or edge letter)
+ */
+static int32 is_edgesym(char ch)
+{
+ if ((ch & 0x80) != 0) return(TRUE);
+ switch (ch) {
+  case 'r': case 'f': case 'p': case 'n': case '*': return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*
+ * convert a coded edge line to a string 
+ * in form during input before converted to line separate edge char and 
+ * edge destination in line char position 
+ */
+static char *to_codedge_line(char *s, char *culine)
+{
+ register char *cpi, *cpo;
+ int32 uch;
+
+ for (cpi = culine, cpo = s; *cpi != '\0'; cpi++)
+  {
+   if ((*cpi & 0x80) != 0)
+    {
+     *cpo++ = '(';
+     /* notice 5-3 are e1 and 2-0 are e2 */
+     uch = (int32) *cpi;
+     *cpo++ = to_edgech((uch >> 3) & 0x7);
+     *cpo++ = to_edgech(uch & 0x7);
+     *cpo++ = ')'; 
+    }
+   else *cpo++ = *cpi;
+  }
+ *cpo = '\0';
+ return(s);
+}
+
+/*
+ * perform some consistency checks on edge udps
+ * - input column probably needs edge in some row
+ * - output column probably needs - somewhere
+ */
+static void extra_chk_edgeudp(struct udp_t *udpp)
+{
+ register int32 i;
+ int32 out_hasbar;
+ struct utline_t *utlp;
+
+ for (i = 0; i < (int32) udpp->numins; i++)
+  {
+   for (utlp = udpp->utlines; utlp != NULL; utlp = utlp->utlnxt)
+    {
+     if (utlp->uledinum == i) goto next;
+    }
+   __gfinform(421, udpp->usym->syfnam_ind, udpp->usym->sylin_cnt,
+    "sequential udp \"%s\" column for input %s lacks any edge(s)",
+     udpp->usym->synam, to_udp_prtnam(udpp, i + 1));
+next:;
+  }
+ /* inputs are 0 to num ins - 1 then previous state, then next state */
+ i = udpp->numins + 1;
+ out_hasbar = FALSE;
+ for (utlp = udpp->utlines; utlp != NULL; utlp = utlp->utlnxt)
+  {
+   if (utlp->tline[i] == '-') out_hasbar = TRUE;
+  }
+ if (!out_hasbar)
+  {
+   __gfinform(422, udpp->usym->syfnam_ind, udpp->usym->sylin_cnt,
+    "sequential udp %s output column lacks any no change (-) symbols",
+    udpp->usym->synam);
+  }
+}
+
+/*
+ * find input position %d (first is output)
+ * know position number legal and starts at 1
+ */
+static char *to_udp_prtnam(struct udp_t *udpp, int32 inum)
+{
+ register struct mod_pin_t *mpp;
+ int32 nins;
+
+ nins = 1;
+ mpp = udpp->upins->mpnxt;
+ for (; mpp != NULL; mpp = mpp->mpnxt, nins++)
+  {
+   if (nins == inum) goto done;
+  }
+ __misc_terr(__FILE__, __LINE__);
+done:
+ return(mpp->mpsnam);
+}
+
+/*
+ * UDP DUMP ROUTINES - FOR DEBUGGING
+ */
+
+/*
+ * dump a udp for debugging
+ * f cannot be nil to put in string
+ */
+extern void __dmp_udp(FILE *f, struct udp_t *udpp)
+{
+ register struct mod_pin_t *mpp;
+ int32 first_time;
+ char s1[RECLEN], s2[RECLEN];
+
+ if (f == NULL) __arg_terr(__FILE__, __LINE__);
+ __cv_msg("\n");
+ __cur_sofs = 0;
+ __outlinpos = 0;
+ __pv_stlevel = 0;
+
+ __wrap_puts("primitive ", f);
+ __wrap_puts(udpp->usym->synam, f);
+ first_time = TRUE;
+ /* notice udp module pin lists continue to use next pointer */
+ for (mpp = udpp->upins; mpp != NULL; mpp = mpp->mpnxt)
+  {
+   if (first_time) { __wrap_putc('(', f); first_time = FALSE; }
+   else __wrap_puts(", ", f);
+   /* know udp pins must be named */
+   __wrap_puts(mpp->mpsnam, f);
+  }
+ __nl_wrap_puts(");", f);
+
+ /* notice here mpsnam must exist or earlier syntax error */
+ __pv_stlevel = 1;
+ mpp = udpp->upins;
+ __wrap_puts("output ", f);
+ __wrap_puts(mpp->mpsnam, f);
+ __wrap_putc(';', f);
+ if (udpp->utyp != U_COMB)
+  {
+   __wrap_puts("  reg ", f);
+   __wrap_puts(mpp->mpsnam, f);
+   __wrap_putc(';', f); 
+  }
+ __nl_wrap_puts("", f);
+ 
+ __wrap_puts("input ", f);
+ first_time = TRUE;
+ for (mpp = mpp->mpnxt; mpp != NULL; mpp = mpp->mpnxt)
+  {
+   if (first_time) first_time = FALSE; else __wrap_puts(", ", f);
+   __wrap_puts(mpp->mpsnam, f);
+  }
+ __nl_wrap_puts(";", f);
+
+ if (udpp->ival != NO_VAL)
+  {
+   __wrap_puts("initial ", f);
+   __wrap_puts(udpp->upins->mpsnam, f);
+   sprintf(s1, " = 1'b%s", __to_uvvnam(s2, (word32) udpp->ival));
+   __wrap_puts(s1, f);
+   __nl_wrap_puts(";", f);
+  }
+ __nl_wrap_puts("", f);
+ __nl_wrap_puts("table", f);
+ dmp_udp_lines(f, udpp);
+ __nl_wrap_puts("endtable", f);
+ __pv_stlevel--;
+ __nl_wrap_puts("endprimitive", f);
+}
+
+/*
+ * dump udp lines
+ * need to also dump initial value
+ */
+static void dmp_udp_lines(FILE *f, struct udp_t *udpp)
+{
+ register int32 i;
+ register struct utline_t *utlp;
+ int32 numins, sav_stlevel;
+ char *chp, s1[RECLEN];
+
+ sav_stlevel = __pv_stlevel;
+ __pv_stlevel = 4;
+ __outlinpos = 0;
+ numins = udpp->numins;
+ for (utlp = udpp->utlines; utlp != NULL; utlp = utlp->utlnxt)
+  {
+   for (chp = utlp->tline, i = 0; i < numins; i++, chp++)
+    {    
+     /* the one possible edge */
+     if (utlp->uledinum == i)
+      {
+       /* special wild card types edges are kept as original char */
+       /* 01 and 10 are converted from rise-fall - convert back */
+       if (utlp->utabsel == '0' && *chp == '1') __wrap_puts("    r", f);
+       else if (utlp->utabsel == '1' && *chp == '0') __wrap_puts("    f", f);
+       else if (utlp->utabsel == '*') __wrap_puts("    *", f);
+       else if (utlp->utabsel == 'p') __wrap_puts("    p", f);
+       else if (utlp->utabsel == 'n') __wrap_puts("    n", f);
+       else
+        {
+         sprintf(s1, " (%c%c)", (char) utlp->utabsel, *chp);
+         __wrap_puts(s1, f);
+        }
+      }
+     /* various wild cards and states left as input char */
+     else { sprintf(s1, "%5c", *chp); __wrap_puts(s1, f); }
+    }
+   if (udpp->utyp != U_COMB)
+    { sprintf(s1, " : %c ", *chp); __wrap_puts(s1, f); chp++; }
+   sprintf(s1, " : %c ;", *chp);
+   __nl_wrap_puts(s1, f);
+  }
+ __pv_stlevel = sav_stlevel;
+}
+
+/*
+ * READ SPECIFY SECTION ROUTINES
+ */
+
+/*
+ * read and build d.s for specify section items
+ * expects specify to have been read and reads endspecify
+ * current approach concatenates all specify sections in one mod.
+ */
+extern int32 __rd_spfy(struct mod_t *mdp)
+{
+ int32 tmpi, sav_decl_obj;
+ word32 tchktyp;
+ char s1[RECLEN];
+ 
+ __path_num = __tchk_num = 1;
+ sav_decl_obj = __cur_declobj;
+ __cur_declobj = SPECIFY;
+ /* all specify sections concatenated together */
+ if (mdp->mspfy == NULL) mdp->mspfy = alloc_spfy();
+ __cur_spfy = mdp->mspfy;
+ /* at this point only module symbol tabl on scope stack since specify */
+ /* is module item */
+ if (__top_sti != 0) __misc_terr(__FILE__, __LINE__);
+ /* place special symbol table for specparams on scope stack */
+ __venviron[++__top_sti] = __cur_spfy->spfsyms;
+
+ for (;;)
+  {
+   __get_vtok();
+   switch ((byte) __toktyp)
+    {
+     case SPECPARAM: 
+      if (!rd_specparamdecl())
+       {
+        /* notice unless T (found ;) will not sync to normal ( path */
+specitem_resync:
+        switch ((byte) __syncto_class) {
+         case SYNC_FLEVEL: case SYNC_MODLEVEL: case SYNC_STMT:
+          __top_sti--;
+          return(FALSE);
+         case SYNC_SPECITEM:
+          break;
+         /* if sync. to statement assume initial left out */
+         default: __case_terr(__FILE__, __LINE__);
+        }
+       }
+      continue;
+     case IF: case LPAR: case IFNONE:
+      if (!rd_delay_pth()) goto specitem_resync;
+      break;
+     case ENDSPECIFY: goto done;
+     case ID:
+      /* this must be timing check */
+      if (*__token == '$')
+       {
+        if ((tmpi = __fr_tcnam(__token)) == -1)
+         {
+          __pv_ferr(1228,
+           "system task %s illegal in specify section", __token);
+          goto err_skip;
+         }
+        tchktyp = tmpi;
+        __get_vtok();
+        if (__toktyp != LPAR)
+         {
+          __pv_ferr(1231,
+          "timing check %s argument list left parenthesis expected - %s read",
+          __to_tcnam(s1, tchktyp) , __prt_vtok());
+          goto err_skip;
+         } 
+        /* specify system timing check tasks */
+        /* the routines fill cur tchk */
+        switch ((byte) tchktyp) {
+         case TCHK_SETUP: case TCHK_HOLD:
+          if (!rd_setup_or_hold_tchk(tchktyp)) goto specitem_resync;
+          break;
+         case TCHK_SETUPHOLD:
+          if (!rd_setuphold_tchk()) goto specitem_resync;
+          break;
+         case TCHK_WIDTH:
+          if (!rd_width_tchk()) goto specitem_resync;
+          break;
+         case TCHK_PERIOD:
+          if (!rd_period_tchk()) goto specitem_resync;
+          break;
+         case TCHK_SKEW: case TCHK_RECOVERY: case TCHK_REMOVAL:
+          if (!rd_skew_recov_rem_tchk(tchktyp)) goto specitem_resync;
+          break;
+         case TCHK_RECREM:
+          if (!rd_recrem_tchk()) goto specitem_resync;
+          break;
+         case TCHK_NOCHANGE:
+          if (!rd_nochg_tchk()) goto specitem_resync;
+          break;
+         case TCHK_FULLSKEW:
+         case TCHK_TIMESKEW:
+          /* SJM 11/21/03 - this and other new 2001 tchks not supported */
+          /* for now just skip and later add support for this and others */
+          __pv_fwarn(3124,"%s timing check not yet supported - ignored",
+           __to_tcnam(__xs, tchktyp)); 
+          goto err_skip;
+         default: __case_terr(__FILE__, __LINE__);
+        }
+        /* add to timing check list */
+        if (__end_tchks == NULL) __cur_spfy->tchks = __cur_tchk;
+        else __end_tchks->tchknxt = __cur_tchk;
+        __end_tchks = __cur_tchk;
+        break;
+       }
+      /* fall through to error since ID not specify item */
+      /*FALLTHRU*/
+     default:
+      __pv_ferr(1229, "specify section item expected - %s read",
+       __prt_vtok());
+err_skip:
+     if (!__spec_vskipto_any(SEMI)) goto specitem_resync;
+     /* just fall through if seme to next */
+    }
+  }
+done:
+ __top_sti = 0;
+ __cur_declobj = sav_decl_obj;
+ /* notice freezing at module end for specparam symbol table too */
+ return(TRUE);
+}
+
+/*
+ * allocate a specify block - called when first specify block seen
+ */
+static struct spfy_t *alloc_spfy(void)
+{
+ struct spfy_t *spcp;
+
+ spcp = (struct spfy_t *) __my_malloc(sizeof(struct spfy_t));
+ /* notice this symbol table links to mod through this special specify */
+ /* block but otherwise no symbol table links */
+ spcp->spfsyms = __alloc_symtab(TRUE);
+ spcp->spcpths = NULL; 
+ spcp->tchks = NULL;
+ spcp->msprms = NULL; 
+ spcp->sprmnum = 0;
+ __end_spcpths = NULL;
+ __end_tchks = NULL;
+ __end_msprms = NULL;
+ return(spcp);
+}
+
+/*
+ * read the specparam declaration statement 
+ * form: specparam [name] = [constant?], ...
+ * no  # and () around delay is optional in parameter decl.
+ * reads parameter name through ending ;
+ *
+ * here width actual bit width - later converted to int32 or real
+ * and then usually to 64 bit delay
+ */
+static int32 rd_specparamdecl(void)
+{
+ int32 good, sav_slin_cnt, sav_sfnam_ind, prng_decl, pwid, rwid, r1, r2;
+ struct net_t *np;
+ struct expr_t *dx1, *dx2, *x1, *x2;
+ char paramnam[IDLEN];
+
+ pwid = 0;
+ dx1 = dx2 = x1 = x2 = NULL;
+ prng_decl = FALSE;
+ __get_vtok();
+ if (__toktyp == LSB)
+  {
+   /* also check to make sure ranges are non x/z 32 bit values */
+   if (!__rd_opt_param_vec_rng(&dx1, &dx2, FALSE)) return(FALSE);
+   if (dx1 == NULL || dx2 == NULL) goto rd_param_list;
+
+   r1 = (int32) __contab[dx1->ru.xvi];
+   r2 = (int32) __contab[dx2->ru.xvi];
+   pwid = (r1 >= r2) ? r1 - r2 + 1 : r2 - r1 + 1; 
+   x1 = dx1; x2 = dx2;
+   prng_decl = TRUE;
+   /* know parameter name read */
+  }
+
+rd_param_list:
+ for (;;)
+  {
+   if (__toktyp != ID)
+    {
+     __pv_ferr(1230, "specparam name expected - %s read", __prt_kywrd_vtok());
+bad_end:
+     /* part of delay expression may have been built */
+     if (!__spec_vskipto2_any(COMMA, SEMI)) return(FALSE);
+     if (__toktyp == COMMA) { __get_vtok(); continue; }
+     return(TRUE);
+    }
+   strcpy(paramnam, __token);
+
+   /* notice the initial value is required */
+   __get_vtok();
+   if (__toktyp != EQ)
+    {
+     __pv_ferr(1232,
+      "specparam declaration equal expected - %s read", __prt_vtok());
+     goto bad_end;
+    }
+   /* 06/22/00 - SJM - special path pulse form, for now ignore with warn */
+   if (strncmp(paramnam, "PATHPULSE$", 10) == 0)
+    {
+     __pv_fwarn(3102,
+      "%s special path pulse specparam ignored - use +show_canceled_e option instead",
+      paramnam);
+     /* 06/22/00 - SJM - FIXME - need to really parse this */ 
+     if (!__spec_vskipto_any(SEMI)) 
+      {
+       __pv_ferr(3408,
+        "PATHPULSE$ specparam %s right hand side value illegal format",
+        paramnam);
+       return(FALSE);
+      }
+     goto nxt_sparam;
+    }
+
+   /* know symbol table env. in specify specparam rhs specparam local */
+   __get_vtok();
+   __sav_spsytp = __venviron[0];
+   __venviron[0] = __venviron[1];
+   __top_sti = 0;
+   good = __col_paramrhsexpr();
+   __venviron[0] = __sav_spsytp;
+   __top_sti = 1; 
+   /* on error, does not add spec param */
+   if (!good) goto bad_end;
+   __bld_xtree(0);
+
+   /* checking rhs does no evaluation (not known yet) but set sizes */
+   /* and makes sure contains only num and previously defined specparams */
+   if (__expr_has_glb(__root_ndp)
+    || !__src_rd_chk_paramexpr(__root_ndp, WBITS))
+    {
+     __pv_ferr(1233,
+      "specparam %s right hand side %s illegal - defined specparams and constants only",
+      paramnam, __msgexpr_tostr(__xs, __root_ndp));
+     goto nxt_sparam;
+    }
+
+   /* SJM 06/17/99 - illegal to assign string literal to specparam */
+   /* SJM 02/04/00 - must allow since needed for models where PLI used */
+   /* to read parameter value - and should be this is just wide reg */
+   /* --- REMOVED --- 
+   if (__root_ndp->is_string)
+    {
+     __pv_fwarn(659,
+      "specparam %s right hand side string not a delay value - converted to 0 delay",
+      paramnam);
+     -* need to still add value of x to prevent further errors *-
+     __free2_xtree(__root_ndp);
+     __root_ndp->szu.xclen = WBITS;
+     __set_numval(__root_ndp, 0L, 0L, WBITS);  
+     -* notice x1, x2 range expressions always WBITS-1 to 0 for specparams *-  
+    }
+   --- */
+
+   /* if range declared that is used, else if non scalar expr, use that */
+   if (prng_decl)
+    {
+     if (pwid == 1) x1 = x2 = NULL;
+     else
+      {
+       /* for specparam - assume int/word32, convert to real if needed */
+       x1 = __bld_rng_numxpr(pwid - 1L, 0L, WBITS);
+       x2 = __bld_rng_numxpr(0L, 0L, WBITS);
+      }
+    }
+   else
+    {
+     if (__root_ndp->is_real) rwid = REALBITS; 
+     else rwid = __root_ndp->szu.xclen;
+
+     if (rwid == 1) x1 = x2 = NULL;
+     else
+      {
+       /* if expr value unsized, know will be 32 bit width already */  
+       x1 = __bld_rng_numxpr(rwid - 1, 0, WBITS);
+       x2 = __bld_rng_numxpr(0, 0, WBITS);
+      }
+    }
+
+   /* check and links on modules parameter list */
+   /* when rhs expr. evaluated, if real will change */
+   /* LOOKATME - problem with all params in list sharing range xprs? */ 
+   np = __add_param(paramnam, x1, x2);
+ 
+   /* using ncomp delay union to store original expresssion - set first */
+   /* need this separate copy even after parameter value assigned */
+   np->nu.ct->n_dels_u.d1x = __root_ndp;
+   np->nu.ct->parm_srep = SR_PXPR;
+
+   /* can assign specparam value immediately */
+   /* SJM 06/17/99 - needs to run in run/fixup mode - statement loc set */
+   sav_slin_cnt = __slin_cnt;
+   sav_sfnam_ind = __sfnam_ind;
+   __sfnam_ind = (int32) np->nsym->syfnam_ind;
+   __slin_cnt = np->nsym->sylin_cnt;
+
+   assign_1specparam(np, __root_ndp, prng_decl, pwid);
+
+   __slin_cnt = sav_slin_cnt;
+   __sfnam_ind = sav_sfnam_ind;
+
+   /* specparams can never be strings or IS forms */ 
+   __mod_specparams++;
+
+nxt_sparam:
+   if (__toktyp == SEMI) break;
+   if (__toktyp != COMMA)
+    {
+     __pv_ferr(1236,
+      "specparam ; or , separator expected - %s read", __prt_vtok());
+     if (!__spec_vskipto2_any(COMMA, SEMI)) return(FALSE); 
+     if (__toktyp == SEMI) break;
+    }
+   __get_vtok();
+  }
+ return(TRUE);
+}
+
+/*
+ * assign values to specparams - like defparams but can never be IS form
+ *
+ * 02/04/00 - SJM change to move toward v2k LRM and match XL better
+ * type determined from RHS - range allowed and used for width
+ *
+ * SJM 10/06/03 - signed keyword illegal and specparams never signed
+ * unless real
+ */
+static void assign_1specparam(struct net_t *np, struct expr_t *ndp,
+ int32 prng_decl, int32 pwid)
+{
+ int32 wlen;
+ word32 *wp;
+ struct xstk_t *xsp;
+
+ /* need dummy itree place on itree stack for eval */
+ xsp = __eval_xpr(ndp);
+
+ /* case 1: range declaration - may need to convert value */
+ if (prng_decl)
+  {
+   /* convert declared param type real rhs to int/reg */
+   if (ndp->is_real)
+    {
+     __cnv_stk_fromreal_toreg32(xsp);
+     np->nu.ct->pbase = BDEC;
+     np->nu.ct->prngdecl = TRUE;
+     np->nwid = xsp->xslen;
+     np->ntyp = N_REG;
+     np->n_signed = TRUE;
+    }
+   else
+    {
+     if (xsp->xslen != pwid) __sizchgxs(xsp, pwid);
+
+     np->nu.ct->prngdecl = TRUE;
+     np->nwid = xsp->xslen;
+     np->ntyp = N_REG;
+     if (np->nwid > 1) { np->n_isavec = TRUE; np->vec_scalared = TRUE; } 
+     np->nu.ct->pbase = ndp->ibase;
+    }
+
+   wlen = wlen_(np->nwid);
+   wp = (word32 *) __my_malloc(2*WRDBYTES*wlen); 
+   memcpy(wp, xsp->ap, 2*WRDBYTES*wlen);
+   __pop_xstk();
+   np->nva.wp = wp;
+   np->srep = SR_PNUM;
+   return;
+  }
+
+ /* SJM 10/06/03 - since specparams never signed, interpret as word32 */
+ /* even if rhs signed with sign bit on */
+
+ /* case 2: type determined from constant expr */
+ /* spec params either reg or real - by here if range decl ndp fixed */
+ if (ndp->is_real)
+  {
+   np->nwid = REALBITS;
+   np->ntyp = N_REAL;
+   np->n_signed = TRUE;
+   np->n_isavec = TRUE;
+   np->nu.ct->pbase = BDBLE;
+   wp = (word32 *) __my_malloc(2*WRDBYTES); 
+   memcpy(wp, xsp->ap, 2*WRDBYTES);
+  }
+ else
+  {
+   np->nwid = xsp->xslen;
+   np->ntyp = N_REG;
+   if (np->nwid > 1) { np->n_isavec = TRUE; np->vec_scalared = TRUE; } 
+   if (ndp->is_string) np->nu.ct->pstring = TRUE;
+
+   np->nu.ct->pbase = ndp->ibase;
+   wlen = wlen_(np->nwid);
+   wp = (word32 *) __my_malloc(2*WRDBYTES*wlen); 
+   memcpy(wp, xsp->ap, 2*WRDBYTES*wlen);
+  }
+ __pop_xstk();
+ /* build wire value - this is assign to wire so wire flags unchged */
+ np->nva.wp = wp;
+ np->srep = SR_PNUM;
+}
+
+/*
+ * DELAY PATH ROUTINES
+ */
+
+/*
+ * read the ([path desc. list?] [=*]> [path desc. list?]) = [path val.]
+ * know initial ( read and if conditional present in condx
+ * notice no path if any error but may still return T
+ *
+ * here when collecting expressions both specparams and top module symbol
+ * table accessible for wires but only local specparams for delay
+ */
+static int32 rd_delay_pth(void)
+{
+ int32 good;
+ int32 pdtyp, pth_edge, pthpolar, datasrcpolar, is_ifnone;
+ struct sy_t *pthsyp;
+ struct exprlst_t *ilstx, *olstx;
+ struct paramlst_t *pmphdr;
+ struct expr_t *condx, *datsrcx, *lop, *last_dsx;
+ struct spcpth_t *pthp;
+
+ is_ifnone = FALSE;
+ condx = datsrcx = NULL;
+ /* needed since gcc sees as unset - do not think so */
+ olstx = NULL;
+ pdtyp = PTH_NONE;
+ datasrcpolar = POLAR_NONE;
+ pthpolar = POLAR_NONE;
+ if (__toktyp == IFNONE)
+  { 
+   __get_vtok();
+   if (__toktyp != LPAR)
+    {
+     __pv_ferr(1197,
+      "sdpd ifnone token not followed by path beginning ( - %s read",
+      __prt_vtok());
+     /* here skipping to ) will skip path - no start tok - can not correct */
+     if (!__spec_vskipto_any(SEMI)) return(FALSE);
+     return(TRUE);
+    }
+   is_ifnone = TRUE;
+   goto no_pthcond;
+  }
+ if (__toktyp == LPAR) goto no_pthcond;
+ /* must be if token to get here, read optional condition expr. 1st */
+ __get_vtok();
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(1251,
+    "sdpd conditional expression if token not followed by ( - %s read",
+     __prt_vtok());
+bad_sdp:
+   if (!__spec_vskipto2_any(SEMI, RPAR)) return(FALSE);
+   if (__toktyp == SEMI) return(TRUE);
+   /* have ) make cond x NULL - this is not delay this is if actual expr */
+   __set_numval(__exprtab[0], 1L, 1L, 1);
+   __last_xtk = 0;
+   goto bad_sdpx;
+  }
+ __get_vtok();
+ if (!__col_parenexpr(-1)) goto bad_sdp;
+bad_sdpx:
+ __bld_xtree(0);
+ condx = __root_ndp;
+ if (__expr_has_glb(condx))
+  {
+   __pv_ferr(1022,
+    "global hierarchical reference illegal in state dependent path condition %s",
+    __msgexpr_tostr(__xs, condx));
+  }
+ __get_vtok();
+ if (__toktyp != LPAR)
+  {
+   __pv_ferr(1252,
+    "sdpd conditional expression not followed by path start ( - %s read",
+    __prt_vtok());
+   /* here skipping to ) will skip path */
+   if (!__spec_vskipto_any(SEMI)) return(FALSE);
+   return(TRUE);
+  }
+
+no_pthcond:
+ /* for edge sensitive path can have edge before input */
+ /* but only pos and neg edges */
+ __get_vtok();
+ if (__toktyp == NEGEDGE || __toktyp == POSEDGE) 
+  {
+   pth_edge = (__toktyp == NEGEDGE) ? E_NEGEDGE : E_POSEDGE;
+   __get_vtok();
+  }
+ else pth_edge = NOEDGE;
+
+ /* this requires read 1st token of path */ 
+ if ((ilstx = rd_pthtermlst()) == NULL)
+  {
+bad_pth:
+   if (!__spec_vskipto3_any(SEMI, RPAR, EQ)) return(FALSE);
+   if (__toktyp == RPAR) goto get_eq; 
+   if (__toktyp == EQ) goto got_eq;
+   return(TRUE);
+  }
+ /* this just attempts to catch some common errors */
+ if (__toktyp == RPAR || __toktyp == TCHKEVAND)
+  {
+   __pv_ferr(1253,
+    "input path description connector operator or semicolon expected - %s read",
+    __prt_vtok());
+   goto bad_pth;
+  }
+ /* path polarity is option stored for pli but not used */
+ if (__toktyp == PLUS || __toktyp == MINUS)
+  {
+   pthpolar = (__toktyp == PLUS) ? POLAR_PLUS : POLAR_MINUS;
+   __get_vtok();
+  }
+ else pthpolar = POLAR_NONE;
+
+ /* path type required */
+ if (__toktyp == FPTHCON) pdtyp = PTH_FULL; 
+ else if (__toktyp == PPTHCON) pdtyp = PTH_PAR;
+ else
+  {
+   __pv_ferr(1258,
+    "either full => or parallel *> path operator expected - %s read",
+    __prt_vtok());
+   goto bad_pth;
+  }
+ /* if ( here then form is ([dst. term list] [polarity?]:[data src. expr.]) */
+ __get_vtok();
+ if (__toktyp == LPAR)
+  { 
+   /* this requires read 1st token of path */ 
+   __get_vtok();
+   if ((olstx = rd_pthtermlst()) == NULL) goto bad_end;
+   /* data source polarity determines delay selection */
+   if (__toktyp == PLUS || __toktyp == MINUS)
+    {
+     datasrcpolar = (__toktyp == PLUS) ? POLAR_PLUS : POLAR_MINUS;
+     __get_vtok();
+    }
+   else datasrcpolar = POLAR_NONE;
+   if (__toktyp != COLON)  
+    {
+     __pv_ferr(1254,
+      "data source path destination colon terminator expected - %s read",
+      __prt_vtok());
+     goto bad_pth;
+    }
+   __get_vtok();
+   /* comma separated list allowed here - width must match dest. width */
+   if (!__col_parenexpr(-1)) goto bad_pth;
+   __bld_xtree(0);
+   /* common edge path trigger as 1 expression not list case */
+   if (__toktyp != COMMA)
+    { datsrcx = __root_ndp; __get_vtok(); goto chk_endrpar; }
+
+   /* this is complicated data source expression list case */
+   lop = __alloc_newxnd();
+   lop->optyp = FCCOM;
+   lop->ru.x = NULL;
+   lop->lu.x = __root_ndp;
+   datsrcx = lop;
+   for (last_dsx = lop;;) 
+    {
+     /* if good this reads trailing delimiter */
+     if (!__col_connexpr(-1)) goto bad_end;
+     __bld_xtree(0);
+     lop = __alloc_newxnd();
+     lop->optyp = FCCOM;
+     lop->ru.x = NULL;
+     lop->lu.x = __root_ndp;
+     last_dsx->ru.x = lop;
+     if (__toktyp == RPAR) { __get_vtok(); break; }
+     if (__toktyp != COMMA) 
+      {
+       __pv_ferr(1255,
+        "edge sensitive path data source expression list separator expected - %s read",
+        __prt_vtok());
+       goto bad_end;
+      }
+     __get_vtok();
+     if (__toktyp == COMMA || __toktyp == RPAR) 
+      {
+        __pv_ferr(1259,
+         "edge sensitive path data source expression ,, or ,) forms illegal");
+        goto bad_end;
+      }
+    }
+  }
+ else if ((olstx = rd_pthtermlst()) == NULL) goto bad_pth;
+
+chk_endrpar:
+ if (__toktyp != RPAR)
+  {
+   __pv_ferr(1256,
+    "path output terminal list right parenthesis expected - %s read",
+    __prt_vtok());
+   goto bad_pth;
+  }
+get_eq:
+ __get_vtok();
+ if (__toktyp != EQ) 
+  {
+   __pv_ferr(1257, "path delay equal sign expected - %s read",
+    __prt_vtok());
+bad_end:
+   if (!__spec_vskipto_any(SEMI)) return(FALSE);
+   return(TRUE);
+  }
+got_eq:
+ /* know symbol table env. in specify always specparam local on mod. lev. */
+ __sav_spsytp = __venviron[0];
+ __venviron[0] = __venviron[1];
+ __top_sti = 0;
+ /* notice = read but not ( - unusual case of no 1st token read before call */ 
+ good = rd_pathdelaylist(&pmphdr);
+ __venviron[0] = __sav_spsytp;
+ __top_sti++; 
+ if (!good) goto bad_end;
+
+ /* build the path delay element */
+ pthp = (struct spcpth_t *) __my_malloc(sizeof(struct spcpth_t));
+ init_spcpth(pthp);
+ pthp->pthtyp = pdtyp; 
+ pthp->pthpolar = pthpolar; 
+ pthp->peins = (struct pathel_t *) ilstx;
+ pthp->peouts = (struct pathel_t *) olstx;
+
+ /* add the location identifying symbol */
+ pthsyp = __bld_loc_symbol(__path_num, __venviron[0], "path", "delay path");
+ pthsyp->sytyp = SYM_PTH;
+ pthsyp->syfnam_ind = __cur_fnam_ind;
+ pthsyp->sylin_cnt = __lin_cnt;
+ pthp->pthsym = pthsyp;
+ pthsyp->el.epthp = pthp;
+ pthsyp->sydecl = TRUE;
+ __path_num++;
+
+ /* set delay part */
+ pthp->pth_delrep = DT_CMPLST;
+ pthp->pth_du.pdels = pmphdr;
+
+ /* set sdpd and conditional path values */ 
+ pthp->pthedge = pth_edge;  
+ pthp->dsrc_polar = datasrcpolar;
+ pthp->datasrcx = datsrcx;
+ pthp->pth_ifnone = is_ifnone;
+ pthp->pthcondx = condx;
+
+ if (__end_spcpths == NULL) __cur_spfy->spcpths = pthp;
+ else __end_spcpths->spcpthnxt = pthp;
+ __end_spcpths = pthp;
+ return(TRUE);
+}
+
+/*
+ * read a path terminal list
+ * know 1st token read and reads ending )
+ */
+static struct exprlst_t *rd_pthtermlst(void)
+{
+ struct exprlst_t *xpmphdr, *xpmp, *last_xpmp;
+
+ /* build specify terminal list - semantics that requires subset of mod. */
+ /* I/O port terminals checked later */
+ /* no ,, and at least one required */
+ for (xpmphdr = NULL, last_xpmp = NULL;;)
+  {
+   /* this will have skipped to end of statement on error */
+   if (!col_pthexpr()) return(NULL);
+   __bld_xtree(0);
+   xpmp = __alloc_xprlst();
+   xpmp->xp = __root_ndp;
+   if (last_xpmp == NULL) xpmphdr = xpmp; else last_xpmp->xpnxt = xpmp;
+   last_xpmp = xpmp;
+   if (__toktyp == RPAR || __toktyp == FPTHCON || __toktyp == PPTHCON
+    || __toktyp == PLUS || __toktyp == MINUS || __toktyp == TCHKEVAND
+    || __toktyp == COLON) break;
+   __get_vtok();
+  }
+ return(xpmphdr);
+}
+
+/*
+ * collect a delay path terminal expression
+ * expects 1st token to be read and read ending token
+ * ends with ) or ',' or => or *> or - or + or : preceding connection op.
+ * for timing checks can end with TCHKEVAND &&&
+ * allows full expressions because port bit select can be full const. expr.
+ *
+ * notice ending thing not included in expr. but left in token
+ *
+ * this collects a specify expr. - caller must eliminate wrong tokens for
+ * either tchk or path 
+ *
+ * notice this is lhs element not delay constants
+ * maybe should be empty on error
+ */
+static int32 col_pthexpr(void)
+{
+ int32 parlevel, sqblevel;
+
+ for (__last_xtk = -1, parlevel = 0, sqblevel = 0;;)
+  {
+   switch ((byte) __toktyp) {
+    case LPAR: parlevel++; break;
+    /* any expression (must later be constant) legal in selects */
+    case LSB: sqblevel++; break;
+    case RPAR: 
+     if (parlevel <= 0 && sqblevel <= 0) return(TRUE); else parlevel--;
+     break;
+   case RSB:
+    sqblevel--;
+    break;
+   case COMMA:
+    /* illegal here but parse and check later */
+    if (parlevel <= 0 && sqblevel <= 0) return(TRUE);
+    break;
+   case PLUS: case MINUS:
+    if (parlevel <= 0 && sqblevel <= 0) return(TRUE);
+    break;
+   case COLON:
+    if (parlevel <= 0 && sqblevel <= 0) return(TRUE);
+    break;
+   /* notice these are never nested */
+   case FPTHCON: case PPTHCON: case TCHKEVAND:
+    return(TRUE);
+   case TEOF:
+   case SEMI:
+    goto bad_end;
+   }
+   if (!__bld_expnode()) goto bad_end;
+   __get_vtok();
+  }
+
+bad_end:
+ __set_xtab_errval();
+ return(FALSE);
+}
+
+/*
+ * read delay path list 
+ * almost same as read oparams del but surrounding () always optional
+ *
+ * reads and checks for ending ; 
+ * builds a parameter/delay list and returns pointer to header
+ * returns F on sync error - caller must resync
+ * but in places with known delimiter attempt to resync to delim 
+ */
+static int32 rd_pathdelaylist(struct paramlst_t **pmphdr)
+{
+ int32 rv;
+ struct paramlst_t *pmp, *last_pmp;
+
+ *pmphdr = NULL;
+
+ /* this is #[number] or #id - not (..) form - min:typ:max requires () */
+ /* for path delay will never see this form */
+ __get_vtok();
+ /* case 1: has optional () surround list */
+ if (__toktyp == LPAR) 
+  {
+   for (last_pmp = NULL;;)
+    {
+     __get_vtok();
+     if (!__col_delexpr())
+      {
+       /* need to look to skip to any possible end ( may be unmatched */
+       if (!__vskipto3_modend(COMMA, RPAR, SEMI)) return(FALSE);
+       if (__toktyp == SEMI) return(FALSE);
+       if (__toktyp == RPAR) { __get_vtok(); rv = FALSE; goto chk_semi; }
+       /* if comman do not add but continue checking */
+       continue;
+      }       
+     __bld_xtree(0);
+     pmp = __alloc_pval();
+     pmp->plxndp = __root_ndp;
+
+     /* link on front */
+     if (last_pmp == NULL) *pmphdr = pmp; else last_pmp->pmlnxt = pmp;
+     last_pmp = pmp;
+
+     if (__toktyp == COMMA) continue;
+     if (__toktyp == RPAR) break;
+     /* should never happen - sync on err above, if does give up */
+     __pv_ferr(1050,
+      "path delay delay list comma or right parenthesis expected - %s read",
+      __prt_vtok());
+     return(FALSE);
+    }
+   rv = TRUE;
+   __get_vtok();
+chk_semi:
+   if (__toktyp != SEMI)
+    {
+     __pv_ferr(1279, "path delay final ; expected - %s read", __prt_vtok());
+     return(FALSE);
+    }
+   return(rv);
+  }
+ /* case 2: optional surrounding omitted */ 
+ for (last_pmp = NULL;;)
+  {
+   /* this reads the end , or ; */
+   if (!__col_paramrhsexpr())
+    {
+     /* need to look to skip to any possible end ( may be unmatched */
+     if (!__vskipto3_modend(COMMA, RPAR, SEMI)) return(FALSE);
+     if (__toktyp == SEMI) return(FALSE);
+     if (__toktyp == RPAR) { __get_vtok(); rv = FALSE; goto chk_semi; }
+     __get_vtok();
+     continue;
+    }       
+   __bld_xtree(0);
+   pmp = __alloc_pval();
+   pmp->plxndp = __root_ndp;
+   if (last_pmp == NULL) *pmphdr = pmp; else last_pmp->pmlnxt = pmp;
+   last_pmp = pmp;
+
+   if (__toktyp == COMMA) { __get_vtok(); continue; }
+   if (__toktyp == SEMI) break;
+   /* should never happen - sync on err above, if does give up */
+   __pv_ferr(1050,
+    "path delay delay list comma or semicolon expected - %s read",
+     __prt_vtok());
+   return(FALSE);
+  }
+ return(TRUE);
+}
+ 
+/*
+ * initialize a specify section delay path
+ */
+static void init_spcpth(struct spcpth_t *pthp)
+{
+ pthp->pthtyp = PTH_NONE;
+ pthp->pth_gone = FALSE;
+ pthp->pth_as_xprs = TRUE;
+ pthp->pth_delrep = DT_NONE;
+ pthp->pthpolar = FALSE;
+ pthp->pthedge = NOEDGE;
+ pthp->dsrc_polar = POLAR_NONE; 
+ pthp->pth_ifnone = FALSE;
+ pthp->pth_0del_rem = FALSE;
+ pthp->pthsym = NULL;
+ pthp->last_pein = -1;
+ pthp->last_peout = -1;
+ pthp->peins = NULL;
+ pthp->peouts = NULL;
+ pthp->pth_du.d1v = NULL;
+ pthp->datasrcx = NULL;
+ pthp->pthcondx = NULL;
+ pthp->spcpthnxt = NULL;
+}
+
+/*
+ * TIMING CHECK READ ROUTINES
+ */
+
+/*
+ * read setup or hold timing check
+ * know system task keyword and ( read and reads ending ; if possible
+ *
+ * read and parse timing checks as is - during prep changed to needed form
+ */
+static int32 rd_setup_or_hold_tchk(word32 ttyp)
+{
+ int32 fnum, lnum;
+ struct sy_t *syp, *tcsyp;
+ struct paramlst_t *pmp;
+ struct tchk_t tmptchk;
+ struct expr_t *limx;
+
+ __init_tchk(&tmptchk, ttyp);
+ /* must save location since, need system task line as tchk loc. */
+ fnum = __cur_fnam_ind;
+ lnum = __lin_cnt;
+ if (!rd_tchk_part(ttyp, &tmptchk, &limx)) return(FALSE);
+ /* notice can only be ID if present */
+ if (__toktyp == COMMA) { syp = rd_notifier(); __get_vtok(); }
+ else syp = NULL;
+ /* even even error end, still add since good */
+ if (__toktyp != RPAR) goto noparsemi;
+ __get_vtok();
+ if (__toktyp != SEMI)
+  {
+noparsemi:
+   __pv_ferr(1261, "%s timing check does not end with ); - %s read",
+    __to_tcnam(__xs, ttyp), __prt_vtok());
+   if (!__spec_vskipto_any(SEMI)) return(FALSE);
+  }
+ __cur_tchk = (struct tchk_t *) __my_malloc(sizeof(struct tchk_t));
+ *__cur_tchk = tmptchk; 
+ /* add the location idnentifying symbol */
+ tcsyp = __bld_loc_symbol(__tchk_num, __venviron[0], "tchk", "timing check");
+ tcsyp->sytyp = SYM_TCHK;
+ tcsyp->syfnam_ind = fnum;
+ tcsyp->sylin_cnt = lnum;
+ tcsyp->el.etcp = __cur_tchk;
+ tcsyp->sydecl = TRUE;
+ __cur_tchk->tcsym = tcsyp;
+ tcsyp->el.etcp = __cur_tchk;
+ __tchk_num++;
+
+ __cur_tchk->ntfy_np = (struct net_t *) syp;
+ /* setup and hold identical - users changes order of args - ref. event */
+ /* always first so $setup(data, clk, ...), $hold(clk, data, ...) */
+ pmp = __alloc_pval(); pmp->plxndp = limx; pmp->pmlnxt = NULL;
+ __cur_tchk->tclim_du.pdels = pmp;
+ return(TRUE);
+} 
+
+/*
+ * build timing check symbol
+ *
+ * even if already declared, change to delay object
+ * if used previously, change to delay object - error if previously declared
+ * if used in previous expr. but later declared, error emitted at declaration
+ * common case first used in $set[it]delay expr. and added to symbol table
+ * as wire then here changed to delay object
+ */
+extern struct sy_t *__bld_loc_symbol(int32 num, struct symtab_t *sytp,
+ char *pref, char *emsgnam)
+{
+ char s1[RECLEN];
+ struct sy_t *syp;
+
+ sprintf(s1, "__%s$$%d", pref, num);
+ syp = __decl_sym(s1, sytp);
+ if (!__sym_is_new)
+  {
+   if (syp->sydecl)
+    {
+     __pv_ferr(1160,
+      "%s constructed internal name %s conflicts with declared %s",
+      emsgnam, s1, __to_sytyp(__xs, syp->sytyp));
+    }
+   else
+    {
+     __pv_ferr(1160, "%s constructed internal name %s conflicts with wire",
+      emsgnam, s1);
+    }
+  }
+ return(syp);
+}
+
+/*
+ * read the event and first limit part of all timing checks
+ * common code for all timing checks, limits differ
+ * this must read 1st token before reading tchk events
+ * if returns F, parameters not set
+ * this syncs to ; or item location and returns F 
+ * on T reads ) or , after first (maybe only) limit
+ * notice 1 limit always required
+ */
+static int32 rd_tchk_part(word32 ttyp, struct tchk_t *tcp,
+ struct expr_t **limx)
+{
+ struct expr_t *xp, *condx;
+ int32 edgval;
+
+ /* notice ref. always first */
+ __get_vtok();
+ if (!rd_tchk_selector(&edgval, &xp, &condx))
+  {
+   if (!__spec_vskipto2_any(SEMI, COMMA)) return(FALSE);
+   if (__toktyp == SEMI)
+    {
+got_semi:
+     __syncto_class = SYNC_SPECITEM;
+     return(FALSE);
+    }
+  }
+ tcp->startedge = edgval;  
+ tcp->startxp = xp;
+ tcp->startcondx = condx;
+
+ /* tcp initialized to empty fields */
+ if (ttyp != TCHK_WIDTH && ttyp != TCHK_PERIOD) 
+  {
+   __get_vtok();
+   if (!rd_tchk_selector(&edgval, &xp, &condx))
+    {
+     if (!__spec_vskipto2_any(SEMI, COMMA)) return(FALSE);
+     if (__toktyp == SEMI) goto got_semi;
+    }  
+   tcp->chkedge = edgval;  
+   tcp->chkxp = xp;
+   tcp->chkcondx = condx;
+  }
+ __get_vtok();
+ __sav_spsytp = __venviron[0];
+ __venviron[0] = __cur_spfy->spfsyms;
+ /* limit is one number but can be d:d:d form - but know ends with , or ) */
+ if (!__col_delexpr())
+  { 
+   if (!__spec_vskipto2_any(SEMI, COMMA))
+    { __venviron[0] = __sav_spsytp; return(FALSE); }
+   if (__toktyp == SEMI)
+    { __venviron[0] = __sav_spsytp; goto got_semi; }
+   /* set error, if ,, form will not get here */
+   /* make it look like ,, form */
+   __set_0tab_errval();
+  }
+ __bld_xtree(0);
+ if (__has_top_mtm)
+  {
+   __pv_fwarn(653,
+    "%s timing check min:typ:max limit expression needs parentheses under 1364 - unportable",
+    __to_tcnam(__xs, ttyp));
+  }
+ *limx = __root_ndp;
+ __venviron[0] = __sav_spsytp;
+ return(TRUE);
+}
+
+/*
+ * initialize a timing check record
+ */
+extern void __init_tchk(struct tchk_t *tcp, word32 ttyp)
+{
+ tcp->tchktyp = ttyp; 
+ /* notice del rep applies to both limits if present */
+ tcp->tc_delrep = DT_CMPLST; 
+ tcp->tc_delrep2 = DT_CMPLST; 
+ tcp->tc_gone = FALSE;
+ tcp->tc_supofsuphld = FALSE;
+ tcp->tc_recofrecrem = FALSE;
+ tcp->tc_haslim2 = FALSE;
+ tcp->startedge = NOEDGE;
+ tcp->startxp = NULL;
+ tcp->tcsym = NULL;
+ tcp->startcondx = NULL;
+ tcp->chkedge = NOEDGE;
+ tcp->chkxp = NULL;
+ tcp->chkcondx = NULL;
+ /* notice this may be nil */
+ tcp->ntfy_np = NULL;
+ tcp->tclim_du.pdels = NULL;
+ tcp->tclim2_du.pdels = NULL;
+ tcp->tchknxt = NULL;
+}
+
+/*
+ * read setuphold timing check (both with 2 limits)
+ * know system task keyword read
+ */
+static int32 rd_setuphold_tchk(void)
+{
+ word32 ttyp;
+ int32 fnum, lnum;
+ struct tchk_t tmptchk;
+ struct expr_t *limx, *lim2x;
+ struct sy_t *syp, *tcsyp;
+ struct paramlst_t *pmp;
+
+ ttyp = TCHK_SETUPHOLD;
+ __init_tchk(&tmptchk, ttyp);
+ fnum = __cur_fnam_ind;
+ lnum = __lin_cnt;
+
+ if (!rd_tchk_part(ttyp, &tmptchk, &limx)) return(FALSE);
+ if (__toktyp != COMMA)
+  {
+   __pv_ferr(1267,
+    "$setuphold hold limit expression , terminator expected - %s read",
+    __prt_vtok());
+   __spec_vskipto_any(SEMI);
+   return(FALSE);
+  }
+ __get_vtok();
+ __sav_spsytp = __venviron[0];
+ __venviron[0] = __cur_spfy->spfsyms;
+ /* can be ,, or ,) empty but required */
+ if (!__col_delexpr())
+  { 
+   if (!__spec_vskipto2_any(SEMI, COMMA))
+    { __venviron[0] = __sav_spsytp; return(FALSE); }
+   if (__toktyp == SEMI)
+    {
+     __venviron[0] = __sav_spsytp;
+     __syncto_class = SYNC_SPECITEM;
+     return(FALSE);
+    }
+   /* set rhs error expr. */
+   __set_0tab_errval();
+  }
+ __bld_xtree(0);
+ if (__has_top_mtm)
+  {
+   __pv_fwarn(653,
+    "%s timing check min:typ:max 2nd limit expression needs parentheses under 1364 - unportable",
+    __to_tcnam(__xs, ttyp));
+  }
+ lim2x = __root_ndp;
+ __venviron[0] = __sav_spsytp;
+
+ /* notice can only be ID if present */
+ if (__toktyp == COMMA) { syp = rd_notifier(); __get_vtok(); }
+ else syp = NULL;
+ /* even even error end, still add since good */
+ if (__toktyp != RPAR) goto noparsemi;
+ __get_vtok();
+ if (__toktyp != SEMI)
+  {
+noparsemi:
+   __pv_ferr(1262, "$setuphold timing check does not end with ); - %s read",
+    __prt_vtok());
+   if (!__spec_vskipto_any(SEMI)) return(FALSE);
+  }
+ __cur_tchk = (struct tchk_t *) __my_malloc(sizeof(struct tchk_t));
+ *__cur_tchk = tmptchk; 
+
+ /* add the location idnentifying symbol */
+ tcsyp = __bld_loc_symbol(__tchk_num, __venviron[0], "tchk", "timing check");
+ tcsyp->sytyp = SYM_TCHK;
+ tcsyp->syfnam_ind = fnum;
+ tcsyp->sylin_cnt = lnum;
+ __cur_tchk->tcsym = tcsyp;
+ tcsyp->el.etcp = __cur_tchk;
+ __tchk_num++;
+ __cur_tchk->ntfy_np = (struct net_t *) syp;
+ pmp = __alloc_pval();
+ pmp->plxndp = limx;
+ pmp->pmlnxt = NULL;
+ __cur_tchk->tclim_du.pdels = pmp;
+ pmp = __alloc_pval();
+ pmp->plxndp = lim2x;
+ pmp->pmlnxt = NULL;
+ __cur_tchk->tclim2_du.pdels = pmp;
+ __cur_tchk->tc_haslim2 = TRUE;
+ return(TRUE);
+}
+
+/*
+ * read recrem timing check (both with 2 limits)
+ * know system task keyword read
+ *
+ * SJM 01/16/04 - almost same as setup hold but 2001 LRM has extra stuff
+ * that is not yet added
+ */
+static int32 rd_recrem_tchk(void)
+{
+ word32 ttyp;
+ int32 fnum, lnum;
+ struct tchk_t tmptchk;
+ struct expr_t *limx, *lim2x;
+ struct sy_t *syp, *tcsyp;
+ struct paramlst_t *pmp;
+ char s1[RECLEN];
+
+ ttyp = TCHK_RECREM;
+ __init_tchk(&tmptchk, ttyp);
+ fnum = __cur_fnam_ind;
+ lnum = __lin_cnt;
+
+ if (!rd_tchk_part(ttyp, &tmptchk, &limx)) return(FALSE);
+
+ /* for recrem both terminals must be edges */ 
+ if (tmptchk.startedge == NOEDGE)
+  {
+   __pv_ferr(1260,
+   "%s timing check first recovery reference event missing required edge",
+   __to_tcnam(s1, ttyp));
+  }
+ if (tmptchk.chkedge == NOEDGE)
+  {
+   __pv_ferr(1260,
+    "%s timing 2nd removal reference event missing required edge",
+   __to_tcnam(s1, ttyp));
+  }
+
+ if (__toktyp != COMMA)
+  {
+   __pv_ferr(1267,
+    "$recrem removal limit expression , terminator expected - %s read",
+    __prt_vtok());
+   __spec_vskipto_any(SEMI);
+   return(FALSE);
+  }
+ __get_vtok();
+ __sav_spsytp = __venviron[0];
+ __venviron[0] = __cur_spfy->spfsyms;
+ /* can be ,, or ,) empty but required */
+ if (!__col_delexpr())
+  { 
+   if (!__spec_vskipto2_any(SEMI, COMMA))
+    { __venviron[0] = __sav_spsytp; return(FALSE); }
+   if (__toktyp == SEMI)
+    {
+     __venviron[0] = __sav_spsytp;
+     __syncto_class = SYNC_SPECITEM;
+     return(FALSE);
+    }
+   /* set rhs error expr. */
+   __set_0tab_errval();
+  }
+ __bld_xtree(0);
+ if (__has_top_mtm)
+  {
+   __pv_fwarn(653,
+    "%s timing check min:typ:max 2nd limit expression needs parentheses under 1364 - unportable",
+    __to_tcnam(__xs, ttyp));
+  }
+ lim2x = __root_ndp;
+ __venviron[0] = __sav_spsytp;
+
+ /* notice can only be ID if present */
+ if (__toktyp == COMMA) { syp = rd_notifier(); __get_vtok(); }
+ else syp = NULL;
+ /* even even error end, still add since good */
+ if (__toktyp != RPAR) goto noparsemi;
+ __get_vtok();
+ if (__toktyp != SEMI)
+  {
+noparsemi:
+   __pv_ferr(1262, "$setuphold timing check does not end with ); - %s read",
+    __prt_vtok());
+   if (!__spec_vskipto_any(SEMI)) return(FALSE);
+  }
+ __cur_tchk = (struct tchk_t *) __my_malloc(sizeof(struct tchk_t));
+ *__cur_tchk = tmptchk; 
+
+ /* add the location idnentifying symbol */
+ tcsyp = __bld_loc_symbol(__tchk_num, __venviron[0], "tchk", "timing check");
+ tcsyp->sytyp = SYM_TCHK;
+ tcsyp->syfnam_ind = fnum;
+ tcsyp->sylin_cnt = lnum;
+ __cur_tchk->tcsym = tcsyp;
+ tcsyp->el.etcp = __cur_tchk;
+ __tchk_num++;
+ __cur_tchk->ntfy_np = (struct net_t *) syp;
+ pmp = __alloc_pval();
+ pmp->plxndp = limx;
+ pmp->pmlnxt = NULL;
+ __cur_tchk->tclim_du.pdels = pmp;
+ pmp = __alloc_pval();
+ pmp->plxndp = lim2x;
+ pmp->pmlnxt = NULL;
+ __cur_tchk->tclim2_du.pdels = pmp;
+ __cur_tchk->tc_haslim2 = TRUE;
+ return(TRUE);
+}
+
+/*
+ * read width timing check
+ * know system task keyword read
+ * width has 2 limits (but 2nd can be omitted), period has 1
+ */
+static int32 rd_width_tchk(void)
+{
+ word32 ttyp;
+ int32 fnum, lnum;
+ struct tchk_t tmptchk;
+ struct expr_t *limx, *lim2x;
+ struct sy_t *syp, *tcsyp;
+ struct paramlst_t *pmp;
+
+ ttyp = TCHK_WIDTH;
+ __init_tchk(&tmptchk, ttyp);
+
+ fnum = __cur_fnam_ind;
+ lnum = __lin_cnt;
+
+ if (!rd_tchk_part(ttyp, &tmptchk, &limx)) return(FALSE);
+ if (tmptchk.startedge != E_NEGEDGE && tmptchk.startedge != E_POSEDGE)
+  __pv_ferr(1266,
+   "$width timing check event missing required negedge or posedge"); 
+ /* 2nd limit optional and becomes NULL */
+ if (__toktyp == RPAR) { syp = NULL; lim2x = NULL; goto done; }
+ if (__toktyp != COMMA)
+  {
+   __pv_ferr(1268,
+    "$width first limit expression , terminator expected - %s read",
+    __prt_vtok());
+   __spec_vskipto_any(SEMI);
+   return(FALSE);
+  }
+ __get_vtok();
+ __sav_spsytp = __venviron[0];
+ __venviron[0] = __cur_spfy->spfsyms;
+ /* lrm says no ,, or ,) forms for width */
+ /* since ignored by sim value of 0 ok place holder and just ignored */
+ if (!__col_delexpr())
+  { 
+   if (!__spec_vskipto2_any(SEMI, COMMA))
+    { __venviron[0] = __sav_spsytp; return(FALSE); }
+   if (__toktyp == SEMI)
+    {
+     __venviron[0] = __sav_spsytp;
+     __syncto_class = SYNC_SPECITEM;
+     return(FALSE);
+    }
+   /* make it look like ,, form */
+   __set_0tab_errval();
+  }
+ __bld_xtree(0);
+ lim2x = __root_ndp;
+ __venviron[0] = __sav_spsytp;
+
+ /* notice can only be ID and may be omited */
+ if (__toktyp == COMMA) { syp = rd_notifier(); __get_vtok(); }
+ else syp = NULL;
+ /* even even error end, still add since good */
+ if (__toktyp != RPAR) goto noparsemi;
+done:
+ __get_vtok();
+ if (__toktyp != SEMI)
+  {
+noparsemi:
+   __pv_ferr(1263, "$width timing check does not end with ); - %s read",
+    __prt_vtok());
+   if (!__spec_vskipto_any(SEMI)) return(FALSE);
+  }
+
+ /* notice no data even here */
+ __cur_tchk = (struct tchk_t *) __my_malloc(sizeof(struct tchk_t));
+ *__cur_tchk = tmptchk; 
+
+ /* add the location idnentifying symbol */
+ tcsyp = __bld_loc_symbol(__tchk_num, __venviron[0], "tchk", "timing check");
+ tcsyp->sytyp = SYM_TCHK;
+ tcsyp->syfnam_ind = fnum;
+ tcsyp->sylin_cnt = lnum;
+ tcsyp->sydecl = TRUE;
+ __cur_tchk->tcsym = tcsyp;
+ tcsyp->el.etcp = __cur_tchk;
+ __tchk_num++;
+
+ __cur_tchk->ntfy_np = (struct net_t *) syp;
+ pmp = __alloc_pval();
+ pmp->plxndp = limx;
+ pmp->pmlnxt = NULL;
+ __cur_tchk->tclim_du.pdels = pmp;
+ /* always build 2nd limit as 0 if missing (during fix) so present */
+ __cur_tchk->tc_haslim2 = TRUE;
+ /* notice missing 2nd limit ok since only timing verifier threshold */
+ /* that stops errors if pulse less than threshold */ 
+ if (lim2x == NULL) lim2x = __bld_rng_numxpr(0L, 0L, WBITS);
+ pmp = __alloc_pval();
+ pmp->plxndp = lim2x;
+ pmp->pmlnxt = NULL;
+ __cur_tchk->tclim2_du.pdels = pmp;
+ return(TRUE);
+}
+
+/*
+ * read period timing check
+ * know system task keyword read
+ * period has 1 limit (required), width has 2
+ */
+static int32 rd_period_tchk(void)
+{
+ word32 ttyp;
+ int32 fnum, lnum;
+ struct tchk_t tmptchk;
+ struct expr_t *limx;
+ struct sy_t *syp, *tcsyp;
+ struct paramlst_t *pmp;
+
+ ttyp = TCHK_PERIOD;
+ __init_tchk(&tmptchk, ttyp);
+
+ fnum = __cur_fnam_ind;
+ lnum = __lin_cnt;
+
+ if (!rd_tchk_part(ttyp, &tmptchk, &limx)) return(FALSE);
+ if (tmptchk.startedge == NOEDGE)
+  __pv_ferr(1269, "$period timing check event missing required edge"); 
+ /* notice can only be ID if present */
+ if (__toktyp == COMMA) { syp = rd_notifier(); __get_vtok(); }
+ else syp = NULL;
+ /* even even error end, still add since good */
+ if (__toktyp != RPAR) goto noparsemi;
+ __get_vtok();
+ if (__toktyp != SEMI)
+  {
+noparsemi:
+   __pv_ferr(1264, "$period timing check does not end with ); - %s read",
+    __prt_vtok());
+   if (!__spec_vskipto_any(SEMI)) return(FALSE);
+  }
+ __cur_tchk = (struct tchk_t *) __my_malloc(sizeof(struct tchk_t));
+ *__cur_tchk = tmptchk; 
+
+ /* add the location idnentifying symbol */
+ tcsyp = __bld_loc_symbol(__tchk_num, __venviron[0], "tchk", "timing check");
+ tcsyp->sytyp = SYM_TCHK;
+ tcsyp->syfnam_ind = fnum;
+ tcsyp->sylin_cnt = lnum;
+ tcsyp->sydecl = TRUE;
+ __cur_tchk->tcsym = tcsyp;
+ tcsyp->el.etcp = __cur_tchk;
+ __tchk_num++;
+
+ __cur_tchk->ntfy_np = (struct net_t *) syp;
+ pmp = __alloc_pval();
+ pmp->plxndp = limx;
+ pmp->pmlnxt = NULL;
+ __cur_tchk->tclim_du.pdels = pmp;
+ return(TRUE);
+}
+
+/*
+ * read skew or recovery timing check
+ * know system task keyword read
+ * different timing checks have identical arguments
+ *
+ * SJM 01/16/04 - added removal first terminal is the ref events that
+ * needs to be an edge for both
+ */
+static int32 rd_skew_recov_rem_tchk(word32 ttyp)
+{
+ int32 fnum, lnum;
+ struct tchk_t tmptchk;
+ struct expr_t *limx;
+ struct sy_t *syp, *tcsyp;
+ struct paramlst_t *pmp;
+ char s1[RECLEN];
+
+ __init_tchk(&tmptchk, ttyp);
+ /* must save location since, need system task line as tchk loc. */
+ fnum = __cur_fnam_ind;
+ lnum = __lin_cnt;
+ if (!rd_tchk_part(ttyp, &tmptchk, &limx)) return(FALSE);
+ if (ttyp == TCHK_RECOVERY || ttyp == TCHK_REMOVAL)
+  {
+   if (tmptchk.startedge == NOEDGE)
+    __pv_ferr(1260,
+     "%s timing check first reference event missing required edge",
+     __to_tcnam(s1, ttyp));
+  }
+
+ /* notice can only be ID if present */
+ if (__toktyp == COMMA) { syp = rd_notifier(); __get_vtok(); }
+ else syp = NULL;
+ /* even even error end, still add since good */
+ if (__toktyp != RPAR) goto noparsemi;
+ __get_vtok();
+ if (__toktyp != SEMI)
+  {
+noparsemi:
+   __pv_ferr(1265, "%s timing check does not end with ); - %s read",
+    __to_tcnam(s1, ttyp), __prt_vtok());
+   if (!__spec_vskipto_any(SEMI)) return(FALSE);
+  }
+ __cur_tchk = (struct tchk_t *) __my_malloc(sizeof(struct tchk_t));
+ *__cur_tchk = tmptchk; 
+
+ /* add the location identifying symbol */
+ tcsyp = __bld_loc_symbol(__tchk_num, __venviron[0], "tchk", "timing check");
+ tcsyp->sytyp = SYM_TCHK;
+ tcsyp->syfnam_ind = fnum;
+ tcsyp->sylin_cnt = lnum;
+ tcsyp->sydecl = TRUE;
+ __cur_tchk->tcsym = tcsyp;
+ tcsyp->el.etcp = __cur_tchk;
+ __tchk_num++;
+
+ __cur_tchk->ntfy_np = (struct net_t *) syp;
+ pmp = __alloc_pval(); pmp->plxndp = limx; pmp->pmlnxt = NULL;
+ __cur_tchk->tclim_du.pdels = pmp;
+ return(TRUE);
+}
+
+/*
+ * must correctly parse $nochange but ignore with warning
+ * this does not build and data structure
+ */
+static int32 rd_nochg_tchk(void)
+{
+ word32 ttyp;
+ struct tchk_t tmptchk;
+ struct expr_t *limx;
+ char s1[RECLEN];
+
+ ttyp = TCHK_NOCHANGE;
+ __init_tchk(&tmptchk, ttyp);
+ /* this reads the first limit but not second */
+ if (!rd_tchk_part(ttyp, &tmptchk, &limx)) return(FALSE);
+ if (tmptchk.startedge != E_NEGEDGE && tmptchk.startedge != E_POSEDGE)
+  __pv_ferr(1271,
+   "$nochange timing check first reference event missing negedge or posedge"); 
+ __free_xtree(limx);
+ __free_xtree(tmptchk.startxp);
+ __free_xtree(tmptchk.startcondx);
+ __free_xtree(tmptchk.chkxp);
+ __free_xtree(tmptchk.chkcondx);
+
+ if (__toktyp != COMMA)
+  {
+   __pv_ferr(1272,
+    "$nochange second event - comma expected - %s read", __prt_vtok());
+   __spec_vskipto_any(SEMI);
+   return(FALSE);
+  }
+ __get_vtok();
+ __sav_spsytp = __venviron[0];
+ __venviron[0] = __cur_spfy->spfsyms;
+ /* lrm says no ,, or ,) forms for nochange */
+ if (!__col_delexpr())
+  { 
+   if (!__spec_vskipto2_any(SEMI, COMMA))
+    { __venviron[0] = __sav_spsytp; return(FALSE); }
+   if (__toktyp == SEMI)
+    {
+     __venviron[0] = __sav_spsytp;
+     __syncto_class = SYNC_SPECITEM;
+     return(FALSE);
+    }
+   /* make it look like ,, form */
+   __set_0tab_errval();
+  }
+ /* this is needed for checking */
+ __bld_xtree(0);
+ __free_xtree(__root_ndp);
+ __venviron[0] = __sav_spsytp;
+ /* even even error end, still add since good */
+ if (__toktyp != RPAR) goto noparsemi;
+
+ __get_vtok();
+ if (__toktyp != SEMI)
+  {
+noparsemi:
+   __pv_ferr(1273, "%s timing check does not end with ); - %s read",
+    __to_tcnam(s1, ttyp), __prt_vtok());
+   if (!__spec_vskipto_any(SEMI)) return(FALSE);
+  }
+ __pv_fwarn(599, "$nochange timing check has no effect in simulation");
+ return(TRUE);
+}
+
+/*
+ * read a timing check event - know always followed by , 
+ * know 1st token read and reads ending ,
+ * returns NULL on error, caller must skip to ;
+ * caller syncs - returns NULL if syntax error (will need syncing)
+ */
+static int32 rd_tchk_selector(int32 *edgval, struct expr_t **xp,
+ struct expr_t **condx)
+{
+ *edgval = NOEDGE;
+ switch ((byte) __toktyp) {  
+  case NEGEDGE: *edgval = E_NEGEDGE; break; 
+  case POSEDGE: *edgval = E_POSEDGE; break; 
+  case EDGE:
+   __get_vtok();
+   if (__toktyp != LSB) 
+    {
+     __pv_ferr(1281, "timing check event edge list [ expected - %s read",
+      __prt_vtok());
+edge_sync:
+     /* caller must synchronize - except try for enclosing ] */
+     if (!__spec_vskipto_any(RSB)) return(FALSE);
+     goto get_pthx;
+    }
+   if (!rd_edges(edgval)) goto edge_sync;
+   break;
+  default: goto no_edge;
+ }
+
+get_pthx:
+ __get_vtok();
+no_edge:
+ if (!col_pthexpr()) return(FALSE);
+ __bld_xtree(0);
+ *xp = __root_ndp;
+ if (__toktyp != COMMA)
+  {
+   if (__toktyp != TCHKEVAND)
+    {
+     __pv_ferr(1282,
+      "timing check data or reference event, comma or &&& expected - %s read",
+      __prt_vtok());
+     return(FALSE);
+    }
+   /* read &&& expr. */
+   __get_vtok();
+   if (!__col_connexpr(-1)) return(FALSE);
+   if (__toktyp != COMMA)
+    {
+     __pv_ferr(1283,
+      "timing check event &&& expression comma expected - %s read",
+      __prt_vtok());
+     return(FALSE);
+    }
+   __bld_xtree(0);
+   *condx = __root_ndp;
+  }
+ else *condx = NULL;
+ return(TRUE);
+}
+
+/*
+ * read an edge list
+ * know [ read and reads trailing ]
+ * if error tries to sync to , ], ), ;
+ */
+static int32 rd_edges(int32 *edge)
+{
+ char s1[RECLEN];
+ byte etmp, e1;
+
+ *edge = etmp = NOEDGE;
+ __letendnum_state = TRUE;
+ for (;;)
+  {
+   strcpy(s1, "");
+   for (;;)
+    {
+     __get_vtok();
+     switch ((byte) __toktyp) {
+      case COMMA: case RSB: goto got_pair;
+      case ID: strcat(s1, __token); break;
+      case NUMBER: strcat(s1, __numtoken); break;
+      default:
+       __pv_ferr(1284, "edge list edge value pair expected - %s read",
+        __prt_vtok());
+       __letendnum_state = FALSE;
+       return(FALSE);
+      }
+    }
+got_pair:
+   if (strlen(s1) > 2)
+    {
+bad_edge:
+     __pv_ferr(1286, "edge list element %s illegal", s1);
+     continue;
+    }
+   switch (s1[0]) {
+    case '0':
+     if (s1[1] == '1') e1 = EDGE01;
+     else if (s1[1] == 'x') e1 = EDGE0X;
+     else goto bad_edge;
+     break;
+    case '1':
+     if (s1[1] == '0') e1 = EDGE10;
+     else if (s1[1] == 'x') e1 = EDGE1X;
+     else goto bad_edge;
+     break;
+    case 'x':
+     if (s1[1] == '0') e1 = EDGEX0;
+     else if (s1[1] == '1') e1 = EDGEX1;
+     else goto bad_edge;
+     break;
+    default: goto bad_edge;
+   }
+   if ((etmp & e1) != 0)
+    __pv_fwarn(577, "edge %s repeated in edge list", s1);
+   else etmp |= e1;
+   /* notice last edge will be vv with __toktyp of ] - must proces last */
+   if (__toktyp == RSB) break;
+  }
+ __letendnum_state = FALSE;
+ *edge = etmp;
+ return(TRUE);
+}
+
+/*
+ * read an notifier 
+ * know leading , read and reads just the notifier reg
+ */
+static struct sy_t *rd_notifier(void) 
+{ 
+ struct sy_t *syp;
+
+ __get_vtok();
+ if (__toktyp != ID)
+  {
+bad_notfy:
+   __pv_ferr(1285, "notifier register name expected - %s read",
+    __prt_kywrd_vtok());
+   return(NULL);
+  } 
+ /* this declares thing as a net - fixed later and checked even later */
+ __last_xtk = -1;
+ /* FIXME - since can never fail should change to arg terr */
+ if (!__bld_expnode()) goto bad_notfy;
+ __bld_xtree(0);
+ syp = __root_ndp->lu.sy;
+ /* type will be checked later */
+ return(syp);
+}
+
+/*
+ * ROUTINES TO PROCESS `language INCLUDE CONSTRUCT
+ */
+
+extern char __pv_ctab[];
+
+/*
+ * read lines after language up to `endlanguage
+ *
+ * know first token of line read and it is `language
+ * reads through `endlanguage
+ *
+ * both `language and `endlanguage lines passed to call back if registered
+ */
+extern void __do_foreign_lang(void)
+{
+ register char *chp, *chp2;
+ int32 first_time, done, savfnam_ind, sav_lin_cnt;
+
+ if (!__rding_top_level || __rescanning_lib)
+  {
+   if (!__rescanning_lib)
+    {
+     __pv_ferr(2657,
+      "`language compiler directive inside Verilog construct - skipping to `endlanguage");
+    }
+   savfnam_ind = __cur_fnam_ind;
+   sav_lin_cnt = __lin_cnt;
+   if (__notokenize_skiplines("`endlanguage") == TEOF)
+    {
+     __pv_terr(327,
+      "skipped `language line %s no matching `endlanguage before **EOF**",
+      __bld_lineloc(__xs, (word32) savfnam_ind, sav_lin_cnt));  
+    }
+   if (__langstr != NULL) strcpy(__langstr, "");
+   return;
+  }
+ if (__lib_verbose || __verbose)
+  {
+   __cv_msg("  Processing `language directive at **%s(%d)\n", 
+    __in_fils[__cur_fnam_ind], __lin_cnt);
+  }
+ __total_lang_dirs++;
+ if (__iact_state)
+  {
+   __ia_err(1401,
+    "`language compiler directive illegal in interactive commands");
+   __skipover_line();
+   if (__langstr != NULL) strcpy(__langstr, "");
+   return; 
+  }
+ if (__langstr == NULL) __langstr = __my_malloc(IDLEN + 1);
+
+ __doing_langdir = TRUE;
+ for (first_time = TRUE, done = FALSE;;)
+  {
+rd_again:
+   chp = __langstr;
+   /* this does not move line count to next line - code here must */
+   if (__my_getlin(__langstr) == EOF) 
+    {
+     /* first try to pop some sort of outer nested thing */
+     if (__pop_vifstk()) goto rd_again;
+     /* next try to replace just finished 0th element with new input file */
+     if (__cur_infi + 1 > __last_inf) goto eof_error;
+     __cur_infi++; 
+     if (!__open_sfil()) goto eof_error;
+     /* know first token of file flag now on */
+     __file_just_op = FALSE;
+     __first_num_eol = TRUE; 
+     goto rd_again;
+
+eof_error:
+     __pv_ferr(2657,
+      "while processing foreign `language section **EOF** read before `endlanguage");
+     if (first_time)
+      {
+       if (__langstr != NULL) strcpy(__langstr, "");
+       __doing_langdir = FALSE;
+       return;
+      }
+
+     strcpy(__langstr, "`endlanguage");
+     __langstr[12] = '\n';
+     __langstr[13] = '\0';
+     done = TRUE;
+     goto try_callback;
+    }
+   if (first_time)
+    {
+     char s1[IDLEN];
+
+     if (strlen(__langstr) + 11 >= IDLEN)
+      {
+       __pv_ferr(2679,
+        "`language section line too long (%d) - truncated", IDLEN - 1);
+      }
+     strcpy(s1, __langstr);
+     strcpy(__langstr, "`language");
+     if (s1[0] != ' ' && s1[0] != '\t') strcat(__langstr, " ");
+     strcat(__langstr, s1);
+     first_time = FALSE;
+    }
+   else
+    {
+     if ((chp = __match_cdir(__langstr, "`endlanguage")) != NULL) 
+      done = TRUE;
+     else if ((chp = __match_cdir(__langstr, "`include")) != NULL) 
+      {
+       chp2 = &(chp[8]);  
+       while (vis_white_(*chp2)) chp2++;
+       strcpy(__macwrkstr, chp2);
+       /* correct for right line because line getting moves to next line */
+       __do_include();
+       __lin_cnt++;
+       __total_rd_lines++;
+       /* no need to set beginning of lne because new file just opened */
+       goto rd_again;
+      } 
+     else chp = __langstr;
+    }
+
+try_callback:
+   /* execute call back if any registered - if none just returns */
+   /* by passing chp, know for `langauge/`endlanguage no leading whie space */
+   __exec_vpi_langlinecbs(chp, __in_fils[__cur_fnam_ind], __lin_cnt);
+   __lin_cnt++;
+   __total_rd_lines++;
+   /* this set first token on line using 2 step flag needed for push back */
+   __first_num_eol = TRUE;
+   if (done)
+    {
+     strcpy(__langstr, "");
+     __doing_langdir = FALSE;
+     return;
+    }
+  }
+}
+
+/*
+ * routine to skip over lines to keyword (usually `endlanguage)
+ *
+ * special routine that can not tokenize since probably non Verilog
+ * returns last character read on success else EOF on error of EOF
+ *
+ * this must read and expand `include files because `endlanguage can be
+ * in included file
+ */
+extern int32 __notokenize_skiplines(char *match_prefix)
+{
+ if (__langstr == NULL) __langstr = __my_malloc(IDLEN + 1);
+ for (;;)
+  {
+   if (__my_getlin(__langstr) == EOF)
+    {
+     /* first try to pop some sort of outer nested thing */
+     /* this sets line number to right outer line and no line here */
+     if (__pop_vifstk()) continue;
+
+     /* next try to replace just finished 0th element with new input file */
+     if (__cur_infi + 1 > __last_inf) goto eof_error;
+     __cur_infi++; 
+     if (!__open_sfil()) goto eof_error;
+     /* know first token of file flag now on */
+     __file_just_op = FALSE;
+     /* this set first token on line using 2 step flag needed for push back */
+     __first_num_eol = TRUE; 
+     continue;
+
+eof_error:
+     __pv_ferr(2657,
+      "while processing foreign `language section **EOF** read before `endlanguage");
+     return(TEOF);
+    }
+
+   if (__match_cdir(__langstr, match_prefix) != NULL)
+    {
+     __lin_cnt++;
+     __total_rd_lines++;
+     /* this set first token on line using 2 step flag needed for push back */
+     __first_num_eol = TRUE;
+     break;
+    }
+   /* becausing section ifdefed out, just ignore include */
+   __lin_cnt++;
+   __total_rd_lines++;
+   /* this set first token on line using 2 step flag needed for push back */
+   __first_num_eol = TRUE;
+  }
+ return(UNDEF);
+}
+
+/*
+ * match a directive prefix (may be leading white space) 
+ * returns char ptr to first character of matched if matched
+ * else returns nil if no match
+ */
+extern char *__match_cdir(char *lp, char *match_prefix)
+{
+ register char *chp;
+ int32 slen;
+
+ /* possible lang str not yet allocated */ 
+ if (lp == NULL) return(NULL);
+ slen = strlen(match_prefix);
+ for (chp = __langstr;; chp++) { if (!vis_nonnl_white_(*chp)) break; }
+ if (strncmp(chp, match_prefix, slen) == 0) return(chp); 
+ return(NULL);
+}
+
+/*
+ * execute vpi_control vpiInsertSource operation
+ *
+ * know in `endlanguage line callback or will not get here 
+ *
+ * BEWARE - this works because no longjmp in source reading
+ */
+extern int32 __exec_rdinserted_src(char *buf)
+{
+ register int32 vi;
+ int32 sav_ecnt, retv, sav_vin_top, sav_lincnt, sav_cur_fnamind, len;
+ struct vinstk_t **sav_vinstk;
+
+ /* save lin_cnt to restore after buffer parsed */ 
+ sav_lincnt = __lin_cnt; 
+ sav_cur_fnamind = __cur_fnam_ind;
+
+ sav_ecnt = __pv_err_cnt;
+ /* save the nested open file stack */
+ sav_vinstk = (struct vinstk_t **)
+  __my_malloc((__vin_top + 1)*sizeof(struct vinstk_t *));
+ /* this moves the ptrs to be pointed to by same */
+ for (vi = 0; vi <= __vin_top; vi++)
+  {
+   sav_vinstk[vi] = __vinstk[vi]; 
+   __vinstk[vi] = NULL;
+  }
+ sav_vin_top = __vin_top;
+ __vin_top = -1;
+
+ /* push string on top (only one now on) of read stack */
+ __push_vinfil();
+ __visp = __vinstk[__vin_top];
+ __visp->vichp = __visp->vichp_beg = buf;
+ len = strlen(buf);
+ __visp->vichplen = len;
+ __in_s = NULL;
+
+ for (;;)
+  {
+   __get_vtok();
+   if (__toktyp == TEOF) break;
+   __rding_top_level = FALSE;
+   __rd_ver_mod();
+   __rding_top_level = TRUE;
+   if (__toktyp == TEOF) break;
+  }
+ /* restore the nested open file stack */
+ /* first free any allocated vin stk records from includes */
+ for (vi = 0; vi < MAXFILNEST; vi++)
+  {
+   if (__vinstk[vi] != NULL)
+    {
+     __my_free((char *) __vinstk[vi], sizeof(struct vinstk_t));
+     __vinstk[vi] = NULL;
+    }
+  }
+ /* next copy back and restore */
+ for (vi = 0; vi <= sav_vin_top; vi++) __vinstk[vi] = sav_vinstk[vi];
+ __lin_cnt = sav_lincnt;
+ __cur_fnam_ind = sav_cur_fnamind;
+ __vin_top = sav_vin_top;
+ __visp = __vinstk[__vin_top];
+ __in_s = __visp->vi_s;
+
+ /* LOOKATME - why is this needed */
+ __toktyp = UNDEF;
+ __lasttoktyp = UNDEF;
+
+ if (__pv_err_cnt > sav_ecnt) retv = FALSE; else retv = TRUE;
+ return(retv);
+}
+
+/*
+ * VERILOG 2001 ATTRIBUTE READING ROUTINES
+ */
+
+/*
+ * read, parse and build attribute list from attribute string
+ * builds list and returns header of list or nil on error
+ *
+ * new verilog 2000 feature
+ * know string between (* and *) stored on entry in attr name field
+ * trick is to push string onto file stack as if it is no arg macro 
+ *
+ * expression value converted to constant number here because
+ * attributes need to be used by tools that do not know pound param vals
+ * i.e. can be fed, post generate source
+ */
+extern struct attr_t *__rd_parse_attribute(struct attr_t *rd_attrp)
+{
+ register char *chp; 
+ int32 sav_ecnt, sav_tot_lines, sav_fnam_ind, attllen;
+ struct attr_t *attrp, *attr_hd, *last_attrp;
+ char *attlin, attnam[IDLEN];
+
+ attrp = attr_hd = last_attrp = NULL;
+ attlin = rd_attrp->attrnam;
+ /* SJM 07/30/01 - need to read chars and parse out of global */
+ /* needed so can free work attrnam after rec built */ 
+ if ((attllen = strlen(attlin)) >= __attrparsestrlen - 1)
+  {
+   __attrparsestr = __my_realloc((char *) __attrparsestr, __attrparsestrlen,
+    attllen + 1);
+   __attrparsestrlen = attllen + 1;
+  }
+ strcpy(__attrparsestr, attlin); 
+
+ /* need to save total lines read since counted in attr when collected */
+ /* parsing here counts lines because new lines not escaped */
+ sav_tot_lines = __total_rd_lines;
+ sav_fnam_ind = __cur_fnam_ind;
+ sav_ecnt = __pv_err_cnt;
+
+ /* if currently reading file, must preserve line count */
+ if (__visp->vi_s != NULL) __visp->vilin_cnt = __lin_cnt;
+ /* push string on top of read stack */
+ __push_vinfil();
+ __visp->vichp = __visp->vichp_beg = __attrparsestr;
+
+ /* make sure not freeing line even if somehow hit eof - never should */
+ __visp->vichplen = -1;
+ __in_s = NULL;
+ /* DBG remove --- */
+ if (__debug_flg) __dbg_msg("parsing attribute string %s\n", attlin);
+ /* --- */
+
+ __cur_fnam_ind = rd_attrp->attr_fnind;
+ __lin_cnt = rd_attrp->attrlin_cnt;
+
+ __get_vtok();
+ /* ; added to end of saved attribute string if not there */
+ if (__toktyp == SEMI) 
+  {
+   __pv_ferr(3405,
+    "attribute_instance illegal - at least one attr_spec required");
+chk_eol: 
+   for (chp = __visp->vichp; *chp != '\0'; chp++)
+    {
+     if (!vis_white_(*chp))
+      {
+       __pv_ferr(3407,
+        "attribute_instance comma separator expected - semicolon read");
+       /* on error always skip to end of string - need EOF next read */
+       while (*chp != '\0') chp++;
+       goto done;
+      }
+    }
+   goto done;
+  }
+ for (;;)
+  {
+   if (__toktyp != ID)
+    {
+     __pv_ferr(3404, "attribute name expected - %s read", __prt_vtok());
+err_skip_eol:
+     /* on error always skip to end of string - need EOF next read */
+     for (chp = __visp->vichp; *chp != '\0'; chp++) ;
+     goto done;
+    }
+   strcpy(attnam, __token);
+   __get_vtok();
+   __root_ndp = NULL; 
+   if (__toktyp == EQ)
+    {
+     __get_vtok();
+     /* LOOKATME - should try to resync on errors */
+     __last_xtk = -1;
+     /* on success (T), this reads either , or ; */
+     if (!__col_comsemi(-1)) goto err_skip_eol;
+     __bld_xtree(0);
+     if (__expr_has_glb(__root_ndp) || !__src_rd_chk_paramexpr(__root_ndp, 0))
+      {
+       __pv_ferr(3404,
+        "attr_spec for attribute %s expression error - defined parameters and constants only", 
+        attnam); 
+       /* need to still add value of x to prevent further errors */
+       __free2_xtree(__root_ndp);
+       __root_ndp->szu.xclen = WBITS;
+       /* default value is on 1 (non zero) */
+       __set_numval(__root_ndp, 1, 0, WBITS);  
+      }
+     else
+      {
+       /* because of previous check, this can not fail */
+       __eval_param_rhs_tonum(__root_ndp);
+      }
+    }
+   else __root_ndp = NULL;
+
+   /* allocate in link in attribute */
+   attrp = (struct attr_t *) __my_malloc(sizeof(struct attr_t));
+   attrp->attr_tok = rd_attrp->attr_tok;
+   attrp->attrnam = __pv_stralloc(attnam); 
+   /* must eval. after all param setting is done */
+   attrp->attr_xp = __root_ndp; 
+   /* LOOKATME - think should just use attr inst loc */
+   attrp->attr_fnind = __cur_fnam_ind;
+   attrp->attrlin_cnt = __lin_cnt;
+   attrp->attrnxt = NULL;
+   if (last_attrp == NULL) attr_hd = attrp; else last_attrp->attrnxt = attrp;
+   last_attrp = attrp;
+
+   if (__toktyp == SEMI) goto chk_eol;
+   if (__toktyp != COMMA)
+    {
+     __pv_ferr(3406, "attr_spec separator or end \"*)\" expected - %s read",
+      __prt_vtok());
+     goto err_skip_eol;
+    }
+   __get_vtok();
+   continue;
+  }
+
+done:
+ /* caller must free attribute string when pased for all instances */
+
+ /* restore total lines read */
+ __total_rd_lines = sav_tot_lines;
+ __cur_fnam_ind = sav_fnam_ind;
+ /* SJM 07/30/01 - was using visp but that was not set or index */
+ __cur_fnam = __in_fils[__cur_fnam_ind];
+ /* small memory leak if syntax error */
+ if (__pv_err_cnt > sav_ecnt) return(NULL);
+ /* emit warnings if attr duplicated with different value - inform if same */
+ if (attr_hd != NULL) attr_hd = chk_dup_attrs(attr_hd);
+ return(attr_hd);
+}
+
+/*
+ * check attribute list for duplicates
+ * if duplicate remove - if different value warn if same value inform
+ * 
+ * LOOKATME - if lots of attributes need to sort and match
+ */
+static struct attr_t *chk_dup_attrs(struct attr_t *attr_hd)
+{
+ register struct attr_t *attrp1, *attrp2, *last_attrp1;
+ struct attr_t *new_attrhd, *attrp3;
+ char s1[RECLEN], s2[RECLEN]; 
+
+ new_attrhd = attr_hd;
+ last_attrp1 = NULL;
+ for (attrp1 = attr_hd; attrp1 != NULL;)
+  {
+   for (attrp2 = attrp1->attrnxt; attrp2 != NULL; attrp2 = attrp2->attrnxt)
+    {
+     if (strcmp(attrp1->attrnam, attrp2->attrnam) == 0) 
+      {
+       /* know both numbers but still use xpr cmp */ 
+       if (__cmp_xpr(attrp1->attr_xp, attrp2->attr_xp) == 0)
+        {
+         __gfinform(3001, attrp2->attr_fnind, attrp2->attrlin_cnt,
+          "attribute %s duplicated with same value (first at %s) - first discared",
+         attrp1->attrnam, __bld_lineloc(s1, attrp1->attr_fnind,
+         attrp1->attrlin_cnt));  
+        }
+       else
+        {
+         __gfwarn(3101, attrp2->attr_fnind, attrp2->attrlin_cnt,
+          "attribute %s value %s duplicated with different values - first at %s value %s discarded",
+         attrp1->attrnam, __msgexpr_tostr(s1, attrp2->attr_xp),
+         __bld_lineloc(__xs, attrp1->attr_fnind, attrp1->attrlin_cnt), 
+         __msgexpr_tostr(s2, attrp1->attr_xp));
+        }
+       /* SJM 10/16/00 - must set next before freeing and splicing */
+       attrp3 = attrp1->attrnxt;
+
+       /* splice out first - if more duplicates will catch later */
+       if (last_attrp1 == NULL) new_attrhd = attrp1->attrnxt; 
+       else last_attrp1->attrnxt = attrp1->attrnxt;
+       __free_xtree(attrp1->attr_xp);
+
+       __my_free((char *) attrp1, sizeof(struct attr_t));
+       /* must not advance last attr */
+       attrp1 = attrp3;
+       goto chk_nxt_attr;
+      }
+    }
+   attrp1 = attrp1->attrnxt;
+   last_attrp1 = attrp1;     
+chk_nxt_attr:;
+  }
+ return(new_attrhd);
+}
+
+/*
+ * ROUTINES TO READ CFG LIB.MAP INPUT FILE LIST
+ */
+
+/*
+ * read a cfg file - returns F on error else T
+ * reads both library mapping file and the config blocks
+ *
+ * may have list of config map library files (if none given using map.lib)
+ *
+ * if passed the command line, insrc = FALSE, and mapfile is the file name
+ * otherwise TRUE, NULL if in source
+ *
+ * SJM 11/29/03 - contrary to LRM but following NC, cfg can't appear in src
+ * but allowing list of lib.map files
+ */
+extern int32 __rd_cfg(void)
+{
+ int32 i, sav_ecnt, sav_lin_cnt;
+ FILE *fp;
+ struct mapfiles_t *mapfp;
+ char *sav_cur_fnam;
+
+ /* DBG remove -- */
+ if (__map_files_hd == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* initialize the instance clause rule binding XMR path component glb tab */
+ __siz_bind_comps = 50;
+ __bind_inam_comptab = (char **) __my_malloc(__siz_bind_comps*sizeof(char *)); 
+ __last_bind_comp_ndx = -1;
+ for (i = 0; i < __siz_bind_comps; i++) __bind_inam_comptab[i] = NULL;
+
+ /* SJM 01/15/04 - reading cfg does not use in fils buts must save as cntxt */
+ sav_lin_cnt = __lin_cnt;
+ sav_cur_fnam = __cur_fnam;
+
+ sav_ecnt = __pv_err_cnt; 
+ for (mapfp = __map_files_hd; mapfp != NULL; mapfp = mapfp->mapfnxt) 
+  {
+   /* must set cur file and line count for error messages */
+   __cur_fnam = __pv_stralloc(mapfp->mapfnam);
+   __lin_cnt = 1;
+   if ((fp = __tilde_fopen(__cur_fnam, "r")) == NULL)
+    {
+     __pv_err(3500, "cannot open config map library file %s - skipped",
+      __cur_fnam);
+     continue;
+    }
+   if (feof(fp))
+    {
+     __pv_warn(3121, "config map library file %s empty", __cur_fnam);
+     continue; 
+    }
+   rd1_cfg_file(fp);
+  }
+ /* and then put back */
+ __lin_cnt = sav_lin_cnt;
+ __cur_fnam = sav_cur_fnam;
+ 
+ if (__pv_err_cnt != sav_ecnt) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * read contents of one config file
+ */
+static void rd1_cfg_file(FILE *fp)
+{ 
+ register int32 ttyp;
+ int32 ttyp2, sav_lin_cnt;
+ FILE *incfp ;
+ char *sav_cur_fnam;
+
+ for (;;)
+  {
+   ttyp = __get_cfgtok(fp);
+   if (ttyp == CFG_INCLUDE)
+    {
+     if ((ttyp2 = __get_cfgtok(fp)) != CFG_ID)
+      {
+       __pv_ferr(3501,
+        "config map library include statement non wildcard file path name expected - %s read",
+        __to_cfgtoknam(__xs, ttyp2));
+       if (cfg_skipto_semi(ttyp2, fp) == CFG_EOF) return;  
+       continue;
+      }
+     if ((incfp = __tilde_fopen(__token, "r")) == NULL)
+      {
+       __pv_ferr(3502,
+        "cannot open config map library include file %s - skipped",
+        __token);
+       if (cfg_skipto_semi(ttyp2, fp) == CFG_EOF) return;  
+       continue;
+      }
+     if (feof(incfp))
+      {
+       __pv_warn(3121, "config map library file %s empty", __token);
+       goto skipto_semi;
+      }
+
+     /* SJM 01/15/04 - save ptr and malloc name for later err msgs */
+     sav_lin_cnt = __lin_cnt;
+     sav_cur_fnam = __cur_fnam;
+     __cur_fnam = __pv_stralloc(__token);
+     __lin_cnt = 1;
+
+     rd1_cfg_file(incfp); 
+
+     __cur_fnam = sav_cur_fnam;
+     __lin_cnt = sav_lin_cnt;
+
+skipto_semi:
+     ttyp = __get_cfgtok(fp);
+     if (ttyp != CFG_SEMI)
+      {
+       if (cfg_skipto_semi(ttyp2, fp) == CFG_EOF) return;  
+      }
+     continue;
+    }
+   if (ttyp == CFG_LIBRARY)
+    {
+     rd_cfg_library(fp);
+     continue;
+    }
+   if (ttyp == CFG_CFG) 
+    {
+     rd_cfg_cfg(fp);
+     continue;
+    }
+   if (ttyp == CFG_EOF) return;
+  }
+ /* -- DBG remove ---
+ dump_mod_info();
+ --- */ 
+}
+
+/*
+ * read a library map file library list
+ * expects library keyword to have been read and reads ending ; (or CFG_EOF)
+ *
+ * if no libraries specified and unresolved references after reading
+ * source files (either from config or from list of source files)
+ * elaboration will fail with unresolved lib refs
+ */
+static void rd_cfg_library(FILE *fp)
+{
+ int32 ttyp;
+ struct cfglib_t *lbp;
+ struct libel_t *lbep;
+
+ /* get the library name */
+ if ((ttyp =__get_cfgtok(fp)) != CFG_ID)
+  {
+   __pv_ferr(3503,
+    "library map file library description library name expected - %s read", 
+    __to_cfgtoknam(__xs, ttyp));
+   cfg_skipto_semi(ttyp, fp);
+   return;
+  }
+ lbp = (struct cfglib_t *) __my_malloc(sizeof(struct cfglib_t));
+ init_cfglib(lbp);
+ /* needed for expand error messages */
+ lbp->cfglb_fnam = __cur_fnam;
+ lbp->cfglb_lno = __lin_cnt;
+ lbp->sym_added = FALSE;
+
+ if (!chk_libid(__token))
+  { 
+   __pv_ferr(3504, "library name %s illegal simple Verilog identifier",
+    __token);
+  }
+ lbp->lbname = __pv_stralloc(__token);
+ lbep = rd_cfg_fspec_list(fp, FALSE);
+ lbp->lbels = lbep; 
+ if (__cfglib_tail == NULL) __cfglib_hd = __cfglib_tail = lbp; 
+ else
+  {
+   __cfglib_tail->lbnxt = lbp;
+   __cfglib_tail = lbp;
+  }
+}
+
+/*
+ * read a list of library file spec (wildcard) paths build and return list
+ * reads first element and reads ending EOF (for --incdir) or semi 
+ *
+ * SJM 12/11/03 - notice old config dir code was wrong - comma separated list
+ *
+ * LOOKATME - maybe should return nil on error
+ */
+static struct libel_t *rd_cfg_fspec_list(FILE *fp, int32 in_incdir)
+{
+ int32 ttyp, ttyp2, sav_lin_cnt;
+ struct libel_t *lbep, *lbep2, *lbep_hd, *last_lbep;
+ FILE *incfp;
+ char *sav_cur_fnam;
+
+ for (lbep_hd = last_lbep = NULL;;)
+  {
+   ttyp = __get_cfgtok(fp);
+   if (ttyp == CFG_SEMI || ttyp == CFG_EOF)
+    {
+     if (in_incdir)
+      {
+       if (ttyp == CFG_SEMI)
+        {
+         __pv_ferr(3507,
+          "config library description file path spec in -incdir ';' illegal");
+         cfg_skipto_eof(ttyp, fp);
+        }
+       break; 
+      }
+     if (ttyp == CFG_EOF)
+      {
+       __pv_ferr(3507,
+        "config library description file path spec in -incdir ';' illegal");
+         cfg_skipto_eof(ttyp, fp);
+       /* even if hit wrong early EOF return list build so far */
+      }
+     /* know correct sem read or error emitted */
+     break;
+    }
+
+   if (ttyp != CFG_ID)
+    {
+     __pv_ferr(3506,
+      "config library description file path spec expected - %s read",
+      __to_cfgtoknam(__xs, ttyp)); 
+
+     if ((ttyp2 = cfg_skipto_comma_semi(ttyp, fp)) == CFG_COMMA) continue;
+     if (in_incdir && ttyp2 == CFG_SEMI)
+      {
+       __pv_ferr(3507,
+        "config library description file path spec in -incdir ';' illegal");
+       cfg_skipto_eof(ttyp, fp);
+      }
+     return(NULL);
+    }
+   
+   /* -incdir [name of file contains comma separated lib list] */
+   /* can be nested */
+   /* case 1: -incdir file containg comma separated list but end with EOF */ 
+   if (strcmp(__token, "-incdir") == 0) 
+    {
+     /* read the config list from a file (comma separated) */
+     if ((ttyp2 = __get_cfgtok(fp)) != CFG_ID)
+      {
+       __pv_ferr(3501,
+        "config library description -incdir non wildcard file path name expected - %s read",
+        __to_cfgtoknam(__xs, ttyp2));
+inc_err_skip:
+       if (cfg_skipto_comma_semi(ttyp, fp) == CFG_COMMA) continue;
+       return(NULL);
+      }
+     if ((incfp = __tilde_fopen(__token, "r")) == NULL)
+      {
+       __pv_ferr(3502,
+        "cannot open config library description -incdir file %s - skipped",
+        __token);
+       goto inc_err_skip; 
+      }
+     if (feof(incfp))
+      {
+       __pv_fwarn(3121,
+        "config library description -incdir file %s empty", __token);
+       goto inc_err_skip;
+      }
+
+     /* SJM 01/15/04 - save ptr and malloc name for later err msgs */
+     sav_cur_fnam = __cur_fnam;
+     sav_lin_cnt = __lin_cnt;
+     __cur_fnam = __pv_stralloc(__token);
+     __lin_cnt = 1;
+
+     lbep = rd_cfg_fspec_list(incfp, TRUE);
+     if (lbep != NULL) 
+      {
+       /* link onto end and update last to end of new add (maybe long) list */
+       if (last_lbep == NULL) lbep_hd = lbep;
+       else last_lbep->lbenxt = lbep;
+
+       /* SJM 12/08/03 - think this is wrong ??? - need a last */
+       for (lbep2 = lbep; lbep2->lbenxt != NULL; lbep2 = lbep2->lbenxt) ; 
+       last_lbep = lbep2;
+      } 
+     __my_fclose(incfp); 
+
+     __cur_fnam = sav_cur_fnam;
+     __lin_cnt = sav_lin_cnt;
+    }
+   /* case 2: file spec - only other possibility */
+   lbep = (struct libel_t *) __my_malloc(sizeof(struct libel_t));
+   lbep->lbelsrc_rd = FALSE;
+   lbep->lbefnam = __pv_stralloc(__token);
+   lbep->lbcelndx = NULL;
+   lbep->lbel_sytab = NULL;
+   lbep->lbenxt = NULL;
+   lbep->expanded = FALSE;
+
+   if (last_lbep == NULL) lbep_hd = lbep; else last_lbep->lbenxt = lbep;
+   last_lbep = lbep;
+  }
+ return(lbep_hd);
+}
+
+/*
+ * read map library config block 
+ * know config keyword read and reads the endconfig keyword 
+ *
+ * idea is that the library lists are separate from the config blocks
+ */
+static void rd_cfg_cfg(FILE *fp)
+{
+ int32 ttyp, len, cfg_beg_lno, nbytes, expl_config;
+ struct cfgdes_t *desp, *des_hd, *des_tail;
+ struct cfg_t *cfgp;
+ struct cfgrule_t *rulp, *rule_beg, *rule_end;
+ struct cfgnamlst_t *lblp;
+ char objnam[IDLEN], libnam[IDLEN], celnam[IDLEN];
+ char cfgnam[IDLEN], s1[IDLEN], s2[IDLEN];
+
+ cfg_beg_lno = __lin_cnt;
+ /* get the config name */
+ if ((ttyp =__get_cfgtok(fp)) != CFG_ID)
+  {
+   __pv_ferr(3503, "config declaration config name expected - %s read", 
+    __to_cfgtoknam(__xs, ttyp));
+   if (cfg_skipto_semi(ttyp, fp) == CFG_EOF) return;
+   strcpy(cfgnam, "**none**");
+  }
+ else
+  { 
+   strcpy(cfgnam, __token);
+   ttyp = __get_cfgtok(fp);
+  }
+ if (ttyp != CFG_SEMI)
+  {
+   __pv_ferr(3531,
+    "config declaration config name not followed by semicolon - %s read",
+    __to_cfgtoknam(__xs, ttyp));
+   if (cfg_skipto_semi(ttyp, fp) == CFG_EOF) return;
+  }
+ /* config names may need to match cell type names so can be escaped */
+ if (!chk_libid(cfgnam))
+  {
+   if (chk_escid(cfgnam))
+    {
+     /* remove the leading escaping back slash and ending ' ' */
+     strcpy(s1, &(cfgnam[1]));
+     len = strlen(s1);
+     s1[len - 1] = '\0';
+     strcpy(cfgnam, s1);
+    }
+   else
+    {
+     __pv_ferr(3534,
+      "illegal config name %s - must be legal Verlog identifier", cfgnam);
+    }
+  }
+
+ cfgp = (struct cfg_t *) __my_malloc(sizeof(struct cfg_t));
+ init_cfg(cfgp);
+ cfgp->cfgnam = __pv_stralloc(cfgnam);
+ /* config location info for tracing and error msgs */
+ cfgp->cfg_fnam = __pv_stralloc(__cur_fnam); 
+ cfgp->cfg_lno = cfg_beg_lno;
+
+ ttyp = __get_cfgtok(fp);
+ /* config design statement must come first if used */
+ if (ttyp == CFG_DESIGN)
+  {
+   /* SJM 12/08/03 - as I read LRM, every top module needs separate config */ 
+   /* therefore only one design mod allowed - FIXME- text of LRM contradicts */
+
+   des_hd = des_tail = NULL;
+   for (;;)
+    {
+     ttyp =__get_cfgtok(fp);
+     if (ttyp == CFG_SEMI)
+      {
+       if (des_hd == NULL)
+        {
+         __pv_ferr(3532,
+          "config design statement requires at least one [lib name].[cell name]");
+        }
+       break;
+      }
+     /* get the design specifier [library].[mod name] */
+     if (ttyp != CFG_ID)
+      {
+       __pv_ferr(3533,
+        "config design statement design specifier expected - %s read", 
+        __to_cfgtoknam(__xs, ttyp));
+       if (cfg_skipto_semi(ttyp, fp) == CFG_EOF) return;
+       /* here just leave objnam nil for none */
+      }
+     else
+      { 
+       /* library name required design cell name */ 
+       /* notice cell nam can be escaped and if so escapes removed */
+       if (!extract_design_nam(libnam, celnam, __token))
+        {
+         __pv_ferr(3535,
+          "config design statement [library identifier].[cell identifier] expected - %s illegal",
+          __to_cfgtoknam(__xs, ttyp));
+         /* skip on error */
+         continue;
+        }
+      desp = (struct cfgdes_t *) __my_malloc(sizeof(struct cfgdes_t)); 
+      desp->deslbnam = __pv_stralloc(libnam);
+      desp->deslbp = NULL;
+      desp->topmodnam = __pv_stralloc(celnam);
+      desp->desnxt = NULL;
+
+      if (des_hd == NULL) des_hd = des_tail = desp;
+      else
+       {
+        des_tail->desnxt = desp;
+        des_tail = desp;
+       }
+     }
+    }
+   cfgp->cfgdeslist = des_hd;
+
+   /* know ';' read to get here */
+   ttyp =__get_cfgtok(fp);
+  }
+ rule_beg = rule_end = NULL;
+ for (;;)
+  {
+   /* liblist or use clauses never start a config rule */
+   switch(ttyp) { 
+    case CFG_DEFAULT:
+     if (cfgp->cfgdflt != NULL)
+      {
+       __pv_ferr(3538, "config %s default clause repeated - new one replaces",
+       cfgp->cfgnam);
+      }
+   
+     /* format: default liblist [space sep list of library names]; */ 
+     /* may return nil */
+     if ((ttyp = __get_cfgtok(fp)) != CFG_LIBLIST) 
+      {
+       __pv_ferr(3537,
+        "config declaration default clause not followed by liblist keyword - %s read",
+        __to_cfgtoknam(__xs, ttyp));
+       if (cfg_skipto_semi_endconfig(ttyp, fp) != CFG_SEMI)
+        return;
+       continue;
+      }
+     if ((lblp = rd_liblist(fp)) != NULL)
+      {
+       if (cfgp->cfgdflt != NULL) 
+        {
+         /* SJM 12/19/03 - LOOKATME - what if repated */
+         __pv_ferr(3539, "config declaration default clause repeated - 2nd ignord"); 
+        }
+      }
+     else
+      {
+       __pv_fwarn(3127, "config declaration default clause liblist empty");
+      }
+     rulp = (struct cfgrule_t *) __my_malloc(sizeof(struct cfgrule_t));
+     init_rule(rulp);
+     rulp->rul_libs = lblp;
+     rulp->rultyp = CFG_DEFAULT;
+     cfgp->cfgdflt = rulp;
+     break;
+    case CFG_ENDCFG:
+     /* no semi after end config */
+     goto endcfg_read;
+    case CFG_INSTANCE:
+     /* format: instance [inst name] liblist [space sep lib name list]; */ 
+     /* format: instance [inst name] use [qualified mod type name]; */
+ 
+     /* instance name can be XMR but take apart later */
+     if ((ttyp = __get_cfgtok(fp)) != CFG_ID) 
+      {
+       __pv_ferr(3540,
+        "config instance clause instance named expected - %s read",
+          __to_cfgtoknam(__xs, ttyp));
+        if (cfg_skipto_semi_endconfig(ttyp, fp) != CFG_SEMI)
+         return;
+       continue;
+      }
+     /* save the instance name */
+     strcpy(objnam, __token);
+     /* check config XMR path and build malloced cfg nam list of components */
+     /* if return F, table not built */
+     if (!bld_inst_xmr_comptab(__token))
+      {
+       __pv_ferr(3540,
+        "config instance clause instance name %s illegal Verilog hierarchical name",
+       __token);
+       continue;
+      }  
+
+     lblp = NULL;
+     if ((ttyp = __get_cfgtok(fp)) == CFG_LIBLIST) 
+      {
+       /* case 1: liblist form - always reads ending ; */
+       if ((lblp = rd_liblist(fp)) == NULL)
+        {
+         __pv_fwarn(3129, "config instance clause liblist empty - ignored");
+         goto rd_nxt_tok;
+        }
+       rulp = (struct cfgrule_t *) __my_malloc(sizeof(struct cfgrule_t));
+       init_rule(rulp);
+       rulp->rultyp = CFG_INSTANCE;
+       /* just set the instance name and lib names are in lblp */
+       rulp->objnam = __pv_stralloc(objnam);
+       rulp->rul_libs = lblp;
+      }
+     else if (ttyp == CFG_USE) 
+      {
+       if (rd_use_clause(fp, s1, s2, &expl_config) == CFG_ENDCFG)
+        return;
+       /* on error s1 not set */
+       if (strcmp(s1, "") == 0 && strcmp(s2, "") == 0) goto rd_nxt_tok;
+
+       rulp = (struct cfgrule_t *) __my_malloc(sizeof(struct cfgrule_t));
+       init_rule(rulp);
+       rulp->rultyp = CFG_INSTANCE;
+       /* instance objnam use s1.s2 */
+       rulp->rul_use_libnam = __pv_stralloc(s1);
+       rulp->rul_use_celnam = __pv_stralloc(s2);
+       rulp->objnam = __pv_stralloc(objnam);
+       rulp->use_rule_cfg = expl_config;
+       rulp->is_use = TRUE; 
+      }
+     else
+      {
+       __pv_ferr(3548,
+        "config inst clause not followed by liblist or use clause - %s read",
+        __to_cfgtoknam(__xs, ttyp));
+       if (cfg_skipto_semi(ttyp, fp) == CFG_EOF) return;
+       goto rd_nxt_tok;
+      }
+
+     /* SJM 01/14/03 - can't bld the inst XMR components tab until here */
+     nbytes = (__last_bind_comp_ndx + 1)*sizeof(char *);
+     rulp->inam_comptab = (char **) __my_malloc(nbytes);
+     memcpy(rulp->inam_comptab, __bind_inam_comptab, nbytes);
+     rulp->inam_comp_lasti = __last_bind_comp_ndx;
+     /* head of instance name must match config name a design cell name */
+     for (desp = cfgp->cfgdeslist; desp != NULL; desp = desp->desnxt)
+      {
+       if (strcmp(desp->topmodnam, rulp->inam_comptab[0]) == 0)
+        goto fnd_match;
+      }
+     __pv_ferr(3541,
+      "config instance clause hierachical path %s head does not match any design statement top level module name",
+      s1);
+
+fnd_match: 
+     /* add to end of list since must search in order of appearance */
+     if (rule_beg == NULL) cfgp->cfgrules = rule_beg = rule_end = rulp;
+     else
+      {
+       rule_end->rulnxt = rulp;
+       rule_end = rulp;
+      }
+     
+     break;
+    case CFG_CELL:
+     /* format: cell [<lib:>cell] liblist [space sep lib name list]; */ 
+     /* format: cell [<lib>:cell] use [qualified mod type name]; */
+     if ((ttyp = __get_cfgtok(fp)) != CFG_ID) 
+      {
+       __pv_ferr(3551,
+        "config cell clause [library].cell name expected - %s read",
+        __to_cfgtoknam(__xs, ttyp));
+       if (cfg_skipto_semi_endconfig(ttyp, fp) != CFG_SEMI) return;
+       continue;
+      }
+     if (!extract_libcell_nam(libnam, objnam, __token))
+      {
+       goto rd_nxt_tok;
+      }
+     lblp = NULL;
+     if ((ttyp = __get_cfgtok(fp)) == CFG_LIBLIST) 
+      {
+       /* AIV - LRM (pg 217) states lib.cell with liblist is an error */
+       /* if stmt will work because libnam init in extract_libcell  */
+       if (libnam[0] != '\0') 
+       {
+         __pv_ferr(3552,
+          "config cell clause library.cell (%s.%s) cannot be used with 'liblist' clause", libnam, objnam);
+        if (cfg_skipto_semi_endconfig(ttyp, fp) != CFG_SEMI) return;
+        goto rd_nxt_tok;
+       }
+
+       /* case 1: liblist form - always reads ending ; */
+       if ((lblp = rd_liblist(fp)) == NULL)
+        {
+         __pv_fwarn(3131, "config cell clause liblist empty - ignored");
+         goto rd_nxt_tok;
+        }
+       rulp = (struct cfgrule_t *) __my_malloc(sizeof(struct cfgrule_t));
+       init_rule(rulp);
+       rulp->rultyp = CFG_CELL;
+       /* libnam optional    libnam.objnam */
+       rulp->libnam = __pv_stralloc(libnam);
+       rulp->objnam = __pv_stralloc(objnam);
+       rulp->rul_libs = lblp;
+      }
+     else if (ttyp == CFG_USE) 
+      {
+       if (rd_use_clause(fp, s1, s2, &expl_config) == CFG_ENDCFG) return;
+       /* on error s1 not set */
+       if (strcmp(s1, "") == 0 && strcmp(s2, "") == 0) goto rd_nxt_tok;
+
+       rulp = (struct cfgrule_t *) __my_malloc(sizeof(struct cfgrule_t));
+       init_rule(rulp);
+       /* cell objnam use s1.s2 */
+       rulp->rul_use_libnam = __pv_stralloc(s1);
+       rulp->rul_use_celnam = __pv_stralloc(s2);
+       rulp->use_rule_cfg = expl_config;
+       /* objnam is the cell type to match */
+       rulp->objnam = __pv_stralloc(objnam);
+       rulp->libnam = __pv_stralloc(libnam);
+       rulp->rultyp = CFG_CELL;
+       rulp->is_use = TRUE; 
+      }
+     else
+      {
+       __pv_ferr(3559,
+        "config cell clause not followed by liblist or use keywords - %s read",
+        __to_cfgtoknam(__xs, ttyp));
+       if (cfg_skipto_semi(ttyp, fp) == CFG_EOF) return;
+       goto rd_nxt_tok;
+      }
+
+     /* add to end of list since must search in order of appearance */
+     if (rule_beg == NULL) cfgp->cfgrules = rule_beg = rule_end = rulp;
+     else
+      {
+       rule_end->rulnxt = rulp;
+       rule_end = rulp;
+      }
+     break;
+    default:
+     __pv_ferr(3561,
+      "config declaration rule statement or endconfig expected - %s read",
+      __to_cfgtoknam(__xs, ttyp));
+     if (cfg_skipto_semi(ttyp, fp) == CFG_EOF) return;
+   }
+rd_nxt_tok:
+   ttyp =__get_cfgtok(fp);
+  }
+endcfg_read:
+   /* AIV add the config to the list */
+   if (__cfg_hd == NULL) __cfg_hd = __cur_cfg = cfgp;
+   else { __cur_cfg->cfgnxt = cfgp;  __cur_cfg = cfgp; }
+ return;
+}
+
+/*
+ * initialize a rule record
+ */
+static void init_rule(struct cfgrule_t *rulp)
+{
+ rulp->rultyp = CFG_UNKNOWN;
+ rulp->use_rule_cfg = FALSE;
+ rulp->objnam = NULL;
+ rulp->libnam = NULL;
+ rulp->rul_use_libnam = NULL; 
+ rulp->rul_use_celnam = NULL; 
+ rulp->inam_comptab = NULL;
+ rulp->inam_comp_lasti = -1;
+ rulp->rul_libs = NULL;
+ rulp->rulnxt = NULL;
+ /* AIV just set the line to current line  */
+ rulp->rul_lno =  __lin_cnt;
+ rulp->matched =  FALSE;
+ rulp->is_use =  FALSE;
+}
+
+/*
+ * extract a [lib].[cell] design name - format [lib].[cell] 
+ * lib ID lexical pattern is: [let or _]{let | num | $ | _}
+ *
+ * SJM 12/19/03 - LRM wrong since config can't be in Verilog source lib
+ * and cell names both required
+ *
+ * SJM 01/12/04 - library identifiers (names) can't be escaped
+ */
+static int32 extract_design_nam(char *libnam, char *celnam, char *desnam)
+{
+ register char *chp;
+ int32 len;
+ char s1[IDLEN], s2[IDLEN];
+
+ strcpy(libnam, "");
+ strcpy(celnam, "");
+
+ if ((chp = strchr(desnam, '.')) == NULL) return(FALSE);
+ strncpy(s1, desnam, chp - desnam);
+ s1[chp - desnam] = '\0';
+ if (!chk_libid(s1)) return(-1);
+ strcpy(libnam, s1);
+
+ chp++;
+ strcpy(s2, chp);
+ if (!chk_libid(s2))
+  {
+   if (chk_escid(s2))
+    {
+     /* remove the leading escaping back slash and ending ' ' */
+     strcpy(s1, &(s2[1]));
+     len = strlen(s1);
+     s1[len - 1] = '\0';
+    }
+   else
+    {
+     __pv_ferr(3534,
+      "illegal cell name %s - must be legal Verlog identifier", s2);
+    }
+   strcpy(celnam, s1);
+   return(TRUE);
+  }
+ strcpy(celnam, s2);
+ return(TRUE);
+}
+
+/*
+ * check and return T if library name is legal unescaped ID
+ */
+static int32 chk_libid(char *lbnam)
+{
+ register char *chp;
+
+ chp = lbnam;
+ if (!isalpha(*chp) && *chp != '_') return(FALSE);
+ for (++chp; *chp != '\0'; chp++)
+  {
+   if (!isalnum(*chp) && *chp!= '$' && *chp != '_') return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * check and return T if path component or cell type name is legal escaped ID
+ */
+static int32 chk_escid(char *nam)
+{
+ int32 len;
+ char *chp;
+
+ chp = nam;
+ if (*chp != '\\') return(FALSE); 
+ len = strlen(nam);
+ if (nam[len - 1] != ' ') return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * build table of ptrs to strings in global cfg bind table of instance comps
+ * return F on error
+ *
+ * grows global table - caller will copy to malloced memory
+ */
+static int32 bld_inst_xmr_comptab(char *inam)
+{
+ register int32 ci;
+ register char *chp, *chp2;
+ int32 len;
+ char s1[IDLEN], s2[IDLEN];
+
+ /* AIV need to reset the global, after it is copied */
+ __last_bind_comp_ndx = -1;
+ 
+ for (chp = inam;;)
+  {
+   if (*chp == '\\')
+    {
+     if ((chp2 = strchr(chp, ' ')) == NULL)
+      {
+bad_end:
+       for (ci = 0; ci <= __last_bind_comp_ndx; ci++)
+        {
+         __my_free(__bind_inam_comptab[ci],
+          strlen(__bind_inam_comptab[ci]) + 1);
+         __bind_inam_comptab[ci] = NULL;
+        }
+       return(TRUE);
+      }
+
+     strncpy(s1, chp, chp2 - chp);
+     s1[chp2 - chp] = '\0';
+     if (!chk_escid(s1)) goto bad_end;
+     strcpy(s2, &(s1[1]));
+     s2[chp2 - chp - 2] = '\0';
+     chp++;
+    }
+   else
+    {
+     if ((chp2 = strchr(chp, '.')) == NULL)
+      {
+       strcpy(s2, chp);
+       len = strlen(chp);
+       chp = &(chp[len]);
+      }
+     else
+      {
+       /* non escaped and non tail component */
+       strncpy(s2, chp, chp2 - chp);
+       s2[chp2 - chp] = '\0';
+       chp = chp2;
+      }
+    }
+   /* add malloced comp name to table - table copied so do not need to free */ 
+   if (++__last_bind_comp_ndx >= __siz_bind_comps) grow_bind_comps();
+   __bind_inam_comptab[__last_bind_comp_ndx] = __pv_stralloc(s2); 
+
+   if (*chp == '\0') break;
+   if (*chp != '.') goto bad_end;
+   chp++;
+  }
+ return(TRUE);
+}
+
+/*
+ * routine to grow global bind comp table
+ */
+static void grow_bind_comps(void)
+{
+ int32 osize, nsize;
+     
+ osize = __siz_bind_comps*sizeof(char *);
+ /* SJM 01/13/04 - maybe growing too fast */
+ __siz_bind_comps *= 2;
+ nsize = __siz_bind_comps*sizeof(char *);
+ __bind_inam_comptab = (char **) __my_realloc((char *) __bind_inam_comptab,
+  osize, nsize);
+}
+
+
+/*
+ * extract a <lib>.[cell] name where [lib] optional
+ *
+ * almost same as extracting design [lib].[cell] but there lib name required
+ */
+static int32 extract_libcell_nam(char *libnam, char *celnam, char *nam)
+{
+ register char *chp;
+ char s1[IDLEN], s2[IDLEN];
+
+ strcpy(libnam, "");
+ strcpy(celnam, "");
+
+ /* case 1: library omitted and escaped cell name */
+ if (*nam == '\\')
+  {
+   strcpy(s2, nam); 
+
+do_cell_tail:
+   if ((chp = strchr(nam, ' ')) == NULL) return(FALSE);
+   strncpy(celnam, nam, chp - nam);
+   celnam[chp - nam] = '\0';
+   /* checking esc ID but for now will never fail */
+   if (!chk_escid(s2)) return(FALSE); 
+   strncpy(s1, &(nam[1]), chp - nam - 2);
+   s1[chp - nam - 2] = '\0';
+   strcpy(celnam, s1);
+   chp++;
+   if (*chp != '\0') return(FALSE);
+   return(TRUE);
+  }
+ /* if lib name before '.' present, check and fill */
+ if ((chp = strchr(nam, '.')) != NULL)
+  { 
+   strncpy(s1, nam, chp - nam);
+   s1[chp - nam] = '\0';
+   if (!chk_libid(s1)) return(FALSE);
+   strcpy(libnam, s1);
+   chp++;
+   strcpy(s1, chp);
+  }
+ else strcpy(s1, nam);
+ 
+ /* case 3: lib name present and escaped ID */
+ if (*s1 == '\\') goto do_cell_tail;
+ 
+ /* case 4: lib name non escaped ID */
+ if (!chk_libid(s1)) { strcpy(libnam, ""); return(FALSE); }
+ strcpy(celnam, s1);
+ return(TRUE);
+}
+
+/*
+ * read a use clause and ending SEMI
+ *
+ * know use keyword read and reads ending SEMI unless error where resync 
+ * on error return F and set libnam and cell name to empty
+ */
+static int32 rd_use_clause(FILE *fp, char *libnam, char *celnam,
+ int32 *expl_config)
+{
+ int32 ttyp, ttyp2, has_cfg_suffix;
+
+ strcpy(libnam, "");
+ strcpy(celnam, "");
+
+ if ((ttyp = __get_cfgtok(fp)) != CFG_ID)
+  {
+   __pv_ferr(3542,
+    "config use clause not followed by use specifier - %s read",
+    __to_cfgtoknam(__xs, ttyp));
+   ttyp2 = cfg_skipto_semi_endconfig(ttyp, fp);
+   return(ttyp2);
+  }
+ /* this always sets has cfg suffix */  
+ if (!extract_use_nam(libnam, celnam, &has_cfg_suffix, __token))
+  {
+   __pv_ferr(3546,
+    "config use clause %s illegal - [lib].[cell] or [cell]:config allowed - P1364 disallows configs in library source files",
+    __token);
+  }
+ *expl_config = has_cfg_suffix;
+
+ if ((ttyp = __get_cfgtok(fp)) != CFG_SEMI)
+  {
+   __pv_ferr(3544,
+    "config use clause not followed by semicolon - %s read",
+    __to_cfgtoknam(__xs, ttyp));
+   ttyp = cfg_skipto_semi_endconfig(ttyp, fp);
+   return(ttyp);
+  }
+ return(SEMI);
+}
+
+/*
+ * extract a use clause cell identifier
+ * format: <lib name>[cell type name]<:config>
+ * 
+ * if lib name is omitted parent (current) cell's lib used
+ * if :config used, the use config matching [cell type name] for binding
+ */
+static int32 extract_use_nam(char *libnam, char *celnam, int32 *has_config,
+ char *use_spec)
+{
+ register char *chp;
+ char s1[IDLEN], s2[IDLEN];
+
+ strcpy(libnam, "");
+ strcpy(celnam, "");
+ *has_config = FALSE;
+
+ /* case 1: library omitted and escaped cell name */
+ if (*use_spec == '\\')
+  {
+   strcpy(s2, use_spec); 
+
+do_cell_tail:
+   if ((chp = strchr(use_spec, ' ')) == NULL) return(FALSE);
+   strncpy(celnam, use_spec, chp - use_spec);
+   celnam[chp - use_spec] = '\0';
+   /* checking esc ID but for now will never fail */
+   if (!chk_escid(s2)) return(FALSE); 
+   strncpy(s1, &(use_spec[1]), chp - use_spec - 2);
+   s1[chp - use_spec - 2] = '\0';
+   strcpy(celnam, s1);
+   chp++;
+   if (*chp == ':') 
+    {
+     if (strcmp(chp, ":config") != 0) return(FALSE);
+     /* SJM 05/18/04 - :config hierarchical config indirection indicator */ 
+     /* can't be used with library name since library are for Verilog src */
+     if (strcmp(libnam, "") != 0) return(FALSE);
+     *has_config = TRUE;
+    }
+   else 
+    {
+     if (*chp != '\0') return(FALSE);
+    }
+   return(TRUE);
+  }
+ /* if lib name before '.' present, check and fill */
+ if ((chp = strchr(use_spec, '.')) != NULL)
+  { 
+   strncpy(s1, use_spec, chp - use_spec);
+   s1[chp - use_spec] = '\0';
+   if (!chk_libid(s1)) return(FALSE);
+   strcpy(libnam, s1);
+   chp++;
+   strcpy(s1, chp);
+  }
+ else strcpy(s1, use_spec);
+ 
+ /* case 3: lib name present and escaped ID */
+ if (*s1 == '\\') goto do_cell_tail;
+ 
+ /* case 4: lib name non escaped ID */
+ if ((chp = strchr(s1, ':')) == NULL)
+  {
+   if (!chk_libid(s1)) { strcpy(libnam, ""); return(FALSE); }
+   strcpy(celnam, s1);
+   return(TRUE);
+  }
+ /* :config suffix present */
+ if (strcmp(chp, ":config") != 0) return(FALSE);
+
+ strncpy(s2, s1, chp - s1);
+ s2[chp - s1] = '\0';
+ if (!chk_libid(s2)) return(FALSE);
+ strcpy(celnam, s2);
+
+ /* SJM 05/18/04 - :config hierarchical config indirection indicator */ 
+ /* can't be used with library name since library are for Verilog src */
+ if (strcmp(libnam, "") != 0) return(FALSE);
+
+ *has_config = TRUE;
+ return(TRUE);
+}
+
+/*
+ * read a liblist non comma separated list of libraries
+ *
+ * know liblist keyword read and reads first libr and keeps reading lib
+ * names (no wildcards) until ending semicolon read (i.e. list ends with ;
+ * and no commas)
+ *
+ * library names are simple IDs
+ * even if error continues reading to ; or EOF
+ */
+static struct cfgnamlst_t *rd_liblist(FILE *fp)
+{
+ int32 ttyp;
+ struct cfgnamlst_t *lbp, *lbp_hd, *lbp_tail;
+
+ lbp_hd = lbp_tail = NULL;
+ for (;;)
+  {
+   ttyp = __get_cfgtok(fp);
+   if (ttyp == CFG_SEMI) break; 
+
+   if (ttyp != CFG_ID)
+    {
+     __pv_ferr(3562, "config liblist library name expected - %s read",
+      __to_cfgtoknam(__xs, ttyp));
+     cfg_skipto_semi(ttyp, fp);
+     return(NULL);
+    }
+   if (!chk_libid(__token))
+    {
+     __pv_ferr(3563,
+      "config liblist library name %s illegal - must be simple Verilog ID",
+      __token);
+    }
+   lbp = (struct cfgnamlst_t *) __my_malloc(sizeof(struct cfgnamlst_t)); 
+   lbp->nam = __pv_stralloc(__token);
+   lbp->cnlnxt = NULL; 
+   if (lbp_hd == NULL) lbp_hd = lbp_tail = lbp;
+   else { lbp_tail->cnlnxt = lbp;  lbp_tail = lbp; }
+  }
+ return(lbp_hd);
+}
+
+/*
+ * LOW LEVEL ROUTINES FOR CFG INITIALIZATION AND ERROR RECOVERY  
+ */
+
+/*
+ * initialize a cfg lib record
+ */
+static void init_cfglib(struct cfglib_t *lbp)
+{
+ lbp->lbsrc_rd = FALSE;
+ lbp->lbname = NULL;
+ lbp->lbels = NULL;
+ lbp->lbnxt = NULL;
+}
+
+/*
+ * initialize a cfg block record
+ */
+static void init_cfg(struct cfg_t *cfgp)
+{
+ cfgp->cfgnam = NULL;
+ cfgp->cfgdeslist = NULL;
+ cfgp->cfgrules = NULL;
+ cfgp->cfgdflt = NULL;
+ cfgp->cfg_fnam = NULL;
+ cfgp->cfg_lno = -1;
+ cfgp->cfgnxt = NULL;
+}
+
+/*
+ * cfg get token error recovery skip to semi
+ *
+ * notice config token number not related to source reading numbers
+ * but using __token global for names still
+ */
+static int32 cfg_skipto_semi(int32 ttyp, FILE *fp)
+{
+ for (;;) 
+  {
+   if (ttyp == CFG_SEMI || ttyp == CFG_EOF) break;
+   ttyp = __get_cfgtok(fp);
+  }
+ return(ttyp);
+}
+
+/*
+ * cfg get token error recovery skip to semi or comma
+ *
+ * notice config token number not related to source reading numbers
+ * but using __token global for names still
+ */
+static int32 cfg_skipto_comma_semi(int32 ttyp, FILE *fp)
+{
+ for (;;) 
+  {
+   if (ttyp == CFG_SEMI || ttyp == CFG_EOF) break;
+   ttyp = __get_cfgtok(fp);
+  }
+ return(ttyp);
+}
+
+/*
+ * cfg get token error recovery skip to semi or endconfig
+ *
+ * notice config token number not related to source reading numbers
+ * but using __token global for names still
+ */
+static int32 cfg_skipto_semi_endconfig(int32 ttyp, FILE *fp)
+{
+ for (;;) 
+  {
+   if (ttyp == CFG_SEMI || ttyp == CFG_ENDCFG || ttyp == CFG_EOF) break;
+   ttyp = __get_cfgtok(fp);
+  }
+ return(ttyp);
+}
+
+
+/*
+ * cfg get token error recovery skip 
+ *
+ * notice config token number not related to source reading numbers
+ */
+static int32 cfg_skipto_eof(int32 ttyp, FILE *fp)
+{
+ for (;;) 
+  {
+   if (ttyp == CFG_EOF) break;
+   ttyp = __get_cfgtok(fp);
+  }
+ return(ttyp);
+}
+
+/*
+ * ROUTINES TO EXPAND AND REPLACE LIBRARY WILDCARD FILE LISTS
+ */
+
+/* names for the special wildcard characters - see LRM */
+#define STAR 1
+#define QMARK 2
+#define HIER 3
+
+/*
+ * return TRUE if the string contains a wildcard
+ * '*', '?', '...', or ending in a / => TRUE
+ */
+static int32 has_wildcard(char *cp)
+{
+ int32 i, slen;
+
+ slen = strlen(cp);
+ /* if it ends in a slash return TRUE - include all case */
+ if (cp[slen -1] == '/') return(TRUE);
+ for (i = 0; i <= slen - 1; i++, cp++)
+  {
+   if (*cp == '*') return(TRUE);
+   if (*cp == '?') return(TRUE);
+   if (i < slen + 2 && strncmp(cp, "...", 3) == 0) return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * expand all wild cards in library file name lists
+ *
+ * first step in cfg elaboration after all map and cfg files read
+ */
+extern void __expand_lib_wildcards(void)
+{
+ register struct cfglib_t *lbp;
+ register struct libel_t *lbep;
+ int32 sav_lin_cnt;
+ char *sav_cur_fnam, *cp;
+ FILE *fp;
+
+ /* expand for library */
+ for (lbp = __cfglib_hd; lbp != NULL; lbp = lbp->lbnxt)
+  {
+   sav_lin_cnt = __lin_cnt;
+   sav_cur_fnam = __cur_fnam;
+   __cur_fnam = lbp->cfglb_fnam;
+   __lin_cnt = lbp->cfglb_lno;
+
+   /* for each fspec in one library's fspec list, expand any wildcards */
+   for (lbep = lbp->lbels; lbep != NULL; lbep = lbep->lbenxt)
+    {
+     /* AIV mark the expanded so the pattern string is replaced */
+     lbep->expanded = FALSE;
+     cp = lbep->lbefnam;
+     /* if it doesn't contain a wildcard char must be a file so simple open */
+     if (!has_wildcard(cp))
+      {
+       /* if it returns NULL file no such file */
+       if ((fp = __tilde_fopen(cp, "r")) == NULL)
+        {
+         __pv_ferr(3564, "config library %s unable to match pattern %s\n",
+          lbp->lbname, cp); 
+        }
+       else 
+        {
+         /* no need to change the file name, just mark the flag as expanded */
+         lbep->expanded = TRUE;
+         /* close the open file */
+         __my_fclose(fp); 
+        }
+      }
+     else if (strcmp(cp, "...") == 0)
+      {
+       /* include all files below the current directory */
+       if (!expand_single_hier(lbp, lbep, NULL))
+        {
+         __pv_ferr(3564, "config library %s unable to match pattern %s\n",
+          lbp->lbname, cp); 
+        }
+      }
+     else 
+      {
+        /* match the pattern case */
+        expand_dir_pats(lbp, lbep, cp);
+      }
+   }
+   /* put back for further reading */
+   __lin_cnt = sav_lin_cnt;
+   __cur_fnam = sav_cur_fnam;
+  }
+}
+
+/*
+ * match a hier name with the given pattern name
+ */
+static int32 match_hier_name(struct xpndfile_t *xfp_hd, char *name) 
+{
+ char *cp, *last;
+ char str[RECLEN]; 
+ struct xpndfile_t *xfp;
+ 
+ /* skip past ./ meaningless */
+ if (name[0] == '.' && name[1] == '/') name += 2;
+ last = name;
+ xfp = xfp_hd; 
+ cp = strchr(name, '/');
+ if (cp == NULL)
+  {
+   /* Special case ../../\*.v  - last pattern and matches wildcard */
+   if (xfp->xpfnxt == NULL && match_wildcard_str(name, xfp)) return(TRUE);
+   /* Special case .../\*.v  */
+   else if (xfp->wildcard == HIER && xfp->xpfnxt->xpfnxt == NULL 
+    && match_wildcard_str(name, xfp->xpfnxt)) return(TRUE);
+  }
+ else
+  {
+   for (; xfp != NULL && cp != NULL; cp = strchr(cp, '/'))
+    {
+     /* check the string to the next '/' to match the pattern */
+     /* copy /string/ into str to check with pattern */
+     strncpy(str, last, cp - last); 
+     str[cp-last] ='\0';
+     /* if doesn't match pattern return */
+     if (!match_wildcard_str(str, xfp)) return(FALSE);
+     /* handle special ... case */
+     if (xfp->wildcard == HIER)
+      { 
+       /* no more patterns it is a match */
+       if (xfp->xpfnxt == NULL) return(TRUE);
+
+       /* match all the remaining patterns after .../ */
+       /* move pattern up one and get the next /string/ */
+hier:
+       xfp = xfp->xpfnxt;
+       for (; cp != NULL;  )
+        {
+         /* special case it is the last one */
+         if ((cp - last) == 0) strcpy(str, cp);
+         else
+          {
+           strncpy(str, last, cp - last); 
+           str[cp-last] ='\0';
+          }
+         /* if matches continue */
+         if (match_wildcard_str(str, xfp))
+          {
+           xfp = xfp->xpfnxt; 
+           if (xfp == NULL) return(TRUE);
+          }
+         last = ++cp;
+         /* last pattern in the string dir/dir2/lastpattern */
+         if ((cp = strchr(cp, '/')) == NULL)
+          {
+           /* if more patterns continue */
+           if (xfp->xpfnxt != NULL) return(FALSE); strcpy(str, last); 
+           /* match the lastpattern and gets here it is a match */
+           if (match_wildcard_str(str, xfp)) return(TRUE);
+          }
+        }
+      }
+     last = ++cp;
+
+     /* include all in the directory and the last in the char name */ 
+     if (xfp->incall && strchr(cp, '/') == NULL) return(TRUE);
+
+     /* if the last pattern and didn't match FALSE  */ 
+     xfp = xfp->xpfnxt; 
+     if (xfp == NULL)  return(FALSE);
+     if (xfp->wildcard == HIER && xfp->xpfnxt != NULL) goto hier;
+     /* try to match the last of the string */ 
+     if (*cp != '\0' && strchr(cp, '/') == NULL)
+      {
+       if (xfp->xpfnxt == NULL && match_wildcard_str(cp, xfp)) return(TRUE);
+       else return(FALSE);
+      }
+    }
+  }
+ return(FALSE);
+}
+
+/*
+ * match the special hierarchical wildcard in the pattern
+ * is recursive call which takes the parameters -
+ *
+ * xfp_hd - the start of the split pattern to match 
+ * bpath - the beginning part of the path (the non-wildcard start of the path) 
+ * path - the current path
+ *
+ * builds the strings to match according to attempt to match to the xfp list 
+ */
+static void find_hier(struct libel_t *lbep, struct xpndfile_t *xfp_hd, 
+ char *bpath, char *path)
+{
+ char str[RECLEN];
+ char str2[RECLEN];
+ char dirstr[RECLEN];
+ char *cp;
+ DIR *dp;
+ struct dirent *dir;
+#if defined(__CYGWIN32__) || defined(__SVR4)
+ struct stat sbuf;
+#endif
+  
+ /* start from the current directory */
+ if (path == NULL) { strcpy(str, "."); cp = str; }
+ else cp = path;
+
+ if ((dp = opendir(cp)) == NULL)
+  {
+   __pv_ferr(1368, "during config library expansion cannot open dir %s : %s\n",
+    cp, strerror(errno)); 
+  }
+ 
+ while ((dir = readdir(dp)) != NULL)
+  {
+   if (dir->d_ino == 0) continue;
+   if (strcmp(dir->d_name, ".") == 0) continue;
+   if (strcmp(dir->d_name, "..") == 0) continue;
+#if defined(__CYGWIN32__) || defined(__SVR4)
+   if (stat(dir->d_name, &sbuf) == -1) continue;
+   if ((S_IFMT & sbuf.st_mode) == S_IFDIR)
+#else
+   if (dir->d_type == DT_DIR)
+#endif
+    {
+     /* directory concat name and call recursively */
+     if (path == NULL) sprintf(dirstr, "./%s", dir->d_name);
+     else sprintf(dirstr, "%s/%s", path, dir->d_name);
+     find_hier(lbep, xfp_hd, bpath, dirstr);
+    }
+#if defined(__CYGWIN32__) || defined(__SVR4)
+   else if ((S_IFMT & sbuf.st_mode) == S_IFREG)
+#else
+   else if (dir->d_type == DT_REG)
+#endif
+    {
+     str[0] ='\0';
+     /* concat the file name to the directory */
+     if (path == NULL) strcpy(str, dir->d_name);
+     else sprintf(str, "%s/%s", cp, dir->d_name);
+     /* check if the name matches the xfp list */
+     if (match_hier_name(xfp_hd, str))
+      {
+       if (bpath != NULL)
+        {
+         sprintf(str2, "%s/%s", bpath, str);
+         expand_libel(lbep, str2);
+        }
+       else expand_libel(lbep, str);
+      }
+    }
+  }
+ if (dp != NULL) closedir(dp);
+}
+
+/*
+ * routine to actually do the hierarchical search 
+ * moves to the first wildcard xfp and does search 
+ */
+static void expand_hier_files(struct cfglib_t *lbp, struct libel_t *lbep,
+ struct xpndfile_t *xfp_hd)
+{
+ char dirstr[RECLEN];
+ char bpath[RECLEN];
+ char tmp[RECLEN];
+ int32 first;
+ 
+ /* if the first xfp has a wildcard do the search do search with current xfp */ 
+ if (xfp_hd->wildcard) 
+  {
+   find_hier(lbep, xfp_hd, NULL, NULL);
+   return;
+  }
+ first = TRUE;
+ /* save current dir */
+ getcwd(dirstr, RECLEN); 
+ strcpy(bpath, "");
+ while (!xfp_hd->wildcard && xfp_hd->incall != TRUE) 
+  {
+   if (chdir(xfp_hd->fpat) < 0)
+    {
+     if (first)
+      {
+       __pv_ferr(3564, "config library %s no such directory %s\n",
+       lbp->lbname, xfp_hd->fpat); 
+      }
+     else
+      {
+       __pv_ferr(3564, "config library %s no such directory %s/%s\n",
+        lbp->lbname, bpath, xfp_hd->fpat);
+       chdir(dirstr);
+       return;
+      }
+    }
+   /* move to non-wildcard dir and buld beginning path name */
+   if (first)
+    {
+     strcpy(bpath, xfp_hd->fpat);
+     first = FALSE;
+    }
+   else
+    {
+     strcpy(tmp, bpath);
+     sprintf(bpath, "%s/%s", tmp, xfp_hd->fpat);
+    }
+   xfp_hd = xfp_hd->xpfnxt;
+  }
+ /* do the search */
+ find_hier(lbep, xfp_hd, bpath, NULL);
+ /* go back to the original dir  */
+ chdir(dirstr);
+}
+
+/*
+ * routine to break up the original user pattern by '/' - xfp1/xfp2/xfpn
+ */
+static void expand_dir_pats(struct cfglib_t *lbp, struct libel_t *lbep,
+ char *pat)
+{
+ int32 slen, i, ndx, clevel, last_star;
+ int32  wildcard, hier, cur_hier, last_hier, back_dir;
+ char str[RECLEN]; 
+ char *last, *cp;
+ struct xpndfile_t *xfp, *xfp2, *xfp_hd, *xfp_tail;
+
+ str[0] = '\0';
+ clevel = -1;
+ xfp_hd = xfp_tail = NULL;
+ slen = strlen(pat);
+ cp = last = pat;
+ last_star = last_hier = wildcard = FALSE;
+ back_dir = cur_hier = hier = FALSE;
+ /* ndx if current index of the string */
+ ndx = 0;
+ for (i = 0; i < slen; i++, ndx++, cp++)
+  {
+   /* split add a xfp to the list */
+   if (*cp == '/')
+    {
+     cur_hier = FALSE;
+     /* special verilog escape char */
+     if (i + 1 < slen && *(cp+1) == '/') 
+      {
+       /* LOOKATME FIXME - check if this works */
+       /* special espcaped char // read until next ' ' or end of str */
+       i++;
+       cp++;
+       for (; i < slen && *cp != ' '; i++, cp++) ;
+      }
+     /* skip a /./ since it doesn't do anything */
+     if (ndx == 1 &&  str[0] == '.') { last = (cp + 1); continue; }
+     str[ndx] = '\0'; 
+     if (ndx == 3 && strcmp(str, "...") == 0) 
+      {
+       /* if ... and so was the last skip this one */
+       if (last_hier)
+        {
+         __pv_warn(3124, "config can't have .../... - treating as only one\n");
+         ndx = -1;
+         continue;
+        }
+       cur_hier = hier = TRUE;
+      }
+     else if (ndx == 2 && back_dir && strcmp(str, "..") == 0)
+      {
+       __pv_warn(3125,
+        "Back directory '..' can only be used at the beginning of pattern string\n");
+      }
+      /* AIV 05/25/04 - on the first non '..' set back_dir to true */
+      /* there can be multilple ../.. prior to the pattern */
+     else if(ndx != 2 || strcmp(str, "..") != 0)
+            back_dir = TRUE;
+
+     xfp = (struct xpndfile_t *) __my_malloc(sizeof(struct xpndfile_t)); 
+     xfp->fpat = __pv_stralloc(str);
+     if (cur_hier) 
+      {
+       /* set the wildcar to hierarch */
+       xfp->wildcard = HIER;
+       last_hier = TRUE;
+      }
+     else
+      {
+       /* set the wildcar STAR or QMARK */
+       xfp->wildcard = wildcard;
+       last_hier = FALSE;
+      }
+     xfp->nmatch = 0; 
+     /* special case that ends in '/' inc all the files */
+     if (i + 1 == slen) xfp->incall = TRUE; 
+     else xfp->incall = FALSE; 
+     xfp->xpfnxt = NULL; 
+
+     /* set the current depth level */
+     xfp->level = ++clevel;
+     if (xfp_hd == NULL) xfp_hd = xfp_tail = xfp;
+     else { xfp_tail->xpfnxt = xfp;  xfp_tail = xfp; }
+
+     /* set the last char to one past the / */
+     if (i < slen) last = (cp + 1);
+     /* reset wildcard and last_star and string index */
+     wildcard = FALSE;
+     last_star = FALSE;
+     ndx = -1;
+    }
+   else if (*cp == '*')
+    {
+     /* previous chars was star as well so just set ndx back one to skip */
+     if (last_star) ndx--;
+     last_star = TRUE;
+     wildcard = STAR;
+     /* AIV 05/18/04 - can never be negative since last_star is a flag */
+     /* that can only be set when ndx > 0 */
+     str[ndx] = *cp;
+    }
+   else
+    {
+     /* star takes wildcard precedence over qmark - needed for pat matching */
+     if (*cp == '?' && wildcard != STAR) wildcard = QMARK;
+     last_star = FALSE;
+     str[ndx] = *cp;
+    }
+  } 
+ /* LOOKATME will /a still work */
+ /* add the last one this has to be a file or file pattern */
+ cur_hier = FALSE;
+ if (cp != last)
+  {
+   if (ndx == 1 && *(cp - 1) == '.') goto done;
+   str[ndx] = '\0'; 
+   if (strcmp(str, "...") == 0) 
+    {
+     /* just skip the last ... if there is two in a row */
+     if (last_hier) goto done; cur_hier = hier = TRUE;
+    }
+   xfp = (struct xpndfile_t *) __my_malloc(sizeof(struct xpndfile_t)); 
+   xfp->fpat = __pv_stralloc(str);
+   if (cur_hier) xfp->wildcard = HIER;
+   else xfp->wildcard = wildcard;
+   xfp->nmatch = 0; 
+   xfp->xpfnxt = NULL; 
+   xfp->level = ++clevel;
+   if (xfp_hd == NULL) xfp_hd = xfp_tail = xfp;
+   else { xfp_tail->xpfnxt = xfp;  xfp_tail = xfp; }
+  }
+
+ /* DGB REMOVE */
+ if (xfp_hd == NULL) __misc_terr(__FILE__, __LINE__);
+
+done:
+ /* doesn't contain a hieracrh ... */
+ if (!hier)
+  {
+   /* if the first xfp contains a wildcard just call match overwise */
+   /* move to on wildcard dir and then match */ 
+   if (xfp_hd->wildcard) match_dir_pats(lbep, xfp_hd, NULL, NULL, FALSE, 0); 
+   else movedir_match_dir_pats(lbep, xfp_hd); 
+  }
+ else
+  {
+   /* match the hier case */
+   expand_hier_files(lbp, lbep, xfp_hd); 
+  }
+ /* free xfp list */
+ /* SJM 11/05/04 - need 2nd pointer since xpfnxt can't be accessed */
+ /* after freed */
+ for (xfp = xfp_hd ; xfp != NULL;)
+  {
+   xfp2 = xfp->xpfnxt;
+   __my_free((char *) xfp, sizeof(struct xpndfile_t ));
+   xfp = xfp2; 
+  }
+}
+
+/*
+ * move xfp_hd to the first wildcard to start the search
+ */
+static void movedir_match_dir_pats(struct libel_t *lbep, 
+ struct xpndfile_t *xfp_hd) 
+{
+ int32 level;
+ char dirstr[RECLEN]; 
+ char bpath[RECLEN]; 
+
+ level = 0;
+ /* save current directory */
+ getcwd(dirstr, RECLEN); 
+ while (!xfp_hd->wildcard && xfp_hd->incall != TRUE) 
+  {
+   if (chdir(xfp_hd->fpat) < 0)
+    {
+     /* SJM 05/11/04 - FIXME ### ??? - need way to locate these */
+     /* AIV 05/18/04 if the currect level print current pattern name */
+     if (level == 0)
+      { 
+       __pv_warn(3132, "no such directory %s\n", xfp_hd->fpat);
+      }
+     else
+      {
+      /* if lower level print all previous path and current pattern name */
+       __pv_warn(3132, "Error - no such directory path %s/%s\n",
+        bpath, xfp_hd->fpat);
+      }
+     chdir(dirstr);
+     return;
+    }
+   /* goto the next directory and inc the depth level */
+   if (level == 0) strcpy(bpath, xfp_hd->fpat);
+   else sprintf(bpath, "%s/%s", bpath, xfp_hd->fpat);
+   level++;
+   xfp_hd = xfp_hd->xpfnxt;
+  }
+ /* search directories */
+ match_dir_pats(lbep, xfp_hd, NULL, bpath, FALSE, level); 
+ /* do back to the current directory */
+ chdir(dirstr);
+}
+
+/*
+ * match the patterns for each xfp->fpat per directory
+ *
+ * xfp_hd - points to the first wildcard name1/ 
+ * bpath - start of path not containing a wildcard 
+ * path - points to all current path 
+ * incall - is the flag to include all the files in the dir, end in '/'
+ */
+static void match_dir_pats(struct libel_t *lbep, struct xpndfile_t *xfp_hd,
+char *path, char *bpath, int32 incall, int32 level) 
+{
+ char dirstr[RECLEN]; 
+ char str[RECLEN]; 
+ char str2[RECLEN]; 
+ char *cp; 
+ struct xpndfile_t *xfp;
+ struct dirent *dir;
+ DIR *dp;
+#if defined(__CYGWIN32__) || defined(__SVR4)
+ struct stat sbuf;
+#endif
+     
+ /* if it's null just add the ./ */
+ if (path == NULL) { strcpy(str, "./"); cp = str; }
+ else cp = path;
+
+ xfp = xfp_hd; 
+ dp = NULL;
+ for (; xfp != NULL; xfp = xfp->xpfnxt)
+  {
+   /* if the xfp->level is greater than the current level return */
+   if (xfp->level > level) return;
+   if ((dp = opendir(cp)) == NULL)
+    {
+     __pv_ferr(3569, "in config libary file %s cannot open dir %s : %s\n",
+      lbep->lbefnam, cp, strerror(errno)); 
+     return;
+    }
+   while ((dir = readdir(dp)) != NULL)
+    {
+     if (dir->d_ino == 0) continue;
+     if (strcmp(dir->d_name, ".") == 0) continue;
+     /* handle directories */
+#if defined(__CYGWIN32__) || defined(__SVR4)
+     if (stat(dir->d_name, &sbuf) == -1) continue;
+     if ((S_IFMT & sbuf.st_mode) == S_IFDIR)
+#else
+     if (dir->d_type == DT_DIR)
+#endif
+      {
+       /* if not include all and it matches the wildcard go to next dir */
+       if (!incall && match_wildcard_str(dir->d_name, xfp))
+        {
+         /* path is null copy else concat dir name */
+         if (path == NULL) sprintf(dirstr, "%s", dir->d_name);
+         else sprintf(dirstr, "%s/%s", path, dir->d_name);
+         /* if include all (end's in /) include all files of dir */
+         if (xfp->incall)
+          {
+           match_dir_pats(lbep, xfp, dirstr, bpath, TRUE, level + 1);
+          }
+         else
+          {
+           match_dir_pats(lbep, xfp->xpfnxt, dirstr, bpath, incall,
+            level + 1);
+          }
+         /* if no wildcard and doesn't end in / return */
+         if (!xfp->wildcard && !xfp->incall) return;
+        }
+      }
+#if defined(__CYGWIN32__) || defined(__SVR4)
+     else if ((S_IFMT & sbuf.st_mode) == S_IFREG)
+#else
+     else if (dir->d_type == DT_REG)
+#endif
+      {
+       /* handle files */
+       /* if not include all in current directory */ 
+       if (!incall)
+        {
+         /* if another pattern to macth or pattern ends in / continue */ 
+         if (xfp->xpfnxt != NULL || xfp->incall) continue;
+ 
+         /* if doesn't match the wildcard continue */ 
+         if (!match_wildcard_str(dir->d_name, xfp)) continue;
+        }
+       /* if it gets here include the file */
+       if (path == NULL) sprintf(str, "%s", dir->d_name);
+       else sprintf(str, "%s/%s", cp, dir->d_name);
+       if (bpath != NULL)
+        {
+         sprintf(str2, "%s/%s", bpath, str);
+         expand_libel(lbep, str2);
+        }
+       else expand_libel(lbep, str);
+      }
+    }
+  }
+ if (dp != NULL) closedir(dp);
+}
+
+/*
+ * routine to return T if a wildcard pattern matches a file name 
+ * matches '...', '*', '?'
+ * or file name with any of the wild chars
+ */
+static int32 match_wildcard_str(char *file, struct xpndfile_t *xfp) 
+{
+ int32 fndx, pndx, flen, plen; 
+ int32 ondx, wildcard;
+ char *opat, *patp, *filep;
+
+ patp = xfp->fpat;
+ wildcard = xfp->wildcard;
+ /* if hier include all patterns */
+ if (wildcard == HIER || strcmp(patp, "*") == 0) return(TRUE);
+ 
+ /* if string is an exact match return true */
+ if (strcmp(file, patp) == 0) return(TRUE);
+ /* if it doesn't have a wildcard return */
+ if (!xfp->wildcard) return(FALSE);
+
+ flen = strlen(file);
+ plen = strlen(patp); 
+ 
+ /* special case if it has a star at the end match exact file - start */
+ if (wildcard == STAR && flen == plen - 1 && xfp->fpat[plen-1] == '*')
+  {
+   if (strncmp(file, xfp->fpat, flen) == 0) return(TRUE);
+  }
+ filep = file;
+ fndx = ondx = 0;
+ /* skip the regular characters */
+ while (*patp != '?' && *patp != '*') 
+  {
+   if (*filep != *patp) return(FALSE);
+   filep++;
+   patp++;
+   fndx++;
+   ondx++; 
+  }
+ 
+ /* reset used for * can to reset to location of last special char */
+ opat = patp;
+
+reset:
+ patp = opat;
+ pndx = ondx;
+ for (; fndx < flen && pndx < plen; fndx++, pndx++, filep++, patp++)
+  {
+   /* if strings are equal or '?' goto the next char */
+   if (*filep == *patp || *patp == '?') continue;
+   else if (*patp == '*')
+    {
+     /* special case the \*\*\?\?  */
+     if (*(patp + 1) == '?')
+      {
+       opat = (patp + 1);
+       ondx = pndx + 1;
+       patp++;
+       pndx++;
+       while (*patp == '?' && pndx < plen && fndx < flen)
+        { fndx++, pndx++, filep++, patp++; }
+       /* matching chars return */
+       if (pndx == plen) return(TRUE);
+       goto reset;
+      }
+     opat = patp; ondx = pndx;
+     /* if a star case just move pattern to next char */
+     while (*patp == '*' && pndx < plen)
+      { 
+       patp++; pndx++; 
+      }
+     if (pndx == plen) return(TRUE);
+
+     /* if a qmark just continue and match the next char */
+     if (*patp == '?') continue;
+
+     /* while not equal move file forward */
+     while (fndx < flen && *filep != *patp)
+      { filep++; fndx++; }
+     
+     /* reached the end without finding an equal char */
+     if (fndx == flen &&  *filep != *patp) return(FALSE);
+     if (*filep != *patp && fndx < flen){filep++; fndx++; goto reset; }
+    }
+   /* if not eq, '?', or '*' doesn't match*/
+   else if (fndx < flen && wildcard == STAR) goto reset;
+   else return(FALSE);
+  }
+ if (fndx < flen && wildcard == STAR) goto reset;
+ /* if string reaches the end it is a match */
+ if (flen == fndx)
+  {
+   if (pndx == plen) return(TRUE);
+   /* special case patp ends in the '*' */ 
+   else if (pndx == plen - 1 && *patp == '*') return(TRUE);
+  }
+ return(FALSE);
+} 
+
+/*
+ * expand the lib element
+ */
+static void expand_libel(struct libel_t *lbep, char *file)
+{
+ struct libel_t *newlbp;
+
+ /* if F replace the pattern name with the expanded file name */
+ if (!lbep->expanded)
+  {
+   /* only rename/free if it isn't the orginal string */
+   /* there is no wildcard so the same stays the same */
+   if (lbep->lbefnam != NULL)
+    {
+     __my_free(lbep->lbefnam, strlen(lbep->lbefnam) + 1);
+     lbep->lbefnam = (char *) __pv_stralloc(file);
+    }
+   lbep->expanded = TRUE;
+  }
+ else
+  {
+   /* link on a new expanded file name  */
+   newlbp = (struct libel_t *) __my_malloc(sizeof(struct libel_t));
+   memcpy(newlbp, lbep, sizeof(struct libel_t));
+   newlbp->lbefnam = (char *) __pv_stralloc(file);
+   lbep->lbenxt = newlbp;
+   lbep = newlbp;
+   lbep->expanded = TRUE;
+  }
+}
+
+/*
+ * return to expand all patterns underneath hierarchy
+ *
+ * if pattern is only '...' return all files below the current path
+ * recursively calls itself returning all files
+ */
+static int32 expand_single_hier(struct cfglib_t *lbp, struct libel_t *lbep,
+ char *path)
+{
+ int32 count;
+ char str[RECLEN];
+ char dirstr[RECLEN];
+ char *cp;
+ DIR *dp;
+ struct dirent *dir;
+#if defined(__CYGWIN32__) || defined(__SVR4)
+ struct stat sbuf;
+#endif
+
+ if (path == NULL) { strcpy(str, "."); cp = str; }
+ else cp = path;
+
+ count = 0;
+ if ((dp = opendir(cp)) == NULL)
+  {
+   __pv_ferr(3569, "in config libary %s cannot open dir %s : %s\n",
+    lbp->lbname, cp, strerror(errno)); 
+   return(0);
+  }
+ while ((dir = readdir(dp)) != NULL)
+  {
+   if (dir->d_ino == 0) continue;
+   if (strcmp(dir->d_name, ".") == 0) continue;
+   if (strcmp(dir->d_name, "..") == 0) continue;
+#if defined(__CYGWIN32__) || defined(__SVR4)
+   if (stat(dir->d_name, &sbuf) == -1) continue;
+   if ((S_IFMT & sbuf.st_mode) == S_IFDIR)
+#else
+   if (dir->d_type == DT_DIR)
+#endif
+    {
+     if (path == NULL) sprintf(dirstr, "./%s", dir->d_name);
+     else sprintf(dirstr, "%s/%s", path, dir->d_name);
+     expand_single_hier(lbp, lbep, dirstr);
+    }
+#if defined(__CYGWIN32__) || defined(__SVR4)
+   else if ((S_IFMT & sbuf.st_mode) == S_IFREG)
+#else
+   else if (dir->d_type == DT_REG)
+#endif
+    {
+     str[0] ='\0';
+     if (path == NULL) sprintf(str, "%s", dir->d_name);
+     else sprintf(str, "%s/%s", cp, dir->d_name);
+     count++;
+     expand_libel(lbep, str);
+    }
+  }
+ if (dp != NULL) closedir(dp);
+ return(count);
+}
+
+/*
+ * ROUTINES TO READ CFG LIBRARY SPECIFIED VERILOG SOURCE
+ */
+
+/*
+ * read and bind cells as directed by previously read  config block
+ *
+ * reads cfg design statement and then read libraries according to cfg rules
+ * user must not give and .v files on command line
+ */
+extern void __rd_ver_cfg_src(void)
+{
+ register struct cfg_t *cfgp;
+ 
+ /* SJM 05/18/04 - LOOKATME - why doesn't this test work? */
+ /* ### if (__last_inf != __cmd_ifi) __misc_terr(__FILE__, __LINE__); */
+
+ prep_cfg_vflist();
+
+ if (__cfg_verbose) dump_config_info();
+
+ for (cfgp = __cfg_hd; cfgp != NULL; cfgp = cfgp->cfgnxt)
+  {
+   if (__cfg_verbose)
+       __cv_msg("BINDING RULES IN CONFIG %s \n",  cfgp->cfgnam);
+   bind_cfg_design(cfgp, FALSE);
+  }
+
+ /* AIV 05/24/04 - free and link out of mod list all cfg lib modules */
+ /* that are in scanned files but never instantiated */
+ free_unused_cfgmods();
+}
+
+/*
+ * cfg verbose routine to dump names of expanded library files
+ */
+static void dump_lib_expand(void)
+{
+ struct cfglib_t *lbp;
+ struct libel_t *lbep;
+
+ __cv_msg("  Library expasion file names:\n");
+ for (lbp = __cfglib_hd; lbp != NULL; lbp = lbp->lbnxt)
+  {
+   __cv_msg("  Libname %s\n", lbp->lbname);
+   for (lbep = lbp->lbels; lbep != NULL; lbep = lbep->lbenxt)
+    {
+     __cv_msg("    %s\n", lbep->lbefnam);
+    }
+  }
+}
+
+static void dump_config_info(void)
+{
+ char typ[RECLEN];
+ struct cfg_t *cfgp;
+ struct cfgdes_t *desp;
+ struct cfgrule_t *rulp;
+ struct cfgnamlst_t *cnlp;
+
+ __cv_msg("\n  DUMPING CONFIG INFORMAION:\n");
+ dump_lib_expand();
+ for (cfgp = __cfg_hd; cfgp != NULL; cfgp = cfgp->cfgnxt)
+  {
+   __cv_msg("    Config %s in %s lineno %d \n", cfgp->cfgnam, cfgp->cfg_fnam, 
+    cfgp->cfg_lno);
+
+   /* dump design info */
+   for (desp = cfgp->cfgdeslist; desp != NULL; desp = desp->desnxt)
+    {
+     __cv_msg("      Design %s \n", desp->deslbnam); 
+    }
+
+   /* dump rule default info */
+   if (cfgp->cfgdflt != NULL) __cv_msg("    Default rule:\n"); 
+   rulp = cfgp->cfgdflt;
+   for (cnlp = rulp->rul_libs; cnlp != NULL; cnlp = cnlp->cnlnxt)
+    {
+     __cv_msg("      %s \n", cnlp->nam); 
+    }
+
+   /* dump rule info */
+   for (rulp = cfgp->cfgrules; rulp != NULL; rulp = rulp->rulnxt)
+    {
+     __cv_msg("    Rule \n"); 
+     if (rulp->rultyp == CFG_INSTANCE)
+        strcpy(typ, "Instance");
+     else
+        strcpy(typ, "Cell");
+     if (rulp->use_rule_cfg)
+       __cv_msg("      %s %s using hierarchical config : %s\n", 
+         typ, rulp->objnam, rulp->rul_use_celnam); 
+     else if (rulp->is_use)
+        __cv_msg("      %s %s use %s.%s\n", rulp->objnam, 
+          typ, rulp->rul_use_libnam, rulp->rul_use_celnam); 
+     else
+      {
+       __cv_msg("      %s %s liblist:\n", typ, rulp->objnam); 
+       for (cnlp = rulp->rul_libs; cnlp != NULL; cnlp = cnlp->cnlnxt)
+        {
+         __cv_msg("       %s \n", cnlp->nam); 
+        }
+      }
+    }
+  }
+ __cv_msg("  END CONFIG DUMP\n\n");
+}
+
+/*
+ * prepare the cfg input file stack - never more than one cfg lib file 
+ *
+ * but macro expansions and `include put on top of stack so still needed
+ * this puts one open file struct on tos and inits vinstk  
+ */
+static void prep_cfg_vflist(void)
+{
+ register int32 fi;
+
+ __last_lbf = __last_inf;
+ /* set open file/macro exp./include stack to empty */
+ for (fi = 0; fi < MAXFILNEST; fi++) __vinstk[fi] = NULL;
+ __vin_top = -1;
+ __lasttoktyp = UNDEF;
+ __last_attr_prefix = FALSE;
+ /* this builds the empty top of stack entry */
+ __push_vinfil();
+ __cur_infi = __last_inf;
+}
+
+/*
+ * build error message if the module didn't match any in the
+ * given library
+ */ 
+static void build_rule_error(struct cfg_t *cfgp, struct cfglib_t *cntxt_lbp, 
+ struct cfgrule_t *rulp)
+{
+     
+ /* if this didn't match there is no such instance */
+ if (rulp->rultyp == CFG_INSTANCE)
+  {
+   __pv_err(3576, "config %s at %s: unable to bind rule - no such module %s",
+    cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, rulp->rul_lno), 
+    rulp->objnam);
+  }
+ else if (rulp->rultyp == CFG_CELL)
+  {
+   if (rulp->libnam != NULL)
+    {
+     /* no such library cell */ 
+     __pv_err(3576,
+      "config %s at %s: unable to bind rule - no such cell %s",
+      cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, rulp->rul_lno), 
+      rulp->objnam);
+    } 
+  }
+}
+
+/*
+ * read source of and parse all cells in a design 
+ *
+ * SJM 01/09/04 FIXME ??? - must allow more than one top level design mod 
+ */
+static int32 bind_cfg_design(struct cfg_t *cfgp, int32 is_hier)
+{
+ register struct cfgdes_t *desp;
+ register struct cfgrule_t *rulp;
+ struct cfglib_t *lbp;
+ struct mod_t *mdp;
+
+ if (is_hier)
+  {
+   if (cfgp->cfgdeslist == NULL || cfgp->cfgdeslist->desnxt != NULL)
+    {
+     __pv_err(3571,
+      "hierarchical config %s at %s - only one design statement allowed", 
+      cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, cfgp->cfg_lno));
+     return(FALSE);
+    }
+  }
+
+ for (desp = cfgp->cfgdeslist; desp != NULL; desp = desp->desnxt)
+  {
+   if (desp->deslbnam == NULL)
+    {
+     /* SJM 01/09/04 - FIXME - need to use default rule */
+     __pv_err(3571, "config %s at %s: design library name missing",
+      cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, cfgp->cfg_lno));
+
+     /* --- DBG remove -- */
+     __misc_terr(__FILE__, __LINE__);
+     /* --- */
+    }
+
+   if ((lbp = find_cfglib(desp->deslbnam)) == NULL)
+    {
+     __pv_err(3572, "config %s at %s: unable to find design library %s", 
+      cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, cfgp->cfg_lno),
+      desp->deslbnam);
+     continue;
+    }
+   desp->deslbp = lbp;
+ 
+   /* find the top level module in library lbp and parse source of file it */ 
+   /* is in - normally will be in file by itself */
+
+   /* SJM 01/13/04 - may not be top mod but from config view work down */
+   /* design modules can be non top mods (instantiated somewhere) but */   
+   /* that just works because sub tree just gets bound */
+   /* SJM 01/13/04 - FIXME - but that means inst and type names must be same */
+   if (desp->topmodnam == NULL)
+    {
+     __pv_err(3573,
+      "config %s at %s: top level design module name missing - for design lib %s", 
+      cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, cfgp->cfg_lno),
+      desp->deslbnam);
+     continue;
+    }
+
+   if ((mdp = find_cell_in_cfglib(desp->topmodnam, lbp)) == NULL)
+    {
+     __pv_err(3574,
+      "config %s at %s: unable to find design top level module %s in library %s", 
+      cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, cfgp->cfg_lno),
+      desp->topmodnam, desp->deslbnam);
+     continue;
+    }
+
+   /* can't use undef hd list because only undef inst mod types from */
+   /* the one design top mod added - rest of the mods must be read and */
+   /* parsed but there cells can't be added to undef list */
+ 
+   /* free undef list added from reading one config top level module */
+   free_undef_list();
+ 
+   __last_bind_comp_ndx = 0;
+   __bind_inam_comptab[0] = __pv_stralloc(mdp->msym->synam);
+
+   /* SJM 05/18/04 - binding of mdp uses current cfg library */
+   mdp->mod_cfglbp = lbp;
+   
+   /* AIV rare case with instance/cell rules but no undefined mods */
+   /* that means rules are not matched */
+   if (mdp->mcells == NULL)
+    {
+     for (rulp = cfgp->cfgrules; rulp != NULL; rulp = rulp->rulnxt)
+      {
+       /* just warn because no cells need mapping */
+       /* AIV LOOKATME message can msym be NULL here ?? */
+       __pv_warn(3122,
+        "config %s at %s: unable to bind rule - no modules to map in design %s module %s",
+        cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, rulp->rul_lno),
+        desp->deslbnam, mdp->msym != NULL ? mdp->msym->synam : "undefined");
+      }
+    }
+   else
+    {
+     bind_cells_in1mod(cfgp, desp->deslbp, mdp);
+     /* emit errors for hierarchical paths in rules that do not exist */
+     for (rulp = cfgp->cfgrules; rulp != NULL; rulp = rulp->rulnxt)
+      {
+       if (!rulp->matched)
+        {
+         build_rule_error(cfgp, desp->deslbp, rulp);
+        }
+      }
+    } 
+   /* DBG remove -- */
+   if (__last_bind_comp_ndx > 0) __misc_terr(__FILE__, __LINE__);
+   /* -- */
+   __my_free(__bind_inam_comptab[0], strlen(__bind_inam_comptab[0]) + 1);
+   __last_bind_comp_ndx = -1;
+  }
+ return(TRUE);
+}
+
+/*
+ * build a **<file>(<line. no.) reference for config where in fils not used
+ * this chops file name so know will fit
+ * s must be at least RECLEN wide
+ */
+extern char *__cfg_lineloc(char *s, char *fnam, int32 fnlcnt)
+{
+ char s1[RECLEN];
+
+ sprintf(s, "**%s(%d)", __schop(s1, fnam), fnlcnt);
+ return(s);
+}
+
+/*
+ * find a library by name
+ */
+static struct cfglib_t *find_cfglib(char *lbnam)
+{
+ struct cfglib_t *lbp;
+
+ for (lbp = __cfglib_hd; lbp != NULL; lbp = lbp->lbnxt) 
+  {
+   if (strcmp(lbp->lbname, lbnam) == 0) return(lbp);
+  }
+ return(NULL);
+}
+
+/*
+ * free (empty) undef list
+ *
+ * because config file reading requires parsing all modules in any file
+ * read, can't use undef hd list - must scan cells and resolve
+ * from mcells whose mod type symbol is syundefmod
+ */
+static void free_undef_list(void)
+{
+ struct undef_t *undefp, *undefp2;
+
+ /* final step is to free temp undef list */
+ for (undefp = __undefhd; undefp != NULL;) 
+  {
+   undefp2 = undefp->undefnxt;
+   __my_free((char *) undefp, sizeof(struct undef_t)); 
+   undefp = undefp2;
+  }
+ /* SJM 02/24/05 - must set tail to nil too */
+ __undefhd = __undeftail = NULL;
+}
+
+/*
+ * ROUTINES TO BIND CELLS
+ */
+
+/*
+ * bind all cells inside one already bound module
+ */
+static void bind_cells_in1mod(struct cfg_t *cfgp, struct cfglib_t *cntxt_lbp,
+ struct mod_t *mdp)
+{
+ register struct cfgrule_t *rulp;
+ register struct libel_t *lbep;
+ int32 cell_matched;
+ struct cell_t *cp;
+ struct sy_t *lbsyp;
+ char *mnp;
+ 
+ mdp->cfg_scanned = TRUE;
+ for (cp = mdp->mcells; cp != NULL; cp = cp->cnxt)
+  {
+   if (!cp->cmsym->syundefmod) continue;
+   cell_matched = FALSE;
+   for (rulp = cfgp->cfgrules; rulp != NULL; rulp = rulp->rulnxt)  
+    {
+     if (!try_match_rule(cntxt_lbp, cp, rulp)) continue; 
+  
+     if (__cfg_verbose)
+      {
+       __cv_msg("  ** Rule matched for instance: %s (%s:%s) for rule config file: %s at line %d.\n\n",   
+        cp->csym->synam, __in_fils[cp->cmsym->syfnam_ind], 
+        mdp->msym->synam, cfgp->cfg_fnam, rulp->rul_lno);
+      }
+    
+     if (cell_matched)
+      {
+       __pv_warn(3123, "config %s at %s: overriding previous defined matching rule(s)", 
+        cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, rulp->rul_lno));
+      }
+
+     /* SJM 05/18/04 - cells inside bound to this lib (for %l) */
+     mdp->mod_cfglbp = cntxt_lbp;
+    
+     cell_matched = TRUE;
+     /* if it gets here the module exists so mark as TRUE */
+     rulp->matched = TRUE; 
+     if (!rulp->is_use)
+      {
+       if (!bind_liblist_rule(cfgp, cp, rulp))
+        {
+         /* AIV 06/01/04 - FIXME should print out the entire liblist */ 
+         /* unable to match type of the ins mod in the specified library */
+         __pv_err(3577,
+          "config %s at %s: unable to bind instance rule - module type (%s) never found in liblist (line number %d)",
+          cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, rulp->rul_lno),
+          cp->cmsym->synam, rulp->rul_lno);
+        }
+      }
+     else if (!bind_use_rule(cfgp, cntxt_lbp, cp, rulp))
+      {
+       /* Unable to match the use type of the mod in the specified lib */
+       __pv_err(3578, "config %s at %s: unable to bind use rule - module type (%s) never found in library (%s)",
+       cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, rulp->rul_lno),
+       cp->cmsym->synam, rulp->objnam);
+      }
+      goto nxt_cell;
+    }
+ 
+   /* AIV if a file read via a rule, and in the file it contains mod 'foo' */
+   /* it must also bind the 'foo' in the file without a rule */
+   /* AIV LOOKATME ### ??? - is there a better way to do this */
+   /* get the current file name */
+   if (mdp->mod_last_ifi == - 1) goto nxt_cell; 
+   mnp = __in_fils[mdp->mod_last_ifi]; 
+   for (lbep = cntxt_lbp->lbels; lbep != NULL; lbep = lbep->lbenxt)
+    {
+     /* match the name of the expanded library file name */
+     if (strcmp(lbep->lbefnam, mnp) == 0)
+      {
+       /* find the symbol to be bound in the library symbol table */
+       if ((lbsyp = __get_sym(cp->cmsym->synam, lbep->lbel_sytab)) != NULL) 
+        {
+         /* bind the cell symbols */
+         cp->cmsym = lbsyp;
+         cp->cmsym->cfg_needed = TRUE;
+
+         if (__cfg_verbose)
+          {
+           __cv_msg("  ++ Bound in config: %s\n      instance: %s (%s:%s) bound to cell: %s in module: %s from file: %s in library: %s (SCANNED).\n\n",  
+            cfgp->cfgnam, cp->csym->synam, __in_fils[cp->csym->syfnam_ind], 
+            cp->cmsym->synam, lbsyp->synam, mdp->msym->synam,
+            mnp, cntxt_lbp->lbname);
+           }
+          /* cells inside bound to this lib (for %l) */
+          cp->cmsym->el.emdp->mod_cfglbp = cntxt_lbp;
+
+          /* if a module the unconnected module could have mods */
+          /* that need to be connected as well  */
+          /* if the connecting cell hasn't been sanned and is mod check it */
+          if (!cp->cmsym->el.emdp->cfg_scanned && cp->cmsym->sytyp == SYM_M
+           && mdp->mcells != NULL)
+           {
+            if (__cfg_verbose)
+             {
+              __cv_msg("Binding cells in module: %s in file: %s.\n",
+               mdp->msym->synam, mnp);
+             }
+            if (++__last_bind_comp_ndx >= __siz_bind_comps) grow_bind_comps();
+            __bind_inam_comptab[__last_bind_comp_ndx] = 
+            __pv_stralloc(cp->csym->synam);
+
+            /* bind cells in this one passing lib used to bind this one */
+            bind_cells_in1mod(cfgp, cntxt_lbp, cp->cmsym->el.emdp);
+           
+            __my_free(__bind_inam_comptab[__last_bind_comp_ndx],
+            strlen(__bind_inam_comptab[__last_bind_comp_ndx]) + 1);
+            __last_bind_comp_ndx--;
+           }
+          goto nxt_cell;
+         }
+       }
+     }
+
+   /* must match rules in order */
+   if ((rulp = cfgp->cfgdflt) != NULL)
+    {
+     /* notice default is always liblist form rule - never use form */
+     if (bind_liblist_rule(cfgp, cp, rulp)) goto nxt_cell;
+    }
+   /* error message if cound not bind cell */
+   __pv_err(3575,
+    "config %s at %s: unable to bind cell %s (instance %s) (current lib %s in file %s:%d) - no rule matches",
+    cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, cfgp->cfg_lno),
+    cp->cmsym->synam, cp->csym->synam, cntxt_lbp->lbname,
+     __in_fils[cp->csym->syfnam_ind], cp->csym->sylin_cnt); 
+
+   nxt_cell:;
+  } 
+}
+
+/*
+ * routine to attempt to match one rule and return T if matches
+ * does not bind
+ */
+static int32 try_match_rule(struct cfglib_t *cntxt_lbp, struct cell_t *cp,
+ struct cfgrule_t *rulp)
+{
+ register int32 ci;
+     
+ if (rulp->rultyp == CFG_INSTANCE)
+  {
+   /* match inst */
+   if (!cp->c_named) return(FALSE);
+
+   if (strcmp(cp->csym->synam, rulp->inam_comptab[rulp->inam_comp_lasti])
+    != 0) return(FALSE);
+
+   /* if instance path length from config design root different */
+   /* then can't match */
+   if (__last_bind_comp_ndx + 1 != rulp->inam_comp_lasti) return(FALSE);
+
+   for (ci = __last_bind_comp_ndx; ci >= 0; ci--)
+    {
+     if (strcmp(__bind_inam_comptab[ci], rulp->inam_comptab[ci]) != 0)
+      return(FALSE);
+    }
+   return(TRUE);
+  }
+ else if (rulp->rultyp == CFG_CELL)
+  {
+   if (rulp->libnam != NULL && rulp->libnam[0] != '\0')
+    {
+     if (strcmp(rulp->libnam, cntxt_lbp->lbname) != 0) return(FALSE);
+    }
+   if (strcmp(cp->cmsym->synam, rulp->objnam) == 0) return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * bind instance rule with liblist clause - return T if succeeds else F
+ */
+static int32 bind_liblist_rule(struct cfg_t *cfgp, struct cell_t *cp,
+ struct cfgrule_t *rulp)
+{
+ struct cfgnamlst_t *cnlp;
+ struct cfglib_t *lbp;
+ struct mod_t *bind_mdp;
+ char s1[RECLEN];
+
+ /* match every lib in lib list in order until find match or fail */
+ for (cnlp = rulp->rul_libs; cnlp != NULL; cnlp = cnlp->cnlnxt)
+  {
+   /* find the current lib */
+   if ((lbp = find_cfglib(cnlp->nam)) == NULL)
+    {
+     if (rulp->rultyp == CFG_DEFAULT)
+       strcpy(s1, "default");
+     else
+       strcpy(s1, rulp->objnam);
+
+     __pv_err(3571,
+      "config %s at %s: binding object %s lib list clause library %s not found",
+      cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, cfgp->cfg_lno),
+      s1, cnlp->nam);
+     continue;
+    }
+
+   /* attempt to bind - cp is cell containing */
+   if ((bind_mdp = find_cell_in_cfglib(cp->cmsym->synam, lbp)) == NULL)
+    continue;
+   
+   /* AIV 05/18/04 - binding of mdp uses current cfg library */
+   bind_mdp->mod_cfglbp = lbp;
+
+   /* this does the binding */
+   cp->cmsym = bind_mdp->msym;
+   cp->cmsym->cfg_needed = TRUE;
+
+   if (__cfg_verbose)
+    {
+     if (rulp->rultyp == CFG_DEFAULT)
+       strcpy(s1, "default");
+     else
+       strcpy(s1, rulp->objnam);
+      __cv_msg("  ++ Bound in config: %s\n      instance: %s (%s:%s) bound to cell: %s in library: %s (%s) (LIBLIST %s).\n\n",  
+         cfgp->cfgnam, cp->csym->synam, __in_fils[cp->cmsym->syfnam_ind], 
+         cp->cmsym->synam, bind_mdp->msym->synam,  lbp->lbname, 
+         __in_fils[bind_mdp->msym->syfnam_ind], s1);
+    }
+
+   /* bind cells inside */
+   bind_cells_inside(cfgp, cp, bind_mdp, lbp);
+   return(TRUE);
+  } 
+ return(FALSE);
+}
+
+/*
+ * bind use rule
+ *
+ * use clause - easy because [lib].cell explicitly given
+ * SJM 01/14/03 - WRITEME - handle different cfg (:config)
+ */
+static int32 bind_use_rule(struct cfg_t *cfgp, struct cfglib_t *cntxt_lbp,
+ struct cell_t *cp, struct cfgrule_t *rulp)
+{
+ struct cfg_t *use_replace_cfgp;
+ struct cfglib_t *lbp;
+ struct mod_t *bind_mdp;
+ struct sy_t *msyp;
+
+ /* if use clause heirarchical config form find the config to use */ 
+ if (rulp->use_rule_cfg)
+  {
+   if ((use_replace_cfgp = fnd_cfg_by_name(rulp->rul_use_celnam)) == NULL)
+    {
+     __pv_err(3579,
+      "config %s at %s: hierichical use clause config name %s undefined - config not changed",
+      cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, cfgp->cfg_lno),
+      rulp->rul_use_celnam);
+    }
+
+   if (bind_cfg_design(use_replace_cfgp, TRUE))
+    {
+     /* SJM 05/18/04 - BEWARE - assuming (and must check) only one */
+     /* design statement for hierarchical sub configs */
+     if ((msyp = __get_sym(use_replace_cfgp->cfgdeslist->topmodnam,
+      __modsyms)) != NULL) 
+      cp->cmsym = msyp;
+     cp->cmsym->cfg_needed = TRUE;
+     if (__cfg_verbose)
+      {
+       __cv_msg("  ++ Bound in config: %s using hierarchical config: %s\n      binding instance: %s (%s:%s) bound to cell: %s (%s) (USE CLAUSE).\n\n",  
+       cfgp->cfgnam, use_replace_cfgp->cfgnam, cp->csym->synam, 
+       __in_fils[cp->cmsym->syfnam_ind], cp->cmsym->synam, msyp->synam,
+        __in_fils[msyp->syfnam_ind]);
+      }
+    }
+   return(TRUE);
+  }
+
+ if (rulp->rul_use_libnam == NULL || rulp->rul_use_libnam[0] == '\0') 
+  {
+   lbp = cntxt_lbp;
+  }
+ else
+  { 
+   if ((lbp = find_cfglib(rulp->rul_use_libnam)) == NULL)
+    {
+     __pv_err(3571,
+      "config %s at %s: object %s use clause %s:%s library %s not found",
+      cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, cfgp->cfg_lno),
+      rulp->objnam, rulp->rul_use_libnam, rulp->rul_use_celnam,
+      rulp->rul_use_libnam);
+     return(FALSE);
+    }
+  }
+
+ /* use the rul_use ins name 'use lib.rul_use_celnam' */
+ if ((bind_mdp = find_cell_in_cfglib(rulp->rul_use_celnam, lbp)) == NULL)
+  {
+    __pv_err(3573, "config %s at %s: object %s use clause %s.%s cell %s not found",
+     cfgp->cfgnam, __cfg_lineloc(__xs, cfgp->cfg_fnam, cfgp->cfg_lno),
+     rulp->objnam, lbp->lbname, rulp->rul_use_celnam,
+     rulp->rul_use_celnam);
+    return(FALSE);
+   }
+
+ /* bind the library name (%l) */
+ bind_mdp->mod_cfglbp = lbp;
+
+ /* found cell */
+ cp->cmsym = bind_mdp->msym;
+ cp->cmsym->cfg_needed = TRUE;
+ if (__cfg_verbose)
+  {
+   __cv_msg("  ++ Bound in config: %s \n       binding instance: %s (%s:%s) bound to cell: %s in library: %s (%s) (USE CLAUSE).\n\n",  
+   cfgp->cfgnam, cp->csym->synam, __in_fils[cp->cmsym->syfnam_ind], 
+   cp->csym->synam, bind_mdp->msym->synam, lbp->lbname, 
+   __in_fils[bind_mdp->msym->syfnam_ind]);
+  }
+
+ /* bind cells inside */
+ bind_cells_inside(cfgp, cp, bind_mdp, lbp);
+ return(TRUE);
+}
+
+/*
+ * find a config given a cfg name
+ */
+static struct cfg_t *fnd_cfg_by_name(char *confnam)
+{
+ register struct cfg_t *cfgp;
+
+ for (cfgp = __cfg_hd; cfgp != NULL; cfgp = cfgp->cfgnxt)
+  {
+   if (strcmp(cfgp->cfgnam, confnam) == 0)
+    {
+     return(cfgp);
+    }
+  }
+ return(NULL);
+}
+
+/*
+ * after binding one cell bind cells depth first inside it
+ */
+static void bind_cells_inside(struct cfg_t *cfgp, struct cell_t *cp,
+ struct mod_t *bind_mdp, struct cfglib_t *lbp)
+{
+ if (++__last_bind_comp_ndx >= __siz_bind_comps) grow_bind_comps();
+ __bind_inam_comptab[__last_bind_comp_ndx] = __pv_stralloc(cp->csym->synam);
+
+ /* bind cells in this one passing library used to bind this one */
+ bind_cells_in1mod(cfgp, lbp, bind_mdp);
+           
+ __my_free(__bind_inam_comptab[__last_bind_comp_ndx],
+   strlen(__bind_inam_comptab[__last_bind_comp_ndx]) + 1);
+ __last_bind_comp_ndx--;
+}
+
+/*
+ * ROUTINE TO FIND A CFG CELL IN A LIBRARY AND FIRST PASS READ SRC 
+ */
+
+/*
+ * find a cell in a config library list of cells
+ *
+ * if config library file compiled, find pre-fixup d.s module (cell)
+ * else read all source in file and search for cell
+ *
+ * keeps reading until finding cell or reaching end of library file list
+ * if any part of file is read all cells in file are read and put in
+ * lib el's symbol table with ptr to mod pre-fixup d.s. 
+ */
+static struct mod_t *find_cell_in_cfglib(char *celnam, struct cfglib_t *lbp)
+{
+ register struct libel_t *lbep;
+ struct sy_t *msyp;
+
+ for (lbep = lbp->lbels; lbep != NULL; lbep = lbep->lbenxt)
+  {
+   if (!lbep->lbelsrc_rd)
+    {
+     /* move keep adding files read into in fils for error locations */
+     if (++__last_lbf >= __siz_in_fils) __grow_infils(__last_lbf);
+     __in_fils[__last_lbf] = __pv_stralloc(lbep->lbefnam);
+
+     /* returns F and emits error if can't open llb file */
+     if (!open_cfg_lbfil(lbp->lbname)) continue;
+
+     rd_cfg_srcfil(lbep);
+     lbep->lbelsrc_rd = TRUE;
+    }
+
+   /* AIV - 05/24/04 - the rare case there is no symbol table */
+   /* if the source only contains `define, `tiemscale, etc, continue */
+   if (lbep->lbel_sytab == NULL) continue;
+   if ((msyp = __get_sym(celnam, lbep->lbel_sytab)) != NULL) 
+   {
+    return(msyp->el.emdp); 
+   }
+  }
+ return(NULL);
+}
+
+/*
+ * try to open the config library file and repl. top of stack with its info
+ *
+ * except for includes and macros size of vinstk will always be 1
+ * file must be openable and have contents
+ * return F on fail
+ * in fils of last lbf must be filled with file name
+ * since know last_lbf > last_inf - on EOF get_vtok will resturn to caller
+ */
+static int32 open_cfg_lbfil(char *lbnam)
+{
+ char dirstr[RECLEN]; 
+
+ /* know called with last_lbf index of file to process */
+ __cur_fnam = __in_fils[__last_lbf];
+ /* AIV PUTBACK print directory for now - for debugging */
+ if ((__in_s = __tilde_fopen(__cur_fnam, "r")) == NULL)
+  {
+   __pv_err(710, "cannot open config library %s file %s in dir : %s - skipped",
+    lbnam, __cur_fnam,  getcwd(dirstr, RECLEN)); 
+   return(FALSE);
+  }
+ if (feof(__in_s))
+  {
+   __pv_warn(512, "config library %s file %s empty", lbnam, __cur_fnam);
+   return(FALSE);
+  }
+ /* whenever open new file must discard pushed back */
+ __lasttoktyp = UNDEF;
+ __visp->vi_s = __in_s;
+ __visp->vifnam_ind = __last_lbf;
+ __cur_fnam_ind = __last_lbf;
+ __cur_fnam = __in_fils[__cur_fnam_ind];
+ __lin_cnt = 1;
+ __file_just_op = TRUE;
+ if (__cfg_verbose)
+  {
+   __cv_msg("  Parsing config library %s file \"%s\".\n", lbnam, __cur_fnam);
+  }
+ return(TRUE);
+}
+
+/*
+ * read cfg source file to find and elaborate current module
+ *
+ * read src and to lbel symbol table for every module in library
+ */
+static void rd_cfg_srcfil(struct libel_t *lbep)
+{
+ __get_vtok();
+ if (__toktyp == TEOF)
+  {
+   __pv_fwarn(609, "config library file %s contains no tokens",
+    lbep->lbefnam);
+   /* since empty, mark so not re-read */
+   lbep->lbelsrc_rd = TRUE;
+   return;
+  }
+
+ for (;;)
+  {
+   /* may be a compiler directive */
+   if (__toktyp >= CDIR_TOKEN_START && __toktyp <= CDIR_TOKEN_END)
+    {
+     __process_cdir();
+     goto nxt_tok;
+    }
+   switch ((byte) __toktyp) {
+    case TEOF: return;
+    case MACROMODULE:
+     __get_vtok();
+     __finform(423,
+      "macromodules in config library not expanded - %s translated as module",
+      __token);
+     goto chk_name;
+    case MODULE:
+     __get_vtok();
+chk_name:
+     if (__toktyp != ID)
+      {
+       __pv_ferr(707, "config library file module name expected - %s read",
+        __prt_vtok());
+       /* since error, just try to resynchronize */
+       __vskipto_modend(ENDMODULE);
+       goto nxt_tok;
+      }
+     if (!init_chk_cfg_sytab(lbep, "module"))
+      {
+       __vskipto_modend(ENDMODULE);
+       goto nxt_tok;
+      }
+
+     /* know error here will cause skipping to file level thing */
+     /* this adds mod name to lbel one file's symbol table */
+     if (!__rd_moddef(lbep->lbel_sytab, TRUE)) goto nxt_tok;
+
+     /* when reading source this was set only if in cell define region */
+     /* now turn on (maybe again) if all library modules are cells */
+     /* dummy itstk empty here but if good module read mark as cell */
+     if (__lib_are_cells && __last_libmdp != NULL)
+      {
+       __last_libmdp->m_iscell = TRUE;
+       __design_has_cells = TRUE;
+      }
+     __last_libmdp = NULL;
+     /* know to get here 1 more resolved */
+     break;
+
+    case PRIMITIVE:
+     __get_vtok();
+     if (__toktyp != ID)
+      {
+       __pv_ferr(708,
+        "config library file udp primitive name expected - %s read",
+        __prt_vtok());
+       /* since err, just try to skip to end primitive */
+       __vskipto_modend(ENDPRIMITIVE);
+       goto nxt_tok;
+      }
+     if (!init_chk_cfg_sytab(lbep, "udp primitive"))
+      {
+       __vskipto_modend(ENDPRIMITIVE);
+       goto nxt_tok;
+      }
+
+     if (!__rd_udpdef(lbep->lbel_sytab)) goto nxt_tok;
+     break;
+    default:
+     __pv_ferr(709,
+     "config library file module, primitive or directive expected - %s read",
+      __prt_vtok());
+     /* here just ignores extra semicolons */
+     if (__toktyp != SEMI) __vskipto2_modend(ENDMODULE, ENDPRIMITIVE);
+   }
+nxt_tok:
+   /* why checking this twice */
+   if (__toktyp == TEOF)
+    {
+chk_ifdef:
+     if (__in_ifdef_level != 0)
+      {
+       __pv_err(924, "last `ifdef unterminated in config libary file %s",
+        __cur_fnam);
+      }
+     break;
+    }
+   __get_vtok();
+   if (__toktyp == TEOF) goto chk_ifdef;
+  }
+}
+
+/*
+ * check module/udp name and alloc lib el symbol table if needed
+ * returns F on error
+ */
+static int32 init_chk_cfg_sytab(struct libel_t *lbep, char *celtyp)
+{
+ struct sy_t *syp;
+
+ /* if first mod in file, build the lbel's symbol table */ 
+ if (lbep->lbel_sytab == NULL) lbep->lbel_sytab = __alloc_symtab(FALSE);
+
+ /* check to see if name repeated in this library file */
+ if ((syp = __get_sym(__token, lbep->lbel_sytab)) != NULL) 
+  {
+   __pv_ferr(3474,
+    "%s %s repeated in config library file %s - previous at %s",
+    celtyp, syp->synam, lbep->lbefnam,
+    __bld_lineloc(__xs, syp->syfnam_ind, syp->sylin_cnt));
+   return(FALSE);
+  }
+
+ if (__lib_verbose)
+  {
+   __cv_msg("  Scanning config library %s %s (%s).\n",
+    lbep->lbefnam, celtyp, __token);
+  } 
+ return(TRUE);
+}
+
+/*
+ * ROUTINES TO FREE COMPILED LIBRARY MODULE NEVER INSTANTIATED
+ */
+static void add_cfgsym(char *libnam, struct tnode_t *tnp)
+{
+ struct tnode_t *ntnp;
+ char s1[RECLEN];
+
+  if (tnp == NULL) return;
+  add_cfgsym(libnam, tnp->lp);
+
+  // AIV FIXME ??? sprintf(s1, "%s.%s", libnam, tnp->ndp->synam);
+  if (tnp->ndp->cfg_needed)
+   {
+    strcpy(s1, tnp->ndp->synam);
+    ntnp = __vtfind(s1, __modsyms);
+   //AIV FIXME ###
+    if (!__sym_is_new)
+     {
+      __fterr(305,
+       "Sorry - config code to rename module with same name from different libraries not implemented yet.");
+     }
+    __add_sym(s1, ntnp);
+    ntnp->ndp = tnp->ndp;
+    strcpy(ntnp->ndp->synam, s1);
+    ntnp->ndp->sydecl = TRUE;
+    (__modsyms->numsyms)++;
+   }
+  add_cfgsym(libnam, tnp->rp);
+}
+
+
+/* 
+ * add all the used symbols from a config to __modsyms
+ */
+static void add_cfg_libsyms(struct cfglib_t *cfgp)
+{
+ struct libel_t *lbp;
+ struct symtab_t *symt;
+ struct tnode_t *tnp;
+ char *cp;
+ int32 i;
+
+
+ for (lbp = cfgp->lbels; lbp != NULL; lbp = lbp->lbenxt)
+  {
+   if ((symt = lbp->lbel_sytab) == NULL) continue;
+   if (symt->stsyms != NULL)
+    {
+     for (i = 0; i < symt->numsyms; i++)
+      {
+       if (!symt->stsyms[i]->cfg_needed) continue;
+       cp = symt->stsyms[i]->synam;
+       tnp = __vtfind(cp, __modsyms);
+      //AIV FIXME ###
+       if (!__sym_is_new)
+        {
+         __fterr(305,
+          "Sorry - config code to rename module with same name from different libraries not implemented yet.");
+        }
+       __add_sym(cp, tnp);
+       (__modsyms->numsyms)++;
+       tnp->ndp = symt->stsyms[i];
+      }
+    }
+   else
+    {
+       add_cfgsym(cfgp->lbname, symt->n_head);
+    }
+  }
+}
+
+
+/* 
+ * removes all modules that were scanned in from config libraries 
+ * but are never needed remove from the __modhdr list
+ */
+static void free_unused_cfgmods(void)
+{
+ struct mod_t *mdp, *mdp2, *last_mdp; 
+ long sav_mem_use;
+
+//AIV FIXME ### need to free
+ __modsyms = NULL;
+ __modsyms = __alloc_symtab(FALSE);
+ __sym_addprims();
+ sav_mem_use = __mem_use;
+ last_mdp = NULL;
+ for (mdp = __modhdr; mdp != NULL;)
+  {
+   mdp2 = mdp->mnxt;
+
+   /* if module is from a config and hasn't been linked to a library rm */
+   if (mdp->m_inconfig && mdp->mod_cfglbp == NULL)
+    {
+     /* SJM 05/28/04 FIXME ### ??? - need to do some freeing of libs */
+     /* partially_free_mod(mdp); */
+
+     if (last_mdp != NULL) last_mdp->mnxt = mdp2;
+     mdp = mdp2;
+     continue;
+    }
+   if (!mdp->mod_cfglbp->sym_added)
+   {
+     add_cfg_libsyms(mdp->mod_cfglbp);
+     mdp->mod_cfglbp->sym_added = TRUE;
+   }
+   last_mdp = mdp;
+   mdp = mdp2;
+  }
+ /* AIV 05/31/05 - FIXME ### if not freeing no need to print message */
+ /*
+ if (__cfg_verbose)
+  {
+   __cv_msg(
+   "  Config freeing most memory in unused library modules - %ld bytes freed\n",
+    sav_mem_use - __mem_use);
+  }
+  */
+}
+
+/* 
+ * partially free a module (just the larger parts such as stmts and cells)
+ *
+ * for now freeing most of the inisdes of modules that were parsed during
+ * config library loading - eventually will moved to precompiled lib scheme
+ * so this will be removed
+ *
+ * not free mdp but now nothing points to it
+ *
+ * SJM 05/26/04 - LOOKATME - since only free large d.s. in modules there is
+ * quite a bit of memory leakage here
+ */
+static void partially_free_mod(struct mod_t *mdp)
+{
+ register struct cell_t *cp, *cp2;
+
+ for (cp = mdp->mcells; cp != NULL; )
+  {
+   cp2 = cp->cnxt;
+   __my_free((char *) cp, sizeof(struct cell_t));
+   cp = cp2;
+  }
+
+ /* SJM 05/26/04 - LOOKATME ??? ### can't free stmt until fixup ---
+ struct ialst_t *ialp;
+ struct task_t *tskp;
+ for (ialp = mdp->ialst; ialp != NULL; ialp = ialp->ialnxt) 
+  {
+   __free_stlst(ialp->iastp);
+  }
+
+ for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
+  {
+   __free_stlst(tskp->tskst);
+  }
+ --- */
+
+}
diff --git a/src/v_tf.c b/src/v_tf.c
new file mode 100644
index 0000000..8b0a05e
--- /dev/null
+++ b/src/v_tf.c
@@ -0,0 +1,5404 @@
+/* Copyright (c) 1992-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * module to implement pli tf_ routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <stdarg.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+#include "veriuser.h"
+#include "cv_veriuser.h"
+#include "acc_user.h"
+
+/* local prototypes */
+static void check_veriusertf_table(p_tfcell);
+static void add_veriusertf_task(struct t_tfcell *);
+static void add_veriusertf_func(struct t_tfcell *);
+static int32 chk_idnam_veriusertf(char *);
+static void pli_func_checktf(struct expr_t *);
+static void pli_task_checktf(struct st_t *);
+static void call_allinsts_misctfs(int32);
+static void misc_call_misctf(struct tfrec_t *, int32);
+static struct t_tfcell *get_tfcell(struct tfrec_t *);
+static void allocset_vecval(struct t_tfnodeinfo *, struct xstk_t *, int32);
+static int32 bad_nosimtf_err(char *);
+static int32 bad_notfcontext_err(char *);
+static int32 bad_rosync_err(char *);
+static void init_nodeinfo(struct t_tfnodeinfo *);
+static void init_exprinfo(struct t_tfexprinfo *);
+static int32 get_xinfo_typ(struct expr_t *);
+static struct xstk_t *tf_pushconvfromreal(double, int32);
+static int32 delayed_str_putp(int32, int32, int32, char *, word64, int32);
+static int32 chk_putdstr(char *, int32, int32 *);
+static struct xstk_t *tftostrenval(char *, int32 *);
+static int32 to_stval(char *);
+static void cancel_dputp_toend(struct tfarg_t *, struct dltevlst_t *);
+static int32 delayed_misctf_schd(word64);
+static void bld_pvc_dces(struct expr_t *, int32);
+static void linkon_pvc_dce(struct net_t *, int32, int32, struct gref_t *, int32);
+static void rosync_call_misctf(i_tev_ndx);
+static void exec_tfarg_assign(struct tfarg_t *, struct expr_t *,
+ register word32 *, register word32 *);
+static void emit_tputd_trmsg(struct tedputp_t *, struct tfarg_t *);
+static void reinit_1tfrec(struct tfrec_t *);
+static void vprt_tferr_msg(char *, va_list, va_list);
+static void vprt_tfwarn_msg(char *, va_list, va_list);
+
+/* tf_ P1364 prototypes from veriuser.h file */
+extern void io_mcdprintf(int32 mcd, char *format, ...);
+extern void io_printf(char *format, ...);
+extern char *mc_scan_plusargs(char *plusarg);
+extern void tf_add_long(int32 *aof_lowtime1, int32 *aof_hightime1, int32 lowtime2,
+ int32 hightime2);
+extern int32 tf_asynchoff(void);
+extern int32 tf_asynchon(void);
+extern int32 tf_clearalldelays(void);
+extern int tf_compare_long(unsigned int low1, unsigned int high1,
+ unsigned int low2, unsigned int high2);
+extern int32 tf_copypvc_flag(int32 nparam);
+extern void tf_divide_long(int32 *aof_low1, int32 *aof_high1, int32 low2, int32 high2);
+extern int32 tf_dofinish(void);
+extern int32 tf_dostop(void);
+extern int32 tf_error(char *fmt, ...);
+extern int32 tf_evaluatep(int32 pnum);
+extern p_tfexprinfo tf_exprinfo(int32 pnum, p_tfexprinfo pinfo);
+extern char *tf_getcstringp(int32 nparam);
+extern char *tf_getinstance(void);
+extern int32 tf_getlongp(int32 *aof_highvalue, int32 pnum);
+extern int32 tf_getlongsimtime(int32 *aof_hightime);
+extern int32 tf_getlongtime(int32 *aof_hightime);
+extern int32 tf_getnextlongtime(int32 *aof_lowtime, int32 *aof_hightime);
+extern int32 tf_getp(int32 pnum);
+extern int32 tf_getpchange(int32 nparam);
+extern double tf_getrealp(int32 pnum);
+extern double tf_getrealtime(void);
+extern int32 tf_getsimtime(void);
+extern int32 tf_gettime(void);
+extern char *tf_getworkarea(void);
+extern int32 tf_iasynchoff(char *inst);
+extern int32 tf_iasynchon(char *inst);
+extern int32 tf_iclearalldelays(char *inst);
+extern int32 tf_icopypvc_flag(int32 nparam, char *inst);
+extern int32 tf_ievaluatep(int32 pnum, char *inst);
+extern p_tfexprinfo tf_iexprinfo(int32 pnum, p_tfexprinfo pinfo, char *inst);
+extern char *tf_igetcstringp(int32 nparam, char *inst);
+extern int32 tf_igetlongp(int32 *aof_highvalue, int32 pnum, char *inst);
+extern int32 tf_igetlongsimtime(int32 *aof_hightime);
+extern int32 tf_igetlongtime(int32 *aof_hightime, char *inst);
+extern int32 tf_igetp(int32 pnum, char *inst);
+extern int32 tf_igetpchange(int32 nparam, char *inst);
+extern double tf_igetrealp(int32 pnum, char *inst);
+extern double tf_igetrealtime(char *inst);
+extern int32 tf_igettime(char *inst);
+extern int32 tf_igettimeprecision(char *inst);
+extern int32 tf_igettimeunit(char *inst);
+extern char *tf_igetworkarea(char *inst);
+extern char *tf_imipname(char *cell);
+extern int32 tf_imovepvc_flag(int32 nparam, char *inst);
+extern p_tfnodeinfo tf_inodeinfo(int32 pnum, p_tfnodeinfo pinfo, char *inst);
+extern int32 tf_inump(char *inst);
+extern int32 tf_ipropagatep(int32 pnum, char *inst);
+extern int32 tf_iputlongp(int32 pnum, int32 lowvalue, int32 highvalue, char *inst);
+extern int32 tf_iputp(int32 pnum, int32 value, char *inst);
+extern int32 tf_iputrealp(int32 pnum, double value, char *inst);
+extern int32 tf_irosynchronize(char *inst);
+extern int32 tf_isetdelay(int32 delay, char *inst);
+extern int32 tf_isetlongdelay(int32 lowdelay, int32 highdelay, char *inst);
+extern int32 tf_isetrealdelay(double realdelay, char *inst);
+extern int32 tf_isizep(int32 pnum, char *inst);
+extern char *tf_ispname(char *cell);
+extern int32 tf_istrdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, int32 delay, int32 delaytype, char *inst);
+extern char *tf_istrgetp(int32 pnum, int32 format_char, char *inst);
+extern int32 tf_istrlongdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, int32 lowdelay, int32 highdelay, int32 delaytype, char *inst);
+extern int32 tf_istrrealdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, double realdelay, int32 delaytype, char *inst);
+extern int32 tf_isynchronize(char *inst);
+extern int32 tf_itestpvc_flag(int32 nparam, char *inst);
+extern int32 tf_itypep(int32 pnum, char *inst);
+extern void tf_long_to_real(int32 int_lo, int32 int_hi, double *aof_real);
+extern char *tf_longtime_tostr(int32 lowtime, int32 hightime);
+extern int32 tf_message(int32 level, char *facility, char *messno,
+ char *message, ...);
+extern char *tf_mipname(void);
+extern int32 tf_movepvc_flag(int32 nparam);
+extern void tf_multiply_long(int32 *aof_low1, int32 *aof_high1, int32 low2,
+ int32 high2);
+extern p_tfnodeinfo tf_nodeinfo(int32 pnum, p_tfnodeinfo pinfo);
+extern int32 tf_nump(void);
+extern int32 tf_propagatep(int32 pnum);
+extern int32 tf_putlongp(int32 pnum, int32 lowvalue, int32 highvalue);
+extern int32 tf_putp(int32 pnum, int32 value);
+extern int32 tf_putrealp(int32 pnum, double value);
+extern int32 tf_read_restart(char *blockptr, int32 blocklen);
+extern void tf_real_to_long(double real, int32 *aof_int_lo, int32 *aof_int_hi);
+extern int32 tf_rosynchronize(void);
+extern void tf_scale_longdelay(char *cell, int32 delay_lo, int32 delay_hi,
+ int32 *aof_delay_lo, int32 *aof_delay_hi);
+extern void tf_scale_realdelay(char *cell, double realdelay,
+ double *aof_realdelay);
+extern int32 tf_setdelay(int32 delay);
+extern int32 tf_setlongdelay(int32 lowdelay, int32 highdelay);
+extern int32 tf_setrealdelay(double realdelay);
+extern int32 tf_setworkarea(char *workarea);
+extern int32 tf_sizep(int32 pnum);
+extern char *tf_spname(void);
+extern int32 tf_strdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, int32 delay, int32 delaytype);
+extern char *tf_strgetp(int32 pnum, int32 format_char);
+extern char *tf_strgettime(void);
+extern int32 tf_strlongdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, int32 lowdelay, int32 highdelay, int32 delaytype);
+extern int32 tf_strrealdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, double realdelay, int32 delaytype);
+extern void tf_subtract_long(int32 *aof_lowtime1, int32 *aof_hightime1,
+ int32 lowtime2, int32 hightime2);
+extern int32 tf_synchronize(void);
+extern int32 tf_testpvc_flag(int32 nparam);
+extern int32 tf_text(char *fmt, ...);
+extern int32 tf_typep(int32 pnum);
+extern void tf_unscale_longdelay(char *cell, int32 delay_lo, int32 delay_hi,
+ int32 *aof_delay_lo, int32 *aof_delay_hi);
+extern void tf_unscale_realdelay(char *cell, double realdelay,
+ double *aof_realdelay);
+extern int32 tf_warning(char *fmt, ...);
+extern int32 tf_write_save(char *blockptr, int32 blocklen);
+extern void __dce_turn_chg_store_on(struct mod_t *, struct dcevnt_t *, int32);  
+extern int32 __is_lnegative(word32 *, int32); 
+
+/* extern prototypes (maybe defined in this module) */
+extern struct systsk_t *__alloc_systsk(void);
+extern struct sysfunc_t *__alloc_sysfunc(void);
+extern void __pli_func_sizetf(struct expr_t *);
+extern void __call_all_checktfs(void);
+extern void __call_misctfs_streset(void);
+extern void __call_misctfs_endreset(void);
+extern void __call_misctfs_simstart(void);
+extern void __call_misctfs_iact(void);
+extern void __call_misctfs_finish(void);
+extern void __call_misctfs_scope(void);
+extern char *__get_tfcellnam(struct tfrec_t *);
+extern void __pli_func_calltf(struct expr_t *);
+extern void __pli_task_calltf(struct st_t *);
+extern char *__alloc_vval_to_cstr(word32 *, int32, int32, int32);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern struct xstk_t *__putdstr_to_val(char *, int32, int32, int32);
+extern struct dltevlst_t *__spliceout_last(register struct dltevlst_t *);
+extern struct dltevlst_t *__find_last_bdltevp(register struct dltevlst_t *, word64);
+extern void __pli_dofinish(int32, char *);
+extern void __pvc_call_misctf(struct dcevnt_t *);
+extern void __exec_rosync_misctf(void);
+extern void __sync_call_misctf(struct tev_t *);
+extern void __setdel_call_misctf(i_tev_ndx);
+extern void __process_putpdel_ev(i_tev_ndx);
+extern void __reinit_tfrecs(void);
+extern char *__mytf_malloc(int32);
+
+extern struct tnode_t *__vtfind(char *, struct symtab_t *);
+extern void __add_sym(char *, struct tnode_t *);
+extern void __grow_xstk(void);
+extern void __grow_tevtab(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern int32 __get_arrwide(struct net_t *);
+extern int32 __unnormalize_ndx(struct net_t *, int32);
+extern void __xline_vval_to_cstr(word32 *, int32, int32, int32, int32);
+extern int32 __v64_to_real(double *, word64 *);
+extern void __cnv_stk_fromreg_toreal(struct xstk_t *, int32);
+extern void __cnv_stk_fromreal_toreg32(struct xstk_t *);
+extern void __sizchgxs(register struct xstk_t *, int32);
+extern char *__alloc_getasfmt(struct expr_t *, struct tfrec_t *, int32);
+extern void __lmult(register word32 *, register word32 *, register word32 *, int32);
+extern void __insert_event(register i_tev_ndx);
+extern void __strenwiden_sizchg(struct xstk_t *, int32);
+extern int32 __to_base(int32);
+extern void __to_dhboval(int32, int32);
+extern int32 __is_vdigit(int32, int32);
+extern void __my_free(char *, int32);
+extern char *__my_malloc(int32);
+extern int32 __real_to_v64tim(word64 *, double);
+extern char *__st_regab_tostr(char *, byte *, int32);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern void __evtr_resume_msg(void);
+extern char *__bld_lineloc(char *, word32, int32);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern void __free_dceauxlst(struct dceauxlst_t *, int32);
+extern void __cnv_ticks_tonum64(word64 *, word64, struct mod_t *);
+extern char *__to_timstr(char *, word64 *);
+extern void __disp_itree_path(register struct itree_t *, struct task_t *);
+extern void __emit_stsk_endmsg(void);
+extern void __vpi_endsim_trycall(void);
+extern void __ldivmod2(word32 *, word32 *, word32 *, word32 *, int32);
+extern void __my_vfprintf(FILE *, char *, va_list, va_list);
+extern int32 __em_suppr(int32);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern struct dcevnt_t *__alloc_dcevnt(struct net_t *);
+extern void __alloc_1instdce_prevval(struct dcevnt_t *);
+extern void __init_1instdce_prevval(struct dcevnt_t *);
+extern void __exec2_proc_assign(struct expr_t *, register word32 *, register word32 *);
+extern void __st_perinst_val(union pck_u, int32, register word32 *, register word32 *);
+extern void __mdr_assign_or_sched(register struct expr_t *);
+extern void __exec_conta_assign(struct expr_t *, register word32 *, register word32 *, int32);
+extern void __init_tfdrv(struct tfarg_t *, struct expr_t *, struct mod_t *);
+extern int32 __trim1_0val(word32 *, int32);
+extern void __process_pli_dynamic_libs(struct loadpli_t *);
+extern void __dcelst_off(struct dceauxlst_t *);
+extern double __cnvt_signed64_to_real(word32 *, int32);
+
+extern void __tr_msg(char *, ...);
+extern void __crit_msg(char *, ...);
+extern void __cv_msg(char *, ...);
+extern void __my_fprintf(FILE *, char *, ...);
+extern void __pv_err(int32, char *, ...);
+extern void __pv_warn(int32, char *,...);
+extern void __sgfwarn(int32, char *, ...);
+extern void __sgferr(int32, char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __pv_terr(int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __my_exit(int32, int32);
+extern void __inform(int32, char *, ...);
+
+/* needed here since causes compiler error in veriuser.h */
+#ifdef __STATIC_PLI__
+extern struct t_tfcell veriusertfs[];
+#endif
+
+extern double __dbl_toticks_tab[];
+extern word32 __masktab[];
+
+/*
+ * ROUTINES TO PROCESS VERIUSERTFS D.S. BEFORE PVER STARTS
+ */ 
+
+/*
+ * setup both the static veriuser tfs and/or the +loadpli1 returned tables
+ */
+extern void __setup_veriusertf_systfs(void)
+{
+ register int32 i;
+ register struct dynboot_t *dnbp;
+ register struct loadpli_t *ldp;
+ struct t_tfcell *veriusertf_ptr, *tfcp;
+ int32 sav_last_veriusertf, num_pli1_systfs;
+
+ sav_last_veriusertf = __last_veriusertf;
+
+ /* SJM 07/08/02 - handle all +loadpli1 option dynamic lib loading first */
+ /* this just load the dynamic libraries and finds boot strap routines */
+ if (__pli1_dynlib_hd != NULL) __process_pli_dynamic_libs(__pli1_dynlib_hd);
+
+ /* always add P1364 old built in table - empty unless old static cverobj.o */
+#ifdef __STATIC_PLI__
+ check_veriusertf_table(veriusertfs);
+#else
+ for (ldp = __pli1_dynlib_hd; ldp != NULL; ldp = ldp->load_plinxt)
+  {
+   for (dnbp = ldp->dynblst; dnbp != NULL; dnbp = dnbp->dynbootnxt)
+    {
+     /* bootstrap routine can be nil */
+     if (dnbp->dynu.tf_rout == NULL) continue;
+
+     /* vpi boostrap routines are assume to return void - if not ret ignored */
+     /* notice user must insure if pli1 bootstrap routine returns val, that */
+     /* it is pointer to p tfcell table */
+     veriusertf_ptr = (struct t_tfcell *) (dnbp->dynu.tf_rout)();         
+     dnbp->ret_veriusertf = veriusertf_ptr;
+     if (dnbp->ret_veriusertf != NULL)
+      {
+       check_veriusertf_table(dnbp->ret_veriusertf);
+      }
+    } 
+#endif
+  }
+ 
+ num_pli1_systfs = __last_veriusertf - sav_last_veriusertf;
+ if (num_pli1_systfs != 0 && __verbose)
+  {
+   __cv_msg("  %d veriusertfs PLI 1.0 user tasks and functions defined.\n",
+    num_pli1_systfs);
+  }
+
+ /* SJM 07/16/02 - need internal shadow veriuser tfs table that is copy */
+ /* of legacy user filled veriuser tfs for old static cverobj.o pli1 scheme */ 
+ /* and contains copy of all returned tables for new +load_pli1 mechanism */
+ __shadow_veriusertfs = (struct t_tfcell *)
+  __my_malloc((num_pli1_systfs + 1)*sizeof(struct t_tfcell));
+#ifdef __STATIC_PLI__
+ for (i = 0;; i++)
+  {
+   tfcp = &(veriusertfs[i]);
+   __shadow_veriusertfs[i] = *tfcp;
+   /* copy ending fence before break; */
+   if (tfcp->type == 0) break;
+  }
+#else
+ for (i = 0, ldp = __pli1_dynlib_hd; ldp != NULL; ldp = ldp->load_plinxt)
+  {
+
+   for (dnbp = ldp->dynblst; dnbp != NULL; dnbp = dnbp->dynbootnxt)
+    {
+     int32 j;
+
+     /* bootstrap routine can be nil */
+     if (dnbp->ret_veriusertf == NULL) continue;
+
+     for (j = 0;; j++)
+      {
+       tfcp = &(dnbp->ret_veriusertf[j]);
+       if (tfcp->type == 0) break;
+       __shadow_veriusertfs[i++] = *tfcp;
+      } 
+    } 
+  } 
+ __shadow_veriusertfs[i].type = 0;
+#endif
+}
+
+/*
+ * during initialization routine to process and check tf_cell table entries
+ *
+ * put in normal system task or function table (possibly replacing built-in)
+ * some execution mechanism same
+ */
+static void check_veriusertf_table(struct t_tfcell *boot_veriusertf)
+{
+ register int32 i;
+ struct t_tfcell *tfcp;
+
+ /* notice, must be at least one entry or will crash */
+ for (i = 0;; i++)
+  {
+   tfcp = &(boot_veriusertf[i]);
+   switch (tfcp->type) {
+    case 0: 
+     /* need to start processing vpi systfs by move last systf one past end */
+     /* each table ends by updating last */
+     __last_systf = __last_veriusertf;
+     return;
+    case USERTASK: case USERFUNCTION: case USERREALFUNCTION:
+     if (!chk_idnam_veriusertf(tfcp->tfname)) break;
+     if (++__last_veriusertf - BASE_VERIUSERTFS >= MAXVERIUSERTFS)
+      __pv_terr(320,
+       "too many tasks and functions in veriusertfs (%d) and +loadpli1 bootstrap returned ptfcell tables",
+       MAXVERIUSERTFS);
+     if (tfcp->calltf == NULL)
+      {
+       __pv_warn(578,
+        "PLI1 veriusertfs user function or task %s no Verilog execution routine",
+        tfcp->tfname);
+      }
+     if (tfcp->type == USERTASK) add_veriusertf_task(tfcp);
+     else add_veriusertf_func(tfcp);
+     break;
+    default: __case_terr(__FILE__, __LINE__);
+   }
+  }
+}
+
+/*
+ * add a veriuser table pli system task
+ */
+static void add_veriusertf_task(struct t_tfcell *tfcp)
+{
+ struct systsk_t *stbp;
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+
+ if (tfcp->sizetf != NULL)
+  {
+   __inform(425,
+   "PLI1 veriusertfs task %s - sizetf function ignored but should not be in table",
+    tfcp->tfname);
+   tfcp->sizetf = NULL;
+  }
+ /* allocate a systsk_t entry - needed because splicing pli on and */
+ /* need to be able to compile version without */
+ stbp = __alloc_systsk();
+ stbp->stsknam = tfcp->tfname;
+ stbp->stsknum = __last_veriusertf;
+ tnp = __vtfind(tfcp->tfname, __syssyms);
+ if (!__sym_is_new)
+  {
+   syp = tnp->ndp;
+   __inform(459,
+    "PLI1 veriusertfs task %s replaces predefined system task or function with same name",
+    syp->synam);
+  }
+ else
+  {
+   __add_sym(tfcp->tfname, tnp);
+   (__syssyms->numsyms)++;
+   syp = tnp->ndp;
+  }
+ syp->sytyp = SYM_STSK;
+ syp->sydecl = TRUE;
+ syp->el.esytbp = stbp;
+}
+
+/*
+ * add a veriuser table pli system function (normal or real)
+ */
+static void add_veriusertf_func(struct t_tfcell *tfcp)
+{
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+ struct sysfunc_t *sfbp;
+
+ /* function tfcell must have sizetf or cannot execute */ 
+ /* for real function know size */
+ if (tfcp->type == USERFUNCTION && tfcp->sizetf == NULL)
+  {
+   __pv_warn(578,
+    "PLI1 veriusertfs function %s sizetf function missing - assuming size 1",
+    tfcp->tfname);
+  }
+ else if (tfcp->type == userrealfunction && tfcp->sizetf != NULL)
+  {
+   __inform(425,
+   "PLI1 veriusertfs userrealfunction %s - sizetf function ignored but should not be in table",
+    tfcp->tfname);
+   tfcp->sizetf = NULL;
+  }
+
+ /* allocate a sysfunc_t entry - needed because splicing pli on and */
+ /* need to be able to compile version without */
+ sfbp = __alloc_sysfunc();
+ sfbp->syfnum = __last_veriusertf;
+ sfbp->tftyp = SYSF_TF;
+ sfbp->syfnam = tfcp->tfname;
+ tnp = __vtfind(tfcp->tfname, __syssyms);
+ if (!__sym_is_new)
+  {
+   syp = tnp->ndp;
+   __inform(459,
+    "PLI1 veriusertfs function %s replaces predefined system task or function with same name",
+    syp->synam);
+  }
+ else
+  {
+   __add_sym(tfcp->tfname, tnp);
+   (__syssyms->numsyms)++;
+   syp = tnp->ndp;
+  }
+ syp->sytyp = SYM_SF;
+ syp->sydecl = TRUE;
+ syp->el.esyftbp = sfbp;
+}
+
+/*
+ * check for legal user tf task or function name
+ */
+static int32 chk_idnam_veriusertf(char *tfnam)
+{
+ register char *chp;
+ int32 len;
+
+ chp = tfnam;
+ if (*chp++ != '$') 
+  {
+   __pv_err(1302,
+    "PLI1 - veriusertfs task or function %s must begin with '$'", tfnam); 
+bad_end:   
+   return(FALSE);
+  }
+ for (len = 1; *chp != '\0'; chp++)
+  {
+   /* notice no escaped names here */
+   if (!isalnum(*chp) && *chp != '_' && *chp != '$')  
+    {
+     __pv_err(1303,
+      "PLI1 veriusertfs task or function %s contains illegal char %c",
+      tfnam, *chp);   
+     goto bad_end;
+    }
+   if (++len >= IDLEN)   
+    {
+     /* notice cannot truncate since in user memory */
+     __pv_err(1304,
+      "PLI1 veriusertfs task or function %s name too long (%d)",
+      tfnam, IDLEN); 
+     goto bad_end;
+    }
+  }
+ return(TRUE);
+}
+
+/*
+ * allocate and initialize a system task struct for pli task
+ * built-in system tasks are predefined in table
+ */
+extern struct systsk_t *__alloc_systsk(void)
+{ 
+ struct systsk_t *stbp;
+
+ stbp = (struct systsk_t *) __my_malloc(sizeof(struct systsk_t));
+ stbp->stsknam = NULL;
+ stbp->stsknum = 0;
+ return(stbp);
+}
+
+/*
+ * allocate and initialize a system function struct for pli function
+ * built-in system functions are predefined in table
+ */
+extern struct sysfunc_t *__alloc_sysfunc(void)
+{ 
+ struct sysfunc_t *sfbp;
+
+ sfbp = (struct sysfunc_t *) __my_malloc(sizeof(struct sysfunc_t));
+ sfbp->syfnam = NULL;
+ /* these all all unused */ 
+ sfbp->syfnum = 0;
+ sfbp->retntyp = 0;
+ sfbp->retsigned = FALSE;
+ sfbp->retwid = 0;
+ sfbp->tftyp = SYSF_UNKNOWN;
+ return(sfbp);
+}
+
+/*
+ * WRAPPERS THAT CALL THE USER'S TF FUNCTIONS FROM VERIUSERTFS TABLE
+ */
+
+/*
+ * FUNCTION SIZETF ROUTINES CALL DURING FIXUP
+ */
+
+/*
+ * call pli system function sizetf routine
+ * for function sizetf must exist or will not get here
+ * for userrealfunction just set to expected width (never seen by user)
+ *
+ * here if user calls routine that needs variable just crashes
+ */
+extern void __pli_func_sizetf(struct expr_t *fcallx)
+{
+ int32 siz, nbytes;
+ word32 *wp;
+ double d1;
+ struct sysfunc_t *sfbp;
+ struct t_tfcell *tfcp;
+ struct tfinst_t tfiwrk;
+ int32 (*sizetf_func)();
+
+ sfbp = fcallx->lu.x->lu.sy->el.esyftbp;
+ tfcp = &(__shadow_veriusertfs[sfbp->syfnum - BASE_VERIUSERTFS]); 
+ __tfrec = fcallx->lu.x->szu.xfrec;
+
+ /* for real function, set size and return no sizetf for real func. */
+ if (tfcp->type == userrealfunction)
+  {
+   __tfrec->fretsiz = REALBITS;
+   __tfrec->fretreal = TRUE;
+   fcallx->is_real = TRUE;
+   fcallx->has_sign = TRUE;
+   /* since not checked need to set width for real */
+   fcallx->szu.xclen = REALBITS;
+
+   /* set the 0th expression for tf userrealfunction */
+   /* points to value not expr. that is initialzed to 0.0 */
+   nbytes = 2*wlen_(__tfrec->fretsiz)*WRDBYTES;
+   wp = __tfrec->tfargs[0].arg.awp = (word32 *) __my_malloc(nbytes);
+   /* initialize to 0.0 since no internals for pli func and double */
+   d1 = 0.0;
+   memcpy(wp, &d1, nbytes); 
+   return;
+  }
+ sizetf_func = tfcp->sizetf; 
+
+ if (sizetf_func == NULL)
+  {
+   siz = 1;
+   goto have_size;
+  }
+
+ /* run in first inst. itree loc. - know moditps built by here */ 
+ __push_itstk(__inst_mod->moditps[0]);
+ /* notice assignment of addr. to static works since niled in this rout. */
+ __tfinst = &tfiwrk;
+ __tfinst->callx = fcallx;
+ __tfinst->tfstp = NULL;
+ __tfinst->tfitp = __inst_ptr; 
+
+ /* FIXME ??? - not 64 bit clean */
+ siz = (*sizetf_func)((int32) tfcp->data, REASON_SIZETF);
+ __pop_itstk();
+ if (siz < 1 || siz > MAXNUMBITS)
+  {
+   __sgferr(1277,
+    "tf_ function %s sizetf routine returned illegal size value %d",
+    tfcp->tfname, siz);
+   __tfinst = NULL;
+   __tfrec = NULL;
+   return;
+  }
+
+have_size:
+ __tfrec->fretsiz = siz;
+ /* SJM 04/07/03 - this is needed by compiler so much be also set */
+ /* worked for vpi becausxe no tf rec alternative size location */
+ sfbp->retwid = siz;
+
+ /* set the 0th expression for tf function */
+ /* points to value not expr. that is initialized to x */
+ nbytes = 2*wlen_(__tfrec->fretsiz)*WRDBYTES;
+ wp = __tfrec->tfargs[0].arg.awp = (word32 *) __my_malloc(nbytes);
+ /* initialize to x since no internals for pli functions */
+ one_allbits_(wp, 2*__tfrec->fretsiz); 
+ fcallx->szu.xclen = __tfrec->fretsiz;
+ __tfinst = NULL;
+ __tfrec = NULL;
+}
+
+/*
+ * CHECKTF ROUTINES CALLED NEAR END OF PREP
+ */
+
+/*
+ * go through list of all task and function tf_ calls
+ */
+extern void __call_all_checktfs(void)
+{
+ register struct tfrec_t *tfrp;
+
+ for (tfrp = __tfrec_hdr; tfrp != NULL; tfrp = tfrp->tfrnxt)
+  {
+   if (tfrp->tf_func) pli_func_checktf(tfrp->tfu.callx);
+   else pli_task_checktf(tfrp->tfu.tfstp);
+  }
+}
+
+/*
+ * call pli system function checktf
+ *
+ * must be called after call tf record built
+ * this needs to be left in .a file since locates problem
+ * LOOKATME if user tries to make sim tf_ calls will crash
+ */
+static void pli_func_checktf(struct expr_t *fcallx)
+{
+ struct t_tfcell *tfcp;
+ struct sysfunc_t *sfbp;
+ struct tfinst_t tfiwrk;
+ int32 (*checktf_func)();
+
+ sfbp = fcallx->lu.x->lu.sy->el.esyftbp;
+ tfcp = &(__shadow_veriusertfs[sfbp->syfnum - BASE_VERIUSERTFS]); 
+
+ checktf_func = tfcp->checktf; 
+ if (checktf_func == NULL) return;
+
+ __tfrec = fcallx->lu.x->szu.xfrec;
+ /* run in first inst. itree loc. - know moditps built by here */
+ /* if interactive just run in current itree loc. */
+ /* DBG remove --- */
+ if (__tfrec->tf_inmdp == NULL) __misc_terr(__FILE__, __LINE__);
+ /* ---*/
+ __push_itstk(__tfrec->tf_inmdp->moditps[0]);
+
+ /* notice assignment of addr. to static works since niled in this rout. */
+ __tfinst = &tfiwrk;
+ __tfinst->callx = fcallx;
+ __tfinst->tfstp = NULL;
+ __tfinst->tfitp = __inst_ptr; 
+
+ /* FIXME ??? - not 64 bit clean */
+ (*checktf_func)((int32) tfcp->data, REASON_CHECKTF);
+
+ __tfinst = NULL;
+ __tfrec = NULL;
+ __pop_itstk();
+}
+
+/*
+ * call checktf for task
+ * runs in first instance tree location
+ * this routine must stay in .a lib
+ */ 
+static void pli_task_checktf(struct st_t *stp) 
+{
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct tskcall_t *tkcp;
+ struct t_tfcell *tfcp;
+ struct systsk_t *stbp;
+ struct tfinst_t tfiwrk;
+ int32 (*checktf_func)();
+
+ /* statement is task call not task definition */
+ tkcp = &(stp->st.stkc);
+ stbp = tkcp->tsksyx->lu.sy->el.esytbp;
+ tfcp = &(__shadow_veriusertfs[stbp->stsknum - BASE_VERIUSERTFS]); 
+
+ checktf_func = tfcp->checktf; 
+ if (checktf_func == NULL) return;
+
+ __tfrec = tkcp->tkcaux.trec;
+ sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
+ __vpifnam_ind = __sfnam_ind; 
+ __vpilin_cnt = __slin_cnt;
+
+ /* if interactive just run in current itree loc. */
+ /* DBG remove --- */
+ if (__tfrec->tf_inmdp == NULL) __misc_terr(__FILE__, __LINE__);
+ /* ---*/
+ __push_itstk(__tfrec->tf_inmdp->moditps[0]);
+ /* notice assignment of addr. to static works since niled in this rout. */
+ __tfinst = &tfiwrk;
+ __tfinst->callx = NULL;
+ __tfinst->tfstp = stp;
+ __tfinst->tfitp = __inst_ptr; 
+
+ /* FIXME ??? - not 64 bit clean */
+ (*checktf_func)((int32) tfcp->data, REASON_CHECKTF);
+
+ __pop_itstk();
+ __tfrec = NULL;
+ __tfinst = NULL;
+ __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+}
+
+/*
+ * ROUTINES FOR CALLING ALL MISCTF ROUTINES AT CHANGES
+ */
+
+/*
+ * calling misctfs need to be here so can use REASON constants
+ */
+extern void __call_misctfs_streset(void)
+{
+ call_allinsts_misctfs(REASON_RESET);
+}
+
+extern void __call_misctfs_endreset(void)
+{
+ call_allinsts_misctfs(REASON_ENDOFRESET);
+}
+
+extern void __call_misctfs_simstart(void)
+{
+ call_allinsts_misctfs(REASON_ENDOFCOMPILE);
+}
+
+extern void __call_misctfs_iact(void)
+{
+ call_allinsts_misctfs(REASON_INTERACTIVE);
+}
+
+extern void __call_misctfs_finish(void)
+{
+ call_allinsts_misctfs(REASON_FINISH);
+}
+
+extern void __call_misctfs_scope(void)
+{
+ call_allinsts_misctfs(REASON_SCOPE);
+}
+
+/*
+ * go through list of all task and function tf_ calls
+ * and call misctf for every instance of every call
+ */
+static void call_allinsts_misctfs(int32 reason)
+{
+ register struct tfrec_t *tfrp;
+
+ for (tfrp = __tfrec_hdr; tfrp != NULL; tfrp = tfrp->tfrnxt)
+  misc_call_misctf(tfrp, reason);
+}
+
+/*
+ * call the misctf routine for misceallaneous reason
+ */
+static void misc_call_misctf(struct tfrec_t *tfrp, int32 reason)
+{
+ register int32 ii;
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct t_tfcell *tfcp;
+ struct tfinst_t tfiwrk;
+ struct mod_t *mdp;
+ int32 (*misctf)(int32, int32, int32);
+
+ __tfrec = tfrp;
+ /* if no misc. tf routine just turn off, nothing to do */
+ tfcp = get_tfcell(__tfrec);
+ if ((misctf = tfcp->misctf) == NULL) return;
+
+ sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
+ __vpifnam_ind = __sfnam_ind; 
+ __vpilin_cnt = __slin_cnt;
+
+ /* notice assignment of addr. to static works since niled in this rout. */
+ __tfinst = &tfiwrk;
+ __tfinst->callx = NULL;
+ __tfinst->tfstp = NULL;
+ if (__tfrec->tf_func) __tfinst->callx = __tfrec->tfu.callx;
+ else __tfinst->tfstp = __tfrec->tfu.tfstp;
+ mdp = __tfrec->tf_inmdp;
+
+ /* DBG remove --- */
+ if (mdp == NULL) __misc_terr(__FILE__, __LINE__);
+ /* ---*/
+ for (ii = 0; ii < mdp->flatinum; ii++)
+  {
+   __push_itstk(mdp->moditps[ii]);
+   __tfinst->tfitp = __inst_ptr; 
+
+   /* SJM 06/13/1999 - misctf always requires 3rd argument although */
+   /* ignored except for syncon callbacks ?? */
+   /* FIXME ??? - not 64 bit clean */
+   (*misctf)((int32) tfcp->data, reason, 0);
+   __pop_itstk();
+  }
+ __tfrec = NULL;
+ __tfinst = NULL;
+ __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+}
+
+/*
+ * get a tfcell name
+ */
+extern char *__get_tfcellnam(struct tfrec_t *tfrp)
+{
+ struct t_tfcell *tfcp;
+
+ tfcp = get_tfcell(tfrp);
+ return(tfcp->tfname);
+}
+
+/*
+ * get a tfcell record from a tfrec  
+ */
+static struct t_tfcell *get_tfcell(struct tfrec_t *tfrp)
+{
+ struct t_tfcell *tfcp;
+ struct systsk_t *stbp;
+ struct sysfunc_t *sfbp;
+
+ if (tfrp->tf_func)
+  {
+   sfbp = tfrp->tfu.callx->lu.x->lu.sy->el.esyftbp;
+   tfcp = &(__shadow_veriusertfs[sfbp->syfnum - BASE_VERIUSERTFS]); 
+   return(tfcp);
+  }
+ stbp = tfrp->tfu.tfstp->st.stkc.tsksyx->lu.sy->el.esytbp;
+ tfcp = &(__shadow_veriusertfs[stbp->stsknum - BASE_VERIUSERTFS]); 
+ return(tfcp);
+}
+
+/*
+ * WRAPPERS THAT CALL THE USER'S TF TASKS FROM VERIUSERTFS TABLE
+ */
+
+/*
+ * execute the pli system function calltf routine
+ * this pushes return value on top of expr. stack but does not return it
+ * this uses the instance tree loc. called from
+ */
+extern void __pli_func_calltf(struct expr_t *fcallx)
+{
+ int32 nbytes, sav_fnam_ind, sav_slin_cnt;
+ struct t_tfcell *tfcp;
+ struct sysfunc_t *sfbp;
+ struct xstk_t *xsp;
+ struct tfinst_t tfiwrk;
+ int32 (*calltf_func)();
+      
+ sfbp = fcallx->lu.x->lu.sy->el.esyftbp;
+ tfcp = &(__shadow_veriusertfs[sfbp->syfnum - BASE_VERIUSERTFS]); 
+ __tfrec = fcallx->lu.x->szu.xfrec;
+
+ if ((calltf_func = tfcp->calltf) == NULL)
+  {
+   push_xstk_(xsp, __tfrec->fretsiz);
+   one_allbits_(xsp->ap, xsp->xslen);
+   one_allbits_(xsp->bp, xsp->xslen);
+   __tfrec = NULL;
+   return;
+  }
+
+ sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
+ __vpifnam_ind = __sfnam_ind; 
+ __vpilin_cnt = __slin_cnt;
+
+ /* set up environment that is current implied tf instance */
+ /* notice assignment of addr. to static works since niled in this rout. */
+ __tfinst = &tfiwrk;
+ __tfinst->callx = fcallx;
+ __tfinst->tfstp = NULL;
+ __tfinst->tfitp = __inst_ptr; 
+
+ /* FIXME ??? - not 64 bit clean */
+ (*calltf_func)((int32) tfcp->data, REASON_CALLTF);
+
+ /* must store return value from caller's itree loc. */ 
+ nbytes = 2*wlen_(__tfrec->fretsiz)*WRDBYTES;
+ push_xstk_(xsp, __tfrec->fretsiz);
+ /* this requires contiguous a and b stack values */
+ memcpy(xsp->ap, __tfrec->tfargs[0].arg.awp, nbytes); 
+
+ __sfnam_ind = sav_fnam_ind;
+ __slin_cnt = sav_slin_cnt;
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+ __tfrec = NULL;
+ __tfinst = NULL;
+} 
+
+/*
+ * call the pli tf system task calltf routine
+ */
+extern void __pli_task_calltf(struct st_t *stp)
+{
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct tskcall_t *tkcp;
+ struct t_tfcell *tfcp;
+ struct systsk_t *stbp;
+ struct tfinst_t tfiwrk;
+ int32 (*calltf_tsk)();
+      
+ tkcp = &(stp->st.stkc);
+ stbp = tkcp->tsksyx->lu.sy->el.esytbp;
+ tfcp = &(__shadow_veriusertfs[stbp->stsknum - BASE_VERIUSERTFS]); 
+
+ if ((calltf_tsk = tfcp->calltf) == NULL) return;
+
+ __tfrec = tkcp->tkcaux.trec;
+ sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
+ __vpifnam_ind = __sfnam_ind; 
+ __vpilin_cnt = __slin_cnt;
+
+ /* set up environment that is current implied tf instance */
+ /* notice assignment of addr. to static works since niled in this rout. */
+ __tfinst = &tfiwrk;
+ __tfinst->callx = NULL;
+ __tfinst->tfstp = stp;
+ __tfinst->tfitp = __inst_ptr; 
+
+ /* FIXME ??? - not 64 bit clean */
+ (*calltf_tsk)((int32) tfcp->data, REASON_CALLTF);
+
+ __tfrec = NULL;
+ __tfinst = NULL;
+ __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+}
+
+/*
+ * USER CALLABLE TF_ ROUTINES GROUPED BY TYPE - UTILITY TOWARD BOTTOM
+ */
+
+/*
+ * EXPRESSION AND VALUE INFORMATION ROUTINES
+ */
+
+/*
+ * get number of parameters (user pli tasks are variable arg. no.) that
+ * if checked done by user routine
+ * LOOKATME - does this really need to be other inst?
+ */
+extern int32 tf_inump(char *inst)
+{
+ struct tfinst_t *tfip;
+ struct tfrec_t *tfrp;
+ 
+ tfip = (struct tfinst_t *) inst;
+ if (tfip->callx != NULL) tfrp = tfip->callx->lu.x->szu.xfrec;
+ else tfrp = tfip->tfstp->st.stkc.tkcaux.trec;
+ return(tfrp->tfanump1 - 1);
+}
+
+/*
+ * number of params from saved system task call
+ */
+extern int32 tf_nump(void)
+{
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_nump"));
+ return(__tfrec->tfanump1 - 1);
+}
+
+/*
+ * get parameter type 
+ */
+extern int32 tf_itypep(int32 pnum, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *tfip;
+ struct tfrec_t *sav_tfrp;
+
+ sav_tfrp = __tfrec; 
+ tfip = (struct tfinst_t *) inst;
+ if (tfip->callx != NULL) __tfrec = tfip->callx->lu.x->szu.xfrec;
+ else __tfrec = tfip->tfstp->st.stkc.tkcaux.trec;
+
+ rv = tf_typep(pnum);
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_typep(int32 pnum)
+{
+ struct expr_t *xp;
+
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_typep"));
+ if (pnum < 0 || pnum >= __tfrec->tfanump1) return(TF_NULLPARAM);
+ if (pnum == 0)
+  {
+   if (!__tfrec->tf_func) return(TF_NULLPARAM);
+   if (__tfrec->fretreal) return(TF_READWRITEREAL);
+   return(TF_READWRITE);
+  }
+ xp = __tfrec->tfargs[pnum].arg.axp;
+
+ if (xp->tf_isrw)
+  {
+   if (xp->is_real) return(TF_READWRITEREAL);
+   return(TF_READWRITE);
+  }
+ if (xp->optyp == NUMBER && xp->is_string) return(TF_STRING);
+ if (xp->optyp == OPEMPTY) return(TF_NULLPARAM);
+ if (xp->is_real) return(TF_READONLYREAL);
+ return(TF_READONLY);
+}
+
+/*
+ * return bit length of parameter
+ * return size of parameter in bits - 0 for real
+ */
+extern int32 tf_isizep(int32 pnum, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *tfip;
+ struct tfrec_t *sav_tfrp;
+
+ sav_tfrp = __tfrec; 
+ tfip = (struct tfinst_t *) inst;
+ if (tfip->callx != NULL) __tfrec = tfip->callx->lu.x->szu.xfrec;
+ else __tfrec = tfip->tfstp->st.stkc.tkcaux.trec;
+ rv = tf_sizep(pnum);
+
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_sizep(int32 pnum)
+{
+ struct expr_t *xp;
+ 
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_sizep"));
+ if (pnum < 0 || pnum >= __tfrec->tfanump1) return(TF_NULLPARAM);
+ if (pnum == 0)
+  {
+   if (__tfrec->fretreal) return(TF_NULLPARAM);
+   return(__tfrec->fretsiz);
+  }
+ xp = __tfrec->tfargs[pnum].arg.axp;
+ if (xp->is_real) return(TF_NULLPARAM);
+ return(xp->szu.xclen);
+}
+
+/*
+ * EXPRINFO AND NODINFO ROUTINES
+ */
+
+/* macro to saves and sets inst form environment */
+/* need to be in normal code not part of block or if */
+#define set_tfinst_(inst, stfip, stfrp) \
+ stfip = __tfinst; \
+ stfrp = __tfrec; \
+ __tfinst = (struct tfinst_t *) inst; \
+ if (__tfinst->callx != NULL) __tfrec = __tfinst->callx->lu.x->szu.xfrec; \
+ else __tfrec = __tfinst->tfstp->st.stkc.tkcaux.trec;
+
+
+
+/* 
+ * return node info struct from nparam for read-write (lhs) expr. only  
+ * node info if for underlying object in case select or index
+ * cannot access pli func. return values here (no nodes)
+ *
+ * LOOKATME - need to find out 1 bit representation (always stren)
+ * for now strength illegal since standard document method for storing
+ * strength impossible (provided by 2.0 so leave)
+ */
+extern p_tfnodeinfo tf_inodeinfo(int32 pnum, p_tfnodeinfo pinfo, char *inst)
+{
+ struct t_tfnodeinfo *pinfo2;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ pinfo2 = tf_nodeinfo(pnum, pinfo);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(pinfo2);
+}
+
+extern p_tfnodeinfo tf_nodeinfo(int32 pnum, p_tfnodeinfo pinfo)
+{
+ register struct xstk_t *xsp;
+ register struct net_t *np;
+ int32 wlen, mwid, r1, r2, biti, bitj;
+ double d1;
+ struct tfarg_t *tfap;
+ struct expr_t *xp;
+
+ if (__tfrec == NULL) { bad_notfcontext_err("tf_nodeinfo"); return(NULL); }
+ if (pnum < 1 || pnum >= __tfrec->tfanump1) return(NULL);
+ tfap = &(__tfrec->tfargs[pnum]);
+ xp = tfap->arg.axp;
+ init_nodeinfo(pinfo);
+ /* if not rw (concat not rw), return null */
+ if (!xp->tf_isrw) return(NULL);
+
+ /* cannot handle strength since as documented no way to store value */ 
+ np = tfap->anp;
+ if (np->n_stren)
+  __sgfinform(489,
+   "tf_nodeinfo of strength wire %s node_value set to value part only",
+   np->nsym->synam);  
+
+ /* SJM 10/30/99 - now using tf exprinfo for propagatep following new LRM */
+
+ /* notice node_lhs_element and node_rhs_element unused */
+ /* set the symbol name field */
+ /* not my malloc can only call malloc (no other alloc scheme possible) */
+ pinfo->node_symbol = __mytf_malloc(strlen(np->nsym->synam) + 1);
+ strcpy(pinfo->node_symbol, np->nsym->synam);
+
+ xsp = __eval_xpr(xp); 
+ /* real is special case - no range */
+ /* real array select work handled in xpr eval */
+ if (np->ntyp == N_REAL)
+  {
+   pinfo->node_type = TF_REAL_NODE;
+   /* eval of expr. always gets underlying value and handles xmr */
+   /* notice for xmr, this will acess from right place - cannot push grp */
+   memcpy(&d1, xsp->ap, sizeof(double));
+
+   pinfo->node_value.real_val_p =
+    (double *) __mytf_malloc(sizeof(double));
+   *(pinfo->node_value.real_val_p) = d1;
+   __pop_xstk();
+   return(pinfo);
+  }
+
+ /* set the vector size (component element for array) */
+ pinfo->node_sign = np->n_signed;
+
+ /* select of array (not entire) array special case */
+ if (np->n_isarr)
+  {
+   pinfo->node_vec_size = np->nwid;
+   pinfo->node_type = TF_MEMORY_NODE;
+   mwid = __get_arrwide(np);
+   pinfo->node_mem_size = mwid;
+   /* DBG remove */
+   if (np->nrngrep != NX_ARR) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   /* get range not size */
+   pinfo->node_ms_index = np->nu.rngarr->ai1;
+   pinfo->node_ls_index = np->nu.rngarr->ai2;
+   /* each group is both 32 bits of a part and 32 bits of b */
+   /* notice memory expression are always entire variable */
+   wlen = wlen_(np->nwid); 
+   pinfo->node_ngroups = wlen;
+   allocset_vecval(pinfo, xsp, wlen);
+   __pop_xstk();
+   return(pinfo);
+  }
+
+ pinfo->node_vec_size = xp->szu.xclen;
+ /* set the ranges of the node - always just var not mem decl. range */
+ if (np->nrngrep == NX_WIR)
+  { r1 = np->nu.rngwir->ni1; r2 = np->nu.rngwir->ni2; } 
+ else if (np->nrngrep == NX_DWIR)
+  { r1 = np->nu.rngdwir->ni1; r2 = np->nu.rngdwir->ni2; }
+ else r1 = r2 = -1;
+
+ /* assume entire range */
+ pinfo->node_ms_index = r1;
+ pinfo->node_ls_index = r2;
+ /* for non scalar, non memory and non real, this is expression range */
+ /* if non constant index (for reg) - use entire range */
+
+ biti = -1;
+ if (xp->optyp == LSB)
+  {
+   /* if anything but simple number, range is entire - per change op rules */
+   if (xp->ru.x->optyp == NUMBER)  
+    {
+     biti = __contab[xp->ru.x->ru.xvi];
+     pinfo->node_ms_index = pinfo->node_ls_index = __unnormalize_ndx(np, biti);
+    }
+  }  
+ else if (xp->optyp == PARTSEL)
+  {
+   biti = __contab[xp->ru.x->lu.x->ru.xvi];
+   bitj = __contab[xp->ru.x->ru.x->ru.xvi];
+   pinfo->node_ms_index = __unnormalize_ndx(np, biti);
+   pinfo->node_ls_index = __unnormalize_ndx(np, bitj);
+  } 
+
+ /* set node type field */
+ if (!np->n_isavec) 
+  {
+   if (np->ntyp < NONWIRE_ST) pinfo->node_type = TF_NETSCALAR_NODE;
+   else pinfo->node_type = TF_REG_NODE;
+  } 
+ else
+  { 
+   if (np->ntyp == N_REG) pinfo->node_type = TF_REG_NODE;
+   else if (np->ntyp == N_INT) pinfo->node_type = TF_INTEGER_NODE;
+   else if (np->ntyp == N_TIME) pinfo->node_type = TF_TIME_NODE;
+   else pinfo->node_type = TF_NETVECTOR_NODE;
+  }
+ /* correct for bit select from scalared wire to TF_NETSCALAR */
+ /* must be constant bit select from scalared wire vector */
+ if (pinfo->node_type == TF_NETVECTOR_NODE)
+  {
+   if (np->vec_scalared && biti != -1) pinfo->node_type = TF_NETSCALAR_NODE;
+  }
+
+ wlen = wlen_(xp->szu.xclen);
+ pinfo->node_ngroups = wlen;
+ /* know strength here impossible */
+ allocset_vecval(pinfo, xsp, wlen);
+ __pop_xstk();
+ return(pinfo);
+}
+
+/*
+ * allocate and set the vecval_p field
+ */
+static void allocset_vecval(struct t_tfnodeinfo *pinfo, struct xstk_t *xsp,
+ int32 wlen)
+{
+ register int32 wi;
+ struct t_vecval *vecp;
+
+ pinfo->node_value.vecval_p = (struct t_vecval *)
+  __mytf_malloc(wlen*sizeof(struct t_vecval));
+ vecp = pinfo->node_value.vecval_p;
+ for (wi = 0; wi < wlen; wi++)
+  {
+   vecp[wi].avalbits = (int32) xsp->ap[wi]; 
+   vecp[wi].bvalbits = (int32) xsp->bp[wi]; 
+  }
+}
+
+/*
+ * emit error for illegal routine called from checktf or sizetf
+ * or before start of ims
+ */
+static int32 bad_nosimtf_err(char *rnam) 
+{
+ __sgferr(1289,
+  "%s routine not callable before start of sim, during reset, or from checktf or sizetf because sets value or delay",
+  rnam);
+ return(TF_NULLPARAM);
+}
+
+/*
+ * emit error for tf calls when there is no tf context
+ */
+static int32 bad_notfcontext_err(char *rnam)
+{
+ __sgferr(1289,
+  "%s routine not callable because user code not invoked by PLI 1.0 - was systf registered using vpi_?",
+  rnam);
+ return(TF_NULLPARAM);
+}
+
+/*
+ * emit error for illegal routine called from checktf or sizetf
+ */
+static int32 bad_rosync_err(char *rnam) 
+{
+ __sgferr(1299,
+  "%s routine not callable during ro sync - it schedules or writes", rnam);
+ return(TF_NULLPARAM);
+}
+
+/*
+ * initialize an node info struct
+ */
+static void init_nodeinfo(struct t_tfnodeinfo *ninfop)
+{
+ ninfop->node_type = TF_NULL_NODE;
+ ninfop->node_value.vecval_p = NULL;
+ ninfop->node_symbol = NULL;
+ ninfop->node_ngroups = 0;
+ ninfop->node_vec_size = 0;
+ ninfop->node_sign = FALSE;
+ ninfop->node_ms_index = 0; 
+ ninfop->node_ls_index = 0;
+ ninfop->node_mem_size = 0;
+ ninfop->node_lhs_element = 0;
+ ninfop->node_rhs_element = 0;
+ ninfop->node_handle = NULL;
+}
+
+/*
+ * fill passed exprinfo struct from nparam
+ */
+extern p_tfexprinfo tf_iexprinfo(int32 pnum, p_tfexprinfo pinfo, char *inst)
+{
+ struct t_tfexprinfo *pinfo2;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ pinfo2 = tf_exprinfo(pnum, pinfo);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(pinfo2);
+}
+
+extern p_tfexprinfo tf_exprinfo(int32 pnum, p_tfexprinfo pinfo)
+{
+ register int32 wi;
+ int32 wlen, slen;
+ word32 *wp;
+ double d1;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+ struct tfarg_t *tfap;
+ struct net_t *np;
+ char *chp;
+
+ if (__tfrec == NULL)
+  {
+   bad_notfcontext_err("tf_exprinfo");
+   return(NULL);
+  }
+ if (pnum < 1 || pnum >= __tfrec->tfanump1) return(NULL);
+ tfap = &(__tfrec->tfargs[pnum]);
+ xp = tfap->arg.axp;
+ /* save for possible use by tf_evaluatep */
+ /* SJM 11/29/99 - also following new LRM and XL used by tf_propagatep */
+ tfap->sav_xinfos[__inum] = (char *) pinfo;
+
+ init_exprinfo(pinfo);
+ pinfo->expr_type = (short) get_xinfo_typ(xp); 
+ if (xp->optyp == LSB || xp->optyp == PARTSEL)
+  {
+   if (xp->tf_isrw) pinfo->expr_lhs_select = 1;
+   else pinfo->expr_rhs_select = 1;
+  }
+ if (xp->optyp == NUMBER && xp->is_string) 
+  {
+   wp = &(__contab[xp->ru.xvi]);
+   chp = __alloc_vval_to_cstr(wp, xp->szu.xclen, FALSE, FALSE);
+   pinfo->expr_string = chp;
+   slen = strlen(chp);
+   pinfo->expr_vec_size = 8*slen;
+   return(pinfo);
+  }
+ /* here this always handles any gref itree pushing and popping */
+ xsp = __eval_xpr(xp);
+ if (xp->is_real)
+  {
+   memcpy(&d1, xsp->ap, sizeof(double));
+
+   pinfo->real_value = d1;
+   /* SJM 09/07/99 - previous problem with signedness of reals */ 
+   /* reals always signed */
+   pinfo->expr_sign = TRUE;
+   goto done;
+  }
+ /* AIV 02/03/03 - if expr is ID, signed for systf arg comes from net */
+ if(xp->optyp == ID || xp->optyp == GLBREF)
+  { 
+   np = xp->lu.sy->el.enp;
+   if (np->n_signed) pinfo->expr_sign = TRUE;
+  }   
+ /* only other possibility is number or param where there is no ID */
+ /* so has sign will be correctly set */
+ else if (xp->has_sign) pinfo->expr_sign = TRUE;
+  
+ pinfo->expr_vec_size = (int32) xp->szu.xclen;
+ wlen = wlen_(xp->szu.xclen);
+ pinfo->expr_ngroups = (int32) wlen;
+ pinfo->expr_value_p = (struct t_vecval *)
+  __mytf_malloc(wlen*sizeof(struct t_vecval));
+ for (wi = 0; wi < wlen; wi++)
+  { 
+   pinfo->expr_value_p[wi].avalbits = (int32) xsp->ap[wi];
+   pinfo->expr_value_p[wi].bvalbits = (int32) xsp->bp[wi];
+  } 
+
+done:
+ __pop_xstk();
+ return(pinfo);
+}
+
+/*
+ * convert a verilog value into a c string and return in malloced string  
+ * notice no truncation here mostly for PLI
+ * need to leave prefix of exprline since may be called from nested func.
+ * or as display argument
+ */
+extern char *__alloc_vval_to_cstr(word32 *ap, int32 blen, int32 nd_quotes,
+ int32 space_0)
+{
+ int32 sav_sofs, slen;
+ char *chp;
+
+ sav_sofs = __cur_sofs;
+ /* always convert escaped special character such as new line to \\n */
+ __xline_vval_to_cstr(ap, blen, nd_quotes, space_0, TRUE);
+ slen = __cur_sofs - sav_sofs; 
+ chp = __mytf_malloc(slen + 1);
+ strcpy(chp, &(__exprline[sav_sofs]));
+ /* restore exprline */ 
+ __cur_sofs = sav_sofs;
+ __exprline[sav_sofs] = '\0';
+ return(chp);
+}
+
+/*
+ * initialize an expr info struct 
+ */
+static void init_exprinfo(struct t_tfexprinfo *xinfop)
+{
+ xinfop->expr_type = TF_READONLY; 
+ xinfop->expr_value_p = NULL;
+ xinfop->expr_string = NULL;
+ xinfop->expr_ngroups = 0;
+ xinfop->expr_vec_size = 0;
+ xinfop->expr_sign = FALSE;
+ xinfop->expr_lhs_select = 0;
+ xinfop->expr_rhs_select = 0;
+}
+
+/*
+ * routine to get exprinfo type
+ */
+static int32 get_xinfo_typ(struct expr_t *xp)
+{
+ struct net_t *np;
+
+ switch ((byte) xp->optyp) {
+  case OPEMPTY: return(TF_NULLPARAM); 
+  case NUMBER:
+   if (xp->is_string) return(TF_STRING);
+   return(TF_READONLY);
+  case ISNUMBER:
+   if (xp->is_string) __arg_terr(__FILE__, __LINE__);
+   return(TF_READONLY);
+  case REALNUM: case ISREALNUM: return(TF_READONLYREAL);
+ }
+ /* some kind of rhs expr. that cannot be assigned to */
+ if (xp->tf_isrw)
+ switch ((byte) xp->optyp) {
+  case ID:
+  case GLBREF:
+   np = xp->lu.sy->el.enp;
+   if (np->ntyp == N_REAL) return(TF_READWRITEREAL);
+   /* know this is id than can be lhs */
+   return(TF_READWRITE);
+  case LSB:
+   np = xp->lu.x->lu.sy->el.enp;
+   if (np->n_isarr) return(TF_RWMEMSELECT);
+   return(TF_RWBITSELECT);
+  case PARTSEL: return(TF_RWPARTSELECT);
+  default: __case_terr(__FILE__, __LINE__);
+ }
+ return(TF_READONLY);
+}
+
+/*
+ * PARAMETER ACCESS ROUTINES
+ */
+
+extern int32 tf_igetp(int32 pnum, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_getp(pnum);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * return value of parameter as int
+ * values here are assumed to be signed 
+ * LOOKATME - document that ingores b val 
+ * according to LRM just return the low 32 bits without any checking
+ */
+extern int32 tf_getp(int32 pnum)
+{
+ int32 rv;
+ word32 *wp;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+ char *chp;
+
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_getp"));
+ if (pnum < 0 || pnum >= __tfrec->tfanump1) return(TF_NULLPARAM);
+ /* 0 ok here for possible func. return value */
+
+ xsp = NULL;
+ /* func. return value is special case */
+ if (pnum == 0)
+  {
+   if (!__tfrec->tf_func) return(TF_NULLPARAM);
+
+   push_xstk_(xsp, __tfrec->fretsiz);
+   wp = __tfrec->tfargs[0].arg.awp;
+   memcpy(xsp->ap, wp, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
+   if (__tfrec->fretreal) goto do_real;
+
+   /* SJM 08/31/00 - misread LRM for 2 value PLI 1.0 routines x/z is 0 */
+   if (!vval_is0_(xsp->bp, xsp->xslen)) rv = 0; else rv = (int32) xsp->ap[0];
+   goto done;  
+  }
+
+ xp = __tfrec->tfargs[pnum].arg.axp;
+ if (xp->optyp == OPEMPTY) return(TF_NULLPARAM);
+
+ xsp = __eval_xpr(xp);
+ /* if real, must round */
+ if (xp->is_real)
+  {
+do_real:
+   /* this implements Verilog style rounding */
+   __cnv_stk_fromreal_toreg32(xsp);
+   rv = (int32) xsp->ap[0];
+   goto done;
+  }
+ /* if any kind of literal string - cannot be expr - need c style */
+ /* the return 32 bit int32 is pointer to string */
+ if (xp->optyp == NUMBER && xp->is_string)
+  {
+   chp = __alloc_vval_to_cstr(xsp->ap, xsp->xslen, FALSE, FALSE);
+   /* FIXME ??? - not 64 bit clean */
+   rv = (int32) chp;
+   goto done; 
+  }
+
+ /* finally just return bit pattern - caller must interpret sign */
+ /* SJM 08/31/00 - misread LRM for 2 value PLI 1.0 routines x/z is 0 */
+ if (!vval_is0_(xsp->bp, xsp->xslen)) rv = 0; else rv = (int32) xsp->ap[0];
+done:
+ __pop_xstk();
+ return(rv);
+}
+
+extern int32 tf_igetlongp(int32 *aof_highvalue, int32 pnum, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_getlongp(aof_highvalue, pnum);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * get parameter into 2 32 bit ints (64 bits non x/z)
+ * if string return ptr in low 32 bits
+ * if paremeter real return error, must use getrealp
+ */
+extern int32 tf_getlongp(int32 *aof_highvalue, int32 pnum)
+{
+ int32 rv;
+ word32 *wp;
+ double d1;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+ char *chp;
+
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_getlongp"));
+ *aof_highvalue = 0;
+ if (pnum < 0 || pnum >= __tfrec->tfanump1) return(TF_NULLPARAM);
+ /* 0 ok here for possible func. return value */
+
+ xsp = NULL;
+ /* func. return value is special case */
+ if (pnum == 0)
+  {
+   if (!__tfrec->tf_func) return(TF_NULLPARAM);
+
+   push_xstk_(xsp, __tfrec->fretsiz);
+   wp = __tfrec->tfargs[0].arg.awp;
+   memcpy(xsp->ap, wp, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
+   if (__tfrec->fretreal) goto do_real;
+
+   /* SJM 08/31/00 - misread LRM for 2 value PLI 1.0 routines x/z is 0 */
+   if (!vval_is0_(xsp->bp, xsp->xslen)) { *aof_highvalue = 0; rv = 0; }
+   else
+    {
+     if (__tfrec->fretsiz > 32) *aof_highvalue = (int32) xsp->ap[1];
+     else *aof_highvalue = 0; 
+     rv = (int32) xsp->ap[0];
+    }
+   goto done;  
+  }
+
+ xp = __tfrec->tfargs[pnum].arg.axp;
+ if (xp->optyp == OPEMPTY) return(TF_NULLPARAM);
+
+ xsp = __eval_xpr(xp);
+ if (xp->is_real)
+  {
+do_real:
+   memcpy(&d1, xsp->ap, sizeof(double));
+   tf_real_to_long(d1, &rv, aof_highvalue);
+   goto done;
+  }
+ /* if any kind of literal string - cannot be expr - need c style */
+ /* the return 32 bit int32 is pointer to string */
+ if (xp->optyp == NUMBER && xp->is_string)
+  {
+   chp = __alloc_vval_to_cstr(xsp->ap, xsp->xslen, FALSE, FALSE);
+
+   /* FIXME ??? - not 64 bit clean */
+   rv = (int32) chp;
+   goto done; 
+  }
+
+ /* caller must interpret any sign */
+ /* SJM 08/31/00 - misread LRM for 2 value PLI 1.0 routines x/z is 0 */
+ if (!vval_is0_(xsp->bp, xsp->xslen)) { *aof_highvalue = 0; rv = 0; }
+ else
+  {
+   if (xsp->xslen > 32) *aof_highvalue = (int32) xsp->ap[1];
+   else *aof_highvalue = 0; 
+   rv = (int32) xsp->ap[0];
+  }
+
+done:
+ __pop_xstk();
+ return(rv);
+}
+
+/*
+ * return double from passed routine    
+ */
+extern double tf_igetrealp(int32 pnum, char *inst)
+{
+ double d1;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ d1 = tf_getrealp(pnum);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(d1);
+}
+
+/*
+ * get value of nparam (convert to real if needed) and return
+ * here return 0 if literal string and use signedness of node for sign of r 
+ */
+extern double tf_getrealp(int32 pnum)
+{
+ int32 i1;
+ word32 *wp;
+ double d1;
+ word64 t1;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+
+ xp = NULL;
+ if (__tfrec == NULL)
+  {
+   bad_notfcontext_err("tf_getrealp");
+   return((double) TF_NULLPARAM);
+  }
+ if (pnum < 0 || pnum >= __tfrec->tfanump1) return((double) TF_NULLPARAM);
+
+ /* 0 ok here for possible func. return value */
+ /* func. return value is special case */
+ if (pnum == 0)
+  {
+   if (!__tfrec->tf_func) return(TF_NULLPARAM);
+   push_xstk_(xsp, __tfrec->fretsiz);
+   wp = __tfrec->tfargs[0].arg.awp;
+   if (__tfrec->fretreal)
+    { memcpy(&d1, wp, sizeof(double)); goto done; }
+   memcpy(xsp->ap, wp, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
+   goto do_non_real;
+  }
+
+ xp = __tfrec->tfargs[pnum].arg.axp;
+ /* literal string is error */
+ if (xp->optyp == OPEMPTY || (xp->optyp == NUMBER && xp->is_string))
+  return((double) TF_NULLPARAM);
+
+ xsp = __eval_xpr(xp);
+ /* if real, must round */
+ if (xp->is_real) { memcpy(&d1, xsp->ap, sizeof(double)); goto done; }
+ /* only true if int32 and exactly 32 bits */
+ if (xp->has_sign) { i1 = (int32) xsp->ap[0]; d1 = (double) i1; goto done; }   
+
+do_non_real:
+ /* SJM 05/10/04 - must handle conversion of signed 33-64 to signed double */
+ if (xsp->xslen > WBITS)
+  {
+   if (xp->has_sign) d1 = __cnvt_signed64_to_real(xsp->ap, xsp->xslen);
+   else
+    {
+     t1 = ((word64) xsp->ap[0]) | (((word64) xsp->ap[1]) << 32); 
+     if (!__v64_to_real(&d1, &t1)) d1 = 0.0;
+    }
+  }
+ else d1 = (double) xsp->ap[0];
+
+done:
+ __pop_xstk();
+ return(d1);
+}
+
+/*
+ * convert signed 33 to 64 bit to real - tricky if narrow than 64
+ */
+extern double __cnvt_signed64_to_real(word32 *ap, int32 blen)
+{
+ word64 t1;
+ sword64 st1;
+ double d1;
+ 
+ /* DBG remove -- */
+ if (blen <= WBITS) __misc_terr(__FILE__, __LINE__);
+ /* -- */
+
+ /* t1 is just the word32 bit pattern */
+ t1 = ((word64) ap[0]) | (((word64) ap[1]) << 32); 
+ if (__is_lnegative(ap, blen))
+  {
+   t1 &= (((word64) ~(__masktab[ubits_(blen)])) << 32);
+   st1 = (sword64) t1;
+   st1 = -st1;
+   t1 = (word64) st1;
+   if (!__v64_to_real(&d1, &t1)) d1 = 0.0;
+   else d1 = -d1;
+  }
+ else
+  {
+   if (!__v64_to_real(&d1, &t1)) d1 = 0.0;
+  }
+ return(d1);
+}
+
+/*
+ * TF_ PARAMETER STORE ROUTINES
+ */
+
+extern int32 tf_iputp(int32 pnum, int32 value, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_putp(pnum, value);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * assign int32 value to parameter nparm
+ * return 0 on error else 1 and assign 
+ */
+extern int32 tf_putp(int32 pnum, int32 value)
+{
+ int32 rv;
+ word32 *wp;
+ struct tfarg_t *tfap;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+
+ if (__run_state != SS_SIM)
+  {
+   rv = bad_nosimtf_err("tf_(i)putp");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (__rosync_slot)
+  {
+   rv = bad_rosync_err("tf_(i)putp");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (__tfrec == NULL)
+  {
+   rv = bad_notfcontext_err("tf_putp");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (pnum < 0 || pnum >= __tfrec->tfanump1) return(1);
+
+ tfap = &(__tfrec->tfargs[pnum]);
+ /* 0 ok here for possible func. return value */
+ /* func. return value is special case - change return value, no assign */
+ if (pnum == 0)
+  {
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = (word32) value;
+   xsp->bp[0] = 0L;
+
+   if (!__tfrec->tf_func) return(1);
+   if (__tfrec->fretreal) __cnv_stk_fromreg_toreal(xsp, TRUE);
+   /* contiguous bytes of stack have value after possible conversion */
+   /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */ 
+   else if (xsp->xslen != __tfrec->fretsiz)
+    {
+     __sizchgxs(xsp, __tfrec->fretsiz);
+    }
+   wp = tfap->arg.awp;
+   memcpy(wp, xsp->ap, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
+   __pop_xstk();
+   return(0);
+  }
+
+ xp = tfap->arg.axp;
+ if (!xp->tf_isrw) return(1);
+ push_xstk_(xsp, WBITS);
+ xsp->ap[0] = (word32) value;
+ xsp->bp[0] = 0L;
+
+ /* assigned to param is real must convert before assign */ 
+ if (xp->is_real) __cnv_stk_fromreg_toreal(xsp, TRUE);
+ /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */ 
+ else if (xsp->xslen != xp->szu.xclen) __sizchgxs(xsp, xp->szu.xclen);
+ /* ok to assign (by continuous) to wire */
+ exec_tfarg_assign(tfap, xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+ return(0);
+}
+
+extern int32 tf_iputlongp(int32 pnum, int32 lowvalue, int32 highvalue, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_putlongp(pnum, lowvalue, highvalue);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * input is 64 bit as 2 ints that is assigned to expr.
+ * may need to convert stack to right lhs width and type
+ * return 0 on error else 1 and assign
+ */
+extern int32 tf_putlongp(int32 pnum, int32 lowvalue, int32 highvalue)
+{
+ int32 rv;
+ double d1;
+ struct tfarg_t *tfap;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+
+ if (__run_state != SS_SIM)
+  {
+   rv = bad_nosimtf_err("tf_(i)putlongp");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (__rosync_slot)
+  {
+   rv = bad_rosync_err("tf_(i)putlongp");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (__tfrec == NULL)
+  {
+   rv = bad_notfcontext_err("tf_putlongp");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (pnum < 0 || pnum >= __tfrec->tfanump1) return(1);
+
+ tfap = &(__tfrec->tfargs[pnum]);
+ /* 0 ok here for possible func. return value */
+ /* func. return value is special case - change return value, no assign */
+ if (pnum == 0)
+  {
+   if (!__tfrec->tf_func) return(1);
+
+   /* if assigning to real convert - but rule is to ignore high 32 bits here */
+   if (__tfrec->fretreal)
+    {
+     tf_long_to_real(lowvalue, highvalue, &d1);
+     memcpy(tfap->arg.awp, &d1, sizeof(double));
+     return(0);
+    }   
+
+   push_xstk_(xsp, 64);
+   xsp->ap[0] = (word32) lowvalue;
+   xsp->ap[1] = (word32) highvalue; 
+   xsp->bp[0] = xsp->bp[1] = 0L;
+   /* contiguous bytes of stack have value after possible conversion */
+   /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */ 
+   if (xsp->xslen != __tfrec->fretsiz) __sizchgxs(xsp, __tfrec->fretsiz);
+   memcpy(tfap->arg.awp, xsp->ap, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
+   __pop_xstk();
+   return(0);
+  }
+
+ xp = tfap->arg.axp;
+ if (!xp->tf_isrw) return(1);
+
+ /* assigned to param is real must convert to double before assign */ 
+ /* this must use time long form */
+ if (xp->is_real)
+  {
+   tf_long_to_real(lowvalue, highvalue, &d1);
+   push_xstk_(xsp, REALBITS);
+   memcpy(xsp->ap, &d1, sizeof(double));
+  } 
+ else
+  { 
+   push_xstk_(xsp, 64);
+   xsp->ap[0] = (word32) lowvalue;
+   xsp->ap[1] = (word32) highvalue; 
+   xsp->bp[0] = xsp->bp[1] = 0L;
+   /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */ 
+   if (xsp->xslen != xp->szu.xclen) __sizchgxs(xsp, xp->szu.xclen);
+  }
+ exec_tfarg_assign(tfap, xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+ return(0);
+}
+
+extern int32 tf_iputrealp(int32 pnum, double value, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_putrealp(pnum, value);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * assign real value to paramter nparm
+ */
+extern int32 tf_putrealp(int32 pnum, double value)
+{
+ register struct tfarg_t *tfap;
+ int32 rv;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+
+ if (__run_state != SS_SIM)
+  {
+   rv = bad_nosimtf_err("tf_(i)putrealp");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (__rosync_slot)
+  {
+   rv = bad_rosync_err("tf_(i)putrealp");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (__tfrec == NULL)
+  {
+   rv = bad_notfcontext_err("tf_putrealp");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (pnum < 0 || pnum >= __tfrec->tfanump1) return(1);
+
+ tfap = &(__tfrec->tfargs[pnum]);
+ /* 0 ok here for possible func. return value */
+ /* func. return value is special case - change return value, no assign */
+ if (pnum == 0)
+  {
+   if (!__tfrec->tf_func) return(1);
+   if (__tfrec->fretreal)
+    {
+     memcpy(tfap->arg.awp, &value, sizeof(double));
+     return(0);
+    }
+   if ((xsp = tf_pushconvfromreal(value, __tfrec->fretsiz)) == NULL)
+    return(1);
+   memcpy(tfap->arg.awp, xsp->ap, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
+   __pop_xstk();
+   return(0);
+  }
+
+ xp = tfap->arg.axp;
+ if (!xp->tf_isrw) return(1);
+
+ if (xp->is_real)
+  {
+   push_xstk_(xsp, REALBITS);
+   memcpy(xsp->ap, &value, sizeof(double));
+  }
+ else 
+  { 
+   if ((xsp = tf_pushconvfromreal(value, xp->szu.xclen)) == NULL)
+    return(1);
+  }
+ exec_tfarg_assign(tfap, xp, xsp->ap, xsp->bp);
+ __pop_xstk();
+ return(0);
+}
+
+/*
+ * routine to push and convert to real tf task/function parameter onto stack
+ * know only called 
+ * returns nil with nothing on stack on error 
+ */
+static struct xstk_t *tf_pushconvfromreal(double d1, int32 destsiz)
+{
+ int32 i, lo, hi;
+ struct xstk_t *xsp;
+
+ if (destsiz > WBITS)
+  {
+   tf_real_to_long(d1, &lo, &hi);
+   push_xstk_(xsp, 64);
+   xsp->ap[0] = (word32) lo;
+   xsp->ap[1] = (word32) hi;
+   xsp->bp[0] = xsp->bp[1] = 0L;
+  }
+ else
+  {
+   push_xstk_(xsp, WBITS);
+   i = (int32) d1;
+   xsp->ap[0] = (word32) i;
+   xsp->bp[0] = 0L;
+  } 
+ /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */ 
+ if (xsp->xslen != destsiz) __sizchgxs(xsp, destsiz);
+ return(xsp);
+} 
+
+/*
+ * TF STRING FORM GET VALUE (FOR X/Z) ROUTINES
+ */
+
+/*
+ * get a formatted c style string
+ */
+extern char *tf_istrgetp(int32 pnum, int32 format_char, char *inst)
+{
+ char *chp;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ chp = tf_strgetp(pnum, format_char);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(chp);
+}
+
+/*
+ * get a parameter into c style string  
+ */ 
+extern char *tf_strgetp(int32 pnum, int32 format_char)
+{
+ struct expr_t *xp;
+
+ if (__tfrec == NULL)
+  {
+   bad_notfcontext_err("tf_strgetp");
+   return(NULL);
+  }
+ if (pnum < 0 || pnum >= __tfrec->tfanump1) return(NULL);
+ /* 0 ok here for possible func. return value */
+ if (pnum == 0)
+  {
+   if (!__tfrec->tf_func) return(NULL);
+   return(__alloc_getasfmt((struct expr_t *) NULL, __tfrec, format_char));
+  }
+ xp = __tfrec->tfargs[pnum].arg.axp;
+ if (xp->optyp == OPEMPTY) return(NULL);
+
+ /* if returns 0, know expr line not changed */
+ return(__alloc_getasfmt(xp, (struct tfrec_t *) NULL, format_char));
+}
+
+/*
+ * convert parameter to c string
+ * i.e. force intrepretation as string
+ */
+extern char *tf_igetcstringp(int32 nparam, char *inst)
+{
+ char *chp;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ chp = tf_getcstringp(nparam);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(chp);
+}
+
+/*
+ * convert a value to a c string - evaluate expressions if needed
+ * converts bit pattern to c string 
+ */
+extern char *tf_getcstringp(int32 nparam)
+{
+ int32 blen;
+ word32 *wp;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+ char *chp;
+
+ if (__tfrec == NULL)
+  {
+   bad_notfcontext_err("tf_getcstringp");
+   return(NULL);
+  }
+ if (nparam < 0 || nparam >= __tfrec->tfanump1) return(NULL);
+ /* 0 ok here for possible func. return value */
+ if (nparam == 0)
+  {
+   if (!__tfrec->tf_func) return(NULL);
+   wp = __tfrec->tfargs[0].arg.awp;
+   blen = __trim1_0val(wp, __tfrec->fretsiz);
+   chp = __alloc_vval_to_cstr(wp, __tfrec->fretsiz, FALSE, FALSE);
+   return(chp);
+  }
+ xp = __tfrec->tfargs[nparam].arg.axp;
+ if (xp->optyp == OPEMPTY) return(NULL);
+
+ /* real bit pattern can't be output as string */
+ if (xp->is_real) return(NULL);
+
+ /* even if literal string can still evaluate */
+ /* this takes any bit pattern (i.e. real) and makes a string */
+ /* and ignores and b value */
+ xsp = __eval_xpr(xp);
+ /* must remove high 0 bytes */
+ blen = __trim1_0val(xsp->ap, xsp->xslen);
+ chp = __alloc_vval_to_cstr(xsp->ap, blen, FALSE, FALSE);
+ __pop_xstk();
+ return(chp);
+}
+
+/* 
+ * TF_ STRING FORM PARAMETER DELAYED STORE ROUTINES
+ */
+
+/*
+ * set a delay from a string that is scanfed into a value that is set
+ * for nparam of length bitlength use format_char to interpret value_p
+ * where schedule is delayed delay (scaled) and if of type delaytype
+ * and store value into parameter which will be lhs expr. at scheduled time
+ *
+ * return 0 on error 1 if ok, delaytype is 0 inertial, 1 transport, 2
+ * pure transport
+ * must be >= 0, 0 is #0 form
+ */
+
+/*
+ * schedule set for other pli task
+ */
+extern int32 tf_istrdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, int32 delay, int32 delaytype, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_strdelputp(nparam, bitlength, format_char, value_p, delay,
+  delaytype);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_strdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, int32 delay, int32 delaytype)
+{
+ int32 rv;
+ word64 ticks, t1;
+
+ /* scale from module delay to ticks */
+ t1 = (word64) delay;
+ if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
+ else ticks = t1;
+
+ rv = delayed_str_putp(nparam, bitlength, format_char, value_p,
+  ticks, delaytype);
+ return(rv);
+}
+
+/*
+ * routine that executes all delays since only difference is form
+ * of delay - by here converted to internal ticks (scaling done)
+ * dtyp is delay reschedule determining mode
+ * possibilities:
+ * 
+ * inertial replaces pending sched ev with later and removes earlier 
+ * 0: normal Verilog inertial (change so exactly one delay that is latest)
+ * 1: transport - remove all delays later than scheduled
+ * 2: pure transport - just add delay - never remove 
+ */
+static int32 delayed_str_putp(int32 nparam, int32 blen, int32 fmtch, char *value,
+ word64 ticksdel, int32 dtyp)
+{
+ register struct tfarg_t *tfap;
+ register struct dltevlst_t *dlp, *dlp2, *ins_after_dlp;
+ int32 nbytes;
+ word64 schtim;
+ i_tev_ndx tevpi;
+ struct expr_t *xp;
+ struct tedputp_t *tedp;
+ struct xstk_t *xsp;
+
+ if (__run_state != SS_SIM) return(bad_nosimtf_err("strdelputp type"));
+ if (__rosync_slot) return(bad_rosync_err("strdelputp type"));
+ if (__tfrec == NULL) return(bad_notfcontext_err("strdelputp type"));
+
+ /* cannot used schedule delayed putp to assign to return value */
+ if (nparam < 1 || nparam >= __tfrec->tfanump1) return(TF_NULLPARAM);
+ tfap = &(__tfrec->tfargs[nparam]);
+ xp = tfap->arg.axp;
+ if (!xp->tf_isrw) return(TF_NULLPARAM);
+ /* push value on to stack - width is lhs needed */
+ xsp = __putdstr_to_val(value, blen, xp->szu.xclen, fmtch);
+ if (xsp == NULL) return(TF_NULLPARAM);
+
+ schtim = __simtime + ticksdel;
+ ins_after_dlp = NULL;
+ /* eliminate new and/or cancel any olds */
+ if ((dlp = tfap->dputp_tedlst[__inum]) != NULL)
+  {
+   /* case 1: inertial - remove all but one latest - return if no effect */
+   if (dtyp == 0)
+    {
+     /* start by removing all of list but last (if needed) - know >=2 */
+     if (dlp->terp != NULL)
+      {
+       dlp2 = __spliceout_last(dlp);
+       cancel_dputp_toend(tfap, dlp);
+       dlp = dlp2;
+       tfap->dputp_tedlst[__inum] = dlp; 
+       dlp->telp = NULL;
+      }
+     /* by here list has exactly one element (last) */
+     /* if new one earlier - do not schedule, same time, use new */
+     if (__tevtab[dlp->tevpi].etime > schtim) { __pop_xstk(); return(1); }
+
+     /* know new event time is later - cancel all of list (i.e. 1 in list) */
+     cancel_dputp_toend(tfap, dlp);
+     tfap->dputp_tedlst[__inum] = NULL;
+     ins_after_dlp = NULL;
+     goto bld_tev;
+    }
+   /* case 2: modified transport - remove all delays > than new */
+   /* notice if same time delays must leave and insert this after all */
+   /* currently scheduled for this time */
+   if (dtyp == 1)
+    {
+     /* SJM 09/05/99 - think elmination when scheduled wrong */
+     /* nothing to remove, just put on end of active pnd0 queue */
+     /* SJM - if (schtim == 0ULL) goto bld_tev; WRONG */
+
+     /* know delay list in time order */
+     /* dlp2 is one before first after (maybe last), nil is before all */ 
+     if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL) 
+      { 
+       /* new delay is before all - must empty list */
+       /* all delays at same time not removed */
+       dlp2 = tfap->dputp_tedlst[__inum];
+       cancel_dputp_toend(tfap, dlp2);
+       tfap->dputp_tedlst[__inum] = NULL;
+       ins_after_dlp = NULL;
+       goto bld_tev; 
+      } 
+     /* new delay is after all - nothing to remove */
+     if (dlp2->terp == NULL) { ins_after_dlp = dlp2; goto bld_tev; } 
+     /* new delay is after some and before some */
+     ins_after_dlp = dlp2;
+     if (dlp2->terp != NULL)
+      { cancel_dputp_toend(tfap, dlp2->terp); dlp2->terp = NULL; }
+     goto bld_tev;
+    }
+   /* case 3: pure transport - insert in right place in list */
+   if (dtyp != 2) return(TF_NULLPARAM); 
+   /* new delay is before all - insert at front */
+   if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL) 
+    { ins_after_dlp = NULL; goto bld_tev; }
+   /* if goes after list, end of list returned else place to ins after */
+   ins_after_dlp = dlp2; 
+  }   
+
+bld_tev:
+ /* always build and fill the tev */
+ alloc_tev_(tevpi, TE_TFPUTPDEL, __inst_ptr, schtim);
+ if (__tedpfreelst != NULL)
+  {
+   tedp = __tedpfreelst;
+   __tedpfreelst = (struct tedputp_t *)__tedpfreelst->tedtfrp;
+  }
+ else tedp = (struct tedputp_t *) __my_malloc(sizeof(struct tedputp_t));
+ tedp->tedtfrp = __tfrec;
+ tedp->tedpnum = nparam;
+ __tevtab[tevpi].tu.tedputp = tedp;
+ 
+ nbytes = 2*WRDBYTES*wlen_(xsp->xslen);
+ tedp->tedwp = (word32 *) __my_malloc(nbytes);
+ memcpy(tedp->tedwp, xsp->ap, nbytes);  
+ __pop_xstk();
+ /* schedule event */
+ /* case 1: schedule and add to list */
+ /* SJM 09/05/99 - was only adding to pound 0 at time 0 - WRONG */
+ if (ticksdel == 0ULL)
+  {
+   if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+   else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+  }
+ else __insert_event(tevpi);
+ /* build the dl tev lst */
+ if (__dltevfreelst != NULL)
+  { dlp = __dltevfreelst; __dltevfreelst = __dltevfreelst->terp; }
+ else dlp = (struct dltevlst_t *) __my_malloc(sizeof(struct dltevlst_t)); 
+ dlp->tevpi = tevpi;
+
+ /* insert at front of list */
+ if (ins_after_dlp == NULL)  
+  {
+   dlp2 = tfap->dputp_tedlst[__inum];
+   dlp->terp = dlp2;
+   if (dlp2 != NULL) dlp2->telp = dlp;
+   dlp->telp = NULL;
+   tfap->dputp_tedlst[__inum] = dlp;
+  }
+ /* insert after */
+ else
+  {  
+   dlp->terp = ins_after_dlp->terp; 
+   if (dlp->terp != NULL) dlp->terp->telp = dlp;
+   ins_after_dlp->terp = dlp;
+   dlp->telp = ins_after_dlp;
+  }
+ return(1);
+}
+
+/*
+ * convert putp tf_ routine string to value
+ * returns nil if number bad
+ * stacked return value always lhs expected len wide 
+ *
+ * convert to lhs length and strength if lhs expr stren
+ * this is special type of scan with mechanism not needed by v_cnv
+ *
+ * blen is size for building number with x/z extension - lhslen is needed
+ * to convert so event eval. assign has exactly rigth width - assign convert
+ *
+ * allowing 'v'/'V' extension
+ */
+extern struct xstk_t *__putdstr_to_val(char *s, int32 blen, int32 lhslen,
+ int32 fmtch)
+{
+ register struct xstk_t *xsp;
+ int32 slen, stlen;
+
+ /* value can be at most id len postions wide - used lhs part sel. for wider */
+ if (fmtch == 'v' || fmtch == 'V')
+  {
+   if ((slen = strlen(s)) >= IDLEN) return(NULL);
+   if ((xsp = tftostrenval(s, &stlen)) == NULL) return(NULL);
+   /* adjusts xslen for narrow (xsawlen alloced size) else rebuilds */
+   if (stlen != lhslen) __strenwiden_sizchg(xsp, lhslen);
+   return(xsp);
+  }
+ /* check the number - must fit in id */
+ __itokbase = __to_base(fmtch);
+ /* this copies string without change to num token */
+ if (!chk_putdstr(s, __itokbase, &slen)) return(NULL);
+ if (slen >= IDLEN) return(NULL);
+
+ /* numeric case caller's passed length is token length */
+ __itoklen = blen; 
+ /* this cannot fail but to get here know string good - value in ac/bc wr k*/ 
+ __to_dhboval(__itokbase, TRUE);
+ push_xstk_(xsp, __itoklen);
+ cp_walign_(xsp->ap, __acwrk, __itoklen);
+ cp_walign_(xsp->bp, __bcwrk, __itoklen);
+ /* convert in preparation for storing in event for maybe later assign */
+ /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */ 
+ /* SJM 05/10/04 FIXME ??? ### but here could use format to determine */ 
+ if (xsp->xslen != lhslen) __sizchgxs(xsp, lhslen);
+ return(xsp);
+}
+
+/*
+ * check a number - also copies into token (only change is '_' removed)
+ * returns F on error else T returned len only valid if T 
+ */
+static int32 chk_putdstr(char *s, int32 base, int32 *len)
+{
+ register char *chp, *chp2;
+ register int32 slen;
+
+ /* SJM - 03/20/00 - know num token wide eough */
+ for (*len = 0, slen = 0, chp = s, chp2 = __numtoken; *chp != '\0';)
+  {
+   if (*chp == '_') { chp++; continue; }
+   if (__is_vdigit((int32) *chp, base) < 0) return(FALSE);
+   *chp2++ = *chp++;
+   slen++;
+  }
+ *chp2 = '\0';
+ *len = slen;
+ return(TRUE);
+}
+
+/*
+ * convert to strength value
+ * returns nil on error and checks for good (vector space separated) 
+ */
+static struct xstk_t *tftostrenval(char *s, int32 *bitlen)
+{
+ register int32 bi;
+ int32 blen, done, stval;
+ byte *sbp;
+ struct xstk_t *xsp;
+ char *chp, *chp2, s1[4];
+
+ /* strength value is 3 char value separated by white space */
+ /* 1st count - then allocate and check and build */
+ *bitlen = 0;
+ for (blen = 0, chp = s;;)
+  {
+   while (isspace(*chp)) chp++;
+   if (*chp == '\0') break;
+   blen++;
+   while (!isspace(*chp)) { if (*chp == '\0') goto strend; else chp++; } 
+  }
+strend:
+ /* notice blen is computed from actual chars in string */
+ if (blen == 0) return(NULL);
+ push_xstk_(xsp, 4*blen);
+ sbp = (byte *) xsp->ap;
+ for (chp = s, done = FALSE, bi = blen - 1;;)
+  {
+   while (isspace(*chp)) chp++;
+   if (*chp == '\0') break;
+   chp2 = chp;
+   while (!isspace(*chp))
+    { if (*chp == '\0') { done = TRUE; break; } else chp++; }
+   if (chp - chp2 != 3) return(NULL);
+   strncpy(s1, chp2, 3);
+   s1[3] = '\0';
+   if ((stval = to_stval(s1)) == -1) {__pop_xstk(); return(NULL); } 
+   sbp[bi--] = (byte) stval;
+   if (done) break;
+  }
+ *bitlen = blen;
+ return(xsp);
+}  
+
+/*
+ * convert from 3 character strength to 1 byte strength value
+ * return F on error
+ */
+static int32 to_stval(char *s)
+{
+ int32 st0, st1, stval;
+
+ if (strlen(s) != 3) return(FALSE);
+ if (strcmp(s, "HiZ") == 0) return(ST_HIZ);
+ switch (s[2]) {
+  case '0': stval = 0; break;
+  case '1': stval = 1; break;
+  /* notice z can only be HiZ */
+  case 'x': case 'X': stval = 3; break;
+  case 'H': stval = -2; break;
+  case 'L': stval = -3; break;
+  default: return(-1);
+ }
+ if (isdigit(s[0]))
+  {
+   if (!isdigit(s[1])) return(-1);
+   st0 = s[0] - '0';
+   st1 = s[1] - '1';
+   /* cannot have 07<x,z,0,1> or any numeric 0 */ 
+   if (st0 < 1 || st0 > 7 || st1 < 1 || st1 > 7) return(-1); 
+   /* <0,0>=? is error hiZ required for <0,0>=z */
+   if (st0 == 0 && st1 == 0) return(-1);
+   /* L or H requires and value cannot be digit z */
+   if (stval <= -2) return(-1);
+   stval |= ((st0 << 5) | (st1 << 2));
+   return(stval);
+  }
+ /* must match strength name including case */
+ switch (s[0]) {
+  case 'S':
+   if (s[1] == 'u') st0 = st1 = 7;  
+   else if (s[1] == 't') st0 = st1 = 6;
+   else if (s[1] == 'm') st0 = st1 = 1;
+   else return(-1);
+   break;
+  case 'P': if (s[1] != 'u') return(-1); st0 = st1 = 5; break;
+  case 'L': if (s[1] != 'a') return(-1); st0 = st1 = 4; break;
+  case 'W': if (s[1] != 'e') return(-1); st0 = st1 = 3; break;
+  case 'M': if (s[1] != 'e') return(-1); st0 = st1 = 2; break;
+  default: return(-1);
+ }
+ /* handle H */
+ if (stval == -2)
+  {
+   /* 000sss02 */
+   stval = (st1 << 2) | 2; 
+   return(stval);
+  }
+ /* handle L */
+ if (stval == -3)
+  {
+   /* sss00002 */
+   stval = (st0 << 5) | 2; 
+   return(stval);
+  }
+ /* handle normal value */
+ stval |= ((st0 << 5) | (st1 << 2));
+ return(stval);
+}
+
+/*
+ * cancel all events starting at passed to end 
+ *
+ * for change to inertial - free all but last and return last (latest)
+ * this list for the one given parameter must be ordered by time
+ * caller must set previous next field to nil or nil out list
+ */
+static void cancel_dputp_toend(struct tfarg_t *tfap, struct dltevlst_t *frdlp)
+{
+ register struct dltevlst_t *dlp;
+ register struct tev_t *tevp;
+ int32 lhslen;
+ byte *sbp;
+ struct tedputp_t *tedp;
+ struct expr_t *xp;
+ struct dltevlst_t *last_dlp;
+
+ for (last_dlp = NULL, dlp = frdlp; dlp != NULL; dlp = dlp->terp)  
+  {
+   tevp = &(__tevtab[dlp->tevpi]); 
+   /* DBG remove -- */
+   if (tevp->tetyp != TE_TFPUTPDEL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   tedp = tevp->tu.tedputp;
+   tevp->te_cancel = TRUE;
+   xp = tfap->arg.axp;
+   lhslen = xp->szu.xclen;
+   /* free the value */
+   if (xp->x_stren)
+    { sbp = (byte *) tedp->tedwp; __my_free((char *) sbp, lhslen); }
+   else __my_free((char *) tedp->tedwp, 2*wlen_(lhslen)*WRDBYTES);
+
+   /* free tedputp by linking on free list */
+   tedp->tedtfrp =  (struct tfrec_t *) __tedpfreelst;
+   __tedpfreelst = tedp;
+   last_dlp = dlp;
+  }
+ /* finally link all of tevlst onto free list */
+ /* SJM 08/02/01 - add if to keep lint happy */
+ if (last_dlp != NULL) last_dlp->terp = __dltevfreelst; 
+ __dltevfreelst = frdlp;
+}
+
+/*
+ * splice out and return last tev list element
+ * only called if at least one two
+ */
+extern struct dltevlst_t *__spliceout_last(register struct dltevlst_t *dlp)
+{
+ for (; dlp->terp != NULL; dlp = dlp->terp) ;
+ /* know dlp has one before */ 
+ dlp->telp->terp = NULL; 
+ return(dlp);
+}
+
+/*
+ * find last doubly linked te list element before new time
+ *
+ * know at least one scheduled or routine not called
+ * if multiple as same time, return last of same time
+ * if all at current time returns last of current time 
+ * if ntim after all, returns last
+ * if ntim before all, returns nil
+ *
+ * needed for modified transport where keep earlier (remove all after)
+ * new event is after all same time
+ *
+ * notice modified transport keeps all of same time and put new on end
+ */
+extern struct dltevlst_t *__find_last_bdltevp(register struct dltevlst_t *dlp,
+ word64 ntim)
+{
+ register struct dltevlst_t *last_dlp;
+
+ for (last_dlp = NULL; dlp != NULL; dlp = dlp->terp)
+  {
+   if (ntim < __tevtab[dlp->tevpi].etime) return(dlp->telp);
+   last_dlp = dlp;
+  }
+ return(last_dlp);
+}
+
+/*
+ * schedule set but use long time and other pli task
+ */
+extern int32 tf_istrlongdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, int32 lowdelay, int32 highdelay, int32 delaytype, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_strlongdelputp(nparam, bitlength, format_char, value_p, lowdelay,
+  highdelay, delaytype);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * schedule set but use long time 
+ */
+extern int32 tf_strlongdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, int32 lowdelay, int32 highdelay, int32 delaytype)
+{
+ int32 rv;
+ word64 t1, ticks;
+
+ /* scale from module delay to ticks */
+ /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
+ t1 = ((word64) ((word32) lowdelay)) | (((word64) ((word32) highdelay)) << 32);
+ if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
+ else ticks = t1;
+
+ rv = delayed_str_putp(nparam, bitlength, format_char, value_p,
+  ticks, delaytype);
+ return(rv);
+}
+
+/*
+ * schedule set but use real time and other pli task
+ */
+extern int32 tf_istrrealdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, double realdelay, int32 delaytype, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_strrealdelputp(nparam, bitlength, format_char, value_p, realdelay,
+  delaytype);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * schedule set but use real time 
+ */
+extern int32 tf_strrealdelputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, double realdelay, int32 delaytype)
+{
+ int32 rv;
+ word64 t1, ticks;
+
+ /* convert real to time */
+ if (!__real_to_v64tim(&t1, realdelay)) return(TF_NULLPARAM); 
+
+ /* then scale real from module time to ticks if needed */
+ if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
+ else ticks = t1;
+
+ /* here returns 1 for good and 0 if error */
+ rv = delayed_str_putp(nparam, bitlength, format_char, value_p,
+  ticks, delaytype);
+ return(rv);
+}
+
+/*
+ * added routine that uses real 0 delay (i.e. immediate store)
+ * in delay forms delay 0 is #0
+ * this does not use any delay and is independent of strdelputp
+ * so if pending delay delays will happen as if only option is
+ * pure transport that never cancels a delay
+ */
+extern int32 tf_istrputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_strputp(nparam, bitlength, format_char, value_p);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_strputp(int32 nparam, int32 bitlength, int32 format_char,
+ char *value_p)
+{
+ struct tfarg_t *tfap;
+ int32 lhslen;
+ struct expr_t *lhsxp;
+ struct xstk_t *xsp;
+
+ if (__run_state != SS_SIM) return(bad_nosimtf_err("tf_strputp"));
+ if (__rosync_slot) return(bad_rosync_err("tf_strputp"));
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_strputp"));
+
+ /* cannot used schedule delayed putp to assign to return value */
+ if (nparam < 1 || nparam >= __tfrec->tfanump1) return(TF_NULLPARAM);
+ tfap = &(__tfrec->tfargs[nparam]);
+ lhsxp = tfap->arg.axp;
+ if (!lhsxp->tf_isrw) return(TF_NULLPARAM);
+
+ lhslen = lhsxp->szu.xclen;
+ /* push value on to stack - width is lhs needed (maybe converted) */
+ xsp = __putdstr_to_val(value_p, bitlength, lhslen, format_char);
+ if (xsp == NULL) return(TF_NULLPARAM);
+
+ if (__ev_tracing)
+  {
+   char s1[RECLEN], s2[RECLEN];
+
+   if (tfap->anp->ntyp >= NONWIRE_ST) strcpy(s1, "procedural");
+   else if (lhsxp->x_multfi) strcpy(s1, "continuous fi>1");
+   else strcpy(s1, "continuous fi=1");
+   if (lhsxp->x_stren)
+    __st_regab_tostr(s2, (byte *) xsp->ap, lhsxp->szu.xclen);
+   else __regab_tostr(s2, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE);
+   __evtr_resume_msg();
+   __tr_msg(
+    "tf_ arg %d at %s in %s tf_strputp %s assign value %s\n",
+    nparam, __bld_lineloc(__wrks1, __tfrec->tffnam_ind, __tfrec->tflin_cnt),
+    __msg2_blditree(__wrks2, __inst_ptr), s1, s2);
+  }
+ exec_tfarg_assign(tfap, lhsxp, xsp->ap, xsp->bp);
+ __pop_xstk();
+ return(1);
+}
+
+/*
+ * SYNCHRONIZE (MISCTF) CONTROL AND DELAY (NOT VALUE) ROUTINES
+ */
+
+/*
+ * schedule a delay at delay + __simtime
+ * calls misctf with reason_reactivate when event happens
+ * must be >= 0, 0 is #0 form
+ * must scale for time scale
+ * returns 0 on error else non 0
+ */
+extern int32 tf_isetdelay(int32 delay, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_setdelay(delay);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * set delay for other pli task
+ * SJM 12/17/02 - notice this returns 0 on error unlike most others 
+ */
+extern int32 tf_setdelay(int32 delay)
+{
+ int32 rv;
+ word64 ticks, t1;
+
+ /* scale from module delay to ticks */
+ /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
+ t1 = (word64) ((word32) delay);
+ if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
+ else ticks = t1;
+
+ rv = delayed_misctf_schd(ticks);
+ return(rv);
+}
+
+/*
+ * routine that schedules call to misctf routine 
+ * by here delay converted to internal ticks (scaling done)
+ *
+ * SJM 12/17/02 - notice this returns 0 on error unlike most others 
+ */
+static int32 delayed_misctf_schd(word64 ticksdel)
+{
+ i_tev_ndx tevpi;
+ struct tevlst_t *telp;
+ word64 schtim;
+
+ if (__run_state != SS_SIM) return(bad_nosimtf_err("setdelay type"));
+ if (__rosync_slot) return(bad_rosync_err("setdelay type"));
+ if (__tfrec == NULL) return(bad_notfcontext_err("setdelay type"));
+
+ schtim = __simtime + ticksdel;
+ alloc_tev_(tevpi, TE_TFSETDEL, __inst_ptr, schtim);
+ __tevtab[tevpi].tu.tetfrec = __tfrec;
+
+ /* put event on front of tev pendng list for instance */
+ if (__ltevfreelst != NULL)
+  { telp = __ltevfreelst; __ltevfreelst = __ltevfreelst->telnxt; }
+ else telp = (struct tevlst_t *) __my_malloc(sizeof(struct tevlst_t)); 
+ telp->telnxt = __tfrec->setd_telst[__inum];
+ __tfrec->setd_telst[__inum] = telp;
+ telp->tevpi = tevpi;
+ 
+ /* add to event queue */
+ if (ticksdel == 0ULL)
+  {
+   if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+   else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+  }
+ else __insert_event(tevpi);
+ return(1);
+}
+
+/*
+ * schedule long form (for now just ignore high long)
+ * SJM 12/17/02 - notice this returns 0 on error unlike most others 
+ */
+extern int32 tf_isetlongdelay(int32 lowdelay, int32 highdelay, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_setlongdelay(lowdelay, highdelay);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * other pli task form of schedule long delay
+ */
+extern int32 tf_setlongdelay(int32 lowdelay, int32 highdelay)
+{
+ int32 rv;
+ word64 t1, ticks;
+
+ /* scale from module delay to ticks */
+ /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
+ t1 = ((word64) ((word32) lowdelay))
+  | (((word64) ((word32) highdelay)) << 32);
+ if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
+ else ticks = t1;
+
+ rv = delayed_misctf_schd(ticks);
+ return(rv);
+}
+
+/*
+ * set delay passed as real (double)
+ */
+extern int32 tf_isetrealdelay(double realdelay, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_setrealdelay(realdelay);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * set delay passed as real (double)
+ * SJM 12/17/02 - notice this returns 0 on error unlike most others 
+ */
+extern int32 tf_setrealdelay(double realdelay)
+{
+ int32 rv;
+ word64 t1, ticks;
+
+ /* convert real to time */
+ if (!__real_to_v64tim(&t1, realdelay)) return(TF_NULLPARAM); 
+
+ /* then scale real from module time to ticks if needed */
+ if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
+ else ticks = t1;
+ rv = delayed_misctf_schd(ticks);
+ return(rv);
+}
+
+/*
+ * get next time at which a simulation event is scheduled 
+ * can just scan through required list of scheduled events for this
+ * task call and find first - assume slow
+ *
+ * this is slow if many scheduled events
+ * set time and return 0 if ok, 1 no events, 2 not in ro synchronize mode
+ * 
+ * WRITEME
+ */
+extern int32 tf_getnextlongtime(int32 *aof_lowtime, int32 *aof_hightime)
+{
+ if (__run_state != SS_SIM) return(bad_nosimtf_err("tf_getnextlongtime"));
+ /* MYABE WRITEME */
+ __sgferr(1301,
+  "tf_getnexlongtime not implemented - use PLI 2.0 cbNextSimTime callback");
+ return(TF_NULLPARAM);
+}
+
+/*
+ * clear (unschedule) delays
+ * mark every event as cancelled and frees tev list
+ * must cancel and free for all arguments
+ */
+extern int32 tf_iclearalldelays(char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_clearalldelays();
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_clearalldelays(void)
+{
+ register struct tevlst_t *telp, *last_telp;
+
+ if (__run_state != SS_SIM) return(bad_nosimtf_err("tf_(i)clearalldelays"));
+ if (__rosync_slot) return(bad_rosync_err("tf_(i)clearalldelays"));
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_clearalldelays"));
+
+ if ((telp = __tfrec->setd_telst[__inum]) == NULL) return(1);
+ /* notice these do not have any internal that needs to be freed */ 
+ for (last_telp = NULL; telp != NULL; telp = telp->telnxt) 
+  { __tevtab[telp->tevpi].te_cancel = TRUE; last_telp = telp; }
+ last_telp->telnxt = __ltevfreelst; 
+ __ltevfreelst = __tfrec->setd_telst[__inum];
+ __tfrec->setd_telst[__inum] = NULL;
+ return(1);
+}
+
+/*
+ * other pli form for synchronize call 
+ */
+extern int32 tf_isynchronize(char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_synchronize();
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * cause call of misctf user routine with reason_sync at end of called time
+ * this schedules routine at end of pound0 list when called
+ * set flag that causes calling of misctf at end of time slot (very end?)
+ */
+extern int32 tf_synchronize(void)
+{
+ i_tev_ndx tevpi;
+
+ if (__run_state != SS_SIM)
+  {
+   return(bad_nosimtf_err("tf_synchronize"));
+  }
+ if (__rosync_slot)
+  {
+   return(bad_rosync_err("tf_sychronize"));
+  }
+ if (__tfrec == NULL)
+  {
+   return(bad_notfcontext_err("tf_synchronize"));
+  }
+
+ /* if already called nothing to do */
+ if (__tfrec->sync_tevp[__inum] != -1) return(1);
+
+ alloc_tev_(tevpi, TE_SYNC, __inst_ptr, __simtime);
+ __tevtab[tevpi].tu.tetfrec = __tfrec;
+ __tfrec->sync_tevp[__inum] = tevpi;
+ /* schedule event at end of #0 queue - just need to lin on */
+ if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+ else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+ return(1);
+}
+
+/*
+ * cause call of misctf user routine with reason_sync at end of called time
+ * misctf called with reason_rosync
+ * this schedules routine as very last thing (before monitor/strobe)
+ * user must not call any routine that schedules events (not checked)
+ *
+ * set flag that causes calling of misctf at end of time slot (very end?)
+ */
+extern int32 tf_irosynchronize(char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_rosynchronize();
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_rosynchronize(void)
+{
+ int32 rv;
+ i_tev_ndx tevpi;
+
+ if (__run_state != SS_SIM)
+  {
+   rv = bad_nosimtf_err("tf_rosynchronize");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ /* can not call reason ro sync from within rosync routine */
+ if (__rosync_slot)
+  {
+   rv = bad_rosync_err("tf_rosychronize");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (__tfrec == NULL)
+  {
+   rv = bad_notfcontext_err ("tf_rosynchronize");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+
+ /* if already called nothing to do */
+ if (__tfrec->rosync_tevp[__inum] != -1) return(1);
+
+ /* this is separate list that determines type, type never seen */
+ alloc_tev_(tevpi, TE_UNKN, __inst_ptr, __simtime);
+ __tevtab[tevpi].tu.tetfrec = __tfrec;
+ /* link on front of rosync list */
+ if (__tehdr_rosynci == -1) __tehdr_rosynci = __teend_rosynci = tevpi;
+ else { __tevtab[__teend_rosynci].tenxti = tevpi; __teend_rosynci = tevpi; }
+ __tfrec->rosync_tevp[__inum] = tevpi;
+ __slotend_action |= SE_TFROSYNC;
+ return(0);
+}
+
+/*
+ * turn off parameter change misctf calling
+ */ 
+extern int32 tf_iasynchoff(char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_asynchoff();
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_asynchoff(void)
+{
+ int32 rv;
+
+ if (__run_state != SS_SIM)
+  {
+   rv = bad_nosimtf_err("tf_(i)asynchoff");
+   /* SJM 12/17/02 - error for asynch on/off is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (__tfrec == NULL)
+  {
+   rv = bad_notfcontext_err("tf_asynchoff");
+   /* SJM 12/17/02 - error for asynch on/off is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+
+ /* if already off nothing to do */
+ /* SJM 12/17/02 LOOKATME ??? - assuming nothing to do is success */
+ if (__tfrec->asynchon[__inum]) return(0);
+
+ /* free dces and regen iops if needed for every param to turn off */
+ /* may not be any dce's, but that still works */
+
+ /* SJM 02/08/03 - can never free dces if -O used */
+ /* for interpreter free dces, prev val num insts always 1, know peri */
+ if (__optimized_sim) __dcelst_off(__tfrec->pvcdcep[__inum]);
+ else __free_dceauxlst(__tfrec->pvcdcep[__inum], 1);
+
+ __tfrec->pvcdcep[__inum] = NULL;
+ __tfrec->asynchon[__inum] = 0;
+
+ return(0);
+}
+
+/*
+ * turn on calling of misctf routines on parameter change
+ */ 
+extern int32 tf_iasynchon(char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_asynchon();
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_asynchon(void)
+{
+ register int32 i;
+ int32 rv;
+
+ if (__run_state != SS_SIM)
+  {
+   rv = bad_nosimtf_err("tf_(i)asynchon");
+   /* SJM 12/17/02 - error for asynch on/off is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ if (__tfrec == NULL)
+  {
+   rv = bad_notfcontext_err("tf_asynchon");
+   /* SJM 12/17/02 - error for asynch on/off is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+
+ /* if already on nothing to do */ 
+ /* SJM 12/17/02 LOOKATME ??? - assuming nothing to do is success */
+ if (__tfrec->asynchon[__inum]) return(0);
+ /* build dces for every param and turn on */
+ 
+ __pvc_dcehdr = NULL;
+ for (i = 1; i < __tfrec->tfanump1; i++)
+  bld_pvc_dces(__tfrec->tfargs[i].arg.axp, i);
+ __tfrec->pvcdcep[__inum] = __pvc_dcehdr; 
+ __tfrec->asynchon[__inum] = 1;
+
+ return(0);
+}
+
+/*
+ * PVC FLAG ROUTINES
+ */
+
+/*
+ * move for different inst. and location pli task
+ * move old pvc to saved flag and clears old flag and return moved
+ * -1 is all and return ored change value 
+ */
+extern int32 tf_imovepvc_flag(int32 nparam, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_movepvc_flag(nparam);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_movepvc_flag(int32 nparam)
+{
+ register int32 i, ii;
+ byte oldpvc;
+ int32 rv;
+ struct tfarg_t *tfap;
+
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_movepvc_flag"));
+ ii = __inum;
+ rv = 0;
+ if (nparam == -1)
+  {
+   /* move old to saved pvc flags and reset old */
+   for (i = 1; i < __tfrec->tfanump1; i++)
+    {
+     tfap = &(__tfrec->tfargs[i]);
+     if ((oldpvc = tfap->old_pvc_flgs[ii]) != 0) rv = 1; 
+     tfap->old_pvc_flgs[ii] = 0;
+     tfap->sav_pvc_flgs[ii] = oldpvc;
+    }
+   return(rv);
+  }
+ tfap = &(__tfrec->tfargs[nparam]);
+ if ((oldpvc = tfap->old_pvc_flgs[ii]) != 0) rv = 1; 
+ tfap->old_pvc_flgs[ii] = 0;
+ tfap->sav_pvc_flgs[ii] = oldpvc;
+ return(rv);
+}
+
+/*
+ * copy pvc flag to saved flag
+ * returns flag that was copied
+ * flags are internal to pli tasks per parameter
+ * if nparams == -1 copy all and return logic or of all
+ * notice copy does not result oldpvc that is set by verilog dctrls
+ */
+extern int32 tf_icopypvc_flag(int32 nparam, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_copypvc_flag(nparam);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_copypvc_flag(int32 nparam)
+{
+ register int32 i, ii;
+ byte oldpvc;
+ int32 rv;
+ struct tfarg_t *tfap;
+
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_copypvc_flag"));
+ ii = __inum;
+ rv = 0;
+ if (nparam == -1)
+  {
+   /* move old to saved pvc flags and reset old */
+   for (i = 1; i < __tfrec->tfanump1; i++)
+    {
+     tfap = &(__tfrec->tfargs[i]);
+     if ((oldpvc = tfap->old_pvc_flgs[ii]) != 0) rv = 1; 
+     tfap->sav_pvc_flgs[ii] = oldpvc;
+    }
+   return(rv);
+  }
+ tfap = &(__tfrec->tfargs[nparam]);
+ if ((oldpvc = tfap->old_pvc_flgs[ii]) != 0) rv = 1; 
+ tfap->sav_pvc_flgs[ii] = oldpvc;
+ return(rv);
+}
+
+/*
+ * returns saved flag, -1 means or of all 
+ */
+extern int32 tf_itestpvc_flag(int32 nparam, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_testpvc_flag(nparam);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_testpvc_flag(int32 nparam)
+{
+ register int32 i, ii;
+ int32 rv;
+ struct tfarg_t *tfap;
+
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_testpvc_flag"));
+ rv = 0;
+ ii = __inum;
+ if (nparam == -1)
+  {
+   /* move old to saved pvc flags and reset old */
+   for (i = 1; i < __tfrec->tfanump1; i++)
+    {
+     tfap = &(__tfrec->tfargs[i]);
+     if (tfap->old_pvc_flgs[ii] != 0) rv = 1; 
+    }
+   return(rv);
+  }
+ tfap = &(__tfrec->tfargs[nparam]);
+ if (tfap->old_pvc_flgs[ii] != 0) rv = 1; 
+ return(rv);
+}
+
+/*
+ * get number of parameter that is > nparam
+ * nparam must be 0 for 1st time called within a given user routine
+ * invocation
+ * returns 0 if no change > nparam or error
+ * must execute tf_movepfv_flag before using routine
+ * DOCUMENTME - for Cver does not need to be called with 0 first time
+ */
+extern int32 tf_igetpchange(int32 nparam, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_getpchange(nparam);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+extern int32 tf_getpchange(int32 nparam)
+{
+ register int32 i, ii;
+ struct tfarg_t *tfap;
+
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_getpchange"));
+ ii = __inum;
+ if (nparam == 0) i = 1; else i = nparam + 1;
+ for (; i < __tfrec->tfanump1; i++)
+  {
+   tfap = &(__tfrec->tfargs[i]);
+   if (tfap->sav_pvc_flgs[ii] != 0) return(i);
+  }
+ return(TF_NULLPARAM);
+}
+
+/*
+ * VERILOG SERVICES ROUTINES - MOSTLY TIME AND DELAY SCALING
+ */
+
+/*
+ * get current sim time but scaled to timescale of inst.
+ * scaled from 
+ */
+extern int32 tf_igettime(char *inst)
+{
+ word64 timval;
+ struct tfinst_t *tfi;
+ struct mod_t *mdp;
+
+ tfi = (struct tfinst_t *) inst;
+ mdp = tfi->tfitp->itip->imsym->el.emdp; 
+ if (!mdp->mno_unitcnv)
+  {
+   __cnv_ticks_tonum64(&timval, __simtime, mdp);
+   return((int32) (timval & WORDMASK_ULL));
+  }
+ return((int32) (__simtime & WORDMASK_ULL));
+}
+
+/*
+ * return current time as int32 (low 32 bits)  
+ * user must cast to word32 or will lose high bit
+ */
+extern int32 tf_gettime(void)
+{
+ word64 timval;
+
+ if (!__inst_mod->mno_unitcnv)
+  __cnv_ticks_tonum64(&timval, __simtime, __inst_mod);
+ else timval = __simtime;
+ return((int32) (timval & WORDMASK_ULL));
+}
+
+/*
+ * return current time as int32 (low 32 bits) in ticks not scaled  
+ * user must cast to word32 or will lose high bit
+ */
+extern int32 tf_getsimtime(void)
+{
+ return((int32) (__simtime & WORDMASK_ULL));
+}
+
+/* 
+ * get a long time using other instance for from ticks scaling
+ * caller must cast to word32 or will lose high bits
+ */
+extern int32 tf_igetlongtime(int32 *aof_hightime, char *inst)
+{
+ word64 timval;
+ struct tfinst_t *tfi;
+ struct mod_t *mdp;
+
+ tfi = (struct tfinst_t *) inst;
+ mdp = tfi->tfitp->itip->imsym->el.emdp; 
+ if (!mdp->mno_unitcnv)
+  {
+   __cnv_ticks_tonum64(&timval, __simtime, mdp);
+   *aof_hightime = (int32) ((timval >> 32) & WORDMASK_ULL);
+   return((int32) (timval & WORDMASK_ULL));
+  }
+ *aof_hightime = (int32) ((__simtime >> 32) & WORDMASK_ULL);
+ return((int32) (__simtime & WORDMASK_ULL));
+}
+
+/* 
+ * get a long time in ticks - lowest time precision in design
+ * caller must cast to word32 or will lose high bit
+ *
+ * routine added because present in XL - no inst form 
+ */
+extern int32 tf_getlongsimtime(int32 *aof_hightime)
+{
+ *aof_hightime = (int32) ((__simtime >> 32) & WORDMASK_ULL);
+ return((int32) (__simtime & WORDMASK_ULL));
+}
+
+/* 
+ * get a long time using other instance for from ticks scaling
+ * caller must cast to word32 or will lose high bit
+ */
+extern int32 tf_getlongtime(int32 *aof_hightime)
+{
+ word64 timval;
+
+ if (!__inst_mod->mno_unitcnv)
+  {
+   __cnv_ticks_tonum64(&timval, __simtime, __inst_mod);
+   *aof_hightime = (int32) ((timval >> 32) & WORDMASK_ULL);
+   return((int32) (timval & WORDMASK_ULL));
+  }
+ *aof_hightime = (int32) ((__simtime >> 32) & WORDMASK_ULL);
+ return((int32) (__simtime & WORDMASK_ULL));
+}
+
+/*
+ * convert long time to string - does not scale caller must pass scaled
+ * also no time unit suffix
+ */
+extern char *tf_longtime_tostr(int32 lowtime, int32 hightime)
+{
+ int32 save_nd_tsuf, slen;
+ word64 t1;
+ char *chp, s1[RECLEN];
+ 
+ save_nd_tsuf = __nd_timstr_suf;
+ __nd_timstr_suf = FALSE;
+ 
+ t1 = ((word64) ((word32) lowtime)) | (((word64) ((word32) hightime)) << 32);
+ __to_timstr(s1, &t1);
+ __nd_timstr_suf = save_nd_tsuf;
+ slen = strlen(s1);
+ chp = __mytf_malloc(slen + 1);
+ strcpy(chp, s1);
+ return(chp);
+}
+
+/*
+ * get scaled time as real 
+ * i.e. get time then convert from ticks to real
+ */
+extern double tf_igetrealtime(char *inst)
+{
+ double d1;
+ word64 timval;
+ struct tfinst_t *tfi;
+ struct mod_t *mdp;
+
+ tfi = (struct tfinst_t *) inst;
+ mdp = tfi->tfitp->itip->imsym->el.emdp; 
+ if (!mdp->mno_unitcnv) __cnv_ticks_tonum64(&timval, __simtime, mdp);
+ else timval = __simtime;
+ if (!__v64_to_real(&d1, &timval)) return((double) 0.0);
+ return(d1); 
+}
+
+extern double tf_getrealtime(void)
+{
+ double d1;
+ word64 timval;
+
+ if (!__inst_mod->mno_unitcnv)
+  __cnv_ticks_tonum64(&timval, __simtime, __inst_mod);
+ else timval = __simtime;
+ if (!__v64_to_real(&d1, &timval)) return((double) 0.0);
+ return(d1); 
+}
+
+/*
+ * return pointer that is string of current time
+ * LOOKATME - not listed as scaled in list but assuming it is for now
+ */
+extern char *tf_strgettime(void)
+{
+ int32 save_nd_tsuf, slen;
+ word64 timval;
+ char *chp, s1[RECLEN];
+
+ if (!__inst_mod->mno_unitcnv)
+  __cnv_ticks_tonum64(&timval, __simtime, __inst_mod);
+ else timval = __simtime;
+
+ save_nd_tsuf = __nd_timstr_suf;
+ __nd_timstr_suf = FALSE;
+ __to_timstr(s1, &timval);
+ __nd_timstr_suf = save_nd_tsuf;
+ slen = strlen(s1);
+ chp = __mytf_malloc(slen + 1);
+ strcpy(chp, s1);
+ return(chp);
+}
+
+/*
+ * convert delay into internal simulation time units
+ * use the inst to find module that has delay
+ */
+extern void tf_scale_longdelay(char *cell, int32 delay_lo, int32 delay_hi,
+ int32 *aof_delay_lo, int32 *aof_delay_hi)
+{
+ word64 t1, t2;
+ struct tfinst_t *tfi;
+ struct mod_t *mdp;
+ 
+ /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
+ t1 = ((word64) ((word32) delay_lo)) | (((word64) ((word32) delay_hi)) << 32);
+
+ tfi = (struct tfinst_t *) cell;
+ mdp = tfi->tfitp->itip->imsym->el.emdp; 
+ if (!mdp->mno_unitcnv) cnv_num64to_ticks_(t2, t1, mdp);
+ else t2 = t1;
+ *aof_delay_lo = (int32) (t2 & WORDMASK_ULL);
+ *aof_delay_hi = (int32) ((t2 >> 32) & WORDMASK_ULL);
+}
+
+/*
+ * convert delay as real into internal simulation time units
+ *
+ * passed delay which is in units of cell instance and convert to internal
+ * ticks (i.e. lowest in design)
+ * LOOKATME - for now rouding to ticks but maybe should use time format
+ * values
+ */
+extern void tf_scale_realdelay(char *cell, double realdelay,
+ double *aof_realdelay)
+{
+ int32 unit;
+ struct tfinst_t *tfi;
+ struct mod_t *mdp;
+
+ tfi = (struct tfinst_t *) cell;
+ mdp = tfi->tfitp->itip->imsym->el.emdp; 
+ if (!mdp->mno_unitcnv)
+  {
+   unit = __des_timeprec - mdp->mtime_units;
+   *aof_realdelay = realdelay*__dbl_toticks_tab[unit];
+  }
+ /* just assign if no module time scale */
+ else *aof_realdelay = realdelay;
+}
+
+/*
+ * convert delay from internal simulation time units to delay of mod units
+ * use the inst to find module that has delay
+ */
+extern void tf_unscale_longdelay(char *cell, int32 delay_lo, int32 delay_hi,
+ int32 *aof_delay_lo, int32 *aof_delay_hi)
+{
+ word64 t1, t2;
+ struct tfinst_t *tfi;
+ struct mod_t *mdp;
+ 
+ tfi = (struct tfinst_t *) cell;
+ mdp = tfi->tfitp->itip->imsym->el.emdp; 
+
+ /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
+ t1 = ((word64) ((word32) delay_lo)) | (((word64) ((word32) delay_hi)) << 32);
+
+ if (!mdp->mno_unitcnv) __cnv_ticks_tonum64(&t2, t1, mdp);
+ else t2 = t1;
+ *aof_delay_hi = (int32) ((t2 >> 32) & WORDMASK_ULL);
+ *aof_delay_lo = (int32) (t2 & WORDMASK_ULL);
+}
+
+/*
+ * convert delay from internal simulation time units to mod delay- real form
+ */
+extern void tf_unscale_realdelay(char *cell, double realdelay,
+ double *aof_realdelay)
+{
+ int32 unit;
+ struct tfinst_t *tfi;
+ struct mod_t *mdp;
+ 
+ tfi = (struct tfinst_t *) cell;
+ mdp = tfi->tfitp->itip->imsym->el.emdp; 
+ if (!mdp->mno_unitcnv)
+  {
+   unit = __des_timeprec - mdp->mtime_units;
+   *aof_realdelay = realdelay /__dbl_toticks_tab[unit];
+  }
+ else *aof_realdelay = realdelay;
+}
+
+/*
+ * convert signed long to real
+ * this is unusual in because converts 64 bit signed value
+ * preserving sign to real
+ * for most routines conversion is from int32 or word32 (32 bits) to real
+ */
+extern void tf_long_to_real(int32 int_lo, int32 int_hi, double *aof_real)
+{
+ long long iv1;
+
+ /* SJM 11/29/99 - now know long long always supported so use it */
+ /* also some problems with sign handling */
+ iv1 = (((long long) int_hi) << 32) + ((long long) int_lo);
+ *aof_real = (double) iv1;
+}
+
+/*
+ * normal real to as much of 64bit as possible conversion
+ */
+extern void tf_real_to_long(double real, int32 *aof_int_lo, int32 *aof_int_hi)
+{
+ long long iv1;
+
+ /* SJM 11/29/99 - must use long long arithmetic old routine wrong low 1 */
+ /* in high word32 and 0 in low word32 (from double) */
+ iv1 = (long long) real + 0.50000; 
+ *aof_int_hi = (int32) (iv1 >> 32);  
+ *aof_int_lo = (int32) (iv1 & 0xffffffff); 
+}
+
+/*
+ * get time unit as scaled exponent 1 sec is 0 of time unit of cur module
+ * get from other instance module
+ * if null, return design wide time unit (smallest) 
+ */
+extern int32 tf_igettimeunit(char *inst)
+{
+ int32 i;
+ struct tfinst_t *tfi;
+ struct mod_t *mdp;
+ 
+ tfi = (struct tfinst_t *) inst;
+ /* special case return smallest time precision (not units) in design */
+ if (tfi == NULL) { i = -((int32) __des_timeprec); return(i); } 
+
+ mdp = tfi->tfitp->itip->imsym->el.emdp; 
+ /* this works because no unit conversion means design time prec (min. */
+ /* but stored as positive inverse of neg. exponent) is same as unit */
+ if (!mdp->mno_unitcnv) i = -((int32) mdp->mtime_units);
+ else i = -((int32) __des_timeprec);
+ return(i);
+}
+
+extern int32 tf_gettimeunit(void)
+{
+ int32 i;
+
+ if (!__inst_mod->mno_unitcnv)
+  i = -((int32) (__inst_mod->mtime_units + __inst_mod->mtime_prec));
+ /* if no time scale both precision and units the same */
+ else i = -((int32) __des_timeprec);
+ return(i);
+}
+
+/*
+ * get the time precision for a module
+ */
+extern int32 tf_igettimeprecision(char *inst)
+{
+ int32 i;
+ struct tfinst_t *tfi;
+ struct mod_t *mdp;
+ 
+ tfi = (struct tfinst_t *) inst;
+ /* special case return design precison (sim. tick) value */
+ /* design time units is minimum of all units in design */
+ if (tfi == NULL) { i = -((int32) __des_timeprec); return(i); } 
+
+ mdp = tfi->tfitp->itip->imsym->el.emdp; 
+ if (!mdp->mno_unitcnv) i = -((int32) (mdp->mtime_units + mdp->mtime_prec));
+ else i = -((int32) __des_timeprec);
+ return(i);
+}
+
+/*
+ * get the time precision for a module
+ */
+extern int32 tf_gettimeprecision(void)
+{
+ int32 i;
+ 
+ if (!__inst_mod->mno_unitcnv)
+  i = -((int32) (__inst_mod->mtime_units + __inst_mod->mtime_prec));
+ else i = -((int32) __des_timeprec);
+ return(i);
+}
+
+/*
+ * return a string giving module name for task call from other inst/place
+ */
+extern char *tf_imipname(char *inst)
+{
+ char *chp;
+ struct tfinst_t *sav_tfip;
+
+ sav_tfip = __tfinst;
+ __tfinst = (struct tfinst_t *) inst;
+ __push_itstk(__tfinst->tfitp);
+ chp = tf_mipname(); 
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ return(chp);
+}
+
+/*
+ * return a string (. separated) that is the path to the call to a user
+ * task or function
+ *
+ * just gets this out of cur_itp - when return if schedule has itp
+ */
+extern char *tf_mipname(void)
+{
+ char *chp;
+ int32 slen;
+ int32 sav_sofs = __cur_sofs;
+
+ __disp_itree_path(__inst_ptr, (struct task_t *) NULL);
+ slen = __cur_sofs - sav_sofs;
+ chp = __mytf_malloc(slen + 1);
+ strcpy(chp, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0'; 
+ return(chp);
+}
+
+extern char *tf_ispname(char *cell)
+{
+ char *chp;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(cell, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ chp = tf_spname();
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(chp);
+}
+
+/*
+ * return a string (. separated) that is the scope to the call to a user
+ * task or function - will contain possible named block or task called from
+ * plus module name prefix
+ * for nested blocks can have multiple components
+ */
+extern char *tf_spname(void)
+{
+ int32 slen;
+ int32 sav_sofs = __cur_sofs;
+ char *chp;
+
+ if (__tfrec == NULL)
+  {
+   bad_notfcontext_err("tf_spname");
+   return(NULL);
+  }
+ __disp_itree_path(__inst_ptr, __tfrec->tf_intskp);
+ slen = __cur_sofs - sav_sofs;
+ chp = __mytf_malloc(slen + 1);
+ strcpy(chp, &(__exprline[sav_sofs]));
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0'; 
+ return(chp);
+}
+
+/*
+ * cause $finish simulation termination (any clean up needed)
+ *
+ * normal convention to check verbose mode but no argument for messages
+ */
+extern int32 tf_dofinish(void)
+{
+ __pli_dofinish(0, "tf_dofinish");
+ return(TF_NULLPARAM);
+}
+
+/*
+ * PLI either tf_ or vpi_ routine to stop simulation ($finish)
+ */
+extern void __pli_dofinish(int32 diag_level, char *caller)
+{
+ int32 rv; 
+
+ /* need to call PLI end of sim routines before finishing */
+ if (__tfrec_hdr != NULL) __call_misctfs_finish();
+ if (__have_vpi_actions) __vpi_endsim_trycall();
+
+ /* if not simulating just exit */
+ if (__run_state != SS_SIM)
+  {
+   __cv_msg(
+    "Halted from call to PLI %s before simulation has begun.\n", caller);   
+   goto endit;
+  }
+
+ if (__verbose)
+  {
+   __cv_msg(
+    "Halted at location %s time %s from call to PLI %s.\n",   
+    __bld_lineloc(__wrks2, (word32) __sfnam_ind, __slin_cnt),
+    __to_timstr(__wrks1, &__simtime), caller);
+   __emit_stsk_endmsg();
+  }
+ /* notice must always print error counts if any */
+endit:
+ if (__pv_err_cnt != 0 || __pv_warn_cnt != 0 || __inform_cnt != 0)
+  __cv_msg("  There were %d error(s), %d warning(s), and %d inform(s).\n",
+   __pv_err_cnt, __pv_warn_cnt, __inform_cnt);
+ /* SJM 04/26/04 - needs to exit with non zero if any errors occurred */
+ if (__pv_err_cnt != 0) rv = 1; else rv = 0;
+ __my_exit(rv, TRUE);
+}
+
+/*
+ * cause $stop return to interactive mode
+ * this is tricky since must run interactive environment under here
+ */
+extern int32 tf_dostop(void)
+{
+ if (__run_state != SS_SIM) return(bad_nosimtf_err("tf_dostop"));
+ if (__no_iact)
+  {
+   __sgfwarn(560,
+    "Call to PLI tf_dostop no effect - interactive environment disabled");
+   return(TF_NULLPARAM);
+  }
+ __pending_enter_iact = TRUE;
+ __iact_reason = IAER_STOP;
+ /* must leave signal on - if ^c hit before stop, same effect */
+ /* but entry reason different and lost */
+ return(TF_NULLPARAM);
+}
+
+/*
+ * INSTANCE AND LOCATION USER STORAGE ROUTINES
+ */
+
+/*
+ * convert current inst - arg list and itree place to alloced rec.
+ * allocates record that user can free with tf_freeinst - added
+ */
+extern char *tf_getinstance(void)
+{
+ struct tfinst_t *tfip;
+
+ /* LOOKATME - this storage is not freeable (inherent memory leak?) */
+ tfip = (struct tfinst_t *) malloc(sizeof(struct tfinst_t));
+ *tfip = *__tfinst;
+ return((char *) tfip);
+}
+
+/* 
+ * get associated work area
+ * since can just use malloc this is pointless (was for IBM 360 mvs?)
+ */
+extern char *tf_igetworkarea(char *inst)
+{
+ char *chp;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ chp = tf_getworkarea();
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(chp);
+}
+
+/* 
+ * get associated work area
+ */
+extern char *tf_getworkarea(void)
+{
+ if (__tfrec == NULL)
+  {
+   bad_notfcontext_err("tf_getworkarea");
+   return(NULL);
+  }
+ return(__tfrec->savwrkarea[__inum]);
+}
+
+/*
+ * store work area for other inst/loc pli task
+ */
+extern int32 tf_isetworkarea(char *workarea, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_setworkarea(workarea);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * store (associate) routine with pli task
+ * just a pointer assignment
+ */
+extern int32 tf_setworkarea(char *workarea)
+{
+ if (__tfrec == NULL) return(bad_notfcontext_err("tf_setworkarea"));
+ __tfrec->savwrkarea[__inum] = workarea;
+ return(1);
+}
+
+/*
+ * 64 BIT ARITHMETIC ROUTINES
+ */
+
+/*
+ * add long's which even though passed as int32 are really unsigned
+ * LOOKATME - is this supposed to be long but signed add
+ * if really word32 should change veriuser.h template 
+ */
+extern void tf_add_long(int32 *aof_lowtime1, int32 *aof_hightime1, int32 lowtime2,
+ int32 hightime2)
+{
+ register int32 lowsum;
+
+ lowsum = *aof_lowtime1 + lowtime2;
+ *aof_hightime1 = *aof_hightime1 + hightime2
+  + ((word32) lowsum < (word32) *aof_lowtime1);
+ *aof_lowtime1 = lowsum;
+}
+
+/*
+ * 2's complement signed long subtract
+ * built in 32 bit size for int32 and any borrow is lost
+ * fails on machine that does not use 2's complement for signed ints
+ * also assumes conversion from word32 to int32 can make a negative int
+ * per normal c conventions
+ */
+extern void tf_subtract_long(int32 *aof_lowtime1, int32 *aof_hightime1,
+ int32 lowtime2, int32 hightime2)
+{
+ register int32 lowdif;
+
+ lowdif = *aof_lowtime1 - lowtime2;
+ /* tmp greater than subtracted from means wrap around and need borrow */
+ /* word32 borrow test since need to include high bit */
+ *aof_hightime1 = *aof_hightime1 - hightime2
+  - (int32) (((word32) lowdif > (word32) *aof_lowtime1));
+ *aof_lowtime1 = lowdif;
+}
+
+/*
+ * compare 2 long ints passed in 4 halves
+ * return -1 <, 0 =, +1 >
+ * requires 2 complement representation according to normal c convention
+ */
+extern int tf_compare_long(unsigned int low1, unsigned int high1,
+ unsigned int low2, unsigned int high2)
+{
+ if (high1 == high2) 
+  {
+   if (low1 == low2) return(0); 
+   if (low1 > low2) return(1); 
+   return(-1);
+  }
+ if (high1 < high2) return(-1);
+ return(1);
+}
+
+/*
+ * 2's complement long multiply of 2 64 bit values
+ * this is built in 64 bits because int32 must be 32 bits for portability
+ * this removes and puts back sign
+ */
+extern void tf_multiply_long(int32 *aof_low1, int32 *aof_high1, int32 low2,
+ int32 high2)
+{
+ word32 r[2], u[2], v[2];
+ register int32 ir0, ir1;
+ int32 minus;
+
+ if (*aof_high1 < 0)
+  {
+   minus = TRUE;
+   u[0] = (word32) -(*aof_low1);
+   u[1] = (word32) (-(*aof_high1) - (u[0] != 0)); 
+  }
+ else
+  {
+   minus = FALSE;
+   u[0] = (word32) *aof_low1;
+   u[1] = (word32) *aof_high1;
+  }
+ if (high2 < 0)
+  {
+   minus = !minus;
+   v[0] = (word32) -low2;
+   v[1] = (word32) (-high2 - (v[0] != 0));
+  }
+ else { v[0] = (word32) low2; v[1] = (word32) high2; }
+
+ __lmult((word32 *) r, (word32 *) u, (word32 *) v,  64);
+ if (minus)
+  {
+   ir0 = (int32) r[0];
+   ir1 = (int32) r[1];
+   *aof_low1 = -ir0;
+   *aof_high1 = -ir1 - (*aof_low1 != 0);
+  }
+ else { *aof_low1 = (int32) r[0]; *aof_high1 = (int32) r[1]; }
+}
+
+/*
+ * long divide of word32 times - assuming word32 div not mod
+ * LOOKATME - treating as word32 why are arguments ints? and no way to
+ * indicate divide by 0
+ */
+extern void tf_divide_long(int32 *aof_low1, int32 *aof_high1, int32 low2, int32 high2)
+{
+ word32 res[02], u[2], v[2], dum[2];
+ register int32 ir0, ir1;
+ int32 minus;
+
+ /* divide by 0 must be 0 since no error mechanism */
+ if (low2 == 0L && high2 == 0L) { *aof_low1 = *aof_high1 = 0L; return; } 
+
+ if (*aof_high1 < 0)
+  {
+   minus = TRUE;
+   u[0] = (word32) -(*aof_low1);
+   u[1] = (word32) (-(*aof_high1) - (u[0] != 0)); 
+  }
+ else
+  {
+   minus = FALSE;
+   u[0] = (word32) *aof_low1;
+   u[1] = (word32) *aof_high1;
+  }
+ if (high2 < 0)
+  {
+   minus = !minus;
+   v[0] = (word32) -low2;
+   v[1] = (word32) (-high2 - (v[0] != 0));
+  }
+ else { v[0] = (word32) low2; v[1] = (word32) high2; }
+ __ldivmod2(res, dum, u, v, 64);
+ if (minus)
+  {
+   ir0 = (int32) res[0];
+   ir1 = (int32) res[1];
+   *aof_low1 = -ir0;
+   *aof_high1 = -ir1 - (*aof_low1 != 0);
+  }
+ else { *aof_low1 = (int32) res[0]; *aof_high1 = (int32) res[1]; }
+}
+
+/*
+ * I/O ROUTINES
+ */
+
+/*
+ * emit error using cver mechanism
+ */
+extern int32 tf_error(char *fmt, ...)
+{
+ va_list va, va2;
+
+ va_start(va, fmt);
+ va_start(va2, fmt);
+ vprt_tferr_msg(fmt, va, va2);
+ va_end(va);
+ va_end(va2);
+ return(1);
+}
+
+/*
+ * actually print an error message tf form - also used by tf message
+ */
+static void vprt_tferr_msg(char *fmt, va_list va, va_list va2)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ __pv_err_cnt++;
+ if (!__no_errs)
+  {
+   if (__run_state == SS_SIM)
+    sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+   else strcpy(s1, "");
+
+   __my_fprintf(stdout, "**%s(%d) USER PLI ERROR**%s [1290] ",
+    __in_fils[__sfnam_ind], __slin_cnt, s1);
+   __my_vfprintf(stdout, fmt, va, va2);
+   my_putc_('\n', stdout);
+  }
+ /* no maximum error count for these */
+}
+
+extern int32 tf_warning(char *fmt, ...)
+{
+ va_list va, va2;
+
+ va_start(va, fmt);
+ va_start(va2, fmt);
+ vprt_tfwarn_msg(fmt, va, va2);
+ va_end(va);
+ va_end(va2);
+ return(1);
+}
+
+/*
+ * actually print a warning message tf form - also used by tf message
+ */
+static void vprt_tfwarn_msg(char *fmt, va_list va, va_list va2)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ __pv_warn_cnt++;
+ /* warning number 600 is for all pli tasks so all can be suppressed */
+ if (__no_warns || __em_suppr(600)) return;
+
+ if (__run_state == SS_SIM)
+  sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+ else strcpy(s1, "");
+
+ __my_fprintf(stdout, "**%s(%d) PLI WARN**%s [600] ", __in_fils[__sfnam_ind],
+  __slin_cnt, s1);
+ __my_vfprintf(stdout, fmt, va, va2);
+ my_putc_('\n', stdout);
+}
+
+/*
+ * unimplemented sprintf like routine  
+ */
+extern int32 tf_text(char *fmt, ...)
+{
+ /* ---
+ va_list va;
+
+ va_start(va, fmt);
+ va_end(va);
+ --- */
+ __sgferr(1287, "tf_text not implemented - use sprintf and tf_message");
+ return(TF_NULLPARAM);
+}
+
+/*
+ * print a message using Cver style error message format
+ * facility and messno ignored
+ */
+extern int32 tf_message(int32 level, char *facility, char *messno,
+ char *message, ...)
+{
+ va_list va, va2;
+ char s1[RECLEN], s2[RECLEN];
+
+ va_start(va, message);
+ va_start(va2, message);
+
+ switch (level) {
+  case ERR_INTERNAL:
+   if (__run_state == SS_SIM)
+    sprintf(s1, " now %s", __to_timstr(s2, &__simtime)); 
+   else strcpy(s1, "");
+   __my_fprintf(stdout, "**%s(%d) PLI INTERNAL FATAL**%s [300] ",
+    __in_fils[__sfnam_ind], __slin_cnt, s1);
+   __my_vfprintf(stdout, message, va, va2);
+   my_putc_('\n', stdout);
+   va_end(va);
+   va_end(va2);
+   __my_exit(2, TRUE);
+   break;
+  case ERR_ERROR: case ERR_SYSTEM:
+   vprt_tferr_msg(message, va, va2);
+   break;
+  case ERR_MESSAGE:
+   if (!__no_informs && !__em_suppr(400))
+    { 
+     __my_fprintf(stdout, "--%s(%d) PLI MESSAGE** [400] ",
+      __in_fils[__sfnam_ind], __slin_cnt);
+     __my_vfprintf(stdout, message, va, va2);
+     my_putc_('\n', stdout);
+    }
+   break;
+  case ERR_WARNING:
+   vprt_tfwarn_msg(message, va, va2);
+   break;
+ }
+ va_end(va);
+ va_end(va2);
+ return(1);
+}
+
+/*
+ * printf to multi-channel descriptor
+ */
+extern void io_mcdprintf(int32 mcd, char *format, ...)
+{
+ register int32 i;
+ va_list va, va2;
+
+ /* SJM 09/09/03 - fd case easy because only one stream to write to */
+ if ((mcd & FIO_MSB) == FIO_MSB)
+  {
+   int32 fd;
+
+   fd = (int32) (mcd & ~FIO_MSB);
+   /* if fd does not correspond to open file, just set error indicator */
+   if (__fio_fdtab[fd] == NULL)
+    {
+     __sgfwarn(651,
+      "in tf_ pli file not open for descriptor number %d ", fd);
+     errno = EBADF;
+     return;
+    }
+   /* SJM 10/13/99 - ansii std says varargs not usable after vprintf */
+   va_start(va, format);
+   vfprintf(__fio_fdtab[fd]->fd_s, format, va);
+   va_end(va);
+   return;
+  }
+
+ /* SJM 03/26/00 - mcd 1 now both stdout and log if open */
+ if ((mcd & 1) != 0)
+  {
+   va_start(va, format);
+   va_start(va2, format);
+
+   vprintf(format, va);
+   if (__log_s != NULL) vfprintf(__log_s, format, va2);
+
+   va_end(va);
+   va_end(va2);
+  }
+
+ /* mcd's may require writing to lots of files */
+ for (i = 1; i < 31; i++) 
+  {
+   if (((mcd >> i) & 1L) != 0L)
+    { 
+     if (__mulchan_tab[i].mc_s == NULL)
+      {
+       __sgfwarn(651,
+        "in tf_ pli multi-channel descriptor bit %d on, but file not open",
+        i);
+      }
+     else
+      {
+       /* SJM 10/13/99 - ansii std says varargs not usable after vprintf */
+       va_start(va, format);
+       vfprintf(__mulchan_tab[i].mc_s, format, va);
+       va_end(va);
+      }
+    }
+  }
+ if (((mcd >> 31) & 1) != 0)
+  {
+   __sgfwarn(651,
+    "in tf_ pli multi-channel descriptor bit 31 on but file not open - unusable because reserved for new Verilog 2001 file I/O");
+  }
+}
+
+/*
+ * formatted print to both standard output and log file (if open) 
+ */
+extern void io_printf(char *format, ...)
+{
+ va_list va, va2;
+
+ va_start(va, format);
+ va_start(va2, format);
+ vprintf(format, va);
+ if (__log_s != NULL) vfprintf(__log_s, format, va2);
+ va_end(va);
+ va_end(va2);
+}
+
+/*
+ * scan plus args (for now scan args and if no + do not try to match)
+ * plusarg does not have leading +
+ * DOCUMENTME - returned string is read only
+ */
+extern char *mc_scan_plusargs(char *plusarg)
+{
+ register struct optlst_t *olp;
+ register char *chp;
+ int32 arglen, optlen;
+
+ arglen = strlen(plusarg);
+ /* all options expanded and saved so this is easy */
+ for (olp = __opt_hdr; olp != NULL; olp = olp->optlnxt)
+  {
+   /* ignore markers added for building vpi argc/argv */
+   if (olp->is_bmark || olp->is_emark) continue;
+
+   chp = olp->opt;
+   if (*chp != '+') continue;
+   /* if plus arg longer than option cannot match */ 
+   if ((optlen = strlen(&(chp[1]))) < arglen) continue; 
+   /* match prefix */
+   if (strncmp(&(chp[1]), plusarg, arglen) != 0) continue; 
+   /* return pointer to 1st char after matched prefix */
+   /* may be empty string */
+   return(&(chp[arglen + 1]));
+  }
+ /* if no match return nil ptr not empty string */
+ return(NULL);
+}
+
+/*
+ * OLD ROUTINES NO LONGER IN STANDARD?
+ */
+
+/*
+ * free instance - added routine if needed
+ * rarely needed 
+ */
+/* ---
+extern char tf_freeinstance(char *inst)
+{
+ free(inst);
+}
+--- */
+
+/*
+ * ROUTINES NOT INCLUDED IN PRELIMARY IEEE VERIUSER.H
+ */
+
+/*
+ * think this is no longer needed since assigning causes propagate
+ */
+extern int32 tf_ievaluatep(int32 pnum, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_evaluatep(pnum);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * evaluate an expression for its value and set in tf_texprinfo node
+ * notice this is for exprinfo not nodeinfo
+ *
+ * this uses a previously (last) set tf_texprinfo for this inst.
+ * return 0 if no previous expr or error else 1
+ * places new value into exprinfo structure
+ *
+ * for memories must be cell select since tf_ func/task argument must be
+ * legal ver expr.
+ * notice this is fast because only changes value exprinfo fields 
+ */
+extern int32 tf_evaluatep(int32 pnum)
+{
+ register int32 wi;
+ register struct t_tfexprinfo *pinfo;
+ register struct xstk_t *xsp;
+ int32 wlen, rv;
+ double d1;
+ struct tfarg_t *tfap;
+ struct expr_t *xp;
+
+ if (__tfrec == NULL)
+  {
+   rv = bad_notfcontext_err("tf_evaluatep");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ tfap = &(__tfrec->tfargs[pnum]);
+ pinfo = (struct t_tfexprinfo *) tfap->sav_xinfos[__inum];
+ if (pinfo == NULL) return(1);
+ xp = tfap->arg.axp;
+
+ /* here this always handles any gref itree pushing and popping */
+ xsp = __eval_xpr(xp);
+ if (xp->is_real)
+  {
+   memcpy(&d1, xsp->ap, sizeof(double));
+   pinfo->real_value = d1;
+  }
+ else
+  {
+   wlen = wlen_(xp->szu.xclen);
+   for (wi = 0; wi < wlen; wi++)
+    { 
+     pinfo->expr_value_p[wi].avalbits = (int32) xsp->ap[wi];
+     pinfo->expr_value_p[wi].bvalbits = (int32) xsp->bp[wi];
+    }  
+  }
+ __pop_xstk();
+ return(0);
+} 
+
+/*
+ * progogate a changed rhs value to all lhs?
+ * what does this do and how is expr. stored ?
+ */
+extern int32 tf_ipropagatep(int32 pnum, char *inst)
+{
+ int32 rv;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ __push_itstk(__tfinst->tfitp);
+ rv = tf_propagatep(pnum);
+ __pop_itstk();
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(rv);
+}
+
+/*
+ * propagate the value user placed in node info structure
+ * previous call of tf nodeinfo set current node info struct 
+ * 
+ * this does not work for strengths because node info fails
+ *
+ * SJM 11/30/99 - changed to follow new LRM and use exprinfo for
+ * save (from tf_exprinfo) instead of node info (from tf_nodeinfo)
+ */
+extern int32 tf_propagatep(int32 pnum)
+{
+ register int32 wi;
+ register struct xstk_t *xsp;
+ register struct t_vecval *vecp; 
+ register struct t_tfexprinfo *xpinfo;
+ int32 rv;
+ double d1;
+ struct tfarg_t *tfap;
+ struct expr_t *lhsxp;
+
+ if (__tfrec == NULL)
+  {
+   rv = bad_notfcontext_err("tf_propagatep");
+   /* SJM 12/17/02 - error is 1 and success is 0 */
+   if (rv == TF_NULLPARAM) return(1); else return(0);
+  }
+ tfap = &(__tfrec->tfargs[pnum]);
+ if (pnum < 1 || pnum >= __tfrec->tfanump1) return(1);
+
+ /* need previously stored from call to expr info */
+ xpinfo = (struct t_tfexprinfo *) tfap->sav_xinfos[__inum];
+ if (xpinfo == NULL) return(1);
+
+ if (xpinfo->expr_type == TF_READONLY
+  || xpinfo->expr_type == TF_READONLYREAL
+  || xpinfo->expr_type == TF_STRING
+  || xpinfo->expr_type == TF_NULLPARAM)  
+  {  
+   __sgferr(1280,
+    "tf_propagatep saved expression illegal - expressions not writeable");
+   return(1);
+  }
+ lhsxp = tfap->arg.axp;
+ if (lhsxp->x_stren)
+  {  
+   __sgferr(1212,
+    "tf_propagatep of strength expression illegal - tf_ does not store strength");
+   return(1);
+  }
+
+ /* know user filled field of pinfo before calling this */
+ /* copy value to internal a/b form for assignment */
+ if (xpinfo->expr_type == TF_READWRITEREAL)
+  {
+   d1 = xpinfo->real_value;
+   push_xstk_(xsp, REALBITS);
+   memcpy(xsp->ap, &d1, sizeof(double));
+  }
+ else
+  {
+   /* here just convert from vecval p form to internal a/b form */
+   push_xstk_(xsp, 2*xpinfo->expr_ngroups*WRDBYTES);
+   vecp = xpinfo->expr_value_p;
+   for (wi = 0; wi < xpinfo->expr_ngroups; wi++)
+    {
+     xsp->ap[wi] = (word32) vecp[wi].avalbits;
+     xsp->bp[wi] = (word32) vecp[wi].bvalbits;
+    }
+  } 
+ exec_tfarg_assign(tfap, lhsxp, xsp->ap, xsp->bp);
+ __pop_xstk();
+ return(0);
+}
+
+/*
+ * need $restart mechanism for this 
+ */
+extern int32 tf_read_restart(char *blockptr, int32 blocklen)
+{
+ /* UNIMPLMENTED */
+ __sgferr(1287, 
+  "tf_read_restart not implemented - $save/$restart not yet implemented"); 
+ return(0);
+}
+
+extern int32 tf_write_save(char *blockptr, int32 blocklen)
+{
+ /* UNIMPLMENTED */
+ __sgferr(1287, 
+  "tf_write_save not implemented - $save/$restart not yet implemented"); 
+ return(0);
+}
+
+/*
+ * other pli function/task call version of sleep ? 
+ */
+/* ---
+extern int32 tf_isleep(int32 delay, char *inst)
+{
+ int32 rv;
+}
+-- */
+
+/*
+ * scale to internal time unit and then block for that time
+ * think this is like setdelay - or maybe has no argument and just 
+ * terminates ? - why not just set delay and return?
+ */
+/* -- 
+extern int32 tf_sleep(int32 delay)
+{
+ return(0);
+}
+-- */
+
+/*
+ * NEW ROUTINES ADDED FOR PVER
+ */
+
+/*
+ * routine to determine source location of tf_ instance
+ */
+extern char *tf_igetsourceloc(int32 *lineno, char *inst)
+{
+ char *chp;
+ struct tfinst_t *sav_tfip;
+ struct tfrec_t *sav_tfrp;
+
+ set_tfinst_(inst, sav_tfip, sav_tfrp);
+ chp = tf_getsourceloc(lineno);
+ __tfinst = sav_tfip;
+ __tfrec = sav_tfrp;
+ return(chp);
+}
+
+
+extern char *tf_getsourceloc(int32 *lineno)
+{
+ int32 slen;
+ char *chp, *chp2;
+
+ if (__tfrec == NULL)
+  {
+   bad_notfcontext_err("tf_getsourceloc");
+   return(NULL);
+  }
+ chp2 = __in_fils[__tfrec->tffnam_ind];
+ slen = strlen(chp2);
+ chp = __my_malloc(slen + 1); 
+ strcpy(chp, chp2);
+ *lineno = __tfrec->tflin_cnt;
+ return(chp);
+}
+
+/*
+ * ROUTINES FOR MISCTF PARAMETER CHANGE PROCESSING
+ */
+
+/*
+ * call the misctf routine after parameter changed
+ *
+ * know dce will not be linked on unless async is on for this inst/call 
+ * know right itree location
+ *
+ * notice since this dce does not fit into normal scheme dce 1inst T if
+ * func or F if task, dce2 union is ptr to task call statement or fcall expr
+ * and unused dce_downitp is cast to int32 for pnum (set when built)
+ */
+extern void __pvc_call_misctf(struct dcevnt_t *dcep)
+{
+ int32 pnum, sav_fnam_ind, sav_slin_cnt;
+ struct st_t *stp;
+ struct expr_t *fcallx; 
+ struct t_tfcell *tfcp;
+ struct tskcall_t *tkcp;
+ struct systsk_t *stbp;
+ struct sysfunc_t *sfbp;
+ struct tfinst_t tfiwrk;
+ int32 (*misctf)();
+
+ stp = NULL;
+ fcallx = NULL;
+ /* T dce iscol for pvc means dce2 union is ptr to fcallx else to stp */
+ if (dcep->dce_tfunc)
+  {
+   fcallx = dcep->dceu2.dce_pvc_fcallx; 
+   sfbp = fcallx->lu.x->lu.sy->el.esyftbp;
+   tfcp = &(__shadow_veriusertfs[sfbp->syfnum - BASE_VERIUSERTFS]); 
+   __tfrec = fcallx->lu.x->szu.xfrec;
+  }
+ else
+  {
+   stp = dcep->dceu2.dce_pvc_stp;
+   tkcp = &(stp->st.stkc);
+   stbp = tkcp->tsksyx->lu.sy->el.esytbp;
+   tfcp = &(__shadow_veriusertfs[stbp->stsknum - BASE_VERIUSERTFS]); 
+   __tfrec = tkcp->tkcaux.trec;
+  }
+
+ pnum = dcep->dceu.pnum;
+ /* step 1: update pvc change flags */  
+ /* pvc code never turns change flags off user must call movepvc routine */
+ __tfrec->tfargs[pnum].old_pvc_flgs[__inum] = 1;
+
+ /* if no misc tf routine - done */
+ /* SJM 06/13/1999 - misctf always requires 3rd argument although ignored */
+ /* except for synchon callbacks ?? */
+ if ((misctf = tfcp->misctf) == NULL) return;
+
+ sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
+ __vpifnam_ind = __sfnam_ind; 
+ __vpilin_cnt = __slin_cnt;
+
+ /* set up environment that is current implied tf instance */
+ /* notice assignment of addr. to static works since niled in this rout. */
+ __tfinst = &tfiwrk;
+ __tfinst->callx = NULL;
+ __tfinst->tfstp = NULL;
+ __tfinst->tfitp = __inst_ptr; 
+ if (dcep->dce_tfunc) __tfinst->callx = fcallx; else __tfinst->tfstp = stp;
+
+ /* FIXME ??? - not 64 bit clean */
+ (*misctf)((int32) tfcp->data, REASON_PARAMVC, pnum);
+ __tfinst = NULL;
+ __tfrec = NULL;
+ __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+}
+
+/*
+ * build and link on special pvc tf_ parameter change dce for one param
+ * xp is param expr (can be rhs) - know __tfrec and instance loc. set
+ */
+static void bld_pvc_dces(struct expr_t *xp, int32 pnum)
+{
+ struct net_t *np;
+ int32 biti, bitj;
+ word32 *wp;
+ struct expr_t *idndp, *ndx;
+ struct expr_t *fax;
+ 
+ switch ((byte) xp->optyp) {
+  case GLBREF:
+   idndp = xp; 
+   biti = bitj = -1;
+glb_dce:
+   np = idndp->lu.sy->el.enp;
+   linkon_pvc_dce(np, biti, bitj, idndp->ru.grp, pnum);
+   break;
+  case ID:
+   idndp = xp; 
+   np = xp->lu.sy->el.enp;
+   linkon_pvc_dce(np, -1, -1, (struct gref_t *) NULL, pnum);
+   break;
+  /* SJM 05/18/00 - must do nothing for reals */ 
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   return;
+  case LSB:
+   idndp = xp->lu.x; 
+   np = idndp->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   /* for monits, any reg or non scalaraed wire must trigger on any chg */
+   if (ndx->optyp == NUMBER)
+    {
+     wp = &(__contab[ndx->ru.xvi]);
+     if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
+    }
+   else if (ndx->optyp == ISNUMBER)
+    {
+     wp = &(__contab[ndx->ru.xvi]);
+     wp = &(wp[2*__inum]);
+
+     /* need length for IS number because can be wider - but get low */
+     if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
+    }
+   else
+    {
+     /* notice for monitor and dctrl event change, variable here is legal */
+     /* and implies change for index and trigger on all bits of variable */
+     bld_pvc_dces(ndx, pnum);
+     biti = -1;
+    }
+   bitj = biti;
+   if (biti != -1 && !np->vec_scalared) biti = bitj = -1;
+   if (idndp->optyp == GLBREF) goto glb_dce;
+   linkon_pvc_dce(np, biti, biti, (struct gref_t *) NULL, pnum);
+   break;
+  case PARTSEL:
+   idndp = xp->lu.x; 
+   np = idndp->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   /* know part select never IS */
+   biti = (int32) __contab[ndx->lu.x->ru.xvi];
+   bitj = (int32) __contab[ndx->ru.x->ru.xvi];
+   if (!np->vec_scalared) biti = bitj = -1;
+   if (idndp->optyp == GLBREF) goto glb_dce;
+   linkon_pvc_dce(np, biti, bitj, (struct gref_t *) NULL, pnum);
+   break;
+  case FCALL:
+   /* if any arguments of system or user functions change, monitor triggers */
+   /* notice $time function do not have arguments */
+   for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+    bld_pvc_dces(fax->lu.x, pnum);
+   break;
+  case LCB:
+   for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+    bld_pvc_dces(fax->lu.x, pnum);
+   break;
+  default:
+   if (xp->lu.x != NULL) bld_pvc_dces(xp->lu.x, pnum);
+   if (xp->ru.x != NULL) bld_pvc_dces(xp->ru.x, pnum);
+   break;
+ } 
+}
+
+/*
+ * link on a special (one per inst) pvc dce
+ *
+ * know one of callx and stp set but not both
+ * -2 IS form impossible since any one inst. IS form converted to constant
+ * before here
+ * need old value for ranges since need exact change processing
+ * not sure if ref. itp needed here but stored
+ */
+static void linkon_pvc_dce(struct net_t *np, int32 biti, int32 bitj,
+ struct gref_t *grp, int32 pnum)
+{
+ register struct dcevnt_t *dcep;
+ int32 nd_itpop;
+ struct itree_t *ref_itp;
+ struct dceauxlst_t *dclp;
+
+ ref_itp = __inst_ptr;
+ nd_itpop = FALSE;
+ if (grp != NULL) { __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ /* allocate, init, and fill the fields */
+ dcep = __alloc_dcevnt(np);
+   
+ if (biti == -1) dcep->dce_typ = DCE_PVC;
+ else
+  {
+   dcep->dce_typ = DCE_RNG_PVC;
+   dcep->dci1 = biti;
+   dcep->dci2.i = bitj;
+  }
+ /* link this on front */
+ dcep->dcenxt = np->dcelst;
+
+ np->dcelst = dcep;
+ dcep->dce_1inst = TRUE;
+ /* this is itree dcep put on */
+ dcep->dce_matchitp = __inst_ptr;
+ /* this is placed referenced, unless xmr same as match */
+ dcep->dce_refitp = ref_itp;
+
+ /* also set unused fmon field to pvc object and other pvc fields */
+ if (__tfrec->tf_func)
+  {
+   dcep->dce_tfunc = TRUE;
+   /* unused fmon field used for callx */
+   dcep->dceu2.dce_pvc_fcallx = __tfrec->tfu.callx;
+  }
+ else
+  {
+   dcep->dce_tfunc = FALSE;  
+   /* unused fmon field used for stp */
+   dcep->dceu2.dce_pvc_stp = __tfrec->tfu.tfstp;
+  } 
+ /* unused down itp used for tf_ param number (tf_ func ret val not incl) */
+ dcep->dceu.pnum = pnum;
+ /* __inst_ptr is right place */
+ __alloc_1instdce_prevval(dcep);
+ __init_1instdce_prevval(dcep);
+
+ /* then link on undo/chg list */
+ dclp = (struct dceauxlst_t *) __my_malloc(sizeof(struct dceauxlst_t));
+ dclp->ldcep = dcep; 
+ dclp->dclnxt = __pvc_dcehdr;
+ __pvc_dcehdr = dclp;
+
+ /* since no dce, no loads, and no dmpvars must always turn chg store on */
+ if (!dcep->dce_np->nchg_nd_chgstore)
+  {
+   /* this also regen net's decl iops from dce if -O on */
+   __dce_turn_chg_store_on(__inst_mod, dcep, TRUE);  
+  }
+ /* SJM 02/06/03 - may have npps but not dces so must turn this on */
+ /* since nchg nd chgstore on, know nchg action right */
+ if (np->ntyp >= NONWIRE_ST) np->nchg_has_dces = TRUE;
+
+ if (nd_itpop) __pop_itstk();
+}
+
+/* 
+ * ROUTINES FOR MISCTF ROSYNCHRONIZE PROCESSING
+ */
+
+/*
+ * end of slot call misctf with reason ro sync
+ */
+extern void __exec_rosync_misctf(void)
+{
+ register i_tev_ndx tevpi;
+
+ __rosync_slot = TRUE; 
+ for (tevpi = __tehdr_rosynci; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+  rosync_call_misctf(tevpi);
+ /* slot end action turned off all at once later */
+ /* add the list on to head of tev free list */ 
+ __tevtab[__teend_rosynci].tenxti = __tefreelsti;
+ __tefreelsti = __tehdr_rosynci;
+ __tehdr_rosynci = __teend_rosynci = -1;
+ __rosync_slot = FALSE; 
+}
+
+/*
+ * call the misctf routine for reason ro synchronize
+ */
+static void rosync_call_misctf(i_tev_ndx tevpi)
+{
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct t_tfcell *tfcp;
+ struct tfinst_t tfiwrk;
+ int32 (*misctf)();
+
+ __tfrec = __tevtab[tevpi].tu.tetfrec;
+ tfcp = get_tfcell(__tfrec);
+
+ /* if no misc. tf routine just turn off, nothing to do */
+ if ((misctf = tfcp->misctf) == NULL)
+  {
+   __tfrec->rosync_tevp[__tevtab[tevpi].teitp->itinum] = -1;
+   return;
+  }
+
+ sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
+
+ __push_itstk(__tevtab[tevpi].teitp);
+ /* set up environment that is current implied tf instance */
+ /* notice assignment of addr. to static works since niled in this rout. */
+ __tfinst = &tfiwrk;
+ __tfinst->callx = NULL;
+ __tfinst->tfstp = NULL;
+ __tfinst->tfitp = __inst_ptr; 
+ if (__tfrec->tf_func) __tfinst->callx = __tfrec->tfu.callx;
+ else __tfinst->tfstp = __tfrec->tfu.tfstp;
+
+ /* SJM 06/13/1999 - misctf always requires 3rd argument although ignored except for syncon callbacks ?? */
+ /* FIXME ??? - not 64 bit clean */
+ (*misctf)((int32) tfcp->data, REASON_ROSYNCH, 0);
+
+ __tfrec->rosync_tevp[__inum] = -1;
+ __pop_itstk();
+ __tfrec = NULL;
+ __tfinst = NULL;
+ __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
+}
+
+/*
+ * call the misctf routine for reason synchronize
+ *
+ * this is called once to process every scheduled #0 sync event
+ * there will be at most one event per call/inst but turned off
+ * so can be called next cycle of #0 loop
+ * no way these can be canceled except removed on reset
+ */
+extern void __sync_call_misctf(struct tev_t *tevp)
+{
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct t_tfcell *tfcp;
+ struct tfinst_t tfiwrk;
+ int32 (*misctf)();
+
+ __tfrec = tevp->tu.tetfrec;
+ tfcp = get_tfcell(__tfrec);
+ /* if no misc. tf routine just turn off, nothing to do */
+ if ((misctf = tfcp->misctf) == NULL)
+  {
+   __tfrec->sync_tevp[tevp->teitp->itinum] = -1;
+   return;
+  }
+
+ sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
+
+ __push_itstk(tevp->teitp);
+ /* set up environment that is current implied tf instance */
+ /* notice assignment of addr. to static works since niled in this rout. */
+ __tfinst = &tfiwrk;
+ __tfinst->callx = NULL;
+ __tfinst->tfstp = NULL;
+ __tfinst->tfitp = __inst_ptr; 
+ if (__tfrec->tf_func) __tfinst->callx = __tfrec->tfu.callx;
+ else __tfinst->tfstp = __tfrec->tfu.tfstp;
+
+ /* SJM 06/13/1999 - misctf always requires 3rd argument although ignored except for syncon callbacks ?? */
+ /* FIXME ??? - not 64 bit clean */
+ (*misctf)((int32) tfcp->data, REASON_SYNCH, 0);
+
+ __tfrec->sync_tevp[__inum] = -1;
+ __pop_itstk();
+ __tfrec = NULL;
+ __tfinst = NULL;
+ __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
+}
+
+/*
+ * call the misctf routine for reason reactivate afer delay
+ *
+ * 0 is pound 0 
+ */
+extern void __setdel_call_misctf(i_tev_ndx tevpi)
+{
+ register struct tevlst_t *telp, *last_telp;
+ int32 sav_fnam_ind, sav_slin_cnt;
+ struct t_tfcell *tfcp;
+ struct tfinst_t tfiwrk;
+ int32 (*misctf)();
+
+ __tfrec = __tevtab[tevpi].tu.tetfrec;
+ tfcp = get_tfcell(__tfrec);
+
+ /* if no misc. tf routine just turn off, nothing to do */
+ if ((misctf = tfcp->misctf) == NULL) goto free_telst;
+
+ sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt; 
+ __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
+
+ __push_itstk(__tevtab[tevpi].teitp);
+ /* set up environment that is current implied tf instance */
+ /* notice assignment of addr. to static works since niled in this rout. */
+ __tfinst = &tfiwrk;
+ __tfinst->callx = NULL;
+ __tfinst->tfstp = NULL;
+ __tfinst->tfitp = __inst_ptr; 
+ if (__tfrec->tf_func) __tfinst->callx = __tfrec->tfu.callx;
+ else __tfinst->tfstp = __tfrec->tfu.tfstp;
+
+ /* SJM 06/13/1999 - misctf always requires 3rd argument although ignored except for syncon callbacks ?? */
+ /* FIXME ??? - not 64 bit clean */
+ (*misctf)((int32) tfcp->data, REASON_REACTIVATE, 0);
+
+ __pop_itstk();
+ __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
+ __tfinst = NULL;
+
+free_telst:
+ last_telp = NULL;
+ telp = __tfrec->setd_telst[__tevtab[tevpi].teitp->itinum];
+ for (; telp != NULL; telp = telp->telnxt)
+  {
+   /* but tevpi can not change */
+   if (tevpi == telp->tevpi)
+    {
+     if (last_telp == NULL)
+      __tfrec->setd_telst[__tevtab[tevpi].teitp->itinum] = telp->telnxt;
+     else last_telp->telnxt = telp->telnxt;
+     /* link 1 freed on front */
+     telp->telnxt = __ltevfreelst;
+     __ltevfreelst = telp;
+     __tfrec = NULL;
+     return;
+    }
+   last_telp = telp;
+  }
+ __case_terr(__FILE__, __LINE__); 
+}
+
+/*
+ * process a tf strdelputp store
+ *
+ * know parameter is read write
+ * know value converted and available here 
+ * know tf isrw never concat and may be either wire or reg 
+ */
+extern void __process_putpdel_ev(i_tev_ndx tevpi)
+{
+ register struct expr_t *lhsxp; 
+ register struct tfarg_t *tfap;
+ register int32 lhslen;
+ int32 wlen;
+ word32 *ap, *bp;
+ byte *sbp;
+ struct tfrec_t *tfrp;
+ struct tedputp_t *tedp; 
+ struct dltevlst_t *dlp;
+
+ tedp = __tevtab[tevpi].tu.tedputp;
+ __tevtab[tevpi].tu.tedputp = NULL;
+
+ tfrp = tedp->tedtfrp;
+ tfap = &(tfrp->tfargs[tedp->tedpnum]);
+
+ lhsxp = tfap->arg.axp;
+ lhslen = lhsxp->szu.xclen;
+ wlen = wlen_(lhslen);
+ if (__ev_tracing) emit_tputd_trmsg(tedp, tfap);
+ ap = tedp->tedwp;
+ bp = &(ap[wlen]);
+ exec_tfarg_assign(tfap, lhsxp, ap, bp);
+ /* free the event tf delputp record stored rhs assign to value */
+ if (lhsxp->x_stren)
+  { sbp = (byte *) tedp->tedwp; __my_free((char *) sbp, lhslen); }
+ else __my_free((char *) tedp->tedwp, 2*wlen_(lhslen)*WRDBYTES);
+
+ tedp->tedtfrp =  (struct tfrec_t *) __tedpfreelst;
+ __tedpfreelst = tedp;
+ dlp = tfap->dputp_tedlst[__inum];
+ /* also link out tevlst element - must be on front */
+ /* DBGMAYBELEAVE */
+ if (dlp == NULL || tevpi != dlp->tevpi) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+ tfap->dputp_tedlst[__inum] = dlp->terp;
+ dlp->telp = NULL;
+ /* put this telst elemnt on free list */
+ dlp->terp = __dltevfreelst;
+ __dltevfreelst = dlp;
+}
+
+/*
+ * routine to assign tf arg 
+ * input is a b pointer (b non used if stren) and lhs expr
+ * __inst_ptr set to right instance
+ */
+static void exec_tfarg_assign(struct tfarg_t *tfap, struct expr_t *lhsxp,
+ register word32 *ap, register word32 *bp)
+{
+ register int32 lhslen;
+ register byte *sbp;
+ int32 schd_wire;
+
+ /* case 1 procedural assign */ 
+ if (tfap->anp->ntyp >= NONWIRE_ST)
+  { __exec2_proc_assign(lhsxp, ap, bp); return; }
+
+ /* case 2: need continuous assign (concat impossible) */
+ /* case 2a: fi>1 */
+ lhslen = lhsxp->szu.xclen;
+ if (lhsxp->x_multfi)
+  {
+   /* first update the driver then reeval all drivers */
+   if (lhsxp->x_stren)
+    {
+     sbp = (byte *) ap;
+     /* notice can just copy this is per inst table for driver */
+     memcpy(&(tfap->tfdrv_wp.bp[__inum*lhslen]), sbp, lhslen);
+    }
+   else __st_perinst_val(tfap->tfdrv_wp, lhslen, ap, bp);
+   __mdr_assign_or_sched(lhsxp);
+   return;
+  }
+
+ /* case 2b: fi == 1 conta assign */ 
+ if (lhsxp->lhsx_ndel && !__wire_init) schd_wire = TRUE;
+ else schd_wire = FALSE;
+ __exec_conta_assign(lhsxp, ap, bp, schd_wire);
+}
+
+/*
+ * emit a strdelputp trace message if tracing on
+ */
+static void emit_tputd_trmsg(struct tedputp_t *tedp, struct tfarg_t *tfap)
+{ 
+ word32 *ap, *bp;
+ struct tfrec_t *tfrp;
+ struct expr_t *lhsxp;
+ char s1[RECLEN], s2[IDLEN];
+
+ lhsxp = tfap->arg.axp;
+ if (tfap->anp->ntyp >= NONWIRE_ST) strcpy(s1, "procedural");
+ else
+  {
+   if (lhsxp->x_multfi) strcpy(s1, "continuous fi>1");
+   else strcpy(s1, "continuous fi=1");
+  }
+ tfrp = tedp->tedtfrp;
+ if (lhsxp->x_stren)
+  __st_regab_tostr(s2, (byte *) tedp->tedwp, lhsxp->szu.xclen);
+ else
+  { 
+   ap = tedp->tedwp;
+   bp = &(ap[wlen_(lhsxp->szu.xclen)]);
+   __regab_tostr(s2, ap, bp, lhsxp->szu.xclen, BHEX, FALSE);
+  }
+ __evtr_resume_msg();
+ __tr_msg("tf_ arg %d at %s in %s strdelputp %s assign value %s\n",
+  tedp->tedpnum, __bld_lineloc(__wrks1, tfrp->tffnam_ind, tfrp->tflin_cnt),
+  __msg2_blditree(__wrks2, __inst_ptr), s1, s2);
+} 
+
+/*
+ * ROUTINES TO REINITIALIZE PLI STUFF - TFRECS AND VPI ON RESET
+ */
+
+/*
+ * during reset reinitialize tfrecs 
+ */
+extern void __reinit_tfrecs(void) 
+{
+ register struct tfrec_t *tfrp;
+
+ for (tfrp = __tfrec_hdr; tfrp != NULL; tfrp = tfrp->tfrnxt)
+  reinit_1tfrec(tfrp);
+
+ /* free all ro sync events */ 
+ if (__tehdr_rosynci != -1)
+  {
+   /* add the list on to head of tev free list */ 
+   __tevtab[__teend_rosynci].tenxti = __tefreelsti;
+   __tefreelsti = __tehdr_rosynci;
+   __tehdr_rosynci = __teend_rosynci = -1;
+  }
+}
+ 
+/*
+ * reinit 1 tfrec
+ */
+static void reinit_1tfrec(struct tfrec_t *tfrp)
+{
+ register int32 i, pi;
+ register struct dltevlst_t *dlp;
+ register struct tevlst_t *tlp;
+ struct dltevlst_t *last_dlp;
+ struct tevlst_t *last_tlp;
+ struct tfarg_t *tfap;
+ struct expr_t *xp;
+ struct mod_t *mdp;
+ struct dceauxlst_t *dclp;
+
+ /* DBG remove --- */
+ if (tfrp->tf_inmdp == NULL) __misc_terr(__FILE__, __LINE__);
+ /* ---*/
+
+ mdp = tfrp->tf_inmdp;
+ /* notice arguments start from 1 - 0 is place holder */
+ /* arg 0 used for func. return value, but tfap[0] not used */
+ for (pi = 1; pi < tfrp->tfanump1; pi++)
+  {
+   tfap = &(tfrp->tfargs[pi]);
+   memset(tfap->old_pvc_flgs, 0, mdp->flatinum);
+   memset(tfap->sav_pvc_flgs, 0, mdp->flatinum);
+   xp = tfap->arg.axp;
+   for (i = 0; i < mdp->flatinum; i++)
+    {
+     tfap->sav_xinfos[i] = NULL;
+     if ((dlp = tfap->dputp_tedlst[i]) != NULL)
+      {
+       for (last_dlp = NULL; dlp != NULL; dlp = dlp->terp) last_dlp = dlp;
+       last_dlp->terp = __dltevfreelst; 
+       __dltevfreelst = tfap->dputp_tedlst[i];
+       tfap->dputp_tedlst[i] = NULL;
+      } 
+    }
+   if (tfap->tfdrv_wp.bp != NULL) __init_tfdrv(tfap, xp, mdp);
+  }
+
+ for (i = 0; i < mdp->flatinum; i++) 
+  {
+   if (tfrp->asynchon[i])
+    {
+     /* DBG remove ---*/
+     if (tfrp->pvcdcep[i] == NULL) __misc_terr(__FILE__, __LINE__);
+     /* --- */
+
+     /* SJM 01/02/03 - new algorithm pvcs stay on across reset like vpi */
+     for (dclp = tfrp->pvcdcep[i]; dclp != NULL; dclp = dclp->dclnxt)
+      {
+       /* SJM 05/08/03 - always one inst form */ 
+       /* but need to re-initialize previous value */
+       __init_1instdce_prevval(dclp->ldcep);
+      } 
+    }
+   /* still always remove any pending scheduled event */
+   tfrp->rosync_tevp[i] = -1;
+   tfrp->sync_tevp[i] = -1;
+   /* notice any events for these freed elswhere */
+   if ((tlp = tfrp->setd_telst[i]) != NULL)
+    {
+     for (last_tlp = NULL; tlp != NULL; tlp = tlp->telnxt) last_tlp = tlp;
+     last_tlp->telnxt = __ltevfreelst; 
+     __ltevfreelst = tfrp->setd_telst[i];
+     tfrp->setd_telst[i] = NULL;
+    }
+  }
+}
+
+/*
+ * MISCELLANEOUS ROUTINES
+ */
+
+/*
+ * call to malloc that dies if no memory available
+ * these are normal OS memory allocation with error terminaton
+ */
+extern char *__mytf_malloc(int32 size)
+{
+ char *cp;
+
+ if ((cp = (char *) malloc((word32) size)) == NULL)
+  {
+   __crit_msg(
+   "**FATAL[1]: No more memory from tf_ call at file %s line %d - %ld bytes memory used\n",
+    __in_fils[__tfrec->tffnam_ind], __tfrec->tflin_cnt, __mem_use);
+   __my_exit(4, TRUE);
+  }
+ /* DBG remove ---
+ if (__debug_flg)
+  __dbg_msg("tf_ allocated %d bytes\n", size);
+ --- */
+ return(cp);
+}
diff --git a/src/v_trch.c b/src/v_trch.c
new file mode 100644
index 0000000..77fdffd
--- /dev/null
+++ b/src/v_trch.c
@@ -0,0 +1,4747 @@
+/* Copyright (c) 1991-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * MODULE TO HANDLE TRAN CHANNELS - PREPARATION AND ASSIGNMENT
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+#include "vpi_user.h"
+
+/* local prototypes */
+static void free_vtx_and_edge_freelsts(void);
+static void emit_chan_size_table(void);
+static void bld_trauxs(void);
+static void alloc_traux(struct mod_t *, struct net_t *);
+static void bld_trgraph(struct mod_t *, struct traux_t *, struct net_t *);
+static void init_chanrec(struct chanrec_t *);
+static struct vbinfo_t *add_vtxtraux(struct net_t *, int32, int32);
+static void add_1chan_vtxes_and_edges(int32);
+static struct vtx_t *alloc_vtx(struct net_t *, int32);
+static void add_vtx_to_future_q(struct vtx_t *, struct itree_t *itp);
+static void add_edges_from_npps(struct vtx_t *, int32, struct itree_t *);
+static int32 add1_oside_edge(struct vtx_t *, struct net_pin_t *, struct net_t *,
+ int32, int32, struct itree_t *, struct itree_t *);
+static word32 cnvt_tobase_ntyp(word32);
+static void chg_bidchan_to_vtxlist(struct chanrec_t *);
+static void process_bid_vertices(struct chanrec_t *, struct vtx_t *,
+ struct itree_t *);
+static void add_vtx_to_bidvtxlist(struct chanrec_t *, struct vtx_t *,
+ struct itree_t *);
+static struct edge_t *alloc_edge(struct net_pin_t *);
+static void chkchannel(struct chanrec_t *);
+static void off_bichan_marks(struct chanrec_t *); 
+static void add_vtx_to_offlist(struct vtx_t *);
+static void chkchan_edge(struct chanrec_t *, struct edge_t *);
+static void save_bidandtran_npps(void);
+static void init_sttranif_chan(struct chanrec_t *);
+static void init_add_vtx_and_subtree(struct vtx_t *, struct itree_t *itp);
+static void off_stvtxtab_marks(void);
+
+static void stren_schd_bidpthdrvrs(struct net_t *, byte *, byte *);
+static void schd_bidpthdrvrs(struct net_t *, struct xstk_t *,
+ struct xstk_t *);
+static int32 schd_1bitpthdrvr(struct net_t *, register int32, i_tev_ndx *);
+static int32 evtr_schd_1bitpthdrvr(struct net_t *, register int32,
+ i_tev_ndx *);
+static void eval_assign_bid_chan(struct chanrec_t *);
+static void eval_assign_stbid_chan(struct chanrec_t *);
+static void ld_vtx_netbit(word32 *, word32 *, struct net_t *, int32);
+static void st_vtx_netbit(struct net_t *, int32, word32, word32);
+static void trmsg_frc_inhibit(struct net_t *, int32);
+static void transtore_trmsg(struct net_t *, int32, int32, word32, word32);
+static void stassign_1tranbit(struct net_t *, register int32, register word32);
+static void assign_1tranbit(struct net_t *, register int32, register word32,
+ register word32);
+static void eval_update_1w_tranchan(struct vtx_t *);
+static struct vtxlst_t *add_stchan_chged_vtx(struct vtx_t *, struct itree_t *);
+static void assign_chged_vtxs(void);
+static void find_chgvtx_vicinity(struct vtxlst_t *);
+static void stchan_trif_relax(void);
+static void add_to_chg_vtx_list(struct vtxlst_t *, int32);
+static void dmp_perturb_list(void);
+static char *to_vtx_info(char *, struct vtx_t *, struct itree_t *);
+static int32 try_reduce_tranif_stren(word32 *, struct gate_t *);
+static void try_reduce_tran_stren(word32 *, int32);
+static int32 get_switch_tranif_onoff(struct gate_t *, int32);
+static int32 get_bidchan_val(struct chanrec_t *, register struct net_t *,
+ int32, int32);
+static void dmp_vtx_edges(struct vtx_t *, struct itree_t *);
+static void dmp_vtx_and_out_edges(struct vtx_t *, struct itree_t *);
+static void prt_edge(struct vtx_t *, struct edge_t *, int32);
+static struct net_t *xldrvld_to_netbit(struct expr_t *, int32, int32 *,
+ struct itree_t *);
+static void getv2_itp(struct edge_t *, struct itree_t *, struct itree_t **,
+ struct itree_t **);
+static char *to_vtx(char *, struct vtx_t *);
+static struct itree_t *trchan_get_oside_itp(register struct net_pin_t *, int32,
+ int32 *, struct expr_t **, struct itree_t *);
+static struct expr_t *find_cat_oside_xp(struct expr_t *, int32, int32 *);
+static void fill_port_npps(struct net_t *, int32, struct itree_t *);
+static void add_match_vtxs(struct net_t *, struct net_pin_t *, int32);
+static int32 get_xldl_vtx(struct itree_t *, struct net_t *, int32, int32 *);
+static int32 add_xldl_vtx(struct itree_t *, struct net_t *, int32, int32);
+
+static void do_qc_wire_intran_force(struct net_t *, int32, word32, word32,
+ struct itree_t *);
+static void do_qc_wire_intran_release(struct net_t *, int32, struct expr_t *,
+ struct itree_t *);
+static void do_vpi_wire_intran_force(struct net_t *, int32, word32 *, word32 *);
+static void do_vpi_wire_intran_release(struct net_t *, int32);
+static void do_putv_wire_intran_softforce(struct net_t *, int32, word32 *, word32 *);
+
+/* extern prototypes (maybe defined in this module) */
+extern void __dmp_modtrans(struct mod_t *);
+extern struct net_t *__find_tran_conn_np(struct expr_t *);
+extern void __allocinit_stperival(union pck_u *, int32, struct net_t *, int32);
+extern void __allocinit_perival(union pck_u *, int32, int32, int32);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern char *__my_realloc(char *, int32, int32);
+extern void __get_bidnpp_sect(struct net_t *, struct net_pin_t *, int32 *,
+ int32 *);
+extern struct net_t *__tranx_to_netbit(register struct expr_t *, int32, int32 *,
+ struct itree_t *);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern int32 __get_const_bselndx(register struct expr_t *);
+extern void __eval_tran_bits(register struct net_t *);
+extern void __eval_tran_1bit(register struct net_t *, register int32);
+extern char *__my_malloc(int32);
+extern void __my_free(char *, int32);
+extern struct xstk_t *__stload_mdrwire(struct net_t *);
+extern struct xstk_t *__load_mdrwire(register struct net_t *);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __ld_perinst_val(register word32 *, register word32 *, union pck_u,
+ int32);
+extern void __st_perinst_val(union pck_u, int32, register word32 *,
+ register word32 *);
+extern char *__st_regab_tostr(char *, byte *, int32);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern char *__to_wtnam(char *, struct net_t *);
+extern void __lhsbsel(register word32 *, register int32, word32);
+extern struct pthdst_t *__get_path_del(struct rngdwir_t *, int32, word64 *);
+extern void __emit_path_distinform(struct net_t *, struct pthdst_t *,
+ word64 *);
+extern int32 __em_suppr(int32);
+extern void __emit_path_pulsewarn(struct pthdst_t *, struct tev_t *, word64 *,
+ word64 *, char *, word32);
+extern void __emit_path_samewarn(struct net_t *, int32, struct tev_t *,
+ word64 *, char *, word32);
+extern void __schedule_1wev(struct net_t *, int32, int32, word64, word64,
+ word32, i_tev_ndx *, int32);
+extern void __reschedule_1wev(i_tev_ndx, word32, word64, word64, i_tev_ndx *);
+extern void __cancel_1wev(struct tev_t *t);
+extern char *__to_evtrwnam(char *, struct net_t *, int32, int32,
+ struct itree_t *);
+extern char *__to_timstr(char *, word64 *);
+extern char *__to_vnam(char *, word32, word32);
+extern char *__bld_lineloc(char *, word32, int32);
+extern int32 __move_to_npprefloc(struct net_pin_t *);
+extern word32 __comb_1bitsts(word32, register word32, register word32);
+extern void __eval_1w_nonstren(register word32 *, register word32 *,
+ register word32, register word32, word32);
+extern void __chg_st_val(struct net_t *, register word32 *, register word32 *);
+extern void __st_val(struct net_t *, register word32 *, register word32 *);
+extern void __chg_st_bit(struct net_t *, int32, register word32, register word32);
+extern void __st_bit(struct net_t *, int32, register word32, register word32);
+extern char *__to_vvstnam(char *, word32);
+extern void __dmp_trchan(struct vtx_t *);
+extern void __dmp_bidchan(struct chanrec_t *);
+extern void __dmp1_nplstel(struct mod_t *, struct net_t *,
+ struct net_pin_t *);
+extern void __dmp_bidnet_drvs(struct net_t *, struct mod_t *);
+extern void __add_dmpv_chglst_el(struct net_t *);
+extern void __add_nchglst_el(register struct net_t *);
+extern void __add_select_nchglst_el(register struct net_t *, register int32,
+ register int32);
+extern void __wakeup_delay_ctrls(register struct net_t *, register int32,
+ register int32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern void __ld_bit(register word32 *, register word32 *,
+ register struct net_t *, int32);
+extern void __qc_tran_wireforce(struct net_t *, int32, int32, int32,
+ struct itree_t *, struct st_t *);
+extern void __qc_tran_wirerelease(struct net_t *, int32, int32, struct itree_t *,
+ struct expr_t *);
+extern void __tran_wire_vpi_force(struct net_t *, word32 *, word32 *, int32); 
+extern void __tran_wire_vpi_release(struct net_t *, int32); 
+extern void __tran_exec_putv_wire_softforce(struct net_t *, word32 *, word32 *,
+ int32); 
+extern void __alloc_qcval(struct net_t *);
+extern void __bit1_vpi_or_tran_wireforce(struct net_t *, word32 *, word32 *,
+ int32, int32, int32, char *);
+extern int32 __correct_forced_newwireval(struct net_t *, word32 *, word32 *);
+extern void __find_call_force_cbs(struct net_t *, int32);
+extern void __cb_all_rfs(struct net_t *, int32, int32);
+extern void __find_call_rel_cbs(struct net_t *, int32);
+extern void __assign_1mdrwire(register struct net_t *);
+extern int32 __unnormalize_ndx(struct net_t *, int32);
+extern struct xstk_t *__eval_assign_rhsexpr(register struct expr_t *,
+ register struct expr_t *);
+
+extern void __cv_msg(char *, ...);
+extern void __tr_msg(char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __sgfinform(int32, char *, ...);
+extern void __vpi_err(int32, int32, char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __case_terr(char *, int32);
+extern void __misc_terr(char *, int32);
+extern void __vpi_terr(char *, int32);
+
+extern word32 __mos_stmap[];
+extern word32 __rmos_stmap[];
+extern word32 __cap_to_stren[];
+
+/*
+ * ROUTINES TO BUILD TRAN AND UNCOLLAPSED INOUT TRAN CHANNEL CONN. GRAPHS
+ */
+
+/*
+ * build the separate inout tran graphs
+ * assumes called before building tran gates so cross instance trans
+ * allow all normal trans to be added to inter instance channels
+ * 
+ * must build from both side because channel can go up and and
+ * then down into other instance
+ * FIXME - for now never will see concatenate here
+ */
+extern void __bld_bidandtran_graph(void)
+{
+ register int32 ni, chi;
+ register struct net_t *np;
+ register struct chanrec_t *chanp;
+ int32 si, design_has_trans, start_chanid;
+ struct mod_t *mdp;
+ struct traux_t *trap;
+
+ if (__switch_verbose)
+  { 
+   __cv_msg("  SWITCH: begin switch channel graph construction.\n");
+  }
+
+ /* need to count number of switch (have tranif or different wire types) */
+ bld_trauxs();
+
+ /* DBG remove --
+ malloc_chain_check(1);
+ -- */
+
+ /* alloc channel info table - size increased when needed */
+ __nxt_chan_id = 0;
+ __chantab = (struct chanrec_t *) __my_malloc(1000*sizeof(struct chanrec_t));
+ __chanallocsize = 1000;
+ design_has_trans = FALSE;
+ for (si = 0; si < 7; si++)
+  { __stvtxtab[si] = NULL; __stvtxtabend[si] = NULL; }
+ __chg_vtxlst_hdr = __chg_vtxlst_end = NULL;
+ __off_vtxlst_hdr = __off_vtxlst_end = NULL;
+ __vtx_freelst = NULL;
+ __edge_freelst = NULL;
+ __vtxlst_freelst = NULL;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mnnum == 0) continue;
+   /* if no trans and no inouts module will have no tran channels */
+   if (!mdp->mod_hasbidtran && !mdp->mod_hastran) continue;
+   start_chanid = __nxt_chan_id;
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+    {
+     if ((trap = np->ntraux) == NULL) continue;
+     bld_trgraph(mdp, trap, np);
+     design_has_trans = TRUE;
+    }
+   free_vtx_and_edge_freelsts();
+   if (__switch_verbose && __nxt_chan_id > start_chanid)
+    {
+     __cv_msg(
+      "  SWITCH: %d channels in module %s (%d insts, %d nets) built.\n",
+      __nxt_chan_id - start_chanid,
+      mdp->msym->synam, mdp->flatinum, mdp->mnnum);
+    }
+  }
+
+ __num_switch_chans = 0;
+ for (chi = 0; chi < __nxt_chan_id; chi++)
+  {
+   chanp = &(__chantab[chi]);
+   if (chanp->chtyp != TRPROC_TRAN && chanp->chan_diffwtyps)
+    {
+     if (chanp->chtyp == TRPROC_STBID) chanp->chtyp = TRPROC_STWTYPBID;
+     else if (chanp->chtyp == TRPROC_BID)
+      {
+       /* SJM 04/21/01 - internal error if inout only wired trchan non stren */
+       __case_terr(__FILE__, __LINE__);
+      }
+     else __case_terr(__FILE__, __LINE__); 
+    }
+   if (chanp->chtyp == TRPROC_STWTYPBID || chanp->chtyp == TRPROC_TRAN)
+    __num_switch_chans++;
+
+   /* only check tran channels */
+   /* DBG remove --- */
+   if (__debug_flg)
+    {  
+     if (!chanp->chan_no_vtxs) chkchannel(chanp);
+    }
+   /* --- */
+  }
+ if (__switch_verbose) emit_chan_size_table();
+ /* done with tran npps (nlds and ndrvs must now only have hard ones) */
+ /* move to list in traux for vpi_ local load/driver processing */
+ save_bidandtran_npps();
+ if (__debug_flg && design_has_trans)
+  {
+   __dbg_msg("++ dumping all channels after optimization:\n");
+/* -- DBG remove -- 
+   for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+    {
+     if (mdp->mnnum == 0) continue;
+     if (!mdp->mod_hasbidtran && !mdp->mod_hastran) continue;
+     __dmp_modtrans(mdp);
+    }
+--- */
+   /* 04/12/00 - */
+   for (chi = 0; chi < __nxt_chan_id; chi++)
+    {
+     chanp = &(__chantab[chi]);
+     if (chanp->chan_no_vtxs) __dmp_bidchan(chanp);
+     else
+      {
+       /* dump from vertex although vtx is just used to get back to chan id */
+       __push_itstk(chanp->chvitp);
+       __dmp_trchan(chanp->chvxp);
+       __pop_itstk();
+      }
+    }
+  }
+}
+
+/*
+ * free vtx and edge free lists
+ * 
+ * because freeing pure bid channels now faster to use free list for
+ * vertices and edges
+ * SJM 07/27/01 - also needed because vtx list els used in building channels
+ */
+static void free_vtx_and_edge_freelsts(void)
+{
+ register struct vtx_t *vtxp, *vtxp2;
+ register struct edge_t *ep, *ep2;
+ 
+ for (vtxp = __vtx_freelst; vtxp != NULL;)
+  {
+   /* free list linked using edge field */
+   vtxp2 = (struct vtx_t *) vtxp->vedges;
+   __my_free((char *) vtxp, sizeof(struct vtx_t));
+   vtxp = vtxp2;
+  }
+ __vtx_freelst = NULL;
+
+ for (ep = __edge_freelst; ep != NULL;)
+  {
+   ep2 = ep->enxt;
+   __my_free((char *) ep, sizeof(struct edge_t));
+   ep = ep2;
+  }
+ __edge_freelst = NULL;
+}
+
+/*
+ * routine for switch verbose mode to give table of switch chan sizes 
+ */
+static void emit_chan_size_table(void)
+{
+ register struct chanrec_t *chanp;
+ register int32 chi;
+ int32 size1_5, size5_10, size10_20, size20_50, size50_100, size100_200;
+ int32 size200_500, size500_1000, more1000, i1;
+ struct net_t *np;
+ struct itree_t *itp;
+ char s1[RECLEN], s2[RECLEN];
+
+ itp = NULL;
+ size1_5 = size5_10 = size10_20 = size20_50 = size50_100 = size100_200 = 0;
+ size200_500 = size500_1000 = more1000 = 0;
+ for (chi = 0; chi < __nxt_chan_id; chi++)
+  {
+   chanp = &(__chantab[chi]);
+
+   if (chanp->numvtxs <= 5) size1_5++;
+   else if (chanp->numvtxs <= 10) size5_10++;
+   else if (chanp->numvtxs <= 20) size10_20++;
+   else if (chanp->numvtxs <= 50) size20_50++;
+   else if (chanp->numvtxs <= 100) size50_100++;
+   else if (chanp->numvtxs <= 200) size100_200++;
+   else if (chanp->numvtxs <= 500) size200_500++;
+   else if (chanp->numvtxs <= 1000) size500_1000++;
+   else
+    {
+     more1000++;
+
+     /* SJM 04/23/01 - now need to access vtx for inout from bid vtxlp list */
+     if (chanp->chtyp == TRPROC_TRAN || chanp->chtyp == TRPROC_STWTYPBID)
+      {
+       strcpy(s1, "tran");
+       np = chanp->chvxp->vnp;
+       i1 = chanp->chvxp->vi1;
+       itp = chanp->chvitp;
+      }
+     else
+      {
+       strcpy(s1, "inout"); 
+       np = chanp->bid_vtxlp->vnp;
+       i1 = chanp->bid_vtxlp->vi1;
+       itp = chanp->bid_vtxlp->bidvtx_itp;
+      }
+     if (i1 != -1)
+      {
+       sprintf(s2, "%s.%s[%d]", __msg2_blditree(__xs, itp), np->nsym->synam,
+        i1);
+      }
+     else sprintf(s2, "%s.%s", __msg2_blditree(__xs, itp), np->nsym->synam);
+
+     __cv_msg(
+      "  Large %s switch channel has %d terminals (ID=%d) a vertex: %s\n",
+      s1, chanp->numvtxs, chi, s2);  
+    }
+  }
+ __cv_msg("  Total Number of Switch Channels: %d\n", __nxt_chan_id);
+ if (size1_5 != 0)
+  __cv_msg("  %d channels with less than 5 terminals.\n", size1_5);
+ if (size5_10 != 0)
+  __cv_msg("  %d channels with 6 to 10 terminals.\n", size5_10);
+ if (size10_20 != 0)
+  __cv_msg("  %d channels with 11 to 20 terminals.\n", size10_20);
+ if (size20_50 != 0)
+  __cv_msg("  %d channels with 21 to 50 terminals.\n", size20_50);
+ if (size50_100 != 0)
+  __cv_msg("  %d channels with 51 to 100 terminals.\n", size50_100);
+ if (size100_200 != 0)
+  __cv_msg("  %d channels with 101 to 200 terminals.\n", size100_200);
+ if (size200_500 != 0)
+  __cv_msg("  %d channels with 201 to 500 terminals.\n", size200_500);
+ if (size500_1000 != 0)
+  __cv_msg("  %d channels with 501 to 1000 terminals.\n", size500_1000);
+ if (more1000 != 0)
+  __cv_msg("  %d channels with more than 1000 terminals.\n", more1000);
+}
+
+/*
+ * routine to build the net tran aux records for all nets that need them
+ *
+ * pre-allocates all trauxs including per bit forms for xmrs and inouts
+ * net connection type and type of channel element determine is per inst
+ *
+ * after here all trauxes allocated and all per inst. bits set but 
+ * do not know channel type (processing type)
+ */
+static void bld_trauxs(void) 
+{
+ register struct net_pin_t *npp;
+ register int32 ni, gi, gri;
+ register struct net_t *np;
+ int32 chg;
+ struct gref_t *grp;
+ struct gate_t *gp;
+ struct mod_t *mdp, *refmdp;
+ struct net_t *np1;
+
+ /* all xmr lhs net targs need per inst. and define per inst. channel */
+ /* even if rooted with only one itree loc. target */
+ /* this will get all xmr def. (target) wires from the ref */ 
+ /* this will mark tran terminals so can find all per inst. other sides */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   for (gri = 0, grp = &(mdp->mgrtab[0]); gri < mdp->mgrnum; gri++, grp++)  
+    {
+     /* if ref. point is rhs, channel does not need to be per inst. */
+     if (grp->gr_gone || !grp->gxndp->x_islhs) continue;
+
+     /* for upward rel. can use 1st for mod type since all same */
+     /* SJM 08/15/00 - using 0th ref loc inst. table entry - always exists */ 
+     if (grp->upwards_rel)
+      {
+       refmdp = grp->targu.uprel_itps[0]->itip->imsym->el.emdp;
+      }
+     else refmdp = grp->targmdp;
+
+     np = grp->targsyp->el.enp;
+     /* must do all or will not set all needed mod having tran/bid trans */
+     for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+      {
+       if (npp->npntyp == NP_BIDMDPRT && npp->npntyp == NP_BIDICONN)
+        refmdp->mod_hasbidtran = TRUE; 
+       else if (npp->npntyp == NP_TRAN) refmdp->mod_hastran = TRUE;
+       else continue;
+       /* may have lots of xmrs to same target - all must be per bit/inst */
+       if (np->ntraux == NULL) alloc_traux(refmdp, np);
+      }
+    }
+  }
+
+ /* any inout or inout iconn even if only 1 inst.*/
+ /* need per inst. even if 1 inst in case other side has per inst. */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mnnum == 0) continue;
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+    {
+     if (np->ntraux != NULL) continue;
+     for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+      {
+       if (npp->npntyp == NP_TRAN) { mdp->mod_hastran = TRUE; continue; }
+       if (npp->npntyp == NP_BIDMDPRT || npp->npntyp == NP_BIDICONN)
+        {  
+         /* must go through all to set has bid tran for module */ 
+         mdp->mod_hasbidtran = TRUE; 
+         /* if only one inst. per inst. does nothing */
+         if (np->ntraux == NULL) alloc_traux(mdp, np);
+        }
+      }
+    }
+  }
+
+ /* all nets that connect to other side of per. inst trans */
+ /* all inout trans are alloc and marked by here - look only at trans */
+ /* all tran nets that are per inst from xmr have traux by here */ 
+ /* and all module having tranor bid tran set by here */ 
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (!mdp->mod_hastran) continue;
+   chg = TRUE;
+   while (chg)
+    {
+     chg = FALSE;
+     for (gi = 0; gi < mdp->mgnum; gi++)
+      {
+       gp = &(mdp->mgates[gi]);
+
+       if (gp->g_class != GC_TRAN && gp->g_class != GC_TRANIF) continue;
+
+       /* 04/26/01 - if terminals same, removed so ignore here */
+       if (gp->g_gone) continue;
+
+       /* if xmr, the net will be per inst already */ 
+       np = __find_tran_conn_np(gp->gpins[0]);
+       np1 = __find_tran_conn_np(gp->gpins[1]);
+       if (np->ntraux != NULL)
+        {
+         if (np1->ntraux == NULL)
+          { alloc_traux(mdp, np1); chg = TRUE; }
+        }
+       else if (np1->ntraux != NULL)
+        {
+         if (np->ntraux == NULL)
+          { alloc_traux(mdp, np); chg = TRUE; }
+        }
+      }
+    }
+  }
+ /* allocate non per inst - can only be non xmr/inout conn. tran gate */
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mnnum == 0) continue;
+   if (!mdp->mod_hastran) continue;
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+    {
+     if (np->ntraux != NULL) continue;
+
+     for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+      {
+       /* if on other side of inout/iconn to inout in chan or xmr tran */
+       /* already allocated */
+       if (npp->npntyp == NP_TRAN) { alloc_traux(mdp, np); break; }  
+      }
+    }
+  }
+}
+
+/*
+ * allocate and initialize a traux for a net not yet on any tran channel
+ */
+static void alloc_traux(struct mod_t *mdp, struct net_t *np)
+{
+ struct traux_t *trap; 
+ int32 nbytes;
+
+ /* DBG remove --
+ __dbg_msg("allocating traux for net %s in module %s\n",
+  np->nsym->synam, mdp->msym->synam);
+ --- */
+ 
+ trap = (struct traux_t *) __my_malloc(sizeof(struct traux_t));
+ np->ntraux = trap; 
+ /* alloc storage for hard drivers - must be per instance */
+ if (np->n_stren)
+  __allocinit_stperival(&trap->trnva, mdp->flatinum, np, TRUE);
+ else __allocinit_perival(&trap->trnva, mdp->flatinum, np->nwid, TRUE);
+ /* allocate per inst per bit bit chan */ 
+ nbytes = np->nwid*mdp->flatinum*sizeof(struct vbinfo_t *);
+ /* allocate per bit vtx and chan id */
+ /* BEWARE - assumes can set array of nil ptrs by zeroing */
+ trap->vbitchans = (struct vbinfo_t **) __my_malloc(nbytes);
+ memset(trap->vbitchans, 0, nbytes);
+ trap->tran_npps = NULL;
+}
+
+/*
+ * routine to build tran channel graph for 1 for net
+ * must fill channel for each instance
+ * for type tran channel np insts will be 1 even though maybe more
+ *
+ * SJM - 08/26/00 - changed so storing dest. itree loc (if different) in
+ * edge - so tracing edge just pushes new itree loc
+ */
+static void bld_trgraph(struct mod_t *mdp, struct traux_t *trap,
+ struct net_t *np)
+{
+ register int32 ii, bi2;
+ int32 bi, insts, osize;
+ struct vbinfo_t *vbip;
+ struct chanrec_t *chanp;
+
+ /* know all wires bits in per-inst channels, mark per inst by here */
+ insts = mdp->flatinum;
+     
+ /* build tran channel for each bit of net */ 
+ for (bi2 = np->nwid - 1; bi2 >= 0; bi2--)
+  {
+   /* DBG remove --
+   __cv_msg("++ malloc chain check before processing %s[%d] tran:\n",
+    np->nsym->synam, (!np->n_isavec ? -1 : bi2));
+   malloc_chain_check(1);
+   -- */
+
+   bi = (!np->n_isavec) ? -1 : bi2;
+   /* DBG remove ---
+   if (__debug_flg)
+    {
+     __dbg_msg("++ processing %s[%d] tran:\n", np->nsym->synam,
+      (!np->n_isavec ? -1 : bi));
+    }
+   --- */
+   for (ii = 0; ii < insts; ii++) 
+    {
+     /* notice know that ii and itinum same */
+     __push_itstk(mdp->moditps[ii]);
+     if ((vbip = trap->vbitchans[np->nwid*ii + bi2]) != NULL)
+      {
+       if (__debug_flg)
+        {
+         sprintf(__xs2, ", itp=%s", __msg2_blditree(__xs, __inst_ptr));
+
+         /* DBG remove -- */
+         if (__debug_flg)
+          {
+           __dbg_msg(
+            "-- vertex %s (id=%d%s) already in channel\n",
+            to_vtx(__xs, vbip->vivxp), vbip->chan_id, __xs2);
+          }
+         /* --- */
+        }
+       __pop_itstk();
+       continue; 
+      }
+     /* add the new vertex, bld net to vtx conn and maybe alloc vb tab */
+     vbip = add_vtxtraux(np, bi, __nxt_chan_id++); 
+     trap->vbitchans[np->nwid*ii + bi2] = vbip;
+    
+     if (__nxt_chan_id >= __chanallocsize)
+      {
+       osize = __chanallocsize;
+       __chanallocsize += (3*osize)/2;
+       __chantab = (struct chanrec_t *)
+        __my_realloc((char *) __chantab, osize*sizeof(struct chanrec_t),
+         (int32) (__chanallocsize*sizeof(struct chanrec_t)));
+      }
+     chanp = &(__chantab[__nxt_chan_id - 1]);
+     init_chanrec(chanp);
+     chanp->chvxp = vbip->vivxp;
+     chanp->chvitp = __inst_ptr;
+     chanp->numvtxs = 1;
+     /* SJM 09/18/00 - since no longer checking channels need rigth first */
+     /* channel type for 1 element (unc.) channels */
+     if (np->n_stren) chanp->chtyp = TRPROC_STBID;
+     else chanp->chtyp = TRPROC_BID;
+
+     /* SJM 07/27/01 - change algorithm to use priority queue */
+     /* new algorithm saves oside vtxes on vtx list and adds edges from cur */
+     /* vertex (not both edges at once as before) before moving to next */
+     /* DBG add -- sav_mem_use = __mem_use; */
+     add_vtx_to_future_q(vbip->vivxp, __inst_ptr);
+     add_1chan_vtxes_and_edges(__nxt_chan_id - 1);
+
+     /* st bid and simple bid, convert to simple vtx list and free chan */ 
+     if ((chanp->chtyp == TRPROC_STBID || chanp->chtyp ==TRPROC_BID)
+      && !chanp->chan_diffwtyps)
+      {
+       chg_bidchan_to_vtxlist(chanp);
+      }
+     /* DBG add --
+     else
+      {
+       if (__switch_verbose) 
+        {
+         __cv_msg("tran channel with %d vertices requires %d bytes.\n",
+          chanp->numvtxs, __mem_use - sav_mem_use);
+        }
+      }
+     --- */
+
+     if (__switch_verbose && ((__nxt_chan_id % 5000) == 0))
+      {
+       __cv_msg(
+        "  SWITCH: %d switch/inout channel graphs constructed.\n",
+        __nxt_chan_id);
+      }
+     __pop_itstk();
+    }
+  }
+}
+
+/*
+ * initialize a record for a new channel
+ */
+static void init_chanrec(struct chanrec_t *chanp)
+{
+ chanp->chtyp = TRPROC_UNKN;
+ chanp->chan_diffwtyps = FALSE;
+ chanp->chan_no_vtxs = FALSE;
+ chanp->chvxp = NULL;
+ chanp->chvitp = NULL;
+ chanp->bid_vtxlp = NULL;
+ chanp->numvtxs = 0;
+}
+
+/*
+ * add a new vertex and add net to link vertex
+ * vertices are net and edges are gates or cross port assigns (npps) 
+ */
+static struct vbinfo_t *add_vtxtraux(struct net_t *np, int32 bi, int32 chanid) 
+{
+ struct vtx_t *vtxp;
+ struct vbinfo_t *vbip;
+
+ vbip = (struct vbinfo_t *) __my_malloc(sizeof(struct vbinfo_t));  
+ vbip->chan_id = chanid;
+ /* build the new tran channel - first add this vertex on front */
+ vtxp = alloc_vtx(np, bi);
+ vbip->vivxp = vtxp;
+ return(vbip);
+}
+
+/*
+ * add all rest of vertices and all edges or rest of channel
+ *
+ * LOOKATME - using chg vtxlst list to build tran graph and same list
+ * used later to build perturb list 
+ */
+static void add_1chan_vtxes_and_edges(int32 chanid)
+{
+ register struct vtxlst_t *vtxlp;
+ register struct vtx_t *vtxp;
+ struct itree_t *itp;
+ 
+ /* know at least one vtx list element or will not get here */
+ for (vtxlp = __chg_vtxlst_hdr; vtxlp != NULL; vtxlp = vtxlp->vtxnxt)  
+  {
+   /* see if already processed */
+   vtxp = vtxlp->vtxp;
+   itp = vtxlp->vtx_itp;
+
+   /* mark set when all edges from vertex added */
+   if (vtxp->vtx_mark) continue;
+
+   add_edges_from_npps(vtxp, chanid, itp);
+   vtxp->vtx_mark = TRUE; 
+  }
+ /* turn off all marks */
+ for (vtxlp = __chg_vtxlst_hdr; vtxlp != NULL; vtxlp = vtxlp->vtxnxt)  
+  vtxlp->vtxp->vtx_mark = FALSE;
+
+ /* add entire vtx list to vtx list free list */
+ __chg_vtxlst_end->vtxnxt = __vtxlst_freelst; 
+ __vtxlst_freelst = __chg_vtxlst_hdr;
+ __chg_vtxlst_hdr = __chg_vtxlst_end = NULL;
+}
+
+/*
+ * allocate a tran graph vertex (wire-bit)
+ */
+static struct vtx_t *alloc_vtx(struct net_t *np, int32 bi)
+{
+ struct vtx_t *vtxp;
+
+ if (__vtx_freelst != NULL)
+  {
+   vtxp = __vtx_freelst;
+   __vtx_freelst = (struct vtx_t *) __vtx_freelst->vedges;
+  }
+ else vtxp = (struct vtx_t *) __my_malloc(sizeof(struct vtx_t)); 
+
+ vtxp->new_vtxval = ST_HIZ;
+ vtxp->old_vtxval = ST_HIZ;
+ vtxp->vtx_chged = FALSE;
+ vtxp->vtx_in_vicinity = FALSE;
+ vtxp->vtx_forced = FALSE;
+ vtxp->vtx_supply = FALSE;
+ vtxp->vtx_mark = FALSE;
+ vtxp->vtx_mark2 = FALSE;
+ vtxp->vnp = np;
+ vtxp->vi1 = bi;
+ vtxp->vedges = NULL;
+ return(vtxp);
+}
+
+/*
+ * add vertex to future add vtx from edges fifo queue
+ */
+static void add_vtx_to_future_q(struct vtx_t *vtxp, struct itree_t *itp)
+{
+ register struct vtxlst_t *vtxlp;
+
+ /* alloc and add to list */
+ if (__vtxlst_freelst == NULL)
+  vtxlp = (struct vtxlst_t *) __my_malloc(sizeof(struct vtxlst_t));
+ else
+  {
+   vtxlp = __vtxlst_freelst;
+   __vtxlst_freelst = __vtxlst_freelst->vtxnxt;
+  }
+ vtxlp->vtxp = vtxp;
+ vtxlp->vtx_itp = itp;
+ vtxlp->vtxnxt = NULL;
+ if (__chg_vtxlst_hdr == NULL) __chg_vtxlst_hdr = __chg_vtxlst_end = vtxlp;
+ else
+  {
+   __chg_vtxlst_end->vtxnxt = vtxlp;
+   __chg_vtxlst_end = vtxlp; 
+  }
+}
+
+/*
+ * process all edge's from current vtx list el and add one from this
+ * vtx edge for every npp and add all vertices not in a switch channel
+ *
+ * 05/21/01 SJM - now passing vertex itree loc (for edge it is vtx 1)
+ * 07/27/01 SJM - now add all vertices breadth first
+ */
+static void add_edges_from_npps(struct vtx_t *vtxp, int32 chanid,
+ struct itree_t *vt1_itp)
+{
+ register struct net_pin_t *npp;
+ int32 ri1, ri2, bi, bi2, osbi, fromr_bi, catel_bi;
+ int32 cat_oside_bi, oside_vtxndx;
+ struct net_t *np, *osnp;
+ struct expr_t *xp;
+ struct itree_t *vt2_itp, *oside_itp;
+
+ np = vtxp->vnp;
+ bi = vtxp->vi1;
+ /* bi2 is edge start bit of vectored net */
+ bi2 = (bi == -1) ? 0 : bi;
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   /* ignore hard (channel input) drivers */
+   if (npp->npntyp != NP_BIDICONN && npp->npntyp != NP_BIDMDPRT
+    && npp->npntyp != NP_TRAN) continue;
+
+   /* if npp only applies to one inst, filter if wrong inst */
+   /* this is only for rooted */
+   if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != vt1_itp)
+    continue;
+       
+   /* any IS bit select forms in tran chans removed from splitting */
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   /* unc. because index mismatch */
+   if (ri1 != -1 && (bi2 > ri1 || bi2 < ri2)) continue;
+
+   /* get oside vtx, if same as this side vt2 itp nil */
+   vt2_itp = trchan_get_oside_itp(npp, bi2, &catel_bi, &xp, vt1_itp);
+   /* if other side unc., nothing to add */
+   if (xp->optyp == OPEMPTY) continue;
+
+   oside_itp = (vt2_itp != NULL) ? vt2_itp : vt1_itp; 
+   cat_oside_bi = -1;
+   /* this looks ahead to other side but not used until bottom */
+   /* no itree loc. change */
+   if (npp->npntyp == NP_TRAN)
+    {
+     osnp = __tranx_to_netbit(xp, 0, &osbi, oside_itp); 
+     if (osbi == -2) continue;
+
+     /* flags are not per inst. - use near side bit index */
+     /* for now no special routine for channels with tranifs */
+     __chantab[chanid].chtyp = TRPROC_TRAN;
+     /* FIXME - set tranif processing mode separate value here when used */
+    }
+   else if (npp->npntyp == NP_BIDICONN || npp->npntyp == NP_BIDMDPRT)
+    { 
+     /* set index offset to match other side from this side npp */
+     if (npp->npaux == NULL) fromr_bi = bi2;
+     else
+      { 
+       if (npp->npaux->nbi1 == -1) fromr_bi = bi2;
+       /* ??? LOOKATME - why is npp low psel bit subtracted off */  
+       else fromr_bi = bi2 - npp->npaux->nbi2.i;
+
+       /* in case this side expr in concat need low of where in concat */
+       /* so can add to otherside index to get matching oside bit */
+       if (npp->npaux->lcbi1 != -1) cat_oside_bi = npp->npaux->lcbi2;
+      }
+
+     /* set type of channel if changes */
+     if (__chantab[chanid].chtyp != TRPROC_TRAN)
+      {
+       if (np->n_stren)
+        {
+         /* DBG remove --- */
+         if (__chantab[chanid].chtyp == TRPROC_BID)
+          __misc_terr(__FILE__, __LINE__); 
+         /* --- */
+         __chantab[chanid].chtyp = TRPROC_STBID;
+        }
+       else
+        {
+         /* DBG remove --- */
+         if (__chantab[chanid].chtyp == TRPROC_STBID)
+          __misc_terr(__FILE__, __LINE__); 
+         /* --- */
+         __chantab[chanid].chtyp = TRPROC_BID;
+        }
+      }
+     osnp = __tranx_to_netbit(xp, ((catel_bi == -1) ? fromr_bi : catel_bi),
+      &osbi, oside_itp); 
+     if (osbi == -2) continue;
+    }
+   else { __case_terr(__FILE__, __LINE__); continue; }
+
+   /* compute other side vertex index */
+   /* osbi is other side connecting expr object index (maybe -1) */ 
+   /* cat oside bi is offset of this side npp in other side cat (none -1) */
+   if (osbi == -1)
+    {
+     if (cat_oside_bi != -1) oside_vtxndx = cat_oside_bi;
+     else oside_vtxndx = -1;
+    }
+   else
+    { 
+     if (cat_oside_bi == -1) oside_vtxndx = osbi;
+     else oside_vtxndx = osbi + cat_oside_bi;
+    }
+
+   /* alloc oside vertex if needed and add one edge to it */
+   if (!add1_oside_edge(vtxp, npp, osnp, oside_vtxndx, chanid, vt1_itp,
+    vt2_itp)) continue;
+
+   /* DBG remove --
+   if (__debug_flg)
+    { 
+     int32 ei;
+     struct edge_t *ep;
+
+     -* this must run in itree loc. of this side edge *-
+     __push_itstk(vt1_itp);
+     sprintf(__xs2, ", itp=%s", __msg2_blditree(__xs, __inst_ptr));
+
+     __dbg_msg(">< vertex %s(id=%d%s) added, edges:\n",
+      to_vtx(__xs, vtxp), chanid, __xs2);
+     for (ei = 1, ep = vtxp->vedges; ep != NULL; ep = ep->enxt, ei++) 
+      prt_edge(vtxp, ep, ei);
+     __pop_itstk();
+    }
+   --- */
+  }
+}
+
+/*
+ * convert npp into range - uses current instance 
+ */ 
+extern void __get_bidnpp_sect(struct net_t *np, struct net_pin_t *npp,
+ int32 *bi1, int32 *bi2)
+{
+ struct npaux_t *auxp;
+
+ if ((auxp = npp->npaux) == NULL || auxp->nbi1 == -1)
+  {
+   /* all internal indices normalized to h:0 */
+   if (np->n_isavec) { *bi1 = np->nwid - 1; *bi2 = 0; }
+   else *bi1 = *bi2 = -1;
+   return;
+  }
+ /* DBG remove -- */
+ if (auxp->nbi1 == -2) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ *bi1 = auxp->nbi1;
+ *bi2 = auxp->nbi2.i;
+}
+
+/*
+ * move from trchan npp to other side or 2nd vtx itree loc. 
+ * returns other side itree loc if different else nil
+ *
+ * does not use net (col. to in vtx), so for col. to chges only itp 
+ * LOOKATME - think this code may be wrong?
+ */
+static struct itree_t *trchan_get_oside_itp(register struct net_pin_t *npp,
+ int32 bi2, int32 *catel_bi, struct expr_t **xp2, struct itree_t *vt1_itp)
+{
+ register struct itree_t *vt2_itp, *itp2;
+ register struct expr_t *xp;
+ register struct mod_pin_t *mpp;
+ register struct expr_t *idndp;
+ struct gate_t *gp;
+ struct npaux_t *auxp;
+ struct mod_t *vt2_mdp;
+ int32 netbi;
+
+ *catel_bi = -1;
+ vt2_itp = NULL; 
+ switch ((byte) npp->npntyp) {
+  case NP_TRAN:
+   gp = npp->elnpp.egp;
+   if (npp->obnum == 0) xp = gp->gpins[1]; else xp = gp->gpins[0];
+   break;
+  case NP_BIDMDPRT:
+   xp = vt1_itp->itip->ipins[npp->obnum];
+   vt2_itp = vt1_itp->up_it; 
+   break;
+  case NP_BIDICONN: 
+   if (npp->np_xmrtyp != XNP_LOC)
+    {
+     /* SJM 10/05/99 - for down relative may be at top or at bottom */
+     /* correct by detecting up */
+     if (npp->np_xmrtyp == XNP_RTXMR)
+      {
+       /* always moved to ref. point even if at top - since rooted works */
+       __push_itstk(vt1_itp); 
+       /* SJM 04/17/03 - this can't fail */
+       __move_to_npprefloc(npp);
+       itp2 = __inst_ptr;
+       __pop_itstk();
+       __pop_itstk();
+      }
+     else
+      {
+       /* for non rooted, if at ref. point, do not move */
+       if (vt1_itp->itip->imsym->el.emdp == npp->npaux->npu.npgrp->gin_mdp)
+        itp2 = vt1_itp;
+       else
+        {
+         /* if F, this instance not xmr, if T pushes ref loc on it stk */
+         __push_itstk(vt1_itp); 
+         /* SJM 04/17/03 - if not matching XMR path, must not move */
+         if (!__move_to_npprefloc(npp)) __misc_terr(__FILE__, __LINE__);
+         itp2 = __inst_ptr;
+         __pop_itstk();
+         __pop_itstk();
+        }
+      }
+    }
+   /* local non xmr - set itree loc for use below */
+   else itp2 = vt1_itp;
+
+   /* DBG remove -- */
+   if (itp2->in_its == NULL) __misc_terr(__FILE__, __LINE__);
+   if (itp2->itip->imsym->el.emdp->minum <= npp->elnpp.eii)
+    __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   vt2_itp = &(itp2->in_its[npp->elnpp.eii]);
+   vt2_mdp = vt2_itp->itip->imsym->el.emdp;
+   /* DBG remove -- */
+   if (npp->obnum >= vt2_mdp->mpnum) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   mpp = &(vt2_mdp->mpins[npp->obnum]);
+   xp = mpp->mpref;
+   break;
+  default:  __case_terr(__FILE__, __LINE__); xp = NULL;
+ }
+
+ /* need to find channel */
+ if (xp->optyp == ID || xp->optyp == GLBREF) idndp = xp;  
+ else if (xp->optyp == LSB || xp->optyp == PARTSEL) idndp = xp->lu.x;
+ else if (xp->optyp == OPEMPTY) { *xp2 = xp; return(vt2_itp); }
+ else if (xp->optyp == LCB)
+  {
+   /* LOOKATME - for entire wire no lcb ofset */
+   if ((auxp = npp->npaux) == NULL || auxp->lcbi1 == -1) netbi = bi2;
+   else netbi = bi2 + auxp->lcbi1;
+   
+   /* this does not need itree loc */
+   *xp2 = find_cat_oside_xp(xp, netbi, catel_bi);
+   return(vt2_itp);
+  }
+ else { __case_terr(__FILE__, __LINE__); idndp = NULL; }
+ 
+ if (idndp->optyp == GLBREF) 
+  {
+   /* SJM 07/23/01 - for other side of mod port xmr, need to push oside itp */
+   /* not entering down side - can't happen for ICONN since oside never xmr */
+   /* notice if not mod port will be tran where vt2 itp not set */
+   if (npp->npntyp == NP_BIDMDPRT) __push_itstk(vt2_itp);
+   else __push_itstk(vt1_itp);
+
+   __xmrpush_refgrp_to_targ(idndp->ru.grp);
+   vt2_itp = __inst_ptr;
+   __pop_itstk();
+   __pop_itstk();
+  }
+ *xp2 = xp;
+ return(vt2_itp);
+}
+
+/*
+ * routine to find non concat lhs xp from concat and bit index in concat 
+ *
+ * returns bit index in xp net if bit or part select or vectored net
+ * returns -1 for scalar
+ */
+static struct expr_t *find_cat_oside_xp(struct expr_t *xp, int32 catbi,
+ int32 *catel_bi)
+{
+ register struct expr_t *catxp;
+ register int32 catxlen, bi1;
+
+ for (catxp = xp->ru.x; catxp != NULL; catxp = catxp->ru.x)
+  {
+   catxlen = catxp->lu.x->szu.xclen;
+   /* bi1 is low bit of first (high) concat element */
+   bi1 = catxp->szu.xclen - catxlen;
+
+   /* DBG remove ---
+   if (__debug_flg)
+    __dbg_msg(
+     "+++rhs: total concat wid=%u, low index=%d, wid=%u, remaining wid=%u\n",
+     xp->szu.xclen, bi1, catxlen, catxp->szu.xclen);
+   --- */ 
+   /* since goes from high (left internal) bit to low if passed above right */ 
+   if (catbi >= bi1)
+    {
+     /* for low bit or scalar catel_bi is 0 not 1 */
+     *catel_bi = catbi - bi1; 
+
+     /* -- DBG remove ---
+     if (__debug_flg)
+      {
+       if (catxlen == 1) __msgexpr_tostr(__xs, catxp->lu.x);
+       else sprintf(__xs, "%s[%d]", __msgexpr_tostr(__xs2, catxp->lu.x), 
+        *catel_bi);
+       __dbg_msg(
+        "*** other side concat component %s width %d of concat size %d\n", 
+        __xs, catxlen, xp->szu.xclen);  
+      }
+     --- */
+     return(catxp->lu.x);
+    }
+  }
+ __arg_terr(__FILE__, __LINE__);
+ return(NULL);
+}
+
+/*
+ * given a tran channel lhs non concatenate expression get net and bit
+ *
+ * sets bi to -2 for other side out of this side range
+ * uses other side offset from low (right) to determine index
+ * this uses itree loc to get module for constant table
+ */
+extern struct net_t *__tranx_to_netbit(register struct expr_t *xp,
+ int32 fromr_bi, int32 *bi, struct itree_t *oside_itp)
+{
+ register struct net_t *np;
+ int32 ri1, ri2;
+
+ np = __find_tran_conn_np(xp);
+ if (xp->optyp == LSB)
+ {
+   __push_itstk(oside_itp);
+   *bi = __get_const_bselndx(xp);
+   __pop_itstk();
+   if (fromr_bi > 0) *bi = -2;
+   return(np);
+  }
+ if (xp->optyp == PARTSEL)
+  {
+   ri1 = __contab[xp->ru.x->lu.x->ru.xvi];
+   ri2 = __contab[xp->ru.x->ru.x->ru.xvi];
+   if (fromr_bi == -1) *bi = ri2;
+   else { *bi = ri2 + fromr_bi; if (*bi > ri1) *bi = -2;  }
+   return(np);
+  }
+ /* this side is 1 bit scalar */
+ if (!np->n_isavec)
+  {
+   *bi = -1;
+   if (fromr_bi > 0) *bi = -2;
+  }
+ else { if (fromr_bi >= np->nwid) *bi = -2; else *bi = fromr_bi;  }
+ return(np);
+}
+
+/*
+ * for every npp, add other vertex if needed and connect edge from vtxp
+ *
+ * SJM 07/27/01 - new algorithm that uses breadth first building 
+ * here if edge never seen in channel, aalloc and add vbip and put on
+ * future processing fifo
+ *
+ * npp is one that other side of need to have edges added
+ * vt1 itp always set, vt2 itp itree loc for other edge only if different
+ */
+static int32 add1_oside_edge(struct vtx_t *vtxp, struct net_pin_t *npp,
+ struct net_t *osnp, int32 osbi, int32 chanid, struct itree_t *vt1_itp,
+ struct itree_t *vt2_itp)
+{
+ register struct edge_t *ep1;
+ register struct vbinfo_t *osvbip;
+ int32 osbi2;
+ struct vtx_t *osvtxp;
+ struct traux_t *ostrap;
+ struct itree_t *itp;
+
+ ostrap = osnp->ntraux;
+ osbi2 = (osbi == -1) ? 0 : osbi;
+ /* for non per inst. itinum will be 0 */
+ /* not in channel - add it */
+ if (vt2_itp == NULL) itp = vt1_itp; else itp = vt2_itp;
+ if ((osvbip = ostrap->vbitchans[osnp->nwid*itp->itinum + osbi2])
+  == NULL)
+  {
+   /* add the new vertex, bld net to vtx conn */
+   osvbip = add_vtxtraux(osnp, osbi, chanid); 
+   ostrap->vbitchans[osnp->nwid*itp->itinum + osbi2] = osvbip;
+   osvtxp = osvbip->vivxp;
+   __chantab[chanid].numvtxs++;
+
+   /* SJM 09/11/00 - at edge add set diff wtypes if edge nets ntyp differ */
+   /* SJM 04/23/01 - need to handle wire type synonyms (tri=wire say) */
+   if (cnvt_tobase_ntyp(osnp->ntyp) != cnvt_tobase_ntyp(vtxp->vnp->ntyp))
+    __chantab[chanid].chan_diffwtyps = TRUE;
+
+   /* finally, add to future add from edges fifo list */
+   add_vtx_to_future_q(osvtxp, itp);
+  }
+ else osvtxp = osvbip->vivxp;
+ 
+ /* need to add 2 opposite direct edges */ 
+ ep1 = alloc_edge(npp);
+ /* SJM 08/26/00 - if vt2 itp nil, then no itree change on edges */
+ /* notice for cross inout ports always have itree loc change */
+ if (vt2_itp != NULL) ep1->edgoside_itp = vt2_itp;
+ ep1->ev2 = osvtxp;
+ ep1->enxt = vtxp->vedges;
+ vtxp->vedges = ep1;
+
+ /* DBG remove --
+ if (__debug_flg)
+  {
+   __push_itstk(vt1_itp);
+   __dbg_msg(
+    "!!! adding other side vertex %s and forward edge from %s:\n",
+    to_vtx(__xs, osvtxp), to_vtx(__xs2, vtxp));
+   -* --
+   prt_edge(vtxp, ep1, -1); 
+   -- *-
+   __pop_itstk();
+  }
+ --- */
+ return(TRUE);
+}
+
+/*
+ * routine to convert wire types to base
+ *
+ * used for finding mixed wire type chans that require relax
+ */
+static word32 cnvt_tobase_ntyp(word32 ntyp)
+{
+ switch (ntyp) {
+  case N_TRI: return(N_WIRE);
+  case N_TRIAND: return(N_WA);
+  case N_TRIOR: return(N_WO);
+  default: break;
+ }  
+ return(ntyp);
+}
+
+/*
+ * given a tran or tranif connecting port, find the net
+ *
+ * will never see concatenate here because xp is component of concat
+ */
+extern struct net_t *__find_tran_conn_np(struct expr_t *xp)
+{
+ struct net_t *np;
+
+ switch ((byte) xp->optyp) { 
+  case ID: case GLBREF: np = xp->lu.sy->el.enp; return(np);
+  case LSB: case PARTSEL: np = xp->lu.x->lu.sy->el.enp; return(np);
+  /* for opempty will be no npp */  
+  default: __case_terr(__FILE__, __LINE__); 
+ }
+ return(NULL);
+}
+
+/*
+ * routine to convert bid only same wire type channel to simple 
+ *
+ * SJM 04/23/01 - can process bid only channels by just going through
+ * list (key is that vtx list element contains itree loc for each one)
+ */
+static void chg_bidchan_to_vtxlist(struct chanrec_t *chanp)
+{
+ register struct edge_t *ep, *ep2;
+ /* DBG remove - int32 sav_mem_use; */
+ struct vtx_t *vtxp;
+ struct vtxlst_t *vtxlp;
+
+ /* free every vertex and its edge list */
+ /* build list of all vertices */
+ vtxp = chanp->chvxp; 
+ /* need to pass itree context since itstk may overflow, use call stack */
+ process_bid_vertices(chanp, vtxp, chanp->chvitp);
+
+ /* build the off list - use this to free */
+ add_vtx_to_offlist(vtxp);
+
+ for (vtxlp = __off_vtxlst_hdr; vtxlp != NULL; vtxlp = vtxlp->vtxnxt)
+  {
+   /* first free edge list */
+   for (ep = vtxlp->vtxp->vedges; ep != NULL;)
+    {
+     ep2 = ep->enxt;
+     __my_free((char *) ep, sizeof(struct edge_t)); 
+     ep = ep2;
+    }
+   /* SJM 08/08/01 - can't free vertices still used by iout channels */
+   /* ??? __my_free((char *) vtxlp->vtxp, sizeof(struct vtx_t)); */
+  }
+
+ /* DBG remove --
+ if (__switch_verbose)
+  {
+   register struct bidvtxlst_t *bvtxlp;
+   int32 chanid;
+
+   chanid = chanp - __chantab;
+   __cv_msg("-- chan %d (%d vertices): conversion freed %d bytes\n",
+    chanid, chanp->numvtxs, sav_mem_use - __mem_use); 
+  }
+ --- */
+
+ /* chan now stored as bid vtx list */
+ chanp->chvxp = NULL;
+ chanp->chvitp = NULL;
+ chanp->chan_no_vtxs = TRUE; 
+
+ /* then add entire off vtx list to end of vtx list free list */
+ if (__off_vtxlst_hdr != NULL)
+  {
+   __off_vtxlst_end->vtxnxt =  __vtxlst_freelst; 
+   __vtxlst_freelst = __off_vtxlst_hdr;
+  }
+ __off_vtxlst_hdr = __off_vtxlst_end = NULL;
+}
+
+/*
+ * add vertex and all connected to linear vertex list
+ */
+static void process_bid_vertices(struct chanrec_t *chanp, struct vtx_t *vtxp,
+ struct itree_t *vt1_itp)
+{
+ register struct edge_t *ep;
+ struct itree_t *oside_itp;
+
+ /* mark vertex visited and and add to list */ 
+ vtxp->vtx_mark = TRUE;
+ add_vtx_to_bidvtxlist(chanp, vtxp, vt1_itp);
+
+ for (ep = vtxp->vedges; ep != NULL; ep = ep->enxt)
+  {
+   if (ep->ev2->vtx_mark) continue;
+
+   /* SJM 04/23/01 - this moves to right other side edge itree loc */
+   if (ep->edgoside_itp != NULL) oside_itp = ep->edgoside_itp;
+   else oside_itp = vt1_itp;
+
+   process_bid_vertices(chanp, ep->ev2, oside_itp);
+  }
+}
+
+/*
+ * add a vertex to bid chan linear list
+ */
+static void add_vtx_to_bidvtxlist(struct chanrec_t *chanp, struct vtx_t *vtxp,
+ struct itree_t *vt1_itp)
+{
+ register struct bidvtxlst_t *bidvtxlp;
+
+ bidvtxlp = (struct bidvtxlst_t *) __my_malloc(sizeof(struct bidvtxlst_t));
+
+ bidvtxlp->vnp = vtxp->vnp;
+ bidvtxlp->vi1 = vtxp->vi1;
+ bidvtxlp->bidvtx_itp = vt1_itp;
+ bidvtxlp->bidvtxnxt = NULL;
+
+ /* must always put on end */
+ if (chanp->bid_vtxlp != NULL)
+  { bidvtxlp->bidvtxnxt = chanp->bid_vtxlp; chanp->bid_vtxlp = bidvtxlp; }
+ else chanp->bid_vtxlp = bidvtxlp;
+}
+
+/*
+ * allocate a tran graph edge (npp tran gate)
+ */
+static struct edge_t *alloc_edge(struct net_pin_t *npp)  
+{
+ struct edge_t *ep;
+
+ if (__edge_freelst != NULL)
+  { ep = __edge_freelst; __edge_freelst = __edge_freelst->enxt; }
+ else ep = (struct edge_t *) __my_malloc(sizeof(struct edge_t));
+
+ ep->enpp = npp;
+ ep->edgoside_itp = NULL;
+ ep->ev2 = NULL;
+ ep->enxt = NULL;
+ return(ep);
+}
+
+/*
+ * return T if bit inout only channel, has all same wire types
+ */
+static void chkchannel(struct chanrec_t *chanp)
+{
+ register struct edge_t *ep;
+ int32 bi, chanid, base;
+ struct vtx_t *vtxp;
+ struct traux_t *trap;
+ struct net_t *np;
+
+ vtxp = chanp->chvxp;
+ __push_itstk(chanp->chvitp);
+ np = vtxp->vnp;
+ /* DBG remove -- */
+ if ((trap = np->ntraux) == NULL) __misc_terr(__FILE__, __LINE__);
+ /* --- */ 
+ bi = vtxp->vi1;
+ if (bi == -1) bi = 0;
+ base = __inum*np->nwid;
+ chanid = trap->vbitchans[base + bi]->chan_id;
+ /* DBG remove -- */
+ if (&(__chantab[chanid]) != chanp) __misc_terr(__FILE__, __LINE__);
+ /* --- */ 
+ vtxp->vtx_mark = TRUE;
+
+ for (ep = vtxp->vedges; ep != NULL; ep = ep->enxt)
+  {
+   if (ep->ev2->vtx_mark) continue;
+   ep->ev2->vtx_mark = TRUE;
+   chkchan_edge(chanp, ep);
+  }
+ /* SJM 09/11/00 - not set ch typ even if this not called */
+ __pop_itstk();
+
+ /* off vertex marks, to be ready for next traversal */
+ off_bichan_marks(chanp);
+}
+
+/*
+ * routine to turn off all vertex marks for
+ */
+static void off_bichan_marks(struct chanrec_t *chanp) 
+{
+ register struct vtxlst_t *vtxlp;
+
+ add_vtx_to_offlist(chanp->chvxp);
+ 
+ /* turn of marks in all vertices on list */
+ for (vtxlp = __off_vtxlst_hdr; vtxlp != NULL; vtxlp = vtxlp->vtxnxt)
+  {
+   vtxlp->vtxp->vtx_mark = FALSE;
+   vtxlp->vtxp->vtx_mark2 = FALSE;
+  }
+
+ /* then add entire list to end of free list */
+ if (__off_vtxlst_hdr != NULL)
+  {
+   __off_vtxlst_end->vtxnxt =  __vtxlst_freelst; 
+   __vtxlst_freelst = __off_vtxlst_hdr;
+  }
+ __off_vtxlst_hdr = __off_vtxlst_end = NULL;
+} 
+
+/*
+ * add all vertices to list using vtx mark2 for cutting cyles
+ * also used as first step in freeing channel
+ */
+static void add_vtx_to_offlist(struct vtx_t *vtxp)
+{
+ register struct vtxlst_t *vtxlp;
+ register struct edge_t *ep;
+
+ /* alloc and add to list */
+ if (__vtxlst_freelst == NULL)
+  vtxlp = (struct vtxlst_t *) __my_malloc(sizeof(struct vtxlst_t));
+ else
+  {
+   vtxlp = __vtxlst_freelst;
+   __vtxlst_freelst = __vtxlst_freelst->vtxnxt;
+  }
+ /* add it */
+ vtxlp->vtxp = vtxp;
+ vtxlp->vtxnxt = NULL;
+ vtxp->vtx_mark2 = TRUE; 
+
+ /* put on end */
+ if (__off_vtxlst_end != NULL)
+  { __off_vtxlst_end->vtxnxt = vtxlp; __off_vtxlst_end = vtxlp; }
+ else __off_vtxlst_end = __off_vtxlst_hdr = vtxlp;
+
+ /* all all other side vertices of this one's edges */ 
+ for (ep = vtxp->vedges; ep != NULL; ep = ep->enxt)
+  {
+   if (ep->ev2->vtx_mark2) continue;
+
+   add_vtx_to_offlist(ep->ev2);
+  }
+}
+
+/*
+ * check edge and vertex on other side and update chanp fields
+ * 09/11/00 - SJM - DBG now only called if debug flag on
+ */
+static void chkchan_edge(struct chanrec_t *chanp, struct edge_t *ep)
+{
+ struct vtx_t *vtxp;
+ struct net_t *np;
+ struct edge_t *ep2;
+
+ vtxp = ep->ev2;
+ np = vtxp->vnp;
+ /* DBG remove -- */
+ if (np->ntraux == NULL) __misc_terr(__FILE__, __LINE__);
+ if (chanp->chvxp->vnp->n_stren != np->n_stren)
+  __misc_terr(__FILE__, __LINE__);
+ /* --- */ 
+ if (chanp->chvxp->vnp->ntyp != np->ntyp)
+  {
+   if (chanp->chan_diffwtyps != TRUE) __misc_terr(__FILE__, __LINE__); 
+  }
+ 
+ /* depth first process vertices edges */
+ /* back edge vertex already part of processed tree */
+ for (ep2 = vtxp->vedges; ep2 != NULL; ep2 = ep2->enxt)
+  {
+   if (ep2->ev2->vtx_mark) continue;
+   ep2->ev2->vtx_mark = TRUE;
+   chkchan_edge(chanp, ep2);
+  }
+}
+
+/*
+ * finished with tran soft drivers remove from in tran channel
+ * np list in traux
+ *
+ * know one traux per net with any bits in tran channel
+ * SJM 05/15/99 - move tran channel npps to traux - needed for PLI
+ */
+static void save_bidandtran_npps(void)
+{
+ register struct net_pin_t *npp;
+ register int32 ni;
+ register struct mod_t *mdp;
+ register struct net_t *np;
+ struct net_pin_t *last_npp, *npp2;
+
+ for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
+  {
+   if (mdp->mnnum == 0) continue;
+   for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+    {  
+     for (last_npp = NULL, npp = np->ndrvs; npp != NULL;)
+      {
+       /* save next field */
+       npp2 = npp->npnxt;
+       if (npp->npntyp == NP_BIDMDPRT || npp->npntyp == NP_BIDICONN
+        || npp->npntyp == NP_TRAN) 
+        {
+         /* link out but pointed to by graph edges so cannot free */
+         if (last_npp == NULL) np->ndrvs = npp->npnxt;
+         else last_npp->npnxt = npp->npnxt;
+
+         /* and link onto front of tran channel npp list in traux */
+         /* for first one, sets nil then it migrates to end */ 
+         npp->npnxt = np->ntraux->tran_npps;
+         np->ntraux->tran_npps = npp;
+        }
+       else last_npp = npp; 
+       npp = npp2;
+      }
+    }
+  }
+}
+
+/*
+ * ROUTINES TO EVALUATE AND STORE TRAN CHANNEL AND INOUT WIRE GRAPHS
+ */
+
+/*
+ * evaluate stren tran channels including inouts during initialization
+ * 
+ * non stren wires do not need to be evaluated since z unless driver
+ * causes change but when initializing driver will cause re-eval 
+ * for rtran since everything z to start attenuation can't go weaker than z 
+ *
+ * also since any driver change will cause trnva change, can use initialized
+ * values do not need to reevaluate drivers
+ *
+ * must do for every instance of modules
+ * notice evaluating each channel (all vertices) only once
+ * LOOKATME - for now initializing all channels, but think only some needed
+ * maybe not since need all trans for sure here and if inout only has
+ * pull on it will never be evaluated from gate evaluation
+ */
+extern void __init_all_trchans(void) 
+{
+ register int32 ii;
+ int32 tot_tran_vtxs, tot_bid_vtxs, num_tran_done, num_bid_done;
+ struct chanrec_t *chanp;
+ struct vtxlst_t *vtxlp, *vtxlp2;
+
+ if (__switch_verbose && __nxt_chan_id > 0)
+  {
+   __cv_msg("  SWITCH: begin switch channel initialization (%d channels).\n",
+    __nxt_chan_id);
+  }
+
+ /* if no tran in design nothing to do here */
+ if (__nxt_chan_id == 0) return;
+
+ tot_tran_vtxs = tot_bid_vtxs = 0;
+ num_tran_done = num_bid_done = 0;
+ /* first initialize all tran(if) chans using relaxation of entire chan */ 
+ for (ii = 0; ii < __nxt_chan_id; ii++)
+  {
+   chanp = &(__chantab[ii]);
+   if (chanp->chtyp == TRPROC_STWTYPBID || chanp->chtyp == TRPROC_TRAN)
+    {
+     init_sttranif_chan(chanp);
+     tot_tran_vtxs += chanp->numvtxs;
+     num_tran_done++;
+    }
+   else
+    {
+     if (chanp->chtyp == TRPROC_BID) eval_assign_bid_chan(chanp);
+     else eval_assign_stbid_chan(chanp);
+     tot_bid_vtxs += chanp->numvtxs;
+     num_bid_done++;
+    }
+
+   /* SJM only emit message if switch verbose and some channels inited */
+   if (__switch_verbose && ((num_tran_done + num_bid_done) % 5000) == 0)
+    {
+     double d1, d2;
+
+     d1 = 100.0*(((double) num_tran_done)/((double) __num_switch_chans));
+     d2 = 100.0*(((double) num_bid_done)
+      / ((double) __nxt_chan_id - __num_switch_chans));
+     __cv_msg(
+     "  SWITCH: %d (%.2f%%) tran and %d (%.2f%%) inout channels completed.\n",
+     num_tran_done, d1, num_bid_done, d2);
+    }
+  } 
+ if (__switch_verbose)
+  { 
+   if (__num_switch_chans == 0)
+    { __cv_msg("  SWITCH: design contains no tran(if) switch channels.\n"); }
+   else
+    {
+     __cv_msg(
+      "  SWITCH: tran channels initialized (%d containing %d nodes in design).\n",
+      __num_switch_chans, tot_tran_vtxs);
+    }
+   if (__num_switch_chans == __nxt_chan_id)
+    { __cv_msg("  SWITCH: design contains no inout switch channels.\n"); }
+   else
+    {
+     __cv_msg(
+      "  SWITCH: inout channels initialized (%d containing %d nodes in design).\n",
+      __nxt_chan_id - __num_switch_chans, tot_bid_vtxs); 
+    }
+  }
+
+ /* when done with initialization full relax, reclaim storage */
+ /* since lists will be much shorter from now on */
+ for (vtxlp = __vtxlst_freelst; vtxlp != NULL;)
+  {
+   vtxlp2 = vtxlp->vtxnxt;
+   __my_free((char *) vtxlp, sizeof(struct vtxlst_t));
+   vtxlp = vtxlp2;
+  }
+ __vtxlst_freelst = NULL;
+}
+
+/*
+ * initialize entire tran(if) channel at once (relax the whole thing)
+ */
+static void init_sttranif_chan(struct chanrec_t *chanp)
+{
+ /* add all vertices to st vtx tab lists indexed by low stren */
+ /* starts with the one random chan vertex (since digraph any works) */
+ __push_itstk(chanp->chvitp);
+ init_add_vtx_and_subtree(chanp->chvxp, chanp->chvitp);
+ __pop_itstk();
+
+ /* now that all vertices in st vtx tab, turn off marks so can be used again */
+ /* if needed - mostly for dumping channels */
+ /* works in st vtx tab - know all vertices in it */
+ off_stvtxtab_marks();
+ 
+ stchan_trif_relax();
+
+ /* final step, assign all changed vertices */
+ if (__chg_vtxlst_hdr != NULL) assign_chged_vtxs();
+}
+
+/*
+ * routine to add all vertices to st vtx tab lists indexed by low stren
+ * also set internal tran vertex value from net(bit) driving value
+ * works because force release not possible before here
+ *
+ * NOTICE - this must be called after all normal initialization
+ * LOOKATME - think it pushing does not work for inout port edges
+ */
+static void init_add_vtx_and_subtree(struct vtx_t *vtxp,
+ struct itree_t *vt1_itp)
+{
+ register struct edge_t *ep;
+ int32 bi, inum;
+ word32 vtxval, lowst, st0, st1;
+ struct vtxlst_t *vtxlp;
+ struct net_t *np; 
+ struct itree_t *oside_itp;
+
+ np = vtxp->vnp;
+ bi = vtxp->vi1;
+ bi = (bi == -1) ? 0 : bi;
+
+ inum = vt1_itp->itinum;
+ /* save current value of net as old vtx value */
+ vtxp->old_vtxval = np->nva.bp[inum*np->nwid + bi];
+
+ /* get switch contribution from hard driver's value */
+ vtxval = (word32) np->ntraux->trnva.bp[inum*np->nwid + bi];
+
+ /* and use as first new channel value guess */
+ vtxp->new_vtxval = (byte) vtxval;
+ if (vtxval == ST_SUPPLY0 || vtxval == ST_SUPPLY1) vtxp->vtx_supply = TRUE;
+
+ /* get low strength */
+ st1 = (vtxval >> 2) & 0x7;
+ st0 = (vtxval >> 5) & 0x7;
+ lowst = (int32) ((st1 < st0) ? st1 : st0);
+
+ if (__vtxlst_freelst == NULL)
+  vtxlp = (struct vtxlst_t *) __my_malloc(sizeof(struct vtxlst_t));
+ else
+  {
+   vtxlp = __vtxlst_freelst;
+   __vtxlst_freelst = __vtxlst_freelst->vtxnxt;
+  }
+ vtxlp->vtxp = vtxp;
+ vtxlp->vtx_itp = vt1_itp;
+ vtxlp->vtxnxt = NULL;
+ if (__stvtxtabend[lowst] != NULL)
+  { __stvtxtabend[lowst]->vtxnxt = vtxlp; __stvtxtabend[lowst] = vtxlp; }
+ else __stvtxtab[lowst] = __stvtxtabend[lowst] = vtxlp;
+
+ vtxp->vtx_mark = TRUE;
+ __num_switch_vtxs_processed++;
+
+ /* DBG remove -- */ 
+ if (__debug_flg && __ev_tracing)
+  {
+   __dbg_msg("** vertex %s.%s level %d added to perturb list\n",
+    __msg2_blditree(__xs, vtxlp->vtx_itp), to_vtx(__xs2, vtxp), lowst);
+  }
+
+ for (ep = vtxp->vedges; ep != NULL; ep = ep->enxt)
+  {
+   if (ep->ev2->vtx_mark) continue;
+   
+   /* SJM - 05/21/01 - compute oside edge and use call stack since itstk */
+   /* not deep enough */
+   if (ep->edgoside_itp != NULL) oside_itp = ep->edgoside_itp;
+   else oside_itp = vt1_itp;
+   
+   init_add_vtx_and_subtree(ep->ev2, oside_itp);
+  }
+}
+
+/*
+ * routine to turn off all mark in vertices in st vtx tab
+ *
+ * needed to save marking memory (8 byte per vtx) and now uses just 2 bits 
+ * but need to build and free list of all vertices in channel when done
+ * 
+ * done after all verties are added to tab for intial relax - since marks
+ * not needed in relax can turn off using full st vtx tab
+ */
+static void off_stvtxtab_marks(void)
+{
+ register int32 si;
+ register struct vtxlst_t *vtxlp;
+ 
+ for (si = 7; si >= 0; si--)
+  {
+   for (vtxlp = __stvtxtab[si]; vtxlp != NULL; vtxlp = vtxlp->vtxnxt)
+    {
+     vtxlp->vtxp->vtx_mark = FALSE;
+     vtxlp->vtxp->vtx_mark2 = FALSE;
+    }
+  }
+}
+
+/*
+ * TOP LEVEL ROUTINES TO EVAL TRAN CHANNEL
+ */
+
+/*
+ * evaluate tran channels bit by bit - process for exactly one itree loc.
+ *
+ * bits may be part of empty tran channel (no trans or inouts on chan)
+ * in which case just store/schedule the trnva hard driver value
+ *
+ * for tran or inout, some hard driver (bid. tran chan in) must have
+ * changed to cause evaluation of channel, except for initialization,
+ * any fi>1 eval. goes through here if wire in tran channel
+ */
+extern void __eval_tran_bits(register struct net_t *np)
+{
+ register int32 bi;
+ int32 base;
+ word32 nav, nbv;
+ struct traux_t *trap;
+ struct vbinfo_t *vbip;
+ struct chanrec_t *chanp;
+
+ /* SJM 04/11/01 - can't do incremental relaxation until wire init done */
+ if (__wire_init) return;
+
+ trap = np->ntraux;
+ /* SJM 04/23/01 - all channels now per inst, no extra cost for 1 inst mod */
+ base = __inum*np->nwid;
+
+ /* all others are per bit */
+ for (bi = np->nwid - 1; bi >= 0; bi--) 
+  {
+   /* bit of wire is not really in any tran channel - treated as 1 wire */
+   /* tran channel - just access stored internal hard trnva value */
+   if ((vbip = trap->vbitchans[base + bi]) == NULL)
+    {
+     /* 03/15/00 - SJM - if forced getting drivers ok since st vtx inhibits */
+     /* actual assign */
+     if (np->n_stren)
+      {
+       nav = (word32) trap->trnva.bp[__inum*np->nwid + bi];
+       /* really unused but passing it */
+       nbv = 0;
+      }
+     else ld_vtx_netbit(&nav, &nbv, np, bi);
+     /* notice if strength, nbv not used */
+     st_vtx_netbit(np, bi, nav, nbv);
+    }
+   else
+    {
+     chanp = &(__chantab[vbip->chan_id]);
+     /* BEWARE when this bit on, vb info vtx field invalid (can't use) */
+     if (chanp->chan_no_vtxs)
+      {
+       if (chanp->chtyp == TRPROC_BID) eval_assign_bid_chan(chanp);
+       else eval_assign_stbid_chan(chanp);
+      }
+     /* real tran switch chan - use change vertex to perturb and relax chan */
+     else eval_update_1w_tranchan(vbip->vivxp);
+    } 
+  }
+}
+
+/*
+ * evaluate one tran channel bit - version for path dest. event 
+ * so know always per inst form
+ * just one bit part of all bits routine
+ */
+extern void __eval_tran_1bit(register struct net_t *np, register int32 bi)
+{
+ int32 base;
+ word32 nav, nbv;
+ struct chanrec_t *chanp;
+ struct traux_t *trap;
+ struct vbinfo_t *vbip;
+
+ /* SJM 04/11/01 - can't do incremental relaxation until wire init done */
+ if (__wire_init) return;
+
+ trap = np->ntraux;
+ /* SJM - 12/19/00 - new using 1 bit form in many place so must set */ 
+ /* per instance form because if all in one inst. not per inst*/
+ base = __inum*np->nwid;
+
+ /* bit of wire is not really in any tran channel - treated as 1 wire */
+ /* tran channel - just access stored internal hard trnva value */
+ if ((vbip = trap->vbitchans[base + bi]) == NULL)
+  {
+   /* 03/15/00 - SJM - if forced getting drivers ok since st vtx inhibits */
+   /* actual assign */
+   if (np->n_stren)
+    {
+     nav = (word32) trap->trnva.bp[__inum*np->nwid + bi];
+     /* really unused but passing it */
+     nbv = 0;
+    }
+   else ld_vtx_netbit(&nav, &nbv, np, bi);
+   /* notice if strength, nbv not used */
+   st_vtx_netbit(np, bi, nav, nbv);
+  }
+ else
+  {
+   chanp = &(__chantab[vbip->chan_id]);
+   /* BEWARE when this bit on, vb info vtx field invalid (can't use) */
+   if (chanp->chan_no_vtxs)
+    {
+     if (chanp->chtyp == TRPROC_BID) eval_assign_bid_chan(chanp);
+     else eval_assign_stbid_chan(chanp);
+    }
+   /* real tran switch chan - use change vertex to perturb and relax chan */
+   else eval_update_1w_tranchan(vbip->vivxp);
+  } 
+}
+
+/*
+ * update tran and/or inout channel changed wire hard drivers (chan ins)
+ * returns T if hard drivers of wire changed, F if unchanged
+ *
+ * called from target (definition) changed instance 
+ * for special wires (stren only) such as supply0 mdr load use wire stren
+ * this only changes entire nets trnva per instance hard drivers
+ * update the hard driver for this net-instance
+ *
+ * know driver of np changed, but no other drivers therefore
+ * only need to update hard drivers for the one net but entire channel
+ * anywhere in it can change - must update all of wire
+ * if no hard driver change, returns F, channel cannot change
+ * if only conducting state of tranif change no need to eval. driver
+ * but must always re-eval all chan wires
+ *
+ * notice for rare bits of wire that are not part of tran channel
+ * they are part of empty tran channel and can just store the saved
+ * trnva value - since must eval. entire wire drivers will have those bits
+ * i.e. this is not bit by bit
+ */
+extern int32 __update_tran_harddrvs(struct net_t *np)
+{
+ register byte *sbp, *sbp2;
+ register struct xstk_t *xsp, *xsp2;
+
+ sbp = NULL;
+ if (np->n_stren)
+  {
+   /* this will make chan wire section of input drivers have wire type */
+   /* i.e. supply will probably override its drivers */
+   xsp = __stload_mdrwire(np);
+   sbp = (byte *) xsp->ap;
+   /* SJM - 03/15/01 - even if forced wtill need to update hard drvrs */
+   /* in case ever released - just do not use them when force in effect */
+   sbp2 = &(np->ntraux->trnva.bp[__inum*np->nwid]);
+
+   /* if this is path dest. and part of inout tran channel, must sched */  
+   /* change to internal stored hard driver values */
+   /* some bits may need immed. assign - routine handles updating tran chan */
+   if (np->iotyp == IO_BID && np->n_isapthdst && !__wire_init)
+    {
+     stren_schd_bidpthdrvrs(np, sbp, sbp2);
+     __pop_xstk();
+     /* for any real changes this re-evals 1 bit of channel */
+     /* therefore return F to stop another chan re-eval and store vtx */
+     return(FALSE);
+    }
+   /* SJM 11/24/00 - for path destinations can't eliminate schedule using */ 
+   /* current switch channel state because there may be pending event that */
+   /* requires inertial rescheduling */
+
+   /* SJM 12/13/00 malloc lib fails when bcmp of 1 byte scalar */
+   if (np->nwid == 1)
+    {
+     if (sbp[0] != sbp2[0]) sbp2[0] = sbp[0]; 
+     goto chg;
+   }
+
+   /* if all changed drivers (tran channel input) same, nothing to do */
+   if (memcmp(sbp, sbp2, np->nwid) == 0) goto no_chg;
+
+   /* update this wire drvrs (chan in sect), copy 2nd arg is dest. */
+   memcpy(sbp2, sbp, np->nwid);
+   /* now done with sbp and xsp */ 
+   goto chg; 
+  }
+
+ xsp = __load_mdrwire(np);
+ /* but must update driving value fron tran channel of xmr from inst */
+ push_xstk_(xsp2, np->nwid);
+ __ld_perinst_val(xsp2->ap, xsp2->bp, np->ntraux->trnva, np->nwid);
+
+ /* some bit changed update or schedule path dest. per bit channels */
+ if (np->iotyp == IO_BID && np->n_isapthdst && !__wire_init)
+  {
+   schd_bidpthdrvrs(np, xsp, xsp2);
+   __pop_xstk();
+   __pop_xstk();
+   /* for any real changes this re-evals 1 bit of channel */
+   /* therefore return F to stop another chan re-eval and store vtx */
+   return(FALSE);
+  }
+
+ /* SJM 11/24/00 - also for non stren case, must always use inertial */ 
+ /* rescheduling on inout paths */
+ if (np->nwid <= WBITS)
+  {
+   if (xsp->ap[0] == xsp2->ap[0] && xsp->bp[0] == xsp2->bp[0]) goto no_chg;
+  }
+ else
+  {
+   if (cmp_vval_(xsp->ap, xsp2->ap, np->nwid) == 0
+    && cmp_vval_(xsp->bp, xsp2->bp, np->nwid) == 0) goto no_chg;
+  }
+
+ /* update ins (drvs) for this tran chan wire section */ 
+ __st_perinst_val(np->ntraux->trnva, np->nwid, xsp->ap, xsp->bp);
+chg:
+ if (__ev_tracing)
+  {
+   char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+   if (np->n_stren)
+    { strcpy(s1, " strength"); __st_regab_tostr(s2, sbp, np->nwid); }
+   else
+    {
+     strcpy(s1, "");
+     __regab_tostr(s2, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE);
+    }
+   __tr_msg(
+    "-- driver (hard tran input) of%s channel %s %s changed new value %s\n",  
+    s1, __to_wtnam(s3, np), np->nsym->synam, s2);
+  }
+ __pop_xstk();
+ if (!np->n_stren) __pop_xstk();
+ return(TRUE);
+
+no_chg:
+ if (__ev_tracing)
+  {
+   char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+   if (np->n_stren)
+    { strcpy(s1, " strength"); __st_regab_tostr(s2, sbp, np->nwid); }
+   else
+    {
+     strcpy(s1, "");
+     __regab_tostr(s2, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE);
+    }
+   __tr_msg(
+    "-- a driver (tran channel input) of%s channel %s %s changed but value %s unchanged\n",  
+    s1, __to_wtnam(s3, np), np->nsym->synam, s2);
+  }
+ __pop_xstk();
+ if (!np->n_stren) __pop_xstk();
+ return(FALSE);
+}
+
+/*
+ * schedule stren inout channel path destination hard drivers and channel
+ * some bits may not have changed or need immediate assign and chan update
+ */
+static void stren_schd_bidpthdrvrs(struct net_t *np, byte *drv_sbp, 
+ byte *trnva_sbp)
+{
+ register int32 bi; 
+ int32 nd_chan_upd;
+ i_tev_ndx *itevpi;
+ struct rngdwir_t *dwirp; 
+
+ dwirp = np->nu.rngdwir;
+ itevpi = &(dwirp->wschd_pbtevs[__inum*np->nwid]);
+ for (bi = 0; bi < np->nwid; bi++)
+  {
+   __new_gateval = (word32) drv_sbp[bi];
+   __old_gateval = (word32) trnva_sbp[bi];
+
+   if (__ev_tracing) nd_chan_upd = evtr_schd_1bitpthdrvr(np, bi, itevpi);
+   else nd_chan_upd = schd_1bitpthdrvr(np, bi, itevpi);
+
+   if (nd_chan_upd)
+    {
+     /* update stren tran driver and re-eval and store channel new value */ 
+     trnva_sbp[bi] = (byte) __new_gateval;
+     __eval_tran_1bit(np, bi);
+    }
+  }
+}
+
+/*
+ * schedule non stren inout channel path dest. hard drivers and channel
+ * some bits may not have changed or need immediate assign and chan update
+ */
+static void schd_bidpthdrvrs(struct net_t *np, struct xstk_t *drv_xsp,
+ struct xstk_t *trnva_xsp)
+{
+ register int32 bi; 
+ register word32 tmp;
+ int32 nd_chan_upd;
+ i_tev_ndx *itevpi;
+ struct rngdwir_t *dwirp; 
+
+ dwirp = np->nu.rngdwir;
+ itevpi = &(dwirp->wschd_pbtevs[__inum*np->nwid]);
+ for (bi = 0; bi < np->nwid; bi++)
+  {
+   tmp = rhsbsel_(drv_xsp->bp, bi);
+   __new_gateval = (tmp << 1) | (rhsbsel_(drv_xsp->ap, bi));
+   tmp = rhsbsel_(trnva_xsp->bp, bi);
+   __old_gateval = (tmp << 1) | (rhsbsel_(trnva_xsp->ap, bi));
+
+   if (__ev_tracing) nd_chan_upd = evtr_schd_1bitpthdrvr(np, bi, itevpi);
+   else nd_chan_upd = schd_1bitpthdrvr(np, bi, itevpi);
+
+   if (nd_chan_upd)
+    {
+     /* update stren tran driver and re-eval and store channel new value */ 
+     __lhsbsel(trnva_xsp->ap, bi, (__new_gateval & 1L));
+     __lhsbsel(trnva_xsp->bp, bi, ((__new_gateval >> 1) & 1L));
+     __st_perinst_val(np->ntraux->trnva, np->nwid, trnva_xsp->ap,
+      trnva_xsp->bp);
+     __eval_tran_1bit(np, bi);
+    }
+  }
+}
+
+/*
+ * schedule 1 bit path bidirect driver
+ *
+ * show cancel e analysis including non inout path distributed delay
+ *
+ * this works for both strength 8 bit nval and oval and non strength
+ * if scalar bi must be 0 (i.e. biti can not be -1)
+ * nval is new value to schedule change to, old value is current wire value
+ *
+ * old and new gate values in globals - maybe changed since caller saves
+ */
+static int32 schd_1bitpthdrvr(struct net_t *np, register int32 biti,
+ i_tev_ndx *itevpi)
+{
+ register word32 nval, oval;
+ word32 is_stren;
+ word64 schtim;
+ i_tev_ndx tevpi;
+ struct rngdwir_t *dwirp; 
+ struct pthdst_t *pdp;
+ struct tev_t *tevp;
+
+ dwirp = np->nu.rngdwir;
+ tevpi = itevpi[biti];
+
+ /* DBG remove ---
+ if (tevpi != -1 && __tevtab[tevpi].tetyp != TE_BIDPATH)
+  __misc_terr(__FILE__, __LINE__);
+ --- */
+
+ nval = __new_gateval;
+ oval = __old_gateval; 
+
+ /* since always use last changed value, if last same as current */
+ /* because gate style glitch nothing to do since already right value */   
+ if (tevpi == -1 && nval == oval)
+  return(FALSE);
+
+ is_stren = np->n_stren;
+
+ /* possible for some bits to not be path destinations */
+ if (oval != nval)
+  {
+   if ((pdp = __get_path_del(dwirp, biti, &schtim)) == NULL)
+    return(TRUE);   
+  }
+ else { pdp = NULL; schtim = 0ULL; }
+
+ /* special case 0 - distributed delay longer - immediate assign */
+ /* normal cause is path (probably from multiple input final driving gate) */
+ /* that has not path delay on it - this may be ok */
+ if (pdp != NULL && schtim <= __simtime)
+  {
+   /* problem with modeling - distributed delay longer than path */
+   if (!__no_informs) __emit_path_distinform(np, pdp, &__pdmindel);
+
+   /* modeling anomally style spike possible - know immed. assign earlier */ 
+   if (tevpi != -1)
+    {
+     /* calls here take ptr not index */
+     tevp = &(__tevtab[tevpi]); 
+     if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+      {
+       __emit_path_pulsewarn(pdp, tevp, &__simtime, &(tevp->etime),
+        "distributed longer or no path delay", is_stren);
+      }
+     /* always cancel pending */
+     __cancel_1wev(tevp);
+     itevpi[biti] = -1;
+
+     /* this is same for on detect and on event */
+     if (__show_cancel_e)
+      {
+       /* this is special case where immediate assign must be to x */ 
+       /* and cancel future event that can be scheduled for now */
+set_on_detect_x:
+       /* set global causes use in tran channel re-eval */
+       if (is_stren) __new_gateval = (word32) ST_STRONGX;
+       else __new_gateval = (word32) 3;
+       return(TRUE);
+      }
+     /* if no show canceled e, just assign later */  
+    }
+   /* no schedule, distributed longer - global new gateval right and used */
+   return(TRUE);
+  }
+
+ /* no pending event */
+ /* SJM 11/24/00 - know if no pending event will have path */
+ if (tevpi == -1)
+  {
+   /* because no pending event must be different */
+   __schedule_1wev(np, biti, TE_BIDPATH, __pdmindel, schtim, nval,
+    itevpi, FALSE);
+   return(FALSE);
+  }    
+ /* pending event */
+ tevp = &(__tevtab[tevpi]); 
+ /* new and old same but know scheduled different - classic pulse/glitch */
+ if (nval == oval)
+  {
+   /* have delay to use to select pa0th */  
+   if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+    {
+     __emit_path_samewarn(np, biti, tevp, &(tevp->etime), "pulse",
+      is_stren);
+    }
+   
+   /* if spike, suppress future but schedule to x at currently scheduled */
+   if (__show_cancel_e)
+    {
+     if (__showe_onevent)
+      { tevp->outv = (is_stren) ? ST_STRONGX : 3; return(FALSE); }
+
+     __cancel_1wev(tevp);
+     itevpi[biti] = -1;
+     goto set_on_detect_x;
+    }
+   /* remove pulse */
+   __cancel_1wev(tevp);
+   itevpi[biti] = -1;
+   return(FALSE);
+  }
+
+ /* now know pdp set */
+
+ /* new schedule to same value case */
+ /* here delay can be different because different path selected */
+ /* and maybe other reasons */
+ /* done silently here - trace message only below */
+ if (tevp->outv == (byte) nval) return(FALSE);
+
+ /* inertial reschedule */
+ if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+  __emit_path_pulsewarn(pdp, tevp, &(tevp->etime), &schtim,
+   "inout unstable", is_stren);   
+
+ /* easy show cancel (set to x case) - no new event may or may not switch */
+ if (__show_cancel_e)
+  {
+   /* LOOKATME - maybe need to check old tevp and new schd time and if 2nd */
+   /* input change results in earlier edge cancel and schedule earlier */
+   if (__showe_onevent)
+    { tevp->outv = (is_stren) ? ST_STRONGX : 3; return(FALSE); }
+
+   __cancel_1wev(tevp);
+   itevpi[biti] = -1;
+   goto set_on_detect_x;
+  }
+ /* inertial reschedule, this handles cancel if needed */
+ __reschedule_1wev(tevpi, nval, __pdmindel, schtim, itevpi);
+ return(FALSE);
+}
+
+/*
+ * tracing version of schedule stren 1 bit inout channel path dest drivers
+ *
+ * show cancel e analysis including non inout path distributed delay
+ *
+ * this works for both strength 8 bit nval and oval and non strength
+ * if scalar bi must be 0 (i.e. biti can not be -1)
+ * nval is new value to schedule change to, old value is current wire value
+ *
+ * old and new gate values in globals - maybe changed since caller saves
+ */
+static int32 evtr_schd_1bitpthdrvr(struct net_t *np, register int32 biti,
+ i_tev_ndx *itevpi)
+{
+ register word32 nval, oval;
+ i_tev_ndx tevpi;
+ word32 is_stren;
+ word32 outval;
+ word64 schtim, distdel, tevptim;
+ struct rngdwir_t *dwirp; 
+ struct pthdst_t *pdp;
+ struct spcpth_t *pthp;
+ struct tev_t *tevp;
+ char s1[RECLEN], s2[RECLEN], vs1[10], vs2[10], vs3[10];
+
+ is_stren = np->n_stren;
+ dwirp = np->nu.rngdwir;
+ tevpi = itevpi[biti];
+ nval = __new_gateval;
+ oval = __old_gateval; 
+
+ if (tevpi != -1)
+  {
+   /* DBG remove --- */
+   if (__tevtab[tevpi].tetyp != TE_BIDPATH) __misc_terr(__FILE__, __LINE__); 
+   /* --- */
+   strcpy(s1, " (pending event)");
+  }
+ else strcpy(s1, "");
+
+ /* if no change and do not need schedule time for cancel, done */
+ __tr_msg("-- path delay inout destination %s driver change%s now %s:\n",
+  __to_evtrwnam(__xs, np, biti, biti, __inst_ptr), s1,
+  __to_timstr(__xs2, &__simtime));
+
+ /* since always use last changed value, if last same as current */
+ /* because gate style glitch nothing to do since already right value */   
+ if (tevpi == -1 && nval == oval)
+  {
+   __tr_msg(" PATHDEL, NOCHG <OV=%s> at %s\n", __to_vnam(vs1, is_stren, nval),
+    __to_timstr(__xs, &__simtime));
+   return(FALSE);
+  }
+
+ /* possible for some bits to not be path desitinations - just immed assign */
+ if (nval != oval)
+  {
+   if ((pdp = __get_path_del(dwirp, biti, &schtim)) == NULL)   
+    {
+     __tr_msg(" BIT %d NOT PATH DEST: IMMED ASSIGN <OV=%s, NV=%s>\n",
+      biti,__to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren, nval));
+     return(TRUE);
+    } 
+   pthp = pdp->pstchgp->chgu.chgpthp;
+   __tr_msg(" PATH (at line %s) SRC CHG TIME %s\n",
+    __bld_lineloc(s1, pthp->pthsym->syfnam_ind, pthp->pthsym->sylin_cnt),
+    __to_timstr(__xs, &__pdlatechgtim));
+  }
+ else { pdp = NULL; schtim = 0ULL; }
+
+ /* special case 0 - distributed delay longer - immediate assign */
+ if (schtim <= __simtime)
+  {
+   /* problem with modeling - distributed delay longer than path */
+   /* or changed path has no path delay */
+   if (!__no_informs && pdp != NULL)
+     __emit_path_distinform(np, pdp, &__pdmindel);
+
+   /* modeling anomally style spike possible - know immed. assign earlier */ 
+   if (tevpi != -1)
+    {
+     /* most routines here need ptr to event not index */
+     tevp = &(__tevtab[tevpi]); 
+     if (__warn_cancel_e && !__no_warns && !__em_suppr(592) && pdp != NULL)
+      __emit_path_pulsewarn(pdp, tevp, &__simtime, &(tevp->etime),
+       "distributed longer or no path delay", is_stren);
+
+     /* always cancel pending */
+     outval = (word32) tevp->outv;
+     tevptim = tevp->etime;
+     /* always cancel pending */
+     __cancel_1wev(tevp);
+     itevpi[biti] = -1;
+
+     /* this is same for on detect and on event since immed. assign */
+     if (__show_cancel_e)
+      {
+       /* this is special case where immediate assign must be to x */ 
+       /* and cancel future event that can be scheduled for now */
+       __tr_msg(
+        " INOUT PATH, DIST DELAY PULSE <OV=%s, OSV=%s at %s NV=%s SHOWING X FROM NOW>\n",
+        __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren, outval),
+        __to_timstr(s1, &tevptim), __to_vnam(vs3, is_stren, nval));
+set_on_detect_x:
+       if (is_stren) __new_gateval = (word32) ST_STRONGX;
+       else __new_gateval = (word32) 3;
+       return(TRUE);
+      }
+     __tr_msg(
+      " INOUT PATH, DIST DELAY PULSE <OV=%s, OSV=%s at %s - NV=%s ASSIGN AND CANCEL>\n",
+      __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren,
+      (word32) tevp->outv), __to_timstr(s1, &(tevp->etime)),
+      __to_vnam(vs3, is_stren, nval));
+     /* no schedule, distributed delay longer - new gate val used for chan. */
+     return(TRUE); 
+    }
+
+   /* know if no pending event, pdp not nil */
+   /* no pending event store - know must be different */
+   distdel = __simtime - __pdlatechgtim;
+   __tr_msg(
+    " DIST DELAY %s LONGER THAN INOUT PATH %s: IMMED ASSIGN <OV=%s, NV=%s>\n",
+    __to_timstr(__xs2, &distdel), __to_timstr(s1, &__pdmindel), 
+    __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren, nval));
+   /* use new gateval in tran channel eval */
+   return(TRUE);
+  }
+
+ /* real path delay */
+ /* case 1: no pending event */
+ /* know if no pending event, pdp not nil */
+ if (tevpi == -1)
+  {
+   /* because no pending event must be different */
+   __tr_msg(" PATH DEL, SCHD AT %s <OV=%s, NSV=%s>\n",
+    __to_timstr(s1, &schtim), __to_vnam(vs1, is_stren, oval),
+    __to_vnam(vs2, is_stren, nval));
+   __schedule_1wev(np, biti, TE_BIDPATH, __pdmindel, schtim, nval,
+    itevpi, FALSE);
+   return(FALSE);
+  }    
+
+ /* pending event */
+ tevp = &(__tevtab[tevpi]); 
+ /* new and old same but know scheduled different - classic pulse/glitch */
+ if (nval == oval)
+  {
+   /* preform show cancel e analysis, know scheduled different - tell user */
+   /* this is classical spike analysis */
+   if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+    {
+     __emit_path_samewarn(np, biti, tevp, &(tevp->etime), "pulse",
+      is_stren);
+    }
+
+   /* if spike, suppress future but schedule to x at currently scheduled */
+   if (__show_cancel_e)
+    {
+     if (__showe_onevent) sprintf(s1, "%s (on event)", __to_timstr(__xs,
+      &(tevp->etime)));
+     else sprintf(s1, "%s (on detect)", __to_timstr(__xs, &__simtime));
+
+     /* LOOKATME - think on event pulse should use schedule if earlier? */
+     __tr_msg(
+      " INOUT PATH DEL, PEND AT %s, PULSE <OV=NSV=%s, OSV=%s SHOWING X FROM %s>\n",
+      __to_timstr(__xs, &(tevp->etime)), __to_vnam(vs1, is_stren, oval),
+      __to_vnam(vs2, is_stren, (word32) tevp->outv), s1);
+
+     if (__showe_onevent)
+      { tevp->outv = (is_stren) ? ST_STRONGX : 3; return(FALSE); }
+
+     __cancel_1wev(tevp); 
+     itevpi[biti] = -1;
+     goto set_on_detect_x;
+    }
+   /* remove pulse */
+   __tr_msg(
+    " INOUT PATH DEL, PEND, PULSE, INERTIAL CANCEL AT %s <OV=%s, OSV=%s>\n",
+    __to_timstr(s1, &(tevp->etime)), __to_vnam(vs1, is_stren, oval),
+    __to_vnam(vs2, is_stren, (word32) tevp->outv));
+   /* no spike, but newly scheduled to same so no event */
+   __cancel_1wev(tevp);
+   itevpi[biti] = -1;
+   return(FALSE);
+  }
+
+ /* form here on know pdp set */
+ /* new schedule to same value case */
+ /* know that delay same and later so just discard new event */
+ /* done silently here - trace message only */
+ if (tevp->outv == (byte) nval)
+  {
+   __tr_msg(
+    " INOUT PATH DEL, MODEL ANOMALLY IGNORE SCHED TO SAME <OSV=NSV=%s> OLD AT %s NEW %s\n",
+    __to_vnam(vs1, is_stren, nval), __to_timstr(s1, &(tevp->etime)),
+    __to_timstr(s2, &schtim));
+   return(FALSE);
+  }
+
+ /* inertial reschedule */
+ if (__warn_cancel_e && !__no_warns && !__em_suppr(592))
+  __emit_path_pulsewarn(pdp, tevp, &(tevp->etime), &schtim, "inout unstable",
+   is_stren);
+
+ /* easy show cancel (set to x case) - no new event may or may not switch */
+ if (__show_cancel_e)
+  {
+   if (__showe_onevent) sprintf(s2, "%s (on event)", __to_timstr(__xs,
+    &(tevp->etime)));
+   else sprintf(s2, "%s (on detect)", __to_timstr(__xs, &__simtime));
+
+   __tr_msg(
+    " INOUT PATH DEL, PEND AT %s, UNSTABLE <OV=%s, OSV=%s, NSV=%s SHOWING X FROM %s>\n",
+    __to_timstr(s1, &(tevp->etime)), __to_vnam(vs1, is_stren, oval),
+    __to_vnam(vs2, is_stren, (word32) tevp->outv), __to_vnam(vs3, is_stren,
+    nval), s2);
+   if (__showe_onevent)
+    { tevp->outv = (is_stren) ? ST_STRONGX : 3; return(FALSE); }
+
+   __cancel_1wev(tevp);
+   itevpi[biti] = -1;
+   goto set_on_detect_x;
+  }
+
+ /* inertial reschedule, this handles cancel if needed */ 
+ __tr_msg(
+  " INOUT PATH DEL, PEND, UNSTABLE, INERTIAL RESCHD <OV=%s, OSV=%s AT %s, NSV=%s AT %s>\n",
+  __to_vnam(vs1, is_stren, oval), __to_vnam(vs2, is_stren, (word32) tevp->outv),
+  __to_timstr(s1, &(tevp->etime)), __to_vnam(vs3, is_stren, nval),
+  __to_timstr(s2, &schtim)); 
+
+ __reschedule_1wev(tevpi, nval, __pdmindel, schtim, itevpi);
+ return(FALSE);
+}
+
+/*
+ * ROUTINES FOR BID ONLY ALL SAME WIRE TYPE CHANNELS 
+ */
+
+/*
+ * for stren bid only per bit same wire type tran channel
+ * combine all nodes into one stren value using chan rec list
+ *
+ * this accumlates combined channel strength values in __acum_sb
+ *
+ * SJM 04/23/01 - changed so always eval from one chan distinguished vtx
+ * works since no stren reduction or wired nets in channel always
+ * need to combine all nodes into one value that is then stored everywhere 
+ * this allows removing back edges (i.e. no longer digraph)
+ */
+static void eval_assign_stbid_chan(struct chanrec_t *chanp)
+{
+ register struct bidvtxlst_t *bidvtxlp; 
+ register word32 sb2;
+ register struct net_t *np;
+ register int32 bi;
+
+ /* first eval all contributors to the one universal new value */
+ __acum_sb = ST_HIZ;
+ bidvtxlp = chanp->bid_vtxlp;
+ for (; bidvtxlp != NULL; bidvtxlp = bidvtxlp->bidvtxnxt)
+  {
+   __push_itstk(bidvtxlp->bidvtx_itp);
+
+   np = bidvtxlp->vnp;
+   bi = bidvtxlp->vi1;
+   bi = (bi == -1) ? 0 : bi;
+   /* SJM - 03/15/00 - if wire is forced, use its values as "driving" val */
+   if (np->frc_assgn_allocated
+    && np->nu2.qcval[__inum*np->nwid + bi].qc_active)
+    {
+     sb2 = np->nva.bp[__inum*np->nwid + bi];
+    }
+   else sb2 = np->ntraux->trnva.bp[__inum*np->nwid + bi];
+   __acum_sb = (word32) __comb_1bitsts(np->ntyp, __acum_sb, sb2);
+   __pop_itstk();
+  }
+
+ /* then assign it to every vertex */
+ bidvtxlp = chanp->bid_vtxlp;
+ for (; bidvtxlp != NULL; bidvtxlp = bidvtxlp->bidvtxnxt)
+  {
+   __push_itstk(bidvtxlp->bidvtx_itp);
+
+   np = bidvtxlp->vnp;
+   bi = bidvtxlp->vi1;
+   stassign_1tranbit(np, bi, __acum_sb);
+   __pop_itstk();
+  }
+}
+
+/*
+ * for oon stren bid only per bit same wire type tran channel
+ * combine all nodes into one stren value using chan rec list
+ *
+ * SJM 04/23/01 - changed so always eval from one chan distinguished vtx
+ * works since no stren reduction or wired nets in channel always
+ * need to combine all nodes into one value that is then stored everywhere 
+ * this allows removing back edges (i.e. no longer digraph)
+ */
+static void eval_assign_bid_chan(struct chanrec_t *chanp) 
+{
+ register struct bidvtxlst_t *bidvtxlp; 
+ register struct net_t *np;
+ word32 nav, nbv; 
+ int32 bi, bi2;
+ 
+ /* initialize to 2 (hiz) */
+ __acum_a = 0;
+ __acum_b = 1;
+
+ /* first eval all contributors to the one universal new value */
+ /* uses global accum - in gcc global access faster */
+ bidvtxlp = chanp->bid_vtxlp;
+ for (; bidvtxlp != NULL; bidvtxlp = bidvtxlp->bidvtxnxt)
+  {
+   __push_itstk(bidvtxlp->bidvtx_itp);
+   np = bidvtxlp->vnp;
+   bi = bidvtxlp->vi1;
+   bi2 = (bi == -1) ? 0 : bi;
+   if (np->frc_assgn_allocated
+    && np->nu2.qcval[__inum*np->nwid + bi2].qc_active)
+    {
+     if (bi == -1) ld_scalval_(&nav, &nbv, np->nva.bp);
+     else __ld_bit(&nav, &nbv, np, bi);
+    }
+   else ld_vtx_netbit(&nav, &nbv, np, bi);
+   __eval_1w_nonstren(&__acum_a, &__acum_b, nav, nbv, np->ntyp);
+   __pop_itstk();
+  }
+
+ /* then assign it to every vertex */
+ bidvtxlp = chanp->bid_vtxlp;
+ for (; bidvtxlp != NULL; bidvtxlp = bidvtxlp->bidvtxnxt)
+  {
+   __push_itstk(bidvtxlp->bidvtx_itp);
+   np = bidvtxlp->vnp;
+   bi = bidvtxlp->vi1;
+   assign_1tranbit(np, bi, __acum_a, __acum_b);
+   __pop_itstk();
+  }
+}
+
+/*
+ * load the bit value of one non strength vertex 
+ * called from itree location of wire 
+ */
+static void ld_vtx_netbit(word32 *ap, word32 *bp, struct net_t *np, int32 bi)
+{
+ struct xstk_t *xsp;
+
+ if (!np->n_isavec) ld_scalval_(ap, bp, np->ntraux->trnva.bp); 
+ else
+  {
+   /* know bi not -1 since vector */ 
+   push_xstk_(xsp, np->nwid);
+   __ld_perinst_val(xsp->ap, xsp->bp, np->ntraux->trnva, np->nwid);
+   ap[0] = rhsbsel_(xsp->ap, bi);
+   bp[0] = rhsbsel_(xsp->bp, bi);
+   __pop_xstk();
+  }
+}
+
+/*
+ * routine to assign 1 non stren bid only channel tran bit
+ */
+static void assign_1tranbit(struct net_t *np, int32 bi, word32 nav, word32 nbv)
+{
+ /* non stren case */ 
+ if (bi == -1) bi = 0;
+ /* tran channel elements in P1364 can not have wire delays */
+ /* no meaning since drivers of all in channel and wires must be same */
+
+ /* SJM 06/02/99 - will have DWIR and no path if all 0 paths removed */
+ /* to optimize invalidating internal consistency check */
+
+ /* for path dest., need immediate assign - internal hard driver value */
+ /* change is delayed */
+
+ /* if wire bit forced (qcval inst non nil), must not assign to wire */
+ if (np->frc_assgn_allocated
+  && np->nu2.qcval[__inum*np->nwid + bi].qc_active)
+  {
+   /* need not pass bi -1 since checks separately for scalar net */
+   if (__debug_flg && __ev_tracing) trmsg_frc_inhibit(np, bi);
+   return;
+  }
+
+ if (!np->n_isavec) __chg_st_val(np, &nav, &nbv);
+ else __chg_st_bit(np, bi, nav, nbv);
+
+ if (__debug_flg && __ev_tracing)
+  {
+   transtore_trmsg(np, bi, __lhs_changed, nav, nbv);
+  }
+ /* SJM 08/24/03 - since record reset must test to see if chged */
+ if (__lhs_changed) record_sel_nchg_(np, bi, bi);
+}
+
+/*
+ * store one vertex net bit from passed a and b values
+ * called from itree location of np definition
+ */
+static void st_vtx_netbit(struct net_t *np, int32 bi, word32 nav, word32 nbv)
+{
+ /* this does not use lhs changed */
+ if (np->n_stren) stassign_1tranbit(np, bi, nav);
+ else assign_1tranbit(np, bi, nav, nbv);
+}
+
+/*
+ * emit a tran channel force inhibit of tran channel store
+ */
+static void trmsg_frc_inhibit(struct net_t *np, int32 bi)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ if (np->n_isavec) sprintf(s1, "%s[%d]", np->nsym->synam, bi);
+ else strcpy(s1, np->nsym->synam);
+ if (np->n_stren) strcpy(s2, " strength"); else strcpy(s2, ""); 
+ __tr_msg("## tran/inout channel store of%s %s inhibited - active force\n",
+  s2, s1);
+}
+
+/*
+ * emit a tran channel store trace message
+ */
+static void transtore_trmsg(struct net_t *np, int32 bi, int32 chg, word32 nav,
+ word32 nbv)
+{
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN], s4[RECLEN];
+ byte sb2;
+ 
+ if (np->n_stren)
+  {
+   strcpy(s1, " strength");
+   sb2 = (byte) nav;
+   __st_regab_tostr(s2, &sb2, 1);
+  }
+ else
+  {
+   strcpy(s1, "");
+   __regab_tostr(s2, &nav, &nbv, 1, BHEX, FALSE);
+  }
+ if (np->n_isavec) sprintf(s3, "%s[%d]", np->nsym->synam, bi);
+ else strcpy(s3, np->nsym->synam);
+ if (chg)
+  __tr_msg("## tran/inout channel store of%s %s %s NV=%s\n", s1,
+   __to_wtnam(s4, np), s3, s2);
+ else
+  __tr_msg("## tran/inout channel no change of%s %s %s OV=%s\n",
+   s1, __to_wtnam(s4, np), s3, s2);
+}
+
+/*
+ * assign one strength tran channel element (wire-bit)
+ * bi is -1 for scalar else bit index
+ * handles trireg and any forced assign inhibition
+ * called from itree loc. of np 
+ *
+ * routine does not traverse edge graph
+ */
+static void stassign_1tranbit(struct net_t *np, register int32 bi,
+ register word32 sbv)
+{
+ register byte *sbp2;
+ register int32 bind;
+
+ bind = (bi == -1) ? 0 : bi;
+
+ /* get strength wire address */
+ get_stwire_addr_(sbp2, np);
+
+ /* tran channel elements in P1364 can not have wire delays */
+ /* no meaning since drivers of all in channel and wires must be same */
+ /* SJM 06/02/99 - will have DWIR and no path if all 0 paths removed */
+ /* to optimize invalidating internal consistency check */
+
+ /* stren non delay wire */ 
+ /* if bit forced, must not assign */
+ if (np->frc_assgn_allocated
+  && np->nu2.qcval[__inum*np->nwid + bind].qc_active)
+   { 
+    if (__debug_flg && __ev_tracing) trmsg_frc_inhibit(np, bi);
+    return;
+   }
+
+ /* this may change sbv from tran channel new value to trireg value */ 
+ /* SJM 10/16/00 - this was commented out but that caused Samsung trireg */
+ /* tests to fail - must have had a reason to comment out but why? */
+ /* --- */
+ if (np->ntyp == N_TRIREG)
+  {
+   if (__wire_init) sbv = (byte) (3 | __cap_to_stren[np->n_capsiz]);
+   else 
+    {  
+     if (sbv == ST_HIZ)
+      sbv = (byte) ((sbp2[bind] & 3) | __cap_to_stren[np->n_capsiz]);
+    }
+  }
+ /* --- */
+ if (__debug_flg && __ev_tracing)
+  {
+   int32 chg;
+
+   if (sbv != (word32) sbp2[bind]) chg = TRUE; else chg = FALSE;
+   transtore_trmsg(np, bi, chg, sbv, sbv);
+  } 
+ if (sbv != (word32) sbp2[bind])
+  {
+   sbp2[bind] = (byte) sbv;
+   /* notice needs to be bi since need -1 if scalar */
+   /* always record since immediate assign - no setting of lhs changed */ 
+   /* SJM 08/24/03 - and no need to now since this resets anyway */
+   record_sel_nchg_(np, bi, bi);
+  }  
+}
+
+/*
+ * ROUTINES FOR BID TRAN STREN CHANNEL (ALSO BID DIFFERENT WIRE TYPES)
+ */
+
+/*
+ * assign or schedule channel when hard driver of transistor enable adjacent
+ * to this vertex changed
+ *
+ * normally pass only argument but when tranif enable changes pass both
+ * this allows doing only one relaxation
+ *
+ * this must handle assign inhibition from forcing and trireg decays
+ * build the vincincity lists and relax only those vertices
+ * uses Bryant algorithm
+ *
+ * called from itree loc. of start vertex 
+ */
+
+/*
+ * eval and asssign locally changed part of tran always stren channel 
+ *
+ * itee context on it stk
+ * has trans or bid strength and different wire types 
+ * add this vertex to relaxation list
+ */
+static void eval_update_1w_tranchan(struct vtx_t *vtxp)
+{
+ struct vtxlst_t *vtxlp;
+
+ vtxlp = add_stchan_chged_vtx(vtxp, __inst_ptr);
+ vtxp->vtx_in_vicinity = TRUE;
+ find_chgvtx_vicinity(vtxlp);
+
+ /* do the relaxation only on perturbed in vicinity vertices */
+ stchan_trif_relax();
+
+ /* final step, assign (maybe schedule) all changed vertices */
+ if (__chg_vtxlst_hdr != NULL) assign_chged_vtxs();
+}
+
+/*
+ * add a changed vertex to st vtx tab in preparation for relaxation
+ * passed itree context of vertex
+ *
+ * this adds the vertex that has changed because hard driver changed, or
+ * it was forced/released or it is tranif terminal and enable changed 
+ */
+static struct vtxlst_t *add_stchan_chged_vtx(struct vtx_t *vtxp,
+ struct itree_t *vt1_itp)
+{
+ int32 bi, inum;
+ word32 vtxval, st0, st1, lowst;
+ struct net_t *np;
+ struct vtxlst_t *vtxlp;
+
+ np = vtxp->vnp;
+ bi = (vtxp->vi1 == -1) ? 0 : vtxp->vi1;
+ inum = vt1_itp->itinum;
+
+ /* always move new vtx value to old */
+ /* for trireg and net's with delay (when supported?) net val may differ */
+ /* NO - only update old value when store new value ---
+ vtxp->old_vtxval = vtxp->new_vtxval;
+ --- */
+
+ /* add vtx to change list and solve channel using relaxation */ 
+ /* first guess at new (current) is hard driver value unless forced */ 
+ if (np->frc_assgn_allocated
+  && np->nu2.qcval[__inum*np->nwid + bi].qc_active)
+  {
+   vtxp->vtx_forced = TRUE; 
+   vtxval = (word32) np->nva.bp[inum*np->nwid + bi];
+   vtxp->new_vtxval = vtxval;
+  }
+ else
+  {
+   /* when released tran channel relaxed again - this turns off force */
+   vtxval = (word32) np->ntraux->trnva.bp[inum*np->nwid + bi];
+   /* 04/25/01 - SJM - must turn off forcing each time since some releases */
+   /* may have happened but release not connectd to tran vertices */
+   vtxp->vtx_forced = FALSE; 
+  }
+ vtxp->new_vtxval = (byte) vtxval;
+ if (vtxval == ST_SUPPLY0 || vtxval == ST_SUPPLY1) vtxp->vtx_supply = TRUE;
+ /* think needed since vpi can drive to supply then remove */
+ else vtxp->vtx_supply = FALSE;
+
+ /* SJM 04/09/01 - for stren ranges using low - think that will work */
+ st1 = (vtxval >> 2) & 0x7;
+ st0 = (vtxval >> 5) & 0x7;
+ lowst = (st1 < st0) ? st1 : st0;
+
+ /* alloc and link on changed one vertex */
+ /* because will be large at start then tiny better to malloc/free */
+ if (__vtxlst_freelst == NULL)
+  vtxlp = (struct vtxlst_t *) __my_malloc(sizeof(struct vtxlst_t));
+ else
+  {
+   vtxlp = __vtxlst_freelst;
+   __vtxlst_freelst = __vtxlst_freelst->vtxnxt;
+  }
+ vtxlp->vtxp = vtxp;
+ vtxlp->vtx_itp = vt1_itp;
+ vtxlp->vtxnxt = NULL;
+
+ /* must always put on end */
+ if (__stvtxtabend[lowst] != NULL)
+  { __stvtxtabend[lowst]->vtxnxt = vtxlp; __stvtxtabend[lowst] = vtxlp; }
+ else __stvtxtab[lowst] = __stvtxtabend[lowst] = vtxlp;
+
+ __num_switch_vtxs_processed++;
+
+ /* DBG remove -- */ 
+ if (__debug_flg && __ev_tracing)
+  {
+   __dbg_msg("** vertex %s.%s level %d added to incremental perturb list\n",
+    __msg2_blditree(__xs, vtxlp->vtx_itp), to_vtx(__xs2, vtxp), lowst);
+  }
+ return(vtxlp);
+}
+
+/*
+ * routine to store into nets all changed vertices 
+ */
+static void assign_chged_vtxs(void)
+{
+ register struct vtxlst_t *vtxlp;
+ register int32 bi, bi2;
+ register struct vtx_t *vtxp;
+ word32 sbv;
+ byte *sbp2;
+ struct net_t *np;
+
+ for (vtxlp = __chg_vtxlst_hdr; vtxlp != NULL; vtxlp = vtxlp->vtxnxt)
+  {
+   __push_itstk(vtxlp->vtx_itp);
+
+   vtxp = vtxlp->vtxp;
+   np = vtxp->vnp;
+   bi = vtxp->vi1;
+   bi2 = (bi == -1) ? 0 : bi;
+   /* sbp2 of index is addr to store new net value into */
+   get_stwire_addr_(sbp2, np);
+   /* sbv is new value to store */
+   sbv = (word32) vtxp->new_vtxval;
+   /* for next relax old value is current node val, old val no longer need */
+   vtxp->old_vtxval = vtxp->new_vtxval;
+
+   /* know if vertex forced will never be on change list */
+
+   /* this may change sbv from tran channel new value to trireg value */ 
+   /* SJM 10/16/00 - this was commented out but that caused Samsung trireg */
+   /* tests to fail - must have had a reason to comment out but why? */
+   if (np->ntyp == N_TRIREG)
+    {
+     if (__wire_init) sbv = (byte) (3 | __cap_to_stren[np->n_capsiz]);
+     else 
+      {  
+       if (sbv == ST_HIZ)
+        sbv = (byte) ((sbp2[bi2] & 3) | __cap_to_stren[np->n_capsiz]);
+      }
+    }
+   /* DBG remove --- */
+   if (__debug_flg && __ev_tracing)
+    {
+     int32 chg;
+
+     if (sbv != (word32) sbp2[bi2]) chg = TRUE; else chg = FALSE;
+     transtore_trmsg(np, bi, chg, sbv, sbv);
+    } 
+   if (sbv != (word32) sbp2[bi2])
+    {
+     sbp2[bi2] = (byte) sbv;
+
+     /* notice needs to be bi since need -1 if scalar */
+     /* always record since this assign does not set lhs changed */ 
+     if (bi == -1) record_nchg_(np);
+     else record_sel_nchg_(np, bi, bi);
+    } 
+   vtxlp->vtxp->vtx_chged = FALSE;
+   
+   __pop_itstk();
+  }
+ /* add entire list to end of free list */
+ if (__chg_vtxlst_hdr != NULL)
+  {
+   __chg_vtxlst_end->vtxnxt =  __vtxlst_freelst; 
+   __vtxlst_freelst = __chg_vtxlst_hdr;
+  }
+ __chg_vtxlst_hdr = __chg_vtxlst_end = NULL;
+}
+
+/*
+ * find all nodes in vicinity of a changed node and add to change list
+ *
+ * any node on other side of x/1 conducting edge with lower stren is 
+ * in vicincity (usually undriven nodes) - forced/assigned never in this set
+ * this gets itree context from passed vtx list
+ */
+static void find_chgvtx_vicinity(struct vtxlst_t *vtxlp)
+{
+ register struct edge_t *ep;
+ int32 bi, bi2, gid;
+ word32 conducting;
+ struct vtx_t *vtxp, *vtxp2;
+ struct vtxlst_t *vtxlp2;
+ struct gate_t *gp;
+ struct itree_t *oside_itp; 
+
+ vtxp = vtxlp->vtxp;
+ bi = vtxp->vi1;
+ if (bi == -1) bi = 0; 
+
+ for (ep = vtxp->vedges; ep != NULL; ep = ep->enxt)
+  { 
+   vtxp2 = ep->ev2;
+   if (vtxp2->vtx_in_vicinity) continue;
+
+   bi2 = vtxp2->vi1;
+   if (bi2 == -1) bi2 = 0;
+
+   /* if vicinty node forced - can never be in vicinity, can't change */
+   if (vtxp2->vtx_forced) continue;
+
+   /* supply can only change if opposite supply across inout */
+   if (vtxp2->vtx_supply)
+    {
+     /* if other side not supply, never can change */
+     if (!vtxp->vtx_supply) continue;
+
+     /* if edge tran (not port) reducing so can never change */
+     if (ep->enpp->npntyp != NP_BIDMDPRT && ep->enpp->npntyp != NP_BIDICONN)
+      continue;
+     /* if both supplies same (values never changes so good here) can't chg */
+     if (vtxp->new_vtxval == vtxp2->new_vtxval) continue;
+    }
+
+   /* SJM 08/26/00 - all xmr/inout edges per inst. so store oside itp */
+   if (ep->edgoside_itp != NULL) oside_itp = ep->edgoside_itp;
+   else oside_itp = vtxlp->vtx_itp;
+
+   if (ep->enpp->npntyp == NP_TRAN)
+    {
+     gp = ep->enpp->elnpp.egp;
+     if (gp->g_class == GC_TRANIF)
+      {
+       gid = gp->gmsym->el.eprimp->gateid; 
+
+       __push_itstk(oside_itp);
+       conducting = get_switch_tranif_onoff(gp, gid);
+       __pop_itstk();
+
+       if (__debug_flg && __ev_tracing)
+        {
+         char s1[RECLEN]; 
+
+         if (conducting == 0) strcpy(s1, "*OFF*");
+         else if (conducting == 1) strcpy(s1, "*ON*");
+         else strcpy(s1, "*UNKNOWN*"); 
+         __dbg_msg( "-- tranif vicinity switch %s at %s conducting %s\n",
+          gp->gsym->synam, __bld_lineloc(__xs, gp->gsym->syfnam_ind,
+          gp->gsym->sylin_cnt), s1);
+        }
+       /* if off, no contribution - if x, conducting stronger */ 
+       if (conducting == 0) continue;
+      } 
+    } 
+   else gp = NULL;
+   vtxlp2 = add_stchan_chged_vtx(vtxp2, oside_itp);
+
+   vtxp2->vtx_in_vicinity = TRUE;
+   /* find vicinity of this node */
+   find_chgvtx_vicinity(vtxlp2);
+  }
+}
+
+/*
+ * routine to solve tran(if) channel by relaxation
+ *
+ * st vtxtab filled with changed nodes (hard drivers/stren tranif enable chged)
+ * works from highest to lowest stren - key is that values can only lessen
+ * this uses Bryant algorithm
+ *
+ * this does not call routines which pushes itree stk can't grow too big
+ * and gets vtx itree loc from vtx list
+ */
+static void stchan_trif_relax(void)
+{
+ register int32 si;
+ register struct edge_t *ep;
+ word32 cur_vtxval, oside_val, st0, st1, lowst, conducting;
+ int32 bi, bi2, nd_itpop, chged, gid, stable;
+ struct vtx_t *vtxp, *vtxp2;
+ struct vtxlst_t *vtxlp, *vtxlp2, *last_vtxlp;
+ struct gate_t *gp;
+ struct net_t *np;
+
+ /* DBG remove --
+ if (__debug_flg && __ev_tracing)
+  {
+   __dbg_msg("=== starting channel relaxtion ===\n");
+  }
+ --- */
+
+ for (;;)
+  {
+   /* process all level from top down */
+   for (stable = TRUE, si = 7; si >= 0; si--) 
+    {
+     /* DBG remove --
+     if (__debug_flg && __ev_tracing) dmp_perturb_list();
+     -- */
+
+     last_vtxlp = NULL;
+     /* relax all vertices at level si */
+     for (vtxlp = __stvtxtab[si]; vtxlp != NULL;)
+      {
+       /* always push and start at vtx itree loc */
+       __push_itstk(vtxlp->vtx_itp);
+
+       /* find new val of this vtx by stren competition with all neighbors */ 
+       vtxp = vtxlp->vtxp;
+       np = vtxp->vnp;
+       vtxp->vtx_in_vicinity = FALSE;
+       bi = vtxp->vi1;
+       if (bi == -1) bi = 0; 
+       /* DBG remove -- */
+       if (__debug_flg && __ev_tracing)
+        {
+         __dbg_msg( "<> relaxing vertex %s.%s at level %d\n",
+          __msg2_blditree(__xs, __inst_ptr), to_vtx(__xs2, vtxp), si);
+        }
+       /* --- */
+
+       /* if this changed node is forced, always wins */
+       /* but need to eval supply in case inout port opposite also supply */
+       if (vtxp->vtx_forced)
+        {
+         __pop_itstk();
+         last_vtxlp = vtxlp;
+         vtxlp = vtxlp->vtxnxt;
+         continue;
+        }
+  
+       /* first quess is hard driver val for current changed vtx */
+       cur_vtxval = (word32) vtxp->new_vtxval;
+       /* add in all contributing edges - only exit is fall thru bottom */
+       for (chged = FALSE, ep = vtxp->vedges; ep != NULL; ep = ep->enxt)
+        { 
+         vtxp2 = ep->ev2;
+
+         /* value for competition is most recent other side vtx value */
+         oside_val = vtxp2->new_vtxval;
+         /* if value is hiz, skip since know will always lose */
+         if (oside_val == ST_HIZ) continue;
+    
+         bi2 = vtxp2->vi1;
+         if (bi2 == -1) bi2 = 0;
+  
+         if (ep->enpp->npntyp == NP_TRAN)
+          {
+           gp = ep->enpp->elnpp.egp;
+           gid = gp->gmsym->el.eprimp->gateid;
+
+           if (gp->g_class == GC_TRANIF)
+            {
+             /* move to itree loc of edge's other side vtx to eval on/off */
+             /* SJM 08/26/00 - all  edges per inst. so store oside itp*/
+             if (ep->edgoside_itp != NULL)
+              { __push_itstk(ep->edgoside_itp); nd_itpop = TRUE; }
+             else nd_itpop = FALSE; 
+
+             /* compute conducting state if tranif and reduce if tran/tranif */
+             /* if conducting x/z, other val stren H/L */
+             conducting = try_reduce_tranif_stren(&oside_val, gp);
+
+             if (nd_itpop) __pop_itstk();
+  
+             /* if tranif not conducting,  no contribution for other side */
+             if (conducting == 0) continue; 
+            } 
+           /* tran just reduces stren, always on - itree cntxt not needed */
+           else try_reduce_tran_stren(&oside_val, gid);
+          }
+         /* if inout, oside value is unchanged */
+  
+         /* if cur val exactly the same as oside no need for stren */
+         /* competition since know result will be same */
+         if (cur_vtxval != oside_val)
+          {
+           /* do stren competition with vtx being determined and oside value */
+           /* oside value may have been corrected if edge stren reducing */
+           cur_vtxval = (word32) __comb_1bitsts(np->ntyp, cur_vtxval, oside_val);
+  
+           /* if cur (new) value changed (oside at last partially won), */  
+           /* need to combine to produce actual cur (new) val */
+           if (cur_vtxval != vtxp->new_vtxval)
+            {
+             /* combine the cur (latest) val with last relax latest */
+             /* this handles stren ranges */
+             cur_vtxval = (word32) __comb_1bitsts(np->ntyp, cur_vtxval,
+              vtxp->new_vtxval);
+             /* use cur (new) as vtx val from now on, rest can all lose */ 
+             vtxp->new_vtxval = cur_vtxval;
+
+             /* chg cur to new imoproved val that was assigned to vtx val */
+             /* LOOKATME - can this happen - think yes but rare */
+             if (cur_vtxval == ST_SUPPLY0 || cur_vtxval == ST_SUPPLY1)
+              vtxp->vtx_supply = TRUE;
+              
+             /* relax value changes so must relax again */
+             chged = TRUE; 
+            }
+          }
+         /* if oside same, cur vtx val does not change */
+        }
+       /* now have new relaxed value - record and move if needed */
+
+       /* SJM 04/23/01 - during wire init do not record - must store */ 
+       /* all internal tran chan new values into nets */
+       /* old may not be same as net's if net pdst or del so scheduled */
+       if (cur_vtxval != vtxp->old_vtxval && !vtxp->vtx_chged)
+        {
+         add_to_chg_vtx_list(vtxlp, si);
+        }
+
+       /* independent of whether new changed value differs from old relax */
+       /* entry value, if changed must move to new correct stren tab index */
+       if (chged)
+        {
+         stable = FALSE;
+         /* DBG remove -- */
+         if (__debug_flg && __ev_tracing)
+          {
+           char s1[RECLEN];
+    
+           __dbg_msg("<> vertex %s.%s at level %d changed to %s\n",
+            __msg2_blditree(__xs, vtxlp->vtx_itp), to_vtx(__xs2, vtxp), si,
+            __to_vvstnam(s1, cur_vtxval));
+          }
+         /* --- */
+        
+         /* put on new higher (probably) st list - need to relax list again */
+         /* can be lower if tranif disabled */ 
+         st1 = (cur_vtxval >> 2) & 0x7;
+         st0 = (cur_vtxval >> 5) & 0x7;
+         lowst = (st1 < st0) ? st1 : st0;
+
+         /* this can be same stren as previous but stren range or new val */
+         /* low st will usually be higher but if tranif off can be lower */
+         if (lowst != si)  
+          {
+           vtxlp2 = vtxlp->vtxnxt;
+
+           /* link out and put on end of other list */
+           if (last_vtxlp == NULL) __stvtxtab[si] = vtxlp->vtxnxt;
+           else last_vtxlp->vtxnxt = vtxlp->vtxnxt;
+           if (vtxlp == __stvtxtabend[si]) __stvtxtabend[si] = last_vtxlp;
+  
+           /* linked out is now end of higher list */ 
+           vtxlp->vtxnxt = NULL;
+     
+           /* since vtxlp has been removed from prev list do not need new */
+           /* alloc, can just link onto end of higher stren list */
+           if (__stvtxtabend[lowst] != NULL)
+            {
+             __stvtxtabend[lowst]->vtxnxt = vtxlp;
+             __stvtxtabend[lowst] = vtxlp;
+            }
+           else __stvtxtab[lowst] = __stvtxtabend[lowst] = vtxlp;
+  
+           /* this will make move to right next one work - no chg of last */
+           __pop_itstk();
+           vtxlp = vtxlp2;
+           continue;
+          }
+         /* if stren same leave in list */
+        }
+       __pop_itstk();
+       last_vtxlp = vtxlp;
+       vtxlp = vtxlp->vtxnxt;
+      }
+    }
+   if (stable) break;
+  }
+ /* final step free all st vtx tab level lists */
+ for (si = 7; si >=0; si--) 
+  { 
+   /* finished with last level can free entire perturbed vtx list */
+   /* i.e. all nodes of higher strength now known */
+   if (__stvtxtab[si] != NULL)
+    {
+     __stvtxtabend[si]->vtxnxt = __vtxlst_freelst;
+     __vtxlst_freelst = __stvtxtab[si];
+     __stvtxtab[si] = __stvtxtabend[si] = NULL;  
+    }
+  }
+ /* DBG remove --
+ if (__debug_flg && __ev_tracing)
+  {
+   __dbg_msg("=== relaxation completed - channel stable ===\n");
+  }
+ --- */
+}
+
+/*
+ * add vertxx to chg vtx list
+ * put on store when done list - only called if not already on list
+ * does not need itree context 
+ */
+static void add_to_chg_vtx_list(struct vtxlst_t *vtxlp, int32 si)
+{
+ struct vtx_t *vtxp;
+ struct vtxlst_t *chg_vtxlp;
+
+ vtxp = vtxlp->vtxp;
+ if (__vtxlst_freelst == NULL)
+  chg_vtxlp = (struct vtxlst_t *) __my_malloc(sizeof(struct vtxlst_t));
+ else
+  {
+   chg_vtxlp = __vtxlst_freelst;
+   __vtxlst_freelst = __vtxlst_freelst->vtxnxt;
+  }
+ *chg_vtxlp = *vtxlp;
+ chg_vtxlp->vtxnxt = NULL;
+  
+ if (__chg_vtxlst_end == NULL) __chg_vtxlst_hdr = __chg_vtxlst_end = chg_vtxlp;
+ else
+  {
+   __chg_vtxlst_end->vtxnxt = chg_vtxlp;
+   __chg_vtxlst_end = chg_vtxlp;
+  }
+ vtxp->vtx_chged = TRUE; 
+ /* DBG remove -- */
+ if (__debug_flg && __ev_tracing)
+  {
+   __dbg_msg("++ vertex %s.%s level %d added to store net change list\n",
+    __msg2_blditree(__xs, vtxlp->vtx_itp), to_vtx(__xs2, vtxp), si);
+  }
+ /* --- */
+}
+
+/*
+ * dump perturbed queue (element for each stren level)
+ */
+static void dmp_perturb_list(void)
+{
+ register int32 si;
+ register struct vtxlst_t *vtxlp;
+ char s1[RECLEN];
+
+ for (si = 7; si >= 0; si--) 
+  {
+   if (__stvtxtab[si] == NULL) __tr_msg(" Level %d **empty**\n", si);
+   else
+    {
+     __dbg_msg(" Level %d:\n", si);
+     for (vtxlp = __stvtxtab[si]; vtxlp != NULL; vtxlp = vtxlp->vtxnxt)
+      {
+       __dbg_msg("  %s\n", to_vtx_info(s1, vtxlp->vtxp, vtxlp->vtx_itp));
+       /* DBG remove -- */
+       if (vtxlp->vtxnxt == NULL)
+        {
+         if (vtxlp != __stvtxtabend[si]) __misc_terr(__FILE__, __LINE__);
+        }
+       /* --- */
+      }
+    }
+  }
+}
+
+/*
+ * dump all vertices in switch channel
+ */
+static char *to_vtx_info(char *s, struct vtx_t *vtxp, struct itree_t *itp)
+{
+ char s1[RECLEN], s2[RECLEN];
+
+ sprintf(s,
+  "  vertex %s.%s new=%s old=%s chg=%d, vicinity=%d, frc=%d, sup=%d", 
+  __msg2_blditree(__xs, itp), to_vtx(__xs2, vtxp),
+  __to_vvstnam(s1, vtxp->new_vtxval), __to_vvstnam(s2, vtxp->old_vtxval),
+  vtxp->vtx_chged, vtxp->vtx_in_vicinity, vtxp->vtx_forced, vtxp->vtx_supply);
+ return(s); 
+}
+
+/*
+ * compute conducting state and oside value for tranif gate 
+ *
+ * returns conducting value if not 0 sets oside_val to reduced val
+ * SJM 04/23/01 - also if tranif and conducting x/z (3), value is H or L
+ */
+static int32 try_reduce_tranif_stren(word32 *oside_val, struct gate_t *gp)
+{
+ int32 conducting, is_resist, gid;
+ word32 sb2, sb3, st1, st0;
+ 
+ gid = gp->gmsym->el.eprimp->gateid;
+ conducting = get_switch_tranif_onoff(gp, gid);
+ if (__debug_flg && __ev_tracing)
+  {
+   char s1[RECLEN]; 
+  
+   if (conducting == 0) strcpy(s1, "*OFF*");
+   else if (conducting == 1) strcpy(s1, "*ON*");
+   else strcpy(s1, "*UNKNOWN*"); 
+   __dbg_msg("-- tranif switch %s at %s conducting %s\n",
+    gp->gsym->synam, __bld_lineloc(__xs, gp->gsym->syfnam_ind,
+    gp->gsym->sylin_cnt), s1);
+  }
+ /* if off, no contribution */
+ if (conducting == 0) return(0);
+
+ /* LOOKATME - maybe should use g_gone or other bit - but adds whole word32 */
+ if (gid == G_RTRANIF0 || gid == G_RTRANIF1) is_resist = TRUE;
+ else is_resist = FALSE;
+
+ sb2 = *oside_val;
+ /* reduce stren for tran and rtran - if conducting off, won't get here */
+ if (is_resist)
+  {
+   /* SJM 04/23/01 - had stren backward st0 is high bit 5-7, st1 2-4 */ 
+   st0 = __rmos_stmap[(sb2 >> 5) & 0x7];
+   st1 = __rmos_stmap[(sb2 >> 2) & 0x7];
+  }
+ else
+  {
+   st0 = __mos_stmap[(sb2 >> 5) & 0x7];
+   st1 = __mos_stmap[(sb2 >> 2) & 0x7];
+  }
+
+ /* SJM 12/04/00 - fixed typo where 0 stren was mixed with 1 stren */
+ /* so reduction was wrong */
+ sb3 = sb2 & 3;
+ if (conducting == 3)
+  {
+   /* L */
+   /* SJM 04/23/01 - had stren backward st0 is high bit 5-7, st1 2-4 */ 
+   if (sb3 == 0) *oside_val = (st0 << 5) | 3;
+   /* H */
+   else if (sb3 == 1) *oside_val = (st1 << 2) | 3;
+   /* LOOKATME - think is z won't get here so only possible is x */
+   else *oside_val = sb3 | (st1 << 2) | (st0 << 5);
+   return(3);
+  }
+ *oside_val = sb3 | (st1 << 2) | (st0 << 5);
+ return(conducting);
+}
+
+/*
+ * compute conducting state and oside value for tran
+ * here conducting state always implied 1
+ * notice this does not need itree context
+ *
+ * returns conducting value if not 0 sets oside_val to reduced val
+ * SJM 04/23/01 - also if tranif and conducting x/z (3), value is H or L
+ */
+static void try_reduce_tran_stren(word32 *oside_val, int32 gid)
+{
+ int32 is_resist;
+ word32 sb2, st1, st0;
+ 
+ /* LOOKATME - maybe should use g_gone or other bit - but adds whole word32 */
+ if (gid == G_RTRAN) is_resist = TRUE; else is_resist = FALSE;
+
+ sb2 = *oside_val;
+ /* reduce stren for tran and rtran - if conducting off, won't get here */
+ if (is_resist)
+  {
+   /* SJM 04/23/01 - had stren backward st0 is high bit 5-7, st1 2-4 */ 
+   st0 = __rmos_stmap[(sb2 >> 5) & 0x7];
+   st1 = __rmos_stmap[(sb2 >> 2) & 0x7];
+  }
+ else
+  {
+   st0 = __mos_stmap[(sb2 >> 5) & 0x7];
+   st1 = __mos_stmap[(sb2 >> 2) & 0x7];
+  }
+ *oside_val = (sb2 & 3) | (st0 << 5) | (st1 << 2);
+}
+
+/*
+ * routine to access tranif on/off during switch channel evaluation 
+ * called with itree context of tranif gate 
+ *
+ * since vertex changes of tran switch channels not made and propagated until
+ * channel completed, if channel in any switch channel must use vtx value
+ *
+ * LOOKATME - could use state unless in same switch channel
+ */
+static int32 get_switch_tranif_onoff(struct gate_t *gp, int32 gid)
+{ 
+ register struct expr_t *termxp;
+ register struct net_t *np2;
+ register int32 val, bi;
+ int32 ibi;
+ struct vbinfo_t *vbip;
+ struct chanrec_t *chanp;
+
+ termxp = gp->gpins[2];
+ if (termxp->optyp == ID || termxp->optyp == GLBREF)
+  np2 = termxp->lu.sy->el.enp;
+ else if (termxp->optyp == LSB) np2 = termxp->lu.x->lu.sy->el.enp;
+ else goto no_traux;
+
+ if (np2->ntraux == NULL) goto no_traux;
+ 
+ switch ((byte) termxp->optyp) {
+  case ID:
+   ibi = np2->nwid*__inum;
+   if ((vbip = np2->ntraux->vbitchans[ibi]) == NULL) goto no_traux;
+   chanp = &(__chantab[vbip->chan_id]);
+   /* SJM 10/29/01 - need to access var value for inout chans, no vtx state */ 
+   if (chanp->chan_no_vtxs) val = get_bidchan_val(chanp, np2, ibi, 0); 
+   else val = (int32) vbip->vivxp->new_vtxval;
+   break;
+  case GLBREF:
+   __xmrpush_refgrp_to_targ(termxp->ru.grp);
+   ibi = np2->nwid*__inum;
+   if ((vbip = np2->ntraux->vbitchans[ibi]) == NULL)
+    { __pop_itstk(); goto no_traux; }
+
+   chanp = &(__chantab[vbip->chan_id]);
+   if (chanp->chan_no_vtxs) val = get_bidchan_val(chanp, np2, ibi, 0); 
+   else val = (int32) vbip->vivxp->new_vtxval;
+   __pop_itstk();
+   break;
+  case LSB:
+   /* BEWARE - this assume constant select expr folded */ 
+   if (termxp->ru.x->optyp != NUMBER) goto no_traux;
+   bi = __get_const_bselndx(termxp);
+   if (termxp->lu.x->optyp == ID)
+    {
+     ibi = np2->nwid*__inum;
+     if ((vbip = np2->ntraux->vbitchans[ibi + bi]) == NULL) goto no_traux;
+     chanp = &(__chantab[vbip->chan_id]);
+     if (chanp->chan_no_vtxs) val = get_bidchan_val(chanp, np2, ibi, bi); 
+     else val = (int32) vbip->vivxp->new_vtxval;
+     break;
+    }
+   __xmrpush_refgrp_to_targ(termxp->lu.x->ru.grp);
+   ibi = np2->nwid*__inum;
+   if ((vbip = np2->ntraux->vbitchans[ibi + bi]) == NULL)
+    { __pop_itstk(); goto no_traux; }
+   chanp = &(__chantab[vbip->chan_id]);
+   if (chanp->chan_no_vtxs) val = get_bidchan_val(chanp, np2, ibi, bi); 
+   else val = (int32) vbip->vivxp->new_vtxval;
+   __pop_itstk();
+   break;
+  default: goto no_traux;
+ }
+ val &= 3;
+ if (val == 2 || val == 3) return(3);
+ /* SJM 04/20/01 - for tranif0 gates, conducting 1 is vtx value 0 */ 
+ if (gid == G_RTRANIF0 || gid == G_TRANIF0) 
+  {
+   val = (val == 0) ? 1 : 0;
+  }
+ return(val);
+
+no_traux:
+ /* notice state is stored as conducting after correct for tranif0 gates */
+ return((int32) get_tranif_onoff_(gp));
+}
+
+/*
+ * get bid non vertex channel value - i.e. the net value 
+ * since that determines on off state
+ *
+ * SJM 10/29/01 - need to access var value for inout chans, no vtx state
+ */
+static int32 get_bidchan_val(struct chanrec_t *chanp, register struct net_t *np,
+ int32 ibi, int32 bi)
+{
+ register int32 val, chtyp;
+ word32 nav, nbv;
+
+ if ((chtyp = chanp->chtyp) == TRPROC_STBID) val = np->nva.bp[ibi + bi];
+ else if (chtyp == TRPROC_BID) 
+  {
+   /* LOOKATME - can this be low bit of vector - think yes */
+   if (!np->n_isavec) ld_scalval_(&nav, &nbv, np->nva.bp);
+   else __ld_bit(&nav, &nbv, np, bi);
+   val = nav | (nbv << 1);
+  }
+ else { val = 3; __case_terr(__FILE__, __LINE__); }
+ return(val);
+}
+
+/*
+ * evaluate a tranif channel when 3rd control input changes
+ * called from itree ref. location of gate
+ *
+ * since no hard driver change, can ignore non tran channel bits
+ * because they only change when hard drivers change
+ *
+ * SJM 04/11/01 - put back to immediately eval switch channel when enable chgs
+ * LOOKATME - think should change so only called when from to 0 (off)
+ * think to/from 1/x do not change channel
+ */
+extern void __immed_eval_trifchan(struct gate_t *gp)
+{
+ int32 nd_itpop, bi;
+ struct net_t *np;
+ struct traux_t *trap;
+ struct expr_t *xp, *idndp;
+ struct vbinfo_t *vbip;
+ struct vtxlst_t *vtxlp;
+
+ /* SJM 04/23/01 - remove non peri channels since only used for 1 inst case */
+ /* but only one graph for that in any case */
+ /* need to find tranif transistor first terminal and perturb */
+ xp = gp->gpins[0]; 
+ if (xp->optyp == ID || xp->optyp == GLBREF) idndp = xp;  
+ else if (xp->optyp == LSB) idndp = xp->lu.x;
+ else { __case_terr(__FILE__, __LINE__); idndp = NULL; }
+
+ if (idndp->optyp == GLBREF) 
+  { __xmrpush_refgrp_to_targ(idndp->ru.grp); nd_itpop = TRUE; }
+ else nd_itpop = FALSE;
+
+ np = idndp->lu.sy->el.enp;
+ bi = -1;
+ if (xp->optyp == LSB) bi = __get_const_bselndx(xp);
+ if (bi == -1) bi = 0;
+ trap = np->ntraux;
+ vbip = trap->vbitchans[np->nwid*__inum + bi];
+
+ /* add this vertex to relaxation list */
+ vtxlp = add_stchan_chged_vtx(vbip->vivxp, __inst_ptr);
+ vbip->vivxp->vtx_in_vicinity = TRUE;
+ find_chgvtx_vicinity(vtxlp);
+
+ if (nd_itpop) __pop_itstk();
+
+ /* also find and perturb 2nd terminal */
+ xp = gp->gpins[1]; 
+ if (xp->optyp == ID || xp->optyp == GLBREF) idndp = xp;  
+ else if (xp->optyp == LSB) idndp = xp->lu.x;
+ else { __case_terr(__FILE__, __LINE__); idndp = NULL; }
+
+ if (idndp->optyp == GLBREF) 
+  { __xmrpush_refgrp_to_targ(idndp->ru.grp); nd_itpop = TRUE; }
+ else nd_itpop = FALSE;
+
+ np = idndp->lu.sy->el.enp;
+ bi = -1;
+ if (xp->optyp == LSB) bi = __get_const_bselndx(xp);
+ if (bi == -1) bi = 0;
+ trap = np->ntraux;
+ vbip = trap->vbitchans[np->nwid*__inum + bi];
+
+ /* add this vertex to relaxation list */
+ if (!vbip->vivxp->vtx_in_vicinity)
+  {
+   vtxlp = add_stchan_chged_vtx(vbip->vivxp, __inst_ptr);
+   vbip->vivxp->vtx_in_vicinity = TRUE;
+   find_chgvtx_vicinity(vtxlp);
+  }
+
+ if (nd_itpop) __pop_itstk();
+
+ /* do the relaxation only on perturbed in vicinity vertices */
+ stchan_trif_relax();
+ /* final step, assign (maybe schedule) all changed vertices */
+ if (__chg_vtxlst_hdr != NULL) assign_chged_vtxs();
+}
+
+/*
+ * ROUTINES TO DUMP TRAN CHANNELS
+ */
+
+/*
+ * dump all trans in a module
+ */
+extern void __dmp_modtrans(struct mod_t *mdp)
+{
+ register int32 ni, ii;
+ register struct net_t *np;
+ int32 insts, bi2;
+ struct traux_t *trap;
+ struct vbinfo_t *vbip;
+ struct vtx_t *vtxp;
+ char s1[RECLEN], s2[RECLEN];
+
+ for (ni = 0, np = &(mdp->mnets[0]); ni < mdp->mnnum; ni++, np++) 
+  {
+   if ((trap = np->ntraux) == NULL)
+    continue;
+
+   insts = mdp->flatinum;
+   for (ii = 0; ii < insts; ii++)
+    {
+     __push_itstk(mdp->moditps[ii]);
+     for (bi2 = np->nwid - 1; bi2 >= 0; bi2--)
+      {
+       if ((vbip = trap->vbitchans[__inum*np->nwid + bi2])
+        == NULL)
+        {
+         sprintf(s1, "%s.", __msg2_blditree(__xs, __inst_ptr));
+         if (!np->n_isavec) strcpy(s2, ""); else sprintf(s2, "[%d]", bi2);  
+         __dbg_msg("-- net %s%s%s not in any tran channel\n", s1,
+          np->nsym->synam, s2);
+        }  
+       else
+        {
+         if (__chantab[vbip->chan_id].chan_no_vtxs)
+          __dmp_bidchan(&(__chantab[vbip->chan_id]));
+         else { vtxp = vbip->vivxp; __dmp_trchan(vtxp); }
+        }
+      }
+     __pop_itstk();
+    }
+  }
+}
+
+/*
+ * dump a chan. channel - requires set itree loc. context to work
+ */
+extern void __dmp_trchan(struct vtx_t *vtxp)
+{
+ register struct edge_t *ep;
+ int32 bi, chanid, base, ei;
+ struct net_t *np;
+ struct chanrec_t *chanp;
+
+ np = vtxp->vnp;
+ bi = (vtxp->vi1 == -1) ? 0 : vtxp->vi1;
+ base = __inum*np->nwid;
+ chanid = vtxp->vnp->ntraux->vbitchans[base + bi]->chan_id;
+ chanp = &(__chantab[chanid]);
+
+ /* __dbg_msg("<<> marking %s\n", to_vtx(__xs2, vtxp)); */
+ vtxp->vtx_mark = TRUE;
+
+ /* dump the distinguished vertex */
+ __dbg_msg(
+  "-** vertex %s.%s(id=%d, type=%d, mixed wires=%d, mark=%u) edges:\n",
+   __msg2_blditree(__xs, __inst_ptr), to_vtx(__xs2, vtxp), chanid,
+   chanp->chtyp, chanp->chan_diffwtyps, vtxp->vtx_mark); 
+  for (ei = 1, ep = vtxp->vedges; ep != NULL; ep = ep->enxt, ei++)
+   { prt_edge(vtxp, ep, ei); }
+
+ dmp_vtx_edges(vtxp, __inst_ptr); 
+
+ /* turn off marks, to be ready for next change */
+ off_bichan_marks(chanp);
+
+ __dbg_msg("=== end of channel ===\n");
+}
+
+/*
+ * dump inout channel - simple list and each node has own itree context
+ */
+extern void __dmp_bidchan(struct chanrec_t *chanp)
+{
+ register struct bidvtxlst_t *bidvtxlp;
+ int32 chanid;
+ char s1[RECLEN];
+
+ chanid = chanp - __chantab;
+ __dbg_msg(" *** inout channel (id=%d, type=%d, mixed_wires=%d):\n",
+  chanid, chanp->chtyp, chanp->chan_diffwtyps); 
+
+ bidvtxlp = chanp->bid_vtxlp;
+ for (; bidvtxlp != NULL; bidvtxlp = bidvtxlp->bidvtxnxt)
+  {
+   if (bidvtxlp->vi1 == -1) strcpy(s1, bidvtxlp->vnp->nsym->synam);
+   else sprintf(s1, "%s[%d]", bidvtxlp->vnp->nsym->synam, bidvtxlp->vi1);
+   __dbg_msg(" -- vertex %s.%s\n", __msg2_blditree(__xs,
+    bidvtxlp->bidvtx_itp), s1);
+  }
+ __dbg_msg("=== end of channel ===\n");
+}
+
+/*
+ * dump vertices on other side of edges of a vtx 
+ * passed vtx itree loc since itree stack probably not high enough
+ */
+static void dmp_vtx_edges(struct vtx_t *vtxp, struct itree_t *vt1_itp)
+{
+ register struct edge_t *ep;
+ struct itree_t *oside_itp;
+
+ /* mark the root vertex */
+ for (ep = vtxp->vedges; ep != NULL; ep = ep->enxt)
+  { 
+   /* DBG remove -- */
+   if (ep->ev2 == NULL) __misc_terr(__FILE__, __LINE__);
+   /* --- */
+
+   if (ep->ev2->vtx_mark)
+    {
+     /* __dbg_msg("<<> vertex %s already marked\n", to_vtx(__xs2, ep->ev2)); */
+     continue;
+    }
+   /* __dbg_msg("<<> vertex %s not marked\n", to_vtx(__xs2, ep->ev2)); */
+
+   /* for mdprt will always be local */  
+   /* DBG remove --- */
+   if (ep->enpp->npntyp == NP_BIDMDPRT
+    && ep->enpp->npproctyp != NP_PROC_INMOD)
+    __misc_terr(__FILE__, __LINE__); 
+   /* --- */ 
+
+   /* SJM - 05/21/01 - compute oside edge and use call stack since itstk */
+   /* not deep enough */
+   if (ep->edgoside_itp != NULL) oside_itp = ep->edgoside_itp;
+   else oside_itp = vt1_itp;
+
+   dmp_vtx_and_out_edges(ep->ev2, oside_itp);
+
+   /* __dbg_msg("<<> marking %s\n", to_vtx(__xs2, ep->ev2)); */
+   ep->ev2->vtx_mark = TRUE;
+
+   dmp_vtx_edges(ep->ev2, oside_itp);
+  }
+}
+
+/*
+ * dump a vertex and all of its out edges
+ */
+static void dmp_vtx_and_out_edges(struct vtx_t *vtxp,
+ struct itree_t *oside_itp)
+{
+ register int32 ei;
+ register struct edge_t *ep;
+
+ if (vtxp->vtx_mark)
+  {
+   /* ---
+   __dbg_msg("<<> %s marked - out edges not printed\n",
+    to_vtx(__xs2, vtxp));
+   --- */
+   return; 
+  }
+ /* else __dbg_msg("<<> %s not marked\n", to_vtx(__xs2, vtxp)); */
+
+ __push_itstk(oside_itp);
+ __dbg_msg(
+  "=== vertex %s.%s edges:\n", __msg2_blditree(__xs, __inst_ptr),
+  to_vtx(__xs2, vtxp));
+ for (ei = 1, ep = vtxp->vedges; ep != NULL; ep = ep->enxt, ei++)
+  { prt_edge(vtxp, ep, ei); }
+ __pop_itstk();
+}
+
+/*
+ * print edge - itree version (expects start to be on itree stack) 
+ */
+static void prt_edge(struct vtx_t *vtxp, struct edge_t *ep, int32 ei)
+{
+ struct itree_t *eitp, *v2itp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (ei == -1) strcpy(s1, ""); else sprintf(s1, " %d:", ei); 
+ getv2_itp(ep, __inst_ptr, &eitp, &v2itp);
+ __dbg_msg(" -- edge%s %s.%s->%s.%s: npp:\n", s1,
+  __msg2_blditree(__xs, __inst_ptr), to_vtx(s2, vtxp),
+  __msg2_blditree(__xs2, v2itp), to_vtx(s3, ep->ev2));  
+ /* LOOKATME - shouldn't test be internal error */
+ if (vtxp != NULL) __dmp1_nplstel(__inst_mod, vtxp->vnp, ep->enpp);
+}
+
+/*
+ * build an vertex identifying string
+ */
+static char *to_vtx(char *s, struct vtx_t *vp)
+{
+ if (vp == NULL) strcpy(s, "*NONE*");
+ if (vp->vi1 == -1) strcpy(s, vp->vnp->nsym->synam);
+ else sprintf(s, "%s[%d]", vp->vnp->nsym->synam, vp->vi1);
+ return(s);
+}
+
+/*
+ * called with itree loc. of first edge in vitp - 2nd edge and 2nd vtx itp
+ */
+static void getv2_itp(struct edge_t *ep, struct itree_t *vitp, 
+ struct itree_t **eitp, struct itree_t **v2itp)
+{
+ int32 num_itpops;
+
+ if (ep->ev2 == NULL) __arg_terr(__FILE__, __LINE__);
+ /* move forward - vitp is first */
+ num_itpops = 1;
+ __push_itstk(vitp);
+ if (ep->enpp->npproctyp == NP_PROC_INMOD) *eitp = vitp;
+ else
+  {
+   /* SJM 04/17/03 - if XMR does not match - do not change itree loc */
+   if (__move_to_npprefloc(ep->enpp))
+    {
+     *eitp = __inst_ptr;
+     num_itpops++;
+    }
+   else __misc_terr(__FILE__, __LINE__);
+  }
+ /* LOOKATME - bit for concat must be index that is from vtx */
+ /* SJM 08/26/00 - because all xmr/inout edges per inst. can store new itree */
+ if (ep->edgoside_itp != NULL)
+  {
+   __push_itstk(ep->edgoside_itp);
+   num_itpops++;
+  }
+ *v2itp = __inst_ptr;
+ while (num_itpops-- > 0) __pop_itstk();
+}
+
+/*
+ * build drivers on a net
+ *
+ * entire net drivers are not net bit
+ * nothing on itree stack here
+ */
+extern void __dmp_bidnet_drvs(struct net_t *np, struct mod_t *mdp)
+{
+ register struct edge_t *ep;
+ register int32 ei;
+ struct traux_t *trap;
+ struct vbinfo_t *vbip;
+ struct vtx_t *vtxp;
+ char s1[RECLEN], s2[RECLEN], s3[RECLEN];
+
+ if (np->ntraux == NULL) return;
+ if ((trap = np->ntraux) == NULL) return; 
+ if ((vbip = trap->vbitchans[0]) == NULL) return;
+ vtxp = vbip->vivxp;
+ if ((ep = vtxp->vedges) == NULL) return;
+
+ for (ei = 0; ep != NULL; ep = ep->enxt, ei++)
+  { 
+   if (ei == -1) strcpy(s1, ""); else sprintf(s1, " %d:", ei); 
+   __dbg_msg(" -- edge%s %s->%s: npp:\n", s1,
+    to_vtx(s2, vtxp), to_vtx(s3, ep->ev2));  
+   if (vtxp != NULL) __dmp1_nplstel(mdp, vtxp->vnp, ep->enpp);
+  }
+}
+
+/*
+ * ROUTINES TO BUILD XL STYLE CONNECTED LOAD/DRIVER NET/BIT TABLES
+ */
+
+/*
+ * build net/bit vertex table for all net/bits that contribute xl style 
+ * loads to acc_ or vpi_ iterator
+ *
+ * LOOKATME - trying to mimic xl style flattening for loads here
+ */
+extern int32 __bld_xl_drvld_vtxtab(struct net_t *np, int32 bi,
+ struct itree_t *itp, int32 is_load)
+{
+ register struct net_pin_t *npp;
+ int32 ix_insert, vi, osbi, fromr_bi, catel_bi;
+ struct xldlnpp_t *xldlp, *xldlp2;
+ struct itree_t *ositp;
+ struct mod_t *osmdp;
+ struct mod_pin_t *mpp;
+ struct net_t *osnp;
+ struct expr_t *xp, *catxp;
+
+ __xldl_hdr = __last_xldl = NULL;
+
+ /* know always at least one vertex - needed for actual lds/drvrs in iter */
+ /* this sets ix insert loc. */
+ vi = get_xldl_vtx(itp, np, bi, &ix_insert);
+ /* DBG remove --- */
+ if (vi != -1) __vpi_terr(__FILE__, __LINE__);
+ /* -- */
+ /* add first net/bit vertex */
+ vi = add_xldl_vtx(itp, np, bi, ix_insert);
+
+ /* add any iconn or mod port 1 bit npp's to a list for more processing */ 
+ fill_port_npps(np, bi, itp);
+ /* common case of xl style and local ld/driver iterator same */
+ if (__xldl_hdr == NULL) return(__num_xldlvtxs);
+ 
+ for (; __xldl_hdr != NULL;)
+  {
+   /* get first unprocessed npp */
+   xldlp = __xldl_hdr;
+   npp = xldlp->xlnpp;
+   __push_itstk(xldlp->xlitp);
+
+   /* move to other side */
+   switch ((byte) npp->npntyp) {
+    /* SJM 09/20/02 - never see PB forms for inouts */ 
+    case NP_ICONN: case NP_BIDICONN:
+     /* other side is mdprt */
+     ositp = &(__inst_ptr->in_its[npp->elnpp.eii]);
+     osmdp = ositp->itip->imsym->el.emdp;
+     mpp = &(osmdp->mpins[npp->obnum]);
+     if (is_load) 
+      {
+       if (npp->npntyp != NP_BIDICONN && mpp->mptyp != IO_IN) 
+        goto nxt_xlld_npp;
+      }
+     else
+      {
+       if (npp->npntyp != NP_BIDICONN && mpp->mptyp != IO_OUT) 
+        goto nxt_xlld_npp;
+      }
+     xp = mpp->mpref;
+     break;
+    case NP_MDPRT: case NP_BIDMDPRT:
+     /* other side is iconn */
+     /* access port before mosing up */
+     mpp = &(__inst_mod->mpins[npp->obnum]);
+
+     /* DBG remove -- */
+     if (__inst_ptr->up_it == NULL) __vpi_terr(__FILE__, __LINE__);
+     /* --- */
+     ositp = __inst_ptr->up_it;
+     osmdp = ositp->itip->imsym->el.emdp;
+     if (is_load) 
+      {
+       if (npp->npntyp != NP_BIDMDPRT && mpp->mptyp != IO_OUT) 
+        goto nxt_xlld_npp;
+      }
+     else
+      {
+       if (npp->npntyp != NP_BIDMDPRT && mpp->mptyp != IO_IN) 
+        goto nxt_xlld_npp;
+      }
+     xp = __inst_ptr->itip->ipins[npp->obnum]; 
+     break;
+    default:
+     goto nxt_xlld_npp;
+   }
+   /* add other side npp to end of list - expr, net, bit set */
+   catel_bi = -1;
+   if (npp->npaux == NULL) fromr_bi = bi;
+   else
+    { 
+     if (npp->npaux->nbi1 == -1) fromr_bi = bi;
+     /* ??? LOOKATME - why is npp low psel bit subtracted off */  
+     else fromr_bi = bi - npp->npaux->nbi2.i;
+
+     /* in case this side expr in concat need low of where in concat */
+     /* so can add to otherside index to get matching oside bit */
+     if (npp->npaux->lcbi1 != -1)
+      { 
+       fromr_bi = bi + npp->npaux->lcbi1;
+       catxp = xp;
+       xp = find_cat_oside_xp(catxp, fromr_bi, &(catel_bi));
+      }
+    }
+   osnp = xldrvld_to_netbit(xp, ((catel_bi == -1) ? fromr_bi : catel_bi),
+    &(osbi), ositp); 
+   if (osbi == -2) goto nxt_xlld_npp;
+
+   /* try to add net vertex - added unless already in table */
+   if ((vi = get_xldl_vtx(ositp, osnp, osbi, &ix_insert)) != -1)
+    {
+     if (__debug_flg)
+      {
+       __dbg_msg(
+        " -- net %s bit %d in %s already in xl style load/drive list\n",
+        osnp->nsym->synam, osbi, __msg2_blditree(__xs, ositp));
+      }
+     goto nxt_xlld_npp;
+    }
+
+   /* add this in sorted position in table */ 
+   add_xldl_vtx(ositp, osnp, osbi, ix_insert);
+   /* also add all its connecting npp's */
+   fill_port_npps(osnp, osbi, ositp);
+
+nxt_xlld_npp:
+   __pop_itstk();
+   /* done with current that is on front so free and update header */
+   xldlp2 = __xldl_hdr->xlnxt; 
+   __my_free((char *) __xldl_hdr, sizeof(struct xldlnpp_t)); 
+   __xldl_hdr = xldlp2;
+  }
+ return(__num_xldlvtxs);
+}
+
+/*
+ * get net and bit from expr for buildin
+ * given an driv tran channel lhs non concatenate expression get net and bit
+ *
+ * almost same as tranx to net bit
+ * sets bi to -2 for other side out of this side range or not constant ndx
+ */
+static struct net_t *xldrvld_to_netbit(register struct expr_t *xp,
+ int32 fromr_bi, int32 *bi, struct itree_t *oside_itp)
+{
+ register struct net_t *np;
+ int32 ri1, ri2;
+
+ np = __find_tran_conn_np(xp);
+ if (xp->optyp == LSB)
+ {
+   __push_itstk(oside_itp);
+   if (xp->ru.x->optyp != NUMBER && xp->ru.x->optyp != ISNUMBER) *bi = -2;
+   else
+    {
+     *bi = __get_const_bselndx(xp);
+     if (fromr_bi > 0) *bi = -2;
+    }
+   __pop_itstk();
+   return(np);
+  }
+ if (xp->optyp == PARTSEL)
+  {
+   ri1 = __contab[xp->ru.x->lu.x->ru.xvi];
+   ri2 = __contab[xp->ru.x->ru.x->ru.xvi];
+   if (fromr_bi == -1) *bi = ri2;
+   else { *bi = ri2 + fromr_bi; if (*bi > ri1) *bi = -2;  }
+   return(np);
+  }
+ /* this side is 1 bit scalar */
+ if (!np->n_isavec)
+  {
+   *bi = -1;
+   if (fromr_bi > 0) *bi = -2;
+  }
+ else { if (fromr_bi >= np->nwid) *bi = -2; else *bi = fromr_bi;  }
+ return(np);
+}
+
+/*
+ * add mod port and iconn edges (npps) connecting to net or net bit to list
+ *
+ * this include all npp's that are one bit and match bit if bit select
+ * filtering out other type (non load or non driver) done elsewhere
+ */
+static void fill_port_npps(struct net_t *np, int32 bi, struct itree_t *itp)
+{
+ register struct net_pin_t *npp;
+ 
+ __push_itstk(itp);
+ /* first all npp loads connected to ports */
+ for (npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   /* only consider iconn and mod port npps */
+   if (npp->npntyp != NP_ICONN && npp->npntyp != NP_MDPRT) continue;
+
+   add_match_vtxs(np, npp, bi);
+  }
+ /* will be no I/O drivers and no tran channel for reg */
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   /* DBG remove --- */
+   if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   goto done;
+  }
+ /* then all npp drivers connected to ports */
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   /* only consider iconn and mod port npps */
+   if (npp->npntyp != NP_ICONN && npp->npntyp != NP_MDPRT) continue;
+
+   add_match_vtxs(np, npp, bi);
+  }
+ /* tran channel connections if they exist */
+ if (np->ntraux == NULL) goto done;
+
+ /* iconn tran channel connections are all loads and all drivers */
+ for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
+  {
+   /* only consider bid iconn and bid mod port npps */
+   if (npp->npntyp != NP_BIDICONN && npp->npntyp != NP_BIDMDPRT) continue;
+
+   add_match_vtxs(np, npp, bi);
+  } 
+done:
+ __pop_itstk();
+}
+
+/*
+ * add right inst and right bit npps to port vertex list
+ */
+static void add_match_vtxs(struct net_t *np, struct net_pin_t *npp, int32 bi)  
+{
+ int32 ri1, ri2;
+ struct xldlnpp_t *xldlp;
+
+ /* filter out per inst. that is not this instance */
+ if (npp->npproctyp == NP_PROC_FILT
+  && npp->npaux->npu.filtitp != __inst_ptr) return;
+
+ /* LOOKATME - what happens with xmr iconns - for now not in xl iters */
+ if (npp->npproctyp == NP_PROC_GREF) return;
+
+ /* this must run with right itree loc. (for vector ri1, ri2 h:0 forms */
+ __get_bidnpp_sect(np, npp, &ri1, &ri2);
+ /* xl drives and loads only combined for scalar or bit select connects */
+ /* any scalar must match */
+ if (ri1 == -1)
+  {
+   /* DBG remove --- */
+   if (bi != -1) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   goto got_match;
+  }
+ /* SJM 01/28/05 - old algorithm that stop on entire vector or psel */
+ /* wrong - must match as usual */
+ if (bi > ri1 || bi < ri2) return;
+
+got_match:
+  xldlp = (struct xldlnpp_t *) __my_malloc(sizeof(struct xldlnpp_t));
+  xldlp->xlnpp = npp;
+  xldlp->xlitp = __inst_ptr;
+  xldlp->xlnxt = NULL;
+
+  if (__last_xldl == NULL) __xldl_hdr = xldlp;
+  else __last_xldl->xlnxt = xldlp;
+  __last_xldl = xldlp;
+}
+
+/*
+ * search sorted index into xl drive/load vertex table for matching vertex
+ *
+ * sets ix_insert index if not found 
+ * binary search better even for small table
+ */
+static int32 get_xldl_vtx(struct itree_t *itp, struct net_t *np, int32 bi,
+ int32 *ix_insert)
+{
+ register int32 m, cv;
+ int32 l, h;
+ register struct xldlvtx_t *xldlvp;
+
+ if (__num_xldlvtxs <= 0) { *ix_insert = 0; return(-1); }
+ l = 0; h = __num_xldlvtxs - 1;
+ for (;;)
+  {
+   m = (l + h)/2;
+   xldlvp = __xldlvtxind[m];
+   /* first sort by module name */
+   if ((cv = strcmp(xldlvp->dlitp->itip->imsym->synam,
+    itp->itip->imsym->synam)) == 0)
+    {
+     /* then by instance of module */
+     if ((cv = xldlvp->dlitp->itinum - itp->itinum) == 0) return(m);
+     /* then by net name */
+     if ((cv = strcmp(xldlvp->dlnp->nsym->synam, np->nsym->synam)) == 0)
+      {
+       /* finally by bit index */
+       if ((cv = xldlvp->dlbi - bi) == 0) return(m);
+      }
+    }
+   if (cv < 0) l = m + 1; else h = m - 1;
+   if (h < l) { *ix_insert = l; break; }
+  }
+ return(-1);
+}
+
+/*
+ * add an a new xl drv/ld vertex (net/bit)
+ *
+ * know now in table and ix_insert set to place to insert or not called 
+ * must call get xldl vtx before calling this to set ix_insert
+ */
+static int32 add_xldl_vtx(struct itree_t *itp, struct net_t *np, int32 bi,
+ int32 ix_insert)
+{
+ register int32 ki;
+ int32 osize, nsize;
+ struct xldlvtx_t *xldlvp;
+
+ if (++__num_xldlvtxs > __siz_xldlvtxtab)
+  {
+   /* first grow table because few new keywords, fibronaci growth */
+   if (__siz_xldlvtxtab == 0)
+    {
+     nsize = 100*sizeof(struct xldlvtx_t *);
+     __xldlvtxind = (struct xldlvtx_t **) __my_malloc(nsize);
+     __siz_xldlvtxtab = 100;
+    }
+   else
+    {
+     osize = __siz_xldlvtxtab*sizeof(struct xldlvtx_t *);
+     nsize = 2*osize;
+     __siz_xldlvtxtab *= 2;
+     __xldlvtxind = (struct xldlvtx_t **) __my_realloc((char *) __xldlvtxind,
+      osize, nsize);
+   }
+  }
+ /* allocate and fill new record */
+ xldlvp = (struct xldlvtx_t *) __my_malloc(sizeof(struct xldlvtx_t));
+ xldlvp->dlnp = np;
+ xldlvp->dlbi = bi;
+ xldlvp->dlitp = itp;
+ 
+ /* copy downward from end making room at ix_insert */
+ for (ki = __num_xldlvtxs - 1; ki > ix_insert; ki--)
+  __xldlvtxind[ki] = __xldlvtxind[ki - 1];
+ __xldlvtxind[ix_insert] = xldlvp;
+ 
+ return(ix_insert);
+}
+
+/*
+ * ROUTINES TO FORCE/RELEASE ALL WIRES IN SWITCH CHANNEL
+ */
+
+/*
+ * qc force wrapper than decomposes vector net object into bit selects
+ * result is that for every bit a switch channel is forced
+ *
+ * know biti down to bitj where values is wid -1 to 0 for wire or psel rng
+ * rhsbi is rhs value bit matching low bit j
+ * this is called in stmt itree context but if lhs xmr, itp passed
+ * and returns also in stmt itree context - called proc handle push/pop
+ */
+extern void __qc_tran_wireforce(struct net_t *np, int32 biti, int32 bitj,
+ int32 rhsbi, struct itree_t *itp, struct st_t *qcfstp)
+{
+ register int32 bi;
+ word32 aval, bval;
+ struct xstk_t *xsp;
+ struct expr_t *rhsx;
+
+ rhsx = qcfstp->st.sqca->qcrhsx; 
+ /* this converts rhs if needed and makes lhs right width */
+ /* must eval rhs in itree context of rhs (i.e. statement) */
+ xsp = __eval_assign_rhsexpr(rhsx, qcfstp->st.sqca->qclhsx);
+ /* do rhs bsel here so pass a/b words with low bit asign bit */ 
+ if (rhsbi == -1) rhsbi = 0;
+
+ if (!np->n_isavec)
+  {
+   /* for scalar biti and bitj will be 0 */
+   /* DBG remove -- */
+   if (biti != 0 || bitj != 0) __misc_terr(__FILE__, __LINE__);
+   /* -- */
+
+   aval = rhsbsel_(xsp->ap, rhsbi);
+   bval = rhsbsel_(xsp->bp, rhsbi);
+   /* SJM 03/15/01 - now just forcing the one wire - caller re-evals channel */
+   /* SJM 04/15/01 - must pass any xmr itree context */
+   do_qc_wire_intran_force(np, -1, aval, bval, itp);
+  }
+ else
+  {
+   for (bi = biti; bi >= bitj; bi--)
+    {
+     aval = rhsbsel_(xsp->ap, rhsbi + (bi - bitj));
+     bval = rhsbsel_(xsp->bp, rhsbi + (bi - bitj));
+     /* SJM 04/15/01 - must pass any xmr itree context */
+     do_qc_wire_intran_force(np, bi, aval, bval, itp);
+    }
+  }
+ __pop_xstk();
+}
+
+/*
+ * do force for one net-bit or scalar in tran channel 
+ */
+static void do_qc_wire_intran_force(struct net_t *np, int32 biti, word32 aval,
+ word32 bval, struct itree_t *lhs_itp)
+{
+ register int32 ibase;
+ int32 nd_itpop;
+
+ /* debug message must use statment not lhs itree context */
+ if (__debug_flg && __ev_tracing)
+  {
+   char s1[RECLEN], s2[RECLEN];
+
+   if (np->n_isavec) sprintf(s1, "%s[%d]", np->nsym->synam, biti); 
+   else strcpy(s1, np->nsym->synam);
+   __tr_msg(
+    ":: quasi-continuous force of switch channel wire %s in %s from force at %s now %s\n",
+    s1, __msg2_blditree(__xs2, __inst_ptr),
+     __bld_lineloc(__xs, (word32) __sfnam_ind, __slin_cnt),
+    __to_timstr(s2, &__simtime));
+  }
+
+ nd_itpop = FALSE;
+ if (lhs_itp != NULL) { __push_itstk(lhs_itp); nd_itpop = TRUE; }
+
+ /* this must run in itree context of lhs (maybe an xmr) */
+ ibase = __inum*np->nwid;
+ if (!np->n_isavec)
+  {
+   __bit1_vpi_or_tran_wireforce(np, &aval, &bval, ibase, 0, 0,
+    "switch channel");
+
+   /* DBG remove -- */
+   if (biti != -1) __misc_terr(__FILE__, __LINE__); 
+   /* --- */
+  }
+ else
+  {
+   /* DBG remove -- */
+   if (biti == -1) __misc_terr(__FILE__, __LINE__); 
+   /* --- */
+   /* because right bit value already selected into a/b low bit, rhsbi is 0 */  
+   __bit1_vpi_or_tran_wireforce(np, &aval, &bval, ibase, biti, 0,
+    "switch channel");
+  }
+
+ /* notice can have both many wire specific and many all cbs */
+ /* call backs also need to match itree loc for lhs xmr */
+ if (__num_vpi_force_cbs > 0) __find_call_force_cbs(np, biti);
+ if (__vpi_force_cb_always) __cb_all_rfs(np, biti, TRUE);
+ 
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * qc release wrapper than decomposes vector net object into bit selects
+ * result is that for every bit a switch channel is released
+ *
+ * SJM 11/24/00 - because no need to get original force value this
+ * can use lhs expr and net/bit
+ * SJM 04/15/01 - need to pass any lhs itree context if lhs xmr
+ */
+extern void __qc_tran_wirerelease(struct net_t *np, int32 biti, int32 bitj,
+ struct itree_t *itp, struct expr_t *lhsx)
+{
+ register int32 bi;
+
+ if (!np->n_isavec)
+  {
+   /* DBG remove -- */
+   if (biti != 0 || bitj != 0) __misc_terr(__FILE__, __LINE__);
+   /* -- */
+   do_qc_wire_intran_release(np, -1, lhsx, itp);
+  }
+ else
+  {
+   for (bi = biti; bi >= bitj; bi--)
+    { do_qc_wire_intran_release(np, bi, lhsx, itp); }
+  }
+}
+
+/*
+ * do release for one net-bit or scalar in tran channel 
+ *
+ * this must push lhs xmr itree loc that it is passed if needed 
+ * this handles release PLI callbacks if needed
+ */
+static void do_qc_wire_intran_release(struct net_t *np, int32 biti,
+ struct expr_t *lhsx, struct itree_t *itp)
+{
+ register int32 bi, ibase;
+ int32 bit_forced, nd_itpop;
+ struct qcval_t *frc_qcp;
+ char s1[RECLEN];
+
+ ibase = __inum*np->nwid;
+ /* messages must use stmt itree loc */
+ for (bi = 0; bi < np->nwid; bi++)
+  {
+   if (np->nu2.qcval[ibase + bi].qc_active) goto some_bit_forced;
+  }
+ strcpy(s1, " - no bits forced");
+ __sgfinform(465, "attempted release of %s in instance %s failed%s",
+  __msgexpr_tostr(__xs2, lhsx), __msg2_blditree(__xs, __inst_ptr), s1);
+ /* SJM - 04/15/01 - if nothing forced must not exec any call backs */ 
+ return;
+
+some_bit_forced:
+ if (__debug_flg && __ev_tracing)
+  {
+   char s2[RECLEN];
+
+   if (np->n_isavec) sprintf(s1, "%s[%d]", np->nsym->synam, biti); 
+   else strcpy(s1, np->nsym->synam);
+
+   __tr_msg(
+    ":: quasi-continuous release of switch channel wire %s in %s from release at %s now %s\n",
+    s1, __msg2_blditree(__xs, __inst_ptr),
+    __bld_lineloc(__xs2, (word32) __sfnam_ind, __slin_cnt),
+    __to_timstr(s2, &__simtime));
+  }
+
+ nd_itpop = FALSE; 
+ if (itp != NULL) { nd_itpop = TRUE; __push_itstk(itp); }
+
+ /* know some forced or will not get here */
+ bit_forced = TRUE;
+ bi = (biti == -1) ? 0 : biti;
+ frc_qcp = &(np->nu2.qcval[ibase + bi]);
+ if (!frc_qcp->qc_active) bit_forced = FALSE;
+ else frc_qcp->qc_active = FALSE;
+
+ /* now that released, assign value from current drivers */ 
+ __assign_1mdrwire(np);
+
+ if (!bit_forced)
+  {
+   if (nd_itpop) __pop_itstk();
+
+   strcpy(s1, " - some bits forced");
+   __sgfinform(465, "attempted release of %s in instance %s failed%s",
+    __msgexpr_tostr(__xs2, lhsx), __msg2_blditree(__xs, __inst_ptr), s1);
+
+   if (nd_itpop) __push_itstk(itp);
+  } 
+
+ /* FIXME - why not calling for every bit in range - only 1 bit possible? */
+ /* notice can have both many wire specific and many all cbs */
+ if (__num_vpi_rel_cbs > 0) __find_call_rel_cbs(np, biti);
+ if (__vpi_rel_cb_always) __cb_all_rfs(np, biti, FALSE);
+
+ if (nd_itpop) __pop_itstk(); 
+}
+
+/*
+ * VPI ROUTINES TO FORCE/RELEASE ALL WIRES IN SWITCH CHANNEL
+ */
+
+/*
+ * vpi force wrapper than decomposes vector net object into bit selects
+ * result is that for every bit a switch channel is forced
+ * here since comes from vpi passed right force itree context
+ */
+extern void __tran_wire_vpi_force(struct net_t *np, word32 *ap, word32 *bp,
+ int32 ndx) 
+{
+ register int32 bi;
+
+ if (ndx == -1 && np->n_isavec)
+  {
+   for (bi = np->nwid - 1; bi >= 0; bi--)
+    { do_vpi_wire_intran_force(np, bi, ap, bp); }
+  }
+ else do_vpi_wire_intran_force(np, ndx, ap, bp);
+}
+
+/*
+ * do vpi force for one net-bit or scalar in tran channel 
+ *
+ * know itree change already made if needed (no different lhs context)
+ * never a need for separate rhs vpi force since user sets and passes value
+ * also do not need dces for these
+ */
+static void do_vpi_wire_intran_force(struct net_t *np, int32 ndx,
+ word32 *ap, word32 *bp)
+{
+ register int32 ibase;
+ char s3[RECLEN]; 
+
+ /* make sure assign/force table exists */ 
+ /* AIV 03/09/05 - force inhibition requires allocated bit set */
+ if (!np->frc_assgn_allocated) __alloc_qcval(np);
+
+ if (__debug_flg && __ev_tracing)
+  {
+   if (ndx == -1) strcpy(__wrks1, np->nsym->synam);
+   else sprintf(__wrks1, "%s[%d]", np->nsym->synam,
+    __unnormalize_ndx(np, ndx));
+   __tr_msg(":: vpi_put_value force of wire %s in %s now %s\n", __wrks1,
+    __msg2_blditree(__wrks2, __inst_ptr), __to_timstr(s3, &__simtime));
+  }
+
+ ibase = __inum*np->nwid;
+ if (!np->n_isavec)
+  {
+   /* SJM 02/23/05 - since scalar do not need ndx check */
+   /* SJM 11/14/00 - must also check cbs for scalar case */
+   __bit1_vpi_or_tran_wireforce(np, ap, bp, ibase, 0, 0,
+    "switch channel vpi_put_value");
+   ndx = -1;
+   goto chk_cbs;
+  }
+ /* SJM 02/23/05 - it is legal to force bit selects too */ 
+ __bit1_vpi_or_tran_wireforce(np, ap, bp, ibase, ndx, ndx,
+  "switch channel vpi_put_value");
+
+chk_cbs:
+ /* notice can have both many wire specific and many all cbs */
+ if (__num_vpi_force_cbs > 0) __find_call_force_cbs(np, ndx);
+ if (__vpi_force_cb_always) __cb_all_rfs(np, ndx, TRUE);
+}
+
+/*
+ * vpi release wrapper than decomposes vector net object into bit selects
+ *
+ * result is that for every bit a switch channel released
+ * never a need for separate rhs vpi force since user sets and passes value
+ * here since comes from vpi passed right force itree context
+ */
+extern void __tran_wire_vpi_release(struct net_t *np, int32 ndx) 
+{
+ register int32 bi;
+
+ if (ndx == -1 && np->n_isavec)
+  {
+   for (bi = np->nwid - 1; bi >= 0; bi--)
+    {
+     /* SJM 03/15/01 - now release entire wire but nothing else in chan */
+     do_vpi_wire_intran_release(np, bi);
+     /* after release must re-compute tran channel */
+     __eval_tran_1bit(np, bi);
+    }
+  }
+ else
+  {
+   /* SJM 03/15/01 - now just release one wire */
+   do_vpi_wire_intran_release(np, ndx);
+   /* since this is scalar eval entire wire */ 
+   __eval_tran_bits(np);
+  }
+}
+
+/*
+ * do vpi release for one net-bit or scalar in tran channel 
+ * know itree change already made if needed
+ */
+static void do_vpi_wire_intran_release(struct net_t *np, int32 ndx)
+{
+ register int32 bi, ibase;
+ int32 bit_forced;
+ struct qcval_t *frc_qcp;
+ char s3[RECLEN];
+ 
+ ibase = __inum*np->nwid;
+ if (ndx == -1) bi = 0; else bi = ndx;
+ frc_qcp = &(np->nu2.qcval[ibase + bi]);
+ if (!frc_qcp->qc_active)
+  {
+no_force: 
+   strcpy(__wrks1, " - not forced");
+   if (ndx == -1) strcpy(__wrks2, np->nsym->synam);  
+   else sprintf(__wrks2, "%s[%d]", np->nsym->synam,
+    __unnormalize_ndx(np, ndx));
+   __vpi_err(2102, vpiNotice,
+    "attempted vpi_put_value release of wire %s in %s failed%s", __wrks2,
+    __msg2_blditree(s3, __inst_ptr), __wrks1);
+   goto done;
+  }
+
+ if (__debug_flg && __ev_tracing)
+  {
+   if (ndx == -1) strcpy(__wrks2, np->nsym->synam);  
+   else sprintf(__wrks2, "%s[%d]", np->nsym->synam,
+    __unnormalize_ndx(np, ndx));
+   __tr_msg(":: vpi_put_value release of wire %s in %s now %s\n", __wrks2,
+    __msg2_blditree(__wrks1, __inst_ptr), __to_timstr(s3, &__simtime));
+  }
+
+ /* know some forced or will not get here */
+ bit_forced = TRUE;
+ if (!frc_qcp->qc_active) bit_forced = FALSE;
+ else frc_qcp->qc_active = FALSE;
+ 
+ /* release is immedate assign even if wire has delay no schedule */
+ /* LOOKATME - could this be 1 bit eval? */
+ __assign_1mdrwire(np);
+ if (!bit_forced && ndx == -1) goto no_force;
+
+done:
+ /* notice can have both many wire specific and many all cbs */
+ if (__num_vpi_rel_cbs > 0) __find_call_rel_cbs(np, ndx);
+ if (__vpi_rel_cb_always) __cb_all_rfs(np, ndx, FALSE);
+}
+
+/*
+ * vpi force wrapper than decomposes vector net object into bit selects
+ * result is that for every bit a switch channel is forced
+ */
+extern void __tran_exec_putv_wire_softforce(struct net_t *np, word32 *ap,
+ word32 *bp, int32 ndx) 
+{
+ register int32 bi;
+
+ if (ndx == -1 && np->n_isavec)
+  {
+   for (bi = np->nwid - 1; bi >= 0; bi--)
+    { do_putv_wire_intran_softforce(np, bi, ap, bp); }
+  }
+ else do_putv_wire_intran_softforce(np, ndx, ap, bp);
+}
+
+/*
+ * do vpi force for one net-bit or scalar in tran channel 
+ * know itree change already made if needed
+ */
+static void do_putv_wire_intran_softforce(struct net_t *np, int32 ndx,
+ word32 *ap, word32 *bp)
+{
+ struct qcval_t *frc_qcp;
+ /* case 1: scalar */
+ if (!np->n_isavec)
+  {
+   /* DBG remove -- */
+   if (ndx != -1) __misc_terr(__FILE__, __LINE__);
+   /* -- */
+
+   /* this add the changed wire to nchglst if needed */
+   if (np->nu2.qcval != NULL)
+    {
+     /* return F if all of wire forced, nothing to do */ 
+     /* if T, this will correct bits in ap and bp so actual assign is right */
+     if (!__correct_forced_newwireval(np, ap, bp)) return;
+    }
+   if (np->nchg_nd_chgstore) __chg_st_val(np, ap, bp);
+   else __st_val(np, ap, bp);
+   return;
+  }
+
+ /* DBG remove -- */
+ if (ndx == -1) __misc_terr(__FILE__, __LINE__);
+ /* -- */
+
+ /* case 2: wire bit select */
+ /* if the 1 bit is really forced nothing to do */
+ /* SJM 12/23/02 - if not allocated can't be active */
+ if (!np->frc_assgn_allocated) return;
+ frc_qcp = &(np->nu2.qcval[np->nwid*__inum + ndx]);
+ if (frc_qcp->qc_active) return;
+
+ /* else simple bit assign */
+ if (np->nchg_nd_chgstore) __chg_st_bit(np, ndx, ap[0], bp[0]);
+ else __st_bit(np, ndx, ap[0], bp[0]); 
+}
diff --git a/src/v_vpi.c b/src/v_vpi.c
new file mode 100644
index 0000000..b1cc853
--- /dev/null
+++ b/src/v_vpi.c
@@ -0,0 +1,6145 @@
+/* Copyright (c) 1995-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * first module to implement pli vpi_ routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <dlfcn.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* local prototypes */
+static int32 lbnam_so_suffix(char *);
+static int32 check_systf(p_vpi_systf_data, int32 *);
+static int32 chk_idnam_systfs(char *);
+static void exec_vpisysfunc_compiletf(struct vpisystf_t *);
+static void exec_vpisystask_compiletf(struct vpisystf_t *);
+static struct sy_t *task_add_vpi_systf(char *, int32);
+static struct sy_t *func_add_vpi_systf(char *, int32);
+static vpiHandle valchg_cb_register(p_cb_data);
+static int32 chk_valchg_cb(p_cb_data, struct h_t *);
+static vpiHandle bld_cbrec(p_cb_data, word32);
+static void bld_cbvc_dces(struct expr_t *, struct cbrec_t *);
+static void linkon_cb_dce(struct net_t *, int32, int32, struct gref_t *,
+ struct cbrec_t *, int32);
+static vpiHandle gateout_valchg_register(struct h_t *, struct t_cb_data *);
+static void set_dce_strenchg_on(struct dceauxlst_t *);
+static vpiHandle rf_cb_register(p_cb_data, int32);
+static int32 chk_rf_cb(p_cb_data, struct h_t *, char *);
+static vpiHandle rf_all_register_cb(p_cb_data, int32);
+static vpiHandle delay_cb_register(register p_cb_data);
+static int32 chk_delay_cb(p_cb_data, struct h_t *);
+static void exec_vpi_delaycbs(int32);
+static void free_cbrec(struct cbrec_t *);
+static vpiHandle action_cb_register(register p_cb_data);
+static void linkout_allcb(struct cbrec_t *, int32);
+static void linkout_gateout_cb(struct cbrec_t *); 
+static void linkout_action_cb(struct cbrec_t *);
+static char *to_cbtypnam(char *, int32);
+static vpiHandle get_cursystfcall(struct h_t *);
+static vpiHandle get_inmod_itp(struct h_t *);
+static vpiHandle get_obj_index(struct h_t *);
+static vpiHandle get_obj_range(struct h_t *, int32);
+static vpiHandle get_obj_parent(struct h_t *);
+static void exprobj_to_itreeloc(struct itree_t **, struct task_t **, 
+ struct expr_t *, struct itree_t *, struct task_t *);
+static vpiHandle get_obj_side(struct h_t *, int32);
+static vpiHandle bld_scope_par(struct h_t *, struct task_t *);
+static vpiHandle getbit_lowconn(struct h_t *);
+static vpiHandle getexpr_lowconn(struct h_t *);
+static vpiHandle getbit_highconn(struct h_t *);
+static struct expr_t *find_catxp_frombit(struct expr_t *, int32, int32 *);
+static vpiHandle getexpr_highconn(struct h_t *);
+static void no1_1to1h_err(word32, word32, struct h_t *);
+static void no_1to1h_err(int32, struct h_t *);
+static vpiHandle get_tchk_term(word32, struct h_t *);
+static vpiHandle get_cond(struct h_t *);
+static vpiHandle bld_1to1_exprclass_handle(struct h_t *);
+static vpiHandle mk_pthterm_exprclass_handle(struct net_t *, int32, int32,
+ struct itree_t *); 
+static vpiHandle get_obj_scope(struct h_t *);
+static vpiHandle get_disable_scope(struct h_t *);
+static vpiHandle get_contained_stmt(struct h_t *);
+static vpiHandle get_dctrl_stmt(struct h_t *, int32);
+static vpiHandle get_udpdef_from_inobj(struct h_t *);
+static vpiHandle get_contained_udp_init(struct h_t *);
+static vpiHandle get_up_poundparam_expr(struct h_t *);
+static vpiHandle bld_itree_iterator(struct h_t *);
+static vpiHandle bld_type_iterator(struct h_t *);
+static vpiHandle bld_inst_iterator(struct h_t *);
+static vpiHandle bld_udpdef_iterator(struct h_t *);
+static void mustbe_inmoditer_err(word32, struct h_t *);
+static vpiHandle bld_scope_iterator(register struct h_t *);
+static vpiHandle bld_symtabs_iterator(struct symtab_t *, struct itree_t *);
+static void fill_scopehandle(struct hrec_t *, struct symtab_t *);
+static vpiHandle bld_net_iterator(struct h_t *, word32);
+static vpiHandle bld_listofnets_iter(struct net_t *, int32, struct itree_t *,
+ word32, struct task_t *);
+static int32 cnt_typnetnum(register struct net_t *, int32, word32);
+
+
+static vpiHandle bld_initalw_iterator(struct h_t *);
+static vpiHandle bld_conta_iterator(struct h_t *);
+static vpiHandle bld_gate_iterator(struct h_t *);
+static vpiHandle bld_modpth_iterator(struct h_t *);
+static vpiHandle bld_tchk_iterator(struct h_t *);
+static vpiHandle bld_param_iterator(struct h_t *, int32);
+static vpiHandle bld_listofparams_iter(struct net_t *, int32, struct itree_t *,
+ struct task_t *, int32);
+static vpiHandle bld_paramarr_iterator(struct h_t *, int32);
+static vpiHandle bld_specparam_iterator(struct h_t *);
+static vpiHandle bld_defparam_stmt_iterator(struct h_t *);
+
+/* NEED? static void shrink_systfdata_tab(void); */
+static void exec_vpi_actioncbs(int32);
+static void exec_vpi_tchkerr(int32, struct tchk_t *, struct itree_t *);
+
+/* extern prototypes (maybe defined in this module) */
+extern void __call_vlog_startup_procs(void);
+extern void __chkbld_vpi_systf_func(struct expr_t *);
+extern void __chkbld_vpi_systf_task(struct st_t *);
+extern void __vpi_sysf_calltf(struct expr_t *);
+extern void __vpi_syst_calltf(struct st_t *);
+extern char *__cb_reason_to_nam(char *, int32);
+extern int32 __expr_is_vpiconst(struct expr_t *);
+extern void __find_call_force_cbs(struct net_t *, int32);
+extern void __find_call_rel_cbs(struct net_t *, int32);
+extern void __cb_all_rfs(struct net_t *, int32, int32);
+extern void __cbvc_callback(struct cbrec_t *, struct h_t *);
+extern void __delay_callback(i_tev_ndx);
+extern void __vpi_startreset_trycall(void);
+extern void __vpi_endreset_trycall(void);
+extern void __vpi_endcomp_trycall(void);
+extern void __vpi_startsim_trycall(void);
+extern void __vpi_endsim_trycall(void);
+extern void __vpi_enteriact_trycall(void);
+extern void __vpi_exitiact_trycall(void);
+extern void __vpi_iactscopechg_trycall(void);
+extern void __vpi_del_nxtsimtim_trycall(void);
+extern void __vpi_del_rosync_call(void);
+extern void __vpi_tchkerr_trycall(struct tchk_t *, struct itree_t *);
+extern void __vpi_error_trycall(void);
+extern struct task_t *__find_qualnam_task(char *, struct mod_t *,
+ struct task_t *);
+extern vpiHandle __mk_exprclass_handle(struct expr_t *, struct itree_t *,
+ struct task_t *);
+extern vpiHandle __mk_handle(word32, void *, struct itree_t *,
+ struct task_t *);
+extern vpiHandle __mk_stmt_handle(word32, struct st_t *, struct itree_t *,
+ struct task_t *);
+extern word32 __to_vpi_tasktyp(word32);
+extern word32 __gate_to_vpiprimtyp(struct gate_t *);
+extern void __init_hrec(struct hrec_t *);
+extern struct thread_t *__alloc_thrd(void);
+extern vpiHandle __nil_iter_err(word32);
+extern struct pviter_t *__alloc_iter(int32, vpiHandle *);
+extern word32 __to_vpi_stmttyp(struct st_t **);
+extern vpiHandle __bld_port_iterator(struct h_t *);
+extern vpiHandle __bld_neticonn_iter(struct h_t *);
+extern vpiHandle __bld_paramassign_stmt_iter(struct h_t *);
+extern vpiHandle __bld_udpline_iter(struct h_t *);
+extern vpiHandle __bld_primterm_iterator(struct h_t *);
+extern vpiHandle __bld_loc_lds_iterator(struct h_t *, int32);
+extern vpiHandle __bld_lds_iterator(struct h_t *, int32);
+extern vpiHandle __bld_loc_drvs_iterator(struct h_t *, int32);
+extern vpiHandle __bld_drvs_iterator(struct h_t *, int32);
+extern vpiHandle __bld_arrwrd_iterator(struct h_t *);
+extern vpiHandle __bld_paramwrd_iterator(struct h_t *);
+extern vpiHandle __bld_bitof_iterator(struct h_t *);
+extern vpiHandle __bld_systf_iterator(struct h_t *);
+extern vpiHandle __bld_tfargexpr_iterator(struct h_t *);
+extern vpiHandle __bld_pthterm_iterator(struct h_t *, word32);
+extern vpiHandle __bld_stmt_iterator(struct h_t *);
+extern vpiHandle __bld_netin_tchkterms(struct h_t *);
+extern vpiHandle __bld_netin_pthterms(struct h_t *);
+extern vpiHandle __bld_caseitems_iter(struct h_t *);
+extern vpiHandle __bld_casi_exprs_iter(struct h_t *);
+extern vpiHandle __bld_operands_iter(struct h_t *);
+extern vpiHandle __bld_allcbs_iter(struct h_t *);
+extern vpiHandle __bld_delay_expr_iter(struct h_t *);
+extern vpiHandle __bld_dig_attr_iter(struct h_t *);
+extern vpiHandle __bld_iodecl_stmt_iter(struct h_t *);
+extern vpiHandle __get_digattr_parent(struct h_t *);
+extern struct itree_t *__find_dfpbot_itp(struct dfparam_t *);
+
+extern char *__my_realloc(char *, int32, int32);
+extern struct systsk_t *__alloc_systsk(void);
+extern struct tnode_t *__vtfind(char *, struct symtab_t *);
+extern void __add_sym(char *, struct tnode_t *);
+extern struct sysfunc_t *__alloc_sysfunc(void);
+extern int32 __validate_handle(char *, struct h_t *);
+extern int32 __validate_nonit_handle(char *, struct h_t *); 
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __grow_xstk(void);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern void __grow_tevtab(void);
+extern void __sim_notbegun_err(char *);
+extern int32 __validate_time_type(char *, int32);
+extern int32 __validate_value_fmt(char *, int32);
+extern char *__to_vpiopnam(char *, int32);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern struct dcevnt_t *__alloc_dcevnt(struct net_t *);
+extern void __alloc_1intdce_prevval(struct dcevnt_t *);
+extern void __init_1instdce_prevval(struct dcevnt_t *);
+extern struct task_t *__getcur_scope_tsk(void);
+extern void __set_vpi_time(struct t_vpi_time *, word64 *, int32, struct mod_t *);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern int32 __vpitime_to_ticks(word64 *, p_vpi_time, struct mod_t *);
+extern void __bad_rosync_err(char *);
+extern void __insert_event(register i_tev_ndx);
+extern void __my_free(char *, int32);
+extern char *__my_malloc(int32);
+extern char *__pv_stralloc(char *);
+extern void __free_dceauxlst(struct dceauxlst_t *, int32);
+extern void __free_xtree(struct expr_t *);
+extern void __free_hp(struct h_t *); 
+extern void __still_comp_err(char *);
+extern int32 __validate_accessm(char *, int32, char *);
+extern int32 __unnormalize_ndx(struct net_t *, int32);
+extern struct expr_t *__bld_rng_numxpr(word32, word32, int32);
+extern int32 __exprtype_get(struct expr_t *);
+extern char *__to_vpionam(char *, word32);
+extern void __getwir_range(struct net_t *, int32 *, int32 *);
+extern void __getarr_range(struct net_t *, int32 *, int32 *, int32 *);
+extern char *__to_mpnam(char *, char *);
+extern int32 __expr_optype_get(struct expr_t *);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern int32 __is_scope_sym(struct sy_t *);
+extern struct expr_t *__sim_alloc_newxnd(void);
+extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
+extern word32 __from_vpi_vartyp(word32);
+extern word32 __ntyp_to_vpivarhtyp(struct net_t *);
+extern word32 __to_vpinetbithtyp(word32);
+extern struct expr_t *__glbnam_to_expr(char *);
+extern struct expr_t *__sim_copy_expr(struct expr_t *);
+extern char *__to_timstr(char *, word64 *);
+extern void __logic_acc_off(struct gate_t *);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern void __dce_turn_chg_store_on(struct mod_t *, struct dcevnt_t *, int32);  
+extern void __dcelst_off(struct dceauxlst_t *);
+extern void __alloc_1instdce_prevval(struct dcevnt_t *);
+
+extern void __cv_msg(char *, ...);
+extern void __tr_msg(char *, ...);
+extern void __pv_err(int32, char *, ...);
+extern void __pv_warn(int32, char *, ...);
+extern void __pv_vpi_terr(int32, char *, ...);
+extern void __inform(int32, char *, ...);
+
+extern void __vpi_err(int32, int32, char *, ...);
+extern void __vpi_terr(char *, int32);
+
+extern word32 __masktab[];
+
+/* vpi only storage */
+extern struct t_vpi_error_info *__last_eip;/* if err, ptr to wrk eifo or nil */
+
+/*
+ * ROUTINES TO REGISTER VPI STYLE SYS TASKS AND FUNCTIONS
+ */
+
+
+#ifdef __APPLE__
+#define SO_SUFFIX ".dylib"
+#else
+#define SO_SUFFIX ".so"
+#endif
+
+/*
+ * process either load pli1 or load vpi dynamic load option lists
+ *
+ * same dynamic loading for both since bootstrap routine not called here
+ */
+extern void __process_pli_dynamic_libs(struct loadpli_t *ldp_hd)
+{
+ register struct loadpli_t *ldp;
+ register struct dynboot_t *dnbp;
+ int32 slen;
+ void *handle;
+ void *boot_rout;
+ char s1[RECLEN], onam[RECLEN];
+    
+ for (ldp = ldp_hd; ldp != NULL; ldp = ldp->load_plinxt)
+  {
+   /* no dynamic library - assume boot routines in other dyn libs */
+   if (ldp->pli1_option) strcpy(onam, "+loadpli1=");
+   else strcpy(onam, "+loadvpi=");
+
+   /* dynamic lib must be defined or previous error */
+   /* if name does not have .so suffix - try that first */
+   if (!lbnam_so_suffix(ldp->libnam))
+    {
+     strcpy(s1, ldp->libnam);
+     strcat(s1, SO_SUFFIX);
+     if ((handle = dlopen(s1, RTLD_LAZY | RTLD_GLOBAL)) == NULL)
+      {
+       if ((handle = dlopen(ldp->libnam, RTLD_LAZY | RTLD_GLOBAL)) == NULL)
+        {
+         __pv_err(1803,
+          "unable to load %s dynamic library (also tried adding %s suffix): %s",
+          ldp->libnam, SO_SUFFIX, dlerror());
+         continue;
+        }
+      }
+     else
+      {
+       slen = strlen(ldp->libnam) + 1;
+       __my_free(ldp->libnam, slen);
+       ldp->libnam = __pv_stralloc(s1);
+      }
+    }
+   else
+    {
+     /* SJM 11/25/02 - must be now not lazy */
+     if ((handle = dlopen(ldp->libnam, RTLD_LAZY | RTLD_GLOBAL)) == NULL)
+      {
+       __pv_err(1803, "unable to load %s dynamic library: %s",
+         onam, dlerror());
+       continue;
+      }
+    }
+
+   /* ok to have no boot routines - if so this does nothing */
+   /* because dynblst empty */
+   for (dnbp = ldp->dynblst; dnbp != NULL; dnbp = dnbp->dynbootnxt)
+    {
+#if defined(__APPLE_CC__) && (__APPLE_CC__ < 1495)
+     /* for Mach (Mac OSX) need to prepend a '_' - old BSD convention */
+     /* LOOKATME - what happens if name already has '_'? */
+     strcpy(s1, "_");
+     strcat(s1, dnbp->bootrout_nam);
+#else
+     strcpy(s1, dnbp->bootrout_nam);
+#endif
+     if ((boot_rout = dlsym(handle, s1)) == NULL)
+      {
+       __pv_err(1803, "unable to find %s bootstrap routine in %s: %s",
+        s1, ldp->libnam, dlerror());
+       continue;
+      } 
+     if (ldp->pli1_option) dnbp->dynu.tf_rout = boot_rout;
+     else dnbp->dynu.vpi_rout = boot_rout;
+    }
+  }
+}
+
+/*
+ * return T if name has .so suffix (may differ on some systems)
+ */
+static int32 lbnam_so_suffix(char *lbnam)
+{
+ int32 suflen;
+ char *cp;
+
+ if ((cp = rindex(lbnam, '.')) == NULL) return(FALSE);
+ suflen = strlen(SO_SUFFIX);
+ if (strncmp(cp, SO_SUFFIX, suflen) == 0 && strlen(cp) == suflen)
+  return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * if vpi used, this is called 
+ */
+extern void __call_vlog_startup_procs(void)
+{
+ register struct loadpli_t *ldp;
+ register struct dynboot_t *dnbp;
+
+ /* SJM 07/08/02 - unless user needs static PLI, this now always empty */
+ __vpi_vlog_start_done = FALSE;
+#ifdef __STATIC_PLI__
+ {
+  register int32 i; 
+
+  for (i = 0;; i++) 
+   {
+    if (vlog_startup_routines[i] == NULL) break; 
+    vlog_startup_routines[i]();
+   }
+ } 
+#else
+ /* SJM 07/08/02 - call each dynamic vpi bootstrap routine */ 
+ /* although normally static cverobj.o not shipped, run after P1364 vpi_ */ 
+ /* standardized vlog_startup_routines table */
+ for (ldp = __vpi_dynlib_hd; ldp != NULL; ldp = ldp->load_plinxt)
+ {
+  /* vpi boostrap routines are assume to return void - if not ret ignored */
+  for (dnbp = ldp->dynblst; dnbp != NULL;  dnbp = dnbp->dynbootnxt)
+   {
+    if (dnbp->dynu.vpi_rout != NULL) (dnbp->dynu.vpi_rout)();         
+   }
+ }
+#endif
+ __vpi_vlog_start_done = TRUE;
+ /* shrink_systfdata_tab(); */
+}
+
+/*
+ * register a vpi_ systf style user system task or function
+ * this must be done from vlog start routines only or error
+ *
+ * emitting both normal source error and vpi error - needed for two reasons 
+ * 1) experts need vpi error when handler registed, 2) novices will not
+ * be able to get error call back or error check code written when initial
+ * registering happens
+ */
+extern vpiHandle vpi_register_systf(p_vpi_systf_data systf_data_p)
+{
+ int32 stf_ind, systf_typ;
+ p_vpi_systf_data in_systfdatp;
+ struct systftab_t *stftabp;
+ struct systsk_t *stbp;
+ struct sysfunc_t *sfbp;
+ struct sy_t *syp;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+
+ __last_eip = NULL;
+ if (__vpi_vlog_start_done)
+  {
+#ifdef __STATIC_PLI__
+   __pv_err(1802,
+    "vpi_register_systf only callable from vlog_startup_routines at start of elaboration");  
+
+   __vpi_err(1802, vpiError,
+    "vpi_register_systf only callable from vlog_startup_routines at start of elaboration");  
+#else
+   __pv_err(1802,
+    "vpi_register_systf from +loadvpi= option only callable at start of elaboration");
+
+   __vpi_err(1802, vpiError,
+    "vpi_register_systf from +loadvpi= option only callable at start of elaboration");  
+#endif
+   return(NULL);
+  }
+ if (!check_systf(systf_data_p, &systf_typ)) return(NULL);
+
+ /* allocate initial registered vpi_ systf table if first time */
+ /* numbering starts just after tf_ table */
+ if (__last_systf == __last_veriusertf) 
+  {
+   __systftab = (struct systftab_t *)
+    __my_malloc(SYSTFDATSIZE*sizeof(struct systftab_t));
+   __size_systftab = SYSTFDATSIZE;
+  }
+
+ __last_systf++;
+ /* grow the vpi_ systf table if at end */
+ if ((__last_systf - __last_veriusertf) >= __size_systftab)
+  {  
+   int32 osize;
+
+   osize = __size_systftab*sizeof(struct systftab_t);
+   __size_systftab = 3*(__size_systftab/2);
+   __systftab = (struct systftab_t *) __my_realloc((char *) __systftab, osize,
+    __size_systftab*sizeof(struct systftab_t));
+  } 
+ stf_ind = __last_systf - (__last_veriusertf + 1);
+ stftabp = &(__systftab[stf_ind]);
+ /* must copy so caller can free passed data - never need to free since */
+ /* no vpi remove systf */
+ in_systfdatp = (p_vpi_systf_data) __my_malloc(sizeof(struct t_vpi_systf_data));
+
+ *(in_systfdatp) = *(systf_data_p);
+ /* only field that needs to be copied (reallocated is name) */
+ in_systfdatp->tfname = __pv_stralloc(systf_data_p->tfname); 
+ stftabp->vpi_sytfdat = in_systfdatp;
+ 
+ if (systf_data_p->type == vpiSysTask)
+  {
+   syp = task_add_vpi_systf(systf_data_p->tfname, __last_systf);
+   stbp = syp->el.esytbp; 
+   stftabp->sfu.stbp = stbp;
+  }
+ else
+  {
+   syp = func_add_vpi_systf(systf_data_p->tfname, __last_systf);
+   sfbp = syp->el.esyftbp;
+   stftabp->sfu.sfbp = sfbp;
+   sfbp->tftyp = systf_typ;  
+  }
+ stftabp->systf_chk = FALSE;
+ /* systf handles do not go on list since cannot be freed */
+ hp = (struct h_t *) __my_malloc(sizeof(struct h_t)); 
+ hrp = (struct hrec_t *) __my_malloc(sizeof(struct hrec_t));
+ __init_hrec(hrp);
+ hrp->htyp = vpiUserSystf;
+ /* handle is 1000 + value that is always correct for indexing stftab table */
+ hrp->hi = __last_systf;
+ hp->hrec = hrp;
+ hp->hin_itp = NULL;
+ return((vpiHandle) hp);
+}
+
+/*
+ * check a user passed systf structure
+ * LOOKATME - also maybe warning for real func that has size_t?
+ *
+ * here error message is not vpi_ error since impossible to se
+ *
+ */
+static int32 check_systf(p_vpi_systf_data systfp, int32 *stftyp)
+{
+ *stftyp = SYSF_VPI;
+ if (!chk_idnam_systfs(systfp->tfname)) return(FALSE);
+
+ if (systfp->type == vpiSysTask)
+  {
+   if (systfp->sizetf != NULL)
+    {
+     __pv_warn(2001, 
+      "vpi_register_systf of task %s systf data record has sizetf function - ignored",
+      systfp->tfname);
+
+     __vpi_err(2001, vpiWarning,
+      "vpi_register_systf of task %s systf data record has sizetf function - ignored",
+      systfp->tfname);
+     systfp->sizetf = NULL;
+    }
+  }
+ else if (systfp->type == vpiSysFunc)
+  {
+   switch (systfp->sysfunctype) {
+    case vpiIntFunc: case vpiRealFunc: case vpiTimeFunc: case vpiSizedFunc:
+     break;
+    default:
+     __vpi_err(1806, vpiError,
+      "vpi_register_systf function %s sysfunctype %d illegal",
+      systfp->tfname, systfp->sysfunctype);
+     return(FALSE);
+    }
+   /* sizetf required for Func Size */
+   if (systfp->sysfunctype == vpiSizedFunc)
+    {
+     if (systfp->sizetf == NULL)
+      {
+       __pv_warn(2028,
+        "vpi_register_systf of function %s systf data record sizetf function missing - using integer size",
+        systfp->tfname);
+
+      __vpi_err(2028, vpiWarning,
+       "vpi_register_systf of function %s systf data record sizetf function missing - using integer size",
+       systfp->tfname);
+      }
+    }
+   else
+    {
+     /* but ignored for any other */
+     if (systfp->sizetf != NULL)
+      {
+       __pv_warn(2002,
+        "vpi_register_systf of function %s non vpiSizedFunc has sizetf - ignored", 
+        systfp->tfname);
+
+       __vpi_err(2002, vpiWarning,
+        "vpi_register_systf of function %s non vpiSizedFunc has sizetf - ignored", 
+        systfp->tfname);
+       systfp->sizetf = NULL;
+      }
+    }
+  }
+ else 
+  {
+   __pv_err(1811,
+    "vpi_register_systf task/function %s type %d illegal",
+    systfp->tfname, systfp->type);
+   return(FALSE);
+  }
+ return(TRUE); 
+}
+
+/*
+ * check for legal vpi systf task or function name
+ * version supporting vpi style errors 
+ */
+static int32 chk_idnam_systfs(char *tfnam)
+{
+ register char *chp;
+ int32 len;
+
+ chp = tfnam;
+ if (chp == NULL || *chp == '\0' || *chp != '$') 
+  {
+   __pv_err(1812,  
+    "vpi_register_systf data record task or function name %s must begin with '$'",
+    tfnam); 
+
+   __vpi_err(1812, vpiError,
+    "vpi_register_systf data record task or function name %s must begin with '$'",
+    tfnam); 
+   return(FALSE);
+  }
+ chp++;
+ for (len = 1; *chp != '\0'; chp++)
+  {
+   /* notice no escaped names here */
+   if (!isalnum(*chp) && *chp != '_' && *chp != '$')  
+    {
+     __pv_err(1813,
+      "vpi_register_systf data record task or function name %s contains illegal char %c",
+      tfnam, *chp);   
+
+     __vpi_err(1813, vpiError,
+      "vpi_register_systf data record task or function name %s contains illegal char %c",
+      tfnam, *chp);   
+     return(FALSE);
+    }
+   if (++len >= IDLEN)   
+    {
+     /* notice cannot truncate since in user memory */
+     __pv_err(1814,
+      "vpi_register_systf data record task or function name %s too long (%d)",
+      tfnam, IDLEN); 
+
+     __vpi_err(1814, vpiError,
+      "vpi_register_systf data record task or function name %s too long (%d)",
+      tfnam, IDLEN); 
+     return(FALSE);
+    }
+  }
+ return(TRUE);
+}
+
+
+/*
+ * add a vpi_ systf pli system task - handles vpi style errors 
+ */
+static struct sy_t *task_add_vpi_systf(char *tnam, int32 tnum)
+{
+ struct systsk_t *stbp;
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+
+ /* allocate a systsk_t entry - needed because splicing pli on and */
+ /* need to be able to compile version without */
+ stbp = __alloc_systsk();
+ /* notice cross linking here is right */
+ stbp->stsknam = tnam; 
+ stbp->stsknum = tnum;
+ tnp = __vtfind(tnam, __syssyms);
+ if (!__sym_is_new)
+  {
+   syp = tnp->ndp;
+
+   __inform(2103,
+    "PLI vpi systf task %s replaces predefined or veriusertf system task or function with same name",
+    syp->synam);
+
+   __vpi_err(2103, vpiNotice,
+    "PLI vpi systf task %s replaces predefined or veriusertf system task or function with same name",
+    syp->synam);
+  }
+ else
+  {
+   __add_sym(tnam, tnp);
+   (__syssyms->numsyms)++;
+   syp = tnp->ndp;
+  }
+ syp->sytyp = SYM_STSK;
+ syp->sydecl = TRUE;
+ syp->el.esytbp = stbp;
+ return(syp);
+}
+
+/*
+ * add a vpi systf task symbol table for registering new systf task
+ */
+static struct sy_t *func_add_vpi_systf(char *fnam, int32 fnum)
+{
+ struct tnode_t *tnp;
+ struct sy_t *syp;
+ struct sysfunc_t *sfbp;
+
+ sfbp = __alloc_sysfunc();
+ /* notice cross linking right here */
+ sfbp->syfnam = fnam;
+ sfbp->syfnum = fnum;
+ /* caller will set this if different */
+ sfbp->tftyp = SYSF_VPI;
+ tnp = __vtfind(fnam, __syssyms);
+ if (!__sym_is_new)
+  {
+   syp = tnp->ndp;
+   __inform(2104,
+    "PLI vpi systf task %s replaces predefined or veriusertf system task or function with same name",
+    syp->synam);
+
+   __vpi_err(2104, vpiNotice,
+    "PLI vpi systf task %s replaces predefined or veriusertf system task or function with same name",
+    syp->synam);
+  }
+ else
+  {
+   __add_sym(fnam, tnp);
+   (__syssyms->numsyms)++;
+   syp = tnp->ndp;
+  }
+ syp->sytyp = SYM_SF;
+ syp->sydecl = TRUE;
+ syp->el.esyftbp = sfbp;
+ return(syp);
+}
+
+/*
+ * get vpi registered systf info - either call or registered handle allowed
+ * notice internal name string is used - user must not free or write into
+ */
+extern void vpi_get_systf_info(vpiHandle object,
+ p_vpi_systf_data systf_data_p)
+{
+ int32 stf_ind;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+ p_vpi_systf_data tfdatp;
+ struct systftab_t *stftabp;
+ 
+ __last_eip = NULL;
+ hp = (struct h_t *) object;
+ if (!__validate_handle("vpi_get_systf_info", hp)) return;
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiUserSystf && hrp->htyp != vpiSysFuncCall
+  && hrp->htyp != vpiSysTaskCall)
+  {
+   __vpi_err(1821, vpiError,
+    "vpi_get_systf_info requires vpiUserSystf or vpiSys[Func|Task]Call handle");
+   return;
+  }
+ stf_ind = hrp->hi - (__last_veriusertf + 1);
+ stftabp = &(__systftab[stf_ind]);
+ tfdatp = (p_vpi_systf_data) stftabp->vpi_sytfdat;
+ *(systf_data_p) = *(tfdatp);
+}
+
+/*
+ * final step shrink table to right size and adjust last values 
+ */
+/* --- LOOKATME - think can not use this
+static void shrink_systfdata_tab(void)
+{
+ int32 num_systfs, osize, nsize;
+
+ -* maybe none *-
+ if (__last_systf == -1) return;
+
+ num_systfs = __last_systf - __last_veriusertf;
+ if (num_systfs > 0 && __verbose)
+  {
+   __cv_msg(
+    "  %d vpi_register_systf user system tasks and functions registered.\n",
+    num_systfs);
+  }
+ if (num_systfs < __size_systftab)
+  {
+   osize = __size_systftab*sizeof(struct systftab_t);
+   nsize = num_systfs*sizeof(struct systftab_t);
+   __systftab = (struct systftab_t *) __my_realloc((char *) __systftab, osize,
+    nsize);
+  }
+}
+--- */
+
+/*
+ * ROUTINES TO EXECUTE VPI COMPILETF AND CHECKTF IF FIRST TIME SEEN
+ */
+
+/*
+ * check a systfs user function and call sizetf and compiletf if present
+ * only called first time function seen (i.e. once per source location)
+ */
+extern void __chkbld_vpi_systf_func(struct expr_t *fcallx)
+{
+ int32 stf_ind;
+ struct sy_t *syp;
+ struct sysfunc_t *syfp;
+ struct systftab_t *stftabp;
+ p_vpi_systf_data stfdp;
+ struct vpisystf_t *vstfp;
+ int32 (*sizetf_func)();
+
+ syp = fcallx->lu.x->lu.sy;
+ syfp = syp->el.esyftbp;
+ stf_ind = syfp->syfnum - (__last_veriusertf + 1); 
+ stftabp = &(__systftab[stf_ind]);
+ stfdp = (p_vpi_systf_data) stftabp->vpi_sytfdat;
+
+ /* SJM 04/14/04 - following PLI 1.0, can use the sysf lu.x ptr to sy */
+ /* field for the per call in source user data settable/readable fld */  
+ fcallx->lu.x->szu.vpi_sysf_datap = NULL; 
+
+ /* if has vpi registered systf compiletf, must put on list so can call */
+ /* just before end of compile (when vpi_ d.s. built) point */  
+ if (stfdp->compiletf != NULL)
+  {
+   vstfp = (struct vpisystf_t *) __my_malloc(sizeof(struct vpisystf_t));
+   vstfp->is_sysfunc = TRUE;
+   vstfp->vstffnam_ind = __sfnam_ind;
+   vstfp->vstflin_cnt = __slin_cnt;
+   vstfp->curmdp = __inst_mod;
+   vstfp->curtskp = __cur_tsk;
+   vstfp->vsystfu.sysfcallx = fcallx;
+
+   /* link onto front */
+   vstfp->vpistfnxt = __vpi_sysf_hdr;
+   __vpi_sysf_hdr = vstfp;
+  }
+
+ /* do not need to set expr. node width - if called before*/
+ if (stftabp->systf_chk) return;
+
+ /* must run sizetf with no environment since still compiling */
+ __cur_sysf_expr = NULL;
+ switch (stfdp->sysfunctype) {
+  case vpiIntFunc:
+   syfp->retntyp = N_INT;
+   syfp->retsigned = TRUE;
+   syfp->retwid = WBITS;
+   fcallx->has_sign = TRUE;
+   break;
+  case vpiRealFunc:
+   syfp->retntyp = N_REAL;
+   syfp->retsigned = TRUE;
+   /* special width or real since no x/z */
+   syfp->retwid = WBITS;  
+   fcallx->is_real = TRUE;  
+   fcallx->has_sign = TRUE;
+   break;
+  case vpiTimeFunc:
+   syfp->retntyp = N_TIME;
+   syfp->retsigned = FALSE;
+   syfp->retwid = TIMEBITS;
+   break;
+  case vpiSizedFunc:
+   syfp->retntyp = N_REG;
+   syfp->retsigned = FALSE;
+
+   /* if sizetf not set warning was emited and use 32 (WBITS) */
+   if ((sizetf_func = stfdp->sizetf) == NULL) syfp->retwid = WBITS;
+   else syfp->retwid = (*sizetf_func)(stfdp->user_data);
+
+   break;
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ fcallx->szu.xclen = syfp->retwid;
+ stftabp->systf_chk = TRUE;
+}
+
+/*
+ * check a systfs user task and link on to compiletf list if needed
+ * only called first time task seen at each source loc. (not per inst)
+ *
+ * never see sizetf here
+ */
+extern void __chkbld_vpi_systf_task(struct st_t *stp)
+{
+ int32 stf_ind;
+ struct systsk_t *stbp;
+ struct systftab_t *stftabp;
+ p_vpi_systf_data stfdp;
+ struct vpisystf_t *vstfp;
+ struct tskcall_t *tkcp;
+
+ tkcp = &(stp->st.stkc);
+ stbp = tkcp->tsksyx->lu.sy->el.esytbp;
+
+ stf_ind = stbp->stsknum - (__last_veriusertf + 1); 
+ stftabp = &(__systftab[stf_ind]);
+ stfdp = (p_vpi_systf_data) stftabp->vpi_sytfdat;
+
+ /* SJM 04/14/04 - following PLI 1.0, can use the syst task_t tkcaux ptr */
+ /* field for the per call in source user data settable/readable fld */  
+ tkcp->tkcaux.vpi_syst_datap = NULL;
+
+ /* if has vpi registered systf compiletf, must pu on list so can call */
+ /* just before end of compile (when vpi_ d.s. built) point */  
+ if (stfdp->compiletf != NULL)
+  {
+   vstfp = (struct vpisystf_t *) __my_malloc(sizeof(struct vpisystf_t));
+   vstfp->is_sysfunc = FALSE;
+   vstfp->vstffnam_ind = __sfnam_ind;
+   vstfp->vstflin_cnt = __slin_cnt;
+   vstfp->curmdp = __inst_mod;
+   vstfp->curtskp = __cur_tsk;
+   vstfp->vsystfu.syststp = stp;
+   /* link onto front of sys task list */
+   vstfp->vpistfnxt = __vpi_syst_hdr;
+   __vpi_syst_hdr = vstfp;
+  }
+ stftabp->systf_chk = TRUE;
+}
+
+/*
+ * ROUTINES TO EXECUTE VPI SYSTF COMPILETF 
+ */
+
+/*
+ * execute every vpi registered systf compiletf routine
+ *
+ * notice because of xform for code gen - these can't be used after here
+ * LOOKATME - memory leak because could be freed and only accessible through
+ * header and list
+ */
+extern void __exec_all_compiletf_routines(void)
+{
+ register struct vpisystf_t *vstfp;
+
+ for (vstfp = __vpi_sysf_hdr; vstfp != NULL; vstfp = vstfp->vpistfnxt)
+  exec_vpisysfunc_compiletf(vstfp);
+
+ for (vstfp = __vpi_syst_hdr; vstfp != NULL; vstfp = vstfp->vpistfnxt)
+  exec_vpisystask_compiletf(vstfp);
+}
+
+/*
+ * execute the vpi systf system function compiletf routine
+ *
+ * like calltf but does not return anything and must build own context since
+ * nothing executing at this time so need thd and itree (first) env. 
+ * also need task on stack if inside task or function
+ *
+ * LOOKATME is there ever a problem calling with first inst?
+ */
+static void exec_vpisysfunc_compiletf(struct vpisystf_t *vstfp)
+{
+ int32 stf_ind;
+ struct sysfunc_t *sfbp;
+ struct systftab_t *stftabp;
+ p_vpi_systf_data stfdp;
+ struct thread_t *thp, *sav_cur_thd;
+ int32 (*vpicomptf_func)();
+      
+ sfbp = vstfp->vsystfu.sysfcallx->lu.x->lu.sy->el.esyftbp;
+ stf_ind = sfbp->syfnum - (__last_veriusertf + 1); 
+ stftabp = &(__systftab[stf_ind]);
+ stfdp = (p_vpi_systf_data) stftabp->vpi_sytfdat;
+ __cur_sysf_expr = vstfp->vsystfu.sysfcallx;
+
+ vpicomptf_func = stfdp->compiletf;
+ __vpifnam_ind = vstfp->vstffnam_ind;
+ __vpilin_cnt = vstfp->vstflin_cnt;
+ __push_itstk(vstfp->curmdp->moditps[0]);
+
+ /* need dummy thread - still if user tried to use tf_stop think will crash */
+ thp = __alloc_thrd();
+ thp->thenbl_sfnam_ind = 0;
+ thp->thenbl_slin_cnt = 0;
+ thp->thnxtstp = NULL; 
+ thp->thpar = NULL;
+ /* think should never have a current thread here */
+ sav_cur_thd = __cur_thd;
+ __cur_thd = thp;
+ 
+ if (vstfp->curtskp != NULL)
+  {
+   /* DBG remove --- */  
+   if (__fcspi != -1) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   __fcstk[++__fcspi] = vstfp->curtskp;
+  }
+
+ /* notice global __sf location values are rigth for call loc. */
+ (*vpicomptf_func)(stfdp->user_data);
+
+ if (vstfp->curtskp != NULL) __fcspi--;
+ __cur_thd = sav_cur_thd;
+ __my_free((char *) thp, sizeof(struct thread_t)); 
+ __pop_itstk();
+ __cur_sysf_expr = NULL;
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+} 
+
+/*
+ * execute the vpi systf system task compiletf routine
+ *
+ * like calltf but does not return anything and must build own context since
+ * nothing executing at this time so need thd and itree (first) env. 
+ * also need task on stack if inside task or function
+ *
+ * LOOKATME is there ever a problem calling with first inst?
+ */
+static void exec_vpisystask_compiletf(struct vpisystf_t *vstfp)
+{
+ int32 stf_ind;
+ struct systsk_t *stbp;
+ struct systftab_t *stftabp;
+ p_vpi_systf_data stfdp;
+ struct thread_t *thp, *sav_cur_thd;
+ struct st_t *stp;
+ int32 (*vpicomptf_tsk)();
+
+ stp = vstfp->vsystfu.syststp;
+ stbp = stp->st.stkc.tsksyx->lu.sy->el.esytbp;
+ stf_ind = stbp->stsknum - (__last_veriusertf + 1); 
+ stftabp = &(__systftab[stf_ind]);
+ stfdp = (p_vpi_systf_data) stftabp->vpi_sytfdat;
+ __cur_syst_stp = stp;
+
+ vpicomptf_tsk = stfdp->compiletf;
+ __vpifnam_ind = __sfnam_ind; 
+ __vpilin_cnt = __slin_cnt;
+
+ __push_itstk(vstfp->curmdp->moditps[0]);
+
+ /* need dummy thread - still if user tried to use tf_stop think will crash */
+ thp = __alloc_thrd();
+ thp->thenbl_sfnam_ind = 0;
+ thp->thenbl_slin_cnt = 0;
+ thp->thnxtstp = NULL; 
+ thp->thpar = NULL;
+ /* think should never have a current thread here */
+ sav_cur_thd = __cur_thd;
+ __cur_thd = thp;
+ 
+ if (vstfp->curtskp != NULL)
+  {
+   /* DBG remove --- */  
+   if (__fcspi != -1) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   __fcstk[++__fcspi] = vstfp->curtskp;
+  }
+
+ /* set systf for get handle and nil handle user must call vpi put value */
+ (*vpicomptf_tsk)(stfdp->user_data);
+
+ if (vstfp->curtskp != NULL) __fcspi--;
+ __cur_thd = sav_cur_thd;
+ __my_free((char *) thp, sizeof(struct thread_t)); 
+ __pop_itstk();
+ __cur_syst_stp = NULL;
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+} 
+
+/*
+ * ROUTINES TO EXECUTE VPI SYSTF CALLTF 
+ */
+
+/*
+ * execute the vpi systf system function calltf routine
+ * this pushes return value on top of expr. stack but does not return it
+ * uses the instance tree loc. called from
+ *
+ * notice required replacement of built-in names happens because
+ * symbol table symbol gets replaced
+ */
+extern void __vpi_sysf_calltf(struct expr_t *fcallx)
+{
+ int32 stf_ind;
+ struct sysfunc_t *sfbp;
+ struct xstk_t *xsp;
+ struct systftab_t *stftabp;
+ p_vpi_systf_data stfdp;
+ int32 (*vpicalltf_func)();
+      
+ sfbp = fcallx->lu.x->lu.sy->el.esyftbp;
+ stf_ind = sfbp->syfnum - (__last_veriusertf + 1); 
+ stftabp = &(__systftab[stf_ind]);
+ stfdp = (p_vpi_systf_data) stftabp->vpi_sytfdat;
+ __cur_sysf_expr = fcallx;
+
+ /* set systf for get handle and nil handle user must call vpi_put_value */
+ push_xstk_(xsp, stftabp->sfu.sfbp->retwid);
+ one_allbits_(xsp->ap, xsp->xslen);
+ one_allbits_(xsp->bp, xsp->xslen);
+ __cur_sysf_xsp = xsp;
+
+ /* LOOKATME - maybe need warning if nil */
+ if ((vpicalltf_func = stfdp->calltf) == NULL) { return; }
+ __vpifnam_ind = __sfnam_ind; 
+ __vpilin_cnt = __slin_cnt;
+
+ /* notice global __sf location values are rigth for call loc. */
+ (*vpicalltf_func)(stfdp->user_data);
+
+ __cur_sysf_xsp = NULL;
+ __cur_sysf_expr = NULL;
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+} 
+
+/*
+ * call the pli tf system task calltf routine
+ */
+extern void __vpi_syst_calltf(struct st_t *stp)
+{
+ int32 stf_ind;
+ struct systsk_t *stbp;
+ struct systftab_t *stftabp;
+ p_vpi_systf_data stfdp;
+ int32 (*vpicalltf_tsk)();
+
+ stbp = stp->st.stkc.tsksyx->lu.sy->el.esytbp;
+ stf_ind = stbp->stsknum - (__last_veriusertf + 1); 
+ stftabp = &(__systftab[stf_ind]);
+ stfdp = (p_vpi_systf_data) stftabp->vpi_sytfdat;
+ __cur_syst_stp = stp;
+
+ /* LOOKATME - maybe need warning if nil */
+ if ((vpicalltf_tsk = stfdp->calltf) == NULL) return;
+
+ __vpifnam_ind = __sfnam_ind; 
+ __vpilin_cnt = __slin_cnt;
+ /* set systf for get handle and nil handle user must call vpi put value */
+ (*vpicalltf_tsk)(stfdp->user_data);
+
+ __cur_syst_stp = NULL;
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+}
+
+/*
+ * ROUTINES TO IMPLEMENT VPI CALLBACKS
+ */
+
+/*
+ * register a callback
+ *
+ * this can add non delay or val change call backs before sim begins
+ */
+extern vpiHandle vpi_register_cb(p_cb_data cb_data_p)
+{
+ __last_eip = NULL;
+
+ if (cb_data_p->cb_rtn == NULL) 
+  {
+   __vpi_err(1810, vpiError,
+    "vpi_register_cb no effect - no call back routine (cb_rtn field NULL)");
+   return(NULL);
+  }
+
+ /* needs built net list */ 
+ /* cannot check handle until call back type */
+ switch (cb_data_p->reason) {
+  /* value change cbs */
+  case cbValueChange:
+   if (__run_state != SS_SIM)
+    {
+no_sim:
+      __sim_notbegun_err("vpi_register_cb");
+      return(NULL);
+    } 
+   return(valchg_cb_register(cb_data_p));
+  case cbForce: case cbRelease:
+   if (__run_state != SS_SIM) goto no_sim;
+   return(rf_cb_register(cb_data_p, cb_data_p->reason));
+  /* delayed wake up cbs */
+  case cbReadWriteSynch: case cbReadOnlySynch:
+  case cbNextSimTime: case cbAfterDelay:
+   if (__run_state != SS_SIM) goto no_sim;
+   /* schedule a delay callback - reason determines how scheduled */
+   return(delay_cb_register(cb_data_p));
+  /* fixed routine call cbs - can be register before start of sim */ 
+  case cbEndOfCompile: case cbStartOfSimulation: case cbEndOfSimulation:
+  case cbError: case cbPLIError:
+  case cbTchkViolation: case cbStartOfReset:
+  case cbEndOfReset: case cbEnterInteractive: case cbExitInteractive:
+  case cbInteractiveScopeChange:
+  case cbLanguageLine: 
+    return(action_cb_register(cb_data_p));  
+  case cbAtStartOfSimTime: return(delay_cb_register(cb_data_p));
+
+  /* currently unimplemented */
+  case cbStartOfSave: case cbEndOfSave: case cbStartOfRestart:
+  case cbEndOfRestart: case cbUnresolvedSystf:
+   __vpi_err(1823, vpiError, "vpi_register_cb reason %s unsupported",
+    __cb_reason_to_nam(__wrks1, cb_data_p->reason));
+   return(NULL);
+  case cbStmt:
+   /* after move time, execute event from special list */ 
+   __vpi_err(1823, vpiError,
+    "vpi_register_cb reason %s unsupported - not yet implemented",
+    __cb_reason_to_nam(__wrks1, cb_data_p->reason));
+   return(NULL);
+  default:
+   __vpi_err(1824, vpiError,
+    "vpi_register_cb illegal reason value %d - no callback registered",
+     cb_data_p->reason); 
+ }
+ return(NULL);
+}
+
+/*
+ * convert a callback reason to a name
+ */
+extern char *__cb_reason_to_nam(char *s, int32 reason)
+{
+ switch (reason) {
+  case cbValueChange: strcpy(s, "cbValueChange"); break;
+  case cbStmt: strcpy(s, "cbStmt"); break;
+  case cbForce: strcpy(s, "cbForce"); break;
+  case cbRelease: strcpy(s, "cbRelease"); break;
+  case cbAtStartOfSimTime: strcpy(s, "cbAtStartOfSimTime"); break;
+  case cbReadWriteSynch: strcpy(s, "cbReadWriteSynch"); break;
+  case cbReadOnlySynch: strcpy(s, "cbReadOnlySynch"); break;
+  case cbNextSimTime: strcpy(s, "cbNextSimTime"); break;
+  case cbAfterDelay: strcpy(s, "cbAfterDelay"); break;
+  case cbEndOfCompile: strcpy(s, "cbEndOfCompile"); break;
+  case cbStartOfSimulation: strcpy(s, "cbStartOfSimulation"); break;
+  case cbEndOfSimulation: strcpy(s, "cbEndOfSimulation"); break;
+  case cbError: strcpy(s, "cbError"); break;
+  case cbPLIError: strcpy(s, "cbPLIError"); break;
+  case cbTchkViolation: strcpy(s, "cbTchkViolation"); break;
+  case cbStartOfReset: strcpy(s, "cbStartOfReset"); break;
+  case cbEndOfReset: strcpy(s, "cbEndOfReset"); break;
+  case cbEnterInteractive: strcpy(s, "cbEnterInteractive"); break;
+  case cbExitInteractive: strcpy(s, "cbExitInteractive"); break;
+  case cbInteractiveScopeChange:
+   strcpy(s, "cbInteractiveScopeChange");
+   break;
+  case cbUnresolvedSystf: strcpy(s, "cbUnresolvedSystf"); break;
+  case cbStartOfSave: strcpy(s, "cbStartOfSave"); break;
+  case cbEndOfSave: strcpy(s, "cbEndOfSave"); break;
+  case cbStartOfRestart: strcpy(s, "cbStartOfRestart"); break;
+  case cbEndOfRestart: strcpy(s, "cbEndOfRestart"); break;
+  case cbLanguageLine: strcpy(s, "cbLanguageLine"); break;
+  default:
+   /* checking must be elsewhere */
+   strcpy(s, "**illegal**");
+ }
+ return(s);
+}
+
+/*
+ * setup (register) the value change callback 
+ *
+ * LOOKATME - think call backs for events not possible
+ *
+ * interpreting LRM to only allow value change call backs on members of
+ * expression class (can come from to <expr. class> or contents of mod/task)
+ *
+ * LRM says term but interpreting term as "expr. of term" where must then go
+ * through loads to find needed term - alternative could actually pass term
+ * such as prim (gate), tchk, path, and more? but not for now
+ */
+static vpiHandle valchg_cb_register(p_cb_data cb_data_p) 
+{
+ int32 biti;
+ vpiHandle cbref, ihref;
+ struct h_t *hp, *hp2;
+ struct hrec_t *hrp;
+ struct net_t *np;
+ struct expr_t *xp;
+ struct gate_t *gp;
+ 
+ hp = (struct h_t *) cb_data_p->obj;
+ if (!chk_valchg_cb(cb_data_p, hp)) return(NULL);
+ hrp = hp->hrec;
+ __cbvc_dcehdr = NULL;
+ __push_itstk(hp->hin_itp);
+ switch (hrp->htyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   np = hrp->hu.hnp;
+   cbref = bld_cbrec(cb_data_p, CB_VALCHG);
+   hp2 = (struct h_t *) cbref;
+   linkon_cb_dce(np, -1, -1, NULL, hp2->hrec->hu.hcbp, DCE_CBVC);
+   break;
+  case vpiNamedEvent:
+   /* FIXME - think need to support change call back on events */
+   np = hrp->hu.hnp;
+   /* DBG remove -- */
+   if (np->ntyp != N_EVENT) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   /* can not place change call back on event since no value? */
+   __vpi_err(2024, vpiWarning,
+    "vpi_register_cb value change form for vpiNamedEvent %s object unsupported",
+    np->nsym->synam);
+   goto bad_end;
+  case vpiNetBit: case vpiRegBit: case vpiVarSelect: case vpiMemoryWord:
+   /* know parent object is a vector or will not get here */
+   if (!hrp->bith_ndx) { xp = hrp->hu.hxp; goto bit_expr_form; }
+
+   np = hrp->hu.hnp;
+   cbref = bld_cbrec(cb_data_p, CB_VALCHG);
+   hp2 = (struct h_t *) cbref;
+   /* always need to set this so callback cb_data field has change index */
+   hp2->hrec->hu.hcbp->cb_ndxobj = TRUE;
+
+   /* for vectored vectors or array - no individual bit/array cell identity */
+   /* LOOKATME - can callbacks be placed on individual cells of arrays? */
+   if (!np->vec_scalared || hrp->htyp == vpiMemoryWord) biti = -1;
+   else biti = hrp->hi;
+
+   /* index stored as normalized h:0 */ 
+   /* must filter bit or array index */
+   linkon_cb_dce(np, biti, biti, NULL, hp2->hrec->hu.hcbp, DCE_CBVC);
+   break;
+  case vpiRealVar: case vpiConstant: 
+   /* no call back allowed on real variable or constant */
+   __vpi_err(1836, vpiError,
+    "vpi_register_cb real value change object %s illegal",
+    __to_vpionam(__wrks1, hrp->htyp));
+bad_end: 
+   __pop_itstk();
+   return(NULL);
+  case vpiPartSelect: case vpiFuncCall: case vpiSysFuncCall: 
+  case vpiOperation: 
+   xp = hrp->hu.hxp;
+bit_expr_form:
+   /* normal rhs expression for which value change monitoring possible */
+   cbref = bld_cbrec(cb_data_p, CB_VALCHG);
+   hp2 = (struct h_t *) cbref;
+   /* LSB for both bit select and array index */
+   hp2->hrec->hu.hcbp->cb_ndxobj = (xp->optyp == LSB) ? TRUE : FALSE;
+   bld_cbvc_dces(xp, hp2->hrec->hu.hcbp);
+   break;
+  case vpiPrimTerm:
+   /* SJM 11/22/00 - add ability to put call backs on non tran/pull */
+   /* gate outputs */
+   gp = hrp->hu.hgp;
+   /* for tran/pull put call back on expr - can go on either */
+   if (gp->g_class == GC_PULL || gp->g_class == GC_TRAN
+    || gp->g_class == GC_TRANIF)
+    {
+     if (gp->g_class == GC_TRANIF && hrp->hi == 2)
+      {
+       __vpi_err(1912, vpiError,
+        "vpi_register_cb of value change for vpiPrimTerm (pos. %d) of %s.%s illegal input - only output or inout allowed",
+        hrp->hi + 1, __msg2_blditree(__xs, hp->hin_itp), gp->gsym->synam);
+       goto bad_end;
+      }
+     xp = hrp->hu.hgp->gpins[hrp->hi];
+     /* SJM 11/28/00 - also must change handle to terminal index handle */
+     ihref = __mk_exprclass_handle(xp, hp->hin_itp, hrp->hin_tskp);
+     /* LOOKATME - must replace cb object passed by user to make this work */ 
+     cb_data_p->obj = ihref;
+     hp = (struct h_t *) ihref;
+     hrp = hp->hrec;
+     goto bit_expr_form;
+    }
+   /* if value monitoring used, must be strength - call backs always */
+   /* monitor strengths for mos/cmos gates and never for others */
+   if (gp->g_class == GC_LOGIC || gp->g_class == GC_UDP)
+    {
+     if (cb_data_p->value != NULL
+      && cb_data_p->value->format == vpiStrengthVal)
+      {
+       __vpi_err(2055, vpiWarning,
+       "vpi_register_cb primtive output value change form for logic/udp gate %s.%s strength never changes but format value vpiStrengthVal",
+        __msg2_blditree(__xs, hp->hin_itp), gp->gsym->synam);
+      }
+    }
+   else 
+    {
+     if (cb_data_p->value != NULL
+      && cb_data_p->value->format != vpiStrengthVal)
+      {
+       __vpi_err(2055, vpiWarning,
+       "vpi_register_cb primtive output value change form for mos/bufif gate %s.%s always called for strength changes but format value non strength",
+        __msg2_blditree(__xs, hp->hin_itp), gp->gsym->synam);
+      }
+    }
+   cbref = gateout_valchg_register(hp, cb_data_p);
+   break;
+  default:
+   __vpi_err(1839, vpiError,
+    "vpi_register_cb object %s illegal for cbValueChange reason",
+    __to_vpionam(__wrks1, hrp->htyp));
+   goto bad_end;
+ }
+ __pop_itstk();
+
+ /* succeeded link dce's onto list associated with this cb for removing */
+ hp2 = (struct h_t *) cbref;
+ /* link on list because may be multiple for different nets from expr */
+ hp2->hrec->hu.hcbp->cbdcep = __cbvc_dcehdr;
+ /* SJM - 05/23/00 - if stren format, for each stren net off no mon stren */
+ if (hp2->hrec->hu.hcbp->cb_retvalfmt == vpiStrengthVal)
+  { 
+   set_dce_strenchg_on(__cbvc_dcehdr);
+  }
+
+ __cbvc_dcehdr = NULL;
+ return(cbref);
+}
+
+/*
+ * check value change callback passed cb_data record
+ */
+static int32 chk_valchg_cb(p_cb_data cb_data_p, struct h_t *hp)
+{
+ if (!__validate_nonit_handle("vpi_register_cb (value change obj)", hp))
+  return(FALSE);
+ if (cb_data_p->time == NULL) 
+  {
+   __vpi_err(1850, vpiError,
+    "vpi_register_cb cbValueChange p_cb_data record required time field empty"); 
+   return(FALSE);
+  }
+ if (cb_data_p->value == NULL) 
+  {
+   __vpi_err(1931, vpiError,
+    "vpi_register_cb cbValueChange p_cb_data record required value field empty"); 
+   return(FALSE);
+  }
+
+ /* validate time format and value format */
+ if (!__validate_time_type("vpi_register_cb cbValueChange",
+  cb_data_p->time->type)) return(FALSE);
+ if (!__validate_value_fmt("vpi_register_cb cbValueChange",
+  cb_data_p->value->format)) return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * build a call back record and build associated handle
+ *
+ * notice need handle for cb remove and dce points to cbrec
+ * if call back handle is freed, no way to remove call back
+ *
+ * know value and time fields point to records or will not get here
+ */
+static vpiHandle bld_cbrec(p_cb_data cb_data_p, word32 cbclass)
+{
+ vpiHandle cbref;
+ struct cbrec_t *cbp;
+ struct h_t *hp, *hp2;
+ struct hrec_t *hrp2;
+ struct gate_t *gp;
+
+ /* no need to init because user always creates and passes */
+ cbp = (struct cbrec_t *) __my_malloc(sizeof(struct cbrec_t));
+ cbp->cb_reason = cb_data_p->reason; 
+ cbp->cb_class = cbclass;
+ cbp->cb_ndxobj = FALSE;
+ /* SJM 07/24/00 - call backs can be set off by user using sim control */
+ cbp->cb_user_off = FALSE;
+ cbp->cb_gateout = FALSE;
+ /* if object passed must copy handle so user can free or reuse */
+ if (cb_data_p->obj != NULL)
+  {
+   /* user can now free or reuse object */ 
+   hp = (struct h_t *) cb_data_p->obj;
+   /* this is same as copy object */
+   hp2 = (struct h_t *) __mk_handle(hp->hrec->htyp, NULL, NULL, NULL);
+   hp2->hin_itp = hp->hin_itp; 
+   hrp2 = hp2->hrec;
+   *(hrp2) = *(hp->hrec);
+   /* if copy from iterator, no longer in iterator */
+   hrp2->in_iter = FALSE; 
+   if (hrp2->free_xpr) hrp2->hu.hxp = __sim_copy_expr(hp->hrec->hu.hxp);
+   cbp->cb_hp = hp2;
+  }
+ else cbp->cb_hp = NULL;
+
+ cbp->cb_rtn = cb_data_p->cb_rtn;
+ cbp->cb_user_data = cb_data_p->user_data;
+
+ if (cb_data_p->time != NULL)
+  cbp->cb_rettimtyp = (word32) cb_data_p->time->type; 
+ else cbp->cb_rettimtyp = vpiSuppressTime;
+ 
+ if (cb_data_p->value != NULL)
+  cbp->cb_retvalfmt = (word32) cb_data_p->value->format; 
+ else cbp->cb_retvalfmt = vpiSuppressVal;
+ cbp->cbdcep = NULL;
+ cbp->cbtevpi = -1;
+
+ /* link on to front design wide list */
+ if (__vpi_cbrec_hdr == NULL)
+  { __vpi_cbrec_hdr = cbp; cbp->cbnxt = cbp->cbprev = NULL; }
+ else
+  {
+   cbp->cbnxt = __vpi_cbrec_hdr;
+   cbp->cbnxt->cbprev = cbp;
+   cbp->cbprev = NULL;
+   __vpi_cbrec_hdr = cbp;
+  }
+ /* callback handles never have itree loc, but obj might */
+ cbref = __mk_handle(vpiCallback, (void *) cbp, NULL, NULL);
+ cbp->cb_cbhp = (struct h_t *) cbref;
+
+ /* 11/28/00 - special processing for gate out term cb */
+ /* BEWARE - must turn off optimization on fly when gate out */
+ /* terminal call back is acclerated output of logic gate */
+ /* only need to turn off for logic gates */ 
+ /* problem here is that this is only value change call back */
+ /* that can't use net scheduling mechanism but must be checked for */ 
+ if (cbp->cb_gateout)
+  { 
+   gp = cbp->cb_hp->hrec->hu.hgp;
+   if (gp->g_class == GC_LOGIC) __logic_acc_off(gp);
+  }
+
+ return(cbref);
+}
+
+/*
+ * build and link on special cb val chg change dce for one callback
+ * xp is expr. - if simple expr. (reg/wire handle not expr) 
+ *
+ * here because variable index becomes entire range all indices are
+ * already normalized h:0 constants
+ */
+static void bld_cbvc_dces(struct expr_t *xp, struct cbrec_t *cbp)
+{
+ struct net_t *np;
+ int32 biti, bitj;
+ word32 *wp;
+ struct expr_t *idndp, *ndx;
+ struct expr_t *fax;
+ 
+ switch ((byte) xp->optyp) {
+  case GLBREF:
+   idndp = xp; 
+   biti = bitj = -1;
+glb_dce:
+   np = idndp->lu.sy->el.enp;
+   linkon_cb_dce(np, biti, bitj, idndp->ru.grp, cbp, DCE_CBVC);
+   break;
+  case ID:
+   idndp = xp; 
+   np = xp->lu.sy->el.enp;
+   linkon_cb_dce(np, -1, -1, NULL, cbp, DCE_CBVC);
+   break;
+  /* SJM 05/18/00 - must do nothing for reals */ 
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   return;
+  case LSB:
+   idndp = xp->lu.x; 
+   np = idndp->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   /* any reg or non scalaraed wire must trigger on any chg */
+   if (ndx->optyp == NUMBER)
+    {
+     wp = &(__contab[ndx->ru.xvi]);
+     if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
+    }
+   else if (ndx->optyp == ISNUMBER)
+    {
+     /* because cb dces are per instance, for IS form just need to get */
+     /* right index and use for per. inst. dces - no need for -2 form */
+     wp = &(__contab[ndx->ru.xvi]);
+     wp = &(wp[2*__inum]);
+     /* need length for IS number because can be wider - but get low */
+     if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
+    }
+   else
+    {
+     /* notice for monitor and dctrl event change, variable here is legal */
+     /* and implies change for index and trigger on all bits of variable */
+     bld_cbvc_dces(ndx, cbp);
+     biti = -1;
+    }
+   if (biti != -1 && !np->vec_scalared) biti = -1;
+   /* know non -1 value already normalized because constant normalized to */
+   /* h:0 when source read */
+   if (idndp->optyp == GLBREF) { bitj = biti; goto glb_dce; }
+   linkon_cb_dce(np, biti, biti, NULL, cbp, DCE_CBVC);
+   break;
+  case PARTSEL:
+   idndp = xp->lu.x; 
+   np = idndp->lu.sy->el.enp;
+   ndx = xp->ru.x;
+   /* know part select never IS and normalized during fixup */
+   biti = (int32) __contab[ndx->lu.x->ru.xvi];
+   bitj = (int32) __contab[ndx->ru.x->ru.xvi];
+   if (!np->vec_scalared) biti = bitj = -1;
+   if (idndp->optyp == GLBREF) goto glb_dce;
+   linkon_cb_dce(np, biti, bitj, NULL, cbp, DCE_CBVC);
+   break;
+  case FCALL:
+   /* if any arguments of system or user functions change, monitor triggers */
+   /* notice $time function do not have arguments */
+   for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+    bld_cbvc_dces(fax->lu.x, cbp);
+   break;
+  case LCB:
+   for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
+    bld_cbvc_dces(fax->lu.x, cbp);
+   break;
+  default:
+   if (xp->lu.x != NULL) bld_cbvc_dces(xp->lu.x, cbp);
+   if (xp->ru.x != NULL) bld_cbvc_dces(xp->ru.x, cbp);
+   break;
+ } 
+}
+
+/*
+ * link on a special (one per inst) callback valchg dce
+ *
+ * -2 IS form impossible any one inst. IS form made constant before here
+ * need old value for ranges since need exact change processing
+ *
+ * passed biti and bitj must be normalized to internal h:0
+ */
+static void linkon_cb_dce(struct net_t *np, int32 biti, int32 bitj,
+ struct gref_t *grp, struct cbrec_t *cbp, int32 dcetyp)
+{
+ register struct dcevnt_t *dcep;
+ int32 nd_itpop;
+ struct itree_t *ref_itp;
+ struct dceauxlst_t *dclp;
+
+ ref_itp = __inst_ptr;
+ nd_itpop = FALSE;
+ if (grp != NULL) { __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
+ /* allocate, init, and fill the fields */
+ dcep = __alloc_dcevnt(np);
+   
+ if (biti == -1) dcep->dce_typ = dcetyp;
+ else
+  {
+   if (dcetyp == DCE_CBVC) dcep->dce_typ = DCE_RNG_CBVC;
+   else if (dcetyp == DCE_CBF) dcep->dce_typ = DCE_RNG_CBF;
+   else dcep->dce_typ = DCE_RNG_CBR;
+   dcep->dci1 = biti;
+   dcep->dci2.i = bitj;
+  }
+
+ /* since no dce, no loads, and no dmpvars must always turn chg store on */
+ if (!np->nchg_nd_chgstore)
+  {
+   /* this also regen net's decl iops from dce if -O on */
+   __dce_turn_chg_store_on(__inst_mod, dcep, FALSE);  
+  }
+ /* SJM 02/06/03 - may have npps but not dces so must turn this on */
+ /* since nchg nd chgstore on, know nchg action right */
+
+ /* SJM 04/14/04 - if wire also need to turn on when dumpvars execed later */
+ /* this was wrongly only turning on for regs - also needed for nets */
+ np->nchg_has_dces = TRUE;
+
+ /* link this on front */
+ /* notice goes in front of pvc dces? */
+ dcep->dcenxt = np->dcelst;
+ np->dcelst = dcep;
+
+ dcep->dce_1inst = TRUE;
+ /* this is itree dcep put on */
+ dcep->dce_matchitp = __inst_ptr;
+ /* this is placed referenced, unless xmr same as match */
+ dcep->dce_refitp = ref_itp;
+ /* know in right itree place and need prevous value for selects */
+ __alloc_1instdce_prevval(dcep);
+ __init_1instdce_prevval(dcep);
+ dcep->dceu.dce_cbp = cbp;
+
+ /* then link on cb undo/chg list - need if remove called */
+ dclp = (struct dceauxlst_t *) __my_malloc(sizeof(struct dceauxlst_t));
+ dclp->ldcep = dcep; 
+ dclp->dclnxt = __cbvc_dcehdr;
+ __cbvc_dcehdr = dclp;
+
+ if (nd_itpop) __pop_itstk();
+}
+
+/*
+ * for val change callback with vpi stren value - turn off no stren mon
+ * if wire is stren model
+ *
+ * need to go through list since one for each net
+ * only call if vpi_ value change callback stren format is stren change 
+ */
+static void set_dce_strenchg_on(struct dceauxlst_t *dceaux_hd)
+{
+ register struct dceauxlst_t *dceauxlp;
+
+ for (dceauxlp = dceaux_hd; dceauxlp != NULL; dceauxlp = dceauxlp->dclnxt)
+  {
+   if (!dceauxlp->ldcep->dce_np->n_stren) continue;
+
+   dceauxlp->ldcep->dce_nomonstren = FALSE;
+  }
+}
+
+/*
+ * allocate and add value change call back to gate output per inst list
+ */
+static vpiHandle gateout_valchg_register(struct h_t *hp,
+ struct t_cb_data *datp)
+{
+ register int32 i, last_i;
+ register struct mod_t *mdp;
+ int32 gi, tevpi;
+ word64 timval;
+ struct gate_t *gp;
+ vpiHandle cbref;
+ struct cbrec_t *cbp;
+ struct h_t *hp2;
+
+ gp = hp->hrec->hu.hgp;
+ mdp = __inst_mod; 
+ /* if first primitive out cb for this module allocate list headers */
+ if (mdp->mgateout_cbs == NULL)
+  {
+   mdp->mgateout_cbs = (i_tev_ndx **)
+    __my_malloc(mdp->mgnum*sizeof(i_tev_ndx *));
+   for (i = 0; i < mdp->mgnum; i++) mdp->mgateout_cbs[i] = NULL;
+  }
+ gi = gp - mdp->mgates; 
+ if (mdp->mgateout_cbs[gi] == NULL)
+  {
+   mdp->mgateout_cbs[gi] = (i_tev_ndx *)
+    __my_malloc(mdp->flatinum*sizeof(int32));
+   for (i = 0; i < mdp->flatinum; i++) mdp->mgateout_cbs[gi][i] = -1;
+  }
+ __have_vpi_gateout_cbs = TRUE;
+
+ /* need a cbref to hold passsed cb data record */
+ cbref = bld_cbrec(datp, CB_VALCHG);
+ hp2 = (struct h_t *) cbref;
+ cbp = hp2->hrec->hu.hcbp;
+ cbp->cb_gateout = TRUE;
+
+ /* need an event so cb can be removed */
+ timval = 0ULL;
+ alloc_tev_(tevpi, 0, NULL, timval);
+ __tevtab[tevpi].tu.tehp = hp2;
+ /* needed for remove because must match event from non delay sched list */
+ cbp->cbtevpi = tevpi;
+
+ /* using a list of events so can free and reuse while linking out */
+ /* from all cb list */ 
+ /* LOOKATME could store extra field to speed search up but lists short */
+ /* link on end of list */
+ if ((i = mdp->mgateout_cbs[gi][__inum]) == -1)
+  {
+   mdp->mgateout_cbs[gi][__inum] = tevpi;
+  }
+ else 
+  {
+   last_i = -1;
+   for (; i != -1; i = __tevtab[i].tenxti) last_i = i;
+   __tevtab[last_i].tenxti = tevpi; 
+  }
+ return(cbref);
+}
+
+/*
+ * setup (register) the force or release callback (specific net/reg form)
+ *
+ * scheme: the lhs forced or released wire has a dce placed on that
+ * is checked for force or release statement (or vpi routine) is execed
+ * cb remove just unlinks the dce
+ *
+ * force and release can only be entire reg (but not real or array)
+ * or wire or bit select of wire but not non lvalue expression
+ */
+static vpiHandle rf_cb_register(p_cb_data cb_data_p, int32 qctyp)
+{
+ int32 rftyp, biti;
+ vpiHandle cbref;
+ struct h_t *hp, *hp2;
+ struct net_t *np;
+ struct hrec_t *hrp;
+ struct expr_t *ndx, *xp;
+ char s1[RECLEN];
+
+ if (qctyp == cbForce) { strcpy(s1, "cbForce"); rftyp = DCE_CBF; }
+ else { strcpy(s1, "cbRelease"); rftyp = DCE_CBR; }
+ hp = (struct h_t *) cb_data_p->obj;
+ if (!chk_rf_cb(cb_data_p, hp, s1)) return(NULL);
+ 
+ /* handle nil obj (cb for all rel or force separately - no dces needed */
+ if (cb_data_p->obj == NULL) return(rf_all_register_cb(cb_data_p, qctyp));
+
+ hrp = hp->hrec; 
+ __cbvc_dcehdr = NULL;
+ __push_itstk(hp->hin_itp);
+ switch (hrp->htyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   np = hrp->hu.hnp;
+   cbref = bld_cbrec(cb_data_p, CB_VALCHG);
+   hp2 = (struct h_t *) cbref;
+   linkon_cb_dce(np, -1, -1, NULL, hp2->hrec->hu.hcbp, rftyp);
+   break;
+  case vpiNetBit:
+   /* this can be either form */
+   if (!hrp->bith_ndx)
+    {
+     /* DBG remove --- */
+     if (hrp->hu.hxp->optyp != LSB) __vpi_terr(__FILE__, __LINE__);
+     /* --- */ 
+     ndx = hrp->hu.hxp->ru.x;
+     /* know index is 32 bits */
+     if (!__expr_is_vpiconst(ndx))
+      {
+bad_bsel:
+       __vpi_err(1834, vpiError,
+       "vpi_register_cb %s non constant or 'bx bit select of vpiNetBit illegal",
+        s1);
+       __pop_itstk();
+       return(NULL);
+      }
+
+     xp = hrp->hu.hxp->lu.x;
+     np = xp->lu.sy->el.enp;
+     /* know correct itree loc. on top of stack - this may access IS number */
+     /* but never variable - and know already normalized to h:0 */
+     biti = __comp_ndx(np, ndx);
+     if (biti == -1) goto bad_bsel;
+    }
+   /* stored in normalized h:0 range */
+   else { np = hrp->hu.hnp; biti = hrp->hi; }
+
+   cbref = bld_cbrec(cb_data_p, CB_VALCHG);
+   hp2 = (struct h_t *) cbref;
+   /* must filter bit or array index */
+   linkon_cb_dce(np, biti, biti, NULL, hp2->hrec->hu.hcbp, rftyp);
+   break;
+  default:
+   __vpi_err(1839, vpiError, "vpi_register_cb %s object %s illegal", s1,
+    __to_vpionam(__wrks1, hrp->htyp));
+   __pop_itstk();
+   return(NULL);
+ }
+ __pop_itstk();
+ if (qctyp == cbForce) __num_vpi_force_cbs++; else __num_vpi_rel_cbs++; 
+ return(cbref);
+}
+
+/*
+ * check force/release callback passed cb_data record
+ */
+static int32 chk_rf_cb(p_cb_data cb_data_p, struct h_t *hp, char *rfnam)
+{
+ /* if obj nil, legal means all forces/release form */
+ if (hp != NULL)
+  {
+   if (!__validate_nonit_handle("vpi_register_cb", hp)) return(FALSE);
+  }
+ if (cb_data_p->time == NULL) 
+  {
+   __vpi_err(1932, vpiError,
+    "vpi_register_cb %s p_cb_data record required time field empty", rfnam); 
+   return(FALSE);
+  }
+ if (cb_data_p->value == NULL) 
+  {
+   __vpi_err(1933, vpiError,
+    "vpi_register_cb %s p_cb_data record required value field empty", rfnam); 
+   return(FALSE);
+  }
+
+ /* validate time format and value format */
+ if (!__validate_time_type("vpi_register_cb", cb_data_p->time->type))
+  return(FALSE);
+ if (!__validate_value_fmt("vpi_register_cb", cb_data_p->value->format))
+  return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * return T if expression will be converted to vpiConst
+ */
+extern int32 __expr_is_vpiconst(struct expr_t *xp)
+{
+ switch ((byte) xp->optyp) {
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
+   return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*
+ * setup (register) every force or release callback
+ *
+ * caller must make right itree loc.
+ *
+ * here on any change check flag and if set go through list of
+ * all registered all changes cbs (can be many) and exec routine
+ * before cb, build and sets handle (handle can must be copied by user)
+ */
+static vpiHandle rf_all_register_cb(p_cb_data cb_data_p, int32 qctyp)
+{
+ vpiHandle cbref;
+ struct h_t *hp;
+ struct rfcblst_t *rfp;
+
+ /* build the cbrec and handle */
+ cbref = bld_cbrec(cb_data_p, CB_VALCHG);
+ hp = (struct h_t *) cbref;
+
+ rfp = (struct rfcblst_t *) __my_malloc(sizeof(struct rfcblst_t)); 
+ rfp->rfcbp = hp->hrec->hu.hcbp;
+ rfp->rfcbnxt = NULL;
+ 
+ /* link on to right list and update flags */
+ if (qctyp == cbForce) 
+  {
+   if (!__vpi_force_cb_always)
+    {
+     __vpi_force_cb_always = TRUE;
+     __force_allcb_hdr = __force_allcb_end = rfp;
+    }
+   else { __force_allcb_end->rfcbnxt = rfp; __force_allcb_end = rfp; }
+  }
+ else
+  {
+   if (!__vpi_rel_cb_always)
+    { __vpi_rel_cb_always = TRUE; __rel_allcb_hdr = __rel_allcb_end = rfp; }
+   else { __rel_allcb_end->rfcbnxt = rfp; __rel_allcb_end = rfp; }
+  }
+ return(cbref);
+}
+
+/*
+ * from force - go thru net dces looking for force cb 
+ */
+extern void __find_call_force_cbs(struct net_t *np, int32 i1)
+{
+ register struct dcevnt_t *dcep;
+ register struct cbrec_t *cbp;
+
+ for (dcep = np->dcelst; dcep != NULL; dcep = dcep->dcenxt) 
+  {
+   if (dcep->dce_typ == DCE_RNG_CBF)
+    {
+     if (i1 != -1 && (i1 < dcep->dci2.i || i1 > dcep->dci1))
+      { if (__num_vpi_force_cbs == 1) return; else continue; }
+     goto try_non_rng;
+    }
+   if (dcep->dce_typ != DCE_CBF) continue;
+
+try_non_rng:
+   /* SJM 07/24/00 - must turn off PLI 1.0 PV dces from inside self */
+   /* LOOKATME - on/off of cbs may break use of counter to stop loop */
+   /* think only does small amount of extra work */
+   if (dcep->dce_off) continue;
+
+   /* only entire reg/wire or 1 bit of wire allowed here */
+   if (dcep->dce_matchitp != __inst_ptr) continue;
+   /* have matching force */  
+   cbp = dcep->dceu.dce_cbp; 
+
+   /* SJM 07/24/00 - must run with this callback off in case rf in user code */
+   dcep->dce_off = TRUE;
+
+   __cbvc_callback(cbp, cbp->cb_hp);
+
+   /* SJM 07/24/00 - unless user turned off with vpi control turn back on */
+   /* user may turn off in value change call back routine */
+   if (!dcep->dceu.dce_cbp->cb_user_off) dcep->dce_off = FALSE;
+
+   /* if only one force cb (common case) can stop now */
+   if (__num_vpi_force_cbs == 1) return; 
+  }
+}
+
+/*
+ * from release - go thru net dces looking for release cb 
+ */
+extern void __find_call_rel_cbs(struct net_t *np, int32 i1)
+{
+ register struct dcevnt_t *dcep;
+ register struct cbrec_t *cbp;
+
+ for (dcep = np->dcelst; dcep != NULL; dcep = dcep->dcenxt) 
+  {
+   if (dcep->dce_typ == DCE_RNG_CBR)
+    {
+     if (i1 != -1 && (i1 < dcep->dci2.i || i1 > dcep->dci1))
+      { if (__num_vpi_rel_cbs == 1) return; else continue; }
+     goto try_non_rng;
+    }
+   if (dcep->dce_typ != DCE_CBR) continue;
+try_non_rng:
+   /* only entire reg/wire or 1 bit of wire allowed here */
+   if (dcep->dce_matchitp != __inst_ptr) continue;
+   /* have matching force */  
+   cbp = dcep->dceu.dce_cbp;
+
+   /* SJM 07/24/00 - must run with this callback off in case rf in user code */
+   dcep->dce_off = TRUE;
+
+   __cbvc_callback(cbp, cbp->cb_hp);
+
+   /* SJM 07/24/00 - unless user turned off with vpi control turn back on */
+   /* user may turn off in value change call back routine */
+   if (!dcep->dceu.dce_cbp->cb_user_off) dcep->dce_off = FALSE;
+
+   /* if only one force cb (common case) can stop now */
+   if (__num_vpi_rel_cbs == 1) return; 
+  }
+}
+
+/*
+ * call all forces and release form registered call backs
+ *
+ * registered routine passed nil 
+ * no dce here - user can register multiple (handle built from changed)
+ *
+ * this builds a forced/released (after) changed reg or bit handle
+ * and does normal vc change call back after that
+ * fills dat obj field then frees handle and sets to nil upon return
+ *
+ * this works for all case because no instance specific filtering 
+ * so just use itree loc for one changed
+ */
+extern void __cb_all_rfs(struct net_t *np, int32 bi, int32 is_force)
+{
+ register struct rfcblst_t *rfp; 
+ word32 sav_cb_ndxobj;
+ struct cbrec_t *cbp;
+ struct h_t *hp;
+ struct task_t *tskp;
+
+ /* SJM 07/24/00 - if user executes force/release from within all rf */
+ /* type call back must not see rf callback again */ 
+ if ( __allrel_cbs_off) return;
+
+ __vpifnam_ind = __sfnam_ind;
+ __vpilin_cnt = __slin_cnt;
+ tskp = __getcur_scope_tsk();
+ /* SJM 07/24/00 - if user executes force/release from within all rf */
+ /* type call back must not see rf callback again */ 
+ if (is_force)
+  {
+   if (__allforce_cbs_off) return;
+   rfp = __force_allcb_hdr;
+  }
+ else
+  {
+   if (__allrel_cbs_off) return;
+   rfp = __rel_allcb_hdr; 
+  } 
+
+ for (; rfp != NULL; rfp = rfp->rfcbnxt)
+  {
+   cbp = rfp->rfcbp;
+   sav_cb_ndxobj = cbp->cb_ndxobj;
+   if (bi == -1)
+    {  
+     cbp->cb_ndxobj = FALSE;
+     hp = (struct h_t *) __mk_handle(vpiNet, (void *) np, __inst_ptr, tskp);
+    }
+   else 
+    {
+     cbp->cb_ndxobj = TRUE;
+     hp = (struct h_t *) __mk_handle(vpiNetBit, (void *) np, __inst_ptr, tskp);
+     hp->hrec->hi = bi;
+    }
+   /* SJM 07/24/00 - all force/release form cbs require no force/release */ 
+   /* call backs allows from within user callback routine in case user code */
+   /* does some forcing and releasing */
+   if (is_force) __allforce_cbs_off = TRUE; else __allrel_cbs_off = TRUE;
+
+   __cbvc_callback(cbp, hp);
+
+   if (is_force) __allforce_cbs_off = FALSE; else __allrel_cbs_off = FALSE;
+
+   /* this just frees temp handle allocated for call back */  
+   cbp->cb_ndxobj = sav_cb_ndxobj; 
+   /* free the temp object - because can be indexed need vpi free */
+   vpi_free_object((vpiHandle) hp);
+  }
+ __sfnam_ind = __vpifnam_ind;
+ __slin_cnt = __vpilin_cnt;
+}
+
+/*
+ * call the cb value change call back routine (process the change)
+ * also for force/release - net specific type - only cbrec ptr used
+ *
+ * for all form of force/release need to pass hp which is one that
+ * changed - changes each time called for all (nil) case
+ *
+ * dcep's always 1 instance - called for any change of expr. 
+ *
+ * must allocate new cb_data record and set time and and value fields
+ * (unless field type suppress) following new LRM rules for val chg cbs 
+ *
+ * this routine runs with no vpi_ location because event usually changes
+ * but does have an itree loc.
+ */
+extern void __cbvc_callback(struct cbrec_t *cbp, struct h_t *hp)
+{
+ int32 biti, ndx;
+ struct t_cb_data wrk_cbdata, *datp;
+ struct t_vpi_time wrk_time;
+ struct t_vpi_value wrk_val;
+ struct xstk_t *xsp;
+ struct net_t *np; 
+ struct h_t *hp2;
+ struct hrec_t *hrp2;
+
+ /* suppress call backs during reset */
+ if (__run_state == SS_RESET) return; 
+
+ datp = &wrk_cbdata;
+ datp->reason = cbp->cb_reason;
+ datp->cb_rtn = cbp->cb_rtn;
+ /* value change return call back requires all next 3 fields be present */
+ /* must be passed for all force/release case - usually just from cbp fld */
+ datp->obj = (vpiHandle) hp;
+ datp->time = &wrk_time;
+ datp->value = &wrk_val;
+ datp->user_data = cbp->cb_user_data;
+
+ if (cbp->cb_retvalfmt != vpiSuppressVal)
+  {
+   datp->value->format = (int32) cbp->cb_retvalfmt;
+   vpi_get_value(datp->obj, datp->value);  
+  }
+ else datp->value->format = vpiSuppressVal;
+ if (cbp->cb_rettimtyp != vpiSuppressTime)
+  {
+   datp->time->type = (int32) cbp->cb_rettimtyp;
+   __set_vpi_time(datp->time, &__simtime, datp->time->type, __inst_mod); 
+  }
+ else datp->time->type = vpiSuppressTime;
+
+ /* if bit handle or bit select or array word32 select handle set index field */
+ if (cbp->cb_ndxobj)
+  {  
+   /* cb object is object not index */
+   hp2 = (struct h_t *) datp->obj;
+   hrp2 = hp2->hrec;
+   /* alt form for expr. handle is index rather than expr. */
+   if (!hrp2->bith_ndx)
+    {
+     /* DBG remove --- */
+     if (hrp2->htyp != vpiNetBit && hrp2->htyp != vpiRegBit  
+      && hrp2->htyp != vpiVarSelect && hrp2->htyp != vpiMemoryWord) 
+      __vpi_terr(__FILE__, __LINE__);
+
+     if (hrp2->hu.hxp->optyp != LSB) __vpi_terr(__FILE__, __LINE__);
+     /* --- */
+
+     /* evaluate index expr. even if constant because of IS case */
+     __push_itstk(hp2->hin_itp);
+     xsp = __eval_xpr(hrp2->hu.hxp->ru.x);
+     __pop_itstk();
+     if (xsp->bp[0] != 0) datp->index = 0;
+     else
+      {
+       ndx = (int32) xsp->ap[0];
+       /* constants must be unnormalized - non constant not normalized so */
+       /* no need to unnormalize */
+       if (__expr_is_vpiconst(hp2->hrec->hu.hxp->ru.x))
+        {
+         np = hrp2->hu.hxp->lu.x->lu.sy->el.enp; 
+         biti = __unnormalize_ndx(np, ndx);
+        }
+       else biti = ndx;
+       __pop_xstk();
+       datp->index = biti;
+      }
+    }
+   /* for non expr bit obj type, stored as internal h:0 need unnormalize */
+   else datp->index = __unnormalize_ndx(hrp2->hu.hnp, hrp2->hi);
+  }
+
+ /* DBG remove --
+ if (__debug_flg && __ev_tracing)
+  {
+   -* SJM 08/16/01 - BEWARE - not sure if can call vpi routine in here *-
+   __tr_msg("<> processing vpi_ %s callback on %s now %s\n", 
+    to_cbtypnam(__xs2, datp->reason), vpi_get_str(vpiFullName, datp->obj),
+    __to_timstr(__xs, &__simtime));
+  }
+ --- */
+
+ (*(datp->cb_rtn))(datp);
+
+ /* t_cb_data automatic so no need to free */
+}
+
+/*
+ * execute a special case primitive output terminal value change call back
+ *
+ * these can only be freed by cb remove
+ */
+extern void __exec_vpi_gateoutcbs(register int32 tevpi)
+{
+ struct cbrec_t *cbp;
+
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+  {
+   /* if already cancelled (i.e. callback removed), nothing to do */ 
+   /* LOOKATME - think canceling not possible - will have been removed */
+   if (__tevtab[tevpi].te_cancel) continue;
+
+   cbp = __tevtab[tevpi].tu.tehp->hrec->hu.hcbp;
+   /* SJM 07/24/00 - user can turn off/on with sim control */ 
+   if (cbp->cb_user_off) continue;
+
+   __cbvc_callback(cbp, cbp->cb_hp);
+  }
+ /* nothing to free since cb_data record in automatic storage */ 
+}
+
+/*
+ * ROUTINES TO IMPLEMENT DELAY STYLE CALL BACKS
+ */
+
+/*
+ * routine that registers all delay (time) callbacks
+ * removal when done automatic - can be removed before happen
+ *
+ * for: sim start, wr sync, ro sync, next sim time, normal delay
+ *
+ * SJM 07/24/00 - delay call backs can't be turned off by user
+ */
+static vpiHandle delay_cb_register(register p_cb_data datp) 
+{
+ word64 ticksdel, schtim;
+ vpiHandle cbref;
+ i_tev_ndx tevpi;
+ struct h_t *hp;
+ struct mod_t *mdp;
+
+ /* need delay value in internal ticks */
+ ticksdel = 0ULL;
+ hp = (struct h_t *) datp->obj;
+ if (!chk_delay_cb(datp, hp)) return(NULL);
+
+ if (datp->reason != cbNextSimTime)
+  {
+   /* notice the object does not need to be scope object */
+   if (hp != NULL && hp->hin_itp != NULL)
+    mdp = hp->hin_itp->itip->imsym->el.emdp;
+   else mdp = NULL;  
+   if (!__vpitime_to_ticks(&ticksdel, datp->time, mdp)) return(NULL);
+  }
+
+ /* #0 cases - add to event queue - at current time */
+ if (datp->reason == cbNextSimTime || ticksdel == 0ULL)
+  {
+   /* can't schedule any #0 in ro sync region */
+   if (__rosync_slot && datp->reason != cbNextSimTime)
+    { __bad_rosync_err("vpi_register_cb"); return(NULL); }
+
+   cbref = bld_cbrec(datp, CB_DELAY);
+   /* notice reusing hp */
+   hp = (struct h_t *) cbref;
+   /* alloc as #0 */ 
+   alloc_tev_(tevpi, TE_VPICBDEL, __it_roots[0], __simtime);
+   __tevtab[tevpi].tu.tehp = hp;
+   /* back link from cbrec to event */
+   hp->hrec->hu.hcbp->cbtevpi = tevpi;
+
+   switch (datp->reason) {
+    case cbAtStartOfSimTime:
+     __vpi_err(1852, vpiError,
+      "vpi_register_cb cbAtStartOfSimTime #0 delay illegal - already past");
+
+     /* on error free actioncb psuedo event, free cbrec, and free callback */ 
+     __tevtab[tevpi].tenxti = __tefreelsti;
+     __tefreelsti = tevpi;
+     free_cbrec(hp->hrec->hu.hcbp);
+     return(NULL);
+    case cbReadOnlySynch:
+     /* link on end of rosync list - exec all cbs in register order */
+     if (__vpicb_tehdri[cbReadOnlySynch] == -1)
+      __vpicb_tehdri[cbReadOnlySynch] = __vpicb_teendi[cbReadOnlySynch]
+       = tevpi;
+     else
+      {
+       __tevtab[__vpicb_teendi[cbReadOnlySynch]].tenxti = tevpi;
+       __vpicb_teendi[cbReadOnlySynch] = tevpi;
+      }
+     __slotend_action |= SE_VPIROSYNC;
+     break;
+    case cbNextSimTime:
+     /* link on front of nxtim list */
+     if (__vpicb_tehdri[cbNextSimTime] == -1)
+      __vpicb_tehdri[cbNextSimTime] = __vpicb_teendi[cbNextSimTime] = tevpi;
+     else
+      {
+       __tevtab[__vpicb_teendi[cbNextSimTime]].tenxti = tevpi;
+       __vpicb_teendi[cbNextSimTime] = tevpi;
+      }
+     __have_vpi_actions = TRUE;
+     break;
+    case cbReadWriteSynch:
+     /* MAYBE FIXME  - for now same as #0 except future becomes #0 */
+    case cbAfterDelay:
+     if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+     else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+     break;
+    default: __vpi_terr(__FILE__, __LINE__);
+   }
+   return(cbref);
+  }
+ /* case 2: for later time */ 
+ schtim = __simtime + ticksdel;
+ cbref = bld_cbrec(datp, CB_DELAY);
+ alloc_tev_(tevpi, TE_VPICBDEL, __it_roots[0], schtim);
+ hp = (struct h_t *) cbref;
+ __tevtab[tevpi].tu.tehp = hp; 
+ /* back link from cbrec to event */
+ hp->hrec->hu.hcbp->cbtevpi = tevpi;
+
+ /* some later slot */
+ switch (datp->reason) {
+  case cbAtStartOfSimTime:
+   /* add to front instead of end of queue */
+   __tevtab[tevpi].vpi_onfront = TRUE;
+   __insert_event(tevpi);
+   break;
+  case cbReadWriteSynch: case cbReadOnlySynch:
+   /* schedule ev for future normal event queue, flag frees, alloc, schds #0 */
+   __tevtab[tevpi].vpi_reschd = TRUE;
+   __insert_event(tevpi);
+   break;
+  case cbAfterDelay:
+   __insert_event(tevpi);
+   break;
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(cbref);
+}
+
+/*
+ * check force/release callback passed cb_data record
+ */
+static int32 chk_delay_cb(p_cb_data datp, struct h_t *hp)
+{
+ /* if optional obj present, it must be valid and a scope object */
+ if (hp != NULL)
+  {
+   if (!__validate_nonit_handle("delay vpi_register_cb", hp)) return(FALSE);
+  }
+ /* unless next sim time, time field required and must not be suppress */
+ if (datp->reason != cbNextSimTime)
+  {
+   if (datp->time == NULL) 
+    {
+     __vpi_err(1934, vpiError,
+      "delay vpi_register_cb p_cb_data record required time field missing"); 
+     return(FALSE);
+    }
+   /* validate time format */
+   if (!__validate_time_type("delay call back", datp->time->type))
+    return(FALSE);
+   if (datp->time->type == vpiSuppressTime) 
+    {
+     __vpi_err(1935, vpiError,
+      "delay vpi_register_cb p_cb_data record time field type vpiSuppress field illegal"); 
+      return(FALSE);
+    }
+  }
+ /* value field ignored - so may be nil - no need to check */
+ return(TRUE);
+}
+
+/*
+ * execute a delay related call back list
+ *
+ * only for ro sync and nxt sim time (after move time)
+ * after event is processed, the cbrec is freed 
+ * tevs freed when done en masse here
+ * list may be empty if all removed - no way to detect until here
+ *
+ * SJM 07/24/00 - delay call backs can't be turned off by user
+ */
+static void exec_vpi_delaycbs(int32 cbtyp)
+{
+ register i_tev_ndx tevpi;
+
+ /* all may have been cancelled */
+ if ((tevpi = __vpicb_tehdri[cbtyp]) == -1) return;
+
+ if (cbtyp == cbReadOnlySynch) __rosync_slot = TRUE; 
+ /* if cancelled cbrec will be freed */
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+  {
+   /* since not scheduled - never can be cancelled */
+   /* DBG remove ---
+   if (__tevtab[tevpi].te_cancel) __vpi_terr(__FILE__, __LINE__);
+   if (__tevtab[tevpi].vpi_reschd) __vpi_terr(__FILE__, __LINE__);
+   --- */
+   /* when called from here reschd never on */
+   __delay_callback(tevpi);
+  }
+
+ /* slot end action turned off all at once later */
+ /* add entire list to tev free list - know no guts */
+ __tevtab[__vpicb_teendi[cbtyp]].tenxti = __tefreelsti;
+ __tefreelsti = __vpicb_tehdri[cbtyp];
+ __vpicb_tehdri[cbtyp] = __vpicb_teendi[cbtyp] = -1;
+ if (cbtyp == cbReadOnlySynch) __rosync_slot = FALSE; 
+}
+
+/*
+ * call the cb delay routine - event exec is calling cb routine
+ * used for all time related cbs
+ *
+ * when processed (not just moved to other part of slot) will never happen
+ * again and handle is freed
+ *
+ * 2 ways through here - 1) move event to other part of slot list, 2) do
+ * callback and free event since done and can never happen again
+ *
+ * if call back cancelled, event cancelled so will never get here
+ */
+extern void __delay_callback(i_tev_ndx tevpi)
+{
+ int32 tevp2i;
+ struct t_cb_data wrk_cbdata, *datp;
+ struct t_vpi_time wrk_time;
+ struct cbrec_t *cbp;
+ struct h_t *cbhp;
+ struct mod_t *mdp;
+
+ /* DBG remove -- */
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg("-- processing vpi_ delay call back at %s\n", 
+   __to_timstr(__xs, &__simtime));
+  }
+ /* --- */
+
+ cbhp = __tevtab[tevpi].tu.tehp;
+ cbp = cbhp->hrec->hu.hcbp; 
+ /* move to right sync location */
+ if (__tevtab[tevpi].vpi_reschd)
+  {
+   /* SJM 08/07/00 - must schedule new event since carrier event free */
+   /* enmass with all other regular events in now being processed queue */ 
+   alloc_tev_(tevp2i, TE_VPICBDEL, __tevtab[tevpi].teitp, __simtime);   
+   /* move cb hp ptr to new event */
+   __tevtab[tevp2i].tu.tehp = cbhp;
+   /* nil field in normal event queue event since it is soon to be freed */
+   __tevtab[tevpi].tu.tehp = NULL;
+   __num_proc_tevents--;
+   /* now all fields same except vpi reschd not on in new - as needed */
+
+   if (cbp->cb_reason == cbReadWriteSynch)
+    {
+     if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevp2i;
+     else { __tevtab[__p0_te_endi].tenxti = tevp2i; __p0_te_endi = tevp2i; }
+    }
+   else if (cbp->cb_reason == cbReadOnlySynch)
+    {
+     /* link on end of rosync list since exec cbs in register order */
+     if (__vpicb_tehdri[cbReadOnlySynch] == -1)
+      __vpicb_tehdri[cbReadOnlySynch] = __vpicb_teendi[cbReadOnlySynch]
+       = tevp2i;
+     else
+      { 
+       __tevtab[__vpicb_teendi[cbReadOnlySynch]].tenxti = tevp2i; 
+       __vpicb_teendi[cbReadOnlySynch] = tevp2i;
+      }
+     __slotend_action |= SE_VPIROSYNC;
+    }
+   else __vpi_terr(__FILE__, __LINE__);
+   return;
+  }
+
+ datp = &wrk_cbdata;
+ datp->reason = cbp->cb_reason;
+ datp->cb_rtn = cbp->cb_rtn;
+ /* if user passed object (for scope) must return else nil */
+ if (cbp->cb_hp != NULL) datp->obj = (vpiHandle) cbp->cb_hp;
+ else datp->obj = NULL;
+
+ wrk_time.type = vpiSuppressTime;
+ datp->time = &wrk_time;
+ /* value always nil */
+ datp->value = NULL;
+ datp->user_data = cbp->cb_user_data;
+ 
+ /* assign time */  
+ if (cbp->cb_rettimtyp != vpiSuppressTime)
+  {
+   datp->time->type = (int32) cbp->cb_rettimtyp;
+   if (cbp->cb_hp != NULL) mdp = cbp->cb_hp->hin_itp->itip->imsym->el.emdp;
+   else mdp = NULL;  
+   __set_vpi_time(datp->time, &__simtime, datp->time->type, mdp); 
+  }
+
+ (*(cbp->cb_rtn))(datp);
+
+ /* datp freed since automatic var */
+ /* remove the call back since can't happen again */
+ free_cbrec(cbp);
+ /* event will be collected by normal mechanism or when all of list done */
+ __tevtab[tevpi].tu.tehp = NULL;  
+}
+
+/*
+ * remove a callback - must unline from global list
+ * only field to free is cb_hp copied object - cbtevp not freeable from here
+ */
+static void free_cbrec(struct cbrec_t *cbp)
+{
+ struct h_t *cbhp;
+
+ /* link out of list */ 
+ /* case 1: at front */
+ if (cbp->cbprev == NULL)
+  {
+   __vpi_cbrec_hdr = cbp->cbnxt;
+   if (cbp->cbnxt != NULL) cbp->cbnxt->cbprev = NULL;
+  }
+ /* case 2: at end but not at front */
+ else if (cbp->cbnxt == NULL) cbp->cbprev->cbnxt = NULL;
+ /* case 3: inside */
+ else { cbp->cbprev->cbnxt = cbp->cbnxt; cbp->cbnxt->cbprev = cbp->cbprev; }
+
+ /* free the copied object handle */
+ if (cbp->cb_hp != NULL)
+  {
+   vpi_free_object((vpiHandle) cbp->cb_hp);
+  }
+ cbhp = cbp->cb_cbhp;
+ __free_hp(cbhp);
+ 
+ __my_free((char *) cbp, sizeof(struct cbrec_t));
+}
+
+/*
+ * add a call back to a action (or feature) (fixed) reason
+ *
+ * cbs remain unless explicitly removed
+ * value and time fields completely ignored
+ */
+static vpiHandle action_cb_register(register p_cb_data datp) 
+{
+ word64 timval;
+ vpiHandle cbref;
+ struct cbrec_t *cbp; 
+ struct h_t *cbhp;
+ i_tev_ndx tevpi;
+
+ if (datp->reason == cbCustomer1)
+  {
+   if (__vpicb_tehdri[datp->reason] != -1)
+    {
+     __vpi_err(1830, vpiError, "cbCustomer1 action callback unsupported");
+     return(NULL);
+    }
+  }
+
+ /* already checked cb_rtn and reason, rest need not be set at all */
+ /* because they are ignored */
+
+ /* need a cbref to hold passsed cb data record */
+ cbref = bld_cbrec(datp, CB_ACTION);
+ cbhp = (struct h_t *) cbref;
+ cbp = cbhp->hrec->hu.hcbp;
+ /* need an event so cb can be removed */
+ timval = 0ULL;
+ alloc_tev_(tevpi, 0, NULL, timval);
+ __tevtab[tevpi].tu.tehp = cbhp;
+ /* needed for remove because must match event from non delay sched list */
+ cbp->cbtevpi = tevpi;
+
+ /* link on to end of list */
+ if (__vpicb_tehdri[datp->reason] == -1)
+  __vpicb_tehdri[datp->reason] = __vpicb_teendi[datp->reason] = tevpi;
+ else
+  {
+   __tevtab[__vpicb_teendi[datp->reason]].tenxti = tevpi;
+   __vpicb_teendi[datp->reason] = tevpi;
+  }
+ /* need special flag for at least one cbError cb active */
+ if (datp->reason == cbError) __vpierr_cb_active = TRUE;
+ __have_vpi_actions = TRUE;
+ return(cbref);
+}
+
+/*
+ * try to call start of reset routine
+ *
+ * wrapper around call since vpi_ include only in vpi_ code
+ */
+extern void __vpi_startreset_trycall(void)
+{
+ if (__vpicb_tehdri[cbStartOfReset] != -1)
+  exec_vpi_actioncbs(cbStartOfReset);
+}
+
+/*
+ * execute end of reset callback wrapper
+ */
+extern void __vpi_endreset_trycall(void)
+{
+ if (__vpicb_tehdri[cbEndOfReset] != -1)
+  exec_vpi_actioncbs(cbEndOfReset);
+}
+
+/*
+ * execute end of compile callback wrapper
+ */
+extern void __vpi_endcomp_trycall(void)
+{
+ if (__vpicb_tehdri[cbEndOfCompile] != -1)
+  exec_vpi_actioncbs(cbEndOfCompile);
+}
+
+/*
+ * execute start of sim callback wrapper
+ */
+extern void __vpi_startsim_trycall(void)
+{
+ if (__vpicb_tehdri[cbStartOfSimulation] != -1)
+  exec_vpi_actioncbs(cbStartOfSimulation);
+}
+
+/*
+ * execute end of sim callback wrapper
+ */
+extern void __vpi_endsim_trycall(void)
+{
+ if (__vpicb_tehdri[cbEndOfSimulation] != -1)
+  exec_vpi_actioncbs(cbEndOfSimulation);
+}
+
+/*
+ * try to call enter iact reason wrapper
+ */
+extern void __vpi_enteriact_trycall(void)
+{
+ __vpifnam_ind = __sfnam_ind;
+ __vpilin_cnt = __slin_cnt;
+ 
+ if (__vpicb_tehdri[cbEnterInteractive] != -1)
+  exec_vpi_actioncbs(cbEnterInteractive);
+
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+}
+
+/*
+ * try to call exit iact reason wrapper
+ */
+extern void __vpi_exitiact_trycall(void)
+{
+ __vpifnam_ind = __sfnam_ind;
+ __vpilin_cnt = __slin_cnt;
+
+ if (__vpicb_tehdri[cbExitInteractive] != -1)
+  exec_vpi_actioncbs(cbExitInteractive);
+
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+}
+
+/*
+ * try to call interactive scope change reason wrapper
+ * this sets cb data handle using alloced and freed after call handle obj
+ */
+extern void __vpi_iactscopechg_trycall(void)
+{
+ word32 parhtyp;
+ vpiHandle scopobj;
+ struct t_cb_data wrk_cbdata, *datp;
+ struct cbrec_t *cbp;
+ i_tev_ndx tevpi;
+ struct mod_t *mdp;
+ struct task_t *up_tskp;
+ struct symtab_t *sytp; 
+
+ if ((tevpi = __vpicb_tehdri[cbInteractiveScopeChange]) == -1) return;
+
+ __vpifnam_ind = __sfnam_ind;
+ __vpilin_cnt = __slin_cnt;
+
+ /* interactive scope change call back sets obj field to new scope */ 
+ if (__scope_tskp == NULL)
+  {
+   mdp = __scope_ptr->itip->imsym->el.emdp;
+   scopobj = __mk_handle(vpiModule, (void *) mdp, __scope_ptr, NULL);
+  }
+ else
+  {
+   sytp = __scope_tskp->tsksymtab;
+   if (sytp->sytpar == NULL || sytp->sytpar->sypofsyt->sytyp == SYM_M)
+    up_tskp = NULL;
+   else up_tskp = sytp->sytpar->sypofsyt->el.etskp;
+
+   parhtyp = __to_vpi_tasktyp(__scope_tskp->tsktyp);
+   scopobj = __mk_handle(parhtyp, (void *) __scope_tskp, __scope_ptr, up_tskp);
+  }
+
+ datp = &wrk_cbdata;
+ /* for action callback next 2 must be nil */
+ datp->time = NULL;
+ datp->value = NULL;
+ /* scope object always return as obj - required */
+ datp->obj = scopobj;
+
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+  {
+   /* DBG remove --- */
+   if (__tevtab[tevpi].te_cancel) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+
+   cbp = __tevtab[tevpi].tu.tehp->hrec->hu.hcbp;
+
+   /* SJM 07/24/00 - user can turn off/on with sim control */ 
+   if (cbp->cb_user_off) continue;
+
+   datp->reason = cbp->cb_reason;
+   datp->cb_rtn = cbp->cb_rtn;
+   datp->user_data = cbp->cb_user_data;
+
+   (*(datp->cb_rtn))(datp);
+  }
+ /* datp automatic so no need to free */
+ /* must leave callback cbrec until released */
+
+ /* can't free created scope object - because user may save and use */ 
+
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+}
+
+/*
+ * try to call next sim time (next move time time) reason wrapper
+ * this is delay cb not action
+ */
+extern void __vpi_del_nxtsimtim_trycall(void)
+{
+ if (__vpicb_tehdri[cbNextSimTime] != -1) exec_vpi_delaycbs(cbNextSimTime);
+}
+
+/*
+ * call the rosync (know slot bit set)
+ * this is del cb not action
+ */
+extern void __vpi_del_rosync_call(void)
+{
+ exec_vpi_delaycbs(cbReadOnlySynch);
+}
+
+/*
+ * try to call tchk violation reason wrapper
+ */
+extern void __vpi_tchkerr_trycall(struct tchk_t *tcp, struct itree_t *itp)
+{
+ __vpifnam_ind = tcp->tcsym->syfnam_ind;
+ __vpilin_cnt = tcp->tcsym->sylin_cnt;
+
+ if (__vpicb_tehdri[cbTchkViolation] != -1)
+  exec_vpi_tchkerr(cbTchkViolation, tcp, itp);
+
+ __vpifnam_ind = 0;
+ __vpilin_cnt = 0;
+}
+
+/*
+ * try to call vpi_ PLI error (only for __vpi errors) reason wrapper
+ *
+ * here error location maybe set by caller of error
+ *
+ * if error call back generated by routine called from error cb
+ * end with fatal error since serious user code bug (infinite loop)
+ */
+extern void __vpi_plierror_trycall(void)
+{
+ if (__acc_vpi_erroff) return;
+
+ if (__vpicb_tehdri[cbPLIError] != -1)
+  {
+   if (__in_vpi_errorcb) 
+    {
+     __pv_vpi_terr(303,
+     "cbPLIError callback caused recursive error callback - giving up"); 
+    }
+   __in_vpi_errorcb = TRUE;
+   exec_vpi_actioncbs(cbPLIError);
+   __in_vpi_errorcb = FALSE;
+  }
+}
+
+/*
+ * try to call vpi_ non PLI error reason wrapper
+ *
+ * all Cver errors except interactive try to call these callbacks
+ * vpi_chk_error used inside these call backs to get Cver einfo
+ */
+extern void __vpi_error_trycall(void)
+{
+ if (__acc_vpi_erroff) return;
+
+ if (__vpicb_tehdri[cbError] == -1) return;
+
+ if (__in_vpi_errorcb) 
+  {
+   __pv_vpi_terr(303,
+    "cbError callback caused recursive error callback - giving up"); 
+  }
+ __in_vpi_errorcb = TRUE;
+ exec_vpi_actioncbs(cbError);
+ __in_vpi_errorcb = FALSE;
+
+ /* PLI error status on until next routine, but other Cver errors */
+ /* only pending in callback - if no callback no error ever pending */
+ /* and when all callbacks done, always turned off */
+ /* needed because no obvious place to reset non PLI errors */
+ __last_eip = NULL;
+}
+
+
+/*
+ * execute a fixed action or feature call back list
+ *
+ * these can only be freed by cb remove
+ */
+static void exec_vpi_actioncbs(int32 cbtyp)
+{
+ register i_tev_ndx tevpi;
+ struct cbrec_t *cbp;
+ struct t_cb_data wrk_cbdata, *datp;
+
+ if ((tevpi = __vpicb_tehdri[cbtyp]) == -1) return;
+
+ datp = &wrk_cbdata;
+ /* for action cbs, next 3 nil */
+ datp->time = NULL;
+ datp->value = NULL;
+ datp->obj = NULL;
+
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+  {
+   /* if already cancelled (i.e. callback removed), nothing to do */ 
+   if (__tevtab[tevpi].te_cancel) continue;
+
+   cbp = __tevtab[tevpi].tu.tehp->hrec->hu.hcbp;
+   /* SJM 07/24/00 - user can turn off/on with sim control */ 
+   if (cbp->cb_user_off) continue;
+
+   datp->reason = cbp->cb_reason;
+   datp->cb_rtn = cbp->cb_rtn;
+   datp->user_data = cbp->cb_user_data;
+
+   (*(datp->cb_rtn))(datp);
+  }
+ /* nothing to free since cb_data record in automatic storage */ 
+}
+
+/*
+ * execute a timing check feature call back list
+ * these can only be freed by cb remove (or reset)
+ */
+static void exec_vpi_tchkerr(int32 cbtyp, struct tchk_t *tcp,
+ struct itree_t *itp)
+{
+ register i_tev_ndx tevpi;
+ struct cbrec_t *cbp;
+ struct t_cb_data wrk_cbdata, *datp;
+
+ if ((tevpi = __vpicb_tehdri[cbtyp]) == -1) return;
+
+ datp = &wrk_cbdata;
+ /* for action cbs, next 2 nil */
+ datp->time = NULL;
+ datp->value = NULL;
+ /* free on return when all call backs done */
+ datp->obj = __mk_handle(vpiTchk, (void *) tcp, itp, NULL);
+
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+  {
+   /* if cancelled, cbrec will have been freed */ 
+   if (__tevtab[tevpi].te_cancel) continue;
+
+   cbp = __tevtab[tevpi].tu.tehp->hrec->hu.hcbp;
+
+   /* SJM 07/24/00 - user can turn off/on with sim control */ 
+   if (cbp->cb_user_off) continue;
+
+   datp->reason = cbp->cb_reason;
+   datp->cb_rtn = cbp->cb_rtn;
+
+   (*(datp->cb_rtn))(datp);
+  }
+ /* can't free timing check object - caller may use it */
+}
+
+/*
+ * execute a Cver extended foreign language line cb 
+ * call back is cbLanguageLine
+ * these can only be freed by cb remove
+ *
+ * this fills value record misc field with ptr to line record
+ */
+extern void __exec_vpi_langlinecbs(char *lp, char *fnam, int32 lno)
+{
+ register i_tev_ndx tevpi;
+ struct t_vpi_value wrk_val;
+ struct t_vpi_languageline wrk_langlin;
+ struct cbrec_t *cbp;
+ struct t_cb_data wrk_cbdata, *datp;
+
+ if ((tevpi = __vpicb_tehdri[cbLanguageLine]) == -1) return;
+
+ datp = &wrk_cbdata;
+ /* for action cbs, next 3 nil */
+ datp->time = NULL;
+ datp->value = &wrk_val;
+ datp->value->format = vpiStringVal;
+ datp->value->value.misc = (char *) &wrk_langlin;
+ wrk_langlin.linep = lp;
+ wrk_langlin.file = fnam;
+ wrk_langlin.lineno = lno;
+ datp->obj = NULL;
+
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
+  {
+   /* if already cancelled (i.e. callback removed), nothing to do */ 
+   if (__tevtab[tevpi].te_cancel) continue;
+
+   cbp = __tevtab[tevpi].tu.tehp->hrec->hu.hcbp;
+   datp->reason = cbp->cb_reason;
+   datp->cb_rtn = cbp->cb_rtn;
+   datp->user_data = cbp->cb_user_data;
+
+   (*(datp->cb_rtn))(datp);
+  }
+ /* nothing to free since cb_data record in automatic storage */ 
+}
+
+/*
+ * CALLBACK REMOVAL ROUTINES
+ */
+
+/*
+ * remove a call back - find and free the cbrec
+ *
+ * handle is also freed because if used again will cause error
+ * can access handle from event and cbrec from handle and back link from 
+ * cbrec to event
+ *
+ * notice not freeing p_cb_data since user allocated
+ * if user references after remove cb, error
+ * BEWARE - action cbs usually do not have any itree loc (hin_itp nil) 
+ *
+ * SJM 02/08/03 - removed need for module since now just turn off dces
+ */
+extern PLI_INT32 vpi_remove_cb(vpiHandle cb_obj)
+{
+ i_tev_ndx tevpi;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+ struct cbrec_t *cbp;
+ struct tev_t *tevp;
+
+ __last_eip = NULL;
+ hp = (struct h_t *) cb_obj;
+ if (!__validate_handle("vpi_remove_cb", hp)) return(FALSE);
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiCallback)
+  {
+   __vpi_err(1832, vpiError,
+    "vpi_remove_cb requires vpiCallback handle - %s illegal",
+    __to_vpionam(__wrks1, hrp->htyp));
+   return(FALSE);
+  }
+ cbp = hrp->hu.hcbp;
+
+ switch (cbp->cb_reason) {
+  /* value change call backs - removal after some occurred */ 
+  case cbValueChange:
+   if (__run_state != SS_SIM)
+    {
+no_sim:
+      __sim_notbegun_err("vpi_remove_cb");
+      return(FALSE);
+    } 
+   /* no event here - once dce records gone, can't occur */
+   /* this can only run once simulation starts run state is SIM STATE */ 
+   if (cbp->cb_gateout) linkout_gateout_cb(cbp); 
+   else
+    {
+     /* SJM 02/08/03 - can only free iact stmt dce if -O on */
+     if (__optimized_sim) __dcelst_off(cbp->cbdcep);
+     else __free_dceauxlst(cbp->cbdcep, 1);
+    }
+   free_cbrec(cbp);
+   break;
+  case cbForce:
+   if (__run_state != SS_SIM) goto no_sim;
+   if (cbp->cb_hp != NULL) 
+    {
+     /* SJM 02/08/03 - can only free iact stmt dce if -O on */
+     if (__optimized_sim) __dcelst_off(cbp->cbdcep);
+     else __free_dceauxlst(cbp->cbdcep, 1);
+
+     free_cbrec(cbp);
+     __num_vpi_force_cbs--;
+     if (__num_vpi_force_cbs < 0) __vpi_terr(__FILE__, __LINE__);
+    }
+   else linkout_allcb(cbp, TRUE);
+   break;
+  case cbRelease:
+   if (__run_state != SS_SIM) goto no_sim;
+   if (cbp->cb_hp != NULL) 
+    {
+     /* SJM 02/08/03 - can only free iact stmt dce if -O on */
+     if (__optimized_sim) __dcelst_off(cbp->cbdcep);
+     else __free_dceauxlst(cbp->cbdcep, 1);
+
+     free_cbrec(cbp);
+     __num_vpi_rel_cbs--;
+     if (__num_vpi_rel_cbs < 0) __vpi_terr(__FILE__, __LINE__);
+    }
+   else linkout_allcb(cbp, FALSE);
+   break;
+
+  /* call backs only removed before they happen */ 
+  /* case 1: always scheduled - part of all events removed at end of slot */ 
+  /* RW sync moves from scheduled with vpi reschd on to #0 list so */ 
+  case cbAfterDelay: case cbAtStartOfSimTime: case cbReadWriteSynch:
+   if (__run_state != SS_SIM) goto no_sim;
+   /* when cancelled handle zero and removed from iterator list so must */
+   /* never be seen again */
+   tevpi = cbp->cbtevpi; 
+   tevp = &(__tevtab[tevpi]);
+   /* DBG remove --- */  
+   if (tevp->te_cancel) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   free_cbrec(cbp);
+   tevp->te_cancel = TRUE;
+   tevp->tu.tehp = NULL;  
+   break;  
+
+  /* if vpi reschd on, scheduled so cancel event */
+  /* else remove from action list */
+  case cbReadOnlySynch:
+   if (__run_state != SS_SIM) goto no_sim;
+   tevpi = cbp->cbtevpi; 
+   tevp = &(__tevtab[tevpi]);
+   /* DBG remove --- */
+   if (tevp->te_cancel) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   if (!tevp->vpi_reschd) goto in_nonschd_list;
+
+   free_cbrec(cbp);
+   tevp->te_cancel = TRUE;
+   tevp->tu.tehp = NULL;  
+   break;  
+  /* this is treated as an action cb for removal - delay when happens */
+  case cbNextSimTime:
+   if (__run_state != SS_SIM) goto no_sim;
+   goto in_nonschd_list;
+
+  /* action cbs */
+  case cbEndOfCompile: case cbStartOfSimulation: case cbEndOfSimulation:
+  case cbError: case cbPLIError: case cbTchkViolation:
+  case cbStartOfReset: case cbEndOfReset:
+  case cbEnterInteractive: case cbExitInteractive:
+  case cbInteractiveScopeChange:
+  case cbLanguageLine: 
+in_nonschd_list:
+   /* permanent lists - link out */
+   linkout_action_cb(cbp);
+   free_cbrec(cbp);
+   break;
+  /* currently unimplemented */
+  case cbStartOfSave: case cbEndOfSave: case cbStartOfRestart:
+  case cbEndOfRestart:
+  case cbUnresolvedSystf:
+   __vpi_err(1823, vpiError, "vpi_remove_cb reason %s unsupported", 
+    __cb_reason_to_nam(__wrks1, cbp->cb_reason));
+   return(FALSE);
+  case cbStmt:
+   __vpi_err(1823, vpiError,
+    "vpi_remove_cb reason %s unsupported - statement callbacks not yet implemented",
+    __cb_reason_to_nam(__wrks1, cbp->cb_reason));
+   return(FALSE);
+  default:
+   __vpi_err(1824, vpiError,
+    "vpi_remove_cb illegal reason value %d - no callback removed",
+     cbp->cb_reason); 
+   return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * find and link out all forces or release handle (cbrec in list)
+ *
+ * this also frees cbrec and allocated copy of cb_data record 
+ */
+static void linkout_allcb(struct cbrec_t *cbp, int32 is_force)
+{
+ register struct rfcblst_t *rfp, *last_rfp; 
+ 
+ last_rfp = NULL;
+ if (is_force)
+  {
+   rfp = __force_allcb_hdr;
+   /* DBG remove --- */
+   if (__vpi_force_cb_always && rfp == NULL) __vpi_terr(__FILE__, __LINE__);
+   if (!__vpi_rel_cb_always && rfp != NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */  
+   for (; rfp != NULL; rfp = rfp->rfcbnxt)
+    { if (rfp->rfcbp == cbp) goto got_force_cbp; last_rfp = rfp; }
+   __vpi_terr(__FILE__, __LINE__);
+got_force_cbp:
+   /* case 1: removing from front */
+   if (last_rfp == NULL) 
+    {
+     /* case 1a: only one */ 
+     if (rfp->rfcbnxt == NULL)
+      {
+       __vpi_force_cb_always = FALSE;
+       __force_allcb_hdr = __force_allcb_end = NULL;
+rem_done:
+       free_cbrec(rfp->rfcbp);
+       __my_free((char *) rfp, sizeof(struct rfcblst_t)); 
+       return;
+     }
+     /* case 1b: more than one */
+     __force_allcb_hdr = rfp->rfcbnxt;
+     goto rem_done;
+    }
+   /* case 2: removing from inside */
+   if (rfp->rfcbnxt == NULL)
+    {  
+     /* case 2a: removing last */
+     __force_allcb_end = last_rfp;
+     last_rfp->rfcbnxt = NULL; 
+     goto rem_done;
+    }
+   /* case 2a: removing interior */
+   last_rfp->rfcbnxt = rfp->rfcbnxt;
+   goto rem_done;
+  }
+ rfp = __rel_allcb_hdr;
+ /* DBG remove --- */
+ if (__vpi_rel_cb_always && rfp == NULL) __vpi_terr(__FILE__, __LINE__);
+ if (!__vpi_rel_cb_always && rfp != NULL) __vpi_terr(__FILE__, __LINE__);
+ /* --- */  
+ for (; rfp != NULL; rfp = rfp->rfcbnxt)
+  { if (rfp->rfcbp == cbp) goto got_rel_cbp; last_rfp = rfp;   }
+ __vpi_terr(__FILE__, __LINE__);
+got_rel_cbp:
+ /* case 1: removing from front */
+ if (last_rfp == NULL) 
+  {
+   /* case 1a: only one */ 
+   if (rfp->rfcbnxt == NULL)
+    {
+     __vpi_rel_cb_always = FALSE;
+     __rel_allcb_hdr = __rel_allcb_end = NULL;
+     goto rem_done;
+    }
+   /* case 1b: more than one */
+   __rel_allcb_hdr = rfp->rfcbnxt;
+   goto rem_done;
+  }
+ /* case 2: removing from inside */
+ if (rfp->rfcbnxt == NULL)
+  {  
+   /* case 2a: removing last */
+   __rel_allcb_end = last_rfp;
+   last_rfp->rfcbnxt = NULL; 
+   goto rem_done;
+  }
+ /* case 2a: removing interior */
+ last_rfp->rfcbnxt = rfp->rfcbnxt;
+ goto rem_done;
+}
+
+/*
+ * link out prim output term 
+ *
+ * although using tev, not part of scheduling mechanism just in list
+ */
+static void linkout_gateout_cb(struct cbrec_t *cbp) 
+{
+ register i_tev_ndx tevpi, last_tevpi;
+ int32 gi, ii;
+ struct h_t *ghp;
+ struct gate_t *gp;
+ struct mod_t *mdp;
+
+ ghp = cbp->cb_hp;
+ mdp = ghp->hin_itp->itip->imsym->el.emdp;
+ ii = ghp->hin_itp->itinum;
+ gp = ghp->hrec->hu.hgp;
+ gi = gp - mdp->mgates;
+ if (mdp->mgateout_cbs == NULL || mdp->mgateout_cbs[gi] == NULL
+  || mdp->mgateout_cbs[gi][ii] == -1)
+  {  
+   __vpi_err(1826, vpiError,
+    "vpi_remove_cb of primitive terminal output value change type failed - cb handle already removed?");
+   return;
+  }  
+ last_tevpi = -1;
+ tevpi = mdp->mgateout_cbs[gi][ii];
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)  
+  {
+   /* find right one to remove and one before it if not front */
+   if (tevpi != cbp->cbtevpi) { last_tevpi = tevpi; continue; } 
+
+   /* one to remove on front */
+   if (last_tevpi == -1) 
+    {
+     /* just one to remove */
+     if (__tevtab[tevpi].tenxti == -1) mdp->mgateout_cbs[gi][ii] = -1;
+     /* link out first te end remains same */
+     else mdp->mgateout_cbs[gi][ii] = __tevtab[tevpi].tenxti;
+    }
+   else
+    {
+     /* at end */
+     if (__tevtab[tevpi].tenxti == -1) __tevtab[last_tevpi].tenxti = -1;
+     /* te end remains same */
+     else __tevtab[last_tevpi].tenxti = __tevtab[tevpi].tenxti;
+    }
+   /* link on front of free list - pseudo event so nothing else to do */
+   __tevtab[tevpi].tenxti = __tefreelsti;
+   __tefreelsti = tevpi;
+   return;
+  }
+ __vpi_terr(__FILE__, __LINE__);
+}
+
+/*
+ * link out action call back tevp from an action list
+ *
+ * although using tev, not part of scheduling mechanism just in list
+ */
+static void linkout_action_cb(struct cbrec_t *cbp) 
+{
+ register i_tev_ndx tevpi, last_tevpi;
+
+ if ((tevpi = __vpicb_tehdri[cbp->cb_reason]) == -1)
+  {  
+   __vpi_err(1826, vpiError,
+    "vpi_remove_cb of action type %s failed - cb handle already removed?",
+    to_cbtypnam(__wrks1, cbp->cb_reason));
+   return;
+  }  
+ last_tevpi = -1;
+ for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)  
+  {
+   /* find right one to remove and one before it if not front */
+   if (tevpi != cbp->cbtevpi) { last_tevpi = tevpi; continue; } 
+
+   /* one to remove on front */
+   if (last_tevpi == -1) 
+    {
+     /* just one to remove */
+     if (__tevtab[tevpi].tenxti == -1)
+      {
+       /* turn off special compile error callback registered flag */
+       if (__vpicb_tehdri[cbp->cb_reason] == cbError)
+        __vpierr_cb_active = FALSE;
+     
+       /* then remove the action call back */
+       __vpicb_tehdri[cbp->cb_reason] = __vpicb_teendi[cbp->cb_reason] = -1; 
+      }
+     /* link out first te end remains same */
+     else __vpicb_tehdri[cbp->cb_reason] = __tevtab[tevpi].tenxti;
+    }
+   else
+    {
+     /* at end */
+     if (__tevtab[tevpi].tenxti == -1)
+      {
+       __tevtab[last_tevpi].tenxti = -1;
+       __vpicb_teendi[cbp->cb_reason] = last_tevpi;
+      }
+     /* te end remains same */
+     else __tevtab[last_tevpi].tenxti = __tevtab[tevpi].tenxti;
+    }
+   /* link on front of free list - pseudo event so nothing else to do */
+   __tevtab[tevpi].tenxti = __tefreelsti;
+   __tefreelsti = tevpi;
+   return;
+  }
+ __vpi_terr(__FILE__, __LINE__);
+}
+
+/*
+ * convert a call back value to its name
+ */
+static char *to_cbtypnam(char *s, int32 reason)
+{
+ switch (reason) {
+  case cbValueChange: strcpy(s, "cbValueChange"); break;
+  case cbStmt: strcpy(s, "cbStmt"); break;
+  case cbForce: strcpy(s, "cbForce"); break;
+  case cbRelease: strcpy(s, "cbRelease"); break;
+  case cbAtStartOfSimTime: strcpy(s, "cbAtStartOfSimTime"); break;
+  case cbReadWriteSynch: strcpy(s, "cbReadWriteSynch"); break;
+  case cbReadOnlySynch: strcpy(s, "cbReadOnlySynch"); break;
+  case cbNextSimTime: strcpy(s, "cbNextSimTime"); break;
+  case cbAfterDelay: strcpy(s, "cbAfterDelay"); break;
+  case cbEndOfCompile: strcpy(s, "cbEndOfCompile"); break;
+  case cbStartOfSimulation: strcpy(s, "cbStartOfSimulation"); break;
+  case cbEndOfSimulation: strcpy(s, "cbEndOfSimulation"); break;
+  case cbError: strcpy(s, "cbError"); break;
+  case cbTchkViolation: strcpy(s, "cbTchkViolation"); break;
+  case cbStartOfSave: strcpy(s, "cbStartOfSave"); break;
+  case cbEndOfSave: strcpy(s, "cbEndOfSave"); break;
+  case cbStartOfRestart: strcpy(s, "cbStartOfRestart"); break;
+  case cbEndOfRestart: strcpy(s, "cbEndOfRestart"); break;
+  case cbStartOfReset: strcpy(s, "cbStartOfReset"); break;
+  case cbEndOfReset: strcpy(s, "cbEndOfReset"); break;
+  case cbEnterInteractive: strcpy(s, "cbEnterInteractive"); break;
+  case cbExitInteractive: strcpy(s, "cbExitInteractive"); break;
+  case cbInteractiveScopeChange: strcpy(s, "cbInteractiveScopeChange"); break;
+  case cbUnresolvedSystf: strcpy(s, "cbUnresolvedSystf"); break;
+  default: strcpy(s, "**none**");
+ }
+ return(s);
+}
+
+/*
+ * get information about a call back
+ *
+ * LOOKATME - standard should return ptr not copy - copy guts for now
+ */
+extern void vpi_get_cb_info(vpiHandle object, p_cb_data cb_data_p)
+{  
+ struct h_t *hp;
+ struct hrec_t *hrp;
+ struct cbrec_t *cbp;
+
+ hp = (struct h_t *) object;
+ if (!__validate_handle("vpi_get_cb_info", hp)) return;
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiCallback)
+  {
+   __vpi_err(1825, vpiError,
+    "vpiget_cb_info requires vpiCallback object argument - %s illegal",
+    __to_vpionam(__wrks1, hrp->htyp));
+   return;
+  }
+ cbp = hrp->hu.hcbp;
+ cb_data_p->reason = cbp->cb_reason;
+ cb_data_p->cb_rtn = cbp->cb_rtn;
+ cb_data_p->obj = (vpiHandle) cbp->cb_hp; 
+ if (cb_data_p->time != NULL) cb_data_p->time->type = (int32) cbp->cb_rettimtyp;
+ if (cb_data_p->value != NULL)
+  cb_data_p->value->format = (int32) cbp->cb_retvalfmt;
+ cb_data_p->index = 0;
+ cb_data_p->user_data = cbp->cb_user_data;
+}
+
+/*
+ * ROUTINES FOR TRAVERSING OBJECTS
+ */
+
+/*
+ * get a 1-to-1 object handle given a reference handle and 1-to-1 access type
+ *
+ * for Cver only declarative structure and variables accessible and know
+ * handle will be of supported object type
+ * 
+ * ALGORITHM:  use destination property (or tag) as first level index
+ * then for each destination use reference handle (object) to
+ * as starting point for which to select the destination property from 
+ */
+extern vpiHandle vpi_handle(PLI_INT32 type, vpiHandle referenceHandle)
+{
+ register struct h_t *rhp;
+ register struct hrec_t *rhrp;
+ int32 sf_ind;
+ word32 sttyp, primtyp;
+ struct sy_t *syp;
+ struct st_t *stp;
+ struct expr_t *xp;
+ struct itree_t *itp;
+ struct net_t *np;
+
+ /* must reset at start of call to no error */
+ __last_eip = NULL;
+ if (__run_state == SS_COMP)
+  { __still_comp_err("vpi_handle"); return(NULL); } 
+ if (!__validate_accessm("vpi_handle", type, "1-to-1")) return(NULL);
+ rhp = (struct h_t *) referenceHandle;
+ /* handle must be nil can not validate */ 
+ if (type == vpiSysTfCall) return(get_cursystfcall(rhp));
+ if (!__validate_handle("vpi_handle", rhp)) return(NULL);
+ rhrp = rhp->hrec;
+
+ switch (type) { 
+  /* get an object of type module (itree instance) that contains handle */ 
+  case vpiModule:
+   return(get_inmod_itp(rhp));
+  case vpiIndex: return(get_obj_index(rhp));
+  case vpiLeftRange: return(get_obj_range(rhp, type));
+  case vpiRightRange: return(get_obj_range(rhp, type));
+  /* only selects have parents - vpiScope or vpiModule for containing scope */
+  case vpiParent: return(get_obj_parent(rhp));
+  case vpiRhs: return(get_obj_side(rhp, type));
+  case vpiLhs: return(get_obj_side(rhp, type));
+  case vpiLowConn:
+   /* port bit high conn is variable or var bit not expr */
+   if (rhrp->htyp == vpiPortBit) return(getbit_lowconn(rhp));
+   /* lowconn of port is module port expression */
+   if (rhrp->htyp == vpiPort) return(getexpr_lowconn(rhp));
+   goto bad_args;
+  case vpiHighConn:
+   /* port bit high conn is variable or var bit not expr */
+   if (rhrp->htyp == vpiPortBit) return(getbit_highconn(rhp));
+   /* highconn of port is expression */
+   if (rhrp->htyp == vpiPort) return(getexpr_highconn(rhp));
+   goto bad_args;
+  case vpiTask:
+   if (rhrp->htyp != vpiTaskCall) goto bad_args;
+   syp = rhrp->hu.hstp->st.stkc.tsksyx->lu.x->lu.sy;
+   /* this is task definition handle - tsk in not set */
+   /* know task def. at top level */
+   return(__mk_handle(vpiTask, (void *) syp->el.etskp, rhp->hin_itp, NULL));
+  case vpiFunction:
+   if (rhrp->htyp != vpiFuncCall) goto bad_args;
+   syp = rhrp->hu.hxp->lu.x->lu.sy;
+   return(__mk_handle(vpiFunction, (void *) syp->el.etskp, rhp->hin_itp, 
+    NULL));
+  case vpiUserSystf:
+   if (rhrp->htyp == vpiSysFuncCall)
+    {
+     syp = rhrp->hu.hxp->lu.x->lu.sy;  
+do_usersystf:
+     sf_ind = syp->el.esyftbp->syfnum;
+     if (sf_ind <= __last_veriusertf || sf_ind > __last_systf)
+      {
+       __vpi_err(1829, vpiError,
+        "%s (of %s) handle no vpiUserSystf handle - not registered vpi_",
+        __to_vpionam(__wrks1, rhp->hrec->htyp), syp->synam);
+       return(NULL);
+      }
+     return(__mk_handle(vpiUserSystf, (void *) sf_ind, NULL, NULL));
+    }
+   if (rhrp->htyp == vpiSysTaskCall)
+    {
+     syp = rhrp->hu.hstp->st.stkc.tsksyx->lu.x->lu.sy;
+     goto do_usersystf;
+    }
+   goto bad_args;
+  /* notifier returns reg handle, others tchk term */
+  case vpiTchkRefTerm: case vpiTchkDataTerm: case vpiTchkNotifier: 
+   return(get_tchk_term((word32) type, rhp));
+  case vpiTchk:
+   /* LOOKATME - LRM says no connection back from notifier */
+   if (rhrp->htyp != vpiTchkRefTerm && rhrp->htyp != vpiTchkDataTerm
+    && rhrp->htyp != vpiTchkNotifier) goto bad_args;
+   return(__mk_handle(vpiTchk, (void *) rhrp->hu.htcp, rhp->hin_itp, NULL));
+  case vpiModPath:
+   if (rhrp->htyp != vpiPathTerm) goto bad_args;
+   return(__mk_handle(vpiModPath, (void *) rhrp->hu.hpthp, rhp->hin_itp,
+    NULL));
+  case vpiPrimitive:
+   /* handle from primitive term to primitive it is part of */
+   if (rhrp->htyp != vpiPrimTerm) goto bad_args;
+   primtyp = __gate_to_vpiprimtyp(rhrp->hu.hgp);
+   return(__mk_handle(primtyp, (void *) rhrp->hu.hgp, rhp->hin_itp, NULL));
+  case vpiCondition: return(get_cond(rhp));
+  case vpiElseStmt:
+   if (rhrp->htyp != vpiIfElse) goto bad_args;
+   stp = rhrp->hu.hstp->st.sif.elsest;
+   if (stp->st_unbhead) sttyp = vpiBegin;
+   else sttyp = __to_vpi_stmttyp(&stp);
+   return(__mk_stmt_handle(sttyp, stp, rhp->hin_itp, rhrp->hin_tskp));
+  case vpiExpr:
+   return(bld_1to1_exprclass_handle(rhp));
+  case vpiNamedEvent:
+   if (rhrp->htyp != vpiEventStmt) goto bad_args;
+   stp = rhrp->hu.hstp;
+   xp = stp->st.scausx;
+   if (xp->optyp == GLBREF)
+    {
+     __push_itstk(rhp->hin_itp);
+     __xmrpush_refgrp_to_targ(xp->ru.grp);
+     itp = __inst_ptr;
+     __pop_itstk();
+     __pop_itstk();
+    }
+   else if (xp->optyp == ID) itp = rhp->hin_itp;
+   else { __vpi_terr(__FILE__, __LINE__); return(NULL); }
+   np = xp->lu.sy->el.enp;
+   return(__mk_handle(vpiNamedEvent, (void *) np, itp, rhrp->hin_tskp));
+  /* scope handle offrom disable statement */
+  case vpiScope: return(get_obj_scope(rhp));
+  case vpiStmt: return(get_contained_stmt(rhp));
+  case vpiDelayControl: case vpiRepeatControl:
+   return(get_dctrl_stmt(rhp, type));
+  case vpiEventControl:
+   /* repeat dctrl form does not have contained stmt only contained ev ctrl */
+   if (rhrp->htyp == vpiRepeatControl)
+    {
+     /* actual h_u object is the S DELCTRL - only difference between */
+     /* repeat ev cntrl and normal ev cntrl is type */
+     return(__mk_handle(vpiEventControl, (void *) rhrp->hu.hstp, rhp->hin_itp,
+      rhrp->hin_tskp));
+    }
+   return(get_dctrl_stmt(rhp, type));
+  case vpiForInitStmt:  
+   if (rhrp->htyp != vpiFor) goto bad_args;
+   stp = rhrp->hu.hstp->st.sfor->forassgn;
+   /* this must really return for init part (special prefix now to for) */
+   /* so cannot call to vpi stmttyp */
+   /* DBG remove -- */
+   if (stp->stmttyp != S_FORASSGN) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   return(__mk_handle(vpiAssignment, (void *) stp, rhp->hin_itp,
+    rhrp->hin_tskp));
+  case vpiForIncStmt:
+   if (rhrp->htyp != vpiFor) goto bad_args;
+   stp = rhrp->hu.hstp->st.sfor->forinc;
+   sttyp = __to_vpi_stmttyp(&stp);
+   return(__mk_stmt_handle(sttyp, stp, rhp->hin_itp, rhrp->hin_tskp));
+  case vpiUdpDefn:
+   return(get_udpdef_from_inobj(rhp));
+  case vpiInitial:
+   /* udp initial statement - containing is udp define */
+   if (rhrp->htyp != vpiUdpDefn) goto bad_args;
+   return(get_contained_udp_init(rhp));
+  case vpiPoundParam:
+   return(get_up_poundparam_expr(rhp));
+  default:
+bad_args:
+   __vpi_err(1827, vpiError,
+    "there is no 1-to-1 relationships of type %s from reference handle %s", 
+    __to_vpionam(__wrks1, (word32) type), __to_vpionam(__wrks2, rhrp->htyp));
+ }
+ return(NULL);
+}
+
+/*
+ * access handle for multi-dimensional array - mult dim arrays not supported
+ */
+extern vpiHandle vpi_handle_multi(PLI_INT32 type, vpiHandle refHandle1,
+ vpiHandle refHandle2, ...)
+{
+ __vpi_err(1801, vpiError, "vpi_handle_multi routine currently unsupported"); 
+ return(NULL);
+}
+
+/*
+ * make a statement handle
+ *
+ * handles name block (fj or begin) except where contents is task not stp
+ */
+extern vpiHandle __mk_stmt_handle(word32 sttyp, struct st_t *stp,
+ struct itree_t *itp, struct task_t *tskp)
+{
+ if (sttyp == vpiNamedBegin || sttyp == vpiNamedFork)
+  {
+   return(__mk_handle(sttyp, (void *) stp->st.snbtsk, itp, tskp));
+  }
+ return(__mk_handle(sttyp, (void *) stp, itp, tskp));
+} 
+
+/*
+ * get current user systf call handle that can be passed to get systf info
+ * 
+ * this must be sys tf call with itree and task loc. but LRM unclear
+ * this can only be called from inside called vpi sys task or func.
+ */
+static vpiHandle get_cursystfcall(struct h_t *hp)
+{
+ vpiHandle ihref;
+ struct task_t *tskp;
+
+ if (hp != NULL)
+  {
+   __vpi_err(1833, vpiError,
+    "vpi_handle with 1-to-1 vpiSysTfCall NULL handle required - %s illegal",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ /* DBG remove --- */  
+ if (__cur_sysf_expr == NULL && __cur_syst_stp == NULL)
+  {
+   __vpi_err(1840, vpiError,
+    "vpi_handle with vpiSysTfCall not called from inside vpi_ systf callback");
+   return(NULL);
+  }
+ /* --- */
+ /* DBG remove --- */
+ if (__cur_sysf_expr != NULL && __cur_syst_stp != NULL)
+  __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+ tskp = __getcur_scope_tsk();
+ if (__cur_sysf_expr != NULL)
+  ihref = __mk_handle(vpiSysFuncCall, (void *) __cur_sysf_expr, __inst_ptr,
+   tskp);
+ else ihref = __mk_handle(vpiSysTaskCall, (void *) __cur_syst_stp, __inst_ptr,
+  tskp);
+ return(ihref);
+}
+
+/*
+ * for object in module, get enclosing module (actually itree inst)
+ *
+ * non declarative object types will never be handle types
+ */
+static vpiHandle get_inmod_itp(struct h_t *hp)
+{
+ struct itree_t *itp;
+
+ switch (hp->hrec->htyp) {
+  case vpiModule:
+   if ((itp = hp->hin_itp->up_it) == NULL) return(NULL);  
+   return(__mk_handle(vpiModule, (void *) itp->itip->imsym->el.emdp, itp,
+    NULL));
+   /* even if inner scope (in nested named blocks?), still itree inst. */
+   /* scope is symbol table so top mod scope goes to itree inst (mod) */
+   /* SJM 11/13/00 - forgot vpiReg - now added and checked new LRM */ 
+  case vpiPort: case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+  case vpiRealVar: case vpiMemory: case vpiNamedEvent: case vpiContAssign:
+  case vpiGate: case vpiSwitch: case vpiUdp: case vpiModPath: case vpiTchk:
+  case vpiSpecParam: case vpiDefParam:
+  case vpiIODecl: case vpiParamArray:
+   break;
+  case vpiParameter: case vpiParamAssign:
+   break;
+
+  /* can get containing module (inst) for any of 4 scope objects */ 
+  case vpiTask: case vpiFunction: case vpiNamedBegin: case vpiNamedFork:
+   break;
+  case vpiInitial: case vpiAlways:
+   break;
+  default: no_1to1h_err(vpiModule, hp); return(NULL);
+ }
+ /* down handle will always have itree loc. */
+ return(__mk_handle(vpiModule, (void *) hp->hin_itp->itip->imsym->el.emdp,
+  hp->hin_itp, NULL));
+}
+
+/*
+ * build a handle from malloced array - user must handle freeing
+ * this should probably be macro
+ */
+extern vpiHandle __mk_handle(word32 typ, void *h_unp, struct itree_t *itp,
+ struct task_t *tskp) 
+{
+ register int32 hi;
+ register struct h_t *hp, *hparr;
+ register struct hrec_t *hrp, *hrarr;
+
+ /* if free list empty - add a few thousand */
+ /* separate malloc calls waste 16 bytes per call for small record */
+ if (__vpi_hfree_hdr == NULL)
+  {
+   hparr = (struct h_t *) __my_malloc(VPI_OBJALLOCNUM*sizeof(struct h_t));
+   for (hi = 0; hi < VPI_OBJALLOCNUM - 1; hi++)
+    {
+     hparr[hi].hin_itp = (struct itree_t *) &(hparr[hi + 1]); 
+    }
+   hparr[VPI_OBJALLOCNUM - 1].hin_itp = NULL;
+   __vpi_hfree_hdr = &(hparr[0]);
+  }
+ if (__vpi_hrecfree_hdr == NULL)
+  {
+   hrarr = (struct hrec_t *)
+    __my_malloc(VPI_OBJALLOCNUM*sizeof(struct hrec_t));
+   for (hi = 0; hi < VPI_OBJALLOCNUM - 1; hi++)
+    {
+     hrarr[hi].hu.hfreenxt = &(hrarr[hi + 1]); 
+    }
+   hrarr[VPI_OBJALLOCNUM - 1].hu.hfreenxt = NULL;
+   __vpi_hrecfree_hdr = &(hrarr[0]);
+  }
+
+ /* know at least one always on each free list by here */
+ hrp = __vpi_hrecfree_hdr;
+ __vpi_hrecfree_hdr = hrp->hu.hfreenxt;
+
+ hp = __vpi_hfree_hdr;
+ __vpi_hfree_hdr = (struct h_t *) hp->hin_itp;
+
+ __init_hrec(hrp);
+ hrp->htyp = typ;
+ hrp->hu.hanyp = h_unp;
+ hrp->hin_tskp = tskp;
+
+ hp->hin_itp = itp;
+ hp->hrec = hrp;
+
+ return((vpiHandle) hp);
+}
+
+/*
+ * initialize a cver internal handle - zeroing handle turns off bits
+ *
+ * BEWARE - because zeroing must always define set bits to init to F (0)
+ */
+extern void __init_hrec(struct hrec_t *hrp)
+{
+ memset(hrp, 0, sizeof(struct hrec_t));
+ hrp->h_magic = PVH_MAGIC;
+ hrp->hi = -1;
+}
+
+/*
+ * build an index expression handle for an object 
+ *
+ * this always blds vpiConst expr. handle - i.e. evaluates expression 
+ *
+ * for bith ndx forms (from per bit iterator) must convert to const and norm
+ */
+static vpiHandle get_obj_index(struct h_t *hp)
+{
+ register word32 av;
+ register struct hrec_t *hrp;
+ vpiHandle ihref;
+ struct h_t *rhp;
+
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiMemoryWord: case vpiNetBit: case vpiRegBit: case vpiVarSelect:
+  case vpiParamArrayWord:
+   /* case 1, alternate form for expr. handle is fixed index */
+   if (hrp->bith_ndx)
+    {
+     /* index hi is fixed index - know in range */
+     av = (word32) __unnormalize_ndx(hrp->hu.hnp, hrp->hi);
+     /* this is expr. separate from bsel so must be unnormalized value */
+     /* because not connected to bsel constant can be unnormalized */
+bld_const_obj:
+     ihref = __mk_handle(vpiConstant, NULL, hp->hin_itp, hrp->hin_tskp);
+     rhp = (struct h_t *) ihref;
+     rhp->hrec->hu.hxp = __bld_rng_numxpr(av, 0L, WBITS);
+     rhp->hrec->free_xpr = TRUE;
+     break;
+    }
+   /* expr form case */
+   /* DBG remove --- */
+   if (hrp->hu.hxp->optyp != LSB) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   ihref = __mk_exprclass_handle(hrp->hu.hxp->ru.x, hp->hin_itp,
+    hrp->hin_tskp);
+   break;
+  case vpiPortBit:
+   /* no ned to normalize since port bits virtual range always h:0 */
+   av = (word32) hrp->hi;
+   goto bld_const_obj;
+  default: no_1to1h_err(vpiIndex, hp); return(NULL);
+ }
+ return(ihref);
+}
+
+/*
+ * build an index expression handle for an object 
+ */
+static vpiHandle get_obj_range(struct h_t *hp, int32 lrtyp)
+{
+ register struct hrec_t *hrp;
+ int32 r1, r2, wid;
+ vpiHandle ihref;
+ word32 rngv;
+ struct h_t *rhp;
+ struct expr_t *xp;
+ struct task_t *tskp;
+ struct net_t *np;
+
+ rngv = 0;
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiNet: case vpiReg:
+   if (!hrp->hu.hnp->n_isavec) return(NULL);
+   goto get_rng;
+  case vpiIntegerVar: case vpiTimeVar:
+get_rng:
+   __getwir_range(hrp->hu.hnp, &r1, &r2);
+   if (lrtyp == vpiLeftRange) rngv = (word32) r1; else rngv = (word32) r2;
+set_val:
+   ihref = __mk_handle(vpiConstant, NULL, hp->hin_itp, hrp->hin_tskp);
+   rhp = (struct h_t *) ihref;
+   rhp->hrec->hu.hxp = __bld_rng_numxpr(rngv, 0L, WBITS);
+   rhp->hrec->free_xpr = TRUE;
+   break;
+  case vpiMemoryWord: case vpiParamArrayWord:
+   if (hrp->bith_ndx) np = hrp->hu.hnp;
+   else
+    {
+     xp = hrp->hu.hxp; 
+     /* DBG remove -- */
+     if (xp->optyp != LSB) __vpi_terr(__FILE__, __LINE__);
+     /* --- */
+     np = xp->lu.x->lu.sy->el.enp; 
+    }
+   if (!np->n_isavec || np->ntyp == N_REAL) return(NULL);
+   __getwir_range(np, &r1, &r2);
+   if (lrtyp == vpiLeftRange) rngv = (word32) r1; else rngv = (word32) r2;
+   goto set_val;
+  case vpiFunction:
+   /* this if function declaration - only reg ret. funcs have range */
+   tskp = hrp->hu.htskp;
+   np = tskp->tskpins->tpsy->el.enp;
+   if (!np->n_isavec) return(NULL);
+   __getwir_range(np, &r1, &r2);
+   if (lrtyp == vpiLeftRange) rngv = (word32) r1; else rngv = (word32) r2;
+   goto set_val;
+  case vpiMemory: case vpiParamArray:
+   __getarr_range(hrp->hu.hnp, &r1, &r2, &wid);
+   if (lrtyp == vpiLeftRange) rngv = (word32) r1; else rngv = (word32) r2;
+   goto set_val;
+  /* expr that is part select has ranges */
+  case vpiPartSelect:
+   xp = hrp->hu.hxp;
+   /* know range can never be x or will not get here */
+
+   if (lrtyp == vpiLeftRange) rngv = __contab[xp->ru.x->lu.x->ru.xvi];
+   else rngv = __contab[xp->ru.x->ru.x->ru.xvi];
+   goto set_val;
+  case vpiIODecl:
+   if (hrp->htyp2 == vpiUdpDefn)
+    {
+     /* udp io decls always scalars so no ranges */
+     return(NULL);
+    } 
+   np = hrp->hu.hnp; 
+   if (!np->n_isavec) return(NULL);
+   goto get_rng;
+  default:
+   no_1to1h_err(lrtyp, hp);
+   return(NULL);
+ }
+ return(ihref);
+}
+
+/*
+ * get parent (containing) handle for bit of object
+ *
+ * also gets object part select is select of
+ * here for non index form of these must map to itree loc of variable
+ * also know never see bith index form for xmr
+ *
+ * tricky because for index handles must map to dest. for xmrs
+ */
+static vpiHandle get_obj_parent(struct h_t *hp)
+{
+ register struct hrec_t *hrp;
+ word32 hotyp;
+ vpiHandle ihref;
+ struct expr_t *idndp;
+ struct net_t *np;
+ struct itree_t *nitp;
+ struct task_t *ntskp;
+ struct h_t *hp2;
+
+ ihref = NULL;
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiMemoryWord:
+   if (hrp->bith_ndx)
+    {
+     ihref = __mk_handle(vpiMemory, (void *) hrp->hu.hnp, hp->hin_itp,
+      hrp->hin_tskp);
+     break;
+    }
+   hotyp = vpiMemory; 
+bld_par_handle:
+   idndp = hrp->hu.hxp->lu.x; 
+   /* expr. form - for xmr must map to right itree and task loc. */
+   exprobj_to_itreeloc(&nitp, &ntskp, idndp, hp->hin_itp, hrp->hin_tskp);
+   ihref = __mk_handle(hotyp, (void *) idndp->lu.sy->el.enp, nitp, ntskp);
+   break;
+  case vpiParamArrayWord:
+   if (hrp->bith_ndx)
+    {
+     ihref = __mk_handle(vpiParamArray, (void *) hrp->hu.hnp, hp->hin_itp,
+      hrp->hin_tskp);
+     break;
+    }
+   hotyp = vpiParamArray; 
+   goto bld_par_handle;
+  case vpiNetBit:
+   if (hrp->bith_ndx)
+    {
+     ihref = __mk_handle(vpiNet, (void *) hrp->hu.hnp, hp->hin_itp,
+      hrp->hin_tskp);
+     break;
+    }
+   hotyp = vpiNet;
+   goto bld_par_handle;
+  case vpiRegBit: case vpiVarSelect:
+   if (hrp->bith_ndx)
+    {
+     hotyp = __ntyp_to_vpivarhtyp(hrp->hu.hnp);
+     ihref = __mk_handle(hotyp, (void *) hrp->hu.hnp, hp->hin_itp,
+      hrp->hin_tskp);
+     break;
+    }
+   hotyp = __ntyp_to_vpivarhtyp(hrp->hu.hxp->lu.x->lu.sy->el.enp);
+   goto bld_par_handle;
+  case vpiPortBit:
+   /* know in_tskp will be nil */
+   ihref = __mk_handle(vpiPort, (void *) hrp->hu.hpi, hp->hin_itp,
+    hrp->hin_tskp);
+   break;
+  case vpiPartSelect:
+   np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+   hotyp = __ntyp_to_vpivarhtyp(np);
+   goto bld_par_handle; 
+  case vpiNetDriver:
+   np = hrp->hu.hnpp->elnpp.enp;  
+   ihref = __mk_handle(vpiNet, (void *) np, hp->hin_itp, hrp->hin_tskp); 
+   break;
+  case vpiPrimTerm:
+   /* parent of primitive (gate) terminal is primitive */
+   hotyp = __gate_to_vpiprimtyp(hrp->hu.hgp);
+   ihref = __mk_handle(hotyp, (void *) hrp->hu.hgp, hp->hin_itp, NULL);
+   break;
+  case vpiNetBitDriver:
+   np = hrp->hu.hnpp->elnpp.enp;
+   ihref = __mk_handle(vpiNetBit, (void *) np, hp->hin_itp, hrp->hin_tskp); 
+   hp2 = (struct h_t *) ihref; 
+   /* DBG remove --- */
+   if (hrp->hu.hnpp->npaux == NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   /* need internal h:0 bit form here */
+   hp2->hrec->hi = hrp->hu.hnpp->npaux->nbi1;
+   break;
+  case vpiAttribute:
+   return(__get_digattr_parent(hp));
+   
+  default: no_1to1h_err(vpiParent, hp); return(NULL);
+ }
+ return(ihref);
+}
+
+/*
+ * get expr. handle variable itree and task location
+ *
+ * for selects passed the left variable expr. node
+ */
+static void exprobj_to_itreeloc(struct itree_t **itpp, struct task_t **tskpp, 
+ struct expr_t *idndp, struct itree_t *itp, struct task_t *tskp)
+{
+ struct mod_t *mdp;
+ struct gref_t *grp;
+
+ mdp = itp->itip->imsym->el.emdp;
+ if (idndp->optyp == ID) 
+  {
+   if (idndp->locqualnam)
+    *tskpp = __find_qualnam_task(idndp->ru.qnchp, mdp, tskp);
+   else *tskpp = tskp;
+   *itpp = itp;
+  }
+ else if (idndp->optyp == GLBREF)
+  {
+   grp = idndp->ru.grp;
+   __push_itstk(itp);
+   __xmrpush_refgrp_to_targ(grp);
+   itp = __inst_ptr;
+   __pop_itstk();
+   __pop_itstk();
+   tskp = grp->targtskp;
+  }
+ else __vpi_terr(__FILE__, __LINE__);
+}
+
+/*
+ * get all 1-to-1 relationships that are on a vpi_ rhs or lhs
+ */
+static vpiHandle get_obj_side(struct h_t *rhp, int32 type)
+{
+ register struct hrec_t *rhrp;
+ int32 hotyp;
+ vpiHandle ihref;
+ struct expr_t *xp;
+ struct st_t *stp;
+ struct task_t *tskp;
+ struct dfparam_t *dfpp;
+ struct itree_t *itp;
+ struct net_t *np;
+
+ tskp = NULL;
+ rhrp = rhp->hrec;
+ switch (rhrp->htyp) { 
+  case vpiContAssign:
+   if (rhrp->htyp2 == vpiGate)
+    {
+     if (type == vpiRhs) xp = rhrp->hu.hgp->gpins[1]; 
+     else xp = rhrp->hu.hgp->gpins[0];
+    }
+   else
+    {
+     if (type == vpiRhs) xp = rhrp->hu.hcap->rhsx; 
+     else xp = rhrp->hu.hcap->lhsx;
+    }
+   break;
+  case vpiAssignment:
+   stp = rhrp->hu.hstp;
+   /* rhs delay or event control has RHS del/evnt control as stmt */
+   if (stp->stmttyp == S_DELCTRL) stp = stp->st.sdc->actionst; 
+   if (type == vpiRhs) xp = stp->st.spra.rhsx; 
+   else xp = stp->st.spra.lhsx; 
+   tskp = rhrp->hin_tskp;
+   break;
+  /* qc assign or force - do not need to distinguish here */
+  case vpiAssignStmt: case vpiForce:
+   stp = rhrp->hu.hstp;
+   if (type == vpiRhs) xp = stp->st.sqca->qcrhsx; 
+   else xp = stp->st.sqca->qclhsx; 
+   tskp = rhrp->hin_tskp;
+   break;
+ case vpiDeassign: case vpiRelease:
+   stp = rhrp->hu.hstp;
+   if (type == vpiLhs) xp = stp->st.sqcdea.qcdalhs; 
+   else { no_1to1h_err(type, rhp); return(NULL); }
+   tskp = rhrp->hin_tskp;
+   break;
+  case vpiDefParam:
+   dfpp = rhrp->hu.hdfp;
+   /* already converted to rooted in exactly one itree */ 
+   if (type == vpiLhs) 
+    {
+     /* left hand side is parameter (i.e. net) and can be task param */
+     np = dfpp->targsyp->el.enp;   
+     /* SJM - 05/26/05 - must search for bottom - splitting changes */
+     itp = __find_dfpbot_itp(dfpp);
+     ihref = __mk_handle(vpiParameter, (void *) np, itp, dfpp->dfptskp);
+     return(ihref);  
+    }
+   /* SJM 01/27/04 - this no longer needs to be const for dependent dfps */ 
+   xp = dfpp->dfpxrhs;
+   /* rhs is constant that must appear in source at module level */
+   break;
+  case vpiParamAssign:
+   /* because know assign (decl.) address - rally same as vpi param object */
+   np = rhrp->hu.hnp;
+   if (type == vpiLhs)
+    {
+     if (np->n_isarr) hotyp = vpiParamArray; else hotyp = vpiParameter;
+     /* i.e. same thing except type different */
+     ihref = __mk_handle(hotyp, (void *) np, rhp->hin_itp, rhrp->hin_tskp);
+     return(ihref);
+    }
+   /* rhs is param expr. - to get value need to get value of lhs */
+   /* DBG remove -- */
+   if (np->nrngrep != NX_CT) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   if (np->nu.ct->parm_srep == SR_PXPR) xp = np->nu.ct->n_dels_u.d1x;
+   else if (np->nu.ct->parm_srep == SR_PISXPR)
+    {
+     /* d4x used but in fact allocated size is number of insts */
+     xp = np->nu.ct->n_dels_u.d4x[rhp->hin_itp->itinum];
+    }
+   else { __vpi_terr(__FILE__, __LINE__); return(NULL); }
+   ihref = __mk_exprclass_handle(xp, rhp->hin_itp, rhrp->hin_tskp);
+   return(ihref);
+  default: no_1to1h_err(type, rhp); return(NULL);
+ }
+ ihref = __mk_exprclass_handle(xp, rhp->hin_itp, tskp);
+ return(ihref);
+}
+
+/*
+ * build a scope (mod or task) parent handle (up one symbol table)
+ *
+ * for named blocks and name fork-join, hu field is statement for
+ * real tasks (task and function definitions hu field is tskp
+ * but in head case other handle information right
+ */
+static vpiHandle bld_scope_par(struct h_t *hp, struct task_t *tskp)
+{
+ word32 parhtyp;
+ vpiHandle ihref;
+ struct task_t *up_tskp;
+ struct symtab_t *sytp, *sytp2;
+
+ sytp = tskp->tsksymtab;
+ if ((sytp2 = sytp->sytpar) == NULL) __vpi_terr(__FILE__, __LINE__);
+ if (sytp2->sypofsyt->sytyp == SYM_M)
+  {
+   ihref = __mk_handle(vpiModule, (void *) sytp->sytpar->sypofsyt->el.emdp,
+    hp->hin_itp, tskp);
+   return(ihref); 
+  }
+ if (sytp2->sytpar == NULL || sytp2->sytpar->sypofsyt->sytyp == SYM_M)
+  up_tskp = NULL;
+ else up_tskp = sytp2->sytpar->sypofsyt->el.etskp;
+
+ parhtyp = __to_vpi_tasktyp(tskp->tsktyp);
+ ihref = __mk_handle(parhtyp, (void *) sytp2->sypofsyt->el.etskp,
+  hp->hin_itp, up_tskp);
+ return(ihref);
+}      
+
+/*
+ * convert from v.h task type to handle constant
+ */
+extern word32 __to_vpi_tasktyp(word32 tsktyp)
+{
+ switch (tsktyp) {
+  case TASK: return(vpiTask);
+  case FUNCTION: return(vpiFunction);
+  case Begin: return(vpiNamedBegin);
+  case FORK: return(vpiNamedFork);
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(0);
+}
+
+/*
+ * build an net/reg bit handle from a port for the low connection (mod port)
+ *
+ * this build a reg/net bit (or reg/net if scalar) handle from expression
+ * use with vpiPort to get entire expression (then can convert if needed) 
+ * this is easy case because no xmrs or qualified names
+ *
+ * hp is port bit handle that must be lvalue
+ *
+ * here unc. impossible because connections determine width
+ */
+static vpiHandle getbit_lowconn(struct h_t *hp)
+{
+ int32 ndx, new_ndx;
+ word32 hotyp;
+ vpiHandle href;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+ struct expr_t *xp, *idndp;
+ struct net_t *np;
+ struct h_t *hp2;
+ struct hrec_t *hrp;
+
+ href = NULL;
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ hrp = hp->hrec;
+ mpp = &(mdp->mpins[hrp->hu.hpi]);
+ /* this is index of port bit - always h:0 */
+ ndx = hrp->hi;
+ xp = mpp->mpref;
+catcmp_again:
+ /* know this is lvalue expr - using cver expressions */
+ switch (xp->optyp) {
+  case ID:
+   idndp = xp;
+make_handle:
+   np = idndp->lu.sy->el.enp;
+   /* notice need special correction for Net (wire) vector as bit */
+   if (np->ntyp < NONWIRE_ST)
+    {
+     hotyp = (np->n_isavec) ? vpiNetBit : vpiNet;
+    }
+   /* reg cnnections never bits */
+   else
+    {
+     if (np->n_isavec) hotyp = __to_vpinetbithtyp(np->ntyp);
+     else hotyp = __ntyp_to_vpivarhtyp(np);
+    }
+   href = __mk_handle(hotyp, (void *) np, hp->hin_itp, NULL); 
+   hp2 = (struct h_t *) href;
+   /* for scalar will be -1 - ndx is internal h:0 that for ID is same bit */
+   hp2->hrec->hi = ndx;
+   if (hotyp == vpiNetBit || hotyp == vpiRegBit || hotyp == vpiVarSelect)
+    hp2->hrec->bith_ndx = TRUE;
+   break;
+  case LSB:
+   /* if constant, convert to bith_ndx form */ 
+   if (__expr_is_vpiconst(xp->ru.x))
+    {
+     idndp = xp->lu.x;
+     /* evaluate index since constant know will be non x but maybe IS form */
+     __push_itstk(hp->hin_itp);
+     ndx = __comp_ndx(idndp->lu.sy->el.enp, xp->ru.x);
+     __pop_itstk();
+     /* DBG remove --- */ 
+     if (ndx == -1) __vpi_terr(__FILE__, __LINE__);
+     /* --- */
+     goto make_handle;
+    }
+   else
+    {
+     /* variable case - this is variable bit or array select */
+     href = __mk_exprclass_handle(xp, hp->hin_itp, hrp->hin_tskp);
+    }
+   break;
+  case PARTSEL:
+   idndp = xp->lu.x;
+   /* because always constant - normalized */
+   ndx = __contab[xp->ru.x->ru.x->ru.xvi] + ndx;
+   goto make_handle;
+  case LCB:
+   xp = find_catxp_frombit(xp, ndx, &new_ndx);
+   ndx = new_ndx;
+   goto catcmp_again;
+  default: __vpi_terr(__FILE__, __LINE__);
+ }  
+ return(href);
+}
+
+/*
+ * build an expr handle from a port for the low connection (mod port)
+ */
+static vpiHandle getexpr_lowconn(struct h_t *hp)
+{
+ vpiHandle ihref;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+
+ if (hp->hrec->htyp != vpiPort)
+  { no1_1to1h_err(vpiLowConn, vpiPort, hp); return(NULL); }
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
+ ihref = __mk_exprclass_handle(mpp->mpref, hp->hin_itp, NULL);
+ return(ihref);
+}
+
+/*
+ * build an variable or var bit handle form vpi Port bit
+ *
+ * know handle is vpiPortBit
+ * for port bit, get iconn expr then take apart to component, then to 
+ * bit in expression, but if vpiOperation returns nil since no handle 
+ *
+ * this is hard case because converting up iconn expr to net/bit handle
+ * and can be xmr or in module qualified name
+ *
+ * same as acc_, only variables, bit and port selects or concatenates thereof
+ * are legal (not bits of constants, for example)
+ *
+ * hp is vpi port bit
+ */
+static vpiHandle getbit_highconn(struct h_t *hp)
+{
+ int32 ndx, new_ndx;
+ word32 xtyp, otyp, hotyp;
+ vpiHandle href;
+ struct inst_t *ip;
+ struct itree_t *up_itp, *itp;
+ struct net_t *np;
+ struct expr_t *xp, *idndp;
+ struct task_t *tskp;
+ struct h_t *hp2;
+ struct hrec_t *hrp;
+ struct gref_t *grp;
+ struct mod_t *mdp;
+
+ href = NULL;
+ hrp = hp->hrec;
+ ip = hp->hin_itp->itip;
+ mdp = ip->imsym->el.emdp;
+ /* no highconn for ports of top level module */
+ if ((up_itp = hp->hin_itp->up_it) == NULL) return(NULL);
+ ndx = hrp->hi; 
+ xp = ip->ipins[hrp->hu.hpi];
+new_expr:
+ /* possibly unconnected */  
+ if (ndx >= xp->szu.xclen)
+ /* possibly unconnected */  
+ /* SJM 08/24/99 - silently return nil if unc. - only way to tell if */
+ /* unc - no warning because otherwise no way to tell unc. */
+ if (ndx >= xp->szu.xclen) return(NULL);
+
+ xtyp = (word32) __exprtype_get(xp);
+ if (xtyp == vpiOperation)
+  {
+   /* know concatenates reduced to one level always */
+   if ((otyp = (word32) __expr_optype_get(xp)) == vpiConcatOp) 
+    {
+     xp = find_catxp_frombit(xp, ndx, &new_ndx);
+     ndx = new_ndx;
+     goto new_expr;
+    }
+   __to_vpiopnam(__wrks2, (int32) otyp);
+no_iconnbit:
+   /* xtyp is an object */
+   __vpi_err(2014, vpiWarning,
+    "vpi_handle: no vpiHighConn of vpiPortBit for %s expression type %s",
+    __to_vpionam(__wrks1, xtyp), __wrks2);
+   return(NULL);
+  }  
+ if (xtyp == vpiConstant || xtyp == vpiSysFuncCall || xtyp == vpiFuncCall)
+  {
+   strcpy(__wrks2, "*none*");
+   goto no_iconnbit;
+  }
+
+ switch (xp->optyp) {
+  case ID:
+   /* if vector, will be bit handle if scalar will be net/reg handle only */
+   idndp = xp;
+make_var:
+   if (idndp->locqualnam)
+    tskp = __find_qualnam_task(idndp->ru.qnchp, mdp, hrp->hin_tskp);
+   else tskp = NULL;
+   itp = up_itp;
+bld_handle:
+   /* this always builds either variable or variable bit */
+   np = idndp->lu.sy->el.enp;
+   /* notice need special correction for Net (wire) vector as bit */
+   if (np->ntyp < NONWIRE_ST)
+    {
+     hotyp = (np->n_isavec) ? vpiNetBit : vpiNet;
+    }
+   else
+    {
+     if (np->n_isavec) hotyp = __to_vpinetbithtyp(np->ntyp);
+     else hotyp = __ntyp_to_vpivarhtyp(np);
+    }
+   href = __mk_handle(hotyp, (void *) np, itp, tskp); 
+   hp2 = (struct h_t *) href;
+   /* for scalar will be 0 */
+   hp2->hrec->hi = ndx;
+   hp2->hrec->bith_ndx = TRUE;
+   break;
+  case GLBREF:
+   idndp = xp;
+make_grp_var:
+   grp = idndp->ru.grp;
+   __push_itstk(up_itp);
+   __xmrpush_refgrp_to_targ(grp);
+   itp = __inst_ptr;
+   __pop_itstk();
+   __pop_itstk();
+   tskp = grp->targtskp;
+   goto bld_handle;
+  case LSB:
+   /* here handle becomes index of bit select */
+   idndp = xp->lu.x;
+   /* no way in vpi_ routines to represent array bit (undivisable) */ 
+   if (idndp->lu.sy->el.enp->n_isarr)
+    {
+     __vpi_err(2026, vpiWarning,
+      "vpi_handle: no vpiHighConn of vpiPortBit for array %s",
+      idndp->lu.sy->el.enp->nsym->synam);
+     return(NULL);
+    }
+   /* also if var select, no highconn because no fixed bit */  
+   if (xp->ru.x->optyp != NUMBER && xp->ru.x->optyp != ISNUMBER)
+    { strcpy(__wrks2, "variable vpiVarSelect"); goto no_iconnbit; }
+
+   /* rule for bit conn, is that it must be constant bit select */ 
+   /* or error before here - but routine must return vpiNetbit */
+   /* need to evaluate for constant since may be IS form */
+   if (__expr_is_vpiconst(xp->ru.x))
+    {
+     __push_itstk(up_itp);
+     /* evaluate index since constant know will be non x */
+     ndx = __comp_ndx(idndp->lu.sy->el.enp, xp->ru.x);
+     if (ndx == -1) 
+      { strcpy(__wrks2, "x/z vpiVarSelect"); goto no_iconnbit; }
+     __pop_itstk();  
+     if (idndp->optyp == GLBREF) goto make_grp_var;
+     goto make_var;
+    }
+   else
+    {
+     /* variable case - this is variable bit or array select */
+     /* up xmr to task if present will be in XMR ref - se just need up */
+     href = __mk_exprclass_handle(xp, up_itp, NULL);
+    }
+   break;
+  case PARTSEL:
+   /* this becomes vpiNetBit or vpiRegBit with index correct for part sel */
+   idndp = xp->lu.x;
+   ndx = __contab[xp->ru.x->ru.x->ru.xvi] + ndx;
+   if (idndp->optyp == GLBREF) goto make_grp_var;
+   goto make_var;
+  default: __vpi_terr(__FILE__, __LINE__);
+ }  
+ return(href);
+}
+
+/*
+ * given a concatenate and a bit index, return the concat component expr
+ *
+ * this works on Cver expr_t not handles
+ * know in range
+ */
+static struct expr_t *find_catxp_frombit(struct expr_t *catxp, int32 bi,
+ int32 *newbi)
+{
+ register struct expr_t *xp;
+ register int32 catbi;
+ 
+ xp = catxp->ru.x;
+ for (catbi = catxp->szu.xclen; xp != NULL; xp = xp->ru.x)
+  {
+   catbi -= xp->lu.x->szu.xclen;
+   if (bi >= catbi) { *newbi = bi - catbi; return(xp->lu.x); }
+  }
+ __vpi_terr(__FILE__, __LINE__);
+ return(NULL);
+}
+
+/*
+ * find loal qualified name task
+ *
+ * because this can only be local qualified (named blocks) name - instance
+ * selects impossible
+ *
+ * never need to store except for vpi since have right symbol
+ * but for vpi need to know task in
+ */
+extern struct task_t *__find_qualnam_task(char *qualnam, struct mod_t *mdp,
+ struct task_t *reftskp)
+{
+ register struct expr_t *gcmp_ndp;
+ struct sy_t *syp;
+ struct expr_t *qn_ndp;
+ struct symtab_t *sytp;
+
+ /* know will have at least 2 components including ending variable */
+ /* this can never fail because processing already check qualified name */
+ if ((qn_ndp = __glbnam_to_expr(qualnam)) == NULL)
+  __vpi_terr(__FILE__, __LINE__);
+ /* handle already in some task - work upward */
+ gcmp_ndp = qn_ndp->ru.x;
+ /* DBG remove --- */ 
+ if (gcmp_ndp->lu.x->optyp != XMRID) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ if (reftskp != NULL) 
+  {
+   for (sytp = reftskp->tsksymtab;;) 
+    {
+     if ((syp = __get_sym(gcmp_ndp->lu.x->ru.qnchp, sytp)) != NULL) 
+      {
+       if (!__is_scope_sym(syp)) __vpi_terr(__FILE__, __LINE__);
+       if (syp->sytyp == SYM_M) sytp = syp->el.emdp->msymtab;
+       else sytp = syp->el.etskp->tsksymtab;
+       gcmp_ndp = gcmp_ndp->ru.x;
+       break;
+      }
+     if ((sytp = sytp->sytpar) == NULL) __vpi_terr(__FILE__, __LINE__);
+    }
+  }
+ else { sytp = mdp->msymtab;; }
+ /* have start of path symbol table - need to stop 1 from tail end */
+ /* DBG remove --- */ 
+ if (gcmp_ndp == NULL) __vpi_terr(__FILE__, __LINE__);
+ /* -- */ 
+ /* know at least one more component by here */
+ for (;;)
+  {
+   /* DBG remove ---*/
+   if (gcmp_ndp->lu.x->optyp != XMRID) __vpi_terr(__FILE__, __LINE__);
+   /* ---*/
+   if ((syp = __get_sym(gcmp_ndp->lu.x->ru.qnchp, sytp)) == NULL
+    || !__is_scope_sym(syp)) __vpi_terr(__FILE__, __LINE__);
+   sytp = syp->el.etskp->tsksymtab;
+   if ((gcmp_ndp = gcmp_ndp->ru.x) == NULL) break; 
+   /* if next is tail wire, also done */
+   if (gcmp_ndp->ru.x == NULL) break;
+  }
+ __free_xtree(qn_ndp); 
+ return(sytp->sypofsyt->el.etskp);
+}
+
+/*
+ * build an expr handle from a port for the high connection (iconn)
+ */
+static vpiHandle getexpr_highconn(struct h_t *hp)
+{
+ vpiHandle ihref;
+ struct inst_t *ip;
+ struct itree_t *up_itp;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiPort && hrp->htyp != vpiPortBit)
+  { no1_1to1h_err(vpiHighConn, vpiPort, hp); return(NULL); }
+ ip = hp->hin_itp->itip;
+ if ((up_itp = hp->hin_itp->up_it) == NULL) return(NULL);
+ /* for port, high conn is iconn expression */
+ ihref = __mk_exprclass_handle(ip->ipins[hrp->hu.hpi], up_itp, NULL);
+ return(ihref);
+}
+
+/*
+ * no 1-to-1 connection error with 1 expected handle
+ */
+static void no1_1to1h_err(word32 typ1to1, word32 exptyp, struct h_t *hp)
+{
+ char s1[RECLEN];
+
+ __vpi_err(1887, vpiError,
+  "vpi_handle: handle %s (expected %s) does not have a 1-to-1 connection for type %s", 
+  __to_vpionam(__wrks2, hp->hrec->htyp), __to_vpionam(s1, exptyp),
+  __to_vpionam(__wrks1, typ1to1));
+}
+
+/*
+ * no 1-to-1 connection error with no one expected handle type
+ */
+static void no_1to1h_err(int32 typ1to1, struct h_t *hp)
+{
+ __vpi_err(1887, vpiError,
+  "vpi_handle: handle %s does not have a 1-to-1 connection for type %s", 
+  __to_vpionam(__wrks2, hp->hrec->htyp), __to_vpionam(__wrks1,
+  (word32) typ1to1));
+}
+
+/*
+ * build an tchk term handle from a tchk - 2 different no iterator 
+ */
+static vpiHandle get_tchk_term(word32 termtyp, struct h_t *hp)
+{
+ vpiHandle ihref;
+ struct tchk_t *tcp;
+ struct h_t *hp2; 
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiTchk)
+  { no1_1to1h_err(termtyp, vpiTchk, hp); return(NULL); }
+ tcp = hrp->hu.htcp;
+ if (termtyp == vpiTchkNotifier)
+  {
+   if (tcp->ntfy_np == NULL) return(NULL);
+   ihref = __mk_handle(vpiReg, (void *) tcp->ntfy_np, hp->hin_itp, NULL);
+  }
+ else
+  {
+   ihref = __mk_handle(vpiTchkTerm, (void *) tcp, hp->hin_itp, NULL);
+   hp2 = (struct h_t *) ihref;
+   /* term type determines since each terminal of tchk different */
+   hp2->hrec->htyp2 = (word32) termtyp;
+  }
+ return(ihref);
+}
+
+/*
+ * get condition 1-to-1 handle from hp
+ */
+static vpiHandle get_cond(struct h_t *hp)
+{
+ register struct hrec_t *hrp;
+ vpiHandle ihref;
+ struct tchk_t *tcp;
+ struct spcpth_t *pthp;
+ struct delctrl_t *dctp;
+ struct expr_t *xp;
+
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiTchkTerm:
+   tcp = hrp->hu.htcp;
+   if (hrp->htyp2 == vpiTchkRefTerm)
+    {
+     if (tcp->startcondx == NULL) return(NULL);
+     ihref = __mk_exprclass_handle(tcp->startcondx, hp->hin_itp, NULL);
+    }
+   else if (hrp->htyp2 == vpiTchkDataTerm)
+    {
+     if (tcp->chkcondx == NULL) return(NULL);
+     ihref = __mk_exprclass_handle(tcp->chkcondx, hp->hin_itp, NULL);
+    }
+   else { __vpi_terr(__FILE__, __LINE__); return(NULL); }
+   break;
+  case vpiModPath:
+   pthp = hrp->hu.hpthp;
+   if (pthp->pthcondx == NULL) return(NULL);
+   ihref = __mk_exprclass_handle(pthp->pthcondx, hp->hin_itp, NULL);
+   break;
+  /* conditon is if conditon */
+  case vpiIf: case vpiIfElse:
+   ihref = __mk_exprclass_handle(hrp->hu.hstp->st.sif.condx,
+    hp->hin_itp, hrp->hin_tskp);
+   break;
+  case vpiCase:
+   ihref = __mk_exprclass_handle(hrp->hu.hstp->st.scs.csx,
+    hp->hin_itp, hrp->hin_tskp);
+   break;
+  /* notice to get condition for rhs proca event control first */
+  /* use stmt handle of event control then handle of event control stmt */
+  /* this is expression that is special - but checking already done */
+  case vpiEventControl:
+   dctp = hrp->hu.hstp->st.sdc;
+   /* DBG remove --- */
+   if (dctp->dc_delrep != DT_1X) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   xp = dctp->dc_du.d1x;  
+   ihref = __mk_exprclass_handle(xp, hp->hin_itp, hrp->hin_tskp);
+   break;
+  case vpiWhile:
+   ihref = __mk_exprclass_handle(hrp->hu.hstp->st.swh.lpx, hp->hin_itp,
+    hrp->hin_tskp);
+   break;
+  case vpiRepeat:
+   ihref = __mk_exprclass_handle(hrp->hu.hstp->st.srpt.repx, hp->hin_itp,
+    hrp->hin_tskp);
+   break;
+  case vpiWait:
+   ihref = __mk_exprclass_handle(hrp->hu.hstp->st.swait.lpx, hp->hin_itp,
+    hrp->hin_tskp);
+   break;  
+  case vpiFor:
+   ihref = __mk_exprclass_handle(hrp->hu.hstp->st.sfor->fortermx,
+    hp->hin_itp, hrp->hin_tskp);
+   break;  
+  default: no_1to1h_err(vpiCondition, hp); return(NULL);
+ }
+ return(ihref);
+}
+
+/*
+ * get expr. (1-to-1) from handle
+ *
+ * this traverses to expr_t then converts to <expr object class> handle
+ * except for disable statement vpi_handle
+ */
+static vpiHandle bld_1to1_exprclass_handle(struct h_t *hp)
+{
+ register int32 pi;
+ register struct hrec_t *hrp;
+ word32 hotyp;
+ struct spcpth_t *pthp;
+ struct tchk_t *tcp;
+ struct gate_t *gp;
+ struct net_t *np;
+ struct pathel_t *pep;
+ struct expr_t *xp;
+ struct delctrl_t *dctp;
+ vpiHandle ihref;
+
+ ihref = NULL;
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiDisable:
+   /* even though disable is a statement scope here is expr. disabling scope */
+   /* odd case because vpiScope 1-to-1 method gets containing scope */ 
+   /* not scope to disable - therefore using vpiExpr 1-to-1 method */
+   return(get_disable_scope(hp));
+  case vpiTchkTerm:
+   tcp = hrp->hu.htcp;
+   /* get tchk term of notifier is expr. already not tchk terminal obj */
+   if (hrp->htyp2 == vpiTchkRefTerm)
+    {
+     if (tcp->startxp == NULL) return(NULL);
+     ihref = __mk_exprclass_handle(tcp->startxp, hp->hin_itp, NULL);
+     break;
+    }
+   if (hrp->htyp2 == vpiTchkDataTerm)
+    {
+     if (tcp->chkxp == NULL) return(NULL);
+     ihref = __mk_exprclass_handle(tcp->chkxp, hp->hin_itp, NULL);
+     break;
+    }
+   __vpi_terr(__FILE__, __LINE__);
+   return(NULL);
+  case vpiPathTerm:
+   pthp = hrp->hu.hpthp;
+   if (hrp->htyp2 == vpiModPathIn || hrp->htyp2 == vpiModPathOut)
+    { 
+     if (hrp->htyp2 == vpiModPathIn) pep = &(pthp->peins[hrp->hi]);
+     else pep = &(pthp->peouts[hrp->hi]);    
+     ihref = mk_pthterm_exprclass_handle(pep->penp, pep->pthi1, pep->pthi2,
+      hp->hin_itp);
+     break;
+    }  
+   if (hrp->htyp2 != vpiModDataPathIn) __vpi_terr(__FILE__, __LINE__);
+   if ((xp = pthp->datasrcx) == NULL) return(NULL);
+
+   /* notice indices start at 0 */
+   if (xp->optyp != FCCOM)
+    {
+     if (hrp->hi > 0) __vpi_terr(__FILE__, __LINE__);
+     ihref = __mk_exprclass_handle(xp, hp->hin_itp, NULL);
+     break;
+    }
+   /* FCCOM list */
+   for (pi = 0; xp != NULL; xp = xp->ru.x, pi++) 
+    {
+     if (xp->optyp != FCCOM || pi > hrp->hi) __vpi_terr(__FILE__, __LINE__); 
+     if (pi == hrp->hi) 
+      {
+       ihref = __mk_exprclass_handle(xp->lu.x, hp->hin_itp, NULL);
+       break;  
+      }
+    }
+   break;
+  case vpiPrimTerm:
+   gp = hrp->hu.hgp;
+   ihref = __mk_exprclass_handle(gp->gpins[hrp->hi], hp->hin_itp, NULL);
+   break;
+  case vpiParameter: case vpiSpecParam:
+   /* parameters stored as nets but this must return expr. not final val. */
+   np = hrp->hu.hnp;
+   if (np->nu.ct->parm_srep == SR_PXPR) xp = np->nu.ct->n_dels_u.d1x;
+   else if (np->nu.ct->parm_srep == SR_PISXPR)
+    {
+     /* d4x used but in fact allocated size is number of insts */
+     xp = np->nu.ct->n_dels_u.d4x[hp->hin_itp->itinum];
+    }
+   else { __vpi_terr(__FILE__, __LINE__); return(NULL); }
+   ihref = __mk_exprclass_handle(xp, hp->hin_itp, hrp->hin_tskp);
+   break;
+  case vpiIODecl:
+   if (hrp->htyp2 == vpiUdpDefn) return(NULL);
+
+   /* since can not be bit of - just get wire or reg type */
+   hotyp = __ntyp_to_vpivarhtyp(hrp->hu.hnp);
+   /* since can only be var. do not need expr. class object */
+   /* can be io decl in task so need task from io decl handle */
+   ihref = __mk_handle(hotyp, (void *) hrp->hu.hnp, hp->hin_itp,
+    hrp->hin_tskp);
+   return(ihref);
+  case vpiRepeatControl:
+   /* 10/28/00 SJM - added vpi Expr 1-to-1 access method from repeat ev ctrl */
+   /* returns the repeat count expr */
+   dctp = hrp->hu.hstp->st.sdc;
+   xp = hrp->hu.hstp->st.sdc->repcntx;
+   ihref = __mk_exprclass_handle(xp, hp->hin_itp, hrp->hin_tskp);
+   return(ihref);
+  default: no_1to1h_err(vpiExpr, hp); return(NULL);
+ }
+ return(ihref);
+}
+
+/*
+ * build a path terminal expression class handle
+ * 
+ * only need to allocate expr_t and waste storage for part select
+ * never a task for specify section object
+ *
+ * builds vpiNetBit index form for bit select
+ */
+static vpiHandle mk_pthterm_exprclass_handle(struct net_t *np,
+ int32 i1, int32 i2, struct itree_t *in_itp) 
+{
+ word32 hotyp;
+ vpiHandle href;
+ struct expr_t *xp, *xpcol, *xpid, *xp1, *xp2;
+ struct h_t *hp;
+
+ if (i1 == -1 && i2 == -1)
+  {
+   hotyp = __ntyp_to_vpivarhtyp(np);
+   href = __mk_handle(hotyp, (void *) np, in_itp, NULL); 
+   return(href);
+  }
+
+ /* bit select */
+ if (i1 == i2)
+  {
+   /* this can be bit index form because can not be xmr */
+   href = __mk_handle(vpiNetBit, (void *) np, in_itp, NULL);
+   hp = (struct h_t *) href;
+   hp->hrec->bith_ndx = TRUE;
+   hp->hrec->hi = i1;
+   return(href);
+  }
+ /* part select - allocate new expr and build expr vpiPartSelect handle */
+ xpid = __sim_alloc_newxnd();
+ xpid->optyp = ID; 
+ xpid->lu.sy = np->nsym;
+ xp1 = __bld_rng_numxpr((word32) i1, 0L, WBITS);
+ xp2 = __bld_rng_numxpr((word32) i2, 0L, WBITS);
+ /* root of part select */
+ xp = __sim_alloc_newxnd();
+ xp->optyp = PARTSEL;
+ xp->lu.x = xpid;
+ xpcol = __sim_alloc_newxnd();
+ xpcol->optyp = COLON;
+ xp->ru.x = xpcol;
+ xpcol->lu.x = xp1;
+ xpcol->ru.x = xp2;
+ href = __mk_exprclass_handle(xp, in_itp, NULL);
+ hp = (struct h_t *) href;
+ hp->hrec->free_xpr = TRUE;
+ return(href);
+}
+
+/*
+ * get object containing scope handle
+ *
+ * LOOKATME - allowing use of vpiScope for things in module even though
+ * LRM says handle should be vpiModule
+ */
+static vpiHandle get_obj_scope(struct h_t *hp)
+{
+ int32 ttyp;
+ vpiHandle ihref;
+ struct mod_t *mdp;
+ struct symtab_t *sytp;
+ struct task_t *up_tskp;
+ struct hrec_t *hrp;
+
+ ihref = NULL;
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  /* also process class containing scope (vpiModule) accessible */
+  /* using vpiModule 1-to-1 method */
+  case vpiAlways: case vpiInitial:
+  /* simple cases - parent is module in */ 
+  case vpiPort: case vpiContAssign:
+  case vpiModPath: case vpiTchk: case vpiSpecParam:
+  case vpiGate: case vpiUdp: case vpiSwitch: 
+   ihref = __mk_handle(vpiModule, (void *) mdp, hp->hin_itp, NULL);
+   break;
+   /* this is object in handle - all variables and stmts */
+  case vpiNet: case vpiReg: case vpiNamedEvent: case vpiMemory:
+  case vpiIntegerVar: case vpiTimeVar: case vpiRealVar:
+  case vpiModule:
+   /* all statements - except those with symbol tables */
+  case vpiAssignStmt: case vpiAssignment: case vpiBegin:
+  case vpiCase: case vpiDeassign: case vpiDelayControl:
+  case vpiEventStmt: case vpiFor: case vpiForce: case vpiForever:
+  case vpiFork: case vpiFuncCall: case vpiIf: case vpiIfElse:
+  case vpiNullStmt: case vpiRelease: case vpiRepeat: case vpiSysFuncCall:
+  case vpiSysTaskCall: case vpiTaskCall: case vpiWait: case vpiWhile:
+  /* for expression forms - in module is where expr. appears not variable */
+  case vpiMemoryWord: case vpiNetBit: case vpiRegBit: case vpiVarSelect:
+  case vpiNetDriver: case vpiNetBitDriver:
+  case vpiParamArray: case vpiParamArrayWord:
+  /* 10/28/00 - added missing things with scope */ 
+  case vpiEventControl: case vpiRepeatControl:
+   /* if index is expression form, context is where expr appears */
+   /* to get variable def. loc. need to get parent object */
+   /* this can either be in module or task */
+   if (hp->hrec->hin_tskp == NULL)
+    ihref = __mk_handle(vpiModule, (void *) mdp, hp->hin_itp, NULL);
+   else
+    {
+     sytp = hrp->hin_tskp->tsksymtab;
+     if (sytp->sytpar == NULL || sytp->sytpar->sypofsyt->sytyp == SYM_M)
+      up_tskp = NULL;
+     else up_tskp = sytp->sytpar->sypofsyt->el.etskp;
+
+     ttyp = __to_vpi_tasktyp(hrp->hin_tskp->tsktyp);
+     ihref = __mk_handle(ttyp, (void *) hrp->hin_tskp, hp->hin_itp, up_tskp);
+    }
+   break;
+  /* these are definitions in */
+  case vpiTask: case vpiFunction:
+   return(bld_scope_par(hp, hrp->hu.htskp));
+  /* LOOKATME - think can reduce to one case for all 4 */
+  case vpiNamedBegin: case vpiNamedFork:
+   /* for named block handle is stmt not task so know loc. - can go from */
+   /* task to enclosing stmt */
+   return(bld_scope_par(hp, hrp->hu.htskp));
+  default: no_1to1h_err(vpiScope, hp); return(NULL);
+ }
+ return(ihref);
+}
+
+/*
+ * get scope (task/func/named fork or join) of disable
+ *
+ * LOOKATME - since statement vpiScope should be containing 
+ * but LRM says this is exception where it is disable scope
+ */
+static vpiHandle get_disable_scope(struct h_t *rhp)
+{
+ int32 ttyp;
+ struct st_t *stp;
+ struct expr_t *xp;
+ struct itree_t *itp;
+ struct task_t *tskp;
+ struct symtab_t *sytp;
+ struct task_t *up_tskp;
+
+ stp = rhp->hrec->hu.hstp;
+ xp = stp->st.sdsable.dsablx;
+
+ if (xp->optyp == GLBREF)
+  {
+   __push_itstk(rhp->hin_itp);
+   __xmrpush_refgrp_to_targ(xp->ru.grp);
+   itp = __inst_ptr;
+   __pop_itstk();
+   __pop_itstk();
+  }
+ else if (xp->optyp == ID) itp = rhp->hin_itp;
+ else { __vpi_terr(__FILE__, __LINE__); return(NULL); }
+
+ /* this is scope symbol */
+ tskp = xp->lu.sy->el.etskp;
+ sytp = tskp->tsksymtab;
+ if (sytp->sytpar == NULL || sytp->sytpar->sypofsyt->sytyp == SYM_M)
+  up_tskp = NULL;
+ else up_tskp = sytp->sytpar->sypofsyt->el.etskp;
+
+ /* return task-function-named block handle */
+ ttyp = __to_vpi_tasktyp(tskp->tsktyp);
+ return(__mk_handle(ttyp, (void *) tskp, itp, up_tskp));
+} 
+
+/*
+ * get a contained in stmt handle
+ */
+static vpiHandle get_contained_stmt(struct h_t *rhp)
+{
+ register struct hrec_t *rhrp;
+ word32 sttyp;
+ vpiHandle ihref;
+ struct st_t *ifstp, *thenstp, *dcstp, *stp;
+ struct csitem_t *csip;
+ struct delctrl_t *dctp;
+ struct task_t *tskp;
+
+ rhrp = rhp->hrec;
+ switch (rhrp->htyp) {
+   case vpiInitial: case vpiAlways:
+    stp = rhrp->hu.hialstp->iastp;
+    if (stp->st_unbhead) sttyp = vpiBegin;
+    else sttyp = __to_vpi_stmttyp(&stp);
+    ihref = __mk_stmt_handle(sttyp, stp, rhp->hin_itp, NULL);
+    break;
+   case vpiTask: case vpiFunction:
+    /* SJM 07/30/01 - misisng access from function or task object to stmt */
+    tskp = rhrp->hu.htskp;
+    stp = tskp->tskst;
+    if (stp->st_unbhead) sttyp = vpiBegin;
+    else sttyp = __to_vpi_stmttyp(&stp);
+    ihref = __mk_stmt_handle(sttyp, tskp->tskst, rhp->hin_itp, tskp);
+    break; 
+   case vpiIf: case vpiIfElse:
+    ifstp = rhrp->hu.hstp;    
+    thenstp = ifstp->st.sif.thenst;
+    if (thenstp->st_unbhead) sttyp = vpiBegin;
+    else sttyp = __to_vpi_stmttyp(&thenstp);
+    ihref = __mk_stmt_handle(sttyp, thenstp, rhp->hin_itp, rhrp->hin_tskp);
+    break;
+   case vpiCaseItem:
+    /* for multiple expressions, know points to first (stp non nil) */
+    csip = rhrp->hu.hcsip;
+    stp = csip->csist; 
+    if (stp->st_unbhead) sttyp = vpiBegin;
+    else sttyp = __to_vpi_stmttyp(&stp);
+    ihref = __mk_stmt_handle(sttyp, stp, rhp->hin_itp, rhrp->hin_tskp);
+    break;
+   case vpiDelayControl:
+    dctp = rhrp->hu.hstp->st.sdc;
+    /* really assignment with rhs delay control so LRM requires nil */
+    if (dctp->dctyp == DC_RHSDELAY || dctp->actionst == NULL) return(NULL);
+    dcstp = dctp->actionst;
+    if (dcstp->st_unbhead) sttyp = vpiBegin;
+    else sttyp = __to_vpi_stmttyp(&dcstp);
+    ihref = __mk_stmt_handle(sttyp, dcstp, rhp->hin_itp, rhrp->hin_tskp);
+    break;
+   case vpiEventControl:
+    dctp = rhrp->hu.hstp->st.sdc;
+    /* really assignment with rhs delay control so LRM requires nil */
+    if (dctp->dctyp == DC_RHSEVENT || dctp->actionst == NULL) return(NULL);
+    dcstp = dctp->actionst;
+    /* since after prep for some loops need to return one stmt after setup */
+    if (dcstp->st_unbhead) sttyp = vpiBegin;
+    else sttyp = __to_vpi_stmttyp(&dcstp);
+    ihref = __mk_stmt_handle(sttyp, dcstp, rhp->hin_itp, rhrp->hin_tskp);
+    break;
+   /* forever condition is nil and never accessed */ 
+   case vpiWhile: case vpiForever:
+    stp = rhrp->hu.hstp->st.swh.lpst;
+loop_sthandle:
+    if (stp->st_unbhead) sttyp = vpiBegin;
+    else sttyp = __to_vpi_stmttyp(&stp);
+    ihref = __mk_stmt_handle(sttyp, stp, rhp->hin_itp, rhrp->hin_tskp);
+    break;
+   case vpiRepeat: stp = rhrp->hu.hstp->st.srpt.repst; goto loop_sthandle;
+   case vpiWait: stp = rhrp->hu.hstp->st.swait.lpst; goto loop_sthandle;
+   case vpiFor: stp = rhrp->hu.hstp->st.sfor->forbody; goto loop_sthandle;
+    
+  default: no_1to1h_err(vpiStmt, rhp); return(NULL);
+ }
+ return(ihref);
+}
+
+/*
+ * get a vpi delay control statement from an vpi assignment statement
+ * this is tricky because for rhs dctrls DELCTRL is stmt not actionst assign
+ */
+static vpiHandle get_dctrl_stmt(struct h_t *rhp, int32 dctype)
+{
+ struct st_t *stp;
+ struct delctrl_t *dctp;
+ struct hrec_t *rhrp;
+
+ rhrp = rhp->hrec;
+ if (rhrp->htyp != vpiAssignment)
+  { no_1to1h_err(dctype, rhp); return(NULL); }
+ stp = rhrp->hu.hstp;
+ if (stp->stmttyp != S_DELCTRL) return(NULL);
+ /* same code for both delay control and event control */
+ dctp = stp->st.sdc;
+ if (dctp->dctyp != DC_RHSEVENT && dctp->dctyp != DC_RHSDELAY) 
+  __vpi_terr(__FILE__, __LINE__);
+ if (dctype == vpiDelayControl && dctp->dctyp == DC_RHSDELAY)
+  {
+   return(__mk_handle(vpiDelayControl, (void *) stp, rhp->hin_itp,
+    rhrp->hin_tskp));
+  }
+ if (dctype == vpiEventControl && dctp->dctyp == DC_RHSEVENT
+  && dctp->repcntx == NULL)
+  {
+   return(__mk_handle(vpiEventControl, (void *) stp, rhp->hin_itp,
+    rhrp->hin_tskp));
+  }
+ /* 10/26/00 SJM - also access repeat control */
+ if (dctype == vpiRepeatControl && dctp->dctyp == DC_RHSEVENT
+  && dctp->repcntx != NULL) 
+  {
+   return(__mk_handle(vpiRepeatControl, (void *) stp, rhp->hin_itp,
+    rhrp->hin_tskp));
+  }
+ return(NULL);
+}
+
+/*
+ * get a udp define handle from either a udp primitive
+ * or object inside udp Def
+ */
+static vpiHandle get_udpdef_from_inobj(struct h_t *rhp)
+{
+ vpiHandle href;
+ struct udp_t *udpp;
+ struct hrec_t *rhrp;
+
+ rhrp = rhp->hrec;
+ switch (rhrp->htyp) {
+  case vpiIODecl:
+   /* DBG remove --- */
+   if (rhrp->htyp2 != vpiUdpDefn) __vpi_terr(__FILE__, __LINE__); 
+   /* --- */
+   udpp = (struct udp_t *) rhp->hin_itp;
+   break;
+  case vpiTableEntry: case vpiInitial:
+   udpp = (struct udp_t *) rhp->hin_itp;
+   break;
+  case vpiUdp:
+   udpp = rhrp->hu.hgp->gmsym->el.eudpp;
+   break;
+  default: no_1to1h_err(vpiUdpDefn, rhp); return(NULL);
+ }
+ href = __mk_handle(vpiUdpDefn, (void *) udpp, NULL, NULL);
+ return(href);
+}
+
+/*
+ * get initial value - handle here is just udp with initial type 
+ */
+static vpiHandle get_contained_udp_init(struct h_t *rhp)
+{
+ vpiHandle href;
+ struct udp_t *udpp;
+ struct h_t *hp;
+
+ udpp = rhp->hrec->hu.hudpp;
+ if (udpp->ival == NO_VAL)  
+  {
+   __vpi_err(2111, vpiNotice,
+    "vpi_handle of vpiInitial for vpiUdpDefn handle failed - no initial value");
+   return(NULL);
+  }
+ href = __mk_handle(vpiInitial, (void *) udpp, NULL, NULL);
+ hp = (struct h_t *) href;
+ hp->hrec->htyp2 = vpiUdpDefn;
+ return(href);
+}
+
+/*
+ * one to one access method for getting up instance pound param override 
+ * expression
+ */
+static vpiHandle get_up_poundparam_expr(struct h_t *rhp)
+{
+ int32 pi;
+ vpiHandle href;
+ struct inst_t *ip;
+ struct mod_t *mdp;
+ struct itree_t *up_itp;
+ struct expr_t *xp;
+
+ if (rhp->hrec->htyp != vpiParameter)
+  {
+   no_1to1h_err(vpiPoundParam, rhp);
+   return(NULL);
+  }
+
+ ip = rhp->hin_itp->itip;
+ if (ip->ipxprtab == NULL) return(NULL);
+
+ mdp = rhp->hin_itp->itip->imsym->el.emdp;
+ pi = rhp->hrec->hu.hnp - mdp->mprms;
+ if ((xp = ip->ipxprtab[pi]) == NULL) return(NULL);
+
+ up_itp = rhp->hin_itp->up_it;
+ /* DBG remove --- */
+ if (up_itp == NULL) __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+
+ href = __mk_exprclass_handle(xp, up_itp, NULL);
+ return(href);
+}
+
+/*
+ * ROUTINES TO BUILD ITERATOR HANDLES (FIRST GROUP) 
+ */
+
+/*
+ * allocate and return an iterator handle
+ *
+ * build the entire table of iterators that are returned in order and
+ * freed by scan
+ *
+ * ALGORITHM: use type as first level index that filters which of multiple
+ *            objects to build into scan table.  Then for given type
+ *            use handle (object) as object from which to traverse and build
+ *            type list (i.e. type is target of ->->[type])
+ *
+ * a nil reference handle means use all top level modules
+ * FIXME - what if reference handle is nil for top level modules?
+ */
+extern vpiHandle vpi_iterate(PLI_INT32 itype, vpiHandle referenceHandle)
+{
+ register struct h_t *hp;
+
+ __last_eip = NULL;
+ if (__run_state == SS_COMP)
+  { __still_comp_err("vpi_iterate"); return(NULL); } 
+ if (!__validate_accessm("vpi_iterate", itype, "1-to-many iterator"))
+  return(NULL);
+ hp = (struct h_t *) referenceHandle;
+ /* some iterators have nil (top level?) and value cases so must check */
+ /* for validitly of nil in the routine */
+ if (hp != NULL && !__validate_handle("vpi_iterate", hp)) return(NULL);
+
+ /* separate processing for each 1 to many connection type */ 
+ /* given 1 - many conn. type handle determines object to traverse from */
+ /* type of thing that can appear as multiple list in some handle */
+ switch (itype) {
+  case vpiModule:
+   return(bld_itree_iterator(hp));
+  case vpiOneOfEachMod:
+   return(bld_type_iterator(hp));
+  case vpiUdpDefn:
+   return(bld_udpdef_iterator(hp));
+  /* this is 1-to-many acess method selector - inside mod or task */
+  case vpiInternalScope:
+   return(bld_scope_iterator(hp));
+  case vpiPort:
+   /* for ports in module and net/reg and bit port hiconn connections */
+   return(__bld_port_iterator(hp));
+  case vpiPortInst: return(__bld_neticonn_iter(hp));
+  case vpiNet: case vpiReg: case vpiNamedEvent: case vpiMemory:
+  case vpiVariables:
+   /* vpiVariables for all of integer, time, real - not separated */  
+   return(bld_net_iterator(hp, (word32) itype));
+  case vpiProcess:
+   /* list of initial - always statements in module - only access from mod */
+   return(bld_initalw_iterator(hp));
+  case vpiContAssign:
+   return(bld_conta_iterator(hp));
+  /* here primitive is right since it is the access method */
+  case vpiPrimitive:
+   /* gate, switch, or udp, handle set to actual type */
+   return(bld_gate_iterator(hp));
+  case vpiModPath: return(bld_modpth_iterator(hp));    
+  case vpiTchk: return(bld_tchk_iterator(hp));    
+  case vpiParameter: return(bld_param_iterator(hp, itype));
+  case vpiParamArray: return(bld_paramarr_iterator(hp, itype));
+  case vpiSpecParam: return(bld_specparam_iterator(hp));    
+  case vpiDefParam: return(bld_defparam_stmt_iterator(hp));
+  case vpiParamAssign: return(__bld_paramassign_stmt_iter(hp));
+  case vpiIODecl: return(__bld_iodecl_stmt_iter(hp));
+  case vpiTableEntry: return(__bld_udpline_iter(hp));
+  case vpiPrimTerm: return(__bld_primterm_iterator(hp));
+
+  case vpiLocalLoad: return(__bld_loc_lds_iterator(hp, itype));
+  case vpiLoad: return(__bld_lds_iterator(hp, itype));
+  case vpiLocalDriver: return(__bld_loc_drvs_iterator(hp, itype)); 
+  case vpiDriver: return(__bld_drvs_iterator(hp, itype)); 
+
+  case vpiMemoryWord: return(__bld_arrwrd_iterator(hp));
+  case vpiParamArrayWord: return(__bld_paramwrd_iterator(hp));
+  case vpiBit: return(__bld_bitof_iterator(hp));
+
+  case vpiUserSystf: return(__bld_systf_iterator(hp));
+  case vpiArgument: return(__bld_tfargexpr_iterator(hp));
+  case vpiModPathIn: case vpiModPathOut: case vpiModDataPathIn:
+   return(__bld_pthterm_iterator(hp, (word32) itype));
+  case vpiStmt: return(__bld_stmt_iterator(hp));
+  case vpiTchkTerm: return(__bld_netin_tchkterms(hp));
+  case vpiPathTerm: return(__bld_netin_pthterms(hp));
+  case vpiCaseItem: return(__bld_caseitems_iter(hp));
+  case vpiExpr: return(__bld_casi_exprs_iter(hp));
+  /* notice only concatenate accessible */
+  case vpiOperand: return(__bld_operands_iter(hp));  
+  /* error if hp non nil - routine checks */
+  case vpiCallback: return(__bld_allcbs_iter(hp));
+  case vpiDelay: return(__bld_delay_expr_iter(hp));
+  case vpiAttribute: return(__bld_dig_attr_iter(hp));
+  default:
+   if (hp == NULL) strcpy(__wrks2, "**NULL**"); 
+   else __to_vpionam(__wrks2, hp->hrec->htyp);
+   __vpi_err(1838, vpiError,
+    "method %s not a 1-to-many (iterator) object for %s handle",
+    __to_vpionam(__wrks1, (word32) itype), __wrks2);
+ }
+ return(NULL);
+}
+
+/*
+ * build the top level module (itree inst.) iterator 
+ */
+static vpiHandle bld_itree_iterator(struct h_t *hp)
+{
+ register int32 ii;
+ register struct h_t *hp2;
+ register struct hrec_t *hrp2;
+ vpiHandle ihref;
+ struct itree_t *itp;
+ struct pviter_t *iterp;
+
+ /* case 1: handle non nil, get instances (vpi Module) inside */
+ if (hp != NULL) return(bld_inst_iterator(hp));
+
+ /* case 2: nil so get top level modules */ 
+ /* LOOKATME - how can there be no top level modules */
+ if (__numtopm <= 0) return(NULL);
+
+ /* get all of it roots */
+ iterp = __alloc_iter(__numtopm, &ihref);
+ for (ii = 0; ii < __numtopm; ii++)
+  {
+   hp2 = &(iterp->scanhtab[ii]);
+   hrp2 = hp2->hrec; 
+   hrp2->htyp = vpiModule;
+   itp = __it_roots[ii];
+   hrp2->hu.hmdp = itp->itip->imsym->el.emdp;
+   hp2->hin_itp = itp;
+  }
+ return(ihref);
+}
+
+/*
+ * build one instance of each type iterator 
+ *
+ * error if handle non nil
+ * LOOKATME - for now returning connect modules (even if only used in
+ * connect or maybe by accident connect from others) - is this right?
+ */
+static vpiHandle bld_type_iterator(struct h_t *hp)
+{
+ register int32 ti;
+ register struct mod_t *mdp;
+ register struct h_t *hp2;
+ register struct hrec_t *hrp2;
+ int32 numtypes;
+ vpiHandle ihref;
+ struct itree_t *itp;
+ struct pviter_t *iterp;
+
+ /* case 1: handle non nil, get instances (vpi Module) inside */
+ if (hp != NULL)
+  {
+   __vpi_err(1860, vpiError,
+    "vpiOneOfEachMod 1-to-many iterator 2nd argument must NULL - %s object passed",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+   return(NULL); 
+  }
+ /* count number of types */
+ for (mdp = __modhdr, numtypes = 0; mdp != NULL; mdp = mdp->mnxt)
+  {
+   numtypes++;
+  }
+
+ if (numtypes <= 0) return(NULL);
+ /* get all of it roots */
+ iterp = __alloc_iter(numtypes, &ihref);
+ for (ti = 0, mdp = __modhdr; ti < numtypes; ti++, mdp = mdp->mnxt)
+  {
+   hp2 = &(iterp->scanhtab[ti]);
+   hrp2 = hp2->hrec; 
+   hrp2->htyp = vpiModule;
+   itp = mdp->moditps[0]; 
+   hrp2->hu.hmdp = mdp;
+   hp2->hin_itp = itp;
+  }
+ return(ihref);
+}
+
+/*
+ * allocate an iterator 
+ */
+extern struct pviter_t *__alloc_iter(int32 nels, vpiHandle *ihrefp)
+{
+ register int32 iti;
+ register struct h_t *hp;
+ register struct hrec_t *hrarr;
+ struct pviter_t *iterp;
+
+ iterp = (struct pviter_t *) __my_malloc(sizeof(struct pviter_t));    
+ iterp->numhs = nels;
+ iterp->nxthi = 0;   
+ *ihrefp = __mk_handle(vpiIterator, (void *) iterp,  NULL, NULL);
+ /* this is table of handle guts not ptrs to handles */
+ iterp->scanhtab = (struct h_t *) __my_malloc(nels*sizeof(struct h_t));
+ hrarr = (struct hrec_t *) __my_malloc(nels*sizeof(struct hrec_t)); 
+ iterp->ihrectab = hrarr;
+
+ /* do the non type specific initialization */
+ for (iti = 0; iti < nels; iti++)
+  {
+   hp = &(iterp->scanhtab[iti]);
+   hp->hin_itp = NULL;
+   hp->hrec = &(hrarr[iti]);
+   __init_hrec(hp->hrec);
+   hp->hrec->in_iter = TRUE;
+  }
+ return(iterp);
+}
+
+/*
+ * build the iterator scan table for module instances in handle instance
+ * 1-to-many Vpi Module to Vpi Module inside
+ * only called if at least one contained instance (hp not nil)
+ */
+static vpiHandle bld_inst_iterator(struct h_t *hp)
+{
+ register int32 ii;
+ register struct hrec_t *hrp2;
+ register struct h_t *hp2;
+ struct mod_t *mdp;
+ struct itree_t *itp, *itp2;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+
+ if (hp->hrec->htyp != vpiModule)
+  { mustbe_inmoditer_err(vpiModule, hp); return(NULL); }
+ itp = hp->hin_itp;
+ mdp = itp->itip->imsym->el.emdp; 
+ if (mdp->minum <= 0) return(NULL);
+ iterp = __alloc_iter(mdp->minum, &ihref);
+ for (ii = 0; ii < mdp->minum; ii++)
+  {
+   hp2 = &(iterp->scanhtab[ii]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiModule;
+   itp2 = &(itp->in_its[ii]);  
+   hrp2->hu.hmdp = itp2->itip->imsym->el.emdp;
+   hp2->hin_itp = itp2;
+  }
+ return(ihref);
+}
+
+/*
+ * error for iterator that only exists in module but handle is other
+ */
+static void mustbe_inmoditer_err(word32 ityp, struct h_t *hp)
+{
+ __vpi_err(1841, vpiError,
+  "%s 1-to-many iterator from object %s illegal - only allowed for vpiModule",
+  __to_vpionam(__wrks1, ityp), __to_vpionam(__wrks2, hp->hrec->htyp));
+}
+
+/*
+ * build the iterator for all defined in design iterators 
+ *
+ * in Cver all non instantiated udps removed
+ */
+static vpiHandle bld_udpdef_iterator(struct h_t *rhp)
+{
+ register int32 ui;
+ register struct udp_t *udpp;
+ register struct hrec_t *hrp;
+ register struct h_t *hp; 
+ int32 nudps;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+
+ if (rhp != NULL)
+  {
+   __vpi_err(1837, vpiError,
+    "vpi_iterate of vpiUdpDefn handle must be NULL (%s illegal) - udp definitions design wide",
+    __to_vpionam(__wrks1, rhp->hrec->htyp));
+   return(NULL);
+  }
+ for (udpp = __udphead, nudps = 0; udpp != NULL; udpp = udpp->udpnxt) nudps++;
+ if (nudps <= 0) return(NULL);
+
+ /* build the design wide iterator of all udps */
+ iterp = __alloc_iter(nudps, &ihref);
+ for (ui = 0, udpp = __udphead; ui < nudps; udpp = udpp->udpnxt, ui++)
+  {
+   hp = &(iterp->scanhtab[ui]);
+   hrp = hp->hrec;
+   hrp->htyp = vpiUdpDefn;
+   hrp->hu.hudpp = udpp;
+   /* there is no hin itp for design wide udps */
+  }
+ return(ihref);
+}
+
+/*
+ * given an object handle - build iterator of all scopes in object
+ *
+ * nil handle is top level scopes
+ * scope is class but actual handler is one of module, taskfunc, named begin,
+ * and named fork
+ */
+static vpiHandle bld_scope_iterator(register struct h_t *hp) 
+{
+ struct mod_t *mdp;
+ struct symtab_t *sytp;
+ 
+ if (hp == NULL) return(__nil_iter_err(vpiInternalScope));
+ switch (hp->hrec->htyp) {
+  case vpiModule:
+   /* scope list in module */
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   return(bld_symtabs_iterator(mdp->msymtab->sytofs, hp->hin_itp));
+  case vpiTask: case vpiFunction:
+   /* real task, hu is task ptr */
+   sytp = hp->hrec->hu.htskp->tsksymtab;
+   return(bld_symtabs_iterator(sytp->sytofs, hp->hin_itp));
+  case vpiNamedBegin: case vpiNamedFork:
+   /* pseudo task, hu is stmt */
+   sytp = hp->hrec->hu.htskp->tsksymtab;
+   return(bld_symtabs_iterator(sytp->sytofs, hp->hin_itp));
+  default:
+   __vpi_err(1843, vpiError,
+    "unable to construct iterator of contained scopes for %s object",
+   __to_vpionam(__wrks1, hp->hrec->htyp));
+ }
+ return(NULL);
+}
+
+/*
+ * emit error for iterator type that can not be nil
+ *
+ * needed because many design lists accessed from nil handle
+ */
+extern vpiHandle __nil_iter_err(word32 otyp)
+{
+ __vpi_err(1854, vpiError, "vpi_iterate type %s passed illegal NULL handle",
+  __to_vpionam(__wrks1, otyp));
+ return(NULL);
+}
+
+/*
+ * build an iterator for a list of scopes - works from symbol table
+ * know passed left most symbol table for multiple disjoint32 scopes
+ */
+static vpiHandle bld_symtabs_iterator(struct symtab_t *sytp,
+ struct itree_t *itp)
+{
+ register int32 ii;
+ register struct symtab_t *sytp2;
+ register struct h_t *hp;
+ register struct hrec_t *hrp;
+ int32 numtabs;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct task_t *up_tskp;
+
+ if (sytp == NULL) return(NULL);
+ for (numtabs = 0, sytp2 = sytp; sytp2 != NULL; sytp2 = sytp2->sytsib)
+  numtabs++;
+ if (numtabs <= 0) return(NULL);
+ iterp = __alloc_iter(numtabs, &ihref);
+ for (sytp2 = sytp, ii = 0; ii < numtabs; sytp2 = sytp2->sytsib, ii++)
+  {
+   hp = &(iterp->scanhtab[ii]);
+   hrp = hp->hrec;
+   fill_scopehandle(hrp, sytp2);
+   hp->hin_itp = itp;
+   if (sytp->sytpar == NULL || sytp->sytpar->sypofsyt->sytyp == SYM_M)
+    up_tskp = NULL;
+   else up_tskp = sytp->sytpar->sypofsyt->el.etskp;
+   /* this task handle is maybe in one up task (for nested named blocks) */  
+   hrp->hin_tskp = up_tskp;
+  }
+ return(ihref);
+}
+
+/*
+ * get vpi_ object associated with a symbol table - always a task_t
+ *
+ * only one of tskp or mdp set
+ */
+static void fill_scopehandle(struct hrec_t *hrp, struct symtab_t *sytp)
+{
+ struct task_t *tskp; 
+ struct sy_t *syp;
+
+ syp = sytp->sypofsyt;
+ switch ((byte) syp->sytyp) {
+  case SYM_M:
+   hrp->htyp = vpiModule;
+   hrp->hu.hmdp = syp->el.emdp;
+   return;
+  case SYM_TSK: hrp->htyp = vpiTask; break;
+  case SYM_F: hrp->htyp = vpiFunction; break;
+  case SYM_LB:
+   tskp = syp->el.etskp;
+   if (tskp->tsktyp == Begin) hrp->htyp = vpiNamedBegin;
+   else if (tskp->tsktyp == FORK) hrp->htyp = vpiNamedFork;
+   else __vpi_terr(__FILE__, __LINE__);
+   /* this is tricky part of named block as task code because scope is tskp */
+   /* but need the enclosing statement (can only be one) */
+   hrp->hu.htskp = syp->el.etskp->st_namblkin->st.snbtsk;
+   return;
+  default:;
+ }
+ hrp->hu.htskp = syp->el.etskp;
+}
+
+/*
+ * given an object containing nets handle - build iterator of all nets
+ *
+ * otype is vpi_ type of net 
+ */
+static vpiHandle bld_net_iterator(struct h_t *hp, word32 otype)
+{
+ register struct hrec_t *hrp;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+ struct itree_t *itp; 
+ struct net_t *np;
+ word32 ntyp;
+
+ if (hp == NULL) return(__nil_iter_err(otype));
+ itp = hp->hin_itp;
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiModule: 
+   mdp = itp->itip->imsym->el.emdp;
+   if (mdp->mnets == NULL) return(NULL);
+   np = &(mdp->mnets[0]);
+   return(bld_listofnets_iter(np, mdp->mnnum, itp, otype, NULL));
+  case vpiTask: case vpiFunction: case vpiNamedBegin: case vpiNamedFork:
+   /* variables class does not map to ntyp */  
+   if (otype != vpiVariables)
+    {
+     /* cannot be wire type for task */
+     ntyp = __from_vpi_vartyp(otype);
+     if (ntyp < NONWIRE_ST)
+      {
+       __vpi_err(1845, vpiError,
+        "unable to construct %s iterator for non module scope %s",
+        __to_vpionam(__wrks1, otype), __to_vpionam(__wrks2, hrp->htyp));
+       return(NULL);
+      }
+    }
+   tskp = hrp->hu.htskp;
+   if (tskp->tsk_regs == NULL) return(NULL);
+
+   np = &(tskp->tsk_regs[0]);
+   return(bld_listofnets_iter(np, tskp->trnum, itp, otype, tskp));
+  default:
+   __vpi_err(1847, vpiError,
+    "unable to construct iterator of contained %s for %s object",
+    __to_vpionam(__wrks1, otype), __to_vpionam(__wrks2, hrp->htyp));
+ }
+ return(NULL);
+}
+
+/*
+ * build an iterator for a list of module nets of type type
+ *
+ * know at least one net or will not be called but maybe none of type
+ */
+static vpiHandle bld_listofnets_iter(struct net_t *np, int32 onnum,
+ struct itree_t *itp, word32 otype, struct task_t *tskp)
+{
+ register int32 ni, ni2;
+ register struct net_t *np2;
+ register struct h_t *hp;
+ register struct hrec_t *hrp;
+ int32 nnum;
+ word32 ntyp, vpityp;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+
+ if ((nnum = cnt_typnetnum(np, onnum, otype)) <= 0) return(NULL);
+ iterp = __alloc_iter(nnum, &ihref);
+ if (otype == vpiMemory)
+  {
+   for (ni = ni2 = 0, np2 = np; ni < onnum; ni++, np2++)
+    {
+     if (np2->n_isarr)
+      {
+       /* notice number of nets (ni) maybe larger than iterator size ni2 */
+       hp = &(iterp->scanhtab[ni2++]);
+       hrp = hp->hrec;
+       hrp->htyp = vpiMemory;
+       hrp->hu.hnp = np2;
+       hp->hin_itp = itp;
+       hrp->hin_tskp = tskp;
+      }
+    }
+   return(ihref);
+  }
+ /* passed vpiNet for all wire types (all non regs) */
+ if (otype == vpiNet)
+  {
+   for (ni = ni2 = 0, np2 = np; ni < onnum; ni++, np2++)
+    {
+     if (np2->ntyp < NONWIRE_ST)
+      {
+       hp = &(iterp->scanhtab[ni2++]);
+       hrp = hp->hrec;
+       hrp->htyp = vpiNet; 
+       hrp->hu.hnp = np2;
+       hp->hin_itp = itp;
+       hrp->hin_tskp = tskp;
+      }
+    }
+   return(ihref);
+  }
+ /* passed vpiVariables for all reg types (all non wires) */
+ if (otype == vpiVariables)
+  {
+   for (ni = ni2 = 0, np2 = np; ni < onnum; ni++, np2++)
+    {
+     if (np2->n_isarr) continue;
+
+     /* 1 to many iterator selector must be variable but handle is separate */
+     /* variable type */
+     if (np2->ntyp == N_TIME) vpityp = vpiTimeVar;
+     else if (np2->ntyp == N_INT) vpityp = vpiIntegerVar;
+     else if (np2->ntyp == N_REAL) vpityp = vpiRealVar;
+     else continue;
+      
+     hp = &(iterp->scanhtab[ni2++]);
+     hrp = hp->hrec;
+     hrp->htyp = vpityp;
+     hrp->hu.hnp = np2;
+     hp->hin_itp = itp;
+     hrp->hin_tskp = tskp;
+    }
+   return(ihref);
+  }
+ /* this is used to convert for comparing know type already checked */
+ ntyp = __from_vpi_vartyp(otype);
+ for (ni2 = ni = 0, np2 = np; ni < onnum; ni++, np2++)
+  {
+   if (np2->n_isarr) continue;
+   if (np2->ntyp == ntyp)
+    {
+     hp = &(iterp->scanhtab[ni2++]);
+     hrp = hp->hrec;
+     hrp->htyp = otype;
+     hrp->hu.hnp = np2;
+     hp->hin_itp = itp;
+     hrp->hin_tskp = tskp;
+    }
+  }
+ return(ihref);
+}
+
+/*
+ * count number of nets of object type
+ * needed because all wires stored in one list in Cver
+ * possibilities are array, net (and wire) or match N_ internal type
+ */
+static int32 cnt_typnetnum(register struct net_t *np, int32 onnum,
+ word32 typ)
+{
+ register int32 ni;
+ word32 nnum;
+ word32 ntyp;
+
+ nnum = 0;
+ if (typ == vpiMemory)
+  {
+   for (ni = 0; ni < onnum; ni++, np++) { if (np->n_isarr) nnum++; }
+   return(nnum);
+  }
+ /* passed vpiNet for all wire types (all non regs) */
+ if (typ == vpiNet)
+  {
+   for (ni = 0; ni < onnum; ni++, np++)
+    { if (np->ntyp < NONWIRE_ST) nnum++; }
+   return(nnum);
+  }
+ /* vpiVarible for real, integer, and time that are accessed together */
+ if (typ == vpiVariables)
+  {
+   for (ni = 0; ni < onnum; ni++, np++)
+    {
+     if (np->n_isarr) continue;
+     if (np->ntyp == N_REAL || np->ntyp == N_INT || np->ntyp == N_TIME)
+      nnum++;
+    }
+   return(nnum);
+  }
+ /* for reg - can not fail */
+ ntyp = __from_vpi_vartyp(typ);
+ for (ni = 0; ni < onnum; ni++, np++)
+  { 
+   if (np->n_isarr) continue;
+   if (np->ntyp == ntyp) nnum++;
+  }
+ return(nnum);
+}
+
+
+/*
+ * build the iterator for initial-always - 1-to-many selector is vpi process
+ * but handle has type of object itself
+ *
+ * the object here is the ialst not the one statement
+ */
+static vpiHandle bld_initalw_iterator(struct h_t *hp)
+{
+ register struct ialst_t *ialp;
+ register int32 iai;
+ register struct hrec_t *hrp2;
+ int32 ianum;
+ vpiHandle ihref;
+ struct h_t *hp2;
+ struct mod_t *mdp;
+ struct itree_t *itp;
+ struct pviter_t *iterp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiProcess));
+ if (hp->hrec->htyp != vpiModule)
+  { mustbe_inmoditer_err(vpiProcess, hp); return(NULL); }
+ itp = hp->hin_itp;
+ mdp = itp->itip->imsym->el.emdp;
+ if (mdp->ialst == NULL) return(NULL); 
+ for (ianum = 0, ialp = mdp->ialst; ialp != NULL; ialp = ialp->ialnxt)
+  ianum++;
+ /* DBG remove - checking again to maybe catch corrupted memory */
+ if (ianum <= 0) return(NULL); 
+
+ iterp = __alloc_iter(ianum, &ihref);
+ for (iai = 0, ialp = mdp->ialst; iai < ianum; iai++, ialp = ialp->ialnxt)
+  {
+   hp2 = &(iterp->scanhtab[iai]);
+   hrp2 = hp2->hrec;
+   if (ialp->iatyp == ALWAYS) hrp2->htyp = vpiAlways;
+   else hrp2->htyp = vpiInitial;
+   hrp2->hu.hialstp = ialp;
+   hp2->hin_itp = itp;
+  }
+ return(ihref);
+}
+
+/*
+ * build the iterator scan table for module contas
+ * only called if at least one conta and no other 1-to-many access path
+ */
+static vpiHandle bld_conta_iterator(struct h_t *hp)
+{
+ register int32 cai, gi;
+ register struct h_t *hp2;
+ register struct hrec_t *hrp2;
+ int32 numcas, num1bcas;
+ vpiHandle ihref;
+ struct conta_t *cap;
+ struct gate_t *gp;
+ struct mod_t *mdp;
+ struct itree_t *itp;
+ struct pviter_t *iterp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiContAssign));
+ if (hp->hrec->htyp != vpiModule)
+  { mustbe_inmoditer_err(vpiContAssign, hp); return(NULL); }
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+
+ itp = hp->hin_itp;
+ /* contas in table - does not include 1 bit cas treated as gate */
+ numcas = mdp->mcanum;
+ num1bcas = 0;
+ if (mdp->mod_1bcas)
+  {
+   for (gi = 0; gi < mdp->mgnum; gi++)
+    {
+     gp = &(mdp->mgates[gi]);
+     if (gp->gmsym->el.eprimp->gateid == G_ASSIGN) num1bcas++;
+    }
+  }
+ if (numcas + num1bcas <= 0) return(NULL);
+ iterp = __alloc_iter(numcas + num1bcas, &ihref);
+ for (cai = 0, cap = &(mdp->mcas[0]); cai < numcas; cai++, cap++)
+  {
+   hp2 = &(iterp->scanhtab[cai]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiContAssign;
+   hrp2->hu.hcap = cap;
+   hp2->hin_itp = itp;
+  }
+ if (mdp->mod_1bcas)
+  {
+   for (gi = 0; gi < mdp->mgnum; gi++)
+    {
+     gp = &(mdp->mgates[gi]);
+   
+     if (gp->gmsym->el.eprimp->gateid != G_ASSIGN) continue;
+     hp2 = &(iterp->scanhtab[cai]);
+     hrp2 = hp2->hrec;
+     hrp2->htyp = vpiContAssign;
+     hrp2->htyp2 = vpiGate;
+     hrp2->hu.hgp = gp;
+     hp2->hin_itp = itp;
+     cai++;
+    }
+  }
+ return(ihref);
+}
+
+/*
+ * build the iterator scan table for gates one scan table mixed the 3
+ * types with htyp giving the type
+ *
+ * notice primitives are all gates, switches, and udps
+ */
+static vpiHandle bld_gate_iterator(struct h_t *hp)
+{
+ register struct gate_t *gp;
+ register struct h_t *hp2;
+ register struct hrec_t *hrp2;
+ int32 numgs, gi, hi;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct mod_t *mdp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiPrimitive));
+ if (hp->hrec->htyp != vpiModule)
+  { mustbe_inmoditer_err(vpiPrimitive, hp); return(NULL); }
+
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ if (mdp->mgnum == 0) return(NULL);
+ for (numgs = 0, gi = 0; gi < mdp->mgnum; gi++)
+  {
+   gp = &(mdp->mgates[gi]);
+   if (gp->gmsym->el.eprimp->gateid != G_ASSIGN) numgs++;
+  }
+ /* DBG remove - checking again to maybe catch corrupted memory */
+ if (numgs <= 0) return(NULL);
+ iterp = __alloc_iter(numgs, &ihref);
+ for (gi = 0, hi = 0; gi < mdp->mgnum; gi++)
+  { 
+   gp = &(mdp->mgates[gi]);
+   if (gp->gmsym->el.eprimp->gateid == G_ASSIGN) continue;
+
+   hp2 = &(iterp->scanhtab[hi++]);
+   hrp2 = hp2->hrec;
+   hrp2->hu.hgp = gp;
+   hp2->hin_itp = hp->hin_itp;
+   hrp2->htyp = __gate_to_vpiprimtyp(gp);
+  }
+ return(ihref);
+}
+
+/*
+ * map from a gate_t to a vpi primitive type (i.e. vpi Switch)
+ */
+extern word32 __gate_to_vpiprimtyp(struct gate_t *gp)
+{
+ int32 ptyp;
+
+ switch ((byte) gp->g_class) {
+  /* LOOKATME - is pull possible here (think so) */  
+  case GC_LOGIC: case GC_BUFIF: case GC_MOS: case GC_CMOS: case GC_PULL:
+   ptyp = vpiGate;
+   break;
+  case GC_UDP: ptyp = vpiUdp; break;
+  case GC_TRAN: case GC_TRANIF: ptyp = vpiSwitch; break;
+  default: __vpi_terr(__FILE__, __LINE__); return(0);
+ }
+ return(ptyp);
+}
+
+/*
+ * build the iterator scan table for mod paths
+ * only called if module has at least one path
+ */
+static vpiHandle bld_modpth_iterator(struct h_t *hp)
+{
+ register int32 pi;
+ register struct spcpth_t *pthp;
+ register struct hrec_t *hrp2;
+ int32 mpths; 
+ vpiHandle ihref;
+ struct h_t *hp2;
+ struct mod_t *mdp;
+ struct pviter_t *iterp;
+ 
+ if (hp == NULL) return(__nil_iter_err(vpiModPath));
+ if (hp->hrec->htyp != vpiModule)
+  { mustbe_inmoditer_err(vpiModPath, hp); return(NULL); }
+
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ if (mdp->mspfy == NULL || mdp->mspfy->spcpths == NULL) return(NULL);
+ mpths = 0;
+ for (pthp = mdp->mspfy->spcpths; pthp != NULL; pthp = pthp->spcpthnxt)
+  mpths++;
+ /* DBG remove - checking again to maybe catch corrupted memory */
+ if (mpths <= 0) return(NULL);
+
+ iterp = __alloc_iter(mpths, &ihref);
+ for (pi = 0, pthp = mdp->mspfy->spcpths; pi < mpths; pthp = pthp->spcpthnxt,
+  pi++)
+  {
+   hp2 = &(iterp->scanhtab[pi]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiModPath;
+   hrp2->hu.hpthp = pthp;
+   hp2->hin_itp = hp->hin_itp;
+  }
+ return(ihref);
+}
+
+/*
+ * build the iterator scan table for tchks
+ *
+ * added complication must remove setup with tc setup of setup hold flag on
+ * hold has pointer to setup value when needed
+ */
+static vpiHandle bld_tchk_iterator(struct h_t *hp)
+{
+ register int32 tci;
+ register struct h_t *hp2;
+ register struct tchk_t *tcp;
+ register struct hrec_t *hrp2;
+ int32 ntchks; 
+ vpiHandle ihref;
+ struct mod_t *mdp;
+ struct pviter_t *iterp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiTchk));
+ if (hp->hrec->htyp != vpiModule)
+  { mustbe_inmoditer_err(vpiTchk, hp); return(NULL); }
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ if (mdp->mspfy == NULL || mdp->mspfy->tchks == NULL) return(NULL);
+ for (ntchks = 0, tcp = mdp->mspfy->tchks; tcp != NULL; tcp = tcp->tchknxt)
+  {
+   if (tcp->tchktyp == TCHK_SETUP && tcp->tc_supofsuphld) continue;
+   if (tcp->tchktyp == TCHK_RECOVERY && tcp->tc_recofrecrem) continue;
+   ntchks++;
+  }
+ /* DBG remove - checking again to maybe catch corrupted memory */
+ if (ntchks <= 0) return(NULL);
+
+ iterp = __alloc_iter(ntchks, &ihref);
+ for (tci = 0, tcp = mdp->mspfy->tchks; tcp != NULL; tcp = tcp->tchknxt)
+  {
+   /* must remove setup of setuphold since can access from hold side */
+   if (tcp->tchktyp == TCHK_SETUP && tcp->tc_supofsuphld) continue;
+   if (tcp->tchktyp == TCHK_RECOVERY && tcp->tc_recofrecrem) continue;
+
+   hp2 = &(iterp->scanhtab[tci++]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiTchk;
+   hrp2->hu.htcp = tcp;
+   hp2->hin_itp = hp->hin_itp;
+  }
+ return(ihref);
+}
+
+/*
+ * given an object containing params handle - build iterator of all params
+ *
+ * otype is vpi_ type of net 
+ */
+static vpiHandle bld_param_iterator(struct h_t *hp, int32 otype)
+{
+ register struct hrec_t *hrp;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+ struct itree_t *itp; 
+
+ if (hp == NULL)
+  {
+   return(__nil_iter_err(vpiParameter));
+  }
+
+ itp = hp->hin_itp;
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiModule: 
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   if (mdp->mprms == NULL) return(NULL);
+   return(bld_listofparams_iter(mdp->mprms, mdp->mprmnum, itp, NULL, FALSE));
+  case vpiTask: case vpiFunction:
+   tskp = hrp->hu.htskp;
+bld_tskprms:
+   if (tskp->tsk_prms == NULL) return(NULL);
+   return(bld_listofparams_iter(tskp->tsk_prms, tskp->tprmnum, itp, tskp,
+    FALSE));
+  case vpiNamedBegin: case vpiNamedFork:
+   tskp = hrp->hu.htskp;
+   goto bld_tskprms;
+  default:
+   __vpi_err(1851, vpiError,
+    "unable to construct iterator of contained %s for %s object",
+    __to_vpionam(__wrks1, (word32) otype), __to_vpionam(__wrks2, hrp->htyp));
+ }
+ return(NULL);
+}
+
+/*
+ * build the iterator scan table for parameters (all nets of mprms)
+ *
+ * LOOKATME - why was mprms not freed? - needed for here
+ */
+static vpiHandle bld_listofparams_iter(struct net_t *nptab, int32 nparams,
+ struct itree_t *itp, struct task_t *tskp, int32 sel_parrays)
+{
+ register int32 pi, iti;
+ register struct hrec_t *hrp;
+ int32 pitersiz;
+ vpiHandle ihref;
+ struct h_t *hp;
+ struct net_t *np;
+ struct pviter_t *iterp;
+
+ if (nparams == 0) return(NULL);
+ for (pi = 0, pitersiz = 0; pi < nparams; pi++)
+  {
+   np = &(nptab[pi]);
+   if (sel_parrays) { if (np->n_isarr) pitersiz++; }
+   else { if (!np->n_isarr) pitersiz++; }
+  }
+ /* because iter by array class may have params but 0 iterator size */
+ if (pitersiz <= 0) return(NULL);
+
+ iterp = __alloc_iter(pitersiz, &ihref);
+ for (pi = 0, iti = -1; pi < nparams; pi++)
+  {
+   np = &(nptab[pi]);
+   if (sel_parrays) { if (!np->n_isarr) continue; }
+   else { if (np->n_isarr) continue; }
+
+   hp = &(iterp->scanhtab[++iti]);
+   hrp = hp->hrec;
+   if (np->n_isarr) hrp->htyp = vpiParamArray; else hrp->htyp = vpiParameter;
+   hrp->hu.hnp = &(nptab[pi]);
+   hp->hin_itp = itp;
+   hrp->hin_tskp = tskp;
+  }
+ return(ihref);
+}
+
+/*
+ * given param array object handle - build iterator of all param arrays
+ *
+ * otype is vpi_ type of containing scope
+ */
+static vpiHandle bld_paramarr_iterator(struct h_t *hp, int32 otype)
+{
+ struct mod_t *mdp;
+ struct task_t *tskp;
+ struct itree_t *itp; 
+ struct hrec_t *hrp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiParameter));
+ itp = hp->hin_itp;
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiModule: 
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   if (mdp->mprms == NULL) return(NULL);
+   return(bld_listofparams_iter(mdp->mprms, mdp->mprmnum, itp, NULL, TRUE));
+  case vpiTask: case vpiFunction:
+   tskp = hrp->hu.htskp;
+bld_tskprms:
+   if (tskp->tsk_prms == NULL) return(NULL);
+   return(bld_listofparams_iter(tskp->tsk_prms, tskp->tprmnum, itp, tskp,
+    TRUE));
+  case vpiNamedBegin: case vpiNamedFork:
+   tskp = hrp->hu.htskp;
+   goto bld_tskprms;
+  default:
+   __vpi_err(1851, vpiError,
+    "unable to construct iterator of contained %s for %s object",
+    __to_vpionam(__wrks1, (word32) otype), __to_vpionam(__wrks2, hrp->htyp));
+ }
+ return(NULL);
+}
+
+/*
+ * build the iterator scan table for specparam (all nets)
+ *
+ * only called if module has at least one specparam
+ * this does not need parent since one in module - can get from itp  
+ */
+static vpiHandle bld_specparam_iterator(struct h_t *hp)
+{
+ register int32 pi;
+ register struct h_t *hp2;
+ register struct hrec_t *hrp2;
+ int32 nsparams; 
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct mod_t *mdp;
+ struct spfy_t *spfyp;
+ struct hrec_t *hrp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiSpecParam));
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiModule)
+  { mustbe_inmoditer_err(vpiSpecParam, hp); return(NULL); }
+
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ if ((spfyp = mdp->mspfy) == NULL) return(NULL);
+ if (spfyp->msprms == NULL) return(NULL);
+
+ nsparams = spfyp->sprmnum;
+ if (nsparams <= 0) return(NULL); 
+ iterp = __alloc_iter(nsparams, &ihref);
+ for (pi = 0; pi < spfyp->sprmnum; pi++)
+  {
+   hp2 = &(iterp->scanhtab[pi]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiSpecParam;
+   hrp2->hu.hnp = &(spfyp->msprms[pi]);
+   hp2->hin_itp = hp->hin_itp;
+  }
+ return(ihref);
+}
+
+/*
+ * build a defparam statement iterator
+ *
+ * no one master list - must match itree location of module handle
+ */
+static vpiHandle bld_defparam_stmt_iterator(struct h_t *hp)
+{
+ register int32 dfi;
+ register struct h_t *hp2;
+ register struct hrec_t *hrp2;
+ register struct dfparam_t *dfp;
+ int32 ndfps; 
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct itree_t *itp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiDefParam));
+ if (hp->hrec->htyp != vpiModule)
+  { mustbe_inmoditer_err(vpiDefParam, hp); return(NULL); }
+
+ if (__dfphdr == NULL) return(NULL);
+
+ for (ndfps = 0, dfp = __dfphdr; dfp != NULL; dfp = dfp->dfpnxt)
+  {
+   itp = __find_dfpbot_itp(dfp);
+   if (itp == hp->hin_itp) ndfps++;
+  }
+ if (ndfps <= 0) return(NULL);
+ iterp = __alloc_iter(ndfps, &ihref);
+ for (dfi = 0, dfp = __dfphdr; dfp != NULL; dfp = dfp->dfpnxt)
+  {
+   itp = __find_dfpbot_itp(dfp);
+   if (itp != hp->hin_itp) continue;
+
+   hp2 = &(iterp->scanhtab[dfi]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiDefParam;
+   hrp2->hu.hdfp = dfp;
+   hp2->hin_itp = hp->hin_itp;
+   dfi++;
+  }
+ return(ihref);
+}
diff --git a/src/v_vpi2.c b/src/v_vpi2.c
new file mode 100644
index 0000000..96e939b
--- /dev/null
+++ b/src/v_vpi2.c
@@ -0,0 +1,6892 @@
+/* Copyright (c) 1995-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * 2nd module to implement pli vpi_ routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* local prototypes */
+static void mk2_exprclass_handle(struct h_t *, struct expr_t *,
+ struct itree_t *, struct task_t *);
+static int32 iconnbit_lvalue(struct mod_pin_t *, struct net_pin_t *,
+ struct itree_t *);
+static vpiHandle bld_inmod_port_iter(struct h_t *);
+static vpiHandle bld_fjlist_iter(struct st_t *, struct itree_t *,
+ struct task_t *);
+static vpiHandle bld_listofstmts_iter(struct st_t *, struct itree_t *,
+ struct task_t *);
+static vpiHandle bld_listofexprs_iter(struct expr_t *, struct itree_t *,
+ struct task_t *);
+static int32 termexpr_matches(struct expr_t *, struct net_t *, int32);
+static int32 bld_net_tchkterms(struct net_t *, struct itree_t *, int32);
+static int32 bld_net_pathterms(struct net_t *, struct itree_t *, int32);
+static int32 bld_delay_iter(union del_u, word32, struct itree_t *,
+ struct task_t *);
+static vpiHandle bld_dig_attrlist_iter(struct h_t *, struct attr_t *);
+static vpiHandle bld_netmdport_iter(struct h_t *);
+static int32 bld_net_mdpins(struct net_t *, struct mod_t *, struct itree_t *);
+static vpiHandle bld_netbitmdport_iter(struct h_t *);
+static int32 cmp_drvld_bitndx(struct net_t **, struct h_t *, char *);
+static int32 bld_netbit_mdpins(struct net_t *, int32, struct mod_t *,
+ struct itree_t *);
+static vpiHandle bld_neticonnport_iter(struct h_t *);
+static int32 bld_net_iconns(struct net_t *, struct itree_t *);
+static int32 same_vpi_handle(struct h_t *, int32, int32, struct h_t *,
+ struct hrec_t *);
+static vpiHandle bld_netbiticonnport_iter(struct h_t *);
+static int32 bld_netbit_iconns(struct net_t *, int32, struct itree_t *);
+static vpiHandle net_lds_iter(struct h_t *);
+static int32 bld_net_lds(struct net_t *, struct itree_t *);
+static int32 fill_ld_handle(struct h_t *, struct hrec_t *, struct net_pin_t *);
+static vpiHandle bit_lds_iter(struct h_t *);
+static int32 bld_bit_lds(struct net_t *, int32, struct itree_t *, int32);
+static int32 fill_bit_ld_handle(struct h_t *, struct hrec_t *, int32, int32, int32,
+ struct net_pin_t *);
+static vpiHandle bit_xl_ldsdrvs_iter(struct h_t *, int32);
+static vpiHandle net_drvs_iter(struct h_t *);
+static int32 bld_net_drvs(struct net_t *, struct itree_t *);
+static int32 fill_drv_handle(struct h_t *, struct hrec_t *, struct net_pin_t *);
+static vpiHandle bit_drvs_iter(struct h_t *hp);
+static int32 bld_bit_drvs(struct net_t *, int32, struct itree_t *, int32);
+static int32 fill_bit_drv_handle(struct h_t *, struct hrec_t *, int32, int32, int32,
+ struct net_pin_t *);
+static vpiHandle reg_drvs_iter(struct h_t *);
+static vpiHandle cnvt_name_to_handle(char *, struct symtab_t *,
+ struct itree_t *);
+static vpiHandle bld_symhandle(char *, struct sy_t *, struct symtab_t *,
+ struct itree_t *);
+static int32 validate_property(char *, int32);
+static int32 modprop_vpiget(struct h_t *, int32);
+static void notpropof_err(word32, int32);
+static word32 to_vpi_reghtyp(word32);
+static int32 netprop_vpiget(struct h_t *, int32);
+static int32 regprop_vpiget(struct h_t *, int32);
+static int32 arrprop_vpiget(struct h_t *, int32);
+static int32 arrwrdprop_vpiget(struct h_t *, int32);
+static int32 paramprop_vpiget(struct h_t *, int32);
+static int32 portprop_vpiget(struct h_t *, int32);
+static int32 get_param_constyp(struct net_t *);
+static int32 gateprop_vpiget(struct h_t *, int32);
+static int32 tcallprop_vpiget(struct h_t *, int32);
+static int32 funcdefprop_vpiget(struct h_t *, int32);
+static int32 contaprop_vpiget(struct h_t *, int32);
+static int32 fcallprop_vpiget(struct h_t *, int32);
+static int32 tchkprop_vpiget(struct h_t *, int32);
+static int32 to_vpi_tchktyp(word32);
+static int32 tchktermprop_vpiget(struct h_t *, int32);
+static int32 to_vpi_edgeval(word32);
+static int32 pthprop_vpiget(struct h_t *, int32);
+static int32 pthtermprop_vpiget(struct h_t *, int32);
+static int32 exprclass_prop_vpiget(struct h_t *, int32);
+static int32 get_vpi_const_typ(struct expr_t *);
+static int32 iodecl_prop_vpiget(struct h_t *, int32);
+static int32 udpiodecl_get(struct h_t *, int32);
+static int32 udpdefnprop_vpiget(struct h_t *, int32);
+static int32 udptabentryprop_vpiget(struct h_t *, int32);
+static int32 dig_attrprop_vpiget(struct h_t *, int32);
+static char *modstrprop_vpiget(struct h_t *, int32);
+static char *netstrprop_vpiget(struct h_t *, int32);
+static char *portstrprop_vpiget(struct h_t *, int32);
+static char *gatestrprop_vpiget(struct h_t *, int32);
+static char *tcallstrprop_vpiget(struct h_t *, int32);
+static char *fcallstrprop_vpiget(struct h_t *, int32);
+static char *taskstrprop_vpiget(struct h_t *, int32);
+static char *iodeclstrprop_vpiget(struct h_t *, int32);
+static char *dig_attrstrpop_vpiget(struct h_t *, int32);
+
+
+/* extern prototypes (maybe defined in this module) */
+extern vpiHandle vpi_handle_by_name(char *, vpiHandle);
+extern vpiHandle vpi_handle_by_index(vpiHandle, PLI_INT32);
+extern int32 vpi_get(PLI_INT32, vpiHandle);
+extern word32 __ntyp_to_vpivarhtyp(struct net_t *);
+extern word32 __to_vpinetbithtyp(word32);
+extern word32 __from_vpi_vartyp(word32);
+extern int32 __expr_optype_get(struct expr_t *);
+extern char *vpi_get_str(int32, vpiHandle);
+extern char *__to_vpionam(char *, word32);
+extern char *__to_vpiopchar(char *, int32);
+extern void __still_comp_err(char *);
+extern int32 __validate_handle(char *, struct h_t *);
+extern int32 __get_vpinet_index(struct net_t **, struct h_t *);
+
+extern vpiHandle __bld_port_iterator(struct h_t *);
+extern vpiHandle __bld_neticonn_iter(struct h_t *);
+extern vpiHandle __bld_paramassign_stmt_iter(struct h_t *);
+extern vpiHandle __bld_udpline_iter(struct h_t *);
+extern vpiHandle __bld_primterm_iterator(struct h_t *);
+extern vpiHandle __bld_loc_lds_iterator(struct h_t *, int32);
+extern vpiHandle __bld_lds_iterator(struct h_t *, int32);
+extern int32 __bld_xl_drvld_vtxtab(struct net_t *, int32, struct itree_t *, int32);
+extern vpiHandle __bld_loc_drvs_iterator(struct h_t *, int32);
+extern vpiHandle __bld_drvs_iterator(struct h_t *, int32);
+extern vpiHandle __bld_arrwrd_iterator(struct h_t *);
+extern vpiHandle __bld_paramwrd_iterator(struct h_t *);
+extern vpiHandle __bld_bitof_iterator(struct h_t *);
+extern vpiHandle __bld_systf_iterator(struct h_t *);
+extern vpiHandle __bld_tfargexpr_iterator(struct h_t *);
+extern vpiHandle __bld_pthterm_iterator(struct h_t *, word32);
+extern vpiHandle __bld_stmt_iterator(struct h_t *);
+extern vpiHandle __bld_netin_tchkterms(struct h_t *);
+extern vpiHandle __bld_netin_pthterms(struct h_t *);
+extern vpiHandle __bld_caseitems_iter(struct h_t *);
+extern vpiHandle __bld_casi_exprs_iter(struct h_t *);
+extern vpiHandle __bld_operands_iter(struct h_t *);
+extern vpiHandle __bld_allcbs_iter(struct h_t *);
+extern vpiHandle __bld_delay_expr_iter(struct h_t *);
+extern vpiHandle __bld_iodecl_stmt_iter(struct h_t *);
+extern struct task_t *__find_qualnam_task(char *, struct mod_t *,
+ struct task_t *);
+extern void __xmrpush_refgrp_to_targ(struct gref_t *);
+extern int32 __move_to_npprefloc(struct net_pin_t *);
+extern void __get_bidnpp_sect(struct net_t *, struct net_pin_t *, int32 *,
+ int32 *);
+extern int32 __exprtype_get(struct expr_t *);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern vpiHandle __nil_iter_err(word32);
+extern void __notstrpropof_err(word32, int32);
+extern struct pviter_t *__alloc_iter(int32, vpiHandle *);
+extern void __init_hrec(struct hrec_t *);
+extern void __grow_htab(int32);
+extern void __grow_htab2(int32);
+extern word32 __to_vpi_stmttyp(struct st_t **);
+extern int32 __ip_indsrch(char *);
+extern struct sy_t *__get_sym(char *, struct symtab_t *);
+extern struct sy_t *__get_nongia_sym(char *, struct symtab_t *);
+extern vpiHandle __mk_handle(word32, void *, struct itree_t *,
+ struct task_t *);
+extern int32 __is_scope_sym(struct sy_t *);
+extern word32 __to_vpi_tasktyp(word32);
+extern word32 __gate_to_vpiprimtyp(struct gate_t *);
+extern int32 __to_vpi_primtyp(struct gate_t *);
+extern int32 __primtermprop_vpiget(struct h_t *, int32);
+
+extern void __getarr_range(struct net_t *, int32 *, int32 *, int32 *);
+extern void __getwir_range(struct net_t *, int32 *, int32 *);
+extern int32 __get_arrwide(struct net_t *);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern char *__msgexpr_tostr(char *, struct expr_t *);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
+extern void __extract_delval(word64 *, int32 *, union del_u, word32);
+extern void __cnv_ticks_tonum64(word64 *, word64, struct mod_t *);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __ld_arr_val(register word32 *, register word32 *, union pck_u,
+ int32, int32, int32);
+extern struct expr_t *__bld_rng_numxpr(word32, word32, int32);
+extern char *__my_realloc(char *, int32, int32);
+extern void __my_free(char *, int32);
+extern char *__my_malloc(int32);
+extern int32 __unnormalize_ndx(struct net_t *, int32);
+extern int32 __to_vpi_netproptyp(word32 ntyp);
+extern struct expr_t *__glbnam_to_expr(char *);
+extern char *__to_glbcmp_nam(struct expr_t *);
+extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
+extern struct expr_t *__sim_alloc_newxnd(void);
+extern int32 __expr_is_vpiconst(struct expr_t *);
+extern char *__to_vpipnam(char *, int32);
+extern word32 __map_tovpi_stren(word32);
+extern char *__strab2_tostr(char *, word32 *, int32, int32, int32);
+extern int32 __name_vpi_hasdot(char *);
+extern void __free_iterator(vpiHandle);
+extern void __free_xtree(struct expr_t *);
+extern int32 __allocfill_cval_new(word32 *, word32 *, int32);
+extern struct attr_t *__find_attrspec(struct h_t *);
+
+extern void __arg_terr(char *, int32);
+extern void __vpi_terr(char *, int32);
+extern void __vpi_err(int32, int32, char *, ...);
+
+/* vpi only storage */
+extern struct t_vpi_error_info *__last_eip;/* if err, ptr to wrk eifo or nil */
+
+/*
+ * ROUTINES TO BUILD ITERATORS (2nd GROUP)
+ */
+
+/*
+ * build an expression from expr_t record
+ *
+ * this is shell that allocates empty handle and call v2 for filling it
+ * needed because need to fill only for building iterators containing exprs
+ *
+ * if allocated, caller must see xp free bit
+ */
+extern vpiHandle __mk_exprclass_handle(struct expr_t *xp,
+ struct itree_t *xin_itp, struct task_t *xin_tskp)
+{
+ vpiHandle href;
+ struct h_t *hp;
+
+ /* here vpiNet is just place holder - fixed by caller */
+ href = __mk_handle(vpiNet, NULL, xin_itp, xin_tskp);
+ hp = (struct h_t *) href;
+ mk2_exprclass_handle(hp, xp, xin_itp, xin_tskp);
+ return(href);
+}
+
+/*
+ * 
+ * here handle content are expressions - bit handle from iterators
+ * use different representation 
+ *
+ * select handles because they are not in handle index value
+ * must be expr. itree loc - when converting to net in must handle xmr 
+ * 
+ * this is version that expects handle to be allocated and filled
+ * (useful for filling iterator handles)
+ */
+static void mk2_exprclass_handle(struct h_t *hp,
+ struct expr_t *xp, struct itree_t *xin_itp, struct task_t *xin_tskp)
+{
+ register struct hrec_t *hrp;
+ int32 otyp, biti;
+ struct itree_t *xitp;
+ struct task_t *xtskp;
+ struct net_t *np;
+ struct expr_t *idndp;
+ struct sy_t *syp;
+
+ hrp = hp->hrec;
+ switch (xp->optyp) {
+  case ID:   
+   syp = xp->lu.sy;
+   xitp = xin_itp;
+   if (xp->locqualnam)
+    xtskp = __find_qualnam_task(xp->ru.qnchp, xin_itp->itip->imsym->el.emdp,
+     xin_tskp);
+   else xtskp = NULL;
+   goto fill_id_handle;
+  case GLBREF:
+   __push_itstk(xin_itp);
+   __xmrpush_refgrp_to_targ(xp->ru.grp);
+   xitp = __inst_ptr;
+   __pop_itstk();
+   __pop_itstk();
+   xtskp = xp->ru.grp->targtskp;
+
+   /* xmr expressions can also be scopes objects (i.e. not net/reg or var) */
+   syp = xp->lu.sy;
+   switch (syp->sytyp) {
+    case SYM_I: case SYM_M:
+     /* DBG remove -- */
+     if (xtskp != NULL) __vpi_terr(__FILE__, __LINE__);
+     /* --- */
+     hrp->htyp = vpiModule;
+     hrp->hu.hmdp = xitp->itip->imsym->el.emdp;
+     hp->hin_itp = xitp;
+     hrp->hin_tskp = NULL;
+     return;
+    /* notice function here must be function call */
+    case SYM_TSK: case SYM_LB:
+     { 
+      struct task_t *tskp;
+      struct symtab_t *sytp;
+
+      tskp = syp->el.etskp;
+      /* DBG remove --- */
+      if (tskp != xtskp) __vpi_terr(__FILE__, __LINE__);
+      /* --- */
+      hrp->htyp = __to_vpi_tasktyp(tskp->tsktyp);
+      hrp->hu.htskp = xtskp; 
+      hp->hin_itp = xitp;
+      sytp = xtskp->tsksymtab->sytpar;
+      /* DBG remove */
+      if (sytp == NULL) __vpi_terr(__FILE__, __LINE__); 
+      /* --- */
+      if (sytp->sypofsyt->sytyp != SYM_I)
+       xin_tskp = sytp->sypofsyt->el.etskp;
+      else xin_tskp = NULL;
+      hrp->hin_tskp = xin_tskp;
+     }
+     return;
+    default:
+     break;
+   }
+
+fill_id_handle:
+   /* this is both net/reg and variable (int32,real.time) but not bit select */
+   np = xp->lu.sy->el.enp;
+   otyp = __ntyp_to_vpivarhtyp(np);
+   hrp->htyp = otyp;
+   hrp->hu.hanyp = (void *) np;
+   hp->hin_itp = xitp;
+   hrp->hin_tskp = xtskp;
+   break;
+  case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM:
+   hrp->htyp = vpiConstant;
+   hrp->hu.hxp = xp;
+   goto fill_itloc;
+  case OPEMPTY:
+   /* this is vpi Null Op operation */
+   hrp->htyp = vpiOperation;
+   hrp->hu.hxp = xp;
+   goto fill_itloc;
+  case LSB:
+   idndp = xp->lu.x;
+   /* SJM 08/23/00 - branches never XMRs */ 
+   /* SJM 08/23/00 - if select from xmr, must change itree loc */
+   if (idndp->optyp == GLBREF)
+    {
+     __push_itstk(xin_itp);
+     __xmrpush_refgrp_to_targ(idndp->ru.grp);
+     xin_itp = __inst_ptr;
+     __pop_itstk();
+     __pop_itstk();
+     xin_tskp = idndp->ru.grp->targtskp;
+    }
+
+   np = idndp->lu.sy->el.enp;
+   if (np->n_isarr) hrp->htyp = vpiMemoryWord;
+   else hrp->htyp = __to_vpinetbithtyp(np->ntyp);
+   /* DBG remove -- */
+   /* must never see parameter bit select or parameter array index */
+   /* because must be converted to constant during translate/load */
+   if (np->n_isaparam) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+
+   /* try to optimize to bith ndx form */
+   if (!__expr_is_vpiconst(xp->ru.x))
+    {
+bld_expr_bsel:
+     hrp->hu.hxp = xp;
+     goto fill_itloc;
+    }
+   biti = __comp_ndx(np, xp->ru.x);
+   if (biti == -1) goto bld_expr_bsel; 
+   hrp->hu.hnp = np;
+   hrp->hi = biti;
+   hrp->bith_ndx = TRUE;
+   goto fill_itloc;
+  case PARTSEL:
+   hrp->htyp = vpiPartSelect;
+   hrp->hu.hxp = xp;
+   /* SJM 08/23/00 - if xmr part select, must change itree loc */
+   if (xp->lu.x->optyp == GLBREF)
+    {
+     idndp = xp->lu.x;
+     __push_itstk(xin_itp);
+     __xmrpush_refgrp_to_targ(idndp->ru.grp);
+     xin_itp = __inst_ptr;
+     __pop_itstk();
+     __pop_itstk();
+     xin_tskp = idndp->ru.grp->targtskp;
+    }
+   goto fill_itloc;
+  case FCALL:
+   if (xp->lu.x->lu.sy->sytyp == SYM_SF) hrp->htyp = vpiSysFuncCall;
+   else
+    {
+     /* SJM 08/23/00 - if xmr user fcall, must change itree loc */
+     if (xp->lu.x->optyp == GLBREF)
+      {
+       idndp = xp->lu.x;
+       __push_itstk(xin_itp);
+       __xmrpush_refgrp_to_targ(idndp->ru.grp);
+       xin_itp = __inst_ptr;
+       __pop_itstk();
+       __pop_itstk();
+       xin_tskp = idndp->ru.grp->targtskp;
+      }
+     hrp->htyp = vpiFuncCall;
+    }
+   hrp->hu.hxp = xp;
+   goto fill_itloc;
+  default:
+   hrp->htyp = vpiOperation;
+   hrp->hu.hxp = xp;
+fill_itloc:
+   hp->hin_itp = xin_itp;
+   hrp->hin_tskp = xin_tskp;
+  }
+}
+
+/*
+ * build a parameter assign statement iterator
+ *
+ * this is internally same as parameter (gets valus from net)
+ *
+ * FIXME - not handle left hand side select parameter assigns in PLI
+ */
+extern vpiHandle __bld_paramassign_stmt_iter(struct h_t *hp)
+{
+ register int32 pi;
+ register struct h_t *hp2;
+ register struct hrec_t *hrp2, *hrp;
+ int32 nparams; 
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+
+ if (hp == NULL)
+  {
+   return(__nil_iter_err(vpiParamAssign));
+  }
+
+ ihref = NULL;
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiModule: 
+   if ((nparams = mdp->mprmnum) <= 0) return(NULL);
+   iterp = __alloc_iter(nparams, &ihref);
+   for (pi = 0; pi < nparams; pi++)
+    {
+     hp2 = &(iterp->scanhtab[pi]);
+     hrp2 = hp2->hrec;
+     hrp2->htyp = vpiParamAssign;
+     hrp2->hu.hnp = &(mdp->mprms[pi]);
+     hp2->hin_itp = hp->hin_itp;
+    }
+   break;
+  case vpiTask: case vpiFunction:
+   tskp = hrp->hu.htskp;
+bld_tskiter:
+   if ((nparams = tskp->tprmnum) <= 0) return(NULL);
+   iterp = __alloc_iter(nparams, &ihref);
+   for (pi = 0; pi < nparams; pi++)
+    {
+     hp2 = &(iterp->scanhtab[pi]);
+     hrp2 = hp2->hrec;
+     hrp2->htyp = vpiParamAssign;
+     hrp2->hu.hnp = &(tskp->tsk_prms[pi]);
+     hp2->hin_itp = hp->hin_itp;
+     hrp2->hin_tskp = tskp;
+    }
+   break;
+  case vpiNamedBegin: case vpiNamedFork:
+   tskp = hrp->hu.htskp;
+   goto bld_tskiter;
+  default:
+   __vpi_err(1851, vpiError,
+    "unable to construct vpiParamAssign iterator for %s object",
+     __to_vpionam(__wrks2, hrp->htyp));
+ }
+ return(ihref);
+}
+
+
+/*
+ * build a IO decl iterator
+ *
+ * this is internally same as parameter (property values from net_t)
+ */
+extern vpiHandle __bld_iodecl_stmt_iter(struct h_t *hp)
+{
+ register int32 ni, nports; 
+ register struct h_t *hp2;
+ register struct net_t *np;
+ register struct hrec_t *hrp2; 
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct mod_t *mdp;
+ struct task_t *tskp;
+ struct udp_t *udpp;
+ struct mod_pin_t *mpp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiIODecl));
+ ihref = NULL;
+ switch (hp->hrec->htyp) {
+  case vpiModule: 
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   /* module port is normal net form */
+   np = &(mdp->mnets[0]);
+   for (nports = 0; nports < mdp->mnnum; nports++, np++)
+    { if (np->iotyp != NON_IO) nports++; }
+   if (nports <= 0) return(NULL);
+
+   iterp = __alloc_iter(nports, &ihref);
+   np = &(mdp->mnets[0]);
+   for (nports = 0, ni = 0; nports < mdp->mnnum; nports++, np++)
+    {
+     if (np->iotyp != NON_IO) continue;
+
+     hp2 = &(iterp->scanhtab[ni]);
+     hrp2 = hp2->hrec;
+     hrp2->htyp = vpiIODecl;
+     hrp2->hu.hnp = np;
+     hp2->hin_itp = hp->hin_itp;
+     ni++;
+    }
+   break;
+  case vpiTask: case vpiFunction:
+   /* normal io decl handle is net - alt form only for udp is mod_port */
+   tskp = hp->hrec->hu.htskp;
+bld_tsk_iodecls:
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   np = &(tskp->tsk_regs[0]);
+   for (nports = 0, ni = 0; ni < tskp->trnum; nports++, np++)
+    { if (np->iotyp != NON_IO) nports++; }
+   if (nports <= 0) return(NULL);
+
+   iterp = __alloc_iter(nports, &ihref);
+   np = &(tskp->tsk_regs[0]);
+   for (nports = 0, ni = 0; nports < tskp->trnum; nports++, np++)
+    {
+     if (np->iotyp != NON_IO) continue;
+
+     hp2 = &(iterp->scanhtab[ni]);
+     hrp2 = hp2->hrec;
+     hrp2->htyp = vpiIODecl;
+     hrp2->hu.hnp = np;
+     hp2->hin_itp = hp->hin_itp;
+     hrp2->hin_tskp = tskp;
+     ni++;
+    }
+   break;
+  case vpiNamedBegin: case vpiNamedFork:
+   tskp = hp->hrec->hu.htskp;
+   goto bld_tsk_iodecls;
+  case vpiUdpDefn:
+   /* here io decl port is alternative mod port form */ 
+   /* LOOKATME - maybe should change Cver d.s. to store udp ports as nets */
+   udpp = hp->hrec->hu.hudpp; 
+   /* DBG remove --- */
+   if (hp->hin_itp != NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   for (nports = 0, mpp = udpp->upins; mpp != NULL; mpp = mpp->mpnxt)
+    {
+     /* DBG remove --- */
+     if (mpp->mptyp == IO_UNKN || mpp->mptyp == IO_BID)
+      __vpi_terr(__FILE__, __LINE__);    
+     /* --- */
+     nports++;
+    }
+   /* DBG remove --- */
+   if (nports <= 0) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   iterp = __alloc_iter(nports, &ihref);
+   for (nports = 0, mpp = udpp->upins; mpp != NULL; mpp = mpp->mpnxt,
+    nports++)
+    {
+     hp2 = &(iterp->scanhtab[nports]);
+     hrp2 = hp2->hrec;
+     hrp2->htyp = vpiIODecl;
+     /* this must be actual udp port, not index since no table as with mod */
+     hrp2->hu.hmpp = mpp;
+     /* use unused itp field to point to containing */
+     hp2->hin_itp = (struct itree_t *) udpp;
+     /* alt form for io decl indicates in udp */
+     hrp2->htyp2 = vpiUdpDefn;
+    }
+   break;
+  default:
+   __vpi_err(1851, vpiError,
+    "unable to construct vpiIODecl iterator for %s object",
+    __to_vpionam(__wrks2, hp->hrec->htyp));
+ }
+ return(ihref);
+}
+
+/*
+ * build a udp table line iterator
+ *
+ * note in Cver get value can only get string form - user must decompose
+ */
+extern vpiHandle __bld_udpline_iter(struct h_t *rhp)
+{
+ register int32 uli;
+ register struct utline_t *utlp;
+ register struct hrec_t *hrp; 
+ int32 nulines;
+ vpiHandle ihref;
+ struct udp_t *udpp;
+ struct h_t *hp; 
+ struct pviter_t *iterp;
+
+ if (rhp == NULL) return(__nil_iter_err(vpiTableEntry));
+ if (rhp->hrec->htyp != vpiUdpDefn)
+  {
+   __vpi_err(1838, vpiError,
+    "vpiTableEntry type 1-to-many iterator requires vpiUdpDefn object - %s illegal",
+    __to_vpionam(__wrks1, rhp->hrec->htyp));
+   return(NULL);
+  }
+ udpp = rhp->hrec->hu.hudpp;
+ for (nulines = 0, utlp = udpp->utlines; utlp != NULL; utlp = utlp->utlnxt) 
+  nulines++;
+ /* this empty udp legal */
+ if (nulines <= 0) return(NULL);
+
+ /* build the design wide iterator of all udps */
+ iterp = __alloc_iter(nulines, &ihref);
+ for (uli = 0, utlp = udpp->utlines; utlp != NULL; utlp = utlp->utlnxt, uli++) 
+  {
+   hp = &(iterp->scanhtab[uli]);
+   hrp = hp->hrec;
+   hrp->htyp = vpiTableEntry;
+   hrp->hu.hutlp = utlp;  
+   hp->hin_itp = (struct itree_t *) udpp;
+   hrp->hi = uli;
+  }
+ return(ihref);
+}
+
+/*
+ * build an iterator for every word32 in array
+ *
+ * notice this builds a handle for every word32 better for large
+ * few bit (1) arrays to use vpi_handle_by_index
+ *
+ * in order to get parent of this handle, need to look at handle in 
+ * iterator - only way to build arrword or vector bit handle
+ */
+extern vpiHandle __bld_arrwrd_iterator(struct h_t *hp)
+{
+ register int32 ai, iti;
+ register struct hrec_t *hrp2; 
+ int32 awid;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct h_t *hp2;
+ struct pviter_t *iterp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiMemoryWord));
+ if (hp->hrec->htyp != vpiMemory) 
+  {
+   __vpi_err(1857, vpiError,
+    "vpiMemoryWord 1-to-many iterator from object %s illegal - must be vpiMemory",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ /* know hp is array (not array word32) handle */  
+ np = hp->hrec->hu.hnp;
+ awid = __get_arrwide(np);
+ /* DBG remove --- */
+ if (awid <= 0) __vpi_terr(__FILE__, __LINE__);
+ /* --- */ 
+ iterp = __alloc_iter(awid, &ihref);
+ for (iti = 0, ai = awid - 1; ai >= 0; ai--, iti++) 
+  {
+   hp2 = &(iterp->scanhtab[iti]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiMemoryWord;
+   hrp2->hu.hnp = np;
+   hrp2->hi = ai;
+   hrp2->bith_ndx = TRUE;
+   hp2->hin_itp = hp->hin_itp;
+   hrp2->hin_tskp = hp->hrec->hin_tskp;
+  }
+ return(ihref);
+}
+
+/*
+ * build an iterator for every word32 (cell) in parameter array
+ */
+extern vpiHandle __bld_paramwrd_iterator(struct h_t *hp)
+{
+ register int32 ai, iti;
+ register struct hrec_t *hrp2; 
+ int32 awid;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct h_t *hp2;
+ struct pviter_t *iterp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiParamArrayWord));
+ if (hp->hrec->htyp != vpiParamArray) 
+  {
+   __vpi_err(1857, vpiError,
+    "vpiParamArrayWord 1-to-many iterator from object %s illegal - must be vpiParamArray",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ /* know hp is array (not array word32) handle */  
+ np = hp->hrec->hu.hnp;
+ awid = __get_arrwide(np);
+ /* DBG remove --- */
+ if (awid <= 0) __vpi_terr(__FILE__, __LINE__);
+ /* --- */ 
+ iterp = __alloc_iter(awid, &ihref);
+ for (iti = 0, ai = awid - 1; ai >= 0; ai--, iti++) 
+  {
+   hp2 = &(iterp->scanhtab[iti]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiParamArrayWord;
+   hrp2->hu.hnp = np;
+   hrp2->hi = ai;
+   hrp2->bith_ndx = TRUE;
+   hp2->hin_itp = hp->hin_itp;
+   hrp2->hin_tskp = hp->hrec->hin_tskp;
+  }
+ return(ihref);
+}
+
+/*
+ * build an iterator for every bit of a reg or net or associated object
+ * 
+ * also for ports, wire drivers for vectored nets, and scheduled wire driver
+ * put value events
+ *
+ * notice there is no one-to-many connection for vpi_ driver to bit driver
+ */
+extern vpiHandle __bld_bitof_iterator(struct h_t *hp)
+{
+ register int32 i, iti;
+ register struct hrec_t *hrp2; 
+ vpiHandle ihref;
+ struct net_t *np;
+ struct h_t *hp2;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp; 
+ struct pviter_t *iterp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiBit));
+ switch (hp->hrec->htyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   np = hp->hrec->hu.hnp;
+   if (!np->n_isavec) return(NULL);
+   /* know nwid never 0 or will not get here */
+   iterp = __alloc_iter(np->nwid, &ihref);
+   /* SJM - 06/14/99 - need 2 indices since bit of always [h:l] order */
+   for (i = np->nwid - 1, iti = 0; i >= 0; i--, iti++) 
+    {
+     hp2 = &(iterp->scanhtab[iti]);
+     hrp2 = hp2->hrec;
+     hrp2->htyp = __to_vpinetbithtyp(np->ntyp);
+     hrp2->hu.hnp = np;
+     hrp2->hi = i;
+     hrp2->bith_ndx = TRUE;
+     hp2->hin_itp = hp->hin_itp;
+     hrp2->hin_tskp = hp->hrec->hin_tskp;
+    }
+   break;
+  case vpiPort:  
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
+   /* returns nil for scalar port - no bits */
+   if (mpp->mpwide == 1) return(NULL);
+   iterp = __alloc_iter(mpp->mpwide, &ihref);
+   /* for port bit handles itp determines port list, hu.hpi port, and hi */
+   /* must be h:0 to match bits of connected vector */
+   /* SJM - 06/14/99 - need 2 indices since bit of always [h:l] order */
+   for (i = mpp->mpwide - 1, iti = 0; i >= 0; i--, iti++)
+    {
+     hp2 = &(iterp->scanhtab[iti]);
+     hrp2 = hp2->hrec;
+     hrp2->htyp = vpiPortBit;
+     hrp2->hu.hpi = hp->hrec->hu.hpi;
+     hrp2->hi = i;
+     hp2->hin_itp = hp->hin_itp;
+     hrp2->hin_tskp = hp->hrec->hin_tskp;
+    }
+   break;   
+  default:
+   __vpi_err(1859, vpiError,
+    "vpiBit 1-to-many iterator from object %s illegal",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ return(ihref);
+}
+
+/*
+ * build iterator of primitive (gate) terminals
+ *
+ * notice needed so parent is primitive (gate) not scope
+ */
+extern vpiHandle __bld_primterm_iterator(struct h_t *hp)
+{
+ register int32 pi;
+ register struct hrec_t *hrp2; 
+ vpiHandle ihref;
+ struct gate_t *gp;
+ struct itree_t *itp;
+ struct h_t *hp2;
+ struct hrec_t *hrp;
+ struct pviter_t *iterp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiPrimTerm));
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiGate && hrp->htyp != vpiUdp && hrp->htyp != vpiSwitch) 
+  {
+   __vpi_err(1855, vpiError,
+    "vpiPrimTerm 1-to-many iterator from %s illegal - member of primitive class required",
+    __to_vpionam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ gp = hrp->hu.hgp;
+ itp = hp->hin_itp;
+ /* DBG remove --- */
+ if (gp->gpnum == 0) __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+ iterp = __alloc_iter((int32) gp->gpnum, &ihref);
+ for (pi = 0; pi < (int32) gp->gpnum; pi++) 
+  {
+   hp2 = &(iterp->scanhtab[pi]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiPrimTerm;
+   hrp2->hi = pi;
+   hrp2->hu.hgp = gp;
+   hp2->hin_itp = itp;
+  }
+ return(ihref);
+}
+
+
+/*
+ * build iterators for vpi Port selector
+ *
+ * iterator for reg/wire is all in module ports that the handle connects to
+ */
+extern vpiHandle __bld_port_iterator(struct h_t *hp)
+{
+ if (hp == NULL) return(__nil_iter_err(vpiPort));
+ switch (hp->hrec->htyp) {
+  case vpiModule: return(bld_inmod_port_iter(hp));
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   /* iterator is usually 1 port net connects to (only more if jumpered) */
+   /* this returns port handles even if selects (i.e. any overlap) */
+   return(bld_netmdport_iter(hp));
+  case vpiNetBit: case vpiRegBit: case vpiVarSelect:
+   /* iterator is usually the one port the bit connects to */
+   /* this returns port bit handles for the one bit */
+   return(bld_netbitmdport_iter(hp));
+  default:
+   __vpi_err(1861, vpiError,
+    "vpiPort 1-to-many iterator from %s illegal - for in module or hiconn module ports",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+  }  
+ return(NULL);
+}
+
+/*
+ * build ports in module iterator (easiest)
+ * since in module and have inst. do not need parent handle 
+ */
+static vpiHandle bld_inmod_port_iter(struct h_t *hp)
+{
+ register int32 pi;
+ register struct h_t *hp2;
+ register struct hrec_t *hrp2; 
+ struct mod_t *mdp;
+ struct itree_t *itp; 
+ struct pviter_t *iterp;
+ vpiHandle ihref;
+
+ itp = hp->hin_itp;
+ mdp = itp->itip->imsym->el.emdp;
+ if (mdp->mpnum <= 0) return(NULL);
+ iterp = __alloc_iter(mdp->mpnum, &ihref);
+ for (pi = 0; pi < mdp->mpnum; pi++)
+  {
+   hp2 = &(iterp->scanhtab[pi]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiPort;
+   /* using index so can get instance port index too */
+   hrp2->hu.hpi = pi;
+   hp2->hin_itp = itp;
+  }
+ return(ihref);
+}
+
+/*
+ * build a statement iterator from a named or unnamed? block 
+ * unnamed blocks usually marked with bit (but S_UNLBK in fork-join) 
+ */
+extern vpiHandle __bld_stmt_iterator(struct h_t *hp)
+{
+ register struct hrec_t *hrp;
+ struct st_t *stp;
+ struct task_t *tskp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiStmt));
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiFork:
+   return(bld_fjlist_iter(hrp->hu.hstp, hp->hin_itp, hrp->hin_tskp));
+
+  case vpiBegin:
+   stp = hrp->hu.hstp;
+   /* this statement only for use in fork-join */
+   if (stp->stmttyp == S_UNBLK)
+    {
+     /* pass first statement of block */
+     stp = stp->st.sbsts;
+     /* here iterator is in same scope as unnamed block */
+     return(bld_listofstmts_iter(stp, hp->hin_itp, hrp->hin_tskp));
+    }
+   if (!stp->st_unbhead) __vpi_terr(__FILE__, __LINE__);
+   /* normal un-named block just has bit set in first statement */
+   return(bld_listofstmts_iter(stp, hp->hin_itp, hrp->hin_tskp));
+
+  case vpiNamedFork:
+   tskp = hrp->hu.htskp;
+   return(bld_fjlist_iter(tskp->tskst, hp->hin_itp, tskp));
+   
+  case vpiNamedBegin:
+   tskp = hrp->hu.htskp;
+   /* here these are in the named block scope not the task stmt */
+   /* notice hin taskp is name block task itself */
+   return(bld_listofstmts_iter(tskp->tskst, hp->hin_itp, tskp));
+  default:
+   __vpi_err(1869, vpiError,
+    "vpiStmt 1-to-many iterator from %s illegal - for blocks only",
+   __to_vpionam(__wrks1, hrp->htyp));
+ }  
+ return(NULL);
+}
+
+/*
+ * build a fork-join iterator - each statement from list
+ */
+static vpiHandle bld_fjlist_iter(struct st_t *stp, struct itree_t *itp,
+ struct task_t *tskp)
+{
+ register int32 si, fji;
+ register struct st_t *fjstp;
+ int32 snum;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct h_t *hp;
+ struct hrec_t *hrp; 
+ struct st_t *stp3;
+
+ /* these do not go into iterators */
+ for (snum = fji = 0;; fji++)
+  {
+   if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+
+   /* DBG remove -- */
+   /* think can not have goto here */
+   if (fjstp->rl_stmttyp == S_GOTO) __vpi_terr(__FILE__, __LINE__); 
+   /* -- */
+   /* SJM 09/24/01 - for these inserted stmts, add next to iterator */
+   if (fjstp->rl_stmttyp == S_REPSETUP || fjstp->rl_stmttyp == S_FORASSGN
+    || fjstp->rl_stmttyp == S_REPDCSETUP) fjstp = fjstp->stnxt;
+   snum++;
+  }
+
+ /* LOOKATME - can this be none */
+ if (snum <= 0) return(NULL);
+
+ iterp = __alloc_iter(snum, &ihref);
+ for (fji = 0, si = 0;; fji++, si++)
+  {
+   if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
+
+   /* these do not go into iterator */
+   /* SJM 09/24/01 - for these inserted stmts, add next to iterator */
+   if (fjstp->rl_stmttyp == S_REPSETUP || fjstp->rl_stmttyp == S_FORASSGN
+    || fjstp->rl_stmttyp == S_REPDCSETUP) fjstp = fjstp->stnxt;
+
+   hp = &(iterp->scanhtab[si]);
+   stp3 = fjstp;
+   hrp = hp->hrec;
+   hrp->htyp = __to_vpi_stmttyp(&stp3);
+
+   /* skipping special setup stmts, no need to use next */
+   if (hrp->htyp == vpiNamedBegin || hrp->htyp == vpiNamedFork)
+    hrp->hu.htskp = fjstp->st.snbtsk;
+   else hrp->hu.hstp = fjstp;
+
+   hp->hin_itp = itp;
+   hrp->hin_tskp = tskp;
+  }
+ return(ihref);
+}
+
+/*
+ * build statement iterator from the first statement
+ */
+static vpiHandle bld_listofstmts_iter(struct st_t *stp, struct itree_t *itp,
+ struct task_t *in_tskp)
+{
+ register int32 si;
+ register struct st_t *stp2;
+ register struct hrec_t *hrp; 
+ int32 snum;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct h_t *hp;
+ struct st_t *stp3;
+
+ for (snum = 0, stp2 = stp; stp2 != NULL; stp2 = stp2->stnxt)
+  {
+   if (stp2->rl_stmttyp == S_GOTO) break;
+   if (stp2->rl_stmttyp == S_REPSETUP || stp2->rl_stmttyp == S_FORASSGN
+    || stp2->rl_stmttyp == S_REPDCSETUP) continue;
+   snum++;
+  }
+ /* LOOKATME - can this be none */
+ if (snum <= 0) return(NULL);
+ iterp = __alloc_iter(snum, &ihref);
+ for (stp2 = stp, si = 0; stp2 != NULL; stp2 = stp2->stnxt)  
+  {
+   if (stp2->rl_stmttyp == S_GOTO) break;
+   /* these do not go into iterators */
+   if (stp2->rl_stmttyp == S_REPSETUP || stp2->rl_stmttyp == S_FORASSGN
+    || stp2->rl_stmttyp == S_REPDCSETUP)
+    continue;
+
+   /* his works for named begin and fj blocks because hu if statement */
+   /* links in d.s. for going between 2 */
+   hp = &(iterp->scanhtab[si++]);
+   hrp = hp->hrec;
+   /* know will never be for assign or repeat where need to move to nxt */
+   stp3 = stp2;
+   hrp->htyp = __to_vpi_stmttyp(&stp3);
+
+   /* skipping special setup stmts, no need to use next */
+   if (hrp->htyp == vpiNamedBegin || hrp->htyp == vpiNamedFork)
+    hrp->hu.htskp = stp2->st.snbtsk;
+   else hrp->hu.hstp = stp2;
+
+   hp->hin_itp = itp;
+   hrp->hin_tskp = in_tskp;
+  }
+ return(ihref);
+}
+
+/*
+ * convert from v.h stmt type to handle constant for stmt class
+ *
+ * tricky because for for assign and repeat setup added pseudo
+ * statements must move to next and return type of next, i.e. the repeat
+ * or for statement itself 
+ *
+ * here ignore unnamed block header since know only called for block contents
+ */
+extern word32 __to_vpi_stmttyp(struct st_t **stpp)
+{
+ struct task_t *tskp;
+ struct st_t *stp;
+ 
+ stp = *stpp;
+ switch ((byte) stp->stmttyp) {
+  /* blocks statements */
+  case S_NAMBLK:
+   /* use task type for statement type */
+   tskp = stp->st.snbtsk;
+   if (tskp->tsktyp == FORK) return(vpiNamedFork);
+   if (tskp->tsktyp == Begin) return(vpiNamedBegin);
+   __vpi_terr(__FILE__, __LINE__); 
+   break;
+  case S_UNBLK: return(vpiBegin);
+  /* the statement is the header that points to the contents fj stlst */
+  case S_UNFJ: return(vpiFork);
+
+  /* atomic statements */
+  case S_IF: 
+   if (stp->st.sif.elsest == NULL) return(vpiIf);
+   return(vpiIfElse);
+  case S_WHILE: return(vpiWhile);
+  case S_FOREVER: return(vpiForever);
+  case S_REPEAT: return(vpiRepeat);
+  case S_WAIT: return(vpiWait);
+  case S_CASE: return(vpiCase);
+  case S_FOR: return(vpiFor);
+  case S_REPDCSETUP:
+   *stpp = stp->stnxt;
+   /* DBG remove --- */
+   if (stp->stnxt == NULL) __vpi_terr(__FILE__, __LINE__);
+   if (stp->stnxt->stmttyp == S_FORASSGN || stp->stnxt->stmttyp == S_REPSETUP
+    || stp->stnxt->stmttyp == S_REPDCSETUP)
+    __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   /* this is always assign mayhbe non blocking or rhs dctrl */
+   return(vpiAssignment);
+  case S_DELCTRL:
+   if (stp->st.sdc->dctyp == DC_DELAY) return(vpiDelayControl);
+   if (stp->st.sdc->dctyp == DC_EVENT) return(vpiEventControl);
+   if (stp->st.sdc->dctyp == DC_RHSEVENT ||
+    stp->st.sdc->dctyp == DC_RHSDELAY) return(vpiAssignment);
+   __vpi_terr(__FILE__, __LINE__);
+   break;
+  case S_CAUSE: return(vpiEventStmt);
+  /* properties in vpi_ distinguish */
+  case S_PROCA: case S_NBPROCA: case S_RHSDEPROCA:
+   return(vpiAssignment);
+  case S_FORASSGN:
+   /* need the following for - always followed by for */
+   *stpp = stp->stnxt;
+   /* DBG remove --- */
+   if (stp->stnxt == NULL) __vpi_terr(__FILE__, __LINE__);
+   if (stp->stnxt->stmttyp == S_FORASSGN || stp->stnxt->stmttyp == S_REPSETUP
+    || stp->stnxt->stmttyp == S_REPDCSETUP)
+    __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   return(vpiFor);
+  case S_REPSETUP:
+   *stpp = stp->stnxt;
+   /* DBG remove --- */
+   if (stp->stnxt == NULL) __vpi_terr(__FILE__, __LINE__);
+   if (stp->stnxt->stmttyp == S_FORASSGN || stp->stnxt->stmttyp == S_REPSETUP
+    || stp->stnxt->stmttyp == S_REPDCSETUP)
+    __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   return(vpiRepeat);
+  case S_QCONTA:
+   if (stp->st.sqca->qcatyp == ASSIGN) return(vpiAssignStmt);
+   if (stp->st.sqca->qcatyp == FORCE) return(vpiForce);
+   __vpi_terr(__FILE__, __LINE__);
+   break;
+  case S_QCONTDEA:
+   if (stp->st.sqcdea.qcdatyp == DEASSIGN) return(vpiRelease);
+   if (stp->st.sqcdea.qcdatyp == RELEASE) return(vpiDeassign);
+   __vpi_terr(__FILE__, __LINE__);
+   break;
+  case S_DSABLE: return(vpiDisable);
+  case S_TSKCALL:
+   if (stp->st.stkc.tsksyx->lu.sy->sytyp == SYM_STSK) return(vpiSysTaskCall);
+   return(vpiTaskCall);
+
+  case S_NULL: case S_STNONE: return(vpiNullStmt);
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(0);
+}
+
+/*
+ * build the top level all vpi_ systf iterator
+ *
+ * original handles build from systf register not freeable but this
+ * iterator is
+ * notice only thing can do with handles in itertor is get systf info
+ */
+extern vpiHandle __bld_systf_iterator(struct h_t *hp)
+{
+ register int32 ti; 
+ register struct hrec_t *hrp2; 
+ int32 num_vpi_systfs;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct h_t *hp2;
+
+ if (hp != NULL)
+  {
+   __vpi_err(1866, vpiError,
+    "vpi_iterate for vpiUserSystf requires NULL handle - %s illegal",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  }
+ num_vpi_systfs = __last_systf - __last_veriusertf;
+ if (num_vpi_systfs <= 0) return(NULL);
+ iterp = __alloc_iter(num_vpi_systfs, &ihref);
+ for (ti = 0; ti < num_vpi_systfs; ti++)
+  {
+   hp2 = &(iterp->scanhtab[ti]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiUserSystf;
+   /* handle must be number (i.e. 1000 + tf_ number + pos.) */ 
+   hrp2->hi = __last_veriusertf + ti + 1; 
+   /* this handle does not have itree loc. since not the call */
+  }
+ return(ihref);
+}
+
+/*
+ * build task or function including system argument list iterator
+ */
+extern vpiHandle __bld_tfargexpr_iterator(struct h_t *hp)
+{
+ register struct hrec_t *hrp;
+ struct expr_t *argxp;
+ struct tskcall_t *tkcp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiArgument));
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  /* for func def. first argment is return value but for call 1st is arg */
+  case vpiFuncCall: case vpiSysFuncCall:
+   argxp = hrp->hu.hxp->ru.x;
+   if (argxp == NULL) return(NULL);
+   return(bld_listofexprs_iter(argxp, hp->hin_itp, hrp->hin_tskp));
+  case vpiTask: case vpiSysTaskCall:
+   tkcp = &(hrp->hu.hstp->st.stkc);
+   if (tkcp->targs == NULL) return(NULL);
+   return(bld_listofexprs_iter(tkcp->targs, hp->hin_itp, hrp->hin_tskp));
+  default:
+   __vpi_err(1879, vpiError,
+    "vpiArgument 1-to-many iterator from %s illegal - for tasks and functions",
+   __to_vpionam(__wrks1, hrp->htyp));
+ }
+ return(NULL);
+}
+
+/*
+ * build list of expressions iterator (know at least one or not called)
+ * passed with first arg - can be nil for no arguments
+ */
+static vpiHandle bld_listofexprs_iter(struct expr_t *argx, struct itree_t *itp,
+ struct task_t *tskp)
+{
+ register int32 xi, numxps;
+ register struct expr_t *xp2;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct h_t *hp;
+
+ /* know there will always be 1 */
+ for (numxps = 0, xp2 = argx; xp2 != NULL; xp2 = xp2->ru.x) numxps++;
+ if (numxps <= 0) return(NULL);
+ iterp = __alloc_iter(numxps, &ihref);
+ for (xp2 = argx, xi = 0; xp2 != NULL; xp2 = xp2->ru.x, xi++) 
+  {
+   hp = &(iterp->scanhtab[xi]);
+   /* expr. object can also be scopes if xmr object */
+   mk2_exprclass_handle(hp, xp2->lu.x, itp, tskp);
+  }
+ return(ihref);
+}
+
+/*
+ * ROUTINES TO BUILD TCHK AND PATH ITERATORS
+ */
+
+/*
+ * build a module specify path iterator (indices and three types)
+ */
+extern vpiHandle __bld_pthterm_iterator(struct h_t *hp, word32 itype)
+{
+ register int32 pi;
+ register struct hrec_t *hrp2; 
+ int32 numpes;
+ struct spcpth_t *pthp;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct h_t *hp2;
+ struct hrec_t *hrp;
+ struct expr_t *xp;
+
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiModPath)
+  {
+   __vpi_err(1858, vpiError,
+    "%s 1-to-many iterator requires vpiModPath reference handle - %s illegal",
+    __to_vpionam(__wrks1, itype), __to_vpionam(__wrks2, hrp->htyp));
+   return(NULL);
+  }
+ pthp = hrp->hu.hpthp;
+ if (itype == vpiModPathIn || itype == vpiModPathOut)
+  { 
+   if (itype == vpiModPathIn) numpes = pthp->last_pein + 1;
+   else numpes = pthp->last_peout + 1;
+   goto bld_iter;
+  }
+ /* know itype already checked */ 
+ /* DBG remove --- */ 
+ if (itype != vpiModDataPathIn) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ 
+ if ((xp = pthp->datasrcx) == NULL) return(NULL);
+
+ if (xp->optyp != FCCOM) numpes = 1;
+ /* FCCOM list */
+ else { for (numpes = 0; xp != NULL; xp = xp->ru.x) numpes++; }
+
+bld_iter:
+ if (numpes <= 0) return(NULL);
+ iterp = __alloc_iter(numpes, &ihref);
+ for (pi = 0; pi < numpes; pi++)
+  {
+   hp2 = &(iterp->scanhtab[pi]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiPathTerm;
+   hrp2->htyp2 = itype;
+   hrp2->hu.hpthp = pthp;
+   /* this is index, path term type determines how accessed */
+   hrp2->hi = pi;
+   hp2->hin_itp = hp->hin_itp;
+  }
+ return(ihref);
+}   
+
+/*
+ * routine to build iterator of vpi Tchk Terms that a net or bit is in
+ *
+ * notifier's not included since not really part of circuit (modeling addon)
+ * and no a terminal
+ * tchk terminals must be wires but not necessarily I/O ports
+ */
+extern vpiHandle __bld_netin_tchkterms(struct h_t *hp)
+{
+ register int32 hi;
+ register struct hrec_t *hrp;
+ int32 ndx, nterms;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct pviter_t *iterp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiTchkTerm));
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiNet && hrp->htyp != vpiNetBit)
+  {
+bad_bit:
+   __vpi_err(1872, vpiError,
+    "vpiTchkTerm 1-to-many iterator from %s illegal - vpiNet or constant vpiNetBit only",
+    __to_vpionam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ if (hrp->htyp == vpiNetBit)
+  {
+   if (!hrp->bith_ndx) goto bad_bit;
+   ndx = hrp->hi;
+  }
+ else ndx = -1;
+ np = hrp->hu.hnp;
+
+ nterms = bld_net_tchkterms(np, (struct itree_t *) hp->hin_itp, ndx);
+ if (nterms <= 0) return(NULL);
+
+ iterp = __alloc_iter(nterms, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, nterms*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, nterms*sizeof(struct hrec_t));
+
+ for (hi = 0; hi < nterms; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+}
+
+/*
+ * build timing check terminals connected to net index ndx 
+ *
+ * -1 for all of wire
+ */
+static int32 bld_net_tchkterms(struct net_t *np, struct itree_t *itp, int32 ndx)
+{
+ register int32 cnt;
+ register struct net_pin_t *npp; 
+ register struct h_t *hp2;
+ register struct hrec_t *hrp2; 
+ struct tchk_t *tcp;
+ struct tchg_t *tchgp;
+
+ __push_itstk(itp);
+ /* for net bit, if any bit in range then entire terminal */
+ for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->npntyp != NP_TCHG) continue;
+
+   /* will be one for each event, since just need tchk use only start ev */
+   if (npp->chgsubtyp != NPCHG_TCSTART) continue;
+
+   /* know tchk terminals are wires or selects (not globals) */
+   tchgp = npp->elnpp.etchgp;
+   tcp = tchgp->chgu.chgtcp;
+   if (termexpr_matches(tcp->startxp, np, ndx))
+    {
+     if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+     hp2 = &(__ithtab[cnt]);
+     hp2->hin_itp = itp;
+
+     hrp2 = &(__ithrectab[cnt++]);
+     __init_hrec(hrp2);
+     /* not using alloc iter so need to set in iter bit explicitly */
+     hrp2->in_iter = TRUE;
+     hrp2->htyp = vpiTchkTerm;
+     hrp2->htyp2 = vpiTchkRefTerm;
+     hrp2->hu.htcp = tcp; 
+     /* only need to set cross link in newly added one */
+     hp2->hrec = hrp2;
+    }
+   if (termexpr_matches(tcp->chkxp, np, ndx))
+    {
+     if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+     hp2 = &(__ithtab[cnt]);
+     hp2->hin_itp = itp;
+
+     hrp2 = &(__ithrectab[cnt++]);
+     __init_hrec(hrp2);
+     hrp2->in_iter = TRUE;
+     hrp2->htyp = vpiTchkTerm;
+     hrp2->htyp2 = vpiTchkDataTerm;
+     hrp2->hu.htcp = tcp; 
+     /* only need to set cross link in newly added one */
+     hp2->hrec = hrp2;
+    }
+  }
+ __pop_itstk();
+ return(cnt);
+}
+
+/*
+ * return T if term matches net and bit (ndx == -1 for all)
+ *
+ * this require itree context to be pushed onto itstk
+ */
+static int32 termexpr_matches(struct expr_t *xp, struct net_t *np, int32 ndx)
+{
+ int32 bi1, bi2;
+ struct net_t *np2;
+
+ if (xp == NULL) return(FALSE);
+ if (xp->optyp == ID)
+  {
+   if (xp->lu.sy->el.enp == np) return(TRUE);
+   return(FALSE);
+  }
+ if (xp->optyp == LSB)
+  {
+   np2 = xp->lu.x->lu.sy->el.enp;
+   if (np != np2) return(FALSE);
+   if (ndx == -1) return(TRUE);
+   bi1 = __comp_ndx(np, xp->ru.x);
+   if (bi1 == ndx) return(TRUE);
+   return(FALSE);
+  }
+ else if (xp->optyp == PARTSEL)
+  {
+   np2 = xp->lu.x->lu.sy->el.enp;
+   if (np != np2) return(FALSE);
+   if (ndx == -1) return(TRUE);
+   bi1 = (int32) __contab[xp->ru.x->lu.x->ru.xvi];
+   bi2 = (int32) __contab[xp->ru.x->ru.x->ru.xvi];
+   if (ndx > bi1 || ndx < bi2) return(FALSE);
+   return(TRUE);
+  }
+ else __vpi_terr(__FILE__, __LINE__);
+ return(FALSE);
+}
+
+/*
+ * grow global work handle table (must add at least addnum)
+ */
+extern void __grow_htab(int32 addnum)
+{
+ register int32 iti;
+ int32 old_ithtsiz, nnum, osize, nsize, ohrsize, nhrsize;
+
+ /* only allocate if accessing driver/load style handles at all */ 
+ if (__ithtsiz == 0)
+  {
+   nnum = 1000 + addnum;
+   __ithtab = (struct h_t *) __my_malloc(nnum*sizeof(struct h_t));
+   __ithrectab = (struct hrec_t *) __my_malloc(nnum*sizeof(struct hrec_t));
+   __ithtsiz = nnum; 
+   return;
+  }
+ old_ithtsiz = __ithtsiz;
+ osize = old_ithtsiz*sizeof(struct h_t);
+ ohrsize = old_ithtsiz*sizeof(struct hrec_t);
+ __ithtsiz = addnum + (3*__ithtsiz)/2; 
+ nsize = __ithtsiz*sizeof(struct h_t);
+ nhrsize = __ithtsiz*sizeof(struct hrec_t);
+ __ithtab = (struct h_t *) __my_realloc((char *) __ithtab, osize, nsize);
+ __ithrectab = (struct hrec_t *) __my_realloc((char *) __ithrectab,
+  ohrsize, nhrsize);
+
+ /* SJM 10/23/00 - must reconnect all cross links in case relloced */
+ /* just need to reset all in previous copied part */
+ for (iti = 0; iti < old_ithtsiz; iti++)
+  { __ithtab[iti].hrec = &(__ithrectab[iti]); }
+}
+
+/*
+ * grow 2nd for subtree processing  global work handle table
+ */
+extern void __grow_htab2(int32 addnum)
+{
+ register int32 iti;
+ int32 old_ithtsiz2, nnum, osize, nsize, ohrsize, nhrsize;
+
+ /* only allocate if accessing driver/load style handles at all */ 
+ if (__ithtsiz2 == 0)
+  {
+   nnum = 1000 + addnum;
+   __ithtab2 = (struct h_t *) __my_malloc(nnum*sizeof(struct h_t));
+   __ithrectab2 = (struct hrec_t *) __my_malloc(nnum*sizeof(struct hrec_t));
+   __ithtsiz2 = nnum; 
+   return;
+  }
+ old_ithtsiz2 = __ithtsiz2;
+ osize = old_ithtsiz2*sizeof(struct h_t);
+ ohrsize = old_ithtsiz2*sizeof(struct hrec_t);
+ __ithtsiz2 = addnum + (3*__ithtsiz2)/2; 
+ nsize = __ithtsiz2*sizeof(struct h_t);
+ nhrsize = __ithtsiz2*sizeof(struct hrec_t);
+ __ithtab2 = (struct h_t *) __my_realloc((char *) __ithtab2, osize, nsize);
+ __ithrectab2 = (struct hrec_t *) __my_realloc((char *) __ithrectab2,
+  ohrsize, nhrsize);
+
+ /* SJM 10/23/00 - must reconnect all cross links in case relloced */
+ /* just need to reset all in previous copied part */
+ for (iti = 0; iti < old_ithtsiz2; iti++)
+  { __ithtab2[iti].hrec = &(__ithrectab2[iti]); }
+}
+
+/*
+ * routine to build iterator of vpi path src and dst terms net is in
+ * 
+ * vpiModDataPathTerm not include since not path source or dest (cond.)
+ * paths must be wires that are input/inout (source) and output/inout (dest)  
+ *
+ * path terms must be wires since input/inout are lvalues and path
+ * destinations need delays so must be wire
+ */
+extern vpiHandle __bld_netin_pthterms(struct h_t *hp)
+{
+ register int32 hi;
+ register struct hrec_t *hrp; 
+ int32 ndx, nterms;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct pviter_t *iterp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiPathTerm));
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiNet && hrp->htyp != vpiNetBit)
+  {
+bad_bit:
+   __vpi_err(1873, vpiError,
+    "vpiPathTerm 1-to-many iterator from %s illegal - vpiNet or vpiNetBit (constant) only",
+    __to_vpionam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ np = hrp->hu.hnp;
+ if (hrp->htyp == vpiNetBit)
+  {
+   /* know this is T unless variable select - only works for constants */
+   if (!hrp->bith_ndx) goto bad_bit;  
+   ndx = hrp->hi; 
+  }
+ else ndx = -1;
+
+ nterms = bld_net_pathterms(np, hp->hin_itp, ndx);
+ if (nterms <= 0) return(NULL);
+
+ iterp = __alloc_iter(nterms, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, nterms*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, nterms*sizeof(struct hrec_t));
+
+ for (hi = 0; hi < nterms; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+} 
+
+/*
+ * build path terminals connected to net index ndx 
+ *
+ * ndx -1 for all of wire
+ * on path sources and destinations here 
+ */
+static int32 bld_net_pathterms(struct net_t *np, struct itree_t *itp, int32 ndx)
+{
+ register int32 bi, pei;
+ register struct net_pin_t *npp; 
+ register struct pthdst_t *pdp;
+ register struct hrec_t *hrp2; 
+ int32 cnt, fr, to;
+ struct h_t *hp2;
+ struct h_t tmph;
+ struct hrec_t tmphrec;
+ struct tchg_t *tchgp;
+ struct spcpth_t *pthp;
+ struct pathel_t *pep;
+
+ /* for net bit, if any bit in range then entire source terminal */
+ /* first path sources - from path source load */
+ for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->npntyp != NP_TCHG) continue;
+   /* will be one for each event, since just need tchk use only start ev */
+   if (npp->chgsubtyp != NPCHG_PTHSRC) continue;
+
+   /* know tchk terminals are wires or selects (not globals) */
+   tchgp = npp->elnpp.etchgp;
+   pthp = tchgp->chgu.chgpthp;
+   for (pei = 0; pei <= pthp->last_pein; pei++)
+    {
+     pep = &(pthp->peins[pei]);
+     if (np != pep->penp) continue;
+     if (ndx != -1 && pep->pthi1 != -1 &&
+      (ndx > pep->pthi1 || ndx < pep->pthi2)) continue;
+
+     if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+     hp2 = &(__ithtab[cnt]);
+     hp2->hin_itp = itp;
+
+     hrp2 = &(__ithrectab[cnt++]);
+     __init_hrec(hrp2);
+     hrp2->in_iter = TRUE;
+     hrp2->htyp = vpiModPathIn;
+     hrp2->hu.hpthp = pthp;
+     hrp2->hi = pei;
+     /* only need to set cross link in newly added one */
+     hp2->hrec = hrp2;
+    }
+  }
+ /* path destinations (if any) are linked on wire */
+ if (np->n_isapthdst)
+  {
+   if (ndx == -1) { fr = 0; to = np->nwid - 1; } else fr = to = ndx;
+   for (bi = fr; bi <= to; bi++) 
+    {
+     pdp = np->nu.rngdwir->n_du.pb_pthdst[bi];
+     for (; pdp != NULL; pdp = pdp->pdnxt)
+      {
+       pthp = pdp->pstchgp->chgu.chgpthp;
+       for (pei = 0; pei <= pthp->last_peout; pei++)
+        {
+         pep = &(pthp->peouts[pei]);
+         if (ndx != -1 && pep->pthi1 != -1 &&
+          (ndx > pep->pthi1 || ndx < pep->pthi2)) continue;
+
+         __init_hrec(&tmphrec);
+         tmphrec.htyp = vpiModPathOut;
+         tmphrec.hu.hpthp = pthp;
+         tmphrec.hi = pei;
+         tmph.hin_itp = itp;
+         /* need to set in iter bit */
+         tmphrec.in_iter = TRUE;
+         tmph.hrec = &tmphrec;
+
+         /* if duplicated do not add */
+         if (cnt != 0 && same_vpi_handle(__ithtab, 0, cnt, &tmph, &tmphrec))
+          continue;
+         if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+         hp2 = &(__ithtab[cnt]);
+         hp2->hin_itp = tmph.hin_itp;
+
+         hrp2 = &(__ithrectab[cnt++]);
+         memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
+         /* only need to set cross link in newly added one */
+         hp2->hrec = hrp2;
+        }
+      }
+    }
+  }
+ return(cnt);
+}
+
+/*
+ * build a delay expression iterator - this is value that appears in source
+ *
+ * except in cver returns expression of the latest back annotated value
+ * not the original source
+ *
+ * FIXME - for vpiDelayControl should be one to one expr op. not iterator?
+ */
+extern vpiHandle __bld_delay_expr_iter(struct h_t *rhp)
+{
+ register struct hrec_t *rhrp;
+ register int32 hi;
+ int32 ndels, ndels2;
+ vpiHandle ihref;
+ struct h_t tmph;
+ struct gate_t *gp;
+ struct spcpth_t *pthp;
+ struct tchk_t *tcp;
+ struct delctrl_t *dctp;
+ struct pviter_t *iterp;
+
+ rhrp = rhp->hrec;
+ switch (rhrp->htyp) {
+  /* need the 3 cleass elements not the class name here */
+  case vpiGate: case vpiUdp: case vpiSwitch:
+   gp = rhrp->hu.hgp;     
+   if (gp->g_delrep == DT_NONE) return(NULL);
+   ndels = bld_delay_iter(gp->g_du, gp->g_delrep, rhp->hin_itp,
+    rhrp->hin_tskp);
+   break;
+  case vpiModPath:
+   pthp = rhrp->hu.hpthp;
+   if (pthp->pth_delrep == DT_NONE) __vpi_terr(__FILE__, __LINE__);
+   ndels = bld_delay_iter(pthp->pth_du, pthp->pth_delrep, rhp->hin_itp,
+    rhrp->hin_tskp);
+   break;
+  case vpiTchk:
+   tcp = rhrp->hu.htcp;
+   if (tcp->tc_delrep == DT_NONE) __vpi_terr(__FILE__, __LINE__);
+   ndels = bld_delay_iter(tcp->tclim_du, tcp->tc_delrep, rhp->hin_itp,
+    rhrp->hin_tskp);
+   if (ndels != 1) __vpi_terr(__FILE__, __LINE__);
+   tmph = __ithtab[0];
+   if (tcp->tc_haslim2)
+    {
+     if (tcp->tc_delrep2 == DT_NONE) __vpi_terr(__FILE__, __LINE__);
+     ndels2 = bld_delay_iter(tcp->tclim2_du, tcp->tc_delrep2, rhp->hin_itp,
+      rhrp->hin_tskp);
+     if (ndels2 != 1) __vpi_terr(__FILE__, __LINE__);
+     __ithtab[1] = __ithtab[0];
+     __ithtab[0] = tmph;
+     ndels = 2;
+    }
+   break;
+  case vpiDelayControl:
+   dctp = rhrp->hu.hstp->st.sdc;
+   if (dctp->dctyp != DC_DELAY && dctp->dctyp != DC_RHSDELAY) 
+    __vpi_terr(__FILE__, __LINE__);
+   if (dctp->dc_delrep == DT_NONE) __vpi_terr(__FILE__, __LINE__);
+   ndels = bld_delay_iter(dctp->dc_du, dctp->dc_delrep, rhp->hin_itp,
+    rhrp->hin_tskp);
+   if (ndels != 1) __vpi_terr(__FILE__, __LINE__);
+   break;
+  default:
+   __vpi_err(1838, vpiError,
+    "vpiDelay 1-to-many (iterator) method illegal for %s object",
+    __to_vpionam(__wrks1, rhp->hrec->htyp));
+   return(NULL);
+  }
+ /* DBG remove --- */
+ if (ndels <= 0) __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+
+ iterp = __alloc_iter(ndels, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, ndels*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, ndels*sizeof(struct hrec_t));
+
+ for (hi = 0; hi < ndels; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+}
+
+/*
+ * fill it htab work iterator with delay expressions 
+ *
+ * not called for DT_NONE
+ */
+static int32 bld_delay_iter(union del_u du, word32 drep, struct itree_t *itp,
+ struct task_t *tskp)
+{
+ register int32 i;
+ int32 ndels;
+ word64 tim[12], timval;
+ struct mod_t *mdp;
+ struct h_t tmph;
+ struct hrec_t tmphrec, *hrp2;
+ struct h_t *hp2;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+
+ /* for expressions, value is same as source (not ticks) */
+ if (drep == DT_1X)
+  {
+   if (__ithtsiz <= 1) __grow_htab(1); 
+   tmph.hrec = &(tmphrec); 
+   mk2_exprclass_handle(&tmph, du.d1x, itp, tskp);
+   tmphrec.in_iter = TRUE; 
+   hp2 = &(__ithtab[0]);
+   memcpy(hp2, &(tmph), sizeof(struct h_t));
+   hrp2 = &(__ithrectab[0]);
+   memcpy(hrp2, &(tmphrec), sizeof(struct hrec_t)); 
+   hp2->hrec = hrp2;
+   return(1);
+  }
+ if (drep == DT_4X)
+  {
+   if (__ithtsiz <= 3) __grow_htab(3);
+   tmph.hrec = &(tmphrec); 
+   mk2_exprclass_handle(&tmph, du.d4x[0], itp, tskp);
+   tmphrec.in_iter = TRUE; 
+
+   hp2 = &(__ithtab[0]);
+   memcpy(hp2, &(tmph), sizeof(struct h_t));
+   hrp2 = &(__ithrectab[0]);
+   memcpy(hrp2, &(tmphrec), sizeof(struct hrec_t)); 
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+   tmph.hrec = &(tmphrec); 
+   mk2_exprclass_handle(&tmph, du.d4x[1], itp, tskp);
+   tmphrec.in_iter = TRUE; 
+   hp2 = &(__ithtab[1]);
+   memcpy(hp2, &(tmph), sizeof(struct h_t));
+   hrp2 = &(__ithrectab[1]);
+   memcpy(hrp2, &(tmphrec), sizeof(struct hrec_t)); 
+
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+   tmph.hrec = &(tmphrec); 
+   mk2_exprclass_handle(&tmph, du.d4x[2], itp, tskp);
+   tmphrec.in_iter = TRUE; 
+   hp2 = &(__ithtab[2]);
+   memcpy(hp2, &(tmph), sizeof(struct h_t));
+   hrp2 = &(__ithrectab[2]);
+   memcpy(hrp2, &(tmphrec), sizeof(struct hrec_t)); 
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+   /* 4x for in source expression has only 3 values (no to x) */
+   return(3);
+  }
+ /* all other cases are constants - reconstruct source assuming no anotate */ 
+ __push_itstk(itp);
+ mdp = itp->itip->imsym->el.emdp;
+ /* non expr. case, return as internal ticks constants */
+ __extract_delval(tim, &ndels, du, drep);
+ /* no t vpi time record here - always convert to number appearing in src */
+ if (ndels > 0 && !mdp->mno_unitcnv)
+  {
+   for (i = 0; i < ndels; i++)
+    {
+     __cnv_ticks_tonum64(&timval, tim[i], mdp);
+     tim[i] = timval;
+    }
+  }
+ for (i = 0; i < ndels; i++)
+  {
+   if (i >= __ithtsiz) __grow_htab(1);
+
+   /* create expresion for each delay and store in constant table for */
+   /* module type of instance */
+   xp = __sim_alloc_newxnd();
+   xp->szu.xclen = TIMEBITS;
+   xp->optyp = NUMBER;
+
+   push_xstk_(xsp, 2);
+   xsp->ap[0] = (word32) (tim[i] & WORDMASK_ULL);
+   xsp->ap[1] = (word32) ((tim[i] >> 32) & WORDMASK_ULL);
+   xsp->bp[0] = 0L;
+   xsp->bp[1] = 0L;
+   xp->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, 2);
+   __pop_xstk();
+
+   hp2 = &(__ithtab[i]);
+   hrp2 = &(__ithrectab[i]);
+   __init_hrec(hrp2);
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+   hrp2->in_iter = TRUE;
+   hrp2->htyp = vpiConstant;
+   hrp2->hu.hxp = xp;
+   hp2->hin_itp = itp;
+   hrp2->hin_tskp = tskp;
+   /* because in iter can not be freed but copied needs free xpr on */
+   hrp2->free_xpr = TRUE;
+  }
+ __pop_itstk();
+ return(ndels);
+}
+
+/*
+ * ROUTINES TO BUILD ATTRIBUTE ITERATOR
+ */
+
+/*
+ * build the attr_spec iterators
+ */
+extern vpiHandle __bld_dig_attr_iter(struct h_t *hp)
+{
+ struct net_t *np;
+ struct gate_t *gp;
+ struct inst_t *ip;
+ struct mod_t *mdp;
+ struct hrec_t *hrp;
+
+ if (hp == NULL) return(__nil_iter_err(vpiAttribute));
+
+ hrp = hp->hrec;
+ switch (hp->hrec->htyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+  case vpiNamedEvent: case vpiRealVar:
+  /* LOOKATME - is this defined in LRM - think so */
+  case vpiMemory:
+   np = hrp->hu.hnp;
+   if (np->nattrs == NULL) return(NULL);
+   return(bld_dig_attrlist_iter(hp, np->nattrs));
+  case vpiModule:
+   ip = hp->hin_itp->itip; 
+   mdp = ip->imsym->el.emdp;
+
+   /* if dig attr attached to inst use it */  
+   if (ip->iattrs != NULL) return(bld_dig_attrlist_iter(hp, ip->iattrs));
+   /* otherwise return mod attrs from mod */
+   if (mdp->mattrs == NULL) return(NULL);
+   return(bld_dig_attrlist_iter(hp, mdp->mattrs));
+  case vpiGate: case vpiSwitch: case vpiUdp:
+   gp = hrp->hu.hgp;
+   if (gp->gattrs == NULL) return(NULL);
+   return(bld_dig_attrlist_iter(hp, gp->gattrs));
+  case vpiPort:
+   __vpi_err(2113, vpiNotice,
+    "vpiAttribute 1-to-many iterator for %s empty - attached to net",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+   return(NULL);
+  default:
+   __vpi_err(2032, vpiWarning,
+    "vpiAttribute 1-to-many iterator for %s empty - attribute not yet stored",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+  }  
+ return(NULL);
+}
+
+/*
+ * get object that is parent of attribute 
+ *
+ * trick is storing digital attribute as object but offset count to
+ * object's attribute record so using htyp2 as parent object htyp
+ */
+extern vpiHandle __get_digattr_parent(struct h_t *hp)
+{
+ struct h_t *hp2;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ hp2 = (struct h_t *) __mk_handle(hrp->htyp2, (void *) hrp->hu.hanyp,
+  hp->hin_itp, hrp->hin_tskp);
+ return((vpiHandle) hp2);
+}
+
+/*
+ * build an attribute iterator of otyp objects from one attr table
+ *
+ * FIXME - should store as table so can access value using index not
+ * list search 
+ */
+static vpiHandle bld_dig_attrlist_iter(struct h_t *hp, struct attr_t *attrp)
+{
+ register int32 ai;
+ register struct attr_t *attrp2; 
+ int32 atnum;
+ struct hrec_t *hrp, *hrp2;
+ struct h_t *hp2;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+
+ if (attrp == NULL) return(NULL);
+ atnum = 0;
+ for (attrp2 = attrp; attrp2 != NULL; attrp2 = attrp2->attrnxt) atnum++; 
+
+ hrp = hp->hrec;
+ iterp = __alloc_iter(atnum, &ihref);
+ for (ai = 0; ai < atnum; ai++)
+  {
+   hp2 = &(iterp->scanhtab[ai]);
+   hp2->hin_itp = hp->hin_itp;
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiAttribute;
+   hrp2->htyp2 = hrp->htyp;
+   hrp2->hi = ai;
+   hrp2->hu.hanyp = hrp->hu.hanyp;
+   hrp2->hin_tskp = hrp->hin_tskp;
+  }  
+ return(ihref);
+}
+
+/*
+ * ROUTINES TO BUILD STATEMENT CONTENTS ITERATOR
+ */
+
+/*
+ * build the case item iterator
+ */
+extern vpiHandle __bld_caseitems_iter(struct h_t *hp)
+{
+ register int32 cii;
+ register struct csitem_t *csip2;
+ register struct hrec_t *hrp2;
+ int32 numcis;
+ vpiHandle ihref;
+ struct csitem_t *dfltcsip;
+ struct h_t *hp2;
+ struct pviter_t *iterp;
+ struct st_t *stp;
+ struct csitem_t *csips;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiCase)
+  {
+   __vpi_err(1835, vpiError,
+    "vpiCaseItem 1-to-many iterator requires vpiCase reference handle - %s illegal",
+    __to_vpionam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ stp = hrp->hu.hstp;
+ /* 08/27/99 - now case default always first on list - nil st if no dflt */
+ dfltcsip = stp->st.scs.csitems;
+
+ csips = dfltcsip->csinxt;
+ for (numcis = 0, csip2 = csips; csip2 != NULL; csip2 = csip2->csinxt)
+  numcis++;
+ if (dfltcsip->csist != NULL) numcis++;
+ if (numcis <= 0) return(NULL);
+
+ iterp = __alloc_iter(numcis, &ihref);
+ for (csip2 = csips, cii = 0; csip2 != NULL; csip2 = csip2->csinxt, cii++) 
+  {
+   /* DBG remove --- */
+   if (csip2->csist == NULL) __vpi_terr(__FILE__, __LINE__); 
+   /* --- */
+   hp2 = &(iterp->scanhtab[cii]);
+   hp2->hin_itp = hp->hin_itp;
+
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiCaseItem;
+   hrp2->hu.hcsip = csip2;
+   hrp2->hin_tskp = hrp->hin_tskp;
+  }
+ /* notice cii at loop exit is next past end */
+ if (dfltcsip->csist != NULL)
+  {
+   hp2 = &(iterp->scanhtab[cii]);
+   hp2->hin_itp = hp->hin_itp;
+
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiCaseItem;
+   hrp2->hu.hcsip = dfltcsip;
+   hrp2->hin_tskp = hrp->hin_tskp;
+  }
+ return(ihref);
+}
+
+/*
+ * build the case item expression iterator from case item (including default)
+ */
+extern vpiHandle __bld_casi_exprs_iter(struct h_t *hp)
+{
+ register int32 xi;
+ register struct exprlst_t *xplst;
+ int32 numxps;
+ vpiHandle ihref;
+ struct csitem_t *csip;
+ struct h_t *hp2;
+ struct pviter_t *iterp;
+ struct hrec_t *hrp;
+
+ 
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiCaseItem)
+  {
+   __vpi_err(1831, vpiError,
+    "vpiExpr 1-to-many iterator only legal for vpiCaseItem - %s illegal",
+    __to_vpionam(__wrks1, hrp->htyp));
+   return(NULL);
+  }
+ csip = hrp->hu.hcsip;
+ for (numxps = 0, xplst = csip->csixlst; xplst != NULL; xplst = xplst->xpnxt)
+  numxps++;
+ if (numxps <= 0) return(NULL);
+ iterp = __alloc_iter(numxps, &ihref);
+ for (xi = 0, xplst = csip->csixlst; xplst != NULL; xplst = xplst->xpnxt, xi++)
+  {
+   hp2 = &(iterp->scanhtab[xi]);
+   mk2_exprclass_handle(hp2, xplst->xp, hp->hin_itp, hrp->hin_tskp);
+  }
+ return(ihref);
+}
+
+/*
+ * build the iterator for operands of an operator
+ * handle is an expression that must have operands
+ *
+ * for part select and bit (const or var) select vpiRange or vpiIndex
+ * not vpiOperand iterator
+ */
+extern vpiHandle __bld_operands_iter(struct h_t *hp)
+{
+ register int32 xi;
+ register struct expr_t *xp, *catxp;
+ int32 xtyp, otyp, numxps;
+ vpiHandle ihref;
+ struct expr_t *xp2;
+ struct h_t *hp2;
+ struct pviter_t *iterp;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ if (hrp->htyp != vpiOperation)
+  {
+   strcpy(__wrks2, "*none*");
+bad_handle:
+   __vpi_err(1831, vpiError,
+    "vpiOperand 1-to-many iterator requires vpiOperation handle - %s (type %s) illegal",
+    __to_vpionam(__wrks1, hrp->htyp), __wrks2);
+   return(NULL);
+  }
+ xp = hrp->hu.hxp;
+ xtyp = __exprtype_get(xp);
+ if (xtyp != vpiOperation)
+  { __to_vpionam(__wrks2, (word32) xtyp); goto bad_handle; }
+
+ otyp = __expr_optype_get(xp);
+
+ /* null op has no operands */
+ if (otyp == vpiNullOp)
+  {
+   return(NULL);
+  }
+ 
+ /* concatenate and ?: are special cases (3-ary and n-ary) */
+ if (otyp == vpiConcatOp) 
+  {
+   for (numxps = 0, catxp = xp->ru.x; catxp != NULL; catxp = catxp->ru.x)
+    numxps++;
+   
+   /* DBG remove --- */
+   if (numxps <= 0) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   iterp = __alloc_iter(numxps, &ihref);
+   for (catxp = xp->ru.x, xi = 0; catxp != NULL; catxp = catxp->ru.x, xi++) 
+    {
+     /* works because alloc of iter make connect from hp to hrec */
+     hp2 = &(iterp->scanhtab[xi]);
+     mk2_exprclass_handle(hp2, catxp->lu.x, hp->hin_itp, hrp->hin_tskp);
+    }
+   return(ihref);
+  }
+ if (otyp == vpiConditionOp)
+  {
+   iterp = __alloc_iter(3, &ihref);
+   for (xi = 0; xi < 3; xi++)
+    {
+     hp2 = &(iterp->scanhtab[xi]);
+     if (xi == 0) xp2 = xp->lu.x;
+     else if (xi == 1) xp2 = xp->ru.x->lu.x;
+     else xp2 = xp->ru.x->ru.x;
+     mk2_exprclass_handle(hp2, xp2, hp->hin_itp, hrp->hin_tskp);
+    }
+   return(ihref);
+  }
+ /* notice ru operand nil implies unary */
+ if (xp->ru.x == NULL)
+  { 
+   iterp = __alloc_iter(1, &ihref);
+   hp2 = &(iterp->scanhtab[0]);
+   mk2_exprclass_handle(hp2, xp->lu.x, hp->hin_itp, hrp->hin_tskp);
+   return(ihref);
+  }
+ /* normal binary operator */
+ iterp = __alloc_iter(2, &ihref);
+ for (xi = 0; xi < 2; xi++)
+  {
+   hp2 = &(iterp->scanhtab[xi]);
+   if (xi == 0) xp2 = xp->lu.x; else xp2 = xp->ru.x;
+   mk2_exprclass_handle(hp2, xp2, hp->hin_itp, hrp->hin_tskp);
+  }
+ return(ihref);
+}
+
+/*
+ * build all callbacks iterator
+ * for now only legal is all, FIXME - should support from objects
+ */
+extern vpiHandle __bld_allcbs_iter(struct h_t *hp)
+{
+ register int32 cbi, numcbs;
+ register struct cbrec_t *cbp;
+ register struct hrec_t *hrp2;
+ vpiHandle ihref;
+ struct pviter_t *iterp;
+ struct h_t *hp2;
+
+ if (hp != NULL)
+  {
+   __vpi_err(1831, vpiError,
+    "for now vpiCallback 1-to-many iterator requires NULL (all cbs) - %s illegal",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+    return(NULL);
+  }
+ if (__vpi_cbrec_hdr == NULL) return(NULL);
+ for (numcbs = 0, cbp = __vpi_cbrec_hdr; cbp != NULL; cbp = cbp->cbnxt)
+  numcbs++;
+ if (numcbs <= 0) return(NULL);
+
+ iterp = __alloc_iter(numcbs, &ihref);
+ /* since register list new added to front, build iterator back to front */ 
+ cbp = __vpi_cbrec_hdr;
+ /* SJM - 06/14/99 - since put latest on front build in reverse order */
+ for (cbi = numcbs - 1; cbp != NULL; cbp = cbp->cbnxt, cbi--) 
+  {
+   hp2 = &(iterp->scanhtab[cbi]);
+   hrp2 = hp2->hrec;
+   hrp2->htyp = vpiCallback;
+   hrp2->hu.hcbp = cbp;
+   /* callback handles do not have itree loc (but obj might) */
+  }
+ return(ihref);
+}
+
+/*
+ * ROUTINES TO BUILD PORT AND PORT BIT ITERATORS
+ */
+
+/*
+ * build vpi Port module port iterator from a net (any type) handle
+ *
+ * given a net, find all ports that connect to the net (usually one)
+ * but jumpered ports legal in Verilog
+ * search through all of load, drivers, and inout vertex edges
+ *
+ * module port connections are never xmr since no xmr forms for port wire
+ */
+static vpiHandle bld_netmdport_iter(struct h_t *hp)
+{
+ register int32 hi;
+ int32 numprts;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct mod_t *mdp;
+ struct pviter_t *iterp;
+
+ np = hp->hrec->hu.hnp;
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ if (mdp->mpnum == 0) return(NULL);
+ numprts = bld_net_mdpins(np, mdp, hp->hin_itp);
+ if (numprts <= 0) return(NULL);
+
+ iterp = __alloc_iter(numprts, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, numprts*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, numprts*sizeof(struct hrec_t));
+ for (hi = 0; hi < numprts; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+}
+
+/*
+ * build modport connecting iterators
+ *
+ * know all jumpered non tran channel ports will be marked if any are
+ *
+ * if multiple connections to same port do not include repeats
+ * this does not run with anything on itstk instead uses itp
+ *
+ * here iterator is vpiPort so returns all port connections
+ *
+ * this is opposite of lowconn - from port connecting net up to port
+ * here because not bit handle, return entire port
+ *
+ * to decompose and match expr. connections and ports, user must create
+ * port iterator get highconn and lowconn connection and then write program
+ * to match
+ */
+static int32 bld_net_mdpins(struct net_t *np, struct mod_t *mdp,
+ struct itree_t *itp)
+{
+ register struct net_pin_t *npp;
+ register struct hrec_t *hrp2;
+ int32 cnt;
+ byte *prtconn;
+ struct h_t *hp2;
+ struct mod_pin_t *mpp;
+ 
+ prtconn = (byte *) __my_malloc(mdp->mpnum);
+ memset(prtconn, 0, mdp->mpnum);
+ /* mod port loads are output ports - can connect to regs too */
+ for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   /* PB mdports for drivers only */
+   if (npp->npntyp == NP_PB_MDPRT)
+    {
+     /* SJM 09/20/02 - for per bit npp forms, ignore all but 1 npp */  
+     /* there will be one npp per bit but only one iterator forllowing LRM */
+     /* and by not doing 2nd per bit indexing, looks like vectored npp */
+     if (npp->pbi != 0) continue;
+    }
+   else if (npp->npntyp != NP_MDPRT) continue;
+
+   /* DBG remove --- */
+   if (npp->elnpp.emdp != mdp) __vpi_terr(__FILE__, __LINE__);
+   /* --- */  
+   mpp = &(mdp->mpins[npp->obnum]);
+   /* if no connection for this port include */
+   if (prtconn[npp->obnum] == 0)
+    {
+     if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+     hp2 = &(__ithtab[cnt]);
+     hrp2 = &(__ithrectab[cnt++]);
+     __init_hrec(hrp2);
+
+     hrp2->in_iter = TRUE;
+     hrp2->htyp = vpiPort;
+     hrp2->hu.hpi = npp->obnum;
+     hp2->hin_itp = itp;
+     /* only need to set cross link in newly added one */
+     hp2->hrec = hrp2;
+     prtconn[npp->obnum] = 1;
+    }
+   if (!mpp->mp_jmpered) break;
+  }
+ /* if reg done */
+ if (np->ntyp >= NONWIRE_ST) goto done;
+
+ /* mod port drivers are input ports - must be wire */
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->npntyp == NP_PB_MDPRT)
+    {
+     /* SJM 09/20/02 - for per bit npp forms, ignore all but 1 npp */  
+     /* there will be one npp per bit but only one iterator forllowing LRM */
+     /* and by not doing 2nd per bit indexing, looks like vectored npp */
+     if (npp->pbi != 0) continue;
+    }
+   else if (npp->npntyp != NP_MDPRT) continue;
+
+   /* DBG remove --- */
+   if (npp->elnpp.emdp != mdp) __vpi_terr(__FILE__, __LINE__);
+   /* --- */  
+   mpp = &(mdp->mpins[npp->obnum]);
+   if (prtconn[npp->obnum] == 0)
+    {
+     if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+     hp2 = &(__ithtab[cnt]);
+     hrp2 = &(__ithrectab[cnt++]);
+     __init_hrec(hrp2);
+
+     hrp2->in_iter = TRUE;
+     hrp2->htyp = vpiPort;
+     hrp2->hu.hpi = npp->obnum;
+     hp2->hin_itp = itp;
+     /* only need to set cross link in newly added one */
+     hp2->hrec = hrp2;
+     prtconn[npp->obnum] = 1;
+    }
+   if (!mpp->mp_jmpered) break;
+  }
+ /* finally inout ports if they exist (always bit by bit) */
+ if (np->ntraux == NULL) goto done;
+
+ /* SJM - 05/15/99 - after tran channels built - leave npps connected */
+ /* as part of ntraux - use for PLI not simulation */
+ /* bid and tran (gate?) npps move to traux for PLI processing */
+ for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->npntyp != NP_BIDMDPRT) continue;
+
+   mpp = &(mdp->mpins[npp->obnum]);
+   /* DBG remove --- */
+   if (npp->elnpp.emdp != mdp) __vpi_terr(__FILE__, __LINE__);
+   /* --- */  
+   mpp = &(mdp->mpins[npp->obnum]);
+   if (prtconn[npp->obnum] == 0)
+    {
+     if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+     hp2 = &(__ithtab[cnt]);
+     hrp2 = &(__ithrectab[cnt++]);
+     __init_hrec(hrp2);
+
+     hrp2->in_iter = TRUE;
+     hrp2->htyp = vpiPort;
+     hrp2->hu.hpi = npp->obnum;
+     hp2->hin_itp = itp;
+     /* only need to set cross link in newly added one */
+     hp2->hrec = hrp2;
+     prtconn[npp->obnum] = 1;
+    }
+  }
+done:
+ __my_free((char *) prtconn, mdp->mpnum);
+ return(cnt);
+}
+
+/*
+ * build the port bit iterator for all bits connecting to the one net bit
+ *
+ * for normal non scalar only connections this is needed to get per bit
+ * connections since different bits will have different connectivity
+ * never get here for scalar
+ *
+ * LOOKATME - netbit here must be constant only (i.e. no eval) 
+ */
+static vpiHandle bld_netbitmdport_iter(struct h_t *hp)
+{
+ register int32 hi;
+ int32 bi, numprts;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct mod_t *mdp;
+ struct itree_t *itp;
+ struct pviter_t *iterp;
+
+ if ((bi = cmp_drvld_bitndx(&np, hp, "vpiPort")) == -1) return(NULL);
+
+ itp = hp->hin_itp;
+ mdp = itp->itip->imsym->el.emdp;
+ if (mdp->mpnum == 0) return(NULL);
+ numprts = bld_netbit_mdpins(np, bi, mdp, itp);
+ if (numprts <= 0) return(NULL);
+
+ iterp = __alloc_iter(numprts, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, numprts*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, numprts*sizeof(struct hrec_t));
+ for (hi = 0; hi < numprts; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+}
+
+/*
+ * compute index for bit object driver/load iterator
+ *
+ * ??? FIXME - think this is wrong needs to use current value 
+ * but then can't call during vpiEndOfCompile?
+ */
+static int32 cmp_drvld_bitndx(struct net_t **nnp, struct h_t *hp, char *objnam)
+{
+ register int32 bi;
+ register struct net_t *np;
+ register struct hrec_t *hrp;
+
+ *nnp = NULL;
+ hrp = hp->hrec;
+ if (!hrp->bith_ndx && !__expr_is_vpiconst(hrp->hu.hxp))
+  {
+   __vpi_err(1880, vpiError,
+    "%s 1-to-many iterator from %s illegal - vpiNetBit/vpiRegBit non constant",
+    objnam, __to_vpionam(__wrks1, hrp->htyp));
+   return(-1);
+  }
+ if (hrp->bith_ndx) { np = hrp->hu.hnp; bi = hrp->hi; }
+ else
+  {
+   /* DBG remove --- */
+   if (hrp->hu.hxp->optyp != LSB) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   /* know expr. is constant to get to here */ 
+   np = hrp->hu.hxp->lu.sy->el.enp;
+   __push_itstk(hp->hin_itp);
+   bi = __comp_ndx(np, hrp->hu.hxp->ru.x);
+   __pop_itstk();
+   /* for x or out of range - iterator empty */
+   if (bi == -1) return(-1);
+  }
+ *nnp = np;
+ return(bi);
+}
+
+/*
+ * build mod portbit connecting iterators
+ * 
+ * notice since net in module npp bits indices and bi will both be h:0 
+ * here built iterator is vpiPortBit, i.e. bit matches
+ *
+ * this is opposite (iterator) of highconn
+ *
+ * here can not eliminate duplicates
+ *
+ * because this is bit, if port scalar returns vpiPort else vpiPortBit
+ * if mod port is concat (rare) does not include and sets warning
+ *
+ * LOOKATME - all 3 cases have mostly same code - could make one func call
+ */
+static int32 bld_netbit_mdpins(struct net_t *np, int32 bi, struct mod_t *mdp,
+ struct itree_t *itp)
+{
+ register struct net_pin_t *npp;
+ register struct hrec_t *hrp2;
+ int32 ri1, ri2, cnt;
+ struct mod_pin_t *mpp;
+ struct h_t *hp2;
+ 
+ /* md prt loads are output ports */
+ for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   /* for per bit mod ports - match if this bit same as bi */
+   if (npp->npntyp == NP_PB_MDPRT)
+    {
+     if (bi == npp->pbi)
+      {
+       ri1 = ri2 = bi;
+       goto got_match;
+      }
+     else continue;
+    }
+
+   if (npp->npntyp != NP_MDPRT) continue;
+
+   /* DBG remove --- */
+   if (npp->elnpp.emdp != mdp) __vpi_terr(__FILE__, __LINE__);
+   /* --- */  
+   __push_itstk(itp);
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   __pop_itstk();
+   if (ri1 == -1 || bi == -1) goto got_match;   
+   if (bi > ri1 || bi < ri2) continue;
+
+got_match:
+   mpp = &(mdp->mpins[npp->obnum]);
+   if (mpp->mpref->optyp == LCB)
+    {
+     char s1[RECLEN];
+
+     sprintf(s1, "%s[%d]", np->nsym->synam, __unnormalize_ndx(np, bi));
+     __vpi_err(2025, vpiWarning,
+      "vpiPort iterator %s bit handle for concatenate port - unable to determine bit so vpiPort used",
+       s1);
+    }
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+   __init_hrec(hrp2);
+   hrp2->in_iter = TRUE;
+
+   if (mpp->mpwide == 1 || mpp->mpref->optyp == LCB) hrp2->htyp = vpiPort;
+   else
+    {
+     hrp2->htyp = vpiPortBit;
+     /* if simple wire (ri1 == -1) bits match one to one - else offset from */
+     /* right edge */
+     /* FIXME - what if range 0:h? */ 
+     if (ri1 == -1) hrp2->hi = bi; else hrp2->hi = bi - ri2;
+    }
+   hrp2->hu.hpi = npp->obnum;
+   hp2->hin_itp = itp;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+   /* LOOKATME - think some bit may be inout channel so need ports */
+   if (!mpp->mp_jmpered) break;
+  }
+ /* will be no drivers and no tran channel for reg */
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   /* DBG remove --- */
+   if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   goto done;
+  }
+
+ /* md prt drivers are input ports */
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   /* SJM 09/20/02 - need to access per bit contained port for PB form */
+   /* for per bit mod ports - match if this bit same as bi */
+   if (npp->npntyp == NP_PB_MDPRT)
+    {
+     if (bi == npp->pbi) goto got_match2;
+     else continue;
+    }
+
+   if (npp->npntyp != NP_MDPRT) continue;
+
+   /* DBG remove --- */
+   if (npp->elnpp.emdp != mdp) __vpi_terr(__FILE__, __LINE__);
+   /* --- */  
+   __push_itstk(itp);
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   __pop_itstk();
+   if (ri1 == -1 || bi == -1) goto got_match2;   
+   if (bi > ri1 || bi < ri2) continue;
+
+got_match2:
+   if (npp->npntyp == NP_MDPRT)
+    {
+     mpp = &(mdp->mpins[npp->obnum]);
+     if (mpp->mpref->optyp == LCB)
+      {
+       char s1[RECLEN];
+
+       sprintf(s1, "%s[%d]", np->nsym->synam, __unnormalize_ndx(np, bi));
+       __vpi_err(2025, vpiWarning,
+        "vpiPort iterator %s bit handle for concatenate port - unable to determine bit so vpiPort used",
+         s1);
+      }
+    }
+   else
+    { 
+     mpp = &(mdp->mpins[npp->obnum]);
+     mpp = &(mpp->pbmpps[npp->pbi]);
+    }
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+   __init_hrec(hrp2);
+   hrp2->in_iter = TRUE;
+
+   if (npp->npntyp == NP_MDPRT)
+    {
+     if (mpp->mpwide == 1 || mpp->mpref->optyp == LCB) hrp2->htyp = vpiPort;
+     else
+      {
+       hrp2->htyp = vpiPortBit;
+       /* notice these are internal h:0 - fixed when index accessed */
+       /* correct for port bit from non concatenate net bit */ 
+       if (ri1 == -1) hrp2->hi = bi; else hrp2->hi = bi - ri2;
+      }
+    } 
+   else
+    {
+     /* SJM 09/20/02 - for PB input port MOD PORT, always scalared */
+     hrp2->htyp = vpiPortBit;
+     hrp2->hi = bi;
+    }
+   hp2->hin_itp = itp;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+   hrp2->hu.hpi = npp->obnum;
+  }
+done:
+ return(cnt);
+}
+
+/*
+ * ROUTINES BUILD PORT INSTANCE (ICONN) ITERATORS
+ */
+
+/*
+ * build vpi port instance (iconn) iterators
+ *
+ * here will commonly have many iconns (ports of in module instances) 
+ * for example if clock feeds lots of instances
+ *
+ * if net if any bits connect in iterator if bit only if right bit matches
+ */
+extern vpiHandle __bld_neticonn_iter(struct h_t *hp)
+{
+ if (hp == NULL) return(__nil_iter_err(vpiPortInst));
+ switch (hp->hrec->htyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   /* iterator is usually 1 port net connects to (only more if jumpered) */
+   /* this returns port handles even if selects */
+   return(bld_neticonnport_iter(hp));
+  case vpiNetBit: case vpiRegBit: case vpiVarSelect:
+   /* iterator is usually 1 port bit bit connects to */
+   /* this returns port bit handles for the one bit */
+   return(bld_netbiticonnport_iter(hp));
+  default:
+   __vpi_err(1863, vpiError,
+    "vpiPortInst 1-to-many iterator from %s illegal - for loconn instance ports",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+  }  
+ return(NULL);
+}
+
+/*
+ * build the iterator for all ports connecting to inside module instances
+ *
+ * each will have different hin_itp and expect many
+ */
+static vpiHandle bld_neticonnport_iter(struct h_t *hp)
+{
+ register int32 hi;
+ int32 numprts;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct itree_t *itp; 
+ struct pviter_t *iterp;
+
+ np = hp->hrec->hu.hnp;
+ itp = hp->hin_itp;
+ numprts = bld_net_iconns(np, itp);
+ if (numprts <= 0) return(NULL);
+
+ iterp = __alloc_iter(numprts, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, numprts*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, numprts*sizeof(struct hrec_t));
+ for (hi = 0; hi < numprts; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+}
+
+/*
+ * build down instance connecting iconns iterators
+ *
+ * here any common bits cause all of inst-port handle to be added to iter
+ * never duplicates since will be different port (inst. term) or different
+ * instance
+ *
+ * but since tran channel per bit, some connections will probably 
+ * connect to same wire and port (i.e. needed to decompose part select or
+ * wire to all the bits)
+ *
+ * algorithm is to count all so know will be at least big enough then
+ * caller reallocates to shink when done
+ *
+ * notice nothing on itree stack here?
+ * also no filtering of bit range and bit counts because return entire port
+ *
+ * SJM 09/20/02 - because this is vectored and only entire ports in   
+ * iterator filter to only one of iconn high conn concat works
+ */
+static int32 bld_net_iconns(struct net_t *np, struct itree_t *itp)
+{
+ register struct net_pin_t *npp;
+ register struct hrec_t *hrp2;
+ int32 cnt;
+ struct h_t *hp2;
+ struct itree_t *itp2;
+ 
+ /* iconn loads are input ports */
+ for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   /* SJM 02/22/02 - works because rhs up expr not decomposed so all */ 
+   /* loads are same - only difference is use part of port for action */
+   if (npp->npntyp == NP_PB_ICONN)
+    {
+     /* SJM 09/20/02 - for per bit npp forms, ignore all but 1 npp */  
+     /* there will be one npp per bit but only one iterator forllowing LRM */
+     if (npp->pbi != 0) continue;
+    }
+   else if (npp->npntyp != NP_ICONN) continue;
+
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
+    continue;
+
+   if (npp->npproctyp == NP_PROC_INMOD) itp2 = &(itp->in_its[npp->elnpp.eii]);
+   else
+    {
+     /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
+     /* but leaving does not hurt */
+     __push_itstk(itp);
+     if (!__move_to_npprefloc(npp))
+      {
+       __pop_itstk();
+       continue;
+      }
+     itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+     __pop_itstk();
+     __pop_itstk();
+    }
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+   __init_hrec(hrp2);
+   hrp2->in_iter = TRUE;
+
+   hrp2->in_iter = TRUE;
+   hrp2->htyp = vpiPort;
+   hrp2->hu.hpi = npp->obnum;
+   hp2->hin_itp = itp2;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+  }
+ /* will be no drivers and no tran channel for reg */
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   /* DBG remove --- */
+   if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   goto done;
+  }
+
+ /* iconn drivers are output ports and only exist for wires */
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   /* PB iconns only for loads */
+   /* DBG remove -- */
+   if (npp->npntyp == NP_PB_ICONN) __vpi_terr(__FILE__, __LINE__);
+   /* -- */
+   if (npp->npntyp != NP_ICONN) continue;
+
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
+    continue;
+
+   if (npp->npproctyp == NP_PROC_INMOD) itp2 = &(itp->in_its[npp->elnpp.eii]);
+   else
+    {
+     /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
+     /* but leaving does not hurt */
+     __push_itstk(itp);
+     if (!__move_to_npprefloc(npp))
+      {
+       __pop_itstk();
+       continue;
+      }
+     itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+     __pop_itstk();
+     __pop_itstk();
+    }
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+   __init_hrec(hrp2);
+   hrp2->in_iter = TRUE;
+
+   hrp2->in_iter = TRUE;
+   hrp2->htyp = vpiPort;
+   hrp2->hu.hpi = npp->obnum;
+
+   /* vpi handle parent will get module/instance port in */
+   hp2->hin_itp = itp2;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+  }
+
+ /* finally inout if they exist */
+ if (np->ntraux == NULL) goto done;
+
+ /* iconns in tran channels are only bid iconns */
+ for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->npntyp != NP_BIDICONN) continue;
+
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
+    continue;
+
+   if (npp->npproctyp == NP_PROC_INMOD) itp2 = &(itp->in_its[npp->elnpp.eii]);
+   else
+    {
+     /* can be iconn from other instance for xmr */
+     /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
+     /* but leaving does not hurt */
+     __push_itstk(itp);
+     if (!__move_to_npprefloc(npp))
+      {
+       __pop_itstk();
+       continue;
+      }
+     itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+     __pop_itstk();
+     __pop_itstk();
+    }
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+   __init_hrec(hrp2);
+   hrp2->in_iter = TRUE;
+   hrp2->htyp = vpiPort;
+   hrp2->hu.hpi = npp->obnum;
+   /* vpi handle parent will get module/instance port in */
+   hp2->hin_itp = itp2;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+  }
+done:
+ return(cnt);
+}
+
+/*
+ * return T if find tran channel inst-port that matches one already
+ * in iterator
+ */
+static int32 same_vpi_handle(struct h_t *htab, int32 fr, int32 num, struct h_t *hp2,
+ struct hrec_t *hrp2)
+{
+ register int32 hi;
+ register struct h_t *hp;
+ register struct hrec_t *hrp;
+
+ for (hi = fr; hi < num; hi++)
+  {
+   hp = &(htab[hi]);
+   hrp = hp->hrec; 
+
+   switch (hrp->htyp) {
+    case vpiPort:
+     if (hrp2->htyp != vpiPort) break;
+     if (hp2->hin_itp != hp->hin_itp) break;
+     if (hrp2->hu.hpi != hrp->hu.hpi) break;
+     return(TRUE);
+    case vpiContAssign:
+     if (hrp2->htyp != vpiContAssign) break;
+     if (hp2->hin_itp != hp->hin_itp) break;
+     if (hrp2->htyp2 == vpiGate || hrp->htyp2 == vpiGate)
+      {
+       if (hrp2->htyp2 != vpiGate || hrp->htyp2 != vpiGate) break; 
+       if (hrp2->hu.hgp != hrp->hu.hgp) break;
+      }
+     else if (hrp2->hu.hcap != hrp->hu.hcap) break;
+     return(TRUE);
+    case vpiPrimTerm:
+     /* terminal of gate */
+     if (hrp2->htyp != vpiPrimTerm) break;
+     if (hp2->hin_itp != hp->hin_itp) break;
+     if (hrp2->hu.hgp != hrp->hu.hgp) break;
+     if (hrp2->hi != hrp->hi) break;
+     return(TRUE);
+    case vpiModPathOut:
+     if (hrp2->htyp != vpiModPathOut) break;
+chk_modpath:
+     if (hp2->hin_itp != hp->hin_itp) break;
+     if (hrp2->hu.hpthp != hrp->hu.hpthp) break;
+     if (hrp2->hi != hrp->hi) break;
+     return(TRUE);
+    case vpiModPathIn:
+     if (hrp2->htyp != vpiModPathIn) break;
+     goto chk_modpath;
+    case vpiForce:
+     if (hrp2->htyp != vpiForce) break;
+     if (hp2->hin_itp != hp->hin_itp) break;
+     if (hrp2->hu.hstp != hrp->hu.hstp) break;
+     return(TRUE);
+    default: __vpi_terr(__FILE__, __LINE__);
+   }
+ }
+ return(FALSE);
+}
+
+/*
+ * build the iterator for all port bits connecting to inside module instances
+ * given a vpi net or reg bit handle, build iterator of port bit handles
+ *
+ * if iconn contenate or operator expression - returns entire handle
+ */
+static vpiHandle bld_netbiticonnport_iter(struct h_t *hp)
+{
+ register int32 hi;
+ int32 bi, numprts;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct itree_t *itp;
+ struct pviter_t *iterp;
+
+ if ((bi = cmp_drvld_bitndx(&np, hp, "vpiPortInst")) == -1) return(NULL);
+
+ itp = hp->hin_itp;
+ numprts = bld_netbit_iconns(np, bi, itp);
+ if (numprts <= 0) return(NULL);
+
+ iterp = __alloc_iter(numprts, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, numprts*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, numprts*sizeof(struct hrec_t));
+ for (hi = 0; hi < numprts; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+}
+
+/*
+ * build down instance connecting iconns iterators
+ *
+ * here any common bits cause all of inst-port handle to be added to iter
+ * never duplicates since will be different port (inst. term) or different
+ * instance
+ *
+ * but since tran channel per bit, some connections will probably 
+ * connect to same wire and port (i.e. needed to decompose part select or
+ * wire to all the bits)
+ *
+ * algorithm is to count all so know will be at least big enough then
+ * caller reallocates to shink when done
+ *
+ * notice nothing on itree stack here?
+ */
+static int32 bld_netbit_iconns(struct net_t *np, int32 bi, struct itree_t *itp)
+{
+ register struct net_pin_t *npp;
+ register struct hrec_t *hrp2;
+ int32 ri1, ri2, cnt, nd_itpop, not_lhs;
+ struct h_t *hp2;
+ struct itree_t *itp2;
+ struct mod_t *downmdp;
+ struct mod_pin_t *mpp;
+ 
+ __push_itstk(itp);
+ /* iconn loads are input ports */
+ for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   /* SJM 02/22/02 - works because rhs up expr not decomposed so all */ 
+   /* loads are same - only difference is use part of port for action */
+   if (npp->npntyp != NP_ICONN && npp->npntyp != NP_PB_ICONN) continue;
+
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT
+    && npp->npaux->npu.filtitp != __inst_ptr) continue;
+
+   /* can be iconn from other instance for xmr */
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
+     /* but leaving does not hurt */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+
+   /* this must run with right itree loc. */
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   if (ri1 == -1 || bi == -1) goto got_match;   
+   if (bi > ri1 || bi < ri2) goto nxt_npp;
+
+got_match:
+   /* if iconn not lvalue (variable, bit or part select or mod pin concate */
+   /* need warning and use entire vpiPort */
+   itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   downmdp = itp2->itip->imsym->el.emdp;
+   if (npp->npntyp == NP_ICONN)
+    {
+     mpp = &(downmdp->mpins[npp->obnum]);
+     if (!iconnbit_lvalue(mpp, npp, itp2)) not_lhs = TRUE; 
+     else not_lhs = FALSE;
+
+     if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+     hp2 = &(__ithtab[cnt]);
+     hrp2 = &(__ithrectab[cnt++]);
+     __init_hrec(hrp2);
+     hrp2->in_iter = TRUE;
+     hrp2->hu.hpi = npp->obnum;
+
+     if (mpp->mpwide == 1 || not_lhs) hrp2->htyp = vpiPort;
+     else
+      {
+       hrp2->htyp = vpiPortBit;
+       /* notice these are internal h:0 - fixed when index accessed */
+       /* correct for port bit from non concatenate net bit */ 
+       /* LOOKATME - is this right? */
+       if (ri1 == -1) hrp2->hi = bi; else hrp2->hi = bi - ri2;
+      }
+    }
+   else
+    {
+     /* SJM 09/20/02 - for per bit separated input iconn, need double ndxing */
+     if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+     hp2 = &(__ithtab[cnt]);
+     hrp2 = &(__ithrectab[cnt++]);
+     __init_hrec(hrp2);
+     hrp2->in_iter = TRUE;
+     hrp2->hu.hpi = npp->obnum;
+     hrp2->htyp = vpiPortBit;
+     hrp2->hi = bi;   
+    }
+   hp2->hin_itp = itp2;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+ /* will be no drivers and no tran channel for reg */
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   /* DBG remove --- */
+   if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   goto done;
+  }
+ /* iconn drivers are output ports and only exist for wires */
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   /* SJM 09/20/02 - since this is output port iconn, never per bit */
+   if (npp->npntyp != NP_ICONN) continue;
+
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT
+    && npp->npaux->npu.filtitp != __inst_ptr) continue;
+
+   /* can be iconn from other instance for xmr */
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
+     /* but leaving does not hurt */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+
+   /* this must run with right itree loc. */
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   if (ri1 == -1 || bi == -1) goto got_match2;   
+   if (bi > ri1 || bi < ri2) goto nxt2_npp;
+
+got_match2:
+   /* if iconn not lvalue (variable, bit or part select or mod pin concate */
+   /* need warning and use entire vpiPort */
+   itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   downmdp = itp2->itip->imsym->el.emdp;
+   mpp = &(downmdp->mpins[npp->obnum]);
+   if (!iconnbit_lvalue(mpp, npp, itp2)) not_lhs = TRUE; 
+   else not_lhs = FALSE;
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+   __init_hrec(hrp2);
+   hrp2->in_iter = TRUE;
+   hrp2->htyp = vpiPort;
+   hrp2->hu.hpi = npp->obnum;
+
+   if (mpp->mpwide == 1 || not_lhs) hrp2->htyp = vpiPort;
+   else
+    {
+     hrp2->htyp = vpiPortBit;
+     /* notice these are internal h:0 - fixed when index accessed */
+     /* correct for port bit from non concatenate net bit */ 
+     if (ri1 == -1) hrp2->hi = bi; else hrp2->hi = bi - ri2;
+    }
+   hp2->hin_itp = itp2;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt2_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+ /* finally inout if they exist */
+ if (np->ntraux == NULL) goto done;
+
+ /* iconn drivers are output ports and only exist for wires */
+ for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->npntyp != NP_BIDICONN) continue;
+
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT
+    && npp->npaux->npu.filtitp != __inst_ptr) continue;
+
+   /* can be iconn from other instance for xmr */
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
+     /* but leaving does not hurt */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+
+   /* this must run with right itree loc. */
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   if (ri1 == -1 || bi == -1) goto got_match3;   
+   if (bi > ri1 || bi < ri2) goto nxt3_npp;
+
+got_match3:
+   /* if iconn not lvalue (variable, bit or part select or mod pin concate */
+   /* need warning and use entire vpiPort */
+   itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   downmdp = itp2->itip->imsym->el.emdp;
+   mpp = &(downmdp->mpins[npp->obnum]);
+   if (!iconnbit_lvalue(mpp, npp, itp2)) not_lhs = TRUE; 
+   else not_lhs = FALSE;
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+   __init_hrec(hrp2);
+   hrp2->in_iter = TRUE;
+   hrp2->htyp = vpiPort;
+   hrp2->hu.hpi = npp->obnum;
+
+   if (mpp->mpwide == 1 || not_lhs) hrp2->htyp = vpiPort;
+   else
+    {
+     hrp2->htyp = vpiPortBit;
+     /* notice these are internal h:0 - fixed when index accessed */
+     /* correct for port bit from non concatenate net bit */ 
+     if (ri1 == -1) hrp2->hi = bi; else hrp2->hi = bi - ri2;
+    }
+   hp2->hin_itp = itp2;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt3_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+
+done:
+ __pop_itstk();
+ return(cnt);
+}
+
+/*
+ * return T if good port and iconn simple (non concat) lvalue
+ */
+static int32 iconnbit_lvalue(struct mod_pin_t *mpp, struct net_pin_t *npp, 
+ struct itree_t *itp2)
+{
+ struct expr_t *xp;
+
+ if (mpp->mpref->optyp == LCB) return(FALSE);
+ xp = itp2->itip->ipins[npp->obnum];
+ if (xp->optyp == ID || xp->optyp == GLBREF || xp->optyp == LSB ||
+  xp->optyp == PARTSEL) return(TRUE); 
+ return(FALSE);
+}
+
+/*
+ * ROUTINES TO BUILD LOCAL LOAD ITERATORS
+ */
+
+/*
+ * build an iterator of wire or reg (or bit) local loads
+ *
+ * list differs but otherwise code is same 
+ * inout ports and trans are both loads and drivers 
+ *
+ * this is local loads including ports and works for vectors
+ * local loads give user exact control over connectivity tracing
+ */
+extern vpiHandle __bld_loc_lds_iterator(struct h_t *hp, int32 otype)
+{
+ if (hp == NULL) return(__nil_iter_err(otype));
+
+ /* routine for each thing that load can be of */
+ switch (hp->hrec->htyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   return(net_lds_iter(hp));
+  case vpiNetBit: case vpiRegBit: case vpiVarSelect:
+   return(bit_lds_iter(hp));
+  default:
+   __vpi_err(1874, vpiError,
+    "vpiLocalLoad 1-to-many iterator from %s illegal - for net/reg/variable loads",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+  }  
+ return(NULL);
+}
+
+/*
+ * build entire wire net load iterator - in list if any bits
+ *
+ * caller must know type of iterator that is scanned since ld and driver
+ * same except for list used
+ */
+static vpiHandle net_lds_iter(struct h_t *hp)
+{
+ register int32 hi;
+ int32 num; 
+ vpiHandle ihref;
+ struct net_t *np;
+ struct itree_t *itp; 
+ struct pviter_t *iterp;
+
+ np = hp->hrec->hu.hnp;
+ itp = hp->hin_itp;
+ if ((num = bld_net_lds(np, itp)) <= 0) return(NULL);
+
+ iterp = __alloc_iter(num, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, num*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, num*sizeof(struct hrec_t));
+ for (hi = 0; hi < num; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+}
+
+/*
+ * build loads on a net or reg (match on any common bits)
+ *
+ * but since tran channel per bit, some connections will probably 
+ * connect to same wire and port (i.e. needed to decompose part select or
+ * wire to all the bits)
+ *
+ * algorithm is to count all so know will be at least big enough then
+ * caller reallocates to shink when done
+ *
+ * notice nothing on itree stack here?
+ * also no need to filter bit range and bit counts
+ */
+static int32 bld_net_lds(struct net_t *np, struct itree_t *itp) 
+{
+ register struct net_pin_t *npp;
+ register struct hrec_t *hrp2;
+ int32 cnt, nd_itpop;
+ struct h_t tmph, *hp2;
+ struct hrec_t tmphrec;
+ 
+ __push_itstk(itp);
+ /* for hard inout/tran channel hard loads, found here */
+ for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   /* SJM 07/12/01 - until add v2k delay devices, omit mipd chg load */ 
+   if (npp->npntyp == NP_MIPD_NCHG) continue;
+   if (npp->npntyp == NP_PB_ICONN && npp->pbi != 0) continue;
+
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
+    continue;
+   /* maybe move to right ref. itree loc. */ 
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - must match each inst in xmr path */
+     /* but leaving does not hurt */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+   __init_hrec(&tmphrec);
+   tmphrec.in_iter = TRUE;
+   tmph.hrec = &tmphrec;
+   if (!fill_ld_handle(&tmph, &tmphrec, npp)) goto nxt_npp;
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+
+   memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
+   hp2->hin_itp = tmph.hin_itp;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+ /* will be no drivers and no tran channel for reg */
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   /* DBG remove --- */
+   if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   goto done;
+  }
+ /* tran channel npps - go in both ld and driver iterators */
+ if (np->ntraux == NULL) goto done;
+
+ /* SJM 05/15/99 - although not using npp's for inouts they are kept */
+ /* around because they are needed for PLI load/driver iterators */
+ for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
+  {
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
+    continue;
+
+   /* maybe move to right ref. itree loc. */ 
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - must match each inst in xmr path */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+   __init_hrec(&tmphrec);
+   tmphrec.in_iter = TRUE;
+   if (!fill_ld_handle(&tmph, &tmphrec, npp)) goto nxt2_npp;
+   tmph.hrec = &tmphrec;
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+
+   memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
+   hp2->hin_itp = tmph.hin_itp;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt2_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+done:
+ __pop_itstk();
+ return(cnt);
+}
+
+/*
+ * fill a load handle - if non handle element, return nil
+ *
+ * caller must have initialized fields in handle
+ * this must be called from ref. (stacked itree loc) for xmr 
+ */
+static int32 fill_ld_handle(struct h_t *hp, struct hrec_t *hrp,
+ struct net_pin_t *npp)
+{
+ struct itree_t *itp2;
+ struct gate_t *gp;
+
+ hp->hin_itp = __inst_ptr;
+ switch ((byte) npp->npntyp) {
+  case NP_ICONN: case NP_BIDICONN: case NP_PB_ICONN:
+   /* load iconn is input port */
+   hrp->htyp = vpiPort;
+   hrp->hu.hpi = npp->obnum;
+   itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   hp->hin_itp = itp2;
+   break;
+  case NP_MDPRT: case NP_BIDMDPRT: case NP_PB_MDPRT:
+   /* load mdprt is output port */
+   hrp->htyp = vpiPort;
+   hrp->hu.hpi = npp->obnum;
+   break;
+  case NP_CONTA:
+   hrp->htyp = vpiContAssign;
+   hrp->hu.hcap = npp->elnpp.ecap;
+   break;
+  case NP_GATE: case NP_TRANIF: case NP_TRAN:
+   gp = npp->elnpp.egp;
+   if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
+    {
+     hrp->htyp = vpiContAssign;
+     hrp->htyp2 = vpiGate;
+     hrp->hu.hgp = gp;
+    }
+   else
+    {
+     gp = npp->elnpp.egp; 
+     hrp->htyp = vpiPrimTerm;
+     hrp->hu.hgp = gp;
+     hrp->hi = npp->obnum;
+    }
+   break;
+  default: return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * build the iterator for all port bits connecting to inside module instances
+ * given a vpi net or reg bit handle, build iterator of port bit handles
+ *
+ * builds in ithtab and then allocates iterator and copies into it
+ */
+static vpiHandle bit_lds_iter(struct h_t *hp)
+{
+ register int32 hi;
+ int32 bi, num;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct itree_t *itp;
+ struct pviter_t *iterp;
+
+ if ((bi = cmp_drvld_bitndx(&np, hp, "vpiLoad/vpiLocalLoad")) == -1)
+  return(NULL);
+
+ itp = hp->hin_itp;
+ num = bld_bit_lds(np, bi, itp, FALSE);
+ if (num <= 0) return(NULL);
+
+ iterp = __alloc_iter(num, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, num*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, num*sizeof(struct hrec_t));
+ for (hi = 0; hi < num; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+}
+
+/*
+ * build net bit loads or drivers iterator
+ * 
+ * fills ithtab that then gets copied from later 
+ *
+ * since per bit never a need to remove duplicates
+ * passed itp is instance of load npp
+ * notice this works for scalar where bi must be -1
+ */
+static int32 bld_bit_lds(struct net_t *np, int32 bi, struct itree_t *itp,
+ int32 no_ports)
+{
+ register struct net_pin_t *npp;
+ register struct hrec_t *hrp2;
+ int32 ri1, ri2, cnt, nd_itpop;
+ struct h_t tmph, *hp2;
+ struct hrec_t tmphrec;
+ 
+ __push_itstk(itp);
+ /* iconn loads are input ports */
+ for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
+  {
+   /* SJM 07/12/01 - until add v2k delay devices, omit mipd chg load */ 
+   if (npp->npntyp == NP_MIPD_NCHG) continue;
+
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT
+    && npp->npaux->npu.filtitp != __inst_ptr) continue;
+
+   /* can be iconn from other instance for xmr */
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - must match each inst in xmr path */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+
+   /* this must run with right itree loc. */
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   if (ri1 == -1 || bi == -1) goto got_match;   
+   if (bi > ri1 || bi < ri2) goto nxt_npp;
+
+got_match:
+   if (no_ports)
+    {
+     /* remove port npp's */
+     switch ((byte) npp->npntyp) {
+      case NP_ICONN: case NP_BIDICONN: case NP_MDPRT: case NP_BIDMDPRT:
+      case NP_PB_ICONN: case NP_PB_MDPRT:
+       goto nxt_npp;
+      default: break;
+     }
+    }
+
+   __init_hrec(&tmphrec);
+   tmphrec.in_iter = TRUE;
+   tmph.hrec = &tmphrec;
+
+   if (!fill_bit_ld_handle(&tmph, &tmphrec, bi, ri1, ri2, npp)) goto nxt_npp; 
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+
+   memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
+
+   hp2->hin_itp = tmph.hin_itp;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+ /* will be no drivers and no tran channel for reg */
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   /* DBG remove --- */
+   if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   goto done;
+  }
+ /* tran channel connections if they exist */
+ if (np->ntraux == NULL) goto done;
+
+ /* iconn tran channel connections are all loads */
+ for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
+  {
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT
+    && npp->npaux->npu.filtitp != __inst_ptr) continue;
+
+   /* can be iconn from other instance for xmr */
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - must match each inst in xmr path */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+
+   /* this must run with right itree loc. */
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   if (ri1 == -1 || bi == -1) goto got2_match;   
+   if (bi > ri1 || bi < ri2) goto nxt2_npp;
+
+got2_match:
+   if (no_ports)
+    {
+     /* remove port npp's */
+     switch ((byte) npp->npntyp) {
+      case NP_ICONN: case NP_BIDICONN: case NP_MDPRT: case NP_BIDMDPRT:
+      case NP_PB_ICONN: case NP_PB_MDPRT:
+       goto nxt2_npp;
+      default: break;
+     }
+    }
+   __init_hrec(&tmphrec);
+   tmphrec.in_iter = TRUE;
+   tmph.hrec = &tmphrec;
+
+   if (!fill_bit_ld_handle(&tmph, &tmphrec, bi, ri1, ri2, npp)) goto nxt_npp; 
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+
+   memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
+
+   hp2->hin_itp = tmph.hin_itp;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt2_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+done:
+ __pop_itstk();
+ return(cnt);
+}
+
+/*
+ * fill a load handle - if non handle element, return nil
+ *
+ * caller must have initialized fields in handle
+ * this must be called from ref. (stacked itree loc) for xmr 
+ *
+ * looking for load of net np bit bi (if scalar not called) 
+ */
+static int32 fill_bit_ld_handle(struct h_t *hp, struct hrec_t *hrp, int32 bi,
+ int32 ri1, int32 ri2, struct net_pin_t *npp)
+{
+ int32 not_lhs;
+ struct itree_t *itp2;
+ struct mod_t *downmdp;
+ struct mod_pin_t *mpp;
+ struct gate_t *gp;
+
+ hp->hin_itp = __inst_ptr;
+ switch ((byte) npp->npntyp) {
+  case NP_ICONN: case NP_BIDICONN:
+   /* load iconn is input port */
+   itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   downmdp = itp2->itip->imsym->el.emdp;
+   mpp = &(downmdp->mpins[npp->obnum]);
+   if (!iconnbit_lvalue(mpp, npp, itp2)) not_lhs = TRUE; 
+   else not_lhs = FALSE;
+   if (mpp->mpwide == 1 || not_lhs) hrp->htyp = vpiPort;
+   else
+    {
+     hrp->htyp = vpiPortBit;
+     /* notice these are internal h:0 - fixed when index accessed */
+     if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
+    }
+   hrp->hu.hpi = npp->obnum;
+   hp->hin_itp = itp2;
+   break;
+  case NP_PB_ICONN: 
+   /* load iconn is concat high conn one bit of PB separated input port */
+   itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   downmdp = itp2->itip->imsym->el.emdp;
+   mpp = &(downmdp->mpins[npp->obnum]);
+   mpp = &(mpp->pbmpps[npp->pbi]);
+   hrp->htyp = vpiPortBit;
+   hrp->hi = bi;
+   hrp->hu.hpi = npp->obnum;
+   hp->hin_itp = itp2;
+   break;
+  case NP_MDPRT: case NP_BIDMDPRT:
+   /* load mod port is output port */
+   mpp = &(__inst_mod->mpins[npp->obnum]);
+   if (mpp->mpref->optyp == LCB || mpp->mpwide == 1) hrp->htyp = vpiPort;
+   else
+    {
+     hrp->htyp = vpiPortBit;
+     /* notice these are internal h:0 - fixed when index accessed */
+     /* correct for port bit from non concatenate net bit */ 
+     if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
+    }
+   hrp->hu.hpi = npp->obnum;
+   break;
+  case NP_PB_MDPRT:
+   /* load mod port is output port - this is one bit from PB decompose */
+   /* but still for vpi_ do not use decomposed mpp */
+   mpp = &(__inst_mod->mpins[npp->obnum]);
+   /* SJM 11/15/02 - LOOKATME ??? - why is this filter needed */
+   if (npp->npntyp == NP_PB_MDPRT && npp->pbi != 0) return(FALSE);
+   hrp->htyp = vpiPortBit;
+   /* notice these are internal h:0 - fixed when index accessed */
+   /* correct for port bit from non concatenate net bit */ 
+   if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
+   hrp->hu.hpi = npp->obnum;
+   break;
+  case NP_CONTA:
+   hrp->htyp = vpiContAssign;
+   hrp->hu.hcap = npp->elnpp.ecap;
+   break;
+  case NP_GATE: case NP_TRANIF: case NP_TRAN:
+   gp = npp->elnpp.egp; 
+   /* must correct for 1 bit conta */
+   if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
+    {
+     hrp->htyp = vpiContAssign;
+     hrp->htyp2 = vpiGate;
+     hrp->hu.hgp = npp->elnpp.egp;
+     break;
+    }
+   hrp->htyp = vpiPrimTerm;
+   hrp->hu.hgp = gp;
+   hrp->hi = npp->obnum;
+   break;
+  default: return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * ROUTINES TO BUILD XL STYLE LOAD ITERATORS (SCALAR OR BIT ONLY)
+ */
+
+/*
+ * build an iterator of wire or reg bit XL style collapsed loads
+ *
+ * inout ports and trans are both loads and drivers 
+ *
+ * no ports here - cross and include actual loads from other side
+ * algorithm sort of (mostly?) duplicates XL collapsing
+ * only makes sense for 1 bit objects
+ *
+ * uese local loads but cross ports 
+ */
+extern vpiHandle __bld_lds_iterator(struct h_t *hp, int32 otype)
+{
+ struct hrec_t *hrp;
+
+ if (hp == NULL) return(__nil_iter_err(otype));
+
+ hrp = hp->hrec;
+ /* routine for each thing that load can be of */
+ switch (hrp->htyp) {
+  case vpiNet: case vpiReg: 
+   if (hrp->hu.hnp->nwid != 1) goto bad_obj;
+   return(bit_xl_ldsdrvs_iter(hp, TRUE));
+  case vpiNetBit: case vpiRegBit: case vpiVarSelect:
+   return(bit_xl_ldsdrvs_iter(hp, TRUE));
+  default:
+bad_obj:
+   __vpi_err(1874, vpiError,
+    "vpiLoad 1-to-many iterator from %s illegal - for one bit net or reg loads only",
+    __to_vpionam(__wrks1, hrp->htyp));
+  }  
+ return(NULL);
+}
+
+/*
+ * build bit XL collapsed style net loads iterator
+ *
+ * caller must know type of iterator that is scanned since ld and driver
+ * same except for list used
+ *
+ * differs from acc next load "iterators" because returns contas and
+ * does not distinguish cells 
+ */
+static vpiHandle bit_xl_ldsdrvs_iter(struct h_t *hp, int32 do_loads)
+{
+ register int32 vti, hi;
+ int32 bi, vtxnum, num, xlnum, new2siz;
+ vpiHandle ihref;
+ struct hrec_t *hrp;
+ struct itree_t *itp;
+ struct net_t *np;
+ struct xldlvtx_t *xldlvp;
+ struct pviter_t *iterp;
+
+ itp = hp->hin_itp;
+ hrp = hp->hrec;
+ /* know if not bit object, then scalar net or reg */
+ if (hrp->htyp == vpiReg || hrp->htyp == vpiNet)
+  {
+   np = hrp->hu.hnp;
+   bi = -1;
+  }
+ else
+  {
+   if ((bi = cmp_drvld_bitndx(&np, hp, "vpiLoad")) == -1) return(NULL);
+  }
+ /* know there will always be one */
+ /* 4th arg. T means loads */
+ vtxnum = __bld_xl_drvld_vtxtab(np, bi, itp, do_loads);
+
+ for (vti = 0, xlnum = 0; vti < vtxnum; vti++)
+  {
+   xldlvp = __xldlvtxind[vti];
+   /* DBG remove -- */
+   if (xldlvp == NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+
+   /* fill ith tab with only non port loads or drivers */ 
+   if (do_loads)
+    {
+     num = bld_bit_lds(xldlvp->dlnp, xldlvp->dlbi, xldlvp->dlitp, TRUE);
+    }
+   else
+    {
+     num = bld_bit_drvs(xldlvp->dlnp, xldlvp->dlbi, xldlvp->dlitp, TRUE);
+    }
+
+   /* copy onto end of 2nd ith tab */
+   if (num > 0)
+    {
+     new2siz = xlnum + num;
+     if (new2siz >= __ithtsiz2) __grow_htab2(num);
+
+     memcpy(&(__ithtab2[xlnum]), __ithtab, num*sizeof(struct h_t));
+     memcpy(&(__ithrectab2[xlnum]), __ithrectab, num*sizeof(struct hrec_t));
+     for (hi = xlnum; hi < num + xlnum; hi++)
+      { __ithtab2[hi].hrec = &(__ithrectab2[hi]); }
+     xlnum += num;
+    }
+   __my_free((char *) xldlvp, sizeof(struct xldlvtx_t));
+   __xldlvtxind[vti] = NULL;
+  }
+ __num_xldlvtxs = 0;
+
+ /* iterator may be empty */
+ if(xlnum <= 0) return(NULL);
+
+ /* final step copy from 2nd ith tab into iterator */
+ iterp = __alloc_iter(xlnum, &ihref);
+ memcpy(iterp->scanhtab, __ithtab2, xlnum*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab2, xlnum*sizeof(struct hrec_t));
+ for (hi = 0; hi < xlnum; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ /* xl style ld/drvr vertex table to empty */
+ return(ihref);
+}
+
+/*
+ * ROUTINES TO BUILD LOCAL DRIVER ITERATOR 
+ */
+
+/*
+ * build an iterator of local wire drivers
+ *
+ * regs have only qausi-continuous vpiForce and vpiRelease drivers
+ *
+ * includes user added vpi drivers
+ *
+ * inout ports and trans are both loads and drivers 
+ * user must traverse all of channel to get hard drivers of inout
+ */
+extern vpiHandle __bld_loc_drvs_iterator(struct h_t *hp, int32 otype)
+{
+ if (hp == NULL) return(__nil_iter_err(otype));
+
+ switch (hp->hrec->htyp) {
+  case vpiNet:
+   return(net_drvs_iter(hp));
+  case vpiNetBit:
+   return(bit_drvs_iter(hp));
+
+  case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+  case vpiRegBit: case vpiVarSelect:
+   /* quasi-procedural force and assign are only drivers of regs */
+   /* also never per bit */
+   return(reg_drvs_iter(hp));
+  default:
+   __vpi_err(1877, vpiError,
+    "vpiDriver 1-to-many iterator from %s illegal - only variables have drivers",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+  }  
+ return(NULL);
+}
+
+/*
+ * build entire wire net drivers iterator - in list if any bits
+ *
+ * normal drivers plus pull and per bit force
+ */
+static vpiHandle net_drvs_iter(struct h_t *hp)
+{
+ register int32 hi;
+ int32 num;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct itree_t *itp; 
+ struct pviter_t *iterp;
+
+ np = hp->hrec->hu.hnp;
+ itp = hp->hin_itp;
+ num = bld_net_drvs(np, itp);
+ if (num <= 0) return(NULL);
+
+ iterp = __alloc_iter(num, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, num*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, num*sizeof(struct hrec_t));
+ for (hi = 0; hi < num; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+}
+
+/*
+ * build drivers on a net
+ *
+ * entire net drivers are not net bit
+ * nothing on itree stack here
+ */
+static int32 bld_net_drvs(struct net_t *np, struct itree_t *itp)
+{
+ register int32 bi;
+ register struct net_pin_t *npp;
+ int32 cnt, cnt2, nd_itpop;
+ struct h_t tmph, *hp2;
+ struct hrec_t tmphrec, *hrp2;
+ struct qcval_t *frc_qcp; 
+ 
+ __push_itstk(itp);
+ for (cnt = 0, npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   /* SJM 09/20/02 - for per bit input port drivers only use first */
+   if (npp->npntyp == NP_PB_MDPRT && npp->pbi != 0) continue; 
+
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
+    continue;
+   /* maybe move to right ref. itree loc. */ 
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - must match each inst in xmr path */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+   __init_hrec(&tmphrec);
+   tmphrec.in_iter = TRUE;
+   tmph.hrec = &tmphrec;
+
+   if (!fill_drv_handle(&tmph, &tmphrec, npp)) goto nxt_npp;
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+
+   memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
+   hp2->hin_itp = tmph.hin_itp;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+ cnt2 = cnt;
+ /* will be no drivers and no tran channel for reg */
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   /* DBG remove --- */
+   if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   goto do_force;
+  } 
+ /* tran channel npps - go in both ld and driver iterators */
+ if (np->ntraux == NULL) goto do_force;
+
+ /* notice any tran channel tran/inout port is driver and load */
+ for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
+  {
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
+    continue;
+   /* maybe move to right ref. itree loc. */ 
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - must match each inst in xmr path */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+
+   __init_hrec(&tmphrec);
+   tmphrec.in_iter = TRUE;
+   tmph.hrec = &tmphrec;
+
+   if (!fill_drv_handle(&tmph, &tmphrec, npp)) goto nxt2_npp;
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+
+   memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
+   hp2->hin_itp = tmph.hin_itp;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt2_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+ cnt2 = cnt;
+
+do_force:
+ /* if not in src or added by PLI, can't be active */  
+ if (!np->frc_assgn_allocated) goto done;
+
+ /* for scalar bit 0 right */
+ /* ?? LOOKATME - this was low to high */
+ frc_qcp = &(np->nu2.qcval[__inum*np->nwid + np->nwid - 1]);
+ /* 11/22/02 AIV removed equal in for break bi >= */
+ for (bi = np->nwid - 1; bi > 0; bi--, frc_qcp--)
+  {
+  
+   /* 11/22/02 AIV must check for null case */
+   if(frc_qcp == NULL) break;
+   if (frc_qcp->qc_active)
+    {
+     /* FIXME - vpi_ driver not found as driver - vpi_ must keep track */ 
+     /* if vpi_ force, do not return as driver */
+     if (frc_qcp->qcstp == NULL) continue;
+
+     __init_hrec(&tmphrec);
+     tmphrec.in_iter = TRUE;
+     tmph.hrec = &tmphrec;
+
+     tmphrec.htyp = vpiForce;
+     tmphrec.hu.hstp = frc_qcp->qcstp;
+     tmph.hin_itp = __inst_ptr;
+
+     if (cnt != 0 && same_vpi_handle(__ithtab, cnt2, cnt, &tmph, &tmphrec))
+      continue;
+
+     if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+     hp2 = &(__ithtab[cnt]);
+     hrp2 = &(__ithrectab[cnt++]);
+     memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
+     hp2->hin_itp = tmph.hin_itp;
+     /* only need to set cross link in newly added one */
+     hp2->hrec = hrp2;
+    }
+  }
+
+done:
+ __pop_itstk();
+ return(cnt);
+}
+
+/*
+ * fill a driver handle (hp) - if non handle element, return nil
+ * notice same rules for loads and drivers (iterator type determines)
+ *
+ * caller must have initialized fields (for iterator type) 
+ * this must be called from ref. (stacked itree loc) for xmr 
+ */
+static int32 fill_drv_handle(struct h_t *hp, struct hrec_t *hrp,
+ struct net_pin_t *npp)
+{
+ struct itree_t *itp2;
+ struct gate_t *gp;
+
+ hp->hin_itp = __inst_ptr;
+ switch ((byte) npp->npntyp) {
+  case NP_ICONN: case NP_BIDICONN:
+   /* SJM 09/20/02 - PB ICONN form only possible for loads */
+   /* iconn driver is output port */
+   hrp->htyp = vpiPort;
+   hrp->hu.hpi = npp->obnum;
+   itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   hp->hin_itp = itp2;
+   break;
+  case NP_MDPRT: case NP_BIDMDPRT: case NP_PB_MDPRT:
+   /* iconn driver is input port */
+   hrp->htyp = vpiPort;
+   hrp->hu.hpi = npp->obnum;
+   break;
+  case NP_CONTA:
+   hrp->htyp = vpiContAssign;
+   hrp->hu.hcap = npp->elnpp.ecap;
+   break;
+  case NP_GATE: case NP_TRANIF: case NP_TRAN:
+   gp = npp->elnpp.egp; 
+   if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
+    {
+     hrp->htyp = vpiContAssign;
+     hrp->htyp2 = vpiGate;
+     hrp->hu.hgp = gp;
+    }
+   else
+    {
+     hrp->htyp = vpiPrimTerm;
+     hrp->hu.hgp = gp;
+     hrp->hi = npp->obnum;
+    }
+   break;
+  case NP_VPIPUTV:
+   /* include entire wire or any bit's driver here */
+   if (npp->npaux != NULL && npp->npaux->nbi1 != -1)
+    {
+     hrp->htyp = vpiNetBitDriver;  
+     hrp->hi = npp->npaux->nbi1;
+    }
+   else hrp->htyp = vpiNetDriver;
+   hrp->hu.hnpp = npp;
+   break;
+  case NP_PULL:
+   gp = npp->elnpp.egp; 
+   hrp->htyp = vpiPrimTerm;
+   hrp->hu.hgp = gp;
+   hrp->hi = npp->obnum;
+   break;
+  default: return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * build the iterator for all port bits connecting to inside module instances
+ * given a vpi net or reg bit handle, build iterator of port bit handles
+ */
+static vpiHandle bit_drvs_iter(struct h_t *hp)
+{
+ register int32 hi;
+ int32 bi, num;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct itree_t *itp;
+ struct pviter_t *iterp;
+
+ if ((bi = cmp_drvld_bitndx(&np, hp, "vpiDriver/vpiLocalDriver")) == -1)
+  return(NULL);
+
+ itp = hp->hin_itp;
+ num = bld_bit_drvs(np, bi, itp, FALSE);
+ if (num <= 0) return(NULL);
+
+ iterp = __alloc_iter(num, &ihref);
+ memcpy(iterp->scanhtab, __ithtab, num*sizeof(struct h_t));
+ memcpy(iterp->ihrectab, __ithrectab, num*sizeof(struct hrec_t));
+ for (hi = 0; hi < num; hi++)
+  {
+   iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
+  }
+ return(ihref);
+}
+
+/*
+ * build net bit drivers iterator
+ *
+ * nothing on itree stack here?
+ * since per bit never a need to remove duplicates
+ */
+static int32 bld_bit_drvs(struct net_t *np, int32 bi, struct itree_t *itp,
+ int32 no_ports)
+{
+ register struct net_pin_t *npp;
+ int32 ri1, ri2, cnt, nd_itpop;
+ struct h_t tmph, *hp2;
+ struct hrec_t tmphrec, *hrp2;
+ struct qcval_t *frc_qcp;
+ 
+ __push_itstk(itp);
+ /* iconn drivers are output ports */
+ for (cnt = 0, npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT
+    && npp->npaux->npu.filtitp != __inst_ptr) continue;
+
+   /* can be iconn from other instance for xmr */
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - must match each inst in xmr path */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+
+   /* this must run with right itree loc. */
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   /* for scalar bi will be -1 here */  
+   if (ri1 == -1 || bi == -1) goto got_match;   
+   if (bi > ri1 || bi < ri2) goto nxt_npp;
+
+got_match:
+   if (no_ports)
+    {
+     /* remove port npp's */
+     switch ((byte) npp->npntyp) {
+      case NP_ICONN: case NP_BIDICONN: case NP_MDPRT: case NP_BIDMDPRT:
+      case NP_PB_MDPRT: case NP_PB_ICONN:
+       goto nxt_npp;
+      default: break;
+     }
+    }
+   __init_hrec(&tmphrec);
+   tmphrec.in_iter = TRUE;
+   tmph.hrec = &tmphrec;
+
+   if (!fill_bit_drv_handle(&tmph, &tmphrec, bi, ri1, ri2, npp)) goto nxt_npp; 
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+
+   memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
+   hp2->hin_itp = tmph.hin_itp;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+ /* will be no drivers and no tran channel for reg */
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   /* DBG remove --- */
+   if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   goto do_force;
+  }
+ /* tran channel connections if they exist */
+ if (np->ntraux == NULL) goto do_force;
+
+ /* iconn drivers are output ports */
+ for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
+  {
+   /* filter out per inst. that is not this instance */
+   if (npp->npproctyp == NP_PROC_FILT
+    && npp->npaux->npu.filtitp != __inst_ptr) continue;
+
+   /* can be iconn from other instance for xmr */
+   nd_itpop = FALSE;
+   if (npp->npproctyp != NP_PROC_INMOD)
+    {
+     /* SJM 04/17/03 - must match each inst in xmr path */
+     if (!__move_to_npprefloc(npp)) continue;
+     nd_itpop = TRUE;
+    }
+
+   /* this must run with right itree loc. */
+   __get_bidnpp_sect(np, npp, &ri1, &ri2);
+   /* for scalar bi will be -1 here */  
+   if (ri1 == -1 || bi == -1) goto got2_match;   
+   if (bi > ri1 || bi < ri2) goto nxt2_npp;
+
+got2_match:
+   if (no_ports)
+    {
+     /* remove port npp's */
+     switch ((byte) npp->npntyp) {
+      case NP_ICONN: case NP_BIDICONN: case NP_MDPRT: case NP_BIDMDPRT:
+      case NP_PB_ICONN: case NP_PB_MDPRT:
+       goto nxt2_npp;
+      default: break;
+     }
+    }
+
+   __init_hrec(&tmphrec);
+   tmphrec.in_iter = TRUE;
+   tmph.hrec = &tmphrec;
+
+   if (!fill_bit_drv_handle(&tmph, &tmphrec, bi, ri1, ri2, npp)) goto nxt_npp; 
+
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+
+   memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
+   hp2->hin_itp = tmph.hin_itp;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+
+nxt2_npp:
+   if (nd_itpop) __pop_itstk();
+  }
+
+do_force:
+ if (!np->frc_assgn_allocated) goto done;
+ /* this is 1 bit form */
+ frc_qcp = &(np->nu2.qcval[__inum*np->nwid + ((bi == -1) ? 0 : bi)]);
+ if (frc_qcp->qc_active)
+  {
+   /* FIXME - vpi_ driver not found as driver - vpi_ must keep track */ 
+   /* if vpi_ force, do not return as driver */
+   if (frc_qcp->qcstp == NULL) goto done;
+
+   /* there is an active force - maybe just constant */
+   if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
+   hp2 = &(__ithtab[cnt]);
+   hrp2 = &(__ithrectab[cnt++]);
+   __init_hrec(hrp2);
+
+   hrp2->in_iter = TRUE;
+   hrp2->htyp = vpiForce;
+   hrp2->hu.hstp = frc_qcp->qcstp;
+   hp2->hin_itp = __inst_ptr;
+   /* only need to set cross link in newly added one */
+   hp2->hrec = hrp2;
+  }
+done:
+ __pop_itstk();
+ return(cnt);
+}
+
+/*
+ * fill a bit driver handle - if non handle element, return nil
+ *
+ * caller must have initialized fields in handle
+ * this must be called from ref. (stacked itree loc) for xmr 
+ *
+ * looking for driver of net np bit bi (if scalar not called) 
+ *
+ * LOOKATME - except for pull, same as fill bit ld handle - right?
+ */
+static int32 fill_bit_drv_handle(struct h_t *hp, struct hrec_t *hrp, int32 bi,
+ int32 ri1, int32 ri2, struct net_pin_t *npp)
+{
+ int32 not_lhs;
+ struct itree_t *itp2;
+ struct mod_t *downmdp;
+ struct mod_pin_t *mpp;
+ struct gate_t *gp;
+
+ hp->hin_itp = __inst_ptr;
+ switch ((byte) npp->npntyp) {
+  case NP_ICONN: case NP_BIDICONN:
+   /* driver iconn is output port */
+   itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
+   downmdp = itp2->itip->imsym->el.emdp;
+   mpp = &(downmdp->mpins[npp->obnum]);
+   if (!iconnbit_lvalue(mpp, npp, itp2)) not_lhs = TRUE; 
+   else not_lhs = FALSE;
+   if (mpp->mpwide == 1 || not_lhs) hrp->htyp = vpiPort;
+   else
+    {
+     hrp->htyp = vpiPortBit;
+     /* notice these are internal h:0 - fixed when index accessed */
+     /* correct for port bit from non concatenate net bit */ 
+     if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
+    }
+   hrp->hu.hpi = npp->obnum;
+   hp->hin_itp = itp2;
+   break;
+  case NP_MDPRT: case NP_BIDMDPRT:
+   /* driver mod port is input port */
+   mpp = &(__inst_mod->mpins[npp->obnum]);
+   if (mpp->mpref->optyp == LCB || mpp->mpwide == 1) hrp->htyp = vpiPort;
+   else
+    {
+     hrp->htyp = vpiPortBit;
+     /* notice these are internal h:0 - fixed when index accessed */
+     /* correct for port bit from non concatenate net bit */ 
+     if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
+    }
+   hrp->hu.hpi = npp->obnum;
+   break;
+  case NP_PB_MDPRT:
+   /* driver is bit of separated into per bits mod input port */
+   hrp->htyp = vpiPortBit;
+   hrp->hu.hpi = npp->obnum;
+   if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
+   break;
+  case NP_CONTA:
+   hrp->htyp = vpiContAssign;
+   hrp->hu.hcap = npp->elnpp.ecap;
+   break;
+  case NP_GATE: case NP_TRANIF: case NP_TRAN:
+   gp = npp->elnpp.egp; 
+   /* must correct for 1 bit conta */
+   if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
+    {
+     hrp->htyp = vpiContAssign;
+     hrp->htyp2 = vpiGate;
+     hrp->hu.hgp = npp->elnpp.egp;
+     break;
+    }
+   hrp->htyp = vpiPrimTerm;
+   hrp->hu.hgp = gp;
+   hrp->hi = npp->obnum;
+   break;
+  case NP_VPIPUTV:
+   /* include entire wire (know overlaps) or matching bit's driver here */
+   if (npp->npaux != NULL && npp->npaux->nbi1 != -1)
+    {
+     if (npp->npaux->nbi1 != bi) break; 
+     hrp->htyp = vpiNetBitDriver;  
+     hrp->hi = npp->npaux->nbi1;
+    }
+   else hrp->htyp = vpiNetDriver;
+   hrp->hu.hnpp = npp;
+   break;
+  case NP_PULL: 
+   gp = npp->elnpp.egp; 
+   hrp->htyp = vpiPrimTerm;
+   hrp->hu.hgp = gp;
+   hrp->hi = npp->obnum;
+   break;
+  default: return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * build iterator for drivers of a reg (or variable)
+ *
+ * only possible drivers are quasi continuous force or assign 
+ * notice only one can be active (i.e. either no iter or size 1)
+ *
+ * d.s for reg qcval is 2 qcval's per inst. - one for entire reg force and
+ * one for qc assign 
+ */
+static vpiHandle reg_drvs_iter(struct h_t *hp)
+{
+ register struct hrec_t *hrp2;
+ vpiHandle ihref;
+ struct net_t *np;
+ struct itree_t *itp; 
+ struct pviter_t *iterp;
+ struct h_t *hp2;
+ struct qcval_t *assgn_qcp, *frc_qcp;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ np = hrp->hu.hnp;
+ itp = hp->hin_itp;
+
+ /* not in src or added by PLI, can't be active */
+ if (!np->frc_assgn_allocated) return(NULL);
+
+ frc_qcp = &(np->nu2.qcval[2*itp->itinum]);
+ if (frc_qcp->qc_active)
+  {
+   /* FIXME - vpi_ driver not found as driver - vpi_ must keep track */ 
+   /* if vpi_ force know will not be reg qc assign */
+   if (frc_qcp->qcstp == NULL) return(NULL);
+
+   /* there is an active force - maybe just constant */
+   iterp = __alloc_iter(1, &ihref);
+   hp2 = &(iterp->scanhtab[0]);
+   hrp2 = hp2->hrec;
+
+   hrp2->htyp = vpiForce;
+   hrp2->hu.hstp = frc_qcp->qcstp;
+   hp2->hin_itp = itp;
+   return(ihref);
+  }
+
+ assgn_qcp = &(np->nu2.qcval[2*itp->itinum + 1]);
+ if (!assgn_qcp->qc_active) return(NULL);
+ iterp = __alloc_iter(1, &ihref);
+ hp2 = &(iterp->scanhtab[0]);
+ hrp2 = hp2->hrec;
+
+ hrp2->htyp = vpiAssignStmt;
+ hrp2->hu.hstp = assgn_qcp->qcstp;
+ hp2->hin_itp = itp;
+ return(ihref);
+}
+
+/* 
+ * ROUTINES TO BUILD XL STYLE DRIVER ITERATOR (SCALAR OR BIT ONLY)
+ */
+
+/*
+ * build an iterator of wire or reg bit XL style collapsed drivers
+ *
+ * inout ports and trans are both loads and drivers 
+ *
+ * no ports here - cross and include actual loads from other side
+ * algorithm sort of (mostly?) duplicates XL collapsing
+ * only makes sense for 1 bit objects
+ */
+extern vpiHandle __bld_drvs_iterator(struct h_t *hp, int32 otype)
+{
+ if (hp == NULL) return(__nil_iter_err(otype));
+
+ /* routine for each thing that load can be of */
+ switch (hp->hrec->htyp) {
+  case vpiNet: case vpiReg: 
+   if (hp->hrec->hu.hnp->nwid != 1) goto bad_obj;
+   return(bit_xl_ldsdrvs_iter(hp, FALSE));
+  case vpiNetBit:
+   return(bit_xl_ldsdrvs_iter(hp, FALSE));
+
+  /* quasi-procedural force and assign are only drivers of regs */
+  /* also really never per bit and no cross module iconn/port */
+  case vpiRegBit: case vpiVarSelect:
+   return(reg_drvs_iter(hp));
+
+  default:
+bad_obj:
+   __vpi_err(1874, vpiError,
+    "vpiLoad 1-to-many iterator from %s illegal - for one bit net or reg loads only",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+  }  
+ return(NULL);
+}
+
+/*
+ * ITERATOR SCAN ROUTINES
+ */
+
+/*
+ * given a handle returned by vpi iterator, get next object
+ * and move to one past
+ *
+ * easy since table of right object type handles already built
+ * LOOKATME - for empty iterator is this supposed to return nil (think yes)
+ */
+extern vpiHandle vpi_scan(vpiHandle iterator)
+{
+ register struct pviter_t *iterp;
+ register struct h_t *ihp, *hp;
+ 
+ /* assume no error */
+ __last_eip = NULL;
+ if (__run_state == SS_COMP) { __still_comp_err("vpi_scan"); return(NULL); } 
+ ihp = (struct h_t *) iterator;
+ if (ihp == NULL) return(NULL);
+ if (!__validate_handle("vpi_scan (iterator)", ihp)) return(NULL);
+ if (ihp->hrec->htyp != vpiIterator) 
+  {
+   __vpi_err(1864, vpiError,
+    "vpi_scan passed handle of type %s - must be vpiIterator",
+    __to_vpionam(__wrks1, ihp->hrec->htyp));
+   return(NULL);
+  }
+ /* for last, return and move past end - then next call return nil and free */
+ iterp = ihp->hrec->hu.hiterp;
+ if (iterp->nxthi == -1) 
+  {
+   __vpi_err(1862, vpiError,
+    "vpi_scan iterator handle invalid because scan already finished or error");
+   return(NULL);
+  }
+ if (iterp->nxthi >= iterp->numhs)
+  {
+   iterp->nxthi = -1;
+   __free_iterator(iterator);
+   return(NULL);
+  }
+ hp = &(iterp->scanhtab[iterp->nxthi]);
+ /* here can not free since corrupt handle */
+ if (!__validate_handle("vpi_scan (component)", hp))
+  {
+   iterp->nxthi = -1;
+   return(NULL);
+  } 
+ (iterp->nxthi)++;
+ return((vpiHandle) hp);
+}
+
+/*
+ * ROUTINES FOR OBTAINING HANDLES
+ */
+ 
+/*
+ * get handle by name - use symbol table of scope (task or itree loc) 
+ *
+ * LRM does not allow vpiFullName for ports
+ */
+extern vpiHandle vpi_handle_by_name(char *name, vpiHandle scope)
+{
+ int32 sav_ecnt;
+ vpiHandle href; 
+ struct h_t *hp;
+ struct symtab_t *sytp;
+ struct itree_t *itp;
+ struct hrec_t *hrp;
+
+ sav_ecnt = __pv_err_cnt;
+ __last_eip = NULL;
+ if (__run_state == SS_COMP)
+  { __still_comp_err("vpi_handle_by_name"); return(NULL); } 
+ if (scope == NULL)
+  {
+   href = cnvt_name_to_handle(name, (struct symtab_t *) NULL,
+    (struct itree_t *) NULL);
+   goto done;
+  }
+
+ hp = (struct h_t *) scope;
+ if (!__validate_handle("vpi_handle_by_name", hp)) return(NULL);
+ hrp = hp->hrec;
+ itp = hp->hin_itp;
+ switch (hrp->htyp) {
+  case vpiModule:
+   sytp = itp->itip->imsym->el.emdp->msymtab;
+   break;
+  case vpiTask: case vpiFunction:
+   sytp = hrp->hu.htskp->tsksymtab;
+   break;
+  case vpiNamedBegin: case vpiNamedFork:
+   sytp = hrp->hu.htskp->tsksymtab;
+   break; 
+  default:
+   __vpi_err(1868, vpiError,
+    "vpi_handle_by_name scope object must be scope handle - %s illegal",
+   __to_vpionam(__wrks1, hrp->htyp));
+  return(NULL);
+ }
+ href = cnvt_name_to_handle(name, sytp, itp);
+
+done:
+ if (sav_ecnt < __pv_err_cnt)
+  {
+   __vpi_err(1878, vpiError,
+    "vpi_handle_by_name failed - name %s illegal", name);
+  }
+ return(href);
+}
+
+/*
+ * convert a name to a handle 
+ *
+ * sytp is scope to start in - if nil, then reference is rooted 
+ * if sytp nil so must be scopitp
+ *
+ * on error, this returns nil
+ * FIXME - figure out whether last gnc was set to last or to last non net
+ *         if so this routine is wrong because it uses last
+ * LOOKATME - this routine fails on arr of insts (comp. with numeric ind)
+ *            but so far that is correct unless LRM changes - if g/i array 
+ *            passed, not seen here
+ */
+static vpiHandle cnvt_name_to_handle(char *nam, struct symtab_t *sytp,
+ struct itree_t *scopitp)
+{
+ int32 ii, has_dot;
+ struct itree_t *itp;
+ struct expr_t *glbndp, *gcmp_ndp;
+ struct sy_t *syp, *hsyp;
+ struct mod_t *mdp;
+ struct inst_t *ip;
+ char *chp;
+ byte *bp1, *bp2;
+
+ /* case 1 - xmr name */
+ has_dot = __name_vpi_hasdot(nam);
+ if (has_dot)
+  {
+   itp = NULL;
+   if ((glbndp = __glbnam_to_expr(nam)) == NULL) return(NULL);
+   gcmp_ndp = glbndp->ru.x;
+   if (sytp == NULL)
+    {
+     chp = __to_glbcmp_nam(gcmp_ndp);
+     if ((ii = __ip_indsrch(chp)) == -1)
+      {
+ret_nil:
+       if (glbndp != NULL) __free_xtree(glbndp);
+       return(NULL);
+      }
+     itp = __it_roots[ii];
+     sytp = itp->itip->imsym->el.emdp->msymtab;
+     gcmp_ndp = gcmp_ndp->ru.x;
+    }
+   else itp = scopitp;
+
+   for (; gcmp_ndp != NULL;)
+    {
+     chp = __to_glbcmp_nam(gcmp_ndp);
+     /* look up first in context then in specify section */
+     if ((syp = __get_nongia_sym(chp, sytp)) == NULL)
+      {
+       if (gcmp_ndp->ru.x != NULL) goto ret_nil;
+       /* this is last component */
+       hsyp = sytp->sypofsyt; 
+       if (hsyp->sytyp != SYM_M) goto ret_nil;
+ 
+       mdp = itp->itip->imsym->el.emdp;
+       /* first try specify section if it exists */ 
+       if (mdp->mspfy != NULL)
+        {
+         if ((syp = __get_sym(chp, mdp->mspfy->spfsyms)) != NULL)
+          {
+           if (glbndp != NULL) __free_xtree(glbndp);
+           return(bld_symhandle(nam, syp, sytp, itp));
+          }
+        }
+       goto ret_nil;
+      }
+     /* non scope symbol found in scope */
+     if (!__is_scope_sym(syp))
+      { 
+       /* if non scope symbol but not end of path - mismatch */
+       if (gcmp_ndp->ru.x != NULL) goto ret_nil;
+       if (glbndp != NULL) __free_xtree(glbndp);
+       /* end of path build whatever it is */
+       return(bld_symhandle(nam, syp, sytp, itp));
+      }
+     /* if last symbol, build the scope handle - this is inst. type ref */
+     if (gcmp_ndp->ru.x == NULL)
+      { 
+       if (glbndp != NULL) __free_xtree(glbndp);
+       return(bld_symhandle(nam, syp, sytp, itp));
+      }
+     /* scope symbol - maybe descend */
+     if (syp->sytyp == SYM_I)
+      {
+       /* syp in itp */
+       ip = syp->el.eip;
+       mdp = itp->itip->imsym->el.emdp;
+       bp1 = (byte *) ip;
+       bp2 = (byte *) mdp->minsts;
+       ii = (bp1 - bp2)/sizeof(struct inst_t);
+       itp = &(itp->in_its[ii]);
+       sytp = itp->itip->imsym->el.emdp->msymtab;
+      }
+     else sytp = syp->el.etskp->tsksymtab;
+     if ((gcmp_ndp = gcmp_ndp->ru.x) == NULL) break;
+    }
+   __vpi_terr(__FILE__, __LINE__);
+   if (glbndp != NULL) __free_xtree(glbndp);
+   return(NULL);
+  }
+
+ /* case 2: simple name */
+ itp = scopitp;
+ /* top level module name */ 
+ if (sytp == NULL)
+  {
+   /* LOOKATME - could add getting user defined systf here by name */
+   /* but LRM says only things with vpiFullName properties can be accessed */
+   if ((ii = __ip_indsrch(nam)) == -1)
+    {
+     return(NULL);
+    }
+   itp = __it_roots[ii];
+   return(__mk_handle(vpiModule, (void *) itp->itip->imsym->el.emdp, itp,
+    (struct task_t *) NULL));
+  }
+ hsyp = sytp->sypofsyt; 
+ /* case 1b simple name in some scope */
+ if ((syp = __get_nongia_sym(nam, sytp)) == NULL)
+  {
+   if (hsyp->sytyp != SYM_M) return(NULL);
+
+   mdp = hsyp->el.emdp;
+   /* try specify section if it exists */ 
+   if (mdp->mspfy != NULL)
+    {
+     if ((syp = __get_sym(nam, mdp->mspfy->spfsyms)) != NULL)
+      return(bld_symhandle(nam, syp, sytp, itp));
+    }
+   return(NULL);
+  }
+ /* simple name found in scope */
+ return(bld_symhandle(nam, syp, sytp, itp));
+}
+
+/*
+ * build a handle from a symbol
+ *
+ * nam here just for error messages
+ */
+static vpiHandle bld_symhandle(char *nam, struct sy_t *syp,
+ struct symtab_t *sytp, struct itree_t *itp)
+{
+ int32 ii, ttyp;
+ word32 otyp;
+ vpiHandle href;
+ struct sy_t *in_tsyp;
+ struct task_t *intskp, *tskp;
+ struct mod_t *mdp;
+ struct inst_t *ip;
+ struct itree_t *down_itp;
+ struct gate_t *gp;
+ struct net_t *np;
+ struct h_t *hp;
+ byte *bp1, *bp2;
+
+ in_tsyp = sytp->sypofsyt;
+ if (in_tsyp->sytyp == SYM_M) intskp = NULL; else intskp = in_tsyp->el.etskp;
+
+ switch ((byte) syp->sytyp) {
+   case SYM_I:
+    if (intskp != NULL) __vpi_terr(__FILE__, __LINE__);
+    mdp = itp->itip->imsym->el.emdp;  
+    ip = syp->el.eip;
+    bp1 = (byte *) ip;
+    bp2 = (byte *) mdp->minsts;
+    ii = (bp1 - bp2)/sizeof(struct inst_t);
+    down_itp = &(itp->in_its[ii]);
+    href = __mk_handle(vpiModule, (void *) down_itp->itip->imsym->el.emdp,
+     down_itp, (struct task_t *) NULL);
+    break;
+   case SYM_TSK: case SYM_F: case SYM_LB: 
+    tskp = syp->el.etskp;
+    ttyp = __to_vpi_tasktyp(tskp->tsktyp);
+    href = __mk_handle(ttyp, (void *) tskp, itp, intskp);
+    break;
+   case SYM_PRIM:
+    if (intskp != NULL) __vpi_terr(__FILE__, __LINE__);
+    gp = syp->el.egp;
+    if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
+     {
+      href = __mk_handle(vpiContAssign, (void *) gp, itp, NULL);
+      hp = (struct h_t *) href;
+      hp->hrec->htyp2 = vpiGate;
+      break;
+     }
+    href = __mk_handle(__gate_to_vpiprimtyp(gp), (void *) gp, itp, NULL);
+    break;
+   case SYM_N:
+    np = syp->el.enp;
+    if (np->n_isaparam)
+     {
+      /* case 1: specparam */
+      if (np->nu.ct->p_specparam)
+       {
+        href = __mk_handle(vpiSpecParam, (void *) np, itp, NULL);
+       }
+      else
+       {
+        /* case 2: parameter */ 
+        /* if local imported param - always returns global "real" copy */
+        /* now just fall thru to make param handle */
+        href = __mk_handle(vpiParameter, (void *) np, itp, NULL);
+       }
+      break;  
+     }
+    /* case 3: variable (wire/net) and never select */
+    /* 01/25/00 SJM - for imported global net this is just normal net */
+    otyp = __ntyp_to_vpivarhtyp(np);
+    href = __mk_handle(otyp, (void *) np, itp, intskp); 
+    break;
+   /* these are Cver extensions for added delay setting system tasks */
+   case SYM_CA:
+    href = __mk_handle(vpiContAssign, (void *) syp->el.ecap, itp, NULL);
+    break;
+   case SYM_TCHK:
+    href = __mk_handle(vpiTchk, (void *) syp->el.etcp, itp, NULL);
+    break;
+   case SYM_PTH:
+    href = __mk_handle(vpiTchk, (void *) syp->el.epthp, itp, NULL);
+    break;
+   case SYM_UDP:
+    __vpi_err(1856, vpiError,
+     "vpi_handle_by_name of udp definition %s object not supported",
+     nam);
+    return(NULL);
+   /* never should see SYM_M - if top level this not called */
+   /* preprocess (SYM_DEF) and system task (SYM_SF) never seen here */
+   default: __vpi_terr(__FILE__, __LINE__); return(NULL);
+  }
+ return(href);
+}
+
+/*
+ * return T if has dot (xmr type path)
+ *
+ * tricky because last name in xmr path can be escaped
+ */
+extern int32 __name_vpi_hasdot(char *nam)
+{
+ register char *chp;
+
+ for (chp = nam; *chp != '\0'; chp++)
+  {
+   if (*chp == '.') return(TRUE);
+   if (*chp == '\\')
+    {
+     for (chp++;; chp++)
+      {
+       if (*chp == ' ') goto nxt_comp; 
+       if (*chp == '\0') break;
+      }
+     return(FALSE);
+    }
+nxt_comp:;
+  }
+ return(FALSE);
+}
+
+/*
+ * get a bit handle from its index
+ *
+ * error and return NULL for non indexable handle
+ * this is passed user [i1:i2] range index instead of normalized internal
+ */
+extern vpiHandle vpi_handle_by_index(vpiHandle object, int32 indx)
+{  
+ int32 biti, ri1, ri2, wid;
+ word32 ityp;
+ word32 av, bv;
+ vpiHandle href;
+ struct h_t *hp, *hp2;
+ struct net_t *np;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+ struct xstk_t *xsp;
+ struct hrec_t *hrp, *hrp2;
+
+ __last_eip = NULL;
+ if (__run_state == SS_COMP)
+  { __still_comp_err("vpi_handle_by_index"); return(NULL); } 
+ hp = (struct h_t *) object;
+ if (!__validate_handle("vpi_handle_by_index", hp)) return(NULL);
+ hrp = hp->hrec;
+
+ ri1 = ri2 = 0;
+ switch (hrp->htyp) {
+  case vpiMemory: case vpiParamArray:
+   /* convert index to internal range */
+   np = hrp->hu.hnp;
+   if (!np->n_isarr) __vpi_terr(__FILE__, __LINE__);
+   __getarr_range(np, &ri1, &ri2, &wid);
+   biti = normalize_ndx_(indx, ri1, ri2);
+   if (biti < 0 || biti >= wid)
+    {
+bad_ndx:
+     __vpi_err(1828, vpiError,
+      "vpi_handle_by_index index %d of %s out of range [%d:%d]", indx,
+      __to_vpionam(__wrks1, hrp->htyp), ri1, ri2);
+     return(NULL);
+    }
+   if (hrp->htyp == vpiMemory) ityp = vpiMemoryWord;
+   else ityp = vpiParamArrayWord;
+   href = __mk_handle(ityp, (void *) np, hp->hin_itp, NULL);
+   hp2 = (struct h_t *) href;
+   hrp2 = hp2->hrec;
+   hrp2->hi = biti;
+   hrp2->bith_ndx = TRUE;
+   break;
+  /* notice can not index from vpiParamArrayWord - converted to const */
+  case vpiMemoryWord:
+   /* LOOKATME - should this be vpiRegBit object? */
+   /* this evaluates expr. to array and bit or for bith form just get ndx */
+   biti = __get_vpinet_index(&np, hp);
+
+   /* DBG remove --- */
+   if (!np->n_isarr) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   if (!np->n_isavec) goto no_ndx;
+   /* load the array */
+   __getarr_range(np, &ri1, &ri2, &wid);
+   push_xstk_(xsp, np->nwid); 
+   __ld_arr_val(xsp->ap, xsp->bp, np->nva, wid, np->nwid, biti);
+   /* determine (normalize) bit */
+   __getwir_range(np, &ri1, &ri2);
+   biti = normalize_ndx_(indx, ri1, ri2);
+   if (biti < 0 || biti >= np->nwid) { __pop_xstk(); goto bad_ndx; }
+   av = rhsbsel_(xsp->ap, biti);
+   bv = rhsbsel_(xsp->bp, biti);
+   __pop_xstk();
+   href = __mk_handle(vpiConstant, (void *) NULL, hp->hin_itp,
+    hp->hrec->hin_tskp);
+   hp2 = (struct h_t *) href;
+   hrp2 = hp2->hrec;
+   hrp2->hu.hxp = __bld_rng_numxpr(av, bv, 1);
+   hrp2->free_xpr = TRUE;
+   break;
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   np = hrp->hu.hnp;
+   if (!np->n_isavec)
+    {
+no_ndx:
+     __vpi_err(2027, vpiWarning,
+      "vpi_handle_by_index of non indexable object %s - index of scalar illegal",  
+      __to_vpionam(__wrks1, hrp->htyp));
+     return(NULL);
+    }
+   __getwir_range(np, &ri1, &ri2);
+   biti = normalize_ndx_(indx, ri1, ri2);
+   if (biti < 0 || biti >= np->nwid) goto bad_ndx;
+   ityp = __to_vpinetbithtyp(np->ntyp);
+   href = __mk_handle(ityp, (void *) np, hp->hin_itp, NULL);
+   hp2 = (struct h_t *) href;
+   hrp2 = hp2->hrec; 
+   hrp2->hi = biti;
+   hrp2->bith_ndx = TRUE;
+   break;
+  case vpiPort: 
+   /* port ranges always wid-1:0 since not declared (can be 0) */
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   mpp = &(mdp->mpins[hrp->hu.hpi]);
+   if (mpp->mpwide == 1) goto no_ndx;
+   ri1 = mpp->mpwide - 1;
+   ri2 = 0;
+   if (indx < 0 || indx > ri1) goto bad_ndx;
+   href = __mk_handle(vpiPortBit, (void *) hrp->hu.hpi, hp->hin_itp, NULL);
+   hp2 = (struct h_t *) href;
+   hrp2 = hp2->hrec;
+   hrp2->hi = indx;
+   break;
+  default:
+   __vpi_err(1846, vpiError,
+    "vpi_handle_index failed because %s has no contained indexable object", 
+    __to_vpionam(__wrks1, hrp->htyp));
+   return(NULL);  
+ }  
+ return(href);
+}
+
+/*
+ * new handle by index that requires new 2001 multi-dimensional vectors
+ * and is only way to access them by indexing
+ *
+ * WRITME - add multi-dimensional vector support
+ */
+extern vpiHandle vpi_handle_by_multi_index(vpiHandle obj, PLI_INT32 num_index,
+ PLI_INT32 *index_array)
+{
+ __vpi_err(1801, vpiError,
+  "new P1364 2001 vpi_handle_by_multi_index unsupported because multi-dimensional arrays not supported");
+ return(NULL);
+}
+
+/*
+ * ROUTINES TO GET PROPERTIES
+ */
+
+/* 
+ * get property type property for object object if it exists
+ */
+extern int32 vpi_get(PLI_INT32 property, vpiHandle object)
+{
+ PLI_INT32 pval;
+ int32 casetyp;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+
+ __last_eip = NULL;
+ if (__run_state == SS_COMP)
+  {
+   __still_comp_err("vpi_get");
+   return(vpiUndefined);
+  } 
+ if (!validate_property("vpi_get", property)) return(0);
+ /* special case return smallest time precision (not units) in design */
+ if (object == NULL)
+  {
+   /* design wide these are same - could be timeformat unit */
+   /* LOOKATME - acc_ equivalent returns timeformat precision here */ 
+   if (property == vpiTimePrecision)
+    { pval = -((int32) __des_timeprec); return(pval); } 
+   else if (property == vpiTimeUnit)
+    { pval = -((int32) __des_timeprec); return(pval); } 
+   __vpi_err(1865, vpiError,  
+    "property %s illegal for vpi_get with NULL object - only for timescale",
+    __to_vpipnam(__wrks1, property));
+   return(vpiUndefined);
+  }
+ hp = (struct h_t *) object;
+ if (!__validate_handle("vpi_get", hp)) return(vpiUndefined);
+ hrp = hp->hrec;
+
+ /* vpiType special meta property for handle object */
+ if (property == vpiType) return(hrp->htyp);
+
+ switch (hrp->htyp) {
+  /* notice - not in LRM but iterators have size property */
+  case vpiIterator:
+   if (property != vpiSize)
+    { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
+   return(hrp->hu.hiterp->numhs);
+  case vpiModule:   
+   pval = modprop_vpiget(hp, property);
+   break;
+  case vpiNet: case vpiNetBit:
+   pval = netprop_vpiget(hp, property);
+   break;
+  case vpiReg: case vpiRegBit: case vpiIntegerVar: case vpiTimeVar:
+  case vpiRealVar: case vpiVarSelect: case vpiNamedEvent:
+   pval = regprop_vpiget(hp, property);
+   break;
+  case vpiMemory: case vpiParamArray:
+   pval = arrprop_vpiget(hp, property);
+   break;
+  case vpiMemoryWord: case vpiParamArrayWord:
+   pval = arrwrdprop_vpiget(hp, property);
+   break;
+  case vpiParameter: case vpiSpecParam:
+   pval = paramprop_vpiget(hp, property);
+   break;
+  case vpiPort: case vpiPortBit:
+   pval = portprop_vpiget(hp, property);
+   break;
+  case vpiGate: case vpiUdp: case vpiSwitch:
+   pval = gateprop_vpiget(hp, property);
+   break;
+  case vpiPrimTerm:
+   pval = __primtermprop_vpiget(hp, property);
+   break;
+  case vpiContAssign:
+   pval = contaprop_vpiget(hp, property);
+   break;
+  case vpiFuncCall: case vpiSysFuncCall:
+   pval = fcallprop_vpiget(hp, property);
+   break;
+  case vpiTaskCall: case vpiSysTaskCall:
+   pval = tcallprop_vpiget(hp, property);
+   break;
+  /* this is function definition not call */
+  case vpiFunction:
+   pval = funcdefprop_vpiget(hp, property);
+   break;
+  case vpiTchk:
+   pval = tchkprop_vpiget(hp, property);
+   break;
+  case vpiTchkTerm:
+   pval = tchktermprop_vpiget(hp, property);
+   break;
+  case vpiModPath:
+   pval = pthprop_vpiget(hp, property);
+   break;
+  case vpiPathTerm:
+   pval = pthtermprop_vpiget(hp, property);
+   break;
+  case vpiSchedBitEvent: 
+   if (property != vpiScheduled)
+    { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
+   /* for vector wire driver form only T if all bits done */
+   if (hrp->evnt_done) return(FALSE);
+   return(TRUE);
+  case vpiSchedEvent:
+   if (property != vpiScheduled)
+    { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
+   /* for non table form bit determines if done or canceled */
+   if (hrp->evnt_done) return(FALSE);
+   /* table vectored driver form - must re-check for */
+   if (hrp->bith_ndx)
+    {
+     register int32 bi;
+     struct net_t *np;
+     i_tev_ndx *evtabi, tevpi;
+
+     np = hrp->hu.hevrec->evnp;
+     evtabi = hrp->hu.hevrec->evndxtab;
+     /* ?? LOOKATME - this was low to high */
+     for (bi = np->nwid - 1; bi >= 0; bi--)
+      {
+       tevpi = evtabi[bi];
+       if (tevpi != -1 && !(__tevtab[tevpi].te_cancel)) return(FALSE);
+      }
+    }
+   return(TRUE);
+
+  /* all statements and processes - not processes (init/always) */
+  case vpiAssignStmt: case vpiBegin: case vpiDeassign:
+  case vpiDelayControl: case vpiEventControl: case vpiDisable:
+  case vpiEventStmt: case vpiFor: case vpiForce: case vpiForever:
+  case vpiFork: case vpiIf: case vpiIfElse: case vpiNullStmt:
+  case vpiRelease: case vpiRepeat: case vpiWait: case vpiWhile:
+try_line_prop:
+   if (property != vpiLineNo)
+    { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
+   pval = hrp->hu.hstp->stlin_cnt;
+   break;
+  /* named blocks are tasks although "in line" */ 
+  case vpiNamedBegin: case vpiNamedFork:
+   if (property != vpiLineNo)
+    { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
+   pval = hrp->hu.htskp->tsksyp->sylin_cnt;
+   break;
+  case vpiDefParam:
+   if (property != vpiLineNo)
+    { notpropof_err(vpiDefParam, property); return(vpiUndefined); }
+   pval = (int32) hrp->hu.hdfp->dfplin_cnt;
+   break;
+  case vpiParamAssign:
+   if (property != vpiLineNo)
+    { notpropof_err(vpiParamAssign, property); return(vpiUndefined); }
+   pval = (int32) hrp->hu.hnp->nsym->sylin_cnt;
+   break;
+  case vpiAssignment:
+   if (property == vpiBlocking)
+    {
+     if (hrp->hu.hstp->rl_stmttyp == S_NBPROCA) pval = TRUE;
+     else pval = FALSE;
+     break;
+    }
+   goto try_line_prop;
+  case vpiCase:
+   if (property == vpiCaseType)
+    {
+     casetyp = hrp->hu.hstp->st.scs.castyp;
+     if (casetyp == CASEZ) pval = vpiCaseZ;
+     else if (casetyp == CASEX) pval = vpiCaseX;
+     else pval = vpiCaseExact;
+     break;
+    }
+   goto try_line_prop;
+  /* all elements of expr. class that are not variables or selects of vars */
+  case vpiConstant: case vpiPartSelect: case vpiOperation:
+   pval = exprclass_prop_vpiget(hp, property);
+   break;
+  case vpiIODecl:
+   pval = iodecl_prop_vpiget(hp, property);
+   break;
+  case vpiUdpDefn:
+   pval = udpdefnprop_vpiget(hp, property);
+   break;
+  case vpiTableEntry:
+   pval = udptabentryprop_vpiget(hp, property);
+   break;
+  case vpiAttribute:
+   pval = dig_attrprop_vpiget(hp, property);
+   break;
+  case vpiCallback:
+   /* property for enable (active or on) call back is vpiActive, i.e. on */
+   if (property != vpiActive)
+    { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
+   if (hrp->hu.hcbp->cb_user_off) return(FALSE);
+   return(TRUE); 
+   
+  default:
+   notpropof_err(hrp->htyp, property);
+   return(vpiUndefined);
+  }
+ return(pval);
+} 
+
+/*
+ * validate property
+ * returns F on error
+ */
+static int32 validate_property(char *rnam, int32 proptyp)
+{
+ if (__to_vpipnam(__wrks1, proptyp) == NULL || proptyp == vpiUndefined)
+  {
+   __vpi_err(1819, vpiError,
+    "%s: property %d illegal or out of range", rnam, proptyp);
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * get int32 property values for module (inst. itree loc.)
+ */
+static int32 modprop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct mod_t *mdp;
+  
+ mdp = hp->hrec->hu.hmdp;
+ switch (prop) {
+  case vpiCellInstance:
+   if (mdp->m_iscell) return(TRUE);
+   return(FALSE);
+  /* delay modes not supported by Cver */
+  case vpiDefDelayMode: return(vpiDelayModeNone);
+  case vpiLineNo: return(hp->hin_itp->itip->isym->sylin_cnt);
+  case vpiDefLineNo: return(mdp->msym->sylin_cnt);
+  case vpiProtected: return(FALSE);
+  case vpiTimeUnit:
+   if (!mdp->mno_unitcnv) pval = -((int32) mdp->mtime_units);
+   /* if no time scale both precision and units the same */
+   else pval = -((int32) __des_timeprec);
+   return(pval);
+  case vpiTimePrecision:
+   if (!mdp->mno_unitcnv)
+    pval = -((int32) (mdp->mtime_units + mdp->mtime_prec));
+   else pval = -((int32) __des_timeprec);
+   return(pval);
+  case vpiDefNetType: return(__to_vpi_netproptyp(mdp->mod_dfltntyp));
+  case vpiUnconnDrive:
+   if (mdp->mod_uncdrv == TOK_NONE) return(vpiHighZ); 
+   if (mdp->mod_uncdrv == PULL0) return(vpiPull0);
+   if (mdp->mod_uncdrv == PULL1) return(vpiPull1);
+   __vpi_terr(__FILE__, __LINE__);
+   return(0);
+  case vpiTopModule: 
+   if (mdp->minstnum == 0) return(TRUE);
+   return(FALSE);
+  /* LOOKATME - what should this be? */
+  case vpiDefDecayTime: return(0);
+  default: notpropof_err(hp->hrec->htyp, prop); break;
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * emit not property of handle err
+ *
+ * know hp non nil or will not get here
+ */
+static void notpropof_err(word32 typh, int32 prop)
+{
+ __vpi_err(1867, vpiError,  
+  "property %s not defined for vpi_get of %s",
+  __to_vpipnam(__wrks1, prop), __to_vpionam(__wrks2, typh));
+}
+
+/*
+ * get the vpi handle object type for a variable (net_t)
+ */
+extern word32 __ntyp_to_vpivarhtyp(struct net_t *np)
+{
+ word32 otyp;
+
+ if (np->n_isaparam)
+  {
+   if (np->n_isarr) otyp = vpiParamArray;
+   else otyp = vpiParameter;
+  }
+ else if (np->ntyp < NONWIRE_ST) otyp = vpiNet;
+ else if (np->n_isarr) otyp = vpiMemory;
+ else otyp = to_vpi_reghtyp(np->ntyp);
+ return(otyp);
+}
+
+/*
+ * routine to convert from internal Cver net (but known to be reg)
+ * type to vpi_ var object type
+ *
+ * SJM 08/11/97 - separated so old one type mapping from ntyp routine
+ *                now 3 depending on vpi_ output needed
+ */
+static word32 to_vpi_reghtyp(word32 ntyp)
+{
+ switch (ntyp) {
+  case N_REG: return(vpiReg);
+  case N_INT: return(vpiIntegerVar);
+  case N_TIME: return(vpiTimeVar);
+  case N_REAL: return(vpiRealVar);
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(0);
+}
+
+/*
+ * convert a Cver side net type to vpi_ var bit select type
+ */
+extern word32 __to_vpinetbithtyp(word32 ntyp)
+{
+ if (ntyp < NONWIRE_ST) return(vpiNetBit);
+ switch (ntyp) {
+  case N_REG: return(vpiRegBit);
+  case N_INT: case N_TIME: case N_REAL: return(vpiVarSelect);
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(0);
+}
+
+/*
+ * routine to convert from internal Cver wire type to vpi property value
+ * also converts internal net types to variable (reg,int32, ...) object types 
+ */
+extern int32 __to_vpi_netproptyp(word32 ntyp)
+{
+ switch (ntyp) {
+  case N_WIRE: return(vpiWire);
+  case N_WA: return(vpiWand);
+  case N_WO: return(vpiWor);
+  case N_TRI: return(vpiTri);
+  case N_TRI0: return(vpiTri0);
+  case N_TRI1: return(vpiTri1);
+  case N_TRIREG: return(vpiTriReg);
+  case N_TRIAND: return(vpiTriAnd);
+  case N_TRIOR: return(vpiTriOr); 
+  case N_SUPPLY0: return(vpiSupply0); 
+  case N_SUPPLY1: return(vpiSupply1);
+  case N_REG: return(vpiReg);
+  case N_INT: return(vpiIntegerVar);
+  case N_TIME: return(vpiTimeVar);
+  case N_REAL: return(vpiRealVar);
+  case N_EVENT: return(vpiNamedEvent);
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * routine to convert from vpi handle type known to be variable to
+ * to internal ntyp
+ * 
+ * never called with bit of (vpiNetBit or vpiRegBit) 
+ */
+extern word32 __from_vpi_vartyp(word32 pval)
+{
+ switch ((byte) pval) {
+  case vpiWire: return(N_WIRE);
+  case vpiWand: return(N_WA);
+  case vpiWor: return(N_WO);
+  case vpiTri: return(N_TRI);
+  case vpiTri0: return(N_TRI0);
+  case vpiTri1: return(N_TRI1);
+  case vpiTriReg: return(N_TRIREG);
+  case vpiTriAnd: return(N_TRIAND);
+  case vpiTriOr: return(N_TRIOR);
+  case vpiSupply0: return(N_SUPPLY0);
+  case vpiSupply1: return(N_SUPPLY1);
+  case vpiReg: return(N_REG);
+  case vpiIntegerVar: return(N_INT);
+  case vpiTimeVar: return(N_TIME);
+  case vpiRealVar: return(N_REAL);
+  case vpiNamedEvent: return(N_EVENT);
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(0);
+}
+
+/*
+ * get int32 property values of net for net or net bit (ignore bit)
+ */
+static int32 netprop_vpiget(struct h_t *hp, int32 prop) 
+{
+ int32 biti;
+ struct net_t *np;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ if (hrp->htyp == vpiNetBit)
+  {
+   if (hrp->bith_ndx) np = hrp->hu.hnp;
+   else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+  }
+ else np = hrp->hu.hnp;
+
+ switch (prop) {
+  case vpiExpanded: return(TRUE);
+  case vpiImplicitDecl:
+   if (np->nsym->sy_impldecl) return(TRUE); 
+   return(FALSE);
+  case vpiLineNo: return(np->nsym->sylin_cnt);
+  /* vpiNetDeclAssign undeclared in Cver */
+
+  /* get net type property (i.e vpiWand) not net expr. part obj htyp */
+  /* know net or net bit or will not get here */
+  case vpiNetType: return(__to_vpi_netproptyp(np->ntyp));
+  case vpiScalar:  
+   if (np->n_isavec) return(FALSE);
+   return(TRUE);
+  /* always false in Cver since the default */ 
+  case vpiExplicitScalared: return(FALSE);
+  case vpiSize:
+   if (hrp->htyp == vpiNetBit) return(1);
+   return(np->nwid);
+  /* no net strengths in Cver (or Verilog?) just charge */
+  /* if no charge strength returns 0 */
+  case vpiChargeStrength:
+   if (np->n_capsiz == CAP_NONE) return(0);
+   if (np->n_capsiz == CAP_SMALL) return(vpiSmallCharge);
+   if (np->n_capsiz == CAP_MED) return(vpiMediumCharge);
+   if (np->n_capsiz == CAP_LARGE) return(vpiLargeCharge);
+   __vpi_terr(__FILE__, __LINE__);
+   break;
+  case vpiVector:
+   if (np->n_isavec) return(TRUE);
+   return(FALSE);
+  case vpiConstantSelect:
+   if (hrp->htyp != vpiNetBit) goto bad_prop;
+   if (hrp->bith_ndx) return(TRUE);
+   if (__expr_is_vpiconst(hrp->hu.hxp->ru.x)) 
+    {
+     __push_itstk(hp->hin_itp);
+     /* if constant already normalized to h:0, else this will normalize */
+     /* variable index */
+     biti = __comp_ndx(np, hrp->hu.hxp->ru.x);
+     __pop_itstk();
+     if (biti == -1) return(FALSE);
+     return(TRUE);
+    }
+   return(FALSE);
+
+  default:
+bad_prop:
+    notpropof_err(hrp->htyp, prop); break;
+ }
+ return(vpiUndefined);
+}
+
+
+/*
+ * get int32 property values for reg or reg bit (includes int32 and time)
+ * all properties same
+ */
+static int32 regprop_vpiget(struct h_t *hp, int32 prop) 
+{
+ int32 biti, is_bit;
+ struct net_t *np;
+ struct hrec_t *hrp;
+ 
+ hrp = hp->hrec; 
+ is_bit = FALSE;
+ if (hrp->htyp == vpiRegBit || hrp->htyp == vpiVarSelect)
+  {
+   if (hrp->bith_ndx) np = hrp->hu.hnp;
+   else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+   is_bit = TRUE;
+  }
+ else np = hrp->hu.hnp;
+
+ switch (prop) {
+  case vpiLineNo: return(np->nsym->sylin_cnt);
+  case vpiScalar:  
+   if (np->n_isavec) return(FALSE);
+   return(TRUE);
+  case vpiSize:
+   if (is_bit) return(1);
+   return(np->nwid);
+  case vpiVector:
+   if (np->n_isavec && !is_bit) return(TRUE);
+   return(FALSE);
+  case vpiConstantSelect:
+   if (hrp->htyp != vpiRegBit && hrp->htyp != vpiVarSelect) goto bad_prop;
+   if (hrp->bith_ndx) return(TRUE);
+   if (__expr_is_vpiconst(hrp->hu.hxp->ru.x)) 
+    {
+     __push_itstk(hp->hin_itp);
+     /* if constant already normalized to h:0, else this will normalize */
+     /* variable index */
+     biti = __comp_ndx(np, hrp->hu.hxp->ru.x);
+     __pop_itstk();
+     if (biti == -1) return(FALSE);
+     return(TRUE);
+    }
+   return(FALSE);
+  default:
+bad_prop:
+   notpropof_err(hrp->htyp, prop); break;
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get int32 property values for array (know hp is array handle)
+ */
+static int32 arrprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct net_t *np;
+
+ np = hp->hrec->hu.hnp;
+ /* const type only for parameter array */
+ if (hp->hrec->htyp == vpiParamArray && prop == vpiConstType)
+  return(get_param_constyp(np));
+
+ switch (prop) {
+  case vpiLineNo: return(np->nsym->sylin_cnt);
+  case vpiSize: return(__get_arrwide(np));
+  default: notpropof_err(hp->hrec->htyp, prop); break;
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get int32 property values for word32 of array
+ */
+static int32 arrwrdprop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 biti;
+ struct net_t *np;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ if (hrp->bith_ndx) np = hrp->hu.hnp;
+ else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+
+ if (hrp->htyp == vpiParamArrayWord && prop == vpiConstType)
+  return(get_param_constyp(np));
+
+ switch (prop) {
+  case vpiLineNo: return(np->nsym->sylin_cnt);
+  case vpiSize: return(np->nwid);
+  case vpiConstantSelect:
+   if (hrp->bith_ndx) return(TRUE);
+   /* DBG remove --- */
+   /* for param array words - variable select impossible */
+   if (hrp->htyp == vpiParamArrayWord) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   if (__expr_is_vpiconst(hrp->hu.hxp->ru.x)) 
+    {
+     __push_itstk(hp->hin_itp);
+     /* if constant already normalized to h:0, else this will normalize */
+     /* variable index */
+     biti = __comp_ndx(np, hrp->hu.hxp->ru.x);
+     __pop_itstk();
+     if (biti == -1) return(FALSE);
+     return(TRUE);
+    }
+   return(FALSE);
+
+  default: notpropof_err(hrp->htyp, prop); break;
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get int32 property values for param
+ */
+static int32 paramprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct net_t *np;
+
+ np = hp->hrec->hu.hnp;
+ switch (prop) {
+  /* this will always be constant because evaluated to constant */
+  /* may have been expr in source but by here always a number */
+  case vpiConstType: return(get_param_constyp(np));
+  case vpiLineNo: return(np->nsym->sylin_cnt);
+  case vpiSize: return(np->nwid);
+  
+  default: notpropof_err(hp->hrec->htyp, prop); break;
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get param constant type property
+ */
+static int32 get_param_constyp(struct net_t *np)
+{
+ int32 ctyp;
+
+ ctyp = 0;
+ if (np->ntyp == N_REAL) return(vpiRealConst);
+ if (np->nu.ct->pstring) return(vpiStringConst);
+
+ switch (np->nu.ct->pbase) {
+  case BBIN: ctyp = vpiBinaryConst; break;
+  case BOCT: ctyp = vpiOctConst; break;
+  case BDEC: ctyp = vpiDecConst; break;
+  case BHEX: ctyp = vpiHexConst; break;
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(ctyp);
+}
+
+/*
+ * get int32 property values for port and port bit
+ */
+static int32 portprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ mpp = &(mdp->mpins[hrp->hu.hpi]);
+ switch (prop) {
+  case vpiConnByName: 
+   if (mpp->mp_explicit) return(TRUE);
+   return(FALSE);
+  case vpiDirection:  
+   if (mpp->mptyp == IO_IN) return(vpiInput);
+   if (mpp->mptyp == IO_OUT) return(vpiOutput);
+   if (mpp->mptyp == IO_BID) return(vpiInout);
+   __vpi_terr(__FILE__, __LINE__);
+   break;
+  case vpiExplicitName:
+   if (mpp->mpsnam == NULL) return(FALSE);
+   return(TRUE);  
+  case vpiPortIndex: return(hrp->hu.hpi);
+  case vpiLineNo: return(mpp->mplin_cnt);
+  case vpiScalar: return(mpp->mpwide == 1);
+  case vpiSize:
+   if (hrp->htyp == vpiPortBit) return(1);
+   return(mpp->mpwide);
+  case vpiVector:
+   if (hrp->htyp == vpiPortBit) return(FALSE);
+   return(mpp->mpwide != 1);
+  default: notpropof_err(hrp->htyp, prop); break;
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get int32 property values for primitives
+ */
+static int32 gateprop_vpiget(struct h_t *hp, int32 prop)
+{
+ word32 sval;
+ struct gate_t *gp;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ gp = hrp->hu.hgp;
+ switch (prop) {
+  case vpiLineNo: return(gp->gsym->sylin_cnt);
+  case vpiPrimType: return(__to_vpi_primtyp(gp));
+  /* LRM defines this as number of inputs */
+  case vpiSize:
+   /* switch all terminasl are inputs (counting inouts) */
+   if (hrp->htyp == vpiSwitch) return(gp->gpnum);
+   /* for udp get from udp definition */
+   if (hrp->htyp == vpiUdp) return(gp->gmsym->el.eudpp->numins);
+   /* all other have one output (cmos is 3 inputs and one output */
+   /* pullup/pulldown not seen here */
+   return(gp->gpnum - 1);
+  /* LOOKATME - what if no gate strength - no way to detect */
+  case vpiStrength0:
+   /* 0 is high 3 bits */
+   sval = (gp->g_stval >> 3) & 0x7;
+   return((int32) __map_tovpi_stren(sval));
+  case vpiStrength1:
+   /* 1 is low 3 bits */
+   sval = gp->g_stval & 0x7;
+   return((int32) __map_tovpi_stren(sval));
+  default: notpropof_err(hrp->htyp, prop); break;
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * routine to convert from internal Cver gate type to vpi primitive class
+ *
+ * i.e. type of udp or particular type of gate (not vpi gate rather vpi Buf)
+ */
+extern int32 __to_vpi_primtyp(struct gate_t *gp)
+{
+ struct primtab_t *ptp;
+ struct udp_t *udpp;
+
+ if (gp->g_class == GC_UDP)
+  {
+   udpp = gp->gmsym->el.eudpp;
+   if (udpp->utyp == U_COMB) return(vpiCombPrim);
+   return(vpiSeqPrim);
+  }
+ ptp = gp->gmsym->el.eprimp; 
+ switch ((byte) ptp->gateid) {
+  case G_BITREDAND: return(vpiAndPrim);
+  case G_NAND: return(vpiNandPrim);
+  case G_NOR: return(vpiNorPrim);
+  case G_BITREDOR: return(vpiOrPrim);
+  case G_BITREDXOR: return(vpiXorPrim);
+  case G_REDXNOR: return(vpiXnorPrim);
+  case G_BUF: return(vpiBufPrim);
+  case G_NOT: return(vpiNotPrim);
+  case G_BUFIF0: return(vpiBufif0Prim);
+  case G_BUFIF1: return(vpiBufif1Prim);
+  case G_NOTIF0: return(vpiNotif0Prim);
+  case G_NOTIF1: return(vpiNotif1Prim);
+  case G_NMOS: return(vpiNmosPrim);
+  case G_RNMOS: return(vpiRnmosPrim);
+  case G_PMOS: return(vpiPmosPrim);
+  case G_RPMOS: return(vpiRpmosPrim);
+  case G_CMOS: return(vpiCmosPrim);
+  case G_RCMOS: return(vpiRcmosPrim);
+  case G_TRAN: return(vpiTranPrim);
+  case G_RTRAN: return(vpiRtranPrim);
+  case G_TRANIF0: return(vpiTranif0Prim);
+  case G_RTRANIF0: return(vpiRtranif0Prim);
+  case G_TRANIF1: return(vpiTranif1Prim);
+  case G_RTRANIF1: return(vpiRtranif1Prim);
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get int32 property values for primitive (gate) terminals
+ */
+extern int32 __primtermprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct gate_t *gp;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ gp = hrp->hu.hgp;
+ switch (prop) {
+  case vpiDirection:
+   /* tran switch first 2 terminals always bid - third for tranif input */
+   if (gp->g_class == GC_TRAN || gp->g_class == GC_TRANIF)
+    {
+     if (hrp->hi == 2) return(vpiInput);
+     return(vpiInout);
+    }
+   /* first (0th) terminal always output */
+   if (hrp->hi == 0) return(vpiOutput);
+   /* rest always input - not supporting >1 outpu buf/not gates */
+   return(vpiInput);
+
+  case vpiTermIndex: return(hrp->hi);
+  case vpiLineNo: return(gp->gsym->sylin_cnt);
+  default: notpropof_err(hrp->htyp, prop); break;
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get property values for task call
+ *
+ * LOOKAT - interpreted LRM to allow vpUserDefn for user system tasks
+ * <not clear from even new Verilog 98 LRM page>
+ */
+static int32 tcallprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct tskcall_t *tkcp;
+ struct systsk_t *stbp;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ switch (prop) {
+  case vpiLineNo: return(hrp->hu.hstp->stlin_cnt);
+  case vpiUserDefn:
+   /* non system task is always user defined */
+   if (hrp->htyp == vpiTaskCall) return(TRUE);
+   tkcp = &(hrp->hu.hstp->st.stkc);
+   stbp = tkcp->tsksyx->lu.sy->el.esytbp;
+   if (stbp->stsknum > BASE_VERIUSERTFS) return(TRUE); 
+   return(FALSE);
+  default: notpropof_err(hrp->htyp, prop);
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get property values of function definition (task def. has only str props)
+ *
+ * this is only for user function definitions (vpiFunction) - use
+ * vpi get systtf_info for system functions
+ */
+static int32 funcdefprop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct net_t *np;
+ struct task_t *tskp;
+
+ tskp = hp->hrec->hu.htskp;
+ pval = 0;
+ switch (prop) { 
+  case vpiLineNo:
+   pval = tskp->tsksyp->sylin_cnt;
+   break;
+  case vpiFuncType: 
+   /* first pin for func. is the return value */
+   np = tskp->tskpins->tpsy->el.enp;
+   if (np->ntyp == N_INT) { pval = vpiIntFunc; break; }
+   if (np->ntyp == N_REAL) { pval = vpiRealFunc; break; }
+   if (np->ntyp == N_TIME) { pval = vpiTimeFunc; break; }
+   pval = vpiSizedFunc;
+   break;
+  case vpiSize:
+   /* first pin for func. is the return value */
+   np = tskp->tskpins->tpsy->el.enp;
+   pval = np->nwid;
+   break;
+  default: 
+   notpropof_err(hp->hrec->htyp, prop);
+   return(vpiUndefined);
+ }
+ return(pval);
+}
+
+/*
+ * get property values (int32) for cont assign
+ */
+static int32 contaprop_vpiget(struct h_t *hp, int32 prop)
+{
+ word32 sval;
+ struct conta_t *cap;
+ struct gate_t *gp;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ if (hrp->htyp2 == vpiGate)
+  {
+   gp = hrp->hu.hgp;
+   switch (prop) {
+    case vpiLineNo: return(gp->gsym->sylin_cnt);
+    case vpiNetDeclAssign:
+     /* in Cver always assuming not part of net since not preserved */
+     /* FIXME - should record */
+     return(FALSE);
+    case vpiStrength0:
+     /* 0 is high 3 bits */
+     sval = (gp->g_stval >> 3) & 0x7;
+     return((int32) __map_tovpi_stren(sval));
+    case vpiStrength1:
+     /* 1 is low 3 bits */
+     sval = gp->g_stval & 0x7;
+     return((int32) __map_tovpi_stren(sval));
+    default: notpropof_err(hrp->htyp, prop); break;
+   }
+   return(vpiUndefined);
+  } 
+ cap = hrp->hu.hcap;
+ switch (prop) {
+  case vpiLineNo: return(cap->casym->sylin_cnt);
+  /* vpiNetDeclAssign undeclared in Cver */
+  case vpiStrength0:
+   /* 0 is high 3 bits */
+   sval = (cap->ca_stval >> 3) & 0x7;
+   return((int32) __map_tovpi_stren(sval));
+  case vpiStrength1:
+   /* 1 is low 3 bits */
+   sval = cap->ca_stval & 0x7;
+   return((int32) __map_tovpi_stren(sval));
+  default: notpropof_err(hrp->htyp, prop); break;
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get property values for function call (user or system)
+ *
+ * name for vpiSysFunc and vpiFunc subtype property changed to vpiFuncType and
+ * now applies to both user and system functions: values now are
+ * vpiIntFunc, vpiRealFunc, vpiTimeFunc, vpiSizedFunc
+ *
+ * contrary to new Veirlog 98 LRM system func calls do not have line location
+ * so emitting warning and return 0
+ */
+static int32 fcallprop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct sy_t *fsyp;
+ struct sysfunc_t *sfbp;
+ struct task_t *tskp;
+ struct net_t *np;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ pval = 0;
+ /* case 1: user function call */
+ if (hrp->htyp == vpiFuncCall)
+  {
+   fsyp = hrp->hu.hxp->lu.x->lu.sy;
+   switch (prop) {
+    case vpiSize:
+     /* FIXME - what should size of real be - for now making it 0 */
+     if (hrp->hu.hxp->is_real) { pval = 0; break; }
+     pval = hrp->hu.hxp->szu.xclen;
+     break;
+    case vpiLineNo:
+     /* for compatibility making location 0 with inform */
+     __vpi_err(2112, vpiNotice,
+      "vpiLineNo property not saved for vpiFuncCall object - 0 returned");
+     pval = 0;
+     break; 
+    case vpiFuncType:
+     tskp = fsyp->el.etskp;
+     /* DBG remove --- */
+     if (tskp->tskpins == NULL || tskp->tskpins->tpsy == NULL)
+      __vpi_terr(__FILE__, __LINE__);
+     /* --- */
+     np = tskp->tskpins->tpsy->el.enp;
+     if (np->ntyp == N_INT) { pval = vpiIntFunc; break; }
+     if (np->ntyp == N_REAL) { pval = vpiRealFunc; break; }
+     if (np->ntyp == N_TIME) { pval = vpiTimeFunc; break; }
+     pval = vpiSizedFunc;
+     break;
+    default:
+no_prop:
+     notpropof_err(hrp->htyp, prop);
+     return(vpiUndefined);
+   }
+   return(pval);
+  }
+ /* DBG remove --- */
+ if (hrp->htyp != vpiSysFuncCall) __vpi_terr(__FILE__, __LINE__);
+ /* --- */ 
+
+ /* case 2: sysfunc of some type call */
+ fsyp = hrp->hu.hxp->lu.x->lu.sy;
+ sfbp = fsyp->el.esyftbp;
+ switch (prop) { 
+  case vpiUserDefn:
+   if (sfbp->syfnum > BASE_VERIUSERTFS) pval = TRUE;
+   else pval = FALSE;
+   break;
+  case vpiSize:
+   /* FIXME - what should size of real be - for now making it 0 */
+   if (sfbp->retntyp == N_REAL) { pval = 0; break; }
+   pval = hrp->hu.hxp->szu.xclen;
+   break;
+
+  /* as of Verilog 98, both normal and system functions have ret. type */
+  case vpiFuncType: 
+   if (sfbp->retntyp == N_INT) { pval = vpiIntFunc; break; }
+   if (sfbp->retntyp == N_REAL) { pval = vpiRealFunc; break; }
+   if (sfbp->retntyp == N_TIME) { pval = vpiTimeFunc; break; }
+   pval = vpiSizedFunc;
+   break;
+  case vpiLineNo: 
+   __vpi_err(2112, vpiNotice,
+    "vpiLineNo property not saved for vpiSysFuncCall object - 0 returned");
+   return(0);
+  default: goto no_prop;
+ }
+ return(pval);
+}
+
+/*
+ * get property values for tchk
+ */
+static int32 tchkprop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct tchk_t *tcp;
+
+ tcp = hp->hrec->hu.htcp; 
+ switch (prop) {
+  case vpiLineNo: pval = tcp->tcsym->sylin_cnt; break;
+  case vpiTchkType:
+   pval = to_vpi_tchktyp(tcp->tchktyp);
+   break;
+  default: notpropof_err(hp->hrec->htyp, prop); pval = vpiUndefined; 
+ }
+ return(pval);
+}
+
+/*
+ * routine to convert from internal Cver tchk type to vpi_ constant
+ *
+ * notice hold of setup hold separate tchk but will never see
+ */
+static int32 to_vpi_tchktyp(word32 tctyp)
+{
+ switch ((byte) tctyp) {
+  case TCHK_SETUP: return(vpiSetup);
+  case TCHK_HOLD: return(vpiHold);  
+  case TCHK_WIDTH: return(vpiWidth);
+  case TCHK_PERIOD: return(vpiPeriod);
+  case TCHK_SKEW: return(vpiSkew);
+  case TCHK_RECOVERY: return(vpiRecovery);
+  case TCHK_NOCHANGE: return(vpiNoChange);
+  case TCHK_SETUPHOLD: return(vpiSetupHold);
+  /* SJM 12/15/03 - new 2001 timing checks - recognized but not supported */
+  case TCHK_FULLSKEW: return(vpiFullskew);
+  case TCHK_RECREM: return(vpiRecrem);
+  case TCHK_REMOVAL: return(vpiRemoval);
+  case TCHK_TIMESKEW: return(vpiTimeskew);
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get property values for function call
+ * LOOKATME - think reversed 1st and 2nd term for setup already moved?
+ */
+static int32 tchktermprop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct tchk_t *tcp;
+
+ tcp = hp->hrec->hu.htcp;
+ switch (prop) {
+  case vpiLineNo: pval = tcp->tcsym->sylin_cnt; break;
+  case vpiEdge:
+   if (hp->hrec->htyp2 == vpiTchkRefTerm)
+    pval = to_vpi_edgeval(tcp->startedge);
+   else if (hp->hrec->htyp2 == vpiTchkDataTerm)
+    pval = to_vpi_edgeval(tcp->chkedge);
+   else { __vpi_terr(__FILE__, __LINE__); return(vpiUndefined); }
+   break;
+  default: notpropof_err(hp->hrec->htyp, prop); pval = vpiUndefined;
+ }
+ return(pval);
+}
+
+/*
+ * routine to convert from internal Cver edge to Vpi edge
+ * they are identical execept no any edge in Cver (same filtering algorithm)
+ * 
+ * LOOKATME: could just remove this identity mapping since same
+ */
+static int32 to_vpi_edgeval(word32 edg)
+{
+ switch ((byte) edg) {
+  case NOEDGE: return(vpiNoEdge);
+  case EDGE01: return(vpiEdge01);
+  case EDGE10: return(vpiEdge10);
+  case EDGE0X: return(vpiEdge0x);
+  case EDGEX1: return(vpiEdgex1);
+  case EDGE1X: return(vpiEdge1x);
+  case EDGEX0: return(vpiEdgex0);
+  case E_POSEDGE: return(vpiPosEdge);
+  case E_NEGEDGE: return(vpiNegEdge);
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ return(vpiUndefined);
+}
+
+/*
+ * get property values for function call
+ */
+static int32 pthprop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct spcpth_t *pthp;
+
+ pthp = hp->hrec->hu.hpthp;
+ switch (prop) {
+  case vpiLineNo: pval = pthp->pthsym->sylin_cnt; break;
+  case vpiPathType:
+   if (pthp->pthtyp == PTH_PAR) pval = vpiPathParallel;
+   else if (pthp->pthtyp == PTH_FULL) pval = vpiPathFull;
+   else { __vpi_terr(__FILE__, __LINE__); pval = vpiUndefined; }
+   break;
+  case vpiPolarity:
+   if (pthp->pthpolar == POLAR_PLUS) pval = vpiPositive;
+   else if (pthp->pthpolar == POLAR_MINUS) pval = vpiNegative;
+   else if (pthp->pthpolar == POLAR_NONE) pval = vpiUnknown;
+   else { __vpi_terr(__FILE__, __LINE__); pval = vpiUndefined; }
+   break;
+  case vpiDataPolarity:
+   if (pthp->dsrc_polar == POLAR_PLUS) pval = vpiPositive;
+   else if (pthp->dsrc_polar == POLAR_MINUS) pval = vpiNegative;
+   else if (pthp->dsrc_polar == POLAR_NONE) pval = vpiUnknown;
+   else { __vpi_terr(__FILE__, __LINE__); pval = vpiUndefined; }
+   break;
+  case vpiModPathHasIfNone: 
+   if (pthp->pth_ifnone) pval = TRUE; else pval = FALSE;
+   break; 
+  default: notpropof_err(hp->hrec->htyp, prop); pval = vpiUndefined;
+ }
+ return(pval);
+}
+
+/*
+ * get property values for function call
+ * handle is hu pthp, hi - index, htyp2 is list from 
+ */
+static int32 pthtermprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct spcpth_t *pthp; 
+ int32 pval;
+
+ pthp = hp->hrec->hu.hpthp;
+ switch (prop) {
+  case vpiLineNo: pval = pthp->pthsym->sylin_cnt; break;
+  case vpiDirection: pval = (int32) hp->hrec->htyp2; break;
+  case vpiEdge:
+   /* only path in has edge */
+   if (hp->hrec->htyp2 != vpiModPathIn) goto no_prop;
+   pval = to_vpi_edgeval(pthp->pthedge);
+   break;
+  default:
+no_prop:
+   notpropof_err(hp->hrec->htyp, prop);
+   pval = vpiUndefined;
+ }
+ return(pval);
+}
+
+/*
+ * get an expr property (know hp is vpiExpr to get here)
+ *
+ * uses changed semantics because of added vpiExpr object
+ */
+static int32 exprclass_prop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct expr_t *xp;
+
+ xp = hp->hrec->hu.hxp;
+ pval = vpiUndefined;
+ switch (hp->hrec->htyp) {
+  case vpiOperation:
+   if (prop == vpiOpType) pval = __expr_optype_get(xp);
+   else if (prop == vpiSize) pval = xp->szu.xclen;
+   else goto not_prop;
+   break;
+  case vpiConstant:
+   if (prop == vpiConstType)
+    {
+     return(get_vpi_const_typ(xp));
+    }
+   else if (prop == vpiSize) pval = xp->szu.xclen;
+   else goto not_prop;
+   break;  
+  /* misc. with no special properties */
+  case vpiFuncCall: case vpiSysFuncCall:
+   if (prop == vpiSize) pval = xp->szu.xclen;
+   else goto not_prop;
+   break;
+  case vpiPartSelect:
+   if (prop == vpiSize) pval = xp->szu.xclen;
+   else if (prop == vpiConstantSelect) pval = TRUE;
+   else goto not_prop;
+   break;
+  default: goto not_prop;
+ }
+ return(pval);
+
+not_prop:
+ notpropof_err(hp->hrec->htyp, prop);
+ return(vpiUndefined);
+}
+
+/*
+ * get constant type property from expression
+ */
+static int32 get_vpi_const_typ(struct expr_t *xp)
+{
+ if (xp->is_real) return(vpiRealConst); 
+ if (xp->is_string) return(vpiStringConst);
+ if (xp->ibase == BBIN) return(vpiBinaryConst);  
+ if (xp->ibase == BOCT) return(vpiOctConst);  
+ if (xp->ibase == BDEC) return(vpiDecConst);  
+ if (xp->ibase == BHEX) return(vpiHexConst);  
+ __vpi_terr(__FILE__, __LINE__);
+ return(vpiUndefined);
+}
+
+/*
+ * given an internal (ndp) expr node, return vpi_ expression htyp
+ *
+ * this gets type, no itree information needed
+ */
+extern int32 __exprtype_get(struct expr_t *ndp)
+{
+ struct net_t *np;
+ struct sy_t *syp;
+
+ /* in this case, must put value on tos */
+ switch ((byte) ndp->optyp) {
+  case NUMBER: case REALNUM: case ISNUMBER: case ISREALNUM:
+   return(vpiConstant);
+  case GLBREF: case ID:
+   np = ndp->lu.sy->el.enp; 
+   return(__ntyp_to_vpivarhtyp(np));
+  case LSB:
+   /* this must just return select from a variable (net/reg/var) */
+   return(vpiVarSelect);
+  case PARTSEL: return(vpiPartSelect);
+  case FCALL:
+   syp = ndp->lu.x->lu.sy;
+   if (syp->sytyp == SYM_SF) return(vpiSysFuncCall);
+   return(vpiFuncCall);
+ }
+ /* LOOKATME - currently no way to check - only other possibility is op */
+ return(vpiOperation);
+}
+
+/*
+ * for a binary or unary or ?: expression return the top node operator type
+ */
+extern int32 __expr_optype_get(struct expr_t *xp)
+{
+ switch ((byte) xp->optyp) { 
+  /* unary ops */
+  case BITNOT: return(vpiBitNegOp);
+  case REALNOT: case NOT: return(vpiNotOp);
+  /* both binary and unary in Cver */
+  case REALMINUS: case MINUS:
+   if (xp->ru.x == NULL) return(vpiMinusOp); 
+   return(vpiSubOp);
+  case PLUS: case REALPLUS:
+   if (xp->ru.x == NULL) return(vpiPlusOp);
+   return(vpiAddOp);
+  /* LOOKATME - vpiUnaryNorOp does not exist in Cver - decomposed */
+  case BITREDOR:
+   if (xp->ru.x == NULL) return(vpiUnaryOrOp);
+   return(vpiBitOrOp);
+  case BITREDXOR:
+   if (xp->ru.x == NULL) return(vpiUnaryXorOp);
+   return(vpiBitXorOp);
+  case REDXNOR:
+   if (xp->ru.x == NULL) return(vpiUnaryXNorOp);
+   return(vpiBitXNorOp);
+  /* vpiUnaryNandOp does not exist in Cver - decomposed */
+  case BITREDAND:
+   if (xp->ru.x == NULL) return(vpiUnaryAndOp);
+   return(vpiBitAndOp);
+
+  /* binary only ops */
+  case TIMES: case REALTIMES: return(vpiMultOp);
+  case DIV: case REALDIV: return(vpiDivOp);
+  case MOD: return(vpiModOp);
+  case REALRELGT: case RELGT: return(vpiGtOp);
+  case RELGE: case REALRELGE: return(vpiGeOp);
+  case RELLT: case REALRELLT: return(vpiLtOp);
+  case RELLE: case REALRELLE: return(vpiLeOp);
+  case RELCEQ: return(vpiCaseEqOp);
+  case RELCNEQ: return(vpiCaseNeqOp);
+  case RELEQ: case REALRELEQ: return(vpiEqOp);
+  case RELNEQ: case REALRELNEQ: return(vpiNeqOp);
+  case BOOLAND: case REALBOOLAND: return(vpiLogAndOp);
+  case BOOLOR: case REALBOOLOR: return(vpiLogOrOp);
+  case SHIFTL: return(vpiLShiftOp);
+  case ASHIFTL: return(vpiArithLShiftOp);
+  case SHIFTR: return(vpiRShiftOp);
+  case ASHIFTR: return(vpiArithRShiftOp);
+  case QUEST: case REALREALQUEST: case REALREGQUEST: case REGREALQCOL:
+    return(vpiConditionOp);
+  /* SJM 06/01/04 - ### ??? LOOKATME - vpi_ can't distinguish 2 ev or types */
+  case OPEVOR: case OPEVCOMMAOR: return(vpiEventOrOp);
+  case OPPOSEDGE: return(vpiPosedgeOp);
+  case OPNEGEDGE: return(vpiNegedgeOp);
+  case LCB: return(vpiConcatOp);
+  case CATREP: return(vpiMultiConcatOp);
+  case OPEMPTY: return(vpiNullOp);
+  default: __vpi_terr(__FILE__, __LINE__);
+ }  
+ return(vpiUndefined);
+}
+
+/*
+ * get properties of an iodecl object
+ *
+ * udp io decl indicated by htyp2 type of vpiUdpDefn
+ * if any bits of net are in port, entire net is a port (hu hnp field set)
+ */
+static int32 iodecl_prop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct net_t *np;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ if (hrp->htyp2 == vpiUdpDefn) return(udpiodecl_get(hp, prop));
+ pval = vpiUndefined;
+ np = hrp->hu.hnp;
+ switch (prop) {
+  case vpiDirection:
+   if (np->ntyp == IO_IN) pval = vpiInput;
+   else if (np->ntyp == IO_OUT) pval = vpiOutput;
+   else if (np->ntyp == IO_BID) pval = vpiInout;
+   else __vpi_terr(__FILE__, __LINE__);
+   break;
+  case vpiLineNo:
+   pval = np->nsym->sylin_cnt;
+   break;
+  case vpiSize:
+   pval = np->nwid;
+   break;
+  case vpiScalar:
+   if (!np->n_isavec) pval = TRUE; else pval = FALSE;
+   break;
+  case vpiVector:
+   if (np->n_isavec) pval = TRUE; else pval = FALSE;
+   break;
+  default: notpropof_err(hrp->htyp, prop);
+ }
+ return(pval);
+}
+
+/*
+ * get properties for a udp io decl object (mod pin - not nets)
+ */
+static int32 udpiodecl_get(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
+ pval = vpiUndefined;
+ switch (prop) {
+  case vpiDirection:
+   if (mpp->mptyp == IO_IN) pval = vpiInput;
+   else if (mpp->mptyp == IO_OUT) pval = vpiOutput;
+   else __vpi_terr(__FILE__, __LINE__);
+   break;
+  case vpiLineNo:
+   pval = mpp->mplin_cnt;
+   break;
+  case vpiSize:
+   pval = 1;
+   break;
+  case vpiScalar:
+   pval = TRUE;
+   break;
+  case vpiVector:
+   pval = FALSE;
+   break;
+  default: notpropof_err(hp->hrec->htyp, prop);
+ }
+ return(pval);
+}
+
+/*
+ * get a upd definition property
+ */
+static int32 udpdefnprop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct udp_t *udpp;
+
+ pval = vpiUndefined;
+ udpp = hp->hrec->hu.hudpp;
+ switch (prop) {
+  case vpiLineNo:
+   pval = udpp->usym->sylin_cnt;
+   break;
+  case vpiSize:
+   /* LOOKATME - for now using number of inputs not states */
+   pval = udpp->numins;
+   break;
+  case vpiProtected:
+   /* no protection in Cver */
+   pval = FALSE;
+   break;
+  case vpiPrimType:
+   /* SJM 03/01/04 - properties were reversed here */
+   if (udpp->utyp == U_COMB) pval = vpiCombPrim;
+   else if (udpp->utyp == U_LEVEL || udpp->utyp == U_EDGE)
+    pval = vpiSeqPrim;
+   else __vpi_terr(__FILE__, __LINE__);
+   break;
+  default: notpropof_err(hp->hrec->htyp, prop);
+ }
+ return(pval);
+}
+
+/*
+ * get a upd definition property
+ */
+static int32 udptabentryprop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ struct udp_t *udpp;
+ struct utline_t *utlp;
+
+ pval = vpiUndefined;
+ udpp = (struct udp_t *) hp->hin_itp;
+ utlp = hp->hrec->hu.hutlp;
+
+ switch (prop) {
+  case vpiLineNo:
+   pval = (int32) utlp->utlin_cnt;
+   break;
+  case vpiSize:
+   /* value is number of states plus one for out */
+   pval = udpp->numstates + 1;
+   break;
+  default: notpropof_err(hp->hrec->htyp, prop);
+ }
+ return(pval);
+}
+
+/*
+ * get property of attribute
+ */
+static int32 dig_attrprop_vpiget(struct h_t *hp, int32 prop)
+{
+ int32 pval;
+ double d1;
+ struct attr_t *attrp;
+ struct xstk_t *xsp;
+
+ pval = vpiUndefined;
+ switch (prop) {
+  case vpiDefAttribute:
+   /* T if no value or non zero value */
+   attrp = __find_attrspec(hp);
+   if (attrp->attr_xp == NULL) { pval = 1; break; }
+   /* LOOKATME - since know number could access as constant */
+   xsp = __eval_xpr(attrp->attr_xp);
+   if (attrp->attr_xp->is_real)
+    {
+     memcpy(&d1, xsp->ap, sizeof(double));
+     if (d1 != 0.0) pval = 1; else pval = 0;
+     __pop_xstk();
+     break;
+    }
+   if (vval_is0_(xsp->ap, xsp->xslen) && vval_is0_(xsp->bp, xsp->xslen))
+    pval = 0; 
+   else pval = 1;
+   __pop_xstk();
+   break;
+  case vpiConstType:
+   attrp = __find_attrspec(hp);
+   if (attrp->attr_xp == NULL) { pval = vpiUndefined; break; }
+   pval = get_vpi_const_typ(attrp->attr_xp);
+   break;
+  default: notpropof_err(hp->hrec->htyp, prop);
+ }
+ return(pval);
+}
+
+/*
+ * find attribute by getting parent object then moving through list
+ * passed attribute object returns matching attribute struct
+ *
+ * BEWARE - this must be inverse of iterator since goes form iterator
+ * element to parent
+ */
+extern struct attr_t *__find_attrspec(struct h_t *hp)
+{
+ register int32 ai;
+ struct attr_t *attrp;
+ struct inst_t *ip;
+ struct mod_t *mdp;
+ struct gate_t *gp;
+ struct hrec_t *hrp;
+
+ attrp = NULL;
+ hrp = hp->hrec;
+ switch (hrp->htyp2) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+  case vpiNamedEvent: case vpiRealVar:
+  /* LOOKATME - is this defined in LRM - think so */
+  case vpiMemory:
+   attrp = hrp->hu.hnp->nattrs;
+   break;
+  case vpiModule:
+   /* FIXME - need to add and access bit determing where attr is ??? */
+   ip = hp->hin_itp->itip; 
+   /* if dig attr attached to inst use it */  
+   if (ip->iattrs != NULL) { attrp = ip->iattrs; break; }
+   /* else use any attached to module */
+   mdp = ip->imsym->el.emdp;
+   attrp = mdp->mattrs;
+   break;
+  case vpiGate: case vpiSwitch: case vpiUdp:
+   gp = hrp->hu.hgp;
+   attrp = gp->gattrs;
+   break;
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+ ai = hrp->hi;
+ for (ai = 0; ai < hrp->hi; ai++)
+  {
+   if (attrp == NULL) __vpi_terr(__FILE__, __LINE__);
+   attrp = attrp->attrnxt;
+  }
+ if (attrp == NULL) __vpi_terr(__FILE__, __LINE__);
+ return(attrp);
+}
+
+
+/*
+ * ROUTINES TO GET STRING PROPERTIES
+ */
+
+/*
+ * get a string property
+ */
+extern char *vpi_get_str(PLI_INT32 property, vpiHandle object)
+{
+ PLI_INT32 pval;
+ struct h_t *hp;
+ struct gate_t *gp;
+ struct sy_t *syp;
+ struct st_t *stp;
+ struct hrec_t *hrp;
+
+ __last_eip = NULL;
+ if (__run_state == SS_COMP)
+  { __still_comp_err("vpi_get_str"); return(NULL); } 
+ if (!validate_property("vpi_get_str", property)) return(NULL);
+
+ if (object == NULL)
+  {
+   __vpi_err(1865, vpiError,  
+    "property %s illegal for vpi_get_str with NULL object",
+    __to_vpipnam(__wrks1, property));
+   return(NULL);
+  }
+
+ hp = (struct h_t *) object;
+ if (!__validate_handle("vpi_get_str", hp)) return(NULL);
+ hrp = hp->hrec;
+
+ /* LOOKATME - special meta string property - standard needs meta name */
+ if (property == vpiType) 
+  {  
+   /* every handle has a type */
+   __to_vpionam(__wrk_vpiget_str, hrp->htyp);
+   return(__wrk_vpiget_str);
+  }
+
+ switch (hrp->htyp) {
+  case vpiModule:   
+   return(modstrprop_vpiget(hp, property));
+  /* all net string properties the same */
+  case vpiNet: case vpiNetBit: case vpiReg: case vpiRegBit: case vpiVarSelect:
+  case vpiIntegerVar: case vpiTimeVar: case vpiNamedEvent:
+  case vpiRealVar: case vpiParameter: case vpiSpecParam:
+  case vpiMemory: case vpiMemoryWord:
+  case vpiParamArray: case vpiParamArrayWord:
+   return(netstrprop_vpiget(hp, property));
+  case vpiPort: case vpiPortBit:
+   return(portstrprop_vpiget(hp, property));
+  case vpiGate: case vpiUdp: case vpiSwitch:
+   return(gatestrprop_vpiget(hp, property));
+  case vpiPrimTerm:  
+   if (property != vpiFile)
+    { __notstrpropof_err(hrp->htyp, property); return(NULL); }
+   gp = hrp->hu.hgp;
+   strcpy(__wrk_vpiget_str, __in_fils[gp->gsym->syfnam_ind]);
+   return(__wrk_vpiget_str);
+  case vpiFuncCall: case vpiSysFuncCall:
+   return(fcallstrprop_vpiget(hp, property));
+  case vpiTaskCall: case vpiSysTaskCall:
+   return(tcallstrprop_vpiget(hp, property));
+  /* handles whose only str property is file location */ 
+  case vpiTchk: case vpiTchkTerm:
+   syp = hrp->hu.htcp->tcsym;
+ret_fnam:
+   if (property != vpiFile)
+    { __notstrpropof_err(hrp->htyp, property); return(NULL); }
+   strcpy(__wrk_vpiget_str, __in_fils[syp->syfnam_ind]);
+   return(__wrk_vpiget_str);
+  case vpiModPath: case vpiPathTerm:
+   syp = hrp->hu.hpthp->pthsym;
+   goto ret_fnam;
+  /* scope def. handles */
+  case vpiContAssign:
+   if (hrp->htyp2 == vpiGate) syp = hrp->hu.hgp->gsym;
+   else syp = hrp->hu.hcap->casym;
+   goto ret_fnam;
+  case vpiNamedBegin: case vpiNamedFork: case vpiTask: case vpiFunction:
+   return(taskstrprop_vpiget(hp, property));
+  case vpiAssignStmt: case vpiAssignment: case vpiBegin:
+  case vpiCase: case vpiDeassign: case vpiDelayControl: case vpiEventControl:
+  case vpiDisable: case vpiEventStmt: case vpiFor: case vpiForce:
+  case vpiForever: case vpiFork: case vpiIf: case vpiIfElse: case vpiNullStmt:
+  case vpiRelease: case vpiRepeat: case vpiWait: case vpiWhile:
+   if (property != vpiFile)
+    { __notstrpropof_err(hrp->htyp, property); return(NULL); }
+   stp = hrp->hu.hstp;
+   strcpy(__wrk_vpiget_str, __in_fils[stp->stfnam_ind]);
+   return(__wrk_vpiget_str);
+  case vpiOperation:
+   /* Cver extension can get the name of operator (i.e. its symbol) */
+   if (property != vpiName)
+    { __notstrpropof_err(hrp->htyp, property); return(NULL); }
+   pval = __expr_optype_get(hrp->hu.hxp);
+   __to_vpiopchar(__wrk_vpiget_str, pval);
+   return(__wrk_vpiget_str);
+  case vpiDefParam:
+   if (property != vpiFile)
+    { __notstrpropof_err(hrp->htyp, property); return(NULL); }
+   strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hdfp->dfpfnam_ind]);
+   return(__wrk_vpiget_str);
+  case vpiParamAssign:
+   if (property != vpiFile)
+    { __notstrpropof_err(hrp->htyp, property); return(NULL); }
+
+   strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hnp->nsym->syfnam_ind]);
+   return(__wrk_vpiget_str);
+  case vpiAttribute:
+   return(dig_attrstrpop_vpiget(hp, property));
+
+  case vpiIODecl: return(iodeclstrprop_vpiget(hp, property));
+  case vpiUdpDefn:
+   if (property == vpiFile) 
+    {
+     strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hudpp->usym->syfnam_ind]);
+    }
+   else if (property == vpiDefName) 
+    {
+     strcpy(__wrk_vpiget_str, hrp->hu.hudpp->usym->synam);
+    }
+   else { __notstrpropof_err(hrp->htyp, property); return(NULL); }
+   return(__wrk_vpiget_str);
+  case vpiTableEntry:
+   if (property != vpiFile)
+    { __notstrpropof_err(hrp->htyp, property); return(NULL); }
+   strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hutlp->utlfnam_ind]);
+   return(__wrk_vpiget_str);
+  default: __notstrpropof_err(hrp->htyp, property);
+ }
+ return(NULL);
+}
+
+/*
+ * get string property values for module (inst. itree loc.)
+ * copy to the one work string for these
+ */
+static char *modstrprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct mod_t *mdp;
+ struct inst_t *ip;
+  
+ mdp = hp->hrec->hu.hmdp;
+ ip = hp->hin_itp->itip;
+ switch (prop) {
+  case vpiName: strcpy(__wrk_vpiget_str, ip->isym->synam); break;
+  case vpiFullName:
+   strcpy(__wrk_vpiget_str, __msg2_blditree(__wrks1, hp->hin_itp));
+   break;
+  case vpiFile:
+   strcpy(__wrk_vpiget_str, __in_fils[ip->isym->syfnam_ind]);
+   break;
+  case vpiDefName:
+   strcpy(__wrk_vpiget_str, mdp->msym->synam);
+   break;
+  case vpiDefFile:
+   strcpy(__wrk_vpiget_str, __in_fils[mdp->msym->syfnam_ind]);
+   break;
+  default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
+ }
+ return(__wrk_vpiget_str);
+}
+
+/*
+ * emit not property of handle err
+ *
+ * know hp non nil or will not get here
+ */
+extern void __notstrpropof_err(word32 typh, int32 prop)
+{
+ __vpi_err(1875, vpiError, 
+  "string property %s not defined for vpi_get_str of %s",
+  __to_vpipnam(__wrks1, prop), __to_vpionam(__wrks2, typh));
+ strcpy(__wrk_vpiget_str, "");  
+}
+
+/*
+ * get string property values for net or array (and bits of)
+ * copy to the one overwritten work string 
+ *
+ * notice although strictly speaking a array is not a net str props the same
+ */
+static char *netstrprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct net_t *np;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ if (hrp->htyp == vpiNetBit || hrp->htyp == vpiRegBit
+  || hrp->htyp == vpiVarSelect || hrp->htyp == vpiMemoryWord
+ )
+  {
+   if (hrp->bith_ndx) np = hrp->hu.hnp;
+   else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+  }
+ else np = hrp->hu.hnp;
+
+ switch (prop) {
+  case vpiFile:
+   strcpy(__wrk_vpiget_str, __in_fils[np->nsym->syfnam_ind]);
+   break;
+  case vpiName: strcpy(__wrk_vpiget_str, np->nsym->synam); break;
+  case vpiFullName:  
+   if (hrp->hin_tskp == NULL)
+    sprintf(__wrk_vpiget_str, "%s.%s", __msg2_blditree(__wrks1, hp->hin_itp),
+     np->nsym->synam);
+   else sprintf(__wrk_vpiget_str, "%s.%s",
+    __msg_blditree(__wrks1, hp->hin_itp, hrp->hin_tskp), np->nsym->synam);
+   break;
+  default: __notstrpropof_err(hrp->htyp, prop); return(NULL);
+ } 
+ return(__wrk_vpiget_str);
+}
+
+/*
+ * get string property values for gates
+ * copy to the one overwritten work string 
+ *
+ * LRM 98 removes vpiFullName property for ports
+ */
+static char *portstrprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
+ switch (prop) {
+  case vpiFile:
+   strcpy(__wrk_vpiget_str, __in_fils[mpp->mpfnam_ind]);
+   break;
+  case vpiName:
+   if (mpp->mpsnam == NULL) return(NULL);
+   return(mpp->mpsnam);
+  default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
+ } 
+ return(__wrk_vpiget_str);
+}
+
+/*
+ * get string property values for gates
+ * copy to the one overwritten work string 
+ */
+static char *gatestrprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct gate_t *gp;
+
+ gp = hp->hrec->hu.hgp;
+ switch (prop) {
+  case vpiDefName:
+   strcpy(__wrk_vpiget_str, gp->gmsym->synam);
+   break;
+  case vpiFile:
+   strcpy(__wrk_vpiget_str, __in_fils[gp->gsym->syfnam_ind]);
+   break;
+  case vpiName: strcpy(__wrk_vpiget_str, gp->gsym->synam); break;
+  case vpiFullName:  
+    sprintf(__wrk_vpiget_str, "%s.%s", __msg2_blditree(__wrks1,
+     hp->hin_itp), gp->gsym->synam);
+   break;
+  default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
+ } 
+ return(__wrk_vpiget_str);
+}
+
+/*
+ * get string property values for task call
+ * copy to the one overwritten work string 
+ */
+static char *tcallstrprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct st_t *stp;
+
+ stp = hp->hrec->hu.hstp;
+ switch (prop) { 
+  case vpiFile:
+   strcpy(__wrk_vpiget_str, __in_fils[stp->stfnam_ind]);
+   break;  
+  case vpiName: 
+   strcpy(__wrk_vpiget_str, stp->st.stkc.tsksyx->lu.sy->synam); 
+   break;  
+  default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
+ }
+ return(__wrk_vpiget_str);
+}
+
+/*
+ * get string property values for function call
+ * copy to the one overwritten work string 
+ *
+ * LOOKATME - for compatibility making location: unkown 0?
+ */
+static char *fcallstrprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ switch (prop) { 
+  case vpiFile:
+   __vpi_err(2112, vpiNotice,
+    "vpiFile call location property not saved for vpiFuncCall or vpiSysFuncCall - [unknown] returned");
+   strcpy(__wrk_vpiget_str, "[Unknown]");
+   break;
+  case vpiName: 
+   strcpy(__wrk_vpiget_str, hrp->hu.hxp->lu.x->lu.sy->synam); 
+   break;
+  default: __notstrpropof_err(hrp->htyp, prop); return(NULL);
+ }
+ return(__wrk_vpiget_str);
+}
+
+/*
+ * get string property values for func/task declaration (scope not call)
+ *
+ * copy to the one overwritten work string 
+ * also named begin or fork
+ */
+static char *taskstrprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct task_t *tskp;
+
+ tskp = hp->hrec->hu.htskp;
+ switch (prop) { 
+  case vpiName: 
+   strcpy(__wrk_vpiget_str, tskp->tsksyp->synam); 
+   break;  
+  case vpiFullName:  
+   sprintf(__wrk_vpiget_str, "%s.%s", __msg2_blditree(__wrks1, hp->hin_itp),
+    tskp->tsksyp->synam); 
+   break;  
+  case vpiFile:
+   strcpy(__wrk_vpiget_str, __in_fils[tskp->tsksyp->syfnam_ind]);
+   break;
+  default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
+ }
+ return(__wrk_vpiget_str);
+}
+
+/*
+ * get string property values for io decl
+ * copy to the one overwritten work string 
+ */
+static char *iodeclstrprop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ switch (prop) { 
+  case vpiName: 
+   if (hrp->htyp2 == vpiUdpDefn)
+    {
+     /* DBG remove -- */
+     if (hrp->hu.hmpp->mpsnam == NULL) __arg_terr(__FILE__, __LINE__);
+     /* --- */
+     strcpy(__wrk_vpiget_str, hrp->hu.hmpp->mpsnam); 
+    }
+   else strcpy(__wrk_vpiget_str, hrp->hu.hnp->nsym->synam);
+   break;
+  case vpiFile:
+   if (hrp->htyp2 == vpiUdpDefn)
+    strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hmpp->mpfnam_ind]);
+   else strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hnp->nsym->syfnam_ind]);
+   break;
+  default: __notstrpropof_err(hrp->htyp, prop); return(NULL);
+ }
+ return(__wrk_vpiget_str);
+}
+
+/*
+ * get string property values for digital attribute
+ * copy to the one overwritten work string 
+ */
+static char *dig_attrstrpop_vpiget(struct h_t *hp, int32 prop)
+{
+ struct attr_t *attrp;
+
+ switch (prop) {
+  case vpiName:
+   /* this can't fail */
+   attrp = __find_attrspec(hp);
+   strcpy(__wrk_vpiget_str, attrp->attrnam);
+   break;
+  default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
+ }
+ return(__wrk_vpiget_str);
+}
diff --git a/src/v_vpi3.c b/src/v_vpi3.c
new file mode 100644
index 0000000..ac9d1a3
--- /dev/null
+++ b/src/v_vpi3.c
@@ -0,0 +1,7505 @@
+/* Copyright (c) 1995-2005 Pragmatic C Software Corp. */
+
+/*
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+ 
+   There is also a commerically supported faster new version of Cver that is
+   not released under the GPL.   See file commerical-cver.txt, or web site
+   www.pragmatic-c.com/commercial-cver or contact sales at pragmatic-c.com to
+   learn more about commerical Cver.
+   
+ */
+
+
+/*
+ * module to implement pli vpi_ routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#ifdef __DBMALLOC__
+#include "../malloc.h"
+#endif
+
+#include "v.h"
+#include "cvmacros.h"
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* local prototypes */
+static int32 chk_delay_num(char *, struct h_t *, int32, struct gate_t *);
+static int32 fillchk_tim(word64 *, int32 *, p_vpi_delay, struct itree_t *);
+static void fill_vpi_delay(p_vpi_delay, word64 *, int32, word32,
+ struct mod_t *);
+
+static void get_varorparam_val(struct h_t *, p_vpi_value);
+static void stscal_fill_valuep(p_vpi_value, register byte *, int32);
+static void stvec_fill_valuep(p_vpi_value, register byte *, int32);
+static void get_var_bit(struct h_t *, p_vpi_value);
+static void get_arrwrd_val(struct h_t *, p_vpi_value);  
+static void get_paramarrwrd_val(struct h_t *, p_vpi_value);  
+static void get_expr_val(struct h_t *, p_vpi_value);  
+static int32 valp_stren_err(struct hrec_t *, p_vpi_value);  
+static void get_primterm_val(struct h_t *, p_vpi_value);  
+static void get_vpisfcall_retval(struct h_t *, p_vpi_value);
+static void get_vpiudpdefn_val(struct h_t *, p_vpi_value);
+static void get_vpitabentry_val(struct h_t *, p_vpi_value);
+static void get_vpi_netdrv_val(struct h_t *, p_vpi_value);
+static struct xstk_t *push_vpi_drv_val(struct h_t *, struct net_t **);
+static void get_vpi_netbitdrv_val(struct h_t *, p_vpi_value);
+static struct xstk_t *push_vpi_bitdrv_val(struct h_t *, struct net_t **);
+static void get_gate_drv_valuep(struct h_t *, p_vpi_value, struct gate_t *);
+static void get_vpiconta_drv_valuep(struct h_t *, p_vpi_value,
+ struct conta_t *);
+static void get_vpiport_drv_valuep(struct h_t *, p_vpi_value,
+ struct mod_pin_t *);
+static void get_vpiportbit_drv_valuep(struct h_t *, p_vpi_value,
+ struct mod_pin_t *, int32);
+static void get_vpi_attrval(struct h_t *, p_vpi_value);
+
+static void correct_objtypval(p_vpi_value, word32, word32, word32, int32);
+static void expr_correct_objtypval(struct expr_t *, p_vpi_value);
+static void fill_valuep(p_vpi_value, struct xstk_t *xsp, word32, int32);
+static void wrkval_grow(int32);
+static void udp_line_to_str(char *, struct udp_t *, struct utline_t *);
+static int32 putv_in_future(word32, p_vpi_time);
+static int32 chk_putv_args(word32, struct h_t *, p_vpi_value); 
+static char *putv_flag_to_str(char *, word32);
+static int32 net_ongetpat_lhs(struct net_t *);
+static int32 good_value_p(p_vpi_value);
+static void free_putv_sched(struct h_t *);
+static void free_regwir_putv_sched(struct net_t *, struct itree_t *,
+ i_tev_ndx); 
+static void free_netbitdrv_putv_sched(struct net_t *, int32, struct itree_t *,
+ i_tev_ndx); 
+static struct h_t *add_net_driver(struct h_t *); 
+static struct h_t *add_netbit_driver(struct h_t *); 
+static struct vpi_drv_t *alloc_vpidrv(struct net_t *, int32);
+static void putv_drvwp_allocinit(struct mod_t *, struct net_t *,
+ struct vpi_drv_t *, int32);
+static void chg_net_to_multfi(struct net_t *, struct mod_t *);
+static int32 get_vpibit_index(struct net_t **np, struct h_t *);
+static struct xstk_t *push_vpi_valuep(p_vpi_value, int32, word32, int32);
+static void reg_vpi_force(register struct net_t *, word32 *, word32 *);
+static void reg_vpi_release(register struct net_t *);
+static void wire_vpi_force(register struct net_t *, word32 *, word32 *,
+ register int32);
+static void wire_vpi_release(struct net_t *, int32);
+static void set_vpisfcall_retval(struct h_t *, p_vpi_value);
+static void set_vpiparam_val(struct h_t *, p_vpi_value);
+static void set_vpiudpdef_ival(struct h_t *, p_vpi_value);
+static void immed_vpi_drv_assign(struct net_t *np, int32, word32 *, word32 *); 
+static void immed_vpibit_drv_assign(struct net_t *np, int32, int32, word32 *,
+ word32 *); 
+static void emit_vpiputv_evtrmsg(struct net_t *, struct teputv_t *, int32);
+static void exec_putv_reg_assign(register struct net_t *, register word32 *,
+ register word32 *, register int32);
+static void exec_putv_wire_softforce(register struct net_t *, register word32 *,
+ register word32 *, register int32);
+static struct h_t *setschd_var_fromvaluep(p_vpi_value, struct net_t *, int32, 
+ word64, byte, int32);
+static void emit_vpiputv_schd_trmsg(struct net_t *, struct xstk_t *,
+ struct dltevlst_t *, word64 *, int32, char *);
+static void bld_regwir_putvrec(struct net_t *);
+static void cancel_vpievents_toend(struct net_t *, struct dltevlst_t *, int32);
+static struct h_t *setschd_drvr_fromvaluep(p_vpi_value, struct h_t *, word64,
+ byte, int32);
+static i_tev_ndx setschd_1bit_drvr(struct net_pin_t *, int32, struct xstk_t *,
+ word64, byte);
+static int32 chk_vpi_logicval(word32);
+static int32 bld_vpinewdu(struct gate_t *, struct gate_t *, p_vpi_delay,
+ struct itree_t *, int32, int32);
+static int32 do_vpi_iact_scopchg(vpiHandle);
+static int32 do_vpi_cb_onoff(vpiHandle, int32);
+static void init_pli_einfo(struct t_vpi_error_info *, int32, int32);
+static int32 to_vpierr_level(int32);
+
+
+/* extern prototypes (maybe defined in this module) */
+extern struct mipd_t *__get_mipd_from_port(struct mod_pin_t *, int32);
+extern void __set_vpi_time(struct t_vpi_time *, word64 *, int32, struct mod_t *);
+extern int32 __get_vpinet_index(struct net_t **, struct h_t *);
+extern int32 __vpitime_to_ticks(word64 *, p_vpi_time, struct mod_t *);
+extern void __reinit_regwir_putvrec(struct net_t *, int32);
+extern void __reinit_netdrvr_putvrec(struct net_t *, struct mod_t *);
+extern void __process_vpi_varputv_ev(i_tev_ndx);
+extern void __process_vpidrv_ev(i_tev_ndx);
+extern void __pli_dofinish(int32, char *);
+extern void __reinit_vpi(void);
+extern void __dmp_listof_handles(struct h_t *);
+extern char *__to_vpionam(char *, word32);
+extern int32 __validate_otyp(word32);
+extern char *__to_vpiopnam(char *, int32);
+extern char *__to_vpiopchar(char *, int32);
+extern void __sim_notbegun_err(char *);
+extern void __still_comp_err(char *);
+extern void __bad_rosync_err(char *);
+extern int32 __validate_handle(char *, register struct h_t *);
+extern int32 __validate_nonit_handle(char *, struct h_t *);
+extern int32 __validate_accessm(char *, int32, char *);
+extern int32 __validate_time_type(char *, int32);
+extern int32 __validate_value_fmt(char *, int32);
+extern void __free_iterator(vpiHandle);
+extern void __free_hp(struct h_t *); 
+
+extern vpiHandle __mk_handle(word32, void *, struct itree_t *,
+ struct task_t *);
+extern int32 __get_arrwide(struct net_t *);
+extern char *__msg2_blditree(char *, struct itree_t *);
+extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
+extern void __extract_delval(word64 *, int32 *, union del_u, word32);
+extern char *__to_tcnam(char *, word32);
+extern void __fill_16vconst(word64 *, word64 *, int32);
+extern void __map_16v_to_12vform(word64 *, word64 *);
+extern int32 __v64_to_real(double *, word64 *);
+extern char *__to_timstr(char *, word64 *);
+extern int32 __add_gate_pnd0del(struct gate_t *, struct mod_t *, char *);
+extern void __chg_1inst_del(struct gate_t *, struct itree_t *, struct gate_t *);
+extern void __free_del(union del_u, word32, int32);
+extern char *__to_mpnam(char *, char *);
+extern void __add_alloc_mipd_npp(struct net_t *, struct mod_t *);
+extern void __setup_mipd(struct mipd_t *, struct net_t *, int32);
+extern int32 __add_conta_pnd0del(struct conta_t *, struct mod_t *, char *);
+extern void __fill_4vconst(word64 *, word64 *, word64 *, word64 *, int32, int32);
+extern int32 __real_to_v64tim(word64 *, double);
+extern void __grow_xstk(void);
+extern void __chg_xstk_width(struct xstk_t *, int32);
+extern void __grow_tevtab(void);
+extern void __ld_wire_val(register word32 *, register word32 *, struct net_t *);
+extern void __ld_bit(register word32 *, register word32 *,
+ register struct net_t *, int32);
+extern void __ld_stval(register word32 *, register word32 *, register byte *, int32);
+extern void __lhsbsel(register word32 *, register int32, word32);
+extern struct xstk_t *__eval2_xpr(register struct expr_t *);
+extern struct xstk_t *__ndst_eval_xpr(struct expr_t *);
+extern void __ld_arr_val(register word32 *, register word32 *, union pck_u,
+ int32, int32, int32);
+extern void __cnv_stk_fromreal_toreg32(struct xstk_t *);
+extern void __regab_disp(word32 *, word32 *, int32, int32, int32, int32);
+extern char *__to_wtnam(char *, struct net_t *);
+extern char *__to_wtnam2(char *, word32);
+extern void __cnv_stk_fromreg_toreal(struct xstk_t *, int32);
+extern char *__alloc_vval_to_cstr(word32 *, int32, int32, int32);
+extern struct xstk_t *__cstr_to_vval(char *);
+extern int32 __wide_vval_is0(register word32 *, int32);
+extern int32 __vval_is1(register word32 *, int32);
+extern char *__my_realloc(char *, int32, int32);
+extern void __my_free(char *, int32);
+extern char *__my_malloc(int32);
+extern int32 __unnormalize_ndx(struct net_t *, int32);
+extern struct dltevlst_t *__spliceout_last(register struct dltevlst_t *);
+extern struct dltevlst_t *__find_last_bdltevp(register struct dltevlst_t *,
+ word64);
+extern void __insert_event(register i_tev_ndx);
+extern struct xstk_t *__putdstr_to_val(char *, int32, int32, int32);
+extern double __cnvt_stk_to_real(struct xstk_t *, int32);
+extern void __sizchgxs(register struct xstk_t *, int32);
+extern struct net_pin_t *__alloc_npin(int32, int32, int32);
+extern int32 __get_pcku_chars(int32, int32);
+extern void __st_perinst_val(union pck_u, int32, register word32 *,
+ register word32 *);
+extern void __vpi_set_chg_proc(struct gate_t *);
+extern void __allocinit_perival(union pck_u *, int32, int32, int32);
+extern void __vpi_set_upiconnport_proc(struct mod_pin_t *);
+extern void __vpi_set_downtomdport_proc(struct mod_pin_t *, struct net_t *);
+extern void __alloc_tfdrv_wp(struct tfarg_t *, struct expr_t *, struct mod_t *);
+extern void __chg_st_arr_val(union pck_u, int32, int32, int32, register word32 *,
+ register word32 *);
+extern void __st_arr_val(union pck_u, int32, int32, int32, register word32 *,
+ register word32 *);
+extern void __chg_st_val(struct net_t *, register word32 *, register word32 *);
+extern void __st_val(struct net_t *, register word32 *, register word32 *);
+extern void __chg_st_bit(struct net_t *, int32, register word32, register word32);
+extern void __st_bit(struct net_t *, int32, register word32, register word32);
+extern int32 __correct_forced_newwireval(struct net_t *, word32 *, word32 *);
+extern void __ld_perinst_val(register word32 *, register word32 *,
+ union pck_u, int32);
+extern word32 __ld_gate_out(register struct gate_t *, int32 *);
+extern word32 __ld_gate_in(struct gate_t *, int32, int32 *);
+extern int32 __update_tran_harddrvs(struct net_t *);
+extern void __tran_wire_vpi_force(struct net_t *, word32 *, word32 *, int32); 
+extern void __tran_wire_vpi_release(struct net_t *, int32); 
+extern void __tran_exec_putv_wire_softforce(struct net_t *, word32 *, word32 *,
+ int32);
+
+extern void __eval_tran_bits(register struct net_t *);
+extern void __eval_tran_1bit(register struct net_t *, register int32);
+extern void __sched_1mdrwire(register struct net_t *);
+extern void __assign_1mdrwire(register struct net_t *);
+extern char *__st_regab_tostr(char *, byte *, int32);
+extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
+extern void __evtr_resume_msg(void);
+extern void __chg_param_tois(struct net_t *, struct mod_t *);
+extern void __re_prep_dels(struct net_t *, struct itree_t *, struct mod_t *,
+ int32);
+extern void __alloc_qcval(struct net_t *);
+extern void __find_call_force_cbs(struct net_t *, int32);
+extern void __cb_all_rfs(struct net_t *, int32, int32);
+extern void __do_qc_store(struct net_t *, struct qcval_t *, int32);
+extern void __find_call_rel_cbs(struct net_t *, int32);
+extern void __st_standval(register byte *, register struct xstk_t *, byte);
+extern char *__pv_stralloc(char *);
+extern word32 __mc1_fopen(char *, int32, int32);
+extern word32 __close_mcd(word32, int32);
+extern void __free_xtree(struct expr_t *);
+extern void __vpi_plierror_trycall(void);
+extern char *__to_vpipnam(char *, int32);
+extern void __bld_vpi_argv(void);
+extern int32 __em_suppr(int32);
+extern int32 __do_vpi_stop(int32);
+extern void __do_vpi_reset(int32, int32, int32);
+extern void __call_misctfs_scope(void);
+extern void __vpi_iactscopechg_trycall(void);
+extern char *__match_cdir(char *, char *);
+extern int32 __exec_rdinserted_src(char *);
+extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
+extern int32 __expr_is_vpiconst(struct expr_t *);
+extern word32 __map_tovpi_stren(word32);
+extern int32 __map_frvpi_stren(int32);
+extern struct expr_t *__sim_copy_expr(struct expr_t *);
+extern void __exec_dumpvars(struct expr_t *);
+extern void __my_dv_flush(void);
+extern void __push_wrkitstk(struct mod_t *, int32);
+extern void __pop_wrkitstk(void);
+extern int32 __chk_showobj(struct h_t *, int32 *, int32 *);
+extern word32 __to_vpi_tasktyp(word32);
+extern int32 __my_vpi_chk_error(void);
+extern struct attr_t *__find_attrspec(struct h_t *);
+extern int32 __move_to_npprefloc(struct net_pin_t *);
+extern void __add_nchglst_el(register struct net_t *);
+extern void __add_select_nchglst_el(register struct net_t *, register int32,
+ register int32);
+extern void __wakeup_delay_ctrls(register struct net_t *, register int32,
+ register int32);
+extern void __add_dmpv_chglst_el(struct net_t *);
+extern char *__cb_reason_to_nam(char *, int32);
+extern void __bit1_vpi_or_tran_wireforce(struct net_t *, word32 *, word32 *, int32,
+ int32, int32, char *);
+extern struct tenp_t *__bld_portbit_netbit_map(struct mod_pin_t *);
+extern int32 __trim1_0val(word32 *, int32);
+extern void __sgn_xtnd_widen(struct xstk_t *, int32);
+extern void __sizchg_widen(register struct xstk_t *, int32);
+
+extern int32 __fd_do_fclose(int32);
+
+extern void __my_fprintf(FILE *, char *, ...);
+extern void __tr_msg(char *, ...);
+extern void __dbg_msg(char *, ...);
+extern void __arg_terr(char *, int32);
+extern void __pv_terr(int32, char *, ...);
+extern void __misc_terr(char *, int32);
+
+extern void __vpi_terr(char *, int32);
+extern void __vpi_err(int32, int32, char *, ...);
+
+extern word32 __masktab[];
+extern double __dbl_toticks_tab[];
+
+/* vpi only storage that is defined here */
+struct t_vpi_error_info __wrk_einfo;/* if err, vpi routine fills this */
+struct t_vpi_error_info *__last_eip;/* if err, ptr to wrk eifo or nil */
+
+/*
+ * ROUTINES FOR ACCESSING DELAYS
+ */
+
+/*
+ * get a delay
+ *
+ * convention for pulsere flag is to use delay for other 2
+ */
+extern void vpi_get_delays(vpiHandle object, p_vpi_delay delay_p)
+{ 
+ register int32 di, di2;
+ int32 ndels, nrep, ndx;
+ word32 getdrep;
+ word64 tim[12], timval;
+ struct mod_t *mdp;
+ struct h_t *hp; 
+ struct gate_t *gp, ogat;
+ struct mod_pin_t *mpp; 
+ struct net_t *np;
+ struct conta_t *cap;
+ struct tchk_t *tcp;
+ struct spcpth_t *pthp;
+ struct delctrl_t *dctp;
+ union del_u getdu;
+ struct t_vpi_delay tmpdel;  
+ struct t_vpi_time tmpda[12];
+ struct hrec_t *hrp;
+ struct mipd_t *mipdp;
+
+ if (__run_state == SS_COMP)
+  { __still_comp_err("vpi_get_delays"); return; } 
+ hp = (struct h_t *) object;
+ if (!__validate_handle("vpi_get_delays", hp)) return;
+ hrp = hp->hrec;
+ nrep = 1;
+ if (delay_p->pulsere_flag) 
+  {
+   __vpi_err(2107, vpiNotice,
+    "vpi_get_delays pulsere_flag values not supported - both same as delay");
+   /* still must access from callers description */
+   nrep *= 3;
+  }
+ if (delay_p->mtm_flag)
+  {
+   __vpi_err(2108, vpiNotice,
+    "vpi_get_delays mtm_flag set but min-typ-max values not supported - all 3 same");
+   nrep *= 3;
+  }
+ /* on error here, user must call error check routine */
+ /* can access delays for any run state but still compiling */
+ if (!chk_delay_num("vpi_get_delays", hp, delay_p->no_of_delays, &ogat))
+  return;
+
+ /* must extract using exact properties from passed vpi_delay */
+ tmpdel = *delay_p;
+ tmpdel.da = &(tmpda[0]);
+
+ __push_itstk(hp->hin_itp);
+ /* need module type since need to scale delay */
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ /* assume if handle created, good - fill the delay union */
+ switch (hrp->htyp) {
+  case vpiGate: case vpiUdp: case vpiSwitch:
+   gp = hrp->hu.hgp;
+   getdu = gp->g_du;
+   getdrep = gp->g_delrep;
+   break;
+  case vpiPort: case vpiPortBit:
+   mpp = &(mdp->mpins[hrp->hu.hpi]);
+   if (hrp->htyp == vpiPort && mpp->mpwide != 1)
+    {
+     __vpi_err(2109, vpiNotice,
+      "vpi_get_delays of non scalar vpiPort (for MIPD) using low bit");
+    }
+   if (!mpp->has_mipd) { getdu.d1v = NULL; getdrep = DT_NONE; }
+   else 
+    {
+     if (hrp->htyp == vpiPort) ndx = 0; else ndx = hrp->hi;
+     mipdp = __get_mipd_from_port(mpp, ndx);
+     getdu = mipdp->pb_mipd_du;
+     getdrep = mipdp->pb_mipd_delrep;
+    } 
+   break;
+  case vpiNet:
+   np = hrp->hu.hnp;
+   /* can check for no delay with property */
+   if (np->nrngrep == NX_DWIR)
+    { getdu = np->nu.rngdwir->n_du; getdrep = np->nu.rngdwir->n_delrep; }
+   else { getdu.d1v = NULL; getdrep = DT_NONE; }
+   break;
+  case vpiContAssign:
+   if (hrp->htyp2 == vpiGate)
+    { gp = hrp->hu.hgp; getdu = gp->g_du; getdrep = gp->g_delrep; }
+   else { cap = hrp->hu.hcap; getdu = cap->ca_du; getdrep = cap->ca_delrep; }
+   break;
+  case vpiTchk:
+   tcp = hrp->hu.htcp;
+   /* know always at least one delay */
+   getdu = tcp->tclim_du;
+   getdrep = tcp->tc_delrep;
+   /* know limit is present */
+   if (getdrep == DT_NONE) __vpi_terr(__FILE__, __LINE__);
+   __extract_delval(tim, &ndels, getdu, getdrep);
+   if (ndels != 1) __vpi_terr(__FILE__, __LINE__);
+   __set_vpi_time(&(tmpdel.da[0]), &(tim[0]), delay_p->time_type, mdp); 
+   if (tcp->tc_haslim2 && delay_p->no_of_delays == 2)
+    {
+     getdu = tcp->tclim2_du;
+     __extract_delval(tim, &ndels, getdu, getdrep);
+     if (ndels != 1) __vpi_terr(__FILE__, __LINE__);
+     __set_vpi_time(&(tmpdel.da[1]), &(tim[0]), delay_p->time_type, mdp); 
+    }
+   __pop_itstk();
+   goto done;
+  case vpiModPath:
+   pthp = hrp->hu.hpthp; getdu = pthp->pth_du; getdrep = pthp->pth_delrep;
+   break;
+  /* procedural delays */  
+  case vpiAssignment:
+   dctp = hrp->hu.hstp->st.sdc;
+   if (dctp->dctyp != DC_RHSDELAY)
+    {
+     __vpi_err(1882, vpiError,
+      "vpi_get_delays of vpiAssignment right hand side delay control impossible - no delay control");
+     __pop_itstk();
+     goto done; 
+    }
+   getdu = dctp->dc_du;
+   getdrep = dctp->dc_delrep;
+   break;
+  case vpiDelayControl:  
+   dctp = hrp->hu.hstp->st.sdc;
+   /* DBG remove --- */
+   if (dctp->dctyp != DC_DELAY) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   getdu = dctp->dc_du;
+   getdrep = dctp->dc_delrep;
+   break;
+  /* will not get to case if not element with delay */
+  default: __vpi_terr(__FILE__, __LINE__); goto done;
+ }
+ if (getdrep == DT_NONE)
+  {
+   __vpi_err(2009, vpiWarning,
+    "vpi_get_delays for object %s that has no delay - value(s) 0 but not #0",
+    __to_vpionam(__wrks1, hrp->htyp));
+   timval = 0ULL;
+   for (di = 0; di < delay_p->no_of_delays; di++) 
+    __set_vpi_time(&(tmpdel.da[di]), &timval, delay_p->time_type, mdp); 
+   __pop_itstk();
+   goto done;
+  }
+ __extract_delval(tim, &ndels, getdu, getdrep);
+ /* this may emit warning that can be checked by calling vpi check */
+ fill_vpi_delay(&tmpdel, tim, ndels, hrp->htyp, mdp);
+ __pop_itstk();
+
+done:
+ /* final step is copying back into user supplied delay p from tmp */
+ for (di = 0; di < delay_p->no_of_delays; di++)
+  {
+   for (di2 = 0; di2 < nrep; di2++)
+    delay_p->da[nrep*di + di2] = tmpdel.da[di];
+  }
+}
+
+/*
+ * routine to check that right number of delays passed for object type
+ *
+ * also checks for object (handle) that can have delay and fill ogp with del 
+ * if return T
+ */
+static int32 chk_delay_num(char *rnam, struct h_t *hp, int32 numdels,
+ struct gate_t *ogp)
+{
+ int32 ndx;
+ struct gate_t *gp;
+ struct conta_t *cap;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+ struct mipd_t *mipdp;
+ struct net_t *np;
+ struct tchk_t *tcp;
+ struct spcpth_t *pthp;
+ struct delctrl_t *dctp;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+ switch (hrp->htyp) {
+  case vpiGate: case vpiUdp: case vpiSwitch:
+   gp = hrp->hu.hgp;
+   ogp->g_du = gp->g_du;
+   ogp->g_delrep = gp->g_delrep;
+chk_prim_num:
+   if (numdels != 1 && numdels != 2 && numdels != 3)
+    {
+     __vpi_err(1881, vpiError,
+      "%s called for object %s delay number %d wrong - must be 1, 2 or 3",
+      rnam, __to_vpionam(__wrks1, hrp->htyp), numdels);
+     return(FALSE);
+    }
+   break;
+  case vpiContAssign:
+   if (hrp->htyp2 == vpiGate)
+    {
+     gp = hrp->hu.hgp;
+     ogp->g_du = gp->g_du;
+     ogp->g_delrep = gp->g_delrep;
+    }
+   else
+    {
+     cap = hrp->hu.hcap;
+     ogp->g_du = cap->ca_du;
+     ogp->g_delrep = cap->ca_delrep;
+    }
+   goto chk_prim_num;
+  case vpiNet:
+   np = hrp->hu.hnp;
+   if (np->nrngrep == NX_DWIR) 
+    { 
+     ogp->g_du = np->nu.rngdwir->n_du;
+     ogp->g_delrep = np->nu.rngdwir->n_delrep;
+    }
+   else { ogp->g_du.d1v = NULL; ogp->g_delrep = DT_NONE; }
+   goto chk_prim_num;
+  case vpiPort: case vpiPortBit:
+   /* MIPD delays for vector vpiPortBit, if vpiPort use low bit with note */
+   /* notice check for input or inout port handled below */
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   mpp = &(mdp->mpins[hrp->hu.hpi]);
+   if (mpp->mptyp != IO_IN && mpp->mptyp != IO_BID)
+    {
+     __vpi_err(2023, vpiWarning,
+      "vpi_get_delays of non input or inout %s - no values returned since no MIPD possible",
+      __to_vpionam(__wrks1, hrp->htyp));
+     return(FALSE);
+    } 
+   if (!mpp->has_mipd) { ogp->g_du.d1v = NULL; ogp->g_delrep = DT_NONE; }
+   else 
+    {
+     if (hrp->htyp == vpiPort) ndx = 0; else ndx = hrp->hi;
+     mipdp = __get_mipd_from_port(mpp, ndx);
+     ogp->g_du = mipdp->pb_mipd_du;
+     ogp->g_delrep = mipdp->pb_mipd_delrep;
+    } 
+   /* SJM 10/28/99 - 12 delay values now possible for MIPDs */ 
+   if (!(numdels == 1 || numdels == 2 || numdels == 3 || numdels == 6
+    || numdels == 12))
+    {
+     __vpi_err(1881, vpiError,
+      "%s called for object %s delay number %d wrong - must be 1, 2, 3, 6, or 12",
+      rnam, __to_vpionam(__wrks1, hrp->htyp), numdels);
+     return(FALSE);
+    }
+   break; 
+  case vpiModPath:
+   if (!(numdels == 1 || numdels == 2 || numdels == 3 || numdels == 6
+    || numdels == 12))
+    {
+     __vpi_err(1881, vpiError,
+      "%s called for object %s delay number %d wrong - must be 1, 2, 3, 6, or 12",
+      rnam, __to_vpionam(__wrks1, hrp->htyp), numdels);
+     return(FALSE);
+    }
+   pthp = hrp->hu.hpthp;
+   ogp->g_du = pthp->pth_du;
+   ogp->g_delrep = pthp->pth_delrep;
+   break;
+  case vpiTchk:
+   tcp = hrp->hu.htcp;
+   /* different delay unions but type must be the same */
+   ogp->g_du = tcp->tclim_du;
+   ogp->g_delrep = tcp->tc_delrep;
+   if (numdels != 1 && numdels != 2)
+    {
+     __vpi_err(1889, vpiError,
+      "%s called for object %s %s delay number %d wrong - must be 1 or 2",
+      rnam, __to_tcnam(__wrks2, tcp->tchktyp), __to_vpionam(__wrks1,
+      hrp->htyp), numdels);
+     return(FALSE);
+    }
+   if (tcp->tc_haslim2)
+    {
+     if (numdels != 2)
+      {
+       __vpi_err(2021, vpiWarning,
+        "%s called for object %s %s delay number %d wrong - missing 2nd omitted",
+        rnam, __to_tcnam(__wrks2, tcp->tchktyp), __to_vpionam(__wrks1,
+        hrp->htyp), numdels);
+      }
+    }
+   else
+    {
+     if (numdels != 1)
+      {
+       __vpi_err(2021, vpiWarning,
+        "%s called for object %s %s delay number %d wrong - only 1 returned or set",
+        rnam, __to_tcnam(__wrks2, tcp->tchktyp), __to_vpionam(__wrks1,
+        hrp->htyp), numdels);
+      }
+    }
+   break;
+  /* procedural delays */  
+  case vpiAssignment: case vpiDelayControl:  
+   dctp = hrp->hu.hstp->st.sdc;
+   if (numdels != 1)
+    {
+     __vpi_err(1881, vpiError,
+      "%s called for procedural object %s delay number %d wrong - must be 1",
+      rnam, __to_vpionam(__wrks1, hrp->htyp), numdels);
+     return(FALSE);
+    }
+   ogp->g_du = dctp->dc_du;
+   ogp->g_delrep = dctp->dc_delrep;
+   break;
+  default:
+   __vpi_err(1883, vpiError, "object %s does not have delays",
+    __to_vpionam(__wrks1, hrp->htyp));
+   return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * given an extracted tim array, vpi_ delay
+ *
+ * extraction produces smallest possible number if any identical values
+ * nvals can be 1, 2, 3, 6, or 12 and gives number of tim[] filled
+ *
+ * 2 delays (nvals) now happens for logic gates and UDPs
+ * for 6 and 16, order is 0-1 (a rise), 1-0 (a fall), 0-z (a toz) 
+ * so can just use
+ * delay_p can need 1,2,3,6,12
+ */
+static void fill_vpi_delay(p_vpi_delay delay_p, word64 *tim, int32 nvals,
+ word32 otyp, struct mod_t *mdp)
+{
+ register int32 di;
+ word64 ntim[16];
+
+ /* if nvals 1, just duplicate in all */
+ if (nvals == 1)
+  {
+   for (di = 0; di < delay_p->no_of_delays; di++) 
+    __set_vpi_time(&(delay_p->da[di]), &(tim[0]), delay_p->time_type, mdp); 
+   return; 
+  }
+ /* if nvals 2, if need 1, warn use first, if 2 if path warn and use 2 */
+ if (nvals == 2)  
+  {
+   if (delay_p->no_of_delays == 1) 
+    {
+     __vpi_err(2011, vpiWarning,
+      "vpi_get_delays for object %s that has 2 delays but get only 1", 
+      __to_vpionam(__wrks1, otyp));
+     __set_vpi_time(&(delay_p->da[0]), &(tim[0]), delay_p->time_type, mdp); 
+     return;
+    }
+   /* if need 2 just copy */
+   if (delay_p->no_of_delays == 2) goto do_copy;
+
+   /* if need 3 fill third following normal rule and copy */ 
+   /* rule is that to-z is as slow as possible */
+   if (delay_p->no_of_delays == 3) 
+    {
+     if (tim[0] > tim[1]) tim[2] = tim[0]; else tim[2] = tim[1];
+     goto do_copy;
+    }
+
+   /* if need 6 convert to 12 (then ok to just ignore high 6 */
+   if (delay_p->no_of_delays >= 6)
+    { __fill_16vconst(ntim, tim, nvals); __map_16v_to_12vform(tim, ntim); }
+   goto do_copy;
+  }
+ /* if nvals 3, if need 1, use warn, use first, if 2 if path warn and */
+ /* use first 2, else no warn use 1st 2 */
+ if (nvals == 3)  
+  {
+   if (delay_p->no_of_delays == 1) 
+    {
+     __vpi_err(2011, vpiWarning,
+      "vpi_get_delays for object %s that has 3 delays but get only 1", 
+      __to_vpionam(__wrks1, otyp));
+     __set_vpi_time(&(delay_p->da[0]), &(tim[0]), delay_p->time_type, mdp); 
+     return;
+    }
+   /* 2 if different toz, warning and ignore */
+   if (delay_p->no_of_delays == 2)
+    {
+     if (tim[0] != tim[2] && tim[1] != tim[2])
+      {
+       __vpi_err(2011, vpiWarning,
+       "vpi_get_delays for object %s that has 3 delays but get only 2", 
+        __to_vpionam(__wrks1, otyp));
+      }
+     goto do_copy;
+    }
+   /* if need 6 convert to 12 (then ok to just ignore high 6 */
+   if (delay_p->no_of_delays >= 6)
+    { __fill_16vconst(ntim, tim, nvals); __map_16v_to_12vform(tim, ntim); }
+   goto do_copy;
+  }
+ /* know can not reduce to 3 - and stored as 6v form */
+ if (nvals == 6)
+  {
+   if (delay_p->no_of_delays < 6) 
+    {
+     __vpi_err(2011, vpiWarning,
+      "vpi_get_delays for object %s that has 6 delays but get only %d", 
+      __to_vpionam(__wrks1, otyp), delay_p->no_of_delays);
+     goto do_copy;
+    }
+   /* if need more than 6 must map to 12v form */
+   if (delay_p->no_of_delays > 6)
+    { __fill_16vconst(ntim, tim, nvals); __map_16v_to_12vform(tim, ntim); }
+   goto do_copy;
+  }
+ /* know can not reduce to 6 */  
+ if (nvals == 12)
+  {
+   if (delay_p->no_of_delays < 12) 
+    {
+     __vpi_err(2011, vpiWarning,
+      "vpi_get_delays for object %s that has 12 delays but get only %d", 
+      __to_vpionam(__wrks1, otyp), delay_p->no_of_delays);
+     goto do_copy;
+    }
+   goto do_copy;
+  }
+ __arg_terr(__FILE__, __LINE__);
+ 
+do_copy:
+ /* copy for 2, 3, 6, or 12 case, know tim has enough */
+ for (di = 0; di < delay_p->no_of_delays; di++) 
+  __set_vpi_time(&(delay_p->da[di]), &(tim[di]), delay_p->time_type, mdp); 
+}
+
+/*
+ * fill a vpi time struct from a word64
+ */
+extern void __set_vpi_time(struct t_vpi_time *vpitimp, word64 *timp,
+ int32 timtyp, struct mod_t *mdp)
+{
+ int32 unit;
+ double d1;
+
+ /* for getting delays, supress times means use 0 (not real) */
+ if (timtyp == vpiSuppressTime)
+  { vpitimp->high = 0L; vpitimp->low = 0L; return; }
+ vpitimp->type = timtyp;
+ /* vpi sim time is internal ticks (lowest precision in design) */
+ if (timtyp == vpiSimTime)
+  {
+   vpitimp->high = (int32) ((*timp >> 32) & WORDMASK_ULL);
+   vpitimp->low = (int32) (*timp & WORDMASK_ULL);
+   return;
+  }
+ /* vpiScaledRealTime case */
+ /* convert module specific ticks to real then scaled real */
+ if (!__v64_to_real(&d1, timp))
+  {
+   __vpi_err(2014, vpiWarning,
+    "conversion from internal time %s to time as real lost precision",
+   __to_timstr(__wrks1, timp));
+  }
+ if (mdp != NULL && !mdp->mno_unitcnv)
+  {
+   unit = __des_timeprec - mdp->mtime_units;
+   d1 /= __dbl_toticks_tab[unit];
+  }
+ vpitimp->real = d1;
+}
+
+/*
+ * set delays
+ */
+extern void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p)
+{
+ int32 is_trireg, ndx, sav_num_dels, bi;
+ struct mod_t *mdp;
+ struct h_t *hp; 
+ struct tenp_t *prtnetmap;
+ struct mipd_t *mipdp;
+ struct gate_t *gp, ngat, ogat;
+ struct net_t *np;
+ struct conta_t *cap;
+ struct tchk_t *tcp;
+ struct spcpth_t *pthp;
+ struct delctrl_t *dctp;
+ struct t_vpi_time tmpda[3];
+ struct t_vpi_delay wrkdel;  
+ struct mod_pin_t *mpp;
+ struct hrec_t *hrp;
+
+ if (__run_state == SS_COMP) { __still_comp_err("vpi_put_delays"); return; } 
+ hp = (struct h_t *) object;
+ if (!__validate_handle("vpi_put_delays", hp)) return;
+ hrp = hp->hrec;
+
+ if (__rosync_slot) { __bad_rosync_err("vpi_put_delays"); return; }
+ if (__run_state == SS_RESET || __run_state == SS_SIM)
+  {
+   /* inform since sim delay setting may not be supported by other sims */
+   __vpi_err(2106, vpiNotice,
+    "vpi_put_delays to object %s after simulation started - non standard feature",
+    __to_vpionam(__wrks1, hrp->htyp));
+  }
+ /* on error here, user must call error check routine */
+ if (!chk_delay_num("vpi_put_delays", hp, delay_p->no_of_delays, &ogat))
+  return;
+ /* can only set MIPD and replace DT NONE during SS_LOAD */
+ /* SJM - 02/16/00 - must allow changing MIPDs after start of sim */
+ /* to mimic XL acc_ */
+ /* ---
+ if (__run_state == SS_RESET || __run_state == SS_SIM)
+  {
+   -* once delays elaborated (after prep, before var init) can only change *-
+   -* delays if already exist *-
+   if (ogat.g_delrep == DT_NONE)
+    {
+     __vpi_err(1891, vpiError,
+      "vpi_put_delays to object %s with no delay in source illegal after simulation started",
+      __to_vpionam(__wrks1, hrp->htyp));
+     return;
+    }
+  } 
+ -- */ 
+ if (delay_p->pulsere_flag) 
+  {
+   if (hrp->htyp != vpiTchk)
+    {
+     __vpi_err(2107, vpiNotice,
+      "vpi_put_delays pulsere_flag values ignored - delay used for both limits");
+    }
+   else
+    {
+     __vpi_err(1884, vpiError,
+      "vpi_put_delays pulsere_flag illegal when setting timing check limit");
+     return;
+    }
+  }
+
+ /* need module type since need to scale delay */
+ is_trireg = FALSE;
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ /* assume if handle created, good - fill the delay union */
+
+ switch (hrp->htyp) {
+  case vpiGate: case vpiUdp: case vpiSwitch:
+really_gate:
+   gp = hrp->hu.hgp;
+   /* already checked for adding delay in non load run state */
+   if (gp->g_delrep == DT_NONE)
+    {
+     if (!__add_gate_pnd0del(gp, mdp, (char *) NULL)) return;
+    }
+   ogat.g_du = gp->g_du;
+   ogat.g_delrep = gp->g_delrep;
+   /* build the new value, maybe using old to append to if append flag */
+   /* uses itree loc. from hp if needed for append access */
+   /* new delay only allocated if returns T */
+   if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, FALSE, FALSE)) return;
+   
+   /* this must always recomputer toz (logic) and tox all because never */
+   /* explicitly given */
+   if (ngat.g_delrep == DT_4V)
+    {
+     if (gp->g_class == GC_UDP || gp->g_class == GC_LOGIC)
+      {
+       if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
+        {
+         ngat.g_du.d4v[2] = ngat.g_du.d4v[0];
+         ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
+        } 
+       else
+        {
+         ngat.g_du.d4v[2] = ngat.g_du.d4v[1];
+         ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
+        }
+      }
+     else
+      {
+       if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
+        ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
+       else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
+      }
+    }
+   
+   /* this handles freeing and realloc of delay union if needed */
+   __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
+   gp->g_du = ogat.g_du;  
+   gp->g_delrep = ogat.g_delrep;
+   __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
+   break;
+  case vpiPort: case vpiPortBit:
+   /* SJM 07/13/01 - notice only for (PORT form MIPD, not src-dst */
+   /* know this is only for one bit, i.e. scalar port of port bit */
+   mpp = &(mdp->mpins[hrp->hu.hpi]);
+   if (mpp->mptyp != IO_IN && mpp->mptyp != IO_BID)
+    {
+     __vpi_err(1885, vpiError,
+      "vpi_put_delays of non input or inout %s %s - not set because MIPD impossible",
+      __to_vpionam(__wrks1, hrp->htyp), __to_mpnam(__wrks2, mpp->mpsnam));
+     return;  
+    } 
+   if (hrp->htyp == vpiPort && mpp->mpwide != 1)
+    {
+     __vpi_err(2109, vpiNotice,
+      "vpi_put_delays of non scalar vpiPort (for MIPD) setting low bit");
+    }
+   if (hrp->htyp == vpiPort) ndx = 0; else ndx = hrp->hi;
+
+   /* build map between ports bit and connected net/bit */
+   prtnetmap = __bld_portbit_netbit_map(mpp);
+   if (!mpp->has_mipd) 
+    {
+     /* notice must build mipd table for all of every net connecting to port */
+     for (bi = 0; bi < mpp->mpwide; bi++)
+      {
+       np = prtnetmap[bi].tenu.np;
+       /* LOOKATME - think unc not possible here */
+       if (np == NULL || (np->nlds != NULL
+        && np->nlds->npntyp == NP_MIPD_NCHG)) continue;
+
+       /* allocate path for every net connected to port */ 
+       __add_alloc_mipd_npp(np, mdp);
+      }
+     mdp->mod_has_mipds = TRUE;
+     mpp->has_mipd = TRUE; 
+    }
+
+   /* ndx is actual port bit that connects */ 
+   np = prtnetmap[ndx].tenu.np;
+   bi = prtnetmap[ndx].nbi;
+
+   /* DBG remove -- */
+   if (np->nlds == NULL || np->nlds->npntyp != NP_MIPD_NCHG)
+    __misc_terr(__FILE__, __LINE__);
+   /* --- */
+   mipdp = &(np->nlds->elnpp.emipdbits[bi]);
+
+   /* if no active mipd for this net/bit, must enable with 0 delay */
+   if (mipdp->no_mipd) __setup_mipd(mipdp, np, mdp->flatinum);
+
+   ogat.g_du = mipdp->pb_mipd_du;
+   ogat.g_delrep = mipdp->pb_mipd_delrep;
+   /* treat this as 16 value path style delay - not 3 value gate type */
+   if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, TRUE, FALSE)) return;
+
+   /* set to x since can never explicitly set */
+   if (ngat.g_delrep == DT_4V)
+    {
+     if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
+      ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
+     else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
+    }
+
+   __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
+   mipdp->pb_mipd_du = ogat.g_du; 
+   mipdp->pb_mipd_delrep = ogat.g_delrep; 
+   __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
+   __my_free((char *) prtnetmap, mpp->mpwide*sizeof(struct tenp_t));
+   break;
+  case vpiNet:
+   np = hrp->hu.hnp;
+   if (np->nrngrep != NX_DWIR)
+    {
+     __vpi_err(1899, vpiError,
+      "vpi_put_delays to wire %s with no delay in source illegal - net must have delay in source",
+      __to_vpionam(__wrks1, hrp->htyp));
+     return;
+    }
+   ogat.g_du = np->nu.rngdwir->n_du;
+   ogat.g_delrep = np->nu.rngdwir->n_delrep;
+   if (np->ntyp == N_TRIREG) is_trireg = TRUE;
+   if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, FALSE, is_trireg))
+    return;
+
+   if (ngat.g_delrep == DT_4V)
+    {
+     /* set to x since can never explicitly set */
+     if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
+      ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
+     else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
+    }
+
+   __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
+   np->nu.rngdwir->n_du = ogat.g_du;  
+   np->nu.rngdwir->n_delrep = ogat.g_delrep;
+   __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
+   break;
+  case vpiContAssign:
+   /* 1 bit contas internally gates */
+   if (hrp->htyp2 == vpiGate) goto really_gate;
+
+   cap = hrp->hu.hcap;
+   /* already checked for adding delay if non load run state */
+   if (cap->ca_delrep == DT_NONE)
+    { 
+     if (!__add_conta_pnd0del(cap, mdp, (char *) NULL)) return;
+    }
+   ogat.g_du = cap->ca_du;
+   ogat.g_delrep = cap->ca_delrep;
+
+   if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, FALSE, FALSE))
+    return;
+   /* notice bld vpi new du can only produce DT 1V or DT 4V here */ 
+   if (ngat.g_delrep == DT_4V)
+    {
+     /* set to x since can never explicitly set */
+     if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
+      ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
+     else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
+    } 
+   __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
+   cap->ca_du = ogat.g_du;  
+   cap->ca_delrep = ogat.g_delrep;
+
+   /* must always make sure if needed ca_4vdel value changes */
+   switch ((byte) cap->ca_delrep) {
+    case DT_4V: case DT_IS4V: case DT_IS4V1: case DT_IS4V2: case DT_4X:
+     cap->ca_4vdel = TRUE;
+     break;
+    default: cap->ca_4vdel = FALSE;
+   }
+   __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
+   break;
+  case vpiTchk:
+   tcp = hrp->hu.htcp;
+   /* if can have 2 set and 2 passed only, set both */
+   if (tcp->tc_haslim2 && delay_p->no_of_delays == 2) 
+    {
+     /* 2nd need same fields as first */
+     wrkdel = *delay_p;
+     if (wrkdel.mtm_flag)
+      {
+       tmpda[0] = delay_p->da[3];
+       tmpda[1] = delay_p->da[4];
+       tmpda[2] = delay_p->da[5];
+      }
+     else tmpda[0] = delay_p->da[1];
+     wrkdel.da = &(tmpda[0]);
+     sav_num_dels = 2;  
+     wrkdel.no_of_delays = 1;
+     delay_p->no_of_delays = 1; 
+    }
+   else sav_num_dels = delay_p->no_of_delays;
+   /* know only 1 or 2 delays (not pulserr but maybe mtm) - copies both */
+   /* always set at least one */ 
+   ogat.g_du = tcp->tclim_du;
+   ogat.g_delrep = tcp->tc_delrep;
+   /* know at least one limit is present */
+   /* DBG remove -- */ 
+   if (ogat.g_delrep == DT_NONE) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, FALSE, FALSE))
+    goto tc_done;
+   __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
+   tcp->tclim_du = ogat.g_du;  
+   tcp->tc_delrep = ogat.g_delrep;
+   __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
+
+   /* has 2 and timing checks also has 2 limits */
+   if (tcp->tc_haslim2 && delay_p->no_of_delays == 2) 
+    {
+     ogat.g_du = tcp->tclim2_du;
+     ogat.g_delrep = tcp->tc_delrep2;
+     if (!bld_vpinewdu(&ngat, &ogat, &wrkdel, hp->hin_itp, TRUE, FALSE))
+      goto tc_done;
+     __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
+     tcp->tclim2_du = ogat.g_du;
+     tcp->tc_delrep2 = ogat.g_delrep;
+     __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
+    }
+tc_done:
+   /* must put back passed number so user can free */ 
+   delay_p->no_of_delays = sav_num_dels; 
+   break; 
+  case vpiModPath:
+   pthp = hrp->hu.hpthp;
+   ogat.g_du = pthp->pth_du;
+   ogat.g_delrep = pthp->pth_delrep;
+   if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, TRUE, FALSE))
+    return;
+   __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
+   pthp->pth_du = ogat.g_du;  
+   pthp->pth_delrep = ogat.g_delrep;
+   __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
+   break;
+  /* procedural delays */  
+  case vpiAssignment:
+   dctp = hrp->hu.hstp->st.sdc;
+   if (dctp->dctyp != DC_RHSDELAY)
+    {
+     __vpi_err(1886, vpiError,
+      "vpi_put_delays of vpiAssignment right hand side delay control impossible - no delay control");
+     return;
+    }
+set_dctrl_delay:
+   ogat.g_du = dctp->dc_du;
+   ogat.g_delrep = dctp->dc_delrep;
+   if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, FALSE, FALSE)) return;
+   __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
+   dctp->dc_du = ogat.g_du; 
+   dctp->dc_delrep = ogat.g_delrep;
+   __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
+   break;
+  case vpiDelayControl:  
+   dctp = hrp->hu.hstp->st.sdc;
+   /* DBG remove --- */
+   if (dctp->dctyp != DC_DELAY) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   goto set_dctrl_delay;
+  /* will not get to this case if not legal element with delay */
+  default: __vpi_terr(__FILE__, __LINE__);
+ }
+}
+
+/*
+ * given a vpi delay_p filled by user, build the _du for it
+ *
+ * know delay number correct
+ * if no source delay, caller changes to #0 before calling
+ */
+static int32 bld_vpinewdu(struct gate_t *ngp, struct gate_t *ogp,
+ p_vpi_delay delay_p, struct itree_t *itp, int32 is_path, int32 is_trireg)
+{
+ register int32 di;
+ int32 ndels, ondels, negdel[16];
+ word64 tim[16], otim[16], ntim[16], *dtab;
+
+ if (!fillchk_tim(tim, negdel, delay_p, itp)) return(FALSE); 
+ ndels = delay_p->no_of_delays;
+
+ /* handle appending - must be on delay_p array */ 
+ if (delay_p->append_flag)
+  { 
+   __push_itstk(itp);
+   __extract_delval(otim, &ondels, ogp->g_du, ogp->g_delrep);
+   __pop_itstk();
+   /* if either 1, widen with inform by replicating the 1 to width of other */
+   if ((ondels == 1 || ndels == 1) && (ondels != ndels)) 
+    {
+     __vpi_err(2008, vpiNotice,
+      "vpi_put_delays append mode old (%d) and new (%d) number of delays differ - one delay replicated",
+      ondels, ndels);   
+
+     if (ondels != 1)
+      {
+       for (di = 1; di < ondels; di++) tim[di] = tim[0];
+       ndels = ondels;
+      }
+     else
+      { 
+       for (di = 1; di < ndels; di++) otim[di] = otim[0];
+       ondels = ndels;
+      }
+    }
+   /* here need 2 delay case that is not normally reduced to */
+   if (!is_path && ondels == 3)
+    {
+     if (is_trireg) 
+      { if (otim[3] == otim[0] || otim[3] == otim[1]) ondels = 2; }
+     else
+      {
+       if ((otim[2] == otim[0] || otim[2] == otim[1]) 
+        && (otim[3] == otim[0] || otim[3] == otim[1])) ondels = 2; 
+      }
+    }
+   /* if too few new delays, use 0 for those (i.e. unchanged) */
+   if (ndels < ondels)
+    {
+     __vpi_err(2005, vpiNotice,
+      "vpi_put_delays append mode more old delays (%d) than new (%d) - 0 used for missing",
+      ondels, ndels);   
+     for (di = ndels; di < ondels; di++) tim[di] = 0ULL;
+     ndels = ondels;
+    }
+   /* too many - ignore with warning */
+   else if (ndels > ondels)
+    {
+     __vpi_err(2006, vpiWarning,
+      "vpi_put_delays append mode more new delays (%d) than old (%d) - extra ignored",
+      ndels, ondels);   
+     ndels = ondels;
+    }
+   /* do the update - know ndels and odels same */
+   for (di = 0; di < ndels; di++) ntim[di] = tim[di];
+   for (di = 0; di < ndels; di++)
+    {
+     if (negdel[di])
+      {
+       if (ntim[di] > otim[di])
+        {
+         __vpi_err(2004, vpiWarning,
+          "vpi_put_delays append result (pos. %d) negative (0 used)", di + 1);
+         tim[di] = 0ULL;
+        }
+       else tim[di] = otim[di] - ntim[di]; 
+      } 
+     else tim[di] = otim[di] + ntim[di];
+    }
+  }
+ /* now tim has right new delay value */
+ /* fill dtab (always 4 or 16 for path) */
+ if (ndels == 1)
+  {
+del1form:
+   ngp->g_du.d1v = (word64 *) __my_malloc(sizeof(word64));
+   *(ngp->g_du.d1v) = tim[0];
+   ngp->g_delrep = DT_1V;
+   return(TRUE);
+  }
+
+ /* see if can reduce to 1 - know at least 2 */
+ for (di = 1; di < ndels; di++) { if (tim[0] != tim[di]) goto no_reduce1; }
+ goto del1form;
+
+no_reduce1:
+ if (is_path)
+  {
+   dtab = (word64 *) __my_malloc(16*sizeof(word64));
+   __fill_16vconst(dtab, tim, ndels);
+   ngp->g_delrep = DT_16V;
+   ngp->g_du.d16v = dtab;
+  }
+ else
+  {
+   dtab = (word64 *) __my_malloc(4*sizeof(word64));
+   __fill_4vconst(dtab, &(tim[0]), &(tim[1]), &(tim[2]), ndels, is_trireg);
+   ngp->g_delrep = DT_4V;
+   ngp->g_du.d4v = dtab;
+  }
+ return(TRUE);
+}
+
+/*
+ * fill and check internal tim[] value from delay p
+ * return F on error
+ *
+ * mtm and pulsere possible here, pulsere no effect though 
+ * scaling depends upon module of handle
+ * LOOKATME - is it true only vpiScaledRealTime can be negative
+ */
+static int32 fillchk_tim(word64 *tim, int32 *negdel, p_vpi_delay delay_p,  
+ struct itree_t *itp)
+{
+ register int32 di;
+ int32 stride, ofset, ndels;
+ double d1;
+ word64 t1;
+ struct t_vpi_time *vpitimp;
+ struct mod_t *mdp;
+
+ ndels = delay_p->no_of_delays;
+ for (di = 0; di < ndels; di++) negdel[di] = FALSE;
+ stride = 1;
+ ofset = 0;
+ if (delay_p->pulsere_flag) stride *= 3;
+ if (delay_p->mtm_flag)
+  {
+   stride *= 3;
+   if (__mintypmax_sel == DEL_MIN) ofset = 0;
+   else if (__mintypmax_sel == DEL_TYP) ofset = 1;
+   else if (__mintypmax_sel == DEL_MAX) ofset = 2;
+   else __vpi_terr(__FILE__, __LINE__);
+  }
+ /* step 1: convert to internal ticks and set neg - maybe needed for inc */
+ for (di = 0; di < ndels; di++)
+  {
+   /* always ignore any pulse limits (2 and 3 or 3 through 8 if mtm) */
+   vpitimp = &(delay_p->da[stride*di + ofset]);
+
+   /* suppress ok for append - just do not change (0 if none) */
+   if (vpitimp->type == vpiSuppressTime)
+    {
+     if (!delay_p->append_flag)
+      {
+       /* () form normal 0 for SDF so do no need warning */
+       __vpi_err(2003, vpiWarning,
+        "vpi_put_delays vpiSuppressTime (pos. %d) ignored for replace mode - 0 used",
+         di + 1);
+      }
+     tim[di] = 0ULL;
+     continue;
+    }
+   if (vpitimp->type == vpiScaledRealTime)
+    {
+     d1 = vpitimp->real;
+     if (d1 < 0.0)
+      {
+       if (!delay_p->append_flag)
+        {
+         __vpi_err(2004, vpiWarning,
+          "replace mode vpi_put_delays value %g (pos. %d) negative (0 used)",
+          d1, di + 1);
+         tim[di] = 0ULL;
+         continue;
+        }  
+       d1 = -d1;
+       negdel[di] = TRUE;
+      }
+     if (!__real_to_v64tim(&t1, d1))
+      {
+       __vpi_err(1895, vpiError,
+        "vpi_put_delays value %g (pos. %d) too large for vpiScaledRealTime",
+         d1, di + 1);
+       return(FALSE);
+      }
+     mdp = itp->itip->imsym->el.emdp;
+     if (!mdp->mno_unitcnv) cnv_num64to_ticks_(tim[di], t1, mdp);
+     else tim[di] = t1;
+     continue;
+    }
+   if (vpitimp->type != vpiSimTime)
+    {
+     __vpi_err(1820, vpiError,
+      "vpi_put_delays t_vpi_time type value %d illegal (pos. %d)",
+      vpitimp->type, di + 1);
+     return(FALSE);
+    }
+   /* vpiSimTime is internal ticks */
+   /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
+   t1 = (word64) ((word32) vpitimp->low)
+    | (((word64) ((word32) vpitimp->high)) << 32);
+   tim[di] = t1;
+  }
+ return(TRUE);
+}
+
+/* 
+ * VALUE PROCESSING ROUTINES
+ */
+
+/*
+ * get value into value_p record
+ *
+ * LOOKATME - does fcall have a value (think not)
+ *
+ * SJM 10/21/99 - changed so if value not set causes vpi_ error
+ */
+extern void vpi_get_value(vpiHandle expr, p_vpi_value value_p)
+{
+ struct h_t *hp;
+ struct hrec_t *hrp;
+ struct gate_t *gp;
+ struct mod_t *mdp;
+ struct mod_pin_t *mpp;
+
+ /* must reset at start of call to no error */
+ __last_eip = NULL;
+ if (__run_state == SS_COMP)
+  { __still_comp_err("vpi_get_value"); return; } 
+
+ hp = (struct h_t *) expr;
+ if (!__validate_handle("vpi_get_value", hp)) return;
+ hrp = hp->hrec;
+
+ /* no access for suppress - LOOKATME - is this true */
+ if (value_p->format == vpiSuppressVal) return;
+
+ switch (hrp->htyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+  case vpiRealVar: case vpiParameter: case vpiSpecParam:
+    __push_itstk(hp->hin_itp); 
+    get_varorparam_val(hp, value_p);
+   __pop_itstk();
+   break;
+  case vpiNetBit: case vpiRegBit: case vpiVarSelect:
+   get_var_bit(hp, value_p);
+   break;
+  case vpiMemoryWord:
+   get_arrwrd_val(hp, value_p);
+   break;  
+  case vpiParamArrayWord:
+   get_paramarrwrd_val(hp, value_p);  
+   break;
+  case vpiConstant: case vpiPartSelect: case vpiOperation: case vpiFuncCall:
+   __push_itstk(hp->hin_itp); 
+   get_expr_val(hp, value_p);
+   __pop_itstk();
+   break;
+  case vpiPrimTerm:
+   get_primterm_val(hp, value_p);
+   break;
+  case vpiSysFuncCall:
+   /* LOOKATME - what is this supposed to do? */ 
+   get_vpisfcall_retval(hp, value_p); 
+   break;
+  case vpiUdpDefn:
+   get_vpiudpdefn_val(hp, value_p); 
+   break;
+  case vpiTableEntry:
+   get_vpitabentry_val(hp, value_p); 
+   break;
+  /* LOOKATME - no get value of quasi-continue force/assign because */
+  /* can build driver iterator and then access lhs expr. - is this right */
+
+  /* remaining access drivers - i.e. access internal driving code not val */
+  case vpiNetDriver:
+   get_vpi_netdrv_val(hp, value_p);
+   break;
+  case vpiNetBitDriver:
+   get_vpi_netbitdrv_val(hp, value_p);
+   break;
+  case vpiGate: case vpiUdp:
+   gp = hrp->hu.hgp;
+conta_gate:
+   get_gate_drv_valuep(hp, value_p, gp);
+   break;
+  case vpiContAssign:
+   if (hrp->htyp2 == vpiGate)
+    {gp = hrp->hu.hgp; goto conta_gate; }
+   get_vpiconta_drv_valuep(hp, value_p, hrp->hu.hcap);
+   break;
+  case vpiPort:
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   mpp = &(mdp->mpins[hrp->hu.hpi]);
+   get_vpiport_drv_valuep(hp, value_p, mpp);
+   break;
+  case vpiPortBit:
+   mdp = hp->hin_itp->itip->imsym->el.emdp;
+   mpp = &(mdp->mpins[hrp->hu.hpi]);
+   get_vpiportbit_drv_valuep(hp, value_p, mpp, hrp->hi);
+   break;
+  case vpiAttribute:
+   get_vpi_attrval(hp, value_p);
+   break;
+  default:
+   __vpi_err(1897, vpiError,
+    "vpi_get_value can not access value of %s (variable, param or expression needed)",
+    __to_vpionam(__wrks1, hrp->htyp));
+   return;
+ } 
+}
+
+/*
+ * get value of any variable or parameter include global param
+ * caller has set itree loc
+ */
+static void get_varorparam_val(struct h_t *hp, p_vpi_value value_p)
+{
+ register struct net_t *np;
+ register struct xstk_t *xsp;
+ byte *sbp;
+ struct xstk_t *xsp2; 
+
+ /* no checking needed */
+
+ np = hp->hrec->hu.hnp;
+ /* correct for type determined format */
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, np->ntyp, np->n_isavec, np->n_stren, FALSE);
+
+ /* non stren */
+ if (value_p->format != vpiStrengthVal)
+  {
+   push_xstk_(xsp, np->nwid); 
+   __ld_wire_val(xsp->ap, xsp->bp, np);
+   fill_valuep(value_p, xsp, np->ntyp, np->nwid);
+   __pop_xstk();
+   return;
+  }
+
+ /* need strength */
+ /* net stored as strength */
+ if (np->n_stren)
+  {
+   get_stwire_addr_(sbp, np);
+   if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
+   else stvec_fill_valuep(value_p, sbp, np->nwid);
+   return;
+  }
+ /* load as non stren and convert to stren case */
+ push_xstk_(xsp, np->nwid); 
+ __ld_wire_val(xsp->ap, xsp->bp, np);
+
+ push_xstk_(xsp2, 4*np->nwid); 
+ sbp = (byte *) xsp2->ap;
+ /* add strong */
+ __st_standval(sbp, xsp, ST_STRVAL); 
+ if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
+ else stvec_fill_valuep(value_p, sbp, np->nwid);
+ __pop_xstk();
+ __pop_xstk();  
+}
+
+/*
+ * fill a scalar strength valuep field from a strength vector
+ */
+static void stscal_fill_valuep(p_vpi_value value_p, register byte *sbp, int32 bi)
+{ 
+ register s_vpi_strengthval *svalp;
+ int32 slen;
+
+ slen = sizeof(struct t_vpi_strengthval);
+ if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
+ value_p->value.strength = (struct t_vpi_strengthval *) __wrkvalbufp;
+
+ svalp = &(value_p->value.strength[0]);
+ svalp[0].logic = (int32) (sbp[bi] & 3L);
+ svalp[0].s0 = __map_tovpi_stren((int32) ((sbp[bi] >> 5) & 7));
+ svalp[0].s1 = __map_tovpi_stren((int32) ((sbp[bi] >> 2) & 7));
+}
+
+/*
+ * fill a strength valuep field from a strength vector
+ *
+ * 04/01/00 - for veriog 2000 now can access/stren strength in vectors
+ * user must allocate wide enough t vpi_strengthval array
+ * caller must convert value to strength if non strength
+ */
+static void stvec_fill_valuep(p_vpi_value value_p, register byte *sbp,
+ int32 swid)
+{ 
+ register int32 bi;
+ register s_vpi_strengthval *svalp;
+ int32 slen;
+
+ slen = swid*sizeof(struct t_vpi_strengthval);
+ if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
+ value_p->value.strength = (struct t_vpi_strengthval *) __wrkvalbufp;
+
+ svalp = &(value_p->value.strength[0]);
+ for (bi = 0; bi < swid; bi++) 
+  {
+   svalp[bi].logic = (int32) (sbp[bi] & 3L);
+   svalp[bi].s0 = __map_tovpi_stren((int32) ((sbp[bi] >> 5) & 7));
+   svalp[bi].s1 = __map_tovpi_stren((int32) ((sbp[bi] >> 2) & 7));
+  }
+}
+
+/*
+ * map from vpi strength values to internal Cver values
+ * returns -1 on bad value  
+ */
+extern int32 __map_frvpi_stren(int32 vpistval)
+{
+ int32 stval;
+
+ /* must be left as int32 in case bad value_p record */
+ switch (vpistval) {
+  case vpiSupplyDrive: stval = ST_SUPPLY; break;
+  case vpiStrongDrive: stval = ST_STRONG; break;
+  case vpiPullDrive: stval = ST_PULL; break;
+  case vpiWeakDrive: stval = ST_WEAK; break;
+  case vpiLargeCharge: stval = ST_LARGE; break;
+  case vpiMediumCharge: stval = ST_MEDIUM; break;
+  case vpiSmallCharge: stval = ST_SMALL; break;
+  case vpiHiZ: stval = ST_HIGHZ; break;
+  default: return(-1);
+ }
+ return(stval);
+}
+
+/*
+ * map from internal strength values to vpi strength constant
+ */
+extern word32 __map_tovpi_stren(word32 stval)
+{
+ word32 vpistval;
+
+ switch ((byte) stval) {
+  case ST_SUPPLY: vpistval = vpiSupplyDrive; break;
+  case ST_STRONG: vpistval = vpiStrongDrive; break;
+  case ST_PULL: vpistval = vpiPullDrive; break;
+  case ST_WEAK: vpistval = vpiWeakDrive; break;
+  case ST_LARGE: vpistval = vpiLargeCharge; break;
+  case ST_MEDIUM: vpistval = vpiMediumCharge; break;
+  case ST_SMALL: vpistval = vpiSmallCharge; break;
+  case ST_HIGHZ: vpistval = vpiHiZ; break;
+  default: __vpi_terr(__FILE__, __LINE__); return(0);
+ }
+ return(vpistval);
+}
+
+/*
+ * get variable bit 
+ *
+ * this must set itree context
+ */
+static void get_var_bit(struct h_t *hp, p_vpi_value value_p)
+{
+ register int32 biti;
+ struct net_t *np;
+ byte *sbp;
+ struct xstk_t *xsp, *xsp2;
+
+ /* nothing to check */
+
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+
+ biti = get_vpibit_index(&np, hp);
+
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, np->ntyp, np->n_isavec, np->n_stren, FALSE);
+
+ /* non strength case */
+ if (value_p->format != vpiStrengthVal)
+  {
+   push_xstk_(xsp, 1);
+   __ld_bit(xsp->ap, xsp->bp, np, biti);
+   fill_valuep(value_p, xsp, np->ntyp, 1);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+
+ /* stored as stren */ 
+ if (np->n_stren) 
+  {
+   get_stwire_addr_(sbp, np);
+   stscal_fill_valuep(value_p, sbp, biti);
+   __pop_itstk();
+   return;
+  }
+
+ /* stored as non stren but get val asked for stren */
+ push_xstk_(xsp, 1);
+ __ld_bit(xsp->ap, xsp->bp, np, biti);
+ push_xstk_(xsp2, 4);
+ sbp = (byte *) xsp2->ap;
+ __st_standval(sbp, xsp, ST_STRVAL); 
+ /* SJM 02/08/01 - for (net/reg) bit object sbp is the one bit */
+ stscal_fill_valuep(value_p, sbp, 0);
+ __pop_xstk();
+ __pop_xstk();
+ __pop_itstk();
+}
+
+/*
+ * get value of one array word32 given a array word32 (indexed) handle 
+ *
+ * know passed handle is array word32 and correct index in range for well
+ * formed handle
+ */
+static void get_arrwrd_val(struct h_t *hp, p_vpi_value value_p)  
+{
+ int32 arri, arrwid;
+ byte *sbp;
+ struct net_t *np;
+ struct xstk_t *xsp, *xsp2;
+
+ /* nothing to check - stren legal */
+
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+
+ /* notice union field is index and since array word32 is in has itree */
+ /* inst., can use for ptr to the containing handle */
+ /* this uses comp_ndx that works for arrays too */
+ arri = get_vpibit_index(&np, hp);
+
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, np->ntyp, np->n_isavec, np->n_stren, FALSE);
+ 
+ /* never strength - but may need to convert */
+ arrwid = __get_arrwide(np);
+ push_xstk_(xsp, np->nwid); 
+ __ld_arr_val(xsp->ap, xsp->bp, np->nva, arrwid, np->nwid, arri);
+ 
+ if (value_p->format != vpiStrengthVal)
+  {
+   fill_valuep(value_p, xsp, np->ntyp, np->nwid);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+
+ /* always need to add stren here */
+ push_xstk_(xsp2, 4*np->nwid); 
+ sbp = (byte *) xsp2->ap;
+ __st_standval(sbp, xsp, ST_STRVAL); 
+
+ if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
+ else stvec_fill_valuep(value_p, sbp, np->nwid);
+ __pop_xstk();
+ __pop_xstk();
+ __pop_itstk();
+}
+
+/*
+ * get value of one param array word32 given a array word32 (indexed) handle 
+ *
+ * know passed handle is parameter array word32 and correct index in range
+ * paramater array values are not packed and must access nva.wp here
+ * because for parameter arrays same as expr. which is top level concat
+ *
+ * LOOKATME - if allowing global param arrays need to fix pushing itree loc
+ * LOOKATME - also maybe should not allow strengths
+ */
+static void get_paramarrwrd_val(struct h_t *hp, p_vpi_value value_p)  
+{
+ int32 arri, wlen;
+ word32 *wp;
+ byte *sbp;
+ struct net_t *np;
+ struct xstk_t *xsp, *xsp2;
+
+ /* nothing to check - allowing strengths */
+
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+
+ /* always constant for param array word32 get values */
+ /* this needs itree context */
+ arri = get_vpibit_index(&np, hp);
+
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, np->ntyp, np->n_isavec, FALSE, FALSE);
+
+ /* do not need array size (no. of cells) because know handle ind in rng */
+ push_xstk_(xsp, np->nwid); 
+ wlen = wlen_(np->nwid);
+ wp = &(np->nva.wp[2*wlen*arri]);
+ memcpy(xsp->ap, wp, 2*WRDBYTES*wlen);
+
+ if (value_p->format != vpiStrengthVal)
+  {
+   fill_valuep(value_p, xsp, np->ntyp, np->nwid);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+
+ /* always need to add stren here */
+ push_xstk_(xsp2, 4*np->nwid); 
+ sbp = (byte *) xsp2->ap;
+ __st_standval(sbp, xsp, ST_STRVAL); 
+
+ if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
+ else stvec_fill_valuep(value_p, sbp, np->nwid);
+ __pop_xstk();
+ __pop_xstk();
+ __pop_itstk();
+}
+
+/*
+ * get value of expression
+ * caller has set itree loc
+ */
+static void get_expr_val(struct h_t *hp, p_vpi_value value_p)  
+{
+ int32 wtyp;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+ struct hrec_t *hrp;
+
+ hrp = hp->hrec;
+
+ /* only error is stren illegal */
+ if (valp_stren_err(hrp, value_p)) return; 
+
+ /* notice expr. handle itree loc. is always ref. location */   
+ /* LOOKATME - these are never strength - think this is right - check */
+ xp = hrp->hu.hxp;
+ xsp = __eval_xpr(xp);
+ if (value_p->format == vpiObjTypeVal) expr_correct_objtypval(xp, value_p);
+
+ if (xp->is_real) wtyp = N_REAL; else wtyp = N_REG;
+ fill_valuep(value_p, xsp, wtyp, xsp->xslen);
+ __pop_xstk();
+}
+
+/*
+ * check for illegal strength - return T if stren (error) F if non stren 
+ * if error if stren
+ */
+static int32 valp_stren_err(struct hrec_t *hrp, p_vpi_value value_p)  
+{ 
+ /* for expressons - strength not allowed */
+ if (value_p->format == vpiStrengthVal)
+  {
+   __vpi_err(1929, vpiError,
+    "vpi_get_value vpiStrengthVal format illegal for expression object %s",
+    __to_vpionam(__wrks1, hrp->htyp));
+   return(TRUE);
+  }
+ return(FALSE);
+}
+
+/*
+ * get value of primitve terminal
+ *
+ * notice legal to get any terminal including input
+ *
+ * SJM 11/26/00 - change so for all but tran and pull gets get internal
+ * driving value for gate/udp/mos-gates in gstate
+ * this now adds strengths for outputs if gate drives strength and
+ * computes
+ *
+ * LOOKATME - for tran and pull gates think net value and driving value same?
+ */
+static void get_primterm_val(struct h_t *hp, p_vpi_value value_p)  
+{
+ register struct gate_t *gp;
+ register word32 gtermwrd;
+ int32 has_stren;
+ byte sbv, *sbp;
+ struct hrec_t *hrp;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+
+ hrp = hp->hrec;
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+
+ gp = hrp->hu.hgp;
+ /* case 1: accessing value of connecting wire as terminal value */ 
+ /* know these always have stren */
+ if (gp->g_class == GC_PULL || gp->g_class == GC_TRAN
+  || gp->g_class == GC_TRANIF)
+  {
+   xp = hrp->hu.hgp->gpins[hrp->hi];
+   if (value_p->format == vpiObjTypeVal) expr_correct_objtypval(xp, value_p);
+
+   /* LOOKATME - is it possible for tran channels to not have stren? */ 
+   if (value_p->format == vpiStrengthVal)
+    {
+     /* this adds strong if expr non strength */
+     xsp = __ndst_eval_xpr(xp);
+     sbp = (byte *) xsp->ap;
+     stscal_fill_valuep(value_p, sbp, 0);
+    }
+   else
+    {
+     xsp = __eval_xpr(xp); 
+     /* type since no net can be reg since reg can connect to input */
+     fill_valuep(value_p, xsp, N_REG, xsp->xslen);
+    }
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+ /* case 2: logic/udp/mos gate - this is same as gate value */
+ if (hrp->hi == 0)
+  {
+   /* case 2a: gate output value */
+   get_gate_drv_valuep(hp, value_p, gp);
+   __pop_itstk();
+   return;
+  }
+ /* case 2b primitive terminal input value - first input is 1 */
+ /* this gets gstate terminal value since within tick gstate may not be */
+ /* updated yet after connecting expr change */ 
+
+ /* SJM 11/26/00 - allowing strength where added as strong */
+ xp = hrp->hu.hgp->gpins[hrp->hi];
+ if (value_p->format == vpiObjTypeVal) expr_correct_objtypval(xp, value_p);
+
+ gtermwrd = __ld_gate_in(gp, hrp->hi, &has_stren);
+ if (value_p->format != vpiStrengthVal)
+  {
+   push_xstk_(xsp, 1);
+   xsp->ap[0] = gtermwrd & 1L;
+   xsp->bp[0] = (gtermwrd >> 1) & 1L;
+   fill_valuep(value_p, xsp, N_WIRE, 1);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+ /* need stren */
+ push_xstk_(xsp, 4);
+ sbv = (byte) gtermwrd;
+ /* add gate driving stren if needed */
+ if (!has_stren && sbv != 2) sbv |= (ST_STRVAL << 2); 
+ stscal_fill_valuep(value_p, &(sbv), 0);
+ __pop_itstk();
+}
+
+/*
+ * get return value for current user task or function only
+ *
+ * must be called from current system function or error
+ * uses own itree context
+ * LOOKATME - no internal vpi storage but LRM not clear
+ * LOOKATME - what is this supposed to do - get last value? 
+ */
+static void get_vpisfcall_retval(struct h_t *hp, p_vpi_value value_p)
+{
+ int32 sf_ind;
+ word32 isavec;
+ p_vpi_systf_data tfdatp;
+ struct systftab_t *sfp;
+ struct sysfunc_t *sfbp;
+ struct hrec_t *hrp;
+ char s1[RECLEN];
+
+ hrp = hp->hrec;
+ /* --- DBG remove --- */
+ if (hrp->hu.hxp == NULL) __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+
+ if (valp_stren_err(hrp, value_p)) return; 
+
+ if (hrp->hu.hxp != __cur_sysf_expr)
+  {
+   if (__cur_sysf_expr != NULL)
+    {
+     sf_ind = __cur_sysf_expr->lu.x->lu.sy->el.esyftbp->syfnum;
+     sf_ind -= (__last_veriusertf + 1); 
+     sfp = &(__systftab[sf_ind]);
+     tfdatp = (p_vpi_systf_data) sfp->vpi_sytfdat;
+     strcpy(s1, tfdatp->tfname);   
+    }
+   else strcpy(s1, "**none called**");
+   __vpi_err(1848, vpiError,
+    "vpi_get_value of vpiSysFuncCall %s (return value) illegal - must use from calltf cb", 
+    s1);
+   return; 
+  }
+ sf_ind = __cur_sysf_expr->lu.x->lu.sy->el.esyftbp->syfnum;
+ sf_ind -= (__last_veriusertf + 1); 
+ sfp = &(__systftab[sf_ind]);
+ tfdatp = (p_vpi_systf_data) sfp->vpi_sytfdat;
+ sfbp = sfp->sfu.sfbp;
+ if (value_p->format == vpiObjTypeVal)
+  {
+   isavec = (sfbp->retwid == 1) ? FALSE : TRUE;
+   correct_objtypval(value_p, sfbp->retntyp, isavec, FALSE, FALSE);
+  }
+ __push_itstk(hp->hin_itp);
+ fill_valuep(value_p, __cur_sysf_xsp, sfbp->retntyp, sfbp->retwid);
+ __pop_itstk();
+}
+
+/*
+ * get udp definition value
+ * value not per instance
+ */
+static void get_vpiudpdefn_val(struct h_t *hp, p_vpi_value value_p)
+{
+ struct hrec_t *hrp;
+ struct udp_t *udpp;
+ struct xstk_t *xsp;
+
+ hrp = hp->hrec;
+ /* checking */
+ if (hrp->hu.hudpp->ival == NO_VAL)
+  {
+   __vpi_err(1939, vpiError,
+    "vpi_get_value of vpiUdpDefn but no initial value - value_p unchanged"); 
+   return;
+  }
+ if (value_p->format == vpiTimeVal)
+  {
+   __vpi_err(1892, vpiError,
+    "vpi_get_value of vpiUdpDefn initial value VpiTimeVal value illegal - no module context"); 
+    return;
+  }
+ if (valp_stren_err(hrp, value_p)) return; 
+
+ /* get initial value - if get here know present */
+ udpp = hrp->hu.hudpp;
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, N_REG, FALSE, FALSE, FALSE);
+ push_xstk_(xsp, 1); 
+ xsp->bp[0] = 0L;
+ if (udpp->ival == 3) { xsp->ap[0] = 1L; xsp->bp[0] = 1L; }
+ else xsp->ap[0] = (word32) udpp->ival;
+ fill_valuep(value_p, xsp, N_REG, xsp->xslen);
+ __pop_xstk();
+}
+
+/*
+ * get udp definition value
+ * value not per instance
+ */
+static void get_vpitabentry_val(struct h_t *hp, p_vpi_value value_p)
+{
+ int32 slen;
+ struct hrec_t *hrp;
+ struct udp_t *udpp;
+ struct utline_t *utlp;
+
+ hrp = hp->hrec;
+
+ /* special correction of obj type here */
+ if (value_p->format != vpiObjTypeVal)
+  {
+   if (value_p->format != vpiStringVal)
+    {
+     __vpi_err(1892, vpiError,
+     "vpi_get_value of vpiTableEntry udp line only vpiStringVal format supported");
+     return;
+    }
+   else value_p->format = vpiStringVal;
+  }
+
+ utlp = hrp->hu.hutlp;
+ udpp = (struct udp_t *) hp->hin_itp;
+ slen = 5*(udpp->numstates + 1) + 1;
+ if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
+ value_p->value.str = __wrkvalbufp;
+ udp_line_to_str(value_p->value.str, udpp, utlp);
+}
+
+/*
+ * DRIVER GET VALUE ROUTINES
+ */
+
+/*
+ * get net driver value
+ *
+ * 04/01/00 SJM - for verilog 2000 vectors of strens legal
+ */
+static void get_vpi_netdrv_val(struct h_t *hp, p_vpi_value value_p)
+{
+ byte *sbp;
+ struct net_t *np;
+ struct xstk_t *xsp, *xsp2;
+
+ /* nothing to check */
+
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+
+ /* notice must access net value through here */
+ xsp = push_vpi_drv_val(hp, &np);
+
+ /* correct for type determined format */
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, np->ntyp, np->n_isavec, np->n_stren, FALSE);
+
+ /* non stren case */
+ if (value_p->format != vpiStrengthVal)
+  {
+   fill_valuep(value_p, xsp, np->ntyp, np->nwid);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+
+ /* this uses net fields since stren expr value impossible */
+ /* net stored as stren - loaded stren driver */
+ if (np->n_stren)
+  {
+   sbp = (byte *) xsp->ap;
+   if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
+   else stvec_fill_valuep(value_p, sbp, np->nwid);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+ /* else convert to stren */
+ push_xstk_(xsp2, 4*np->nwid); 
+ sbp = (byte *) xsp2->ap;
+ /* add strong */
+ __st_standval(sbp, xsp, ST_STRVAL); 
+
+ if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
+ else stvec_fill_valuep(value_p, sbp, np->nwid);
+
+ __pop_xstk();
+ __pop_xstk();
+ __pop_itstk();
+}
+
+/*
+ * push vpi net driver value onto stack (entire net case) 
+ *
+ * existence of handle means all bits of this instance of net have added drvr
+ */
+static struct xstk_t *push_vpi_drv_val(struct h_t *hp, struct net_t **pnp)
+{
+ register struct net_t *np;
+ register struct xstk_t *xsp;
+ register struct vpi_drv_t *vpidrvp;     
+ byte *sbp, *sbp2;
+ struct net_pin_t *npp;
+
+ npp = hp->hrec->hu.hnpp;
+ np = npp->elnpp.enp;
+ *pnp = np;
+ /* obnum is index of driver */
+ vpidrvp = np->vpi_ndrvs[npp->obnum];
+ if (np->n_stren)
+  {
+   push_xstk_(xsp, 4*np->nwid);
+   sbp = (byte *) xsp->ap;
+   sbp2 = &(vpidrvp->vpi_drvwp.bp[__inum*np->nwid]);
+   memcpy(sbp, sbp2, np->nwid);
+  }
+ else
+  {
+   push_xstk_(xsp, np->nwid);
+   __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_drvwp, np->nwid); 
+  }
+ return(xsp);
+}
+
+/*
+ * get net bit driver value
+ */
+static void get_vpi_netbitdrv_val(struct h_t *hp, p_vpi_value value_p)
+{
+ byte *sbp;
+ struct net_t *np;
+ struct xstk_t *xsp, *xsp2;
+
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+
+ xsp = push_vpi_bitdrv_val(hp, &np);
+
+ /* correct for type determined format */
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, np->ntyp, np->n_isavec, np->n_stren, TRUE);
+
+ /* this uses net since stren expr value impossible */
+ if (value_p->format != vpiStrengthVal)
+  {
+   fill_valuep(value_p, xsp, np->ntyp, 1);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+
+ if (np->n_stren) 
+  {
+   sbp = (byte *) xsp->ap;
+   stscal_fill_valuep(value_p, sbp, 0);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+
+ /* must add strong */
+ push_xstk_(xsp2, 4);
+ sbp = (byte *) xsp2->ap;
+ __st_standval(sbp, xsp, ST_STRVAL); 
+ stscal_fill_valuep(value_p, sbp, 0);
+ __pop_xstk();
+ __pop_xstk();
+ __pop_itstk();
+}
+
+/*
+ * push vpi net bit driver value onto stack
+ *
+ * existence of handle means handle's bit of this instance of net has add drvr
+ */
+static struct xstk_t *push_vpi_bitdrv_val(struct h_t *hp, struct net_t **pnp)
+{
+ register struct net_t *np;
+ register struct xstk_t *xsp, *xsp2;
+ register struct vpi_drv_t *vpidrvp;     
+ byte *sbp;
+ struct net_pin_t *npp;
+
+ npp = hp->hrec->hu.hnpp;
+ np = npp->elnpp.enp;
+ *pnp = np;
+ /* obnum is index of driver */
+ vpidrvp = np->vpi_ndrvs[npp->obnum];
+ if (np->n_stren)
+  {
+   push_xstk_(xsp, 4);
+   sbp = (byte *) xsp->ap;
+   sbp[0] = vpidrvp->vpi_drvwp.bp[__inum*np->nwid + hp->hrec->hi];
+  }
+ else
+  {
+   push_xstk_(xsp, 1);
+   push_xstk_(xsp2, np->nwid);
+   __ld_perinst_val(xsp2->ap, xsp2->bp, vpidrvp->vpi_drvwp, np->nwid); 
+   xsp->ap[0] = rhsbsel_(xsp2->ap, hp->hrec->hi);
+   xsp->bp[0] = rhsbsel_(xsp2->bp, hp->hrec->hi);
+   __pop_xstk();
+  }
+ return(xsp);
+}
+
+/*
+ * fill a gate driver valuep
+ */
+static void get_gate_drv_valuep(struct h_t *hp, p_vpi_value value_p,
+ struct gate_t *gp)
+{
+ int32 has_stren;
+ word32 uwrd;
+ byte *sbp;
+ struct xstk_t *xsp;
+
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+
+ /* correct for type determined format */
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, N_WIRE, FALSE, (gp->g_hasst) ? TRUE : FALSE,
+   FALSE);
+
+ if (value_p->format != vpiStrengthVal)
+  {
+   push_xstk_(xsp, 1);
+   uwrd = __ld_gate_out(gp, &has_stren);
+   /* this must load value and remove strength since drives constant */
+   /* notice this is non stren case - stren passing gates not proc. here */
+   xsp->ap[0] = uwrd & 1L;
+   xsp->bp[0] = (uwrd >> 1) & 1L;
+   fill_valuep(value_p, xsp, N_WIRE, 1);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+ /* need stren */
+ push_xstk_(xsp, 4);
+ sbp = (byte *) xsp->ap;
+ sbp[0] = (byte) __ld_gate_out(gp, &has_stren);
+ /* add gate driving stren if needed */
+ if (!has_stren && sbp[0] != 2)
+  {
+   /* 04/01/00 - add gate strength since that is driven */
+   /* 08/07/01 - only possibility here is both strong since no stren */
+   sbp[0] |= (ST_STRVAL << 2); 
+  }
+ stscal_fill_valuep(value_p, sbp, 0);
+ __pop_xstk();
+ __pop_itstk();
+}
+
+/*
+ * for vpi get value - get conta driving value and assign to value p 
+ *
+ * 1 bit conta drivers not seen here (converted to gates) 
+ * in Verilog conta strength hard coded in gate so only or in if needed
+ *
+ * SJM 09/28/02 - for rhs conta per bit must combine PB drv values 
+ */
+static void get_vpiconta_drv_valuep(struct h_t *hp, p_vpi_value value_p,
+ struct conta_t *cap)
+{
+ register int32 bi;
+ int32 blen;
+ byte *sbp;
+ struct xstk_t *xsp, *xsp2;
+ struct conta_t *pbcap;
+
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+
+ /* correct for type determined format - know lhs is some kind of wire */
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, N_WIRE, TRUE, (cap->ca_hasst) ? TRUE : FALSE,
+   FALSE);
+
+ blen = cap->lhsx->szu.xclen;
+ if (cap->ca_pb_sim)
+  {
+   /* SJM 09/28/02 - for per bit rhs concat conta, must assemble val */
+   push_xstk_(xsp, blen);
+   for (bi = 0; bi < blen; bi++) 
+    {
+     pbcap = &(cap->pbcau.pbcaps[bi]);
+     if (pbcap->ca_drv_wp.wp == NULL)
+      {
+       xsp2 = __eval2_xpr(pbcap->rhsx);
+       /* DBG remove -- */
+       if (xsp2->xslen != 1) __misc_terr(__FILE__, __LINE__);
+       /* --- */
+      }
+     else
+      {
+       push_xstk_(xsp2, 1);
+       __ld_perinst_val(xsp2->ap, xsp2->bp, pbcap->ca_drv_wp, 1); 
+      }
+     __lhsbsel(xsp->ap, bi, xsp2->ap[0]);
+     __lhsbsel(xsp->bp, bi, xsp2->bp[0]);
+    }
+  }
+ else
+  {
+   if (cap->ca_drv_wp.wp == NULL)
+    {
+     xsp = __eval2_xpr(cap->rhsx);
+     if (xsp->xslen != blen)
+      {
+       if (xsp->xslen < blen)
+        {
+         /* SJM 05/10/04 - if widening and signed, must sign extend */
+         if (cap->rhsx->has_sign) __sgn_xtnd_widen(xsp, blen);
+         else __sizchg_widen(xsp, blen);
+        }
+       else __sizchgxs(xsp, blen);
+      }
+    }
+   else
+    {
+     push_xstk_(xsp, blen);
+     __ld_perinst_val(xsp->ap, xsp->bp, cap->ca_drv_wp, blen); 
+    }
+  }
+
+ /* 04/01/00 - now for verilog 2000 handling strength vectors */
+ if (value_p->format != vpiStrengthVal)
+  {
+   fill_valuep(value_p, xsp, N_WIRE, blen);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+
+ /* else convert to stren */
+ push_xstk_(xsp2, 4*blen); 
+ sbp = (byte *) xsp2->ap;
+ /* add stren - if does not have st val, stren is strong */
+ __st_standval(sbp, xsp, cap->ca_stval); 
+
+ /* DBG remove --
+ if (blen == 1) __vpi_terr(__FILE__, __LINE__);
+ --- */
+
+ stvec_fill_valuep(value_p, sbp, blen);
+ __pop_xstk();
+ __pop_xstk();
+ __pop_itstk();
+}
+
+/*
+ * for vpi get value - get mod. port driving value and assign to value p 
+ *
+ * port driver is just value of expr.
+ */
+static void get_vpiport_drv_valuep(struct h_t *hp, p_vpi_value value_p,
+ struct mod_pin_t *mpp)
+{
+ int32 is_stren, isavec;
+ byte *sbp;
+ struct xstk_t *xsp, *xsp2;
+
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+
+ if (mpp->mpref->x_stren) is_stren = TRUE; else is_stren = FALSE; 
+ if (mpp->mpwide == 1) isavec = FALSE; else isavec = TRUE;
+ /* correct for type determined format - know lhs is some kind of wire */
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, N_WIRE, isavec, is_stren, FALSE);
+
+ /* if module input port, use driving value */
+ sbp = NULL;
+ /* no delay - driver is expr. value */
+ /* module port (down) side is expr. - no need for width change */
+ if (is_stren) xsp = __ndst_eval_xpr(mpp->mpref);
+ else xsp = __eval2_xpr(mpp->mpref);
+
+ if (value_p->format != vpiStrengthVal)
+  {
+   if (is_stren)
+    {
+     /* here must remove strength */
+     sbp = (byte *) xsp->ap;
+     push_xstk_(xsp2, mpp->mpwide);
+     __ld_stval(xsp2->ap, xsp2->bp, sbp, mpp->mpwide);
+     fill_valuep(value_p, xsp2, N_WIRE, mpp->mpwide);
+     __pop_xstk();
+    }
+   else fill_valuep(value_p, xsp, N_WIRE, mpp->mpwide);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+ /* 04/01/00 SJM - for strength now loading entire vector */
+ if (is_stren)
+  {
+   sbp = (byte *) xsp->ap; 
+   if (mpp->mpwide == 1) stscal_fill_valuep(value_p, sbp, 0);
+   else stvec_fill_valuep(value_p, sbp, mpp->mpwide);
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  } 
+ /* driving value non strength - must add strong */
+ /* load as non stren and convert to stren case */
+ push_xstk_(xsp2, 4*mpp->mpwide); 
+ sbp = (byte *) xsp2->ap;
+ /* add strong */
+ __st_standval(sbp, xsp, ST_STRVAL); 
+ if (mpp->mpwide == 1) stscal_fill_valuep(value_p, sbp, 0);
+ else stvec_fill_valuep(value_p, sbp, mpp->mpwide);
+ __pop_xstk();
+ __pop_xstk();
+ __pop_itstk();
+}
+
+/*
+ * for vpi get value - get mod. port bit driving value and assign to value p 
+ * routine for vpi Port Bit
+ */
+static void get_vpiportbit_drv_valuep(struct h_t *hp, p_vpi_value value_p,
+ struct mod_pin_t *mpp, int32 bi)
+{
+ int32 is_stren, ind;
+ word32 av, bv;
+ byte *sbp;
+ struct xstk_t *xsp, *xsp2, *xsp3;
+
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+
+ if (mpp->mpref->x_stren) is_stren = TRUE; else is_stren = FALSE; 
+ /* DBG remove --- */
+ if (mpp->mpwide == 1) __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+ /* correct for type determined format - know lhs is some kind of wire */
+ if (value_p->format == vpiObjTypeVal)
+  correct_objtypval(value_p, N_WIRE, FALSE, is_stren, TRUE);
+
+ xsp2 = NULL;
+ sbp = NULL;
+ /* no delay - driver is expr. value */
+ /* module port (down) side is expr. - no need for width change */
+ if (is_stren)
+  { 
+   xsp2 = __ndst_eval_xpr(mpp->mpref);
+   sbp = (byte *) xsp2->ap;
+   ind = __inum*mpp->mpwide + bi; 
+   sbp = &(sbp[ind]); 
+  }
+ else
+  {
+   xsp = __eval2_xpr(mpp->mpref);
+   av = rhsbsel_(xsp->ap, bi);
+   bv = rhsbsel_(xsp->bp, bi);
+   __pop_xstk();
+   push_xstk_(xsp2, 1);
+   xsp2->ap[0] = av;
+   xsp2->bp[0] = bv;
+  }
+
+ /* know one bit driving val on stack either stren or non stren */ 
+ if (value_p->format != vpiStrengthVal)
+  {
+   if (is_stren)
+    {
+     /* remove bit's stren */
+     av = sbp[0] & 1L;
+     bv = ((sbp[0] & 2L) >> 1);
+     __pop_xstk();
+     push_xstk_(xsp2, 1);
+     xsp2->ap[0] = av;
+     xsp2->bp[0] = bv;
+     fill_valuep(value_p, xsp2, N_WIRE, 1);
+    }
+   else fill_valuep(value_p, xsp2, N_WIRE, mpp->mpwide);
+   __pop_xstk();
+   __pop_itstk();
+   return;   
+  }
+ /* need stren in value p */
+ if (!is_stren)
+  {
+   push_xstk_(xsp3, 4);
+   /* add strong for bit */
+   sbp = (byte *) xsp3->ap;
+   sbp[0] = (byte) (xsp2->ap[0] | (xsp2->bp[0] << 1));
+   if (sbp[0] != 2) sbp[0] |= (ST_STRVAL << 2); 
+   stscal_fill_valuep(value_p, sbp, 0);
+   __pop_xstk();
+   __pop_xstk();
+   __pop_itstk();
+   return;
+  }
+ stscal_fill_valuep(value_p, sbp, 0);
+ __pop_xstk();
+ __pop_itstk();
+}
+
+/*
+ * get attribute value
+ */
+static void get_vpi_attrval(struct h_t *hp, p_vpi_value value_p)
+{
+ int32 wtyp;
+ struct expr_t *xp;
+ struct xstk_t *xsp;
+ struct hrec_t *hrp;
+ struct attr_t *attrp;
+
+ hrp = hp->hrec;
+
+ /* only error is stren illegal */
+ if (valp_stren_err(hrp, value_p)) return; 
+
+ /* DBG remove --- */
+ if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__); 
+ /* --- */
+ __push_itstk(hp->hin_itp); 
+ 
+ /* can't fail - internal error if not found */
+ attrp = __find_attrspec(hp);
+
+ xp = attrp->attr_xp;
+ if (value_p->format == vpiObjTypeVal) expr_correct_objtypval(xp, value_p);
+ if (xp == NULL)
+  {
+   /* 32 bit 1 if no expr - i.e. defaults to T */
+   push_xstk_(xsp, WBITS);
+   xsp->ap[0] = 1;
+   xsp->bp[0] = 0; 
+  }
+ else xsp = __eval_xpr(xp);
+
+ if (xp != NULL && xp->is_real) wtyp = N_REAL; else wtyp = N_REG;
+ fill_valuep(value_p, xsp, wtyp, xsp->xslen);
+ __pop_xstk();
+ __pop_itstk();
+}
+
+ 
+/*
+ * correct value_p for vpiObjTypeVal given the net accessing value from
+ *
+ * notice semantics is to really change and fill in the format field
+ */
+static void correct_objtypval(p_vpi_value value_p, word32 ntyp,
+ word32 isavec, word32 is_stren, int32 is_bsel)
+{
+ if (ntyp == N_INT) { value_p->format = vpiIntVal; return; }
+ if (ntyp == N_REAL) { value_p->format = vpiRealVal; return; }
+ if (ntyp == N_TIME) { value_p->format = vpiTimeVal; return; }
+ if (!isavec || is_bsel)
+  {
+   if (is_stren) value_p->format = vpiStrengthVal; 
+   else value_p->format = vpiScalarVal;
+   return;
+  }
+ value_p->format = vpiVectorVal;
+}
+
+/*
+ * correct value_p for vpiObjTypeVal given the net accessing value from
+ *
+ * notice semantics is to really change and fill in the format field
+ */
+static void expr_correct_objtypval(struct expr_t *xp, p_vpi_value value_p)  
+{
+ if (xp->is_real) { value_p->format = vpiRealVal; return; }
+ if (xp->has_sign) { value_p->format = vpiIntVal; return; }
+ if (xp->szu.xclen == 1)
+  {
+   if (xp->x_stren) value_p->format = vpiStrengthVal; 
+   else value_p->format = vpiScalarVal;
+   return;
+  }
+ value_p->format = vpiVectorVal;
+}
+
+/*
+ * fill a value_p record
+ *
+ * only for non strength value, strength filled in other routine
+ * caller loads value and places on stack 
+ *
+ * for reals using non real format, conversion before call 
+ * for strings this uses and must enlarge a vpi get value specific work string
+ * caller must place right itree location on top of itree loc. stack
+ */
+static void fill_valuep(p_vpi_value value_p, struct xstk_t *xsp,
+ word32 vwtyp, int32 vwid)
+{
+ register int32 wi;
+ int32 slen, has_sign, blen;
+ char *chp;
+ int32 sav_sofs, dispfmt;
+ double d1;
+ word64 tim;
+
+ sav_sofs = __cur_sofs;
+ has_sign = FALSE; 
+ switch ((byte) value_p->format) {
+   case vpiBinStrVal:
+    dispfmt = BBIN;
+dispstr_fmt:
+    /* convert real to reg */
+    if (vwtyp == N_REAL) __cnv_stk_fromreal_toreg32(xsp);
+
+    /* AIV 03/12/04 - changed so does not trim to match XL */
+    __regab_disp(xsp->ap, xsp->bp, vwid, dispfmt, FALSE, has_sign);
+    slen = __cur_sofs - sav_sofs;
+    if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
+    value_p->value.str = __wrkvalbufp;
+    strcpy(value_p->value.str, &(__exprline[sav_sofs]));
+    /* exprline reset below */
+    break;
+   case vpiOctStrVal: dispfmt = BOCT; goto dispstr_fmt; 
+   case vpiDecStrVal:
+    if (vwtyp == N_INT) has_sign = TRUE; 
+    dispfmt = BDEC;
+    goto dispstr_fmt;
+   case vpiHexStrVal: dispfmt = BHEX; goto dispstr_fmt;
+
+   case vpiScalarVal:
+    if (vwid > 1)    
+     {
+      __vpi_err(2017, vpiWarning,
+       "vpi_get_delays format type vpiScalarVal for %s vector - low bit only",
+       __to_wtnam2(__wrks1, vwtyp));
+     }
+    if (vwtyp == N_REAL) __cnv_stk_fromreal_toreg32(xsp);
+    /* notice this assume vpi[0,1,z,x] are 0, 1, 2, 3 as stored */
+    value_p->value.scalar = ((xsp->bp[0] & 1L) << 1) | (xsp->ap[0] & 1L);
+    break;
+   case vpiIntVal:
+    if (xsp->xslen > WBITS)    
+     {
+      __vpi_err(2017, vpiWarning,
+       "vpi_get_delays format type vpiIntVal for %s wider than 32 bits - low 32 bits only",
+       __to_wtnam2(__wrks1, vwtyp));
+     }
+    if (vwtyp == N_REAL) __cnv_stk_fromreal_toreg32(xsp);
+    /* notice integer x/z bits are always 0 - LOOKATME - is this right? */
+    value_p->value.integer = (int32) (xsp->ap[0] & ~(xsp->bp[0])); 
+    break;
+   case vpiRealVal:
+    if (vwtyp != N_REAL)
+     {
+      if (vwtyp == N_INT) __cnv_stk_fromreg_toreal(xsp, TRUE);
+      else __cnv_stk_fromreg_toreal(xsp, FALSE);
+     }
+    memcpy(&d1, xsp->ap, sizeof(double));
+    value_p->value.real = d1;
+    break; 
+   case vpiStringVal:
+    /* SJM 07/30/01 - conversion to c string requires removing high pad 0's */
+    blen = __trim1_0val(xsp->ap, xsp->xslen);
+    /* chp malloced */
+    chp = __alloc_vval_to_cstr(xsp->ap, blen, FALSE, FALSE);
+    slen = strlen(chp);
+    if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
+    value_p->value.str = __wrkvalbufp;
+    strcpy(value_p->value.str, chp);
+    /* expr line sofs reset before here */ 
+    __my_free(chp, slen + 1);
+    return;
+   case vpiVectorVal:
+    if (vwtyp == N_REAL) __cnv_stk_fromreal_toreg32(xsp);
+    slen = wlen_(xsp->xslen)*sizeof(struct t_vpi_vecval);
+    if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
+    value_p->value.vector = (struct t_vpi_vecval *) __wrkvalbufp; 
+    for (wi = 0; wi < wlen_(xsp->xslen); wi++)
+     {
+      value_p->value.vector[wi].aval = (int32) xsp->ap[wi]; 
+      value_p->value.vector[wi].bval = (int32) xsp->bp[wi]; 
+     }
+    break;
+   case vpiTimeVal:
+    /* value is vpiSimTime internal ticks */
+    /* SJM 02/03/00 - works because stack word32 - no sign extend */
+    tim = (word64) xsp->ap[0] | (((word64) xsp->ap[1]) << 32); 
+    slen = sizeof(struct t_vpi_time);
+    if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
+    value_p->value.time = (struct t_vpi_time *) __wrkvalbufp;
+    value_p->value.time->type = vpiSimTime;
+    value_p->value.time->high = (int32) ((tim >> 32) & WORDMASK_ULL);
+    value_p->value.time->low = (int32) (tim & WORDMASK_ULL);
+    break;
+   /* strength value never pushed because not expression */
+   default: 
+    __vpi_err(1902, vpiError,
+     "vpi_get_value passed s_vpi_value format value %d illegal",
+     value_p->format);
+  } 
+ __cur_sofs = sav_sofs;
+ __exprline[__cur_sofs] = '\0';
+}
+
+/*
+ * grow the one work string used by get value routine
+ */
+static void wrkval_grow(int32 nsize)
+{
+ int32 osize;
+
+ osize = __wrkval_buflen;
+ if (osize == 0)
+  {
+   if (nsize > RECLEN) __wrkval_buflen = nsize;
+   else __wrkval_buflen = RECLEN;
+   __wrkvalbufp = __my_malloc(__wrkval_buflen);
+   return;
+  }
+ __wrkvalbufp = __my_realloc(__wrkvalbufp, osize, nsize);
+ __wrkval_buflen = nsize;
+}
+
+/*
+ * convert one 
+ * need to also dump initial value
+ */
+static void udp_line_to_str(char *s, struct udp_t *udpp, struct utline_t *utlp)
+{
+ register int32 i;
+ int32 numins;
+ char *chp, s1[RECLEN];
+
+ numins = udpp->numins;
+ strcpy(s, "");
+ for (chp = utlp->tline, i = 0; i < numins; i++, chp++)
+  {    
+   /* the one possible edge */
+   if (utlp->uledinum == i)
+    {
+     /* special wild card types edges are kept as original char */
+     /* 01 and 10 are converted from rise-fall - convert back */
+     if (utlp->utabsel == '0' && *chp == '1') strcat(s, "    r");
+     else if (utlp->utabsel == '1' && *chp == '0') strcat(s, "    f");
+     else if (utlp->utabsel == '*') strcat(s, "    *");
+     else if (utlp->utabsel == 'p') strcat(s, "    p");
+     else if (utlp->utabsel == 'n') strcat(s, "    n");
+     else
+      {
+       sprintf(s1, " (%c%c)", (char) utlp->utabsel, *chp);
+       strcat(s, s1);
+      }
+    }
+   /* various wild cards and states left as input char */
+   else { sprintf(s1, "%5c", *chp); strcat(s, s1); }
+  }
+ if (udpp->utyp != U_COMB)
+  { sprintf(s1, " : %c ", *chp); strcat(s, s1); chp++; }
+ sprintf(s1, " : %c ;", *chp);
+ strcat(s, s1);
+}
+
+/*
+ * VPI PUT VALUE ROUTINES
+ */
+
+/*
+ * assign to an object from value_p possibly forcing or scheduled
+ *
+ * if vpiReturnEvent bit on in flags, return event else nil
+ */
+extern vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, 
+ p_vpi_time time_p, PLI_INT32 flags)
+{
+ int32 ndx, bi, wid, ret_event; 
+ word32 dtyp;
+ struct h_t *hp, *hp2;
+ word64 ticksdel;
+ struct net_t *np;
+ struct xstk_t *xsp;
+ struct net_pin_t *npp;
+ struct hrec_t *hrp;
+
+ /* must reset at start of call to no error */
+ __last_eip = NULL;
+ if (__run_state == SS_COMP)
+  { __still_comp_err("vpi_put_value"); return(NULL); } 
+ hp = (struct h_t *) object;
+ if (!__validate_handle("vpi_put_value", hp)) return(NULL);
+ hrp = hp->hrec;
+ if (__run_state != SS_SIM)
+  {
+   if (hrp->htyp != vpiSpecParam && hrp->htyp != vpiParameter)
+    {
+     __sim_notbegun_err("vpi_put_value of non param");
+     return(NULL);
+    }
+  }
+ /* set extra flag and remove return event bit */
+ ret_event = FALSE;
+ if ((flags & vpiReturnEvent) != 0)
+  { dtyp = (word32) (flags & ~vpiReturnEvent); ret_event = TRUE; }
+ else dtyp = (word32) flags; 
+
+ if (__rosync_slot)
+  {
+   /* put value for future time is legal in ro sync slot */
+   if (!putv_in_future(dtyp, time_p))
+    {
+     __bad_rosync_err("vpi_put_value");
+     return(NULL);
+    }
+  }
+
+ __push_itstk(hp->hin_itp);
+
+ /* check all flag and handle combinations - does not check vpi_time rec */
+ if (!chk_putv_args(dtyp, hp, value_p))
+  {
+   __pop_itstk();
+   return(NULL);
+  }
+
+ switch (dtyp) {
+  case vpiCancelEvent: 
+   /* remove scheduled (must exist) and free dputv record */
+   /* free needed because marking cancelled free does not free guts */
+   /* does nothing if event (or some from vectored table done) */
+   free_putv_sched(hp); 
+   /* user problem to free this handle if needed */
+   break;
+  case vpiAddDriver:
+   if (hrp->htyp == vpiNet) hp2 = add_net_driver(hp);
+   else if (hrp->htyp == vpiNetBit) hp2 = add_netbit_driver(hp);
+   else { __vpi_terr(__FILE__, __LINE__); hp2 = NULL; }
+   __pop_itstk();
+   return((vpiHandle) hp2);
+  case vpiForceFlag:
+   /* force release on wire not on special array form driver or event */
+   ndx = __get_vpinet_index(&np, hp);
+   wid = (ndx == -1) ? np->nwid : 1;
+   /* for vpi wire bit push the bit value will force bit ndx in wire */ 
+   /* always need to push non strength even if strength wire because */
+   /* must add strong not use actual strength */
+   if ((xsp = push_vpi_valuep(value_p, wid, np->ntyp, FALSE)) == NULL)
+    break;
+
+   if (np->ntyp >= NONWIRE_ST) reg_vpi_force(np, xsp->ap, xsp->bp);
+   else
+    {
+     /* SJM 11/14/00 - if wire in tran channel force all wires in it */
+     /* SJM 03/15/01 - can't force all of tran channel - just soft force */
+     /* this tran wire and re-eval tran channel */
+     if (np->ntraux != NULL)
+      {
+       __tran_wire_vpi_force(np, xsp->ap, xsp->bp, ndx);
+       /* SJM 03/15/01 - not sure if vector legal but for scalar -1 illegal */ 
+       if (ndx == -1) __eval_tran_bits(np);
+       else __eval_tran_1bit(np, ndx);
+      }  
+     else wire_vpi_force(np, xsp->ap, xsp->bp, ndx);
+    }
+   __pop_xstk();
+   break;
+  case vpiReleaseFlag:
+   ndx = __get_vpinet_index(&np, hp);
+   if (np->ntyp >= NONWIRE_ST) reg_vpi_release(np);
+   else
+    {
+     if (np->ntraux != NULL)
+      {
+       /* SJM 03/15/01 - did't force all of tran channel - just release */ 
+       /* this tran wire and re-eval tran channel */
+       __tran_wire_vpi_release(np, ndx);
+       /* SJM 02/23/05 - bit objects can be released - not just entire vecs */
+       /* thanks to Greenlight for this fix */
+       if (ndx == -1) __eval_tran_bits(np);
+       else __eval_tran_1bit(np, ndx);
+      }
+     else wire_vpi_release(np, ndx);
+    }
+   /* nothing to pop from expr. stack here */
+   break;
+  case vpiNoDelay:
+   switch (hrp->htyp) {
+    case vpiSysFuncCall:
+     /* special immediate (no schedule) assign case */
+     set_vpisfcall_retval(hp, value_p);
+     break;
+    case vpiSpecParam: case vpiParameter:
+     set_vpiparam_val(hp, value_p);
+     break;
+    case vpiUdpDefn:
+     set_vpiudpdef_ival(hp, value_p);
+     break;
+    case vpiNetDriver: case vpiNetBitDriver: 
+     /* can only putv to reg or wire driver which is always per bit */
+     /* according to LRM - time p can be nil if not needed */
+     /* handle consists of table of per bit handles */
+     npp = hrp->hu.hnpp;
+     np = npp->elnpp.enp;
+     if (npp->npaux == NULL || npp->npaux->nbi1 == -1)
+      {
+       /* nothing pushed on stack if returns nil */
+       if ((xsp = push_vpi_valuep(value_p, np->nwid, np->ntyp, np->n_stren))
+        == NULL) break;
+       immed_vpi_drv_assign(np, npp->obnum, xsp->ap, xsp->bp); 
+       __pop_xstk();
+       break;
+      }
+     bi = npp->npaux->nbi1;
+     if ((xsp = push_vpi_valuep(value_p, 1, np->ntyp, np->n_stren)) == NULL)
+      break;
+     immed_vpibit_drv_assign(np, npp->obnum, bi, xsp->ap, xsp->bp); 
+     __pop_xstk();
+     /* no scheduled event handle to return */
+     break;
+    case vpiNet: case vpiNetBit:
+     /* SJM 07/24/00 - no delay assign just changes net value */
+     ndx = __get_vpinet_index(&np, hp);
+     wid = (ndx == -1) ? np->nwid : 1;
+     /* wire and expected can never be strength here */
+     /* SJM 08/03/00 - this may be soft force of strength value */
+     if ((xsp = push_vpi_valuep(value_p, wid, np->ntyp, np->n_stren)) == NULL)
+      break;
+
+     /* following acc_ routines, no delay set ignored any pending assigns */ 
+     /* SJM 11/14/00 - for soft force of in tran chan (inout), now soft */
+     /* all wires in tran chan */ 
+     /* SJM 03/15/01 - can't force all of tran channel - just soft force */
+     /* this tran wire and re-eval tran channel */
+     if (np->ntraux != NULL)
+      {
+       __tran_exec_putv_wire_softforce(np, xsp->ap, xsp->bp, ndx);
+       /* SJM 03/15/01 - not sure if vector legal but for scalar -1 illegal */ 
+       if (np->n_isavec) __eval_tran_1bit(np, ndx);
+       else __eval_tran_bits(np);
+      }
+     else exec_putv_wire_softforce(np, xsp->ap, xsp->bp, ndx);
+
+     __pop_xstk();
+     break;
+    default:
+     /* all regs and vars here */
+     /* know good - checking in already called putv check routine */
+     /* final case is immedate assign to reg or reg bit */
+     ndx = __get_vpinet_index(&np, hp);
+     wid = (ndx == -1) ? np->nwid : 1;
+     /* can never be wire or strength here */
+     if ((xsp = push_vpi_valuep(value_p, wid, np->ntyp, FALSE)) == NULL)
+      break;
+     /* following acc_ routines, no delay set ignored any pending assigns */ 
+     exec_putv_reg_assign(np, xsp->ap, xsp->bp, ndx);
+     __pop_xstk();
+   }
+   break;
+  case vpiInertialDelay: case vpiTransportDelay: case vpiPureTransportDelay:
+   if (!__vpitime_to_ticks(&ticksdel, time_p, __inst_mod)) return(NULL);
+   if (hrp->htyp != vpiNetDriver && hrp->htyp != vpiNetBitDriver)
+    {
+     /* know this is wire or reg or bit of reg (or var) or net or net bit */
+     ndx = __get_vpinet_index(&np, hp);
+     hp2 = setschd_var_fromvaluep(value_p, np, ndx, ticksdel, dtyp, ret_event);
+    }
+   else
+    {
+     /* wire delayed wire driver assignm (bit or table entire wire) */
+     hp2 = setschd_drvr_fromvaluep(value_p, hp, ticksdel, dtyp, ret_event);
+    }
+
+   /* for release if no error, final step is getting after released value */
+   if (__last_eip == NULL && (flags & ~vpiReturnEvent) == vpiReleaseFlag) 
+    vpi_get_value(object, value_p);
+   __pop_itstk();
+   return((vpiHandle) hp2);
+  default:
+    /* should never get here because of previous checking */
+   __vpi_terr(__FILE__, __LINE__);
+   break;
+  }
+ __pop_itstk();
+ return(NULL);
+}
+
+/*
+ * return T if put value is for future time so is allowed in ro sync slot
+ */
+static int32 putv_in_future(word32 dtyp, p_vpi_time time_p)
+{
+ word64 ticksdel;
+
+ switch (dtyp) {
+  case vpiCancelEvent:
+   /* can always cancel since only events in queue are for future */
+   return(TRUE);
+  case vpiAddDriver: case vpiForceFlag: case vpiReleaseFlag: case vpiNoDelay:
+   /* these always immediate */
+   break;
+  case vpiInertialDelay: case vpiTransportDelay: case vpiPureTransportDelay:
+   /* these ok if delay not 0 */
+   /* LOOKATME - maybe these errors should be caught elsewhere - not stop */
+   if (time_p == NULL) break;
+   if (!__vpitime_to_ticks(&ticksdel, time_p, __inst_mod)) break;
+   if (ticksdel != 0ULL) return(TRUE);  
+   break;
+  default: break;
+ } 
+ return(FALSE);
+}
+
+/*
+ * PUTV CHECKING ROUTINES
+ */
+
+/*
+ * routine to check combination of dtyp (flag with vpiReturnEvent) and object
+ * for put value - emits errors and return F on error
+ *
+ * this requires pushed itree context
+ */
+static int32 chk_putv_args(word32 dtyp, struct h_t *hp, p_vpi_value value_p) 
+{
+ register struct hrec_t *hrp;
+ register struct net_t *np;
+ char s1[RECLEN];
+
+ hrp = hp->hrec;
+ switch (dtyp) {
+  case vpiCancelEvent: 
+   /* this can be reg (also var) or scalar net or bit of vector net */
+   if (hrp->htyp != vpiSchedEvent && hrp->htyp != vpiSchedBitEvent)
+    {
+     __vpi_err(1904, vpiError,
+      "vpi_put_value flag vpiCancelEvent requires vpiSchedEvent or vpiSchedBitEvent - %s passed",
+      __to_vpionam(__wrks1, hrp->htyp));
+     return(FALSE);
+    }
+   break; 
+  case vpiAddDriver:
+   if (hrp->htyp == vpiNetBit)
+    {
+     if (hrp->bith_ndx) np = hrp->hu.hnp;
+     else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+
+     /* DBG remove --- */
+     if (!np->n_isavec) __vpi_terr(__FILE__, __LINE__);
+     /* ---*/
+    }
+   else if (hrp->htyp == vpiNet) np = hrp->hu.hnp;
+   else
+    {
+     __vpi_err(1903, vpiError,
+      "vpi_put_value flag vpiAddDriver object %s illegal not vpiNet or vpiNetBit", 
+      __to_vpionam(__wrks1, hrp->htyp));
+     return(FALSE);
+    }
+   /* DBG remove --- */
+   if (np->ntyp >= NONWIRE_ST) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   if (np->n_gone) goto net_gone;
+   /* can not add driver getpat lhs wire - can only have one driver */
+   if (net_ongetpat_lhs(np))
+    {
+     putv_flag_to_str(s1, dtyp);
+     __vpi_err(1913, vpiError,
+      "vpi_put_value %s flag wire %s part of $getpattern lvalue concatenate illegal - can only have one driver",
+      s1, np->nsym->synam);
+     return(FALSE);
+    }
+   /* SJM 03/23/00 - now because global nodes are XMRs can add */
+   break;
+  case vpiForceFlag: case vpiReleaseFlag:
+   /* can not force/release vpi added driver terminals only nets and bits of */
+   /* force release always immediate */
+   switch (hrp->htyp) {
+    case vpiNetBit:
+     if (hrp->bith_ndx) np = hrp->hu.hnp;
+     else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+
+     if (np->n_gone) goto net_gone;
+     break;
+    case vpiIntegerVar: case vpiTimeVar: case vpiReg: case vpiNet:
+     np = hrp->hu.hnp;
+     if (np->n_gone) goto net_gone;
+     break;
+    case vpiRegBit: case vpiVarSelect:
+     putv_flag_to_str(s1, dtyp);
+     __vpi_err(1914, vpiError,
+      "vpi_put_value illegal %s flag for vpiRegBit/vpiVarSelect - entire variable only", s1);
+     return(FALSE);
+    default:
+     putv_flag_to_str(s1, dtyp);
+     __vpi_err(1915, vpiError,
+      "vpi_put_value %s flag object %s illegal - must be variable or variable bit",
+      s1, __to_vpionam(__wrks1, hrp->htyp));
+     return(FALSE);
+   }
+   break;
+  case vpiNoDelay: case vpiInertialDelay: case vpiTransportDelay:
+  case vpiPureTransportDelay:
+   if (!good_value_p(value_p)) return(FALSE);
+   /* net type specific checking */
+   switch (hrp->htyp) {
+    case vpiReg: case vpiIntegerVar: case vpiTimeVar: case vpiRealVar:
+     np = hrp->hu.hnp;
+     break;
+    case vpiRegBit: case vpiVarSelect: case vpiMemoryWord:
+     /* can assign to (but not force release) reg that is word32 of array */
+     if (hrp->bith_ndx) np = hrp->hu.hnp;
+     else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+     break;
+    case vpiNetDriver:
+     np = hrp->hu.hnpp->elnpp.enp;
+     if (np->n_stren && np->n_isavec)
+      {
+       putv_flag_to_str(s1, dtyp);
+       __vpi_err(2012, vpiWarning,
+        "vpi_put_value %s flag to vpiNetDriver strength vector object width %d will only assign to low bit - use vpiNetBitDriver",
+       s1, np->nwid);
+      }
+     /* LOOKATME - maybe need warning for strength wire non strength format */
+     break;
+    case vpiNetBitDriver:
+     np = hrp->hu.hnpp->elnpp.enp;
+     /* LOOKATME - maybe need warning for strength wire non strength format */
+     break;
+    case vpiSpecParam: case vpiParameter:
+     /* special case immediate assigns only */
+     if (dtyp != vpiNoDelay)
+      {
+nd_nodel:
+       putv_flag_to_str(s1, dtyp);
+       __vpi_err(1844, vpiError,
+        "vpi_put_value to %s object only vpiNoDelay flag allowed - %s illegal",
+        __to_vpionam(__wrks1, hrp->htyp), s1);
+       return(FALSE);
+      }
+     np = hrp->hu.hnp;
+     break;
+    case vpiSysFuncCall:
+     if (dtyp != vpiNoDelay) goto nd_nodel;
+     /* handle is function call expr. */ 
+     return(TRUE);
+    case vpiUdpDefn: 
+     if (dtyp != vpiNoDelay) goto nd_nodel;
+     /* will extract the needed 1 scalar bit form any value_p - no extra */
+     /* checking needed */
+     return(TRUE);
+    case vpiNet: case vpiNetBit:
+     /* SJM 07/24/00 - now supporting soft force (proc assign until next */
+     /* driver change) for put value to wires */
+     np = hrp->hu.hnp;
+     break;
+    default:
+     putv_flag_to_str(s1, dtyp);
+     __vpi_err(1919, vpiError,
+      "vpi_put_value %s flag object %s illegal - must be non wire variable or bit of",
+      s1, __to_vpionam(__wrks1, hrp->htyp));
+     return(FALSE);
+   }
+   if (np->n_gone)
+    {
+net_gone:
+     putv_flag_to_str(s1, dtyp);
+     __vpi_err(1911, vpiError,
+      "vpi_put_value %s to net %s illegal - net removed by gate eater - rerun without +gateeater",
+      s1, np->nsym->synam);
+     return(FALSE);
+    }
+   break;
+  default:
+   __vpi_err(1916, vpiError,
+    "vpi_put_value delay mode flag %u illegal value", dtyp); 
+   return(FALSE);
+ }
+ return(TRUE);
+}
+
+/*
+ * convert a flag constant (with vpiReturnEvent bit removed) to its name
+ */
+static char *putv_flag_to_str(char *s, word32 dtyp)
+{
+ switch (dtyp) {
+  case vpiAddDriver: strcpy(s, "vpiAddDriver"); break;
+  case vpiCancelEvent: strcpy(s, "vpiCancelEvent"); break;
+  case vpiForceFlag: strcpy(s, "vpiForceFlag"); break;
+  case vpiReleaseFlag: strcpy(s, "vpiReleaseFlag"); break;
+  case vpiNoDelay: strcpy(s, "vpiNoDelay"); break;
+  case vpiInertialDelay: strcpy(s, "vpiInertial"); break;
+  case vpiTransportDelay: strcpy(s, "vpiTransportDelay"); break;
+  case vpiPureTransportDelay: strcpy(s, "vpiPureTransportDelay"); break;
+  default: sprintf(s, "unknown (%lu)", dtyp);
+ } 
+ return(s); 
+}
+
+/*
+ * return T if net is on getpattern lhs - can not putv assign to it 
+ */
+static int32 net_ongetpat_lhs(struct net_t *np)
+{
+ register struct net_pin_t *npp;
+ struct conta_t *cap; 
+
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   if (npp->npntyp == NP_CONTA)
+    {
+     cap = npp->elnpp.ecap;
+     if (cap->lhsx->getpatlhs) return(TRUE);
+    }
+  }
+ return(FALSE);
+}
+
+/*
+ * return T if value_p has good value that can be assigned from
+ * also emits error
+ */
+static int32 good_value_p(p_vpi_value value_p)
+{
+ int32 sval, s0, s1; 
+
+ if (value_p->format == vpiSuppressVal || value_p->format == vpiObjTypeVal)
+  {
+   if (value_p->format == vpiSuppressVal) strcpy(__wrks1, "vpiSuppressVal");
+   else strcpy(__wrks1, "vpiObjTypeVal");
+   __vpi_err(1908, vpiError,
+    "vpi_put_value value_p record format %s illegal", __wrks1); 
+   return(FALSE);
+  }  
+ /* strength value is only other one that can be checked */
+ else if (value_p->format != vpiStrengthVal) return(TRUE); 
+
+ /* check strength value */
+ sval = value_p->value.strength->logic; 
+ s0 = value_p->value.strength->s0;
+ s1 = value_p->value.strength->s1;
+ /* LOOKATME - XL seems to allow 0 to 7 but contradicts LRM and include */ 
+ /* strength must be legal vpi_ constant value */
+ if (__map_frvpi_stren(s0) == -1 || __map_frvpi_stren(s1) == -1)
+  goto bad_stren;
+ if (sval == vpiZ) 
+  {
+   /* for z both must be high z */
+   if (s0 != vpiHiZ || s1 != vpiHiZ) goto bad_stren;
+  }
+ else if (sval == vpiX)
+  {
+   /* for x, both can't be hiz - but can be edge of range */
+   if (s0 == vpiHiZ && s1 != vpiHiZ) goto bad_stren;
+  }
+ else if (sval == vpi0 || sval == vpi1)
+  {
+   /* for 0 and 1 both can't be hiz */
+   if (s0 == vpiHiZ && s1 == vpiHiZ) goto bad_stren;
+  } 
+ else goto bad_stren;
+ return(TRUE);
+
+bad_stren:
+ __vpi_err(1924, vpiError,
+  "vpi_put_value passed illegal strength value %d <s1=%d:s0=%d>",
+  sval, s1, s0);
+ return(FALSE);
+}
+
+/*
+ * PUTV DESCHEDULING ROUTINES
+ */
+
+/*
+ * free one putv scheduled - handle is vpiSchedEvent or vpiSchedBitEvent
+ *
+ * this can be either schedule reg putv assign or net driver putv change
+ * or net soft force putv assign
+ *
+ * reg/soft force can be one bit or entire reg but only one scheduled event
+ * always entire reg even if one bit select because vectored
+ *
+ * for wire this can either be bit of vectored (vpiSchedBitEvent) or special
+ * array (one for each bit) or just the one for scalared (vpiSchedEvent)
+ *
+ * notice users responsibility to make sure event not occurred because
+ * storage this handle points to may be gone if user does not check
+ * and calls will core dump
+ */
+static void free_putv_sched(struct h_t *hp)
+{
+ register int32 bi;
+ register i_tev_ndx tevpi; 
+ register struct hrec_t *hrp;
+ i_tev_ndx *evtabi;
+ struct net_t *np;
+ struct tev_t *tevp;
+
+ hrp = hp->hrec;
+ /* does nothing if event completed (or maybe already cancelled) */
+ if (hrp->evnt_done) return;
+
+ /* case 1: vpi Sched Event and not scalar */
+ if (hrp->bith_ndx)
+  {
+   /* table form only for vectored entire wire scheduled */
+   /* cancel each bit event that has not already been canceled or happened */
+   np = hrp->hu.hevrec->evnp;
+   evtabi = hrp->hu.hevrec->evndxtab;
+   for (bi = np->nwid - 1; bi >= 0; bi--)
+    {
+     tevpi = evtabi[bi];
+     if (tevpi == -1 || __tevtab[tevpi].te_cancel) continue;
+     free_netbitdrv_putv_sched(np, bi, hp->hin_itp, tevpi);
+    }
+   /* LOOKATME - maybe should free table here? */
+   hrp->evnt_done = TRUE;
+   return;
+  } 
+ tevpi = hrp->hu.htevpi;
+ tevp = &(__tevtab[tevpi]);
+ np = tevp->tu.teputvp->np;
+
+ /* case 2: reg putv assign (not driver) - can be bit or entire vector */ 
+ /* but in both case only one event */
+ /* SJM 07/25/00 - also free soft force event here */  
+ /* here hp set to done if event canceled */
+ if (np->ntyp >= NONWIRE_ST || tevp->vpi_regwir_putv)
+  {
+   free_regwir_putv_sched(np, hp->hin_itp, tevpi);
+   hrp->evnt_done = TRUE;
+   return;
+  }
+
+ /* case 3: scheduled scalar wire or bit of vectored wire */
+ if (!np->n_isavec) bi = 0; else bi = __tevtab[tevpi].tu.teputvp->nbi;
+ free_netbitdrv_putv_sched(np, bi, hp->hin_itp, tevpi);
+ hrp->evnt_done = TRUE;
+}
+
+/*
+ * free putv scheduled reg or wire soft force event either entire net or bit
+ */
+static void free_regwir_putv_sched(struct net_t *np, struct itree_t *itp,
+ i_tev_ndx tevpi) 
+{
+ register struct dltevlst_t *dlp;
+ struct teputv_t *tepvp;
+
+ tepvp = __tevtab[tevpi].tu.teputvp;
+ dlp = np->regwir_putv_tedlst[itp->itinum];
+ /* find event */
+ for (; dlp != NULL; dlp = dlp->terp)  
+  { if (tevpi == dlp->tevpi) goto found_event; }
+
+found_event:
+ /* link out event - case 1: at front */
+ if (dlp->telp == NULL)
+  {
+   np->regwir_putv_tedlst[itp->itinum] = dlp->terp;
+   if (dlp->terp != NULL) dlp->terp->telp = NULL;
+  }
+ /* case 2: at end and list longer than 1 */
+ else if (dlp->terp == NULL) dlp->telp->terp = NULL;
+ /* case 3: inside - excise out dlp */
+ else { dlp->telp->terp = dlp->terp; dlp->terp->telp = dlp->telp; }
+
+ /* never strength but can be entire vector or 1 bit for reg bit object */
+ if (tepvp->nbi == -1)
+  __my_free((char *) tepvp->putv_wp, 2*wlen_(np->nwid)*WRDBYTES);
+ else __my_free((char *) tepvp->putv_wp, 2*WRDBYTES);
+
+ tepvp->putv_wp = NULL;
+ /* free te putv by linking on free list */
+ tepvp->np =  (struct net_t *) __teputvfreelst;
+ __teputvfreelst = tepvp;
+ /* done with dlp */  
+ dlp->terp = __dltevfreelst;
+ __dltevfreelst = dlp;
+ /* finally empty the event (not really needed) */
+ __tevtab[tevpi].tu.teputvp = NULL;
+ __tevtab[tevpi].te_cancel = TRUE;
+}
+
+/*
+ * free a putv scheduled net driver bit event
+ * scalar possible where index is 0 not -1
+ */
+static void free_netbitdrv_putv_sched(struct net_t *np, int32 bi,
+ struct itree_t *itp, i_tev_ndx tevpi) 
+{
+ register struct dltevlst_t *dlp;
+ int32 evi;
+ struct teputv_t *tepvp;
+ struct vpi_drv_t *vpidrvp;
+
+ evi = np->nwid*itp->itinum + bi;
+ tepvp = __tevtab[tevpi].tu.teputvp;
+ vpidrvp = np->vpi_ndrvs[tepvp->di]; 
+ dlp = vpidrvp->putv_drv_tedlst[evi];
+
+ /* find event */
+ for (; dlp != NULL; dlp = dlp->terp)  
+  { if (tevpi == dlp->tevpi) goto found_event; }
+
+found_event:
+ /* link out event - case 1: at front */
+ if (dlp->telp == NULL)
+  {
+   vpidrvp->putv_drv_tedlst[evi] = dlp->terp;
+   if (dlp->terp != NULL) dlp->terp->telp = NULL;
+  }
+ /* case 2: at end and list longer than 1 */
+ else if (dlp->terp == NULL) dlp->telp->terp = NULL;
+ /* case 3: inside - excise out dlp */
+ else { dlp->telp->terp = dlp->terp; dlp->terp->telp = dlp->telp; }
+
+ /* always 1 bit */
+ __my_free((char *) tepvp->putv_wp, 2*WRDBYTES);
+
+ tepvp->putv_wp = NULL;
+ /* free te putv by linking on free list */
+ tepvp->np =  (struct net_t *) __teputvfreelst;
+ __teputvfreelst = tepvp;
+ /* done with dlp */  
+ dlp->terp = __dltevfreelst;
+ __dltevfreelst = dlp;
+ /* finally empty the event (not really needed) */
+ __tevtab[tevpi].tu.teputvp = NULL;
+ __tevtab[tevpi].te_cancel = TRUE;
+}
+
+/*
+ * ROUTINES TO DYNAMICALLY ADD VPI DRIVER (TERMINAL) TO NET 
+ */
+
+/*
+ * dynamically add a vpi put value record for entire net 
+ * construct driver object
+ *
+ * vpi put value driver and scheduled record allocated when driver terminal
+ * added using vpi_put_value with flag vpiAddDriver (this routine does it)
+ *
+ * only needed for vpi_ since only one possibly added tf_ driver can be added
+ * during prep because only works across systf arguments and must be registered
+ * in available at compile time fixed table
+ *
+ * added driver always initialized to hiz
+ *
+ * called with current itree loc on itree stack
+ * LOOKATME - maybe need error for "vectored" wire 
+ */
+static struct h_t *add_net_driver(struct h_t *hp) 
+{
+ register int32 di;
+ register struct vpi_drv_t *vpidrvp;     
+ int32 drvi, osize, nsize;
+ struct mod_t *mdp;
+ struct net_t *np;
+ struct net_pin_t *npp;
+ struct xstk_t *xsp;
+ struct h_t *hp2;
+
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ np = hp->hrec->hu.hnp;
+ push_xstk_(xsp, np->nwid);
+ /* build and initialize the added driver - maybe just set some active bits */
+ /* case 1: no drivers */
+ if (np->vpi_ndrvs == NULL)
+  {
+   vpidrvp = alloc_vpidrv(np, mdp->flatinum);
+   /* allocate driving values and initialize to z */
+   putv_drvwp_allocinit(mdp, np, vpidrvp, TRUE);
+
+   /* build the table will nil ptr fence one past end */
+   np->vpi_ndrvs =
+    (struct vpi_drv_t **) __my_malloc(2*sizeof(struct vpi_drv_t *));
+   np->vpi_ndrvs[0] = vpidrvp;
+   np->vpi_ndrvs[1] = NULL;
+   drvi = 0;
+   /* since new, know will be unused */
+   __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
+   goto set_vec_used;
+  }
+ /* case 2: some drivers and one has all vector bits for cur. itree unused */
+ for (di = 0;; di++)
+  {
+   if ((vpidrvp = np->vpi_ndrvs[di]) == NULL) break;
+
+   __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
+   if (vval_is0_(xsp->ap, np->nwid)) { drvi = di; goto set_vec_used; }
+  }
+ /* case 3: need to add new (after first) driver in pos. di */
+ if (di >= MAXNUMPORTS)
+  {
+   char s1[RECLEN];
+
+   strcpy(s1, np->nsym->synam);
+   __pv_terr(326,
+    "INTERNAL FATAL - more than %d vpi wire drivers added to %s - contact Pragmatic C",
+     MAXNUMPORTS, s1);
+  }
+ /* alloc and fill new every inst. and every bit driver - marks inst. used */
+ vpidrvp = alloc_vpidrv(np, mdp->flatinum);
+ /* allocate driving values and initialize to z */
+ putv_drvwp_allocinit(mdp, np, vpidrvp, TRUE);
+ 
+ /* realloc to increase size of table - set new driver and end fence */
+ osize = (di + 1)*sizeof(struct vpi_drv_t *);
+ nsize = osize + sizeof(struct vpi_drv_t *); 
+ np->vpi_ndrvs = (struct vpi_drv_t **)
+  __my_realloc((char *) np->vpi_ndrvs, osize, nsize);
+ np->vpi_ndrvs[di] = vpidrvp;
+ np->vpi_ndrvs[di + 1] = NULL;
+ drvi = di;
+ __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
+
+set_vec_used:
+ /* know instance's has driver value loaded */
+ one_allbits_(xsp->ap, np->nwid);
+ __st_perinst_val(vpidrvp->vpi_hasdrv, np->nwid, xsp->ap, xsp->bp);
+ __pop_xstk(); 
+
+ /* convert to fi>1 (even if only the new vpi driver) */   
+ if (!np->n_multfi) chg_net_to_multfi(np, mdp);
+
+
+ /* build and add the npp */
+ __cur_npnum = 0;
+ __cur_npnp = np;
+ npp = __alloc_npin(NP_VPIPUTV, -1, -1);
+ /* object number for vpi driver is index among many possible added drivers */ 
+ npp->obnum = drvi;
+ npp->npnxt = np->ndrvs;
+ np->ndrvs = npp;
+ /* DBG remove --- */
+ if (__debug_flg)
+  {
+   __dbg_msg(
+    ".. mod %s adding %s wire vpi_put_value driver to front\n",
+    mdp->msym->synam, np->nsym->synam);
+  }
+ /* --- */
+
+ /* build the driver handle */
+ hp2 = (struct h_t *) __mk_handle(vpiNetDriver, (void *) npp, hp->hin_itp,
+  NULL);
+ return(hp2);
+}
+
+/*
+ * allocate and initialize a vpi entire wire driver 
+ */
+static struct vpi_drv_t *alloc_vpidrv(struct net_t *np, int32 insts)
+{
+ int32 nbytes;
+ struct vpi_drv_t *vpidrvp;
+
+ vpidrvp = (struct vpi_drv_t *) __my_malloc(sizeof(struct vpi_drv_t));
+ nbytes = __get_pcku_chars(np->nwid, insts);
+ vpidrvp->vpi_hasdrv.wp = (word32 *) __my_malloc(nbytes);
+ /* to start no insts or bits have drivers */
+ memset(vpidrvp->vpi_hasdrv.bp, 0, nbytes); 
+
+ /* need scheduled list for every bit of every inst */
+ nbytes = insts*np->nwid*sizeof(struct dltevlst_t *);
+ vpidrvp->putv_drv_tedlst = (struct dltevlst_t **) __my_malloc(nbytes);
+ memset(vpidrvp->putv_drv_tedlst, 0, nbytes); 
+ return(vpidrvp);
+}
+
+/*
+ * dynamically add a vpi put value record for one vpi net bit
+ * construct driver object
+ *
+ * vpi put value driver and scheduled record allocated when driver terminal
+ * added using vpi_put_value with flag vpiAddDriver (this routine does it)
+ *
+ * only needed for vpi_ since only one possibly added tf_ driver can be added
+ * during prep because only works across systf arguments and must be registered
+ * in available at compile time fixed table
+ *
+ * even for bit case always add entire wire driver
+ *
+ * added driver always initialized to hiz
+ *
+ * called with current itree loc on itree stack
+ * LOOKATME - maybe need error for "vectored" wire 
+ */
+static struct h_t *add_netbit_driver(struct h_t *hp) 
+{
+ register int32 di;
+ word32 val;
+ int32 bi, drvi, osize, nsize;
+ struct mod_t *mdp;
+ struct net_t *np;
+ struct net_pin_t *npp;
+ struct vpi_drv_t *vpidrvp;
+ struct xstk_t *xsp;
+ struct h_t *hp2;
+
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ bi = get_vpibit_index(&np, hp);
+ push_xstk_(xsp, np->nwid);
+ /* build and initialize the added driver - maybe just set some active bits */
+ /* case 1: no drivers */
+ if (np->vpi_ndrvs == NULL)
+  {
+   vpidrvp = alloc_vpidrv(np, mdp->flatinum);
+   /* allocate driving values and initialize to z */
+   putv_drvwp_allocinit(mdp, np, vpidrvp, TRUE);
+
+   /* build the table will nil ptr fence one past end */
+   np->vpi_ndrvs =
+    (struct vpi_drv_t **) __my_malloc(2*sizeof(struct vpi_drv_t *));
+   np->vpi_ndrvs[0] = vpidrvp;
+   np->vpi_ndrvs[1] = NULL;
+   drvi = 0;
+   __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
+   goto set_bit_used;
+  }
+ /* case 2: some drivers and one has all vector bits for cur. itree unused */
+ for (di = 0;; di++)
+  {
+   if ((vpidrvp = np->vpi_ndrvs[di]) == NULL) break;
+   /* b part unused */
+   __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
+   val = rhsbsel_(xsp->ap, bi);
+   if (val == 0) { drvi = di; goto set_bit_used; }
+  } 
+ /* case 3: need to add new (after first) driver in pos. di */
+ if (di >= MAXNUMPORTS)
+  {
+   char s1[RECLEN];
+
+   strcpy(s1, np->nsym->synam);
+   __pv_terr(326,
+    "INTERNAL FATAL - more than %d vpi wire drivers added to %s - contact Pragmatic C",
+     MAXNUMPORTS, s1);
+  }
+ /* alloc and fill new every inst. and every bit driver - marks inst. used */
+ vpidrvp = alloc_vpidrv(np, mdp->flatinum);
+ /* allocate driving values and initialize to z */
+ putv_drvwp_allocinit(mdp, np, vpidrvp, TRUE);
+ 
+ /* realloc to increase size of table - set new driver and end fence */
+ osize = (di + 1)*sizeof(struct vpi_drv_t *);
+ nsize = osize + sizeof(struct vpi_drv_t *); 
+ np->vpi_ndrvs = (struct vpi_drv_t **)
+  __my_realloc((char *) np->vpi_ndrvs, osize, nsize);
+ np->vpi_ndrvs[di] = vpidrvp;
+ np->vpi_ndrvs[di + 1] = NULL;
+ drvi = di;
+
+set_bit_used:
+ /* set the one inst-bit that is used */
+ val = 1;
+ __lhsbsel(xsp->ap, bi, val);
+ __st_perinst_val(vpidrvp->vpi_hasdrv, np->nwid, xsp->ap, xsp->bp);
+ __pop_xstk(); 
+
+ /* convert to fi>1 (even if only the new vpi driver) */   
+ if (!np->n_multfi) chg_net_to_multfi(np, mdp);
+
+ /* build and add the npp */
+ __cur_npnum = 0;
+ __cur_npnp = np;
+ npp = __alloc_npin(NP_VPIPUTV, bi, bi);
+ 
+ /* object number for vpi driver is index among many possible added drivers */ 
+ npp->obnum = drvi;
+ npp->npnxt = np->ndrvs;
+ np->ndrvs = npp;
+ /* DBG remove --- */
+ if (__debug_flg)
+  {
+   __dbg_msg(
+    ".. mod %s adding %s[%d] wire bit vpi_put_value driver to front\n",
+    mdp->msym->synam, np->nsym->synam, bi);
+  }
+ /* --- */
+
+ /* build the driver handle - always bith ndx form */
+ hp2 = (struct h_t *) __mk_handle(vpiNetBitDriver, (void *) npp, hp->hin_itp,
+  NULL);
+ hp2->hrec->hi = bi;
+ return(hp2);
+}
+
+/*
+ * return T if instance itp of net np has vpi_ putv drivers for npp bits
+ *
+ * npp (NP VPIPUTV only) either entire wire or one bit
+ * this needs instance to check to be on top of itree stack
+ */
+extern int32 __has_vpi_driver(struct net_t *np, struct net_pin_t *npp)
+{
+ int32 rv;
+ word32 val;
+ struct vpi_drv_t *vpidrvp;     
+ struct xstk_t *xsp;
+
+ vpidrvp = np->vpi_ndrvs[npp->obnum];
+ if ((vpidrvp = np->vpi_ndrvs[npp->obnum]) == NULL) return(FALSE);
+ rv = FALSE;
+ push_xstk_(xsp, np->nwid);
+ __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
+ if (npp->npaux == NULL || npp->npaux->nbi1 == -1) 
+  {
+   /* all bits must be one */
+   if (__vval_is1(xsp->ap, np->nwid)) rv = TRUE;
+   goto done;
+  }
+ /* bit select case */
+ val = rhsbsel_(xsp->ap, npp->npaux->nbi1);
+ if (val == 1) rv = TRUE;
+done:
+ __pop_xstk();
+ return(rv);
+}
+
+/*
+ * reinitialize putvrec drivers for net
+ * called when resetting from prep code
+ *
+ * there may be multiple so must loop thru until hitting ending fence
+ *
+ * leave the drivers (npps) and has drv bits sets but reset driving to z
+ * and free vents
+ */
+extern void __reinit_netdrvr_putvrec(struct net_t *np, struct mod_t *mdp)
+{
+ register int32 bi, di, ii;
+ register struct dltevlst_t *dlp, *dlp2, *last_dlp;
+ struct vpi_drv_t *vpidrvp;
+
+ for (di = 0;; di++)
+  {
+   if ((vpidrvp = np->vpi_ndrvs[di]) == NULL) break;
+
+   /* DBG remove -- */
+   if (vpidrvp->vpi_drvwp.wp == NULL) __arg_terr(__FILE__, __LINE__);
+   /* --- */ 
+   putv_drvwp_allocinit(mdp, np, vpidrvp, FALSE);
+
+   /* events will be in event queue and already freed */ 
+   /* find last and link dlp's onto it */
+   for (ii = 0; ii < mdp->flatinum; ii++) 
+    {
+     /* ?? LOOKATME - this was low to high */
+     for (bi = np->nwid - 1; bi >= 0; bi--)
+      {
+       if ((dlp = vpidrvp->putv_drv_tedlst[ii*np->nwid + bi]) == NULL)
+        continue;
+       last_dlp = NULL;
+       for (dlp2 = dlp; dlp2 != NULL; dlp2 = dlp2->terp) last_dlp = dlp2;
+       /* SJM 08/02/01 - add if too keep lint happy */
+       if (last_dlp != NULL) last_dlp->terp = __dltevfreelst; 
+       __dltevfreelst = dlp;
+       vpidrvp->putv_drv_tedlst[ii*np->nwid + bi] = NULL; 
+      }
+    }
+  }
+}
+
+/*
+ * initialize and maybe allocate a a putv driver (only for wires)
+ *
+ * notice drivers are always one bit but need one per inst
+ */
+static void putv_drvwp_allocinit(struct mod_t *mdp, struct net_t *np,
+ struct vpi_drv_t *vpidrvp, int32 nd_alloc)
+{
+ register int32 ii;
+ int32 nbytes;
+ byte *sbp;
+ struct xstk_t *xsp;
+
+ /* for wire need drivers */
+ if (np->n_stren)
+  {
+   if (nd_alloc)
+    sbp = vpidrvp->vpi_drvwp.bp = (byte *) __my_malloc(mdp->flatinum*np->nwid);
+   else sbp = vpidrvp->vpi_drvwp.bp;
+   set_byteval_(sbp, mdp->flatinum*np->nwid, ST_HIZ);
+  }
+ else 
+  {
+   /* this is per inst. packed one bit non strength driver value */
+   if (nd_alloc)
+    {
+     nbytes = __get_pcku_chars(np->nwid, mdp->flatinum);
+     vpidrvp->vpi_drvwp.wp = (word32 *) __my_malloc(nbytes);
+    } 
+   push_xstk_(xsp, np->nwid);
+   zero_allbits_(xsp->ap, np->nwid);
+   one_allbits_(xsp->bp, np->nwid);
+   __push_wrkitstk(mdp, 0);
+   for (ii = 0; ii < mdp->flatinum; ii++) 
+    {
+     __inst_ptr->itinum = ii;
+     __inum = ii;
+     /* do not need mod con table here */
+     __st_perinst_val(vpidrvp->vpi_drvwp, np->nwid, xsp->ap, xsp->bp);
+    }
+   __pop_wrkitstk();
+   __pop_xstk();
+  }    
+}
+
+/*
+ * change a wire from fi==1 to multi-fi - reorganize nl data structure
+ *
+ * find and set x_multfi bits on driving expressions
+ * notice even if no drivers so really only 1 driver, vpi drivers always fi>1
+ * i.e. will never see NP_VPIPUTV in old npp loop here
+ */
+static void chg_net_to_multfi(struct net_t *np, struct mod_t *mdp)
+{
+ register struct net_pin_t *npp;
+ register int32 ii, bi;
+ int32 lhslen;
+ byte *sbp, *sbp2;
+ struct gate_t *gp;
+ struct conta_t *cap, *pbcap;
+ struct mod_pin_t *mpp;
+ struct xstk_t *xsp;
+ struct inst_t *ip;
+ struct expr_t *lhsxp;
+ struct tfrec_t *tfrp;
+ struct tfarg_t *tfap;
+ struct mod_t *mdp2;
+
+ np->n_multfi = TRUE;
+ for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
+  {
+   switch ((byte) npp->npntyp) {
+    case NP_GATE:
+     gp = npp->elnpp.egp;
+     /* DBG remove --- 
+     if (gp->gpins[0]->x_multfi) __vpi_terr(__FILE__, __LINE__);
+     --- */
+     gp->gpins[0]->x_multfi = TRUE;
+     /* set gchg assign routine to std unaccelerated since fi>1 now */
+     __vpi_set_chg_proc(gp);
+     /* must make sure all gate change events not yet processed use std */
+     if (gp->schd_tevs != NULL)
+      {
+       for (ii = 0; ii < mdp->flatinum; ii++)
+        {
+         if (gp->schd_tevs[ii] != -1)
+          __tevtab[gp->schd_tevs[ii]].gev_acc = FALSE;
+        }
+      }
+     break;
+    case NP_CONTA:
+     cap = npp->elnpp.ecap;
+     /* DBG remove --- 
+     if (cap->lhsx->x_multfi) __vpi_terr(__FILE__, __LINE__);
+     --- */
+     /* SJM 09/20/02 - per bit conta needs to process contained conta */
+     /* and if any bits fi>1 all are */
+     if (cap->ca_pb_sim)
+      {
+       /* must mark all per bit lhs expr, as per bit if any are */  
+       cap->lhsx->x_multfi = TRUE;
+       for (bi = 0; bi < cap->lhsx->szu.xclen; bi++)
+        {
+         pbcap = &(cap->pbcau.pbcaps[npp->pbi]);
+         pbcap->lhsx->x_multfi = TRUE; 
+         if (cap->ca_delrep != DT_NONE) break;
+
+         /* DBG remove -- */ 
+         if (pbcap->lhsx->szu.xclen != 1) __misc_terr(__FILE__, __LINE__);
+         /* --- */
+         __allocinit_perival(&pbcap->ca_drv_wp, mdp->flatinum, 1, TRUE);
+         /* set value from rhs conta value - now fi>1 */
+         for (ii = 0; ii < mdp->flatinum; ii++)
+          {
+           __push_itstk(mdp->moditps[ii]);
+           xsp = __eval_xpr(pbcap->rhsx);
+           __st_perinst_val(pbcap->ca_drv_wp, 1, xsp->ap, xsp->bp);
+           __pop_xstk();
+           __pop_itstk();
+          }
+        }
+      }
+     else
+      {
+       cap->lhsx->x_multfi = TRUE;
+       /* if has delay, already using ca_drv_wp */
+       if (cap->ca_delrep != DT_NONE) break;
+
+       /* but if no delay must alloc and set schd/drv values */
+       lhslen = cap->lhsx->szu.xclen;
+       __allocinit_perival(&cap->ca_drv_wp, mdp->flatinum, lhslen, TRUE);
+       /* set value from rhs conta value - now fi>1 */
+       for (ii = 0; ii < mdp->flatinum; ii++)
+        {
+         __push_itstk(mdp->moditps[ii]);
+         xsp = __eval_xpr(cap->rhsx);
+         if (xsp->xslen != lhslen)
+          {
+           if (xsp->xslen < lhslen)
+            {
+             /* SJM 05/10/04 - if widening and signed, must sign extend */
+             if (cap->rhsx->has_sign) __sgn_xtnd_widen(xsp, lhslen);
+             else __sizchg_widen(xsp, lhslen);
+            }
+           else __sizchgxs(xsp, lhslen);
+          }
+
+         __st_perinst_val(cap->ca_drv_wp, lhslen, xsp->ap, xsp->bp);
+         __pop_xstk();
+         __pop_itstk();
+        }
+      }
+     break;
+    case NP_ICONN:
+     /* SJM 04/21/00 - for non local drivers, must move use right itree loc */
+     if (npp->npproctyp != NP_PROC_INMOD)
+      {
+       /* SJM 04/17/03 - if XMR path does not match do not change here */
+       if (__move_to_npprefloc(npp))
+        {
+         mdp2 = __inst_ptr->itip->imsym->el.emdp;
+         ip = &(mdp2->minsts[npp->elnpp.eii]);
+         lhsxp = ip->ipins[npp->obnum];  
+         lhsxp->x_multfi = TRUE;
+         /* need port for setting std assign routine */
+         mpp = &(ip->imsym->el.emdp->mpins[npp->obnum]);
+         __vpi_set_upiconnport_proc(mpp);
+         __pop_itstk();
+        }
+       break;
+      }
+
+     /* assignment from down to up iconn - maybe >1 inst must no accelerate */
+     /* LOOKATME - maybe could find some accelerating cases but xmr prob? */ 
+     ip = &(mdp->minsts[npp->elnpp.eii]);
+     lhsxp = ip->ipins[npp->obnum];  
+     /* DBG remove --- SJM 03/07/99 
+     if (lhsxp->x_multfi) __vpi_terr(__FILE__, __LINE__);
+     --- */
+     lhsxp->x_multfi = TRUE;
+     /* need port for setting std assign routine */
+     mpp = &(ip->imsym->el.emdp->mpins[npp->obnum]);
+     __vpi_set_upiconnport_proc(mpp);
+     break;
+    case NP_MDPRT:
+     /* the elnpp is module, but already have it */
+     mpp = &(mdp->mpins[npp->obnum]);
+     /* DBG remove --- SJM 10/18/99 
+     if (mpp->mpref->x_multfi) __vpi_terr(__FILE__, __LINE__);
+     --- */
+     mpp->mpref->x_multfi = TRUE;
+     if (mpp->has_scalar_mpps)
+      {
+       for (bi = 0; bi < mpp->mpwide; bi++)
+        {
+         __vpi_set_downtomdport_proc(&(mpp->pbmpps[bi]), np);
+        }
+      }
+     else __vpi_set_downtomdport_proc(mpp, np);
+     break;
+    case NP_TFRWARG:
+     /* if this was previously fi==1, must change and alloc drv_wp */
+     tfrp = npp->elnpp.etfrp;
+     tfap = &(tfrp->tfargs[npp->obnum]);
+     lhsxp = tfap->arg.axp;
+     /* DBG remove ---
+     if (lhsxp->x_multfi) __vpi_terr(__FILE__, __LINE__);
+     --- */
+     /* DBG remove --- */
+     if (tfap->tfdrv_wp.wp != NULL) __vpi_terr(__FILE__, __LINE__);
+     /* --- */ 
+     lhslen = lhsxp->szu.xclen;
+     lhsxp->x_multfi = TRUE;
+     __alloc_tfdrv_wp(tfap, lhsxp, mdp);
+     /* notice value from fi==1 case value of lhs expr - driver is hidden */
+     /* must do this for every instance */
+     for (ii = 0; ii < mdp->flatinum; ii++)
+      {
+       __push_itstk(mdp->moditps[ii]);
+
+       xsp = __eval_xpr(lhsxp);
+       /* here because lhs is width self determing should never differ */
+       /* DBG remove */
+       if (lhslen != xsp->xslen) __vpi_terr(__FILE__, __LINE__);
+       /* -- */ 
+       /* tf can drive strength */
+       if (np->n_stren)
+        __st_perinst_val(tfap->tfdrv_wp, lhslen, xsp->ap, xsp->bp);
+       else
+        { 
+         sbp = (byte *) xsp->ap;
+         sbp2 = tfap->tfdrv_wp.bp;
+         sbp2 = &(sbp2[lhslen*__inum]);
+         memcpy(sbp2, sbp, lhslen);
+        }
+       __pop_xstk();  
+       __pop_itstk();
+      }
+     break;
+    default: __vpi_terr(__FILE__, __LINE__);
+   }  
+  }
+}
+
+/*
+ * PUTV WORK ROUTINES
+ */
+
+/*
+ * get index for either net or bit of net   
+ */
+extern int32 __get_vpinet_index(struct net_t **pnp, struct h_t *hp)
+{
+ register struct hrec_t *hrp;
+ register int32 ndx;
+
+ hrp = hp->hrec;
+ /* can vpiVarSelect occur here? */
+ switch (hrp->htyp) {
+  case vpiRegBit: case vpiNetBit:
+  case vpiMemoryWord: case vpiVarSelect:
+   if (hrp->bith_ndx) { ndx = hrp->hi; *pnp = hrp->hu.hnp; }
+   else
+    {
+     *pnp = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+     __push_itstk(hp->hin_itp);
+     ndx = __comp_ndx(hrp->hu.hxp->lu.sy->el.enp, hrp->hu.hxp->ru.x);
+     __pop_itstk();
+     *pnp = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+    }
+   return(ndx);
+  default: 
+   ndx = -1;
+   *pnp = hrp->hu.hnp;
+ }
+ return(ndx);
+}
+
+/*
+ * get vpiNetBit or vpiRegBit index and net for cases where know Bit handle
+ *
+ * LOOKATME - maybe expr. form should be illegal here 
+ */
+static int32 get_vpibit_index(struct net_t **pnp, struct h_t *hp)
+{
+ register struct hrec_t *hrp;
+ register int32 ndx;
+
+ hrp = hp->hrec;
+ if (hrp->bith_ndx)
+  { ndx = hrp->hi; *pnp = hrp->hu.hnp; return(ndx); }
+
+
+ __push_itstk(hp->hin_itp);
+ ndx = __comp_ndx(hrp->hu.hxp->lu.sy->el.enp, hrp->hu.hxp->ru.x);
+ __pop_itstk();
+ *pnp = hrp->hu.hxp->lu.x->lu.sy->el.enp;
+ return(ndx);
+}
+
+/*
+ * convert a value_p value for a variable (handle) into an a/b value
+ * on top of the expr stack
+ * returns nil on bad value that can not be converted
+ *
+ * value on stack matches net (handle) in both type and width with zero fill
+ * also matches strength with strong added if needed
+ * this must run in itree location of handle in case value is time
+ *
+ * wnen strength need cast to byte ptr then assigns to low bit of it
+ */
+static struct xstk_t *push_vpi_valuep(p_vpi_value value_p, int32 vwid,
+ word32 vntyp, int32 vstren)
+{
+ register int32 wi;
+ byte *sbp;
+ word32 wval, wlen, ubits;
+ int32 scanfmt, is_signed, s0val, s1val, i1;
+ double d1;
+ word64 timval;
+ struct xstk_t *xsp;
+
+ is_signed = FALSE;
+ xsp = NULL;
+ switch ((byte) value_p->format) {
+   case vpiStringVal:
+    /* SJM 07/11/01 - put value of c style string needs to be supported */
+    xsp = __cstr_to_vval(value_p->value.str);
+    /* SJM 07/30/01 - must change to vwid (net's width) - trunc or 0 fill */
+    /* SJM 05/10/04 - vpi strings can't be signed */
+    if (vwid != xsp->xslen) __sizchgxs(xsp, vwid);
+    break;
+   case vpiBinStrVal:
+    scanfmt = 'b';
+    strcpy(__wrks1, "vpiBinStrVal");
+do_xtract:
+    /* extract value_p string into numeric value on tos */
+    xsp = __putdstr_to_val(value_p->value.str, vwid, vwid, scanfmt);
+    if (xsp == NULL)
+     {
+      __vpi_err(1917, vpiError,
+       "vpi_put_value value_p record format %s value illegal", __wrks1); 
+      return(NULL); 
+     }
+    /* if type of net is real must convert to double */
+    if (vntyp == N_REAL)
+     {  
+      d1 = __cnvt_stk_to_real(xsp, is_signed);
+      __pop_xstk();
+      push_xstk_(xsp, WBITS);
+      memcpy(xsp->ap, &d1, sizeof(double)); 
+      return(xsp);
+     }   
+    break;
+   case vpiOctStrVal:
+    scanfmt = 'o';
+    strcpy(__wrks1, "vpiOctStrVal");
+    goto do_xtract; 
+   case vpiDecStrVal:
+    scanfmt = 'd';
+    strcpy(__wrks1, "vpiDecStrVal");
+    if (vwid <= WBITS) is_signed = TRUE;
+    goto do_xtract; 
+   case vpiHexStrVal:
+    scanfmt = 'h';
+    strcpy(__wrks1, "vpiHexStrVal");
+    goto do_xtract; 
+
+   case vpiScalarVal:
+    push_xstk_(xsp, vwid);
+    zero_allbits_(xsp->ap, vwid);
+    zero_allbits_(xsp->bp, vwid);
+    wval = (word32) value_p->value.scalar;
+    if (!chk_vpi_logicval(wval))
+     {  
+      __vpi_err(1921, vpiError,
+       "vpi_put_value vpiScalarVal passed illegal value %d", wval);
+      __pop_xstk();
+      return(NULL);
+     }
+    /* BEWARE this assume vpi[0,1,z,x] are 0, 1, 2, 3 as stored */
+    xsp->ap[0] = (wval & 1L);
+    xsp->bp[0] = (wval >> 1) & 1L;
+    /* it is ok to convert scalar to real which is putved */
+    if (vntyp == N_REAL)
+     {
+      d1 = __cnvt_stk_to_real(xsp, FALSE);
+      __pop_xstk();
+      push_xstk_(xsp, WBITS);
+      memcpy(xsp->ap, &d1, sizeof(double)); 
+      return(xsp);
+     }
+    break;
+   case vpiIntVal:
+    push_xstk_(xsp, vwid);
+    zero_allbits_(xsp->ap, vwid);
+    zero_allbits_(xsp->bp, vwid);
+    /* know this must be good */
+    xsp->ap[0] = (word32) value_p->value.integer;
+    if (vntyp == N_REAL) 
+     {
+      d1 = __cnvt_stk_to_real(xsp, is_signed);
+      __pop_xstk();
+      push_xstk_(xsp, WBITS);
+      memcpy(xsp->ap, &d1, sizeof(double)); 
+      return(xsp);
+     }  
+    break;
+   case vpiRealVal:
+    /* destination not real */
+    d1 = value_p->value.real;
+    if (vntyp != N_REAL)
+     {  
+      if (vntyp == N_INT) 
+       {
+        i1 = (int32) d1;
+        push_xstk_(xsp, vwid);
+        xsp->ap[0] = (word32) i1;
+        xsp->bp[0] = 0L;
+        break;
+       }
+      if (!__real_to_v64tim(&timval, d1))
+       {
+        __vpi_err(2016, vpiWarning,  
+         "precision lost in converting real %g to 64 bit unsigned", d1);
+       }
+      push_xstk_(xsp, 64);
+      xsp->ap[0] = (word32) (timval & WORDMASK_ULL);
+      xsp->ap[1] = (word32) ((timval >> 32) & WORDMASK_ULL);  
+      xsp->bp[0] = xsp->bp[1] = 0L;
+      /* SJM 05/10/04 - time can't be signed */
+      if (vwid != 64) __sizchgxs(xsp, vwid);
+      break;
+     }
+    /* value real and pushing real */
+    push_xstk_(xsp, WBITS);
+    memcpy(xsp->ap, &d1, sizeof(double)); 
+    return(xsp);
+   case vpiStrengthVal:
+    /* know value_p is 1 bit strength and checked in chk putv already */
+    wval = (word32) value_p->value.strength->logic;
+    s0val = __map_frvpi_stren(value_p->value.strength->s0);
+    s1val = __map_frvpi_stren(value_p->value.strength->s1);
+    /* if value is strength, but putting to non strength use logic only */
+    if (!vstren)
+     {
+      /* this forces 8 bytes */
+      push_xstk_(xsp, 1);
+      xsp->ap[0] = wval; 
+      xsp->bp[0] = 0L;
+     }
+    else
+     {
+      /* FIXME - should allow array of strengths here too */
+      /* this forces 8 bytes */
+      push_xstk_(xsp, 4);
+      sbp = (byte *) xsp->ap;
+      wval |= (((((byte) s0val) & 7L) << 5) | ((((byte) s1val) & 7L) << 2));
+      sbp[0] = (byte) wval;
+     }
+    return(xsp);
+   case vpiTimeVal:
+    if (!__vpitime_to_ticks(&timval, value_p->value.time, __inst_mod)) break;
+
+    push_xstk_(xsp, vwid);
+    xsp->bp[0] = xsp->bp[1] = 0L;
+    xsp->ap[0] = (word32) (timval & WORDMASK_ULL);
+    xsp->ap[1] = (word32) ((timval >> 32) & WORDMASK_ULL);
+    break;
+   case vpiVectorVal:
+    push_xstk_(xsp, vwid);
+    wlen = wlen_(vwid);
+    ubits = ubits_(vwid);
+    for (wi = 0; wi < (int32) (wlen - 1); wi++)
+     {
+      xsp->ap[wi] = (word32) value_p->value.vector[wi].aval; 
+      xsp->bp[wi] = (word32) value_p->value.vector[wi].bval; 
+     }
+    /* LOOKATME - P1364 problem since do not know width of vector here, */
+    /* must 0 unused bits of high word32 from last used vector */
+    /* if narrrowing works by accident but widening width change will */
+    /* probably result in core dump - vector value_p should contain width */
+    xsp->ap[wi] = ((word32) value_p->value.vector[wi].aval) & __masktab[ubits];
+    xsp->bp[wi] = ((word32) value_p->value.vector[wi].bval) & __masktab[ubits];
+    
+    if (vntyp == N_REAL)
+     {
+      if (vwid > 64)
+       {
+        __vpi_err(1918, vpiError,
+         "vpi_put_value value_p vpiVectorVal width %d too wide to convert to real",
+         vwid);
+        return(NULL);
+       }
+      d1 = __cnvt_stk_to_real(xsp, FALSE);
+      __pop_xstk();
+      push_xstk_(xsp, WBITS);
+      memcpy(xsp->ap, &d1, sizeof(double)); 
+      return(xsp);
+     }
+    return(xsp);
+   default: 
+    __vpi_err(1925, vpiError,
+     "vpi_put_value passed s_vpi_value format value %d illegal",
+     value_p->format);
+   return(NULL);
+  } 
+ /* putting to strength value - must convert to 1 bid strength add strong */ 
+ if (vstren)
+  {
+   /* convert only the one low bit */
+   wval = (xsp->ap[0] & 1L) | ((xsp->bp[0] & 1L) << 1);
+   __pop_xstk();
+   push_xstk_(xsp, 4);
+   sbp = (byte *) xsp->ap;
+   s0val = s1val = __map_frvpi_stren(vpiStrongDrive);
+   wval |= (((((byte) s0val) & 7L) << 5) | ((((byte) s1val) & 7L) << 2));
+   sbp[0] = (byte) wval;
+  }
+ return(xsp);
+} 
+
+/*
+ * check a 0,1,x,z vpi logic value using vpi .h constants
+ */
+static int32 chk_vpi_logicval(word32 wval)
+{
+ if (wval == vpi0 || wval == vpi1 || wval == vpiZ || wval == vpiX)
+  return(TRUE);
+ return(FALSE);
+}
+
+/*
+ * PUTV FORCE AND RELEASE ROUTINES
+ */
+
+/*
+ * vpi_ force of entire register to constant value
+ * force of entire reg only overrides possible active reg assign
+ * (from statement, no vpi_ assign)
+ *
+ * SJM 06/19/02 - since vpi forces/assign only constant values never 
+ * have dces only unusual part is that qcval may need to be added at run
+ * time - no run time dce changes needed
+ */
+static void reg_vpi_force(register struct net_t *np, word32 *ap, word32 *bp)
+{
+ register struct qcval_t *assgn_qcp, *frc_qcp;
+ char s3[RECLEN], s4[RECLEN];
+
+ strcpy(__wrks1, "");
+ /* make sure force qcval allocated */
+ if (!np->frc_assgn_allocated)
+  {
+   /* LOOKATME - since rhs value, any consequences of this at run time */
+   /* SJM 12/23/02 - in src needed even when added from PLI */
+   np->frc_assgn_allocated = TRUE;
+   if (np->nu2.qcval == NULL) __alloc_qcval(np);
+  }
+ frc_qcp = &(np->nu2.qcval[2*__inum]);
+ assgn_qcp = &(np->nu2.qcval[2*__inum + 1]);
+ /* case 1, vpi_ force pending - must replace with new vpi form force */
+ if (frc_qcp->qc_active)
+  { 
+   frc_qcp->qcstp = NULL;
+   frc_qcp->qcrhsbi = -1;
+   frc_qcp->qclhsbi = -1;
+   frc_qcp->lhsitp = NULL;
+   strcat(__wrks1, " replace force");
+  }
+ /* if qc assign pending (both not possible), mark inactive but leave */
+ /* body so can be reactivated on release */
+ else if (assgn_qcp->qc_active)
+  {
+   assgn_qcp->qc_active = FALSE;
+   strcat(__wrks1, " override assign");
+  }
+ else
+  {
+   /* LOOKATME - could avoid setting these since never used */
+   frc_qcp->qcstp = NULL;
+   frc_qcp->qcrhsbi = -1;
+   frc_qcp->qclhsbi = -1;
+   frc_qcp->lhsitp = NULL;
+  }
+ /* AIV 03/09/05 - inactive force was F must be T */
+ frc_qcp->qc_active = TRUE;
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg(":: vpi_put_value%s force of reg %s to %s in %s now %s\n",
+    __wrks1, np->nsym->synam, __regab_tostr(s3, ap, bp, np->nwid, BHEX, FALSE),
+    __msg2_blditree(s4, __inst_ptr), __to_timstr(__wrks2, &__simtime));
+  }
+ __chg_st_val(np, ap, bp);
+ /* notice can have both many wire specific and many all cbs */
+ if (__num_vpi_force_cbs > 0) __find_call_force_cbs(np, -1);
+ if (__vpi_force_cb_always) __cb_all_rfs(np, -1, TRUE);
+}
+
+/*
+ * implment vpi do release (caller handles getting value from original handle)
+ * releasing reg with pending active assign re-establishes assign
+ */
+static void reg_vpi_release(register struct net_t *np)
+{
+ register struct qcval_t *assgn_qcp, *frc_qcp;
+ char s3[RECLEN];
+
+ strcpy(__wrks1, "");
+ /* SJM 12/23/02 - logic was wrong if never allocated */
+ /* if no force in src or added by PLI, nothing to do */
+ if (np->frc_assgn_allocated) frc_qcp = &(np->nu2.qcval[2*__inum]);
+ else frc_qcp = NULL;
+
+ if (frc_qcp == NULL || !frc_qcp->qc_active)
+  {
+   __vpi_err(2101, vpiNotice,
+   "attempted vpi_put_value release of reg %s in %s failed - never forced",
+    np->nsym->synam, __msg2_blditree(__wrks2, __inst_ptr));
+   goto done;
+  }
+ frc_qcp->qc_active = FALSE; 
+ __force_active = FALSE;
+
+ /* if pending assign from statement - must reactivate it */
+ assgn_qcp = &(np->nu2.qcval[2*__inum + 1]);
+ if (assgn_qcp->qc_active)
+  {
+   /* do store and build dces in ref. itree loc. */ 
+   /* this has assoc. stmt since assign only from Verilog statement */
+   __do_qc_store(np, assgn_qcp, TRUE);
+   __assign_active = TRUE;
+   strcpy(__wrks1, " reactivating assign");
+  }
+ if (__debug_flg && __ev_tracing)
+  {
+   __tr_msg(":: vpi_put_value%s release of reg %s in %s now %s\n", __wrks1,
+    np->nsym->synam, __msg2_blditree(s3, __inst_ptr),
+    __to_timstr(__wrks2, &__simtime));
+  }
+ /* notice can have both many wire specific and many all cbs */
+done:
+ if (__num_vpi_rel_cbs > 0) __find_call_rel_cbs(np, -1);
+ if (__vpi_rel_cb_always) __cb_all_rfs(np, -1, FALSE);
+}
+
+/*
+ * wire force is bit by bit unless vectored wire (when only entire wire)
+ *
+ * force which is for debugging overrides any wire delay assign
+ * when wire change happens (wire event process) if force active, no assign
+ */
+static void wire_vpi_force(register struct net_t *np, word32 *ap, word32 *bp, 
+ register int32 ndx)
+{
+ register int32 bi, ibase;
+ char s3[RECLEN]; 
+ 
+ /* make sure assign/force table exists */ 
+ if (!np->frc_assgn_allocated) __alloc_qcval(np);
+
+ if (__debug_flg && __ev_tracing)
+  {
+   if (ndx == -1) strcpy(__wrks1, np->nsym->synam);
+   else sprintf(__wrks1, "%s[%d]", np->nsym->synam,
+    __unnormalize_ndx(np, ndx));
+   __tr_msg(":: vpi_put_value force of wire %s in %s now %s\n", __wrks1,
+    __msg2_blditree(__wrks2, __inst_ptr), __to_timstr(s3, &__simtime));
+  }
+
+ ibase = __inum*np->nwid;
+ if (!np->n_isavec)
+  {
+   /* SJM 11/14/00 - must also check cbs for scalar case */
+   __bit1_vpi_or_tran_wireforce(np, ap, bp, ibase, 0, 0, "vpi_put_value");
+   ndx = -1;
+   goto chk_cbs;
+  }
+
+ /* for vpi only 2 cases: one bit or entire wire */
+ if (ndx == -1)
+  {
+   /* ?? LOOKATME - this was low to high */
+   for (bi = np->nwid - 1; bi >= 0; bi--)
+    {
+     __bit1_vpi_or_tran_wireforce(np, ap, bp, ibase, bi, bi,
+      "vpi_put_value");
+    }
+   ndx = -1;
+  }
+ else __bit1_vpi_or_tran_wireforce(np, ap, bp, ibase, ndx, 0, "vpi_put_value");
+
+chk_cbs:
+ /* notice can have both many wire specific and many all cbs */
+ if (__num_vpi_force_cbs > 0) __find_call_force_cbs(np, ndx);
+ if (__vpi_force_cb_always) __cb_all_rfs(np, ndx, TRUE);
+}
+
+/*
+ * do 1 bit vpi_ or switch channel form net/bit wire force 
+ * caller must insure qcval records exist
+ *
+ * select bit rhsbi from wp and force to value of lhsbi
+ * must run in possible lhs xmr itree context
+ *
+ * 06/19/02 SJM - for new fixed for compilation dce algorithm these
+ * same since no dces (vpi no dces because rhs value) and tran because
+ * assigning to tran channel is what force is
+ */
+extern void __bit1_vpi_or_tran_wireforce(struct net_t *np, word32 *ap, word32 *bp,
+ int32 ibase, int32 lhsbi, int32 rhsbi, char *msg)
+{
+ register struct qcval_t *frc_qcp;
+ register struct xstk_t *xsp, *xsp2;
+ int32 bi;
+ byte *sbp;
+
+ /* even if currently forced indicate force active */
+ bi = (lhsbi == -1) ? 0 : lhsbi; 
+ frc_qcp = &(np->nu2.qcval[ibase + bi]);
+ frc_qcp->qc_active = TRUE;
+
+ /* get the 1 bit onto stack */
+ push_xstk_(xsp, 1);
+ if (rhsbi != 0) 
+  {
+   xsp->ap[0] = rhsbsel_(ap, rhsbi);
+   xsp->bp[0] = rhsbsel_(bp, rhsbi);
+  }
+ else { xsp->ap[0] = ap[0] & 1L; xsp->bp[0] = bp[0] & 1L; }
+
+ /* emit debug tracing message if needed */
+ if (__debug_flg && __ev_tracing)
+  {
+   if (lhsbi == -1) strcpy(__wrks1, ""); else sprintf(__wrks1, "[%d]", lhsbi);
+   __tr_msg("   %s force of %s into wire %s%s\n", msg,
+    __regab_tostr(__wrks2, xsp->ap, xsp->bp, 1, BHEX, FALSE),
+    np->nsym->synam, __wrks1);
+  }
+
+ /* quasi-continuous assign to strength wire always strong */
+ if (np->n_stren)
+  {
+   push_xstk_(xsp2, 4);
+   sbp = (byte *) xsp2->ap;
+   __st_standval(sbp, xsp, ST_STRVAL);
+   if (np->n_isavec) __chg_st_bit(np, lhsbi, (word32) sbp[0], 0L); 
+   else __chg_st_val(np, (word32 *) sbp, (word32 *) sbp);
+   __pop_xstk();
+  }
+ else 
+  {
+   if (np->n_isavec) __chg_st_bit(np, lhsbi, xsp->ap[0], xsp->bp[0]); 
+   else __chg_st_val(np, xsp->ap, xsp->bp);
+  }
+ __pop_xstk();
+}
+
+/*
+ * after possible concat unwinding, exec the wire section release
+ *
+ * tricky part is need to force evaluation and store of all drivers
+ *
+ * LOOKATME - is there any reason can not just call multi driver eval
+ * even for 1 or no driver case 
+ * LOOKATME - calling release vpi_ callbacks even if not forced 
+ */
+static void wire_vpi_release(struct net_t *np, int32 ndx)
+{
+ register int32 bi, ibase;
+ int32 biti, bitj, all_forced, none_forced;
+ struct qcval_t *frc_qcp;
+ char s3[RECLEN];
+ 
+ if (!np->frc_assgn_allocated) 
+  {
+   strcpy(__wrks1, " - no bits ever forced");
+no_force: 
+   if (ndx == -1) strcpy(__wrks2, np->nsym->synam);  
+   else sprintf(__wrks2, "%s[%d]", np->nsym->synam, __unnormalize_ndx(np, ndx));
+   __vpi_err(2102, vpiNotice,
+    "attempted vpi_put_value release of wire %s in %s failed%s", __wrks2,
+    __msg2_blditree(s3, __inst_ptr), __wrks1);
+   goto done;
+  }
+
+ if (__debug_flg && __ev_tracing)
+  {
+   if (ndx == -1) strcpy(__wrks2, np->nsym->synam);  
+   else sprintf(__wrks2, "%s[%d]", np->nsym->synam, __unnormalize_ndx(np, ndx));
+   __tr_msg(":: vpi_put_value release of wire %s in %s now %s\n", __wrks2,
+    __msg2_blditree(__wrks1, __inst_ptr), __to_timstr(s3, &__simtime));
+  }
+
+ /* possible for no active forces but still must check every bit */
+ ibase = __inum*np->nwid;
+ all_forced = TRUE;
+ /* SJM 12/23/02 - must exec if frc qcp allocated but maybe none forced */
+ none_forced = TRUE;
+ if (ndx == -1) { biti = np->nwid - 1; bitj = 0; } else biti = bitj = ndx;
+ for (bi = biti; bi >= bitj; bi--)
+  {
+   frc_qcp = &(np->nu2.qcval[ibase + bi]);
+   if (!frc_qcp->qc_active) { all_forced = FALSE; continue; }
+   /* notice this also turns off non vpi forces */  
+   frc_qcp->qc_active = FALSE;
+   none_forced = FALSE;
+  }
+ 
+ if (none_forced)
+  {
+   strcpy(__wrks1, " - no bits currently forced");
+   goto done;
+  }
+ /* release is immedate assign even if wire has delay no schedule */
+ __assign_1mdrwire(np);
+ if (!all_forced && ndx == -1)
+  { strcpy(__wrks1, " - some bits forced"); goto no_force; } 
+
+done:
+ /* notice can have both many wire specific and many all cbs */
+ if (__num_vpi_rel_cbs > 0) __find_call_rel_cbs(np, ndx);
+ if (__vpi_rel_cb_always) __cb_all_rfs(np, ndx, FALSE);
+}
+
+/*
+ * IMMEDIATE PUTV ASSIGN ROUTINES
+ */
+
+/*
+ * set return value for current user task or function only
+ * must be called from current system function or error
+ * this pushes and pops itree loc. from handle
+ */
+static void set_vpisfcall_retval(struct h_t *hp, p_vpi_value value_p)
+{
+ int32 sf_ind;
+ p_vpi_systf_data tfdatp;
+ struct sysfunc_t *sfbp;
+ struct systftab_t *sfp;
+ struct xstk_t *xsp;
+ char s1[RECLEN];
+
+ /* --- DBG remove --- */
+ if (hp->hrec->hu.hxp == NULL) __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+ if (hp->hrec->hu.hxp != __cur_sysf_expr)
+  {
+   if (__cur_sysf_expr == NULL)
+    {
+     sf_ind = __cur_sysf_expr->lu.x->lu.sy->el.esyftbp->syfnum;
+     sf_ind -= (__last_veriusertf + 1); 
+     sfp = &(__systftab[sf_ind]);
+     tfdatp = (p_vpi_systf_data) sfp->vpi_sytfdat;
+     strcpy(s1, tfdatp->tfname);   
+    }
+   else strcpy(s1, "**none called**");
+
+   __vpi_err(1876, vpiError,
+    "vpi_put_value of vpiSysFuncCall %s (return value) illegal - must use from calltf cb", 
+    s1);
+   return; 
+  }
+
+ sf_ind = __cur_sysf_expr->lu.x->lu.sy->el.esyftbp->syfnum;
+ sf_ind -= (__last_veriusertf + 1); 
+ sfp = &(__systftab[sf_ind]);
+ tfdatp = (p_vpi_systf_data) sfp->vpi_sytfdat;
+ sfbp = sfp->sfu.sfbp;
+ __push_itstk(hp->hin_itp);
+ /* if error do not change global xsp */ 
+ xsp = push_vpi_valuep(value_p, sfbp->retwid, sfbp->retntyp, FALSE);
+ __pop_itstk();
+ if (xsp == NULL) return;
+ if (__cur_sysf_xsp->xslen != xsp->xslen) __vpi_terr(__FILE__, __LINE__);
+ cp_walign_(__cur_sysf_xsp->ap, xsp->ap, xsp->xslen);
+ cp_walign_(__cur_sysf_xsp->bp, xsp->bp, xsp->xslen);
+ __pop_xstk();
+}
+
+/*
+ * set either a def or specparam value - always per inst
+ * not used for global params
+ *
+ * probably changes from PNUM to PISNUM rep
+ * this never changes original param width and type (maybe real) so value
+ * is converted to already determined type 
+ * user must define wide enough in source if used for delay annotation
+ * or probably truncated with delay loss
+ *
+ * this pushes and pops itree loc. from handle
+ */
+static void set_vpiparam_val(struct h_t *hp, p_vpi_value value_p)
+{
+ register int32 wlen;
+ register struct net_t *np;
+ register word32 *wp;
+ struct xstk_t *xsp;
+ struct mod_t *mdp;
+
+ np = hp->hrec->hu.hnp;
+
+ __push_itstk(hp->hin_itp);
+ mdp = hp->hin_itp->itip->imsym->el.emdp;
+ /* DBG remove --- */ 
+ if (!np->n_isaparam) __arg_terr(__FILE__, __LINE__);
+ /* --- */
+ /* if error nil, know xsp right width and type (i.e. maybe real) */ 
+ xsp = push_vpi_valuep(value_p, np->nwid, np->ntyp, FALSE);
+ if (xsp == NULL) goto done;
+
+ /* DBG remove --- */
+ if (np->nwid != xsp->xslen) __misc_terr(__FILE__, __LINE__);
+ /* --- */
+
+ /* change range rep to IS if needed */
+ if (np->srep == SR_PNUM && mdp->flatinum > 1) __chg_param_tois(np, mdp);
+ wlen = wlen_(np->nwid);
+ wp = &(np->nva.wp[2*wlen*__inum]);
+ memcpy(wp, xsp->ap, 2*WRDBYTES*wlen);
+ __pop_xstk();
+ /* final step is to re-compute (and prep) all delays param effects */
+ /* if called after delay elaboration, param net pin d.s. will be nil */
+ __re_prep_dels(np, hp->hin_itp, hp->hin_itp->itip->imsym->el.emdp, TRUE);
+
+done:
+ __pop_itstk();
+}
+
+
+/*
+ * set a vpi udp definition initial value
+ * this pushes and pops itree loc. from handle
+ *
+ * this is per udp type
+ * LOOKATME - LRM implies assign to vpiUdp primitive (i.e. per inst.)
+ * this must be wrong
+ */
+static void set_vpiudpdef_ival(struct h_t *hp, p_vpi_value value_p)
+{
+ word32 nival;
+ struct udp_t *udpp;
+ struct xstk_t *xsp;
+
+ udpp = hp->hrec->hu.hudpp;
+ /* if error nil, know xsp right width and type (i.e. maybe real) */ 
+ xsp = push_vpi_valuep(value_p, 1, N_REG, FALSE);
+ if (xsp == NULL) return;
+
+ nival = xsp->ap[0] & ((xsp->bp[0] & 1L) << 1);
+ __pop_xstk();
+ if (nival == 2)
+  {
+   __vpi_err(1871, vpiError,
+    "vpi_put_value of vpiUdpDefn initial value 1'bz illegal - value not changed");
+   return;
+  }
+ udpp->ival = nival;
+}
+
+/*
+ * immediate assign to vpi_ wire driver handle from value_p 
+ * assign one bit using npp's index
+ *
+ * this is entire net for immediate no delay case only but can be 1 bit scalar
+ * know if net is strength ap will be sbp (push converts to stren if needed)
+ */
+static void immed_vpi_drv_assign(struct net_t *np, int32 di, word32 *ap, word32 *bp)
+{
+ byte *sbp, *sbp2;
+ struct vpi_drv_t *vpidrvp;     
+
+ /* immedate assign to wire driver (handle is ptr to npp) */
+ vpidrvp = np->vpi_ndrvs[di]; 
+ /* update driver - for vpi_ strength always 1 bit (use low bit) */
+ if (np->n_stren) 
+  {
+   sbp = (byte *) ap;
+   sbp2 = &(vpidrvp->vpi_drvwp.bp[__inum*np->nwid]);
+   sbp2[0] = sbp[0]; 
+  }
+ /* assign entire vector */
+ else __st_perinst_val(vpidrvp->vpi_drvwp, np->nwid, ap, bp);
+
+ /* do fi>1 wire assign */
+ /* handle fi>1 eval and store of bits - maybe in tran channel */
+ /* LOOKATME - because of 1 bit only drivers this is inefficient because */
+ /* muste re-eval all drivers of entire net */
+ if (np->ntraux != NULL)
+  {
+   /* if hard drivers of np do not change, channel cannot change */
+   /* SJM 12/18/00 - for tran/tranif switch channels may just add to list */
+   if (__update_tran_harddrvs(np)) __eval_tran_bits(np);
+  }
+ else
+  {
+   if (np->nrngrep == NX_DWIR) __sched_1mdrwire(np);
+   else __assign_1mdrwire(np);
+  }
+}
+
+/*
+ * immediate assign to vpi_ wire bit driver handle from value_p 
+ *
+ * this is for vpi Net Bit Driver so can never be -1 (no bit for scalar)
+ */
+static void immed_vpibit_drv_assign(struct net_t *np, int32 di, int32 bi,
+ word32 *ap, word32 *bp)
+{
+ byte *sbp, *sbp2;
+ struct vpi_drv_t *vpidrvp;     
+ struct xstk_t *xsp;
+
+ vpidrvp = np->vpi_ndrvs[di]; 
+ /* DBG remove --- */
+ if (bi == -1) __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+ /* update driver - for vpi_ strength always 1 bit (use low big) */
+ if (np->n_stren) 
+  {
+   sbp = (byte *) ap;
+   sbp2 = &(vpidrvp->vpi_drvwp.bp[__inum*np->nwid + bi]);
+   sbp2[0] = sbp[0]; 
+  }
+ /* low bit into 1 bit per inst. vector */
+ else
+  {
+   push_xstk_(xsp, np->nwid);
+   __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_drvwp, np->nwid);
+   __lhsbsel(xsp->ap, bi, ap[0]);
+   __lhsbsel(xsp->bp, bi, bp[0]);
+   __st_perinst_val(vpidrvp->vpi_drvwp, np->nwid, xsp->ap, xsp->bp);
+   __pop_xstk();
+  }
+ /* do fi>1 wire assign */
+ /* handle fi>1 eval and store of bits - maybe in tran channel */
+ /* LOOKATME - because of 1 bit only drivers this is inefficient because */
+ /* muste re-eval all drivers of entire net */
+ if (np->ntraux != NULL)
+  {
+   /* if hard drivers of np do not change, channel cannot change */
+   /* SJM 12/18/00 - for tran/tranif switch channels may just add to list */
+   if (__update_tran_harddrvs(np)) __eval_tran_bits(np);
+  }
+ else
+  {
+   if (np->nrngrep == NX_DWIR) __sched_1mdrwire(np);
+   else __assign_1mdrwire(np);
+  }
+}
+
+/*
+ * VPI EVENT PROCESSING ROUTINES
+ */
+
+/*
+ * process a vpi put value handle assign event
+ *
+ * for regs (also variables) array words, and variable bits
+ * and wires (here softforce is used)
+ *
+ * assigning either entire reg or reg bit but only one pending event allowed
+ *
+ * SJM 07/22/00 - although originally for regs also used for soft force
+ * of wire
+ * SJM 11/14/00 - now wire soft force is more like wire force except no 
+ * release
+ */
+extern void __process_vpi_varputv_ev(i_tev_ndx tevpi)
+{
+ register struct net_t *np;
+ register struct dltevlst_t *dlp;
+ register word32 *ap, *bp;
+ register struct h_t *hp;
+ int32 wlen;
+ struct teputv_t *tepvp;
+
+ tepvp = __tevtab[tevpi].tu.teputvp;
+ __tevtab[tevpi].tu.teputvp = NULL;
+
+ np = tepvp->np;
+ if (__ev_tracing) emit_vpiputv_evtrmsg(np, tepvp, tepvp->nbi);
+
+ /* if putv scheduled event saved, turn on event happened flag in handle */
+ /* because since user has handle later incorrect cancel might be tried */
+ /* for registers only only event per inst allowed (i.e lhs bsel or assign) */
+ if ((hp = tepvp->evnt_hp) != NULL) hp->hrec->evnt_done = TRUE;
+ /* do the proc. assign, or driver change and fi>1 eval */
+ wlen = wlen_(np->nwid);
+ ap = tepvp->putv_wp;
+ bp = &(ap[wlen]);
+
+ if (np->ntyp < NONWIRE_ST)
+  {
+   /* following acc_ routines, no delay set ignored any pending assigns */ 
+   /* SJM 11/14/00 - for soft force of in tran chan (inout), now soft */
+   /* all wires in tran chan */ 
+   /* SJM 03/15/01 - can't force all of tran channel - just soft force */
+   /* this tran wire and re-eval tran channel */
+   if (np->ntraux != NULL)
+    {
+      __tran_exec_putv_wire_softforce(np, ap, bp, tepvp->nbi);
+      __eval_tran_1bit(np, tepvp->nbi);
+     }
+   else exec_putv_wire_softforce(np, ap, bp, tepvp->nbi);
+  }
+ /* reg assign event */
+ else exec_putv_reg_assign(np, ap, bp, tepvp->nbi);
+
+ /* free the the reg putv event auxiliary record - never strength*/ 
+ __my_free((char *) ap, 2*wlen*WRDBYTES);
+ dlp = np->regwir_putv_tedlst[__inum];
+ np->regwir_putv_tedlst[__inum] = dlp->terp;
+
+ /* link on putv event contents record free list */
+ tepvp->np = (struct net_t *) __teputvfreelst;
+ __teputvfreelst = tepvp;
+
+ /* also link out dltevlst element - must be on front */
+ /* DBGMAYBELEAVE */
+ if (dlp == NULL || tevpi != dlp->tevpi) __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+ dlp->telp = NULL;
+ /* put this telst elemnt on free list */
+ dlp->terp = __dltevfreelst;
+ __dltevfreelst = dlp;
+}
+
+/*
+ * emit a delayed scheduled vpi put_value trace message 
+ *
+ * handled both reg proc. assign and driver assign of added vpi wire drvr
+ */
+static void emit_vpiputv_evtrmsg(struct net_t *np, struct teputv_t *tepvp,
+ int32 nbi)
+{ 
+ int32 wid;
+ word32 *ap, *bp;
+ byte *sbp;
+ char ts1[RECLEN], ts2[IDLEN], ts3[RECLEN], ts4[RECLEN];
+
+ if (np->n_isarr)
+  {
+   sprintf(ts3, "array word32 %s[%d]", np->nsym->synam,
+    __unnormalize_ndx(np, nbi));
+   wid = np->nwid;
+  }
+ else if (nbi != -1) 
+  {
+   sprintf(ts3, "%s %s[%d]", __to_wtnam(ts1, np), np->nsym->synam,
+    __unnormalize_ndx(np, nbi));
+   wid = 1;
+  }
+ else
+  {
+   sprintf(ts3, "%s %s", __to_wtnam(ts1, np), np->nsym->synam);
+   wid = np->nwid;
+  }
+ if (np->ntyp >= NONWIRE_ST)
+  {
+   strcpy(ts1, "procedural");
+   /* DBG remove --- */
+   if (np->regwir_putv_tedlst == NULL) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+  }
+ else
+  {
+   if (np->ntraux) strcpy(ts1, "vpi_ inout or tran channel driver"); 
+   else if (np->n_multfi) strcpy(ts1, "vpi_ wire driver");
+   /* SJM  11/25/0 - tracing also for soft force to wire - so fi==1 ok */
+   /* and must leave wid as is */
+   else strcpy(ts1, "wire");
+  }
+
+ /* strength must be driver - other can be one bit or reg width */
+ if (np->n_stren)
+  { sbp = (byte *) tepvp->putv_wp; __st_regab_tostr(ts2, sbp, 1); }
+ else
+  { 
+   ap = tepvp->putv_wp;
+   bp = &(ap[wlen_(wid)]);
+   __regab_tostr(ts2, ap, bp, wid, BHEX, FALSE);
+  }
+ __evtr_resume_msg();
+ __tr_msg("== processing vpi_put_value %s event in %s value %s\n",
+  ts3, __msg2_blditree(ts4, __inst_ptr), ts2);
+} 
+
+/*
+ * exec a vpi put value assign to reg - no delay or event processing
+ */
+static void exec_putv_reg_assign(register struct net_t *np, register word32 *ap,
+ register word32 *bp, register int32 ndx)
+{
+ int32 arrwid, bi;
+ 
+ /* case 1: array */
+ if (np->n_isarr)
+  {
+   /* array never forced or assigned */ 
+   arrwid = __get_arrwide(np);
+   if (np->nchg_nd_chgstore)
+    {
+     __chg_st_arr_val(np->nva, arrwid, np->nwid, ndx, ap, bp);
+     if (__lhs_changed) record_sel_nchg_(np, ndx, ndx);
+    }
+   else __st_arr_val(np->nva, arrwid, np->nwid, ndx, ap, bp);
+   return;
+  }
+ /* case 2: entire reg */
+ if (ndx == -1)
+  {
+   if (np->nu2.qcval != NULL && reg_fr_inhibit_(np)) return; 
+   if (np->nchg_nd_chgstore) __chg_st_val(np, ap, bp);
+   else __st_val(np, ap, bp);
+   return;
+  }
+ /* case 3: reg bit select - if active force, no assign */
+ /* know ndx never -1 here */
+ bi = (ndx == -1) ? 0 : ndx;
+ if (!np->frc_assgn_allocated
+  || !np->nu2.qcval[np->nwid*__inum + bi].qc_active)
+  {
+   /* SJM - 07/24/00 - now do not use chg st bit unless needed */
+   if (np->nchg_nd_chgstore) __chg_st_bit(np, ndx, ap[0], bp[0]);
+   else __st_bit(np, ndx, ap[0], bp[0]); 
+  }
+}
+
+/*
+ * exec a vpi tput value soft force procedural style assign to reg
+ * no delay or event processing (may be called from delay assign ev handler)
+ */
+static void exec_putv_wire_softforce(register struct net_t *np,
+ register word32 *ap, register word32 *bp, register int32 ndx)
+{
+ /* case 1: entire wire */
+ if (ndx == -1)
+  {
+   /* this add the changed wire to nchglst if needed */
+   if (np->nu2.qcval != NULL)
+    {
+     /* return F if all of wire forced, nothing to do */ 
+     /* if T, this will correct bits in ap and bp so actual assign is right */
+     if (!__correct_forced_newwireval(np, ap, bp)) return;
+    }
+   if (np->nchg_nd_chgstore) __chg_st_val(np, ap, bp);
+   else __st_val(np, ap, bp);
+   return;
+  }
+ /* case 2: wire bit select */
+ /* if the 1 bit is forced nothing to do */
+ /* know ndx never -1 since -1 case handled above */
+ if (np->frc_assgn_allocated
+  && np->nu2.qcval[np->nwid*__inum + ndx].qc_active) return;
+
+ /* else simple bit assign */
+ /* SJM 03/15/01 - change to fields in net record */
+ if (np->nchg_nd_chgstore) __chg_st_bit(np, ndx, ap[0], bp[0]);
+ else __st_bit(np, ndx, ap[0], bp[0]); 
+}
+
+/*
+ * process a vpi driver put value assign event
+ *
+ * for scheduled (delayed) assigns to drivers of wires (like contas)
+ *
+ * know a/b value always 1 bit and type known and called from ev itree loc 
+ * for added entire vectored wire driver each bit still has separate event
+ */
+extern void __process_vpidrv_ev(i_tev_ndx tevpi)
+{
+ register struct net_t *np;
+ register struct dltevlst_t *dlp;
+ register word32 *ap, *bp;
+ int32 ndx, evi;
+ struct teputv_t *tepvp;
+ i_tev_ndx *evtabi; 
+ struct h_t *hp;
+ struct hrec_t *hrp;
+
+ tepvp = __tevtab[tevpi].tu.teputvp;
+ __tevtab[tevpi].tu.teputvp = NULL;
+
+ np = tepvp->np;
+ if (__ev_tracing) emit_vpiputv_evtrmsg(np, tepvp, tepvp->nbi);
+
+ /* if putv scheduled event saved, turn on event happened flag in handle */
+ /* because since user has handle later incorrect cancel might be tried */
+ /* also at end of time slot canceled tev will be reused */ 
+ if ((hp = tepvp->evnt_hp) != NULL)
+  {
+   hrp = hp->hrec;
+   if (hrp->bith_ndx)
+    {
+     /* here hp is master entire vector scheduled object */
+     evtabi = hrp->hu.hevrec->evndxtab;
+     evtabi[tepvp->nbi] = -1;
+    }
+   else hrp->evnt_done = TRUE;
+  }
+ /* do the proc. assign, or driver change and fi>1 eval */
+ ap = tepvp->putv_wp;
+ /* for scalar bit is 0 for right index - else the vector's index */
+ if (np->n_stren) bp = ap; else bp = &(ap[1]);
+ if (tepvp->nbi == -1)
+  {
+   immed_vpi_drv_assign(np, tepvp->di, ap, bp);
+   ndx = 0;
+  }
+ else
+  {
+   ndx = tepvp->nbi;
+   immed_vpibit_drv_assign(np, tepvp->di, ndx, ap, bp);
+  }
+
+ /* free the the driver putv event auxiliary record */ 
+ __my_free((char *) ap, 2*WRDBYTES);
+ /* excise out first being processed event */
+ evi = np->nwid*__inum + ndx;
+ dlp = np->vpi_ndrvs[tepvp->di]->putv_drv_tedlst[evi];
+ np->vpi_ndrvs[tepvp->di]->putv_drv_tedlst[evi] = dlp->terp;
+
+ /* link on putv event contents record free list */
+ tepvp->np = (struct net_t *) __teputvfreelst;
+ __teputvfreelst = tepvp;
+
+ /* also link out dltevlst element - must be on front */
+ /* DBGMAYBELEAVE */
+ if (dlp == NULL || tevpi != dlp->tevpi) __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+ dlp->telp = NULL;
+ /* put this telst elemnt on free list */
+ dlp->terp = __dltevfreelst;
+ __dltevfreelst = dlp;
+}
+
+/*
+ * convert a passed delay time to internal ticks
+ */
+extern int32 __vpitime_to_ticks(word64 *timp, p_vpi_time time_p,
+ struct mod_t *mdp) 
+{
+ word64 tim;
+
+ if (time_p->type == vpiScaledRealTime)
+  {
+   if (!__real_to_v64tim(&tim, time_p->real))
+    {
+     __vpi_err(1926, vpiError,
+      "vpiTimeVal type vpiScaledRealTime too large for 64 bit time - not converted");
+     *timp = 0ULL;
+     return(FALSE);
+    }
+   if (mdp != NULL && !mdp->mno_unitcnv) cnv_num64to_ticks_(*timp, tim, mdp);
+   else *timp = tim;
+  }
+ else
+  {
+   if (time_p->type != vpiSimTime)
+    {
+     __vpi_err(2018, vpiWarning,
+      "vpiTimeVal of type vpiSuppressTime meaningless here - using vpiSimTime");
+    }
+   /* sim time is internal ticks (lowest time precision in design) */
+   /* SJM 02/03/00 since PLI time values int32 not word32 cast make 64 */
+   /* bits of 1 for -1 not word32 32 bits value as needed */
+   *timp = ((word64) ((word32) (time_p->low)))
+     | (((word64) ((word32) time_p->high)) << 32);
+  }
+ return(TRUE);
+}
+
+/*
+ * PUTV DELAY SCHEDULING ROUTINES
+ */
+
+/*
+ * implement delayed assign (usually scheduled) of value_p value to reg var
+ * or bit select of reg var or soft force of wire or wire bit  
+ *
+ * inertial replaces pending sched ev with later and removes earlier 
+ * but documentation says something else
+ *
+ * only for delays - * must run in itree loc. of handle 
+ *
+ * SJM 07/25/00 - this routine used also for soft force to nets and net bits
+ *                exactly same algorithm
+ *
+ * no driving values stored for registers or nets
+ * LOOKATME - does this work with strengths - think so
+ */
+static struct h_t *setschd_var_fromvaluep(p_vpi_value value_p,
+ struct net_t *np, int32 ndx, word64 ticksdel, byte dtyp, int32 ret_event)
+{ 
+ register struct dltevlst_t *dlp, *dlp2, *ins_after_dlp;
+ int32 wlen, ewid;
+ i_tev_ndx tevpi;
+ word64 schtim;
+ struct xstk_t *xsp;
+ struct teputv_t *tepvp;
+ struct h_t *hp;
+
+ if (ndx == -1) ewid = np->nwid; else ewid = 1;
+ /* this can be strength if soft force to wire */
+ if ((xsp = push_vpi_valuep(value_p, ewid, np->ntyp, np->n_stren)) == NULL)
+  return(NULL);
+
+ /* allocate per inst but not per bit pending event list if needed */ 
+ /* SJM 07/24/00 - net putv tedlst also used for soft force of wires */
+ if (np->regwir_putv_tedlst == NULL) bld_regwir_putvrec(np);
+
+ schtim = __simtime + ticksdel;
+ if (__ev_tracing) 
+  {
+   char s1[RECLEN]; 
+
+   dlp = np->regwir_putv_tedlst[__inum];
+   if (np->ntyp >= NONWIRE_ST) strcpy(s1, "reg");
+   else strcpy(s1, "wire soft force");
+   emit_vpiputv_schd_trmsg(np, xsp, dlp, &schtim, dtyp, "reg");
+  }
+
+ ins_after_dlp = NULL;
+ /* eliminate new and/or cancel any olds */
+ if ((dlp = np->regwir_putv_tedlst[__inum]) != NULL)
+  {
+   /* case 1: inertial - remove all but one latest - return if no effect */
+   /* inertial follows Verilog normal convention - keep only latest */
+   /* and eliminate any earlier */
+   if (dtyp == vpiInertialDelay)
+    {
+     /* start by removing all of list but last (if needed) - know >= 2 */
+     if (dlp->terp != NULL)
+      {
+       dlp2 = __spliceout_last(dlp);
+       cancel_vpievents_toend(np, dlp, ewid);
+       dlp = dlp2;
+       np->regwir_putv_tedlst[__inum] = dlp;
+       dlp->telp = NULL;
+      }
+     /* by here list has exactly one element (last) */
+     /* if new one earlier - do not schedule, same time, use new */
+     if (__tevtab[dlp->tevpi].etime > schtim) { __pop_xstk(); return(NULL); }
+
+     /* know new event time is later - cancel all of one element list */
+     cancel_vpievents_toend(np, dlp, ewid);
+     np->regwir_putv_tedlst[__inum] = NULL;
+     ins_after_dlp = NULL;
+     goto bld_tev;
+    }
+   /* case 2: modified transport - remove all delays >= than new */
+   /* notice if same time delays must leave and insert this after all */
+   /* currently scheduled for this time */
+   if (dtyp == vpiTransportDelay)
+    {
+     /* SJM 09/05/99 - think elmination when scheduled wrong */
+     /* nothing to remove, just put on end of active pnd0 queue */
+     /* SJM - if (schtim == 0ULL) goto bld_tev; WRONG */
+     /* AIV 03/09/05 - for 0 delay schedule time will not be 0 */
+     if (ticksdel == 0ULL) goto bld_tev;
+
+     /* know delay list in time order */
+     /* dlp2 is one before first after (maybe last), nil is before all */ 
+     if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL) 
+      { 
+       /* new delay is before all - empty list */
+       dlp2 = np->regwir_putv_tedlst[__inum];
+       cancel_vpievents_toend(np, dlp2, ewid);
+       np->regwir_putv_tedlst[__inum] = NULL;
+       ins_after_dlp = NULL;
+       goto bld_tev; 
+      } 
+     /* new delay is after all - nothing to remove */
+     if (dlp2->terp == NULL) { ins_after_dlp = dlp2; goto bld_tev; } 
+     /* new delay is after some and before some */
+     ins_after_dlp = dlp2;
+     if (dlp2->terp != NULL)  
+      { cancel_vpievents_toend(np, dlp2->terp, ewid); dlp2->terp = NULL; }
+     goto bld_tev;
+    }
+   /* DBG remove --- */
+   if (dtyp != vpiPureTransportDelay) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   /* pure transport - insert in right place in list */
+   /* if new delay is before all - insert at front */
+   if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL) 
+    { ins_after_dlp = NULL; goto bld_tev; }
+   /* if goes after list, end of list returned else place to ins after */
+   ins_after_dlp = dlp2; 
+  }   
+
+bld_tev:
+ /* allocate and schedule event */ 
+ alloc_tev_(tevpi, TE_VPIPUTVDEL, __inst_ptr, schtim);
+ /* need to store scheduled driving value in event because can be many */
+ if (__teputvfreelst != NULL)
+  {
+   tepvp = __teputvfreelst;
+   __teputvfreelst = (struct teputv_t *) __teputvfreelst->np;
+  }
+ else tepvp = (struct teputv_t *) __my_malloc(sizeof(struct teputv_t));
+ tepvp->nbi = ndx;
+ tepvp->np = np;
+ /* assume non handle returning mode */
+ tepvp->evnt_hp = NULL;
+ wlen = wlen_(ewid);
+ tepvp->putv_wp = (word32 *) __my_malloc(2*WRDBYTES*wlen);
+ memcpy(tepvp->putv_wp, xsp->ap, 2*WRDBYTES*wlen);
+ __tevtab[tevpi].tu.teputvp = tepvp;
+ __tevtab[tevpi].vpi_regwir_putv = TRUE;
+ __pop_xstk();
+ /* schedule event */
+ /* case 1: schedule and add to list */
+ /* SJM 09/05/99 - was only adding to pound 0 at time 0 - WRONG */
+ if (ticksdel == 0ULL)
+  {
+   if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+   else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+  }
+ else __insert_event(tevpi);
+
+ /* build the dl tev lst */
+ if (__dltevfreelst != NULL)
+  { dlp = __dltevfreelst; __dltevfreelst = __dltevfreelst->terp; }
+ else dlp = (struct dltevlst_t *) __my_malloc(sizeof(struct dltevlst_t)); 
+ dlp->tevpi = tevpi;
+
+ /* insert at front of list */
+ if (ins_after_dlp == NULL)  
+  {
+   dlp2 = np->regwir_putv_tedlst[__inum];
+   dlp->terp = dlp2;
+   if (dlp2 != NULL) dlp2->telp = dlp;
+   dlp->telp = NULL;
+   np->regwir_putv_tedlst[__inum] = dlp;
+  }
+ /* insert after */
+ else
+  {  
+   dlp->terp = ins_after_dlp->terp; 
+   if (dlp->terp != NULL) dlp->terp->telp = dlp;
+   ins_after_dlp->terp = dlp;
+   dlp->telp = ins_after_dlp;
+  }
+ if (ret_event)
+  {
+   /* need itree loc. so can get right pending event list */
+   /* notice if bith ndx on handle is ev rec (table of tev's) else just ev */
+   /* this is 1 bit using tev index not table because bith ndx off */ 
+   hp = (struct h_t *) __mk_handle(vpiSchedEvent, (void *) tevpi,
+    __inst_ptr, NULL);
+   hp->hrec->evnt_done = FALSE;
+   __tevtab[tevpi].tu.teputvp->evnt_hp = hp;
+   return(hp);
+  }
+ return(NULL);
+}
+
+/*
+ * emit a vpi_put_value scheduled assign part
+ * 
+ * LOOKATME - no tracing currently for immediate assigns 
+ */
+static void emit_vpiputv_schd_trmsg(struct net_t *np, struct xstk_t *xsp,
+ struct dltevlst_t *dlp, word64 *schdtimp, int32 dtyp, char *putvnam)
+{
+ char ts1[RECLEN], ts2[RECLEN], ts3[RECLEN];
+
+ if (np->n_stren) __st_regab_tostr(ts1, (byte *) xsp->ap, 1);
+ else __regab_tostr(ts1, xsp->ap, xsp->bp, np->nwid, BHEX, FALSE);
+
+ __evtr_resume_msg();
+ __tr_msg("== schedule %s vpi_put_value to %s (in %s) value %s for %s:\n",
+  putvnam, np->nsym->synam, __msg2_blditree(ts2, __inst_ptr), ts1, 
+  __to_timstr(ts3, schdtimp));
+
+ if (dlp != NULL)
+  {
+   __tr_msg("   <%s update of scheduled events>\n",
+    putv_flag_to_str(ts1, dtyp));
+  }
+ else __tr_msg("   <no scheduled events>\n");
+}
+
+/*
+ * for first putv to reg allocate and zero per inst. scheduled list 
+ * must be called from right (on itstk) itree loc. 
+ */
+static void bld_regwir_putvrec(struct net_t *np)
+{
+ int32 nbytes;
+
+ nbytes = __inst_mod->flatinum*sizeof(struct dltevlst_t *);
+ np->regwir_putv_tedlst = (struct dltevlst_t **) __my_malloc(nbytes);
+ memset(np->regwir_putv_tedlst, 0, nbytes); 
+}
+
+/*
+ * reinitialize putvrec for reg or wire by freeing any pending events
+ *
+ * called when resetting from prep code
+ * only called if putvrec non nil
+ *
+ * SJM 07/25/00 - also putv recs for soft force of regs and wires
+ */
+extern void __reinit_regwir_putvrec(struct net_t *np, int32 insts)
+{
+ register int32 ii;
+ register struct dltevlst_t *dlp, *dlp2, *last_dlp;
+
+ for (ii = 0; ii < insts; ii++)
+  {
+   /* notice events will be in event queue and already freed */ 
+   if ((dlp = np->regwir_putv_tedlst[ii]) == NULL) continue;
+   last_dlp = NULL;
+   for (dlp2 = dlp; dlp2 != NULL; dlp2 = dlp2->terp) last_dlp = dlp2;
+   last_dlp->terp = __dltevfreelst; 
+   __dltevfreelst = dlp;
+  }
+}
+
+/*
+ * for vpi delayed putv cancel all events starting at passed to end 
+ *
+ * for change to inertial - free all but last and return last (latest)
+ * this list for the one given parameter must be ordered by time
+ * caller must set previous next field to nil or nil out list
+ * differs from tf_ dputp only in removing either entire wire or bit 
+ */
+static void cancel_vpievents_toend(struct net_t *np, struct dltevlst_t *frdlp,
+ int32 ewid)
+{
+ register struct dltevlst_t *dlp, *last_dlp;
+ register i_tev_ndx tevpi;
+ struct teputv_t *tepvp;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+
+ for (last_dlp = NULL, dlp = frdlp; dlp != NULL; dlp = dlp->terp)  
+  {
+   tevpi = dlp->tevpi;
+   /* need to leave event, gets processed as cancelled and freed en masse */  
+   __tevtab[tevpi].te_cancel = TRUE;
+   tepvp = __tevtab[tevpi].tu.teputvp;
+   /* tricky part for tab form vector driver must fix table ptr */
+   if ((hp = tepvp->evnt_hp) != NULL)
+    {
+     hrp = hp->hrec;
+     if (hrp->bith_ndx)
+      {   
+       i_tev_ndx *evtabi;
+
+       /* DBG remove --- */
+       if (np->nwid < 2) __vpi_terr(__FILE__, __LINE__);
+       if (hrp->htyp != vpiSchedEvent) __vpi_terr(__FILE__, __LINE__);
+       /* --- */
+       /* only mark event done for non vectored entire wire schd. */ 
+       evtabi = hrp->hu.hevrec->evndxtab;
+       evtabi[tepvp->nbi] = -1;
+       /* LOOKATME - could check entire table and mark event done here */
+      }
+     else hrp->evnt_done = TRUE; 
+    }
+
+   /* free the value since te cancel implies guts never freed */
+   __my_free((char *) tepvp->putv_wp, 2*wlen_(ewid)*WRDBYTES);
+
+   /* free tevputv by linking on free list */
+   tepvp->np = (struct net_t *) __teputvfreelst;
+   __teputvfreelst = tepvp;
+   last_dlp = dlp;
+  }
+ /* finally link all of dltevlst onto free list */
+ /* SJM 08/02/01 - add if to keep lint happy */
+ if (last_dlp != NULL) last_dlp->terp = __dltevfreelst; 
+ __dltevfreelst = frdlp;
+}
+
+/*
+ * delayed schedule of wire driver either scalar, bit, or entire vector
+ *
+ * returns schedule event handle if ret event T else nil
+ * handle type either vpi net or net bit driver
+ */
+static struct h_t *setschd_drvr_fromvaluep(p_vpi_value value_p,
+ struct h_t *hp, word64 ticksdel, byte dtyp, int32 ret_event)
+{ 
+ register int32 bi;
+ register struct net_t *np;
+ int32 some_sched;
+ i_tev_ndx tevpi, *evtabi;
+ struct h_t *hp2;
+ struct net_pin_t *npp;
+ struct xstk_t *xsp, *xsp2;
+ struct schdev_t *schd_ev;
+
+ npp = hp->hrec->hu.hnpp;
+ np = npp->elnpp.enp;
+ /* case 1: net bit */
+ if (hp->hrec->htyp == vpiNetBitDriver)
+  {
+   if ((xsp = push_vpi_valuep(value_p, 1, np->ntyp, np->n_stren)) == NULL)
+    return(NULL);
+   /* DBG remove --- */
+   if (!np->n_isavec) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   tevpi = setschd_1bit_drvr(npp, npp->npaux->nbi1, xsp, ticksdel, dtyp);
+
+   if (ret_event && tevpi != -1)
+    {
+     /* need itree loc. so can get right pending event list */
+     /* notice if bith ndx on handle is ev rec (table of tev's) else just ev */
+     hp2 = (struct h_t *) __mk_handle(vpiSchedBitEvent, (void *) tevpi,
+      __inst_ptr, NULL);
+     hp2->hrec->evnt_done = FALSE;
+     __tevtab[tevpi].tu.teputvp->evnt_hp = hp2;
+    }
+   else hp2 = NULL; 
+   __pop_xstk();
+   return(hp2);
+  }
+ /* case 2: entire net */
+ /* case 2a: scalar net */
+ if (!np->n_isavec)
+  {
+   if ((xsp = push_vpi_valuep(value_p, 1, np->ntyp, np->n_stren)) == NULL)
+    return(NULL);
+   tevpi = setschd_1bit_drvr(npp, 0, xsp, ticksdel, dtyp);
+
+   if (ret_event && tevpi != -1)
+    {
+     /* need itree loc. so can get right pending event list */
+     hp2 = (struct h_t *) __mk_handle(vpiSchedEvent, (void *) tevpi,
+      __inst_ptr, NULL);
+     hp2->hrec->evnt_done = FALSE;
+     /* bith ndx not set indicates not ev tab table */ 
+     __tevtab[tevpi].tu.teputvp->evnt_hp = hp2;
+    }
+   else hp2 = NULL; 
+   __pop_xstk();
+   return(hp2);
+  }
+
+ /* case 2b: vector net */
+ if ((xsp = push_vpi_valuep(value_p, np->nwid, np->ntyp, np->n_stren))
+  == NULL) return(NULL);
+
+ evtabi = (i_tev_ndx *) __my_malloc(np->nwid*sizeof(i_tev_ndx));
+ /* ?? LOOKATME - this was low to high */
+ for (bi = np->nwid - 1; bi >= 0; bi--) evtabi[bi] = -1;
+ some_sched = FALSE;
+ /* for strength vectors just assign to low bit - also warning */
+ if (np->n_stren)
+  {
+   /* BEWARE big endian problem, works providing always pass and cast ptrs */
+   /* i.e. can not pass word32 here on suns will get high not low */
+   tevpi = setschd_1bit_drvr(npp, 0, xsp, ticksdel, dtyp);
+   if (tevpi != -1) some_sched = TRUE;
+   evtabi[0] = tevpi;
+  }
+ else
+  { 
+   push_xstk_(xsp2, 1);
+   /* ?? LOOKATME - this was low to high */
+   for (some_sched = FALSE, bi = np->nwid - 1; bi >= 0; bi--)
+    {
+     /* this works because if net stren value will be always also be stren */
+     /* conversion made in push vpi value if needed */
+     /* also know all bits but low are 0 */
+     xsp2->ap[0] = rhsbsel_(xsp->ap, bi);
+     xsp2->bp[0] = rhsbsel_(xsp->bp, bi);
+
+     /* may return -1 if no event scheduled */
+     /* can pass address of stacked words since never strengths */
+     tevpi = setschd_1bit_drvr(npp, bi, xsp2, ticksdel, dtyp);
+     if (tevpi != -1) some_sched = TRUE;
+     evtabi[bi] = tevpi;
+    }
+   __pop_xstk();
+  }
+ __pop_xstk();
+ if (ret_event && some_sched)
+  {
+   /* need itree loc. so can get right pending event list */
+   /* notice if bith ndx on handle is ev rec (table of tev's) else just ev */
+   schd_ev = (struct schdev_t *) __my_malloc(sizeof(struct schdev_t));
+   schd_ev->evnp = np;
+   schd_ev->evndxtab = evtabi;
+   
+   hp2 = (struct h_t *) __mk_handle(vpiSchedEvent, (void *) schd_ev,
+    __inst_ptr, NULL);
+   hp2->hrec->evnt_done = FALSE;
+   /* BEWARE - using 2 different form for vpiSched.. object this field */
+   /* is used as special case (need evndxtab case) */
+   hp2->hrec->bith_ndx = TRUE;
+   for (bi = np->nwid - 1; bi >= 0; bi--)
+    {
+     tevpi = evtabi[bi];
+     /* SJM 04/20/00 - possible for only some to have events */
+     if (tevpi != -1) __tevtab[tevpi].tu.teputvp->evnt_hp = hp2;
+    }
+  }
+ else
+  {
+   __my_free((char *) evtabi, np->nwid*sizeof(i_tev_ndx));
+   hp2 = NULL; 
+  }
+ return(hp2);
+}
+
+/*
+ * implement assign (scheduled) of 1 bit on xstk to 1 wire driver bit 
+ * delayed assign to driver for either driver bit or 1 bit of scalar
+ * 
+ * always returned scheduled event on sucess (caller creates handle if needed)
+ * if no event scheduled returns nil (possible inertial not schedule)
+ *
+ * inertial replaces pending sched ev with later and removes earlier 
+ * but documentation says something else
+ *
+ * only for delays - no delay handled as special case above here
+ * must run in itree loc. of handle 
+ */
+static i_tev_ndx setschd_1bit_drvr(struct net_pin_t *npp, int32 bi,
+ struct xstk_t *xsp, word64 ticksdel, byte dtyp)
+{ 
+ register struct dltevlst_t *dlp, *dlp2, *ins_after_dlp;
+ int32 evi;
+ i_tev_ndx tevpi; 
+ word64 schtim;
+ struct net_t *np;
+ struct vpi_drv_t *vpidrvp;     
+ struct tev_t *tevp;
+ struct teputv_t *tepvp;
+
+ np = npp->elnpp.enp;
+ schtim = __simtime + ticksdel;
+ ins_after_dlp = NULL;
+ vpidrvp = np->vpi_ndrvs[npp->obnum]; 
+ /* notice bit index 0 for scalar */ 
+ /* table of scheduled events is one list for each net bit per inst. */
+ evi = np->nwid*__inum + bi;
+
+ if (__ev_tracing) 
+  {
+   char ts1[RECLEN];
+
+   if (np->n_isavec) sprintf(ts1, "bit %d driver", bi);
+   else strcpy(ts1, "scalar driver");
+   dlp = vpidrvp->putv_drv_tedlst[evi];
+   emit_vpiputv_schd_trmsg(np, xsp, dlp, &schtim, (int32) dtyp, ts1);
+  }
+
+ /* eliminate new and/or cancel any olds */
+ if ((dlp = vpidrvp->putv_drv_tedlst[evi]) != NULL)
+  {
+   /* case 1: inertial - remove all but one latest - return if no effect */
+   /* inertial follows Verilog normal convention - keep only latest */
+   /* and eliminate any earlier */
+   if (dtyp == vpiInertialDelay)
+    {
+     /* start by removing all of list but last (if needed) - know >= 2 */
+     if (dlp->terp != NULL)
+      {
+       dlp2 = __spliceout_last(dlp);
+       cancel_vpievents_toend(np, dlp, 1);
+       dlp = dlp2;
+       vpidrvp->putv_drv_tedlst[evi] = dlp;
+       dlp->telp = NULL;
+      }
+     /* by here list has exactly one element (last) */
+     /* if new one earlier - do not schedule, same time, use new */
+     tevp = &(__tevtab[dlp->tevpi]);
+     if (tevp->etime > schtim) return(-1);
+
+     /* know new event time is later - cancel all of one element list */
+     cancel_vpievents_toend(np, dlp, 1);
+     vpidrvp->putv_drv_tedlst[evi] = NULL;
+     ins_after_dlp = NULL;
+     goto bld_tev;
+    }
+   /* case 2: modified transport - remove all delays >= than new */
+   /* notice if same time delays must leave and insert this after all */
+   /* currently scheduled for this time */
+   if (dtyp == vpiTransportDelay)
+    {
+     /* SJM 09/05/99 - think elmination when scheduled wrong */
+     /* nothing to remove, just put on end of active pnd0 queue */
+     /* SJM - if (schtim == 0ULL) goto bld_tev; WRONG */
+
+     /* know delay list in time order */
+     /* dlp2 is one before first after (maybe last), nil is before all */ 
+     if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL) 
+      { 
+       /* new delay is before all - empty list */
+       dlp2 = vpidrvp->putv_drv_tedlst[evi];
+       cancel_vpievents_toend(np, dlp2, 1);
+       vpidrvp->putv_drv_tedlst[evi] = NULL;
+       ins_after_dlp = NULL;
+       goto bld_tev; 
+      } 
+     /* new delay is after all - nothing to remove */
+     if (dlp2->terp == NULL) { ins_after_dlp = dlp2; goto bld_tev; } 
+     /* new delay is after some and before some */
+     ins_after_dlp = dlp2;
+     if (dlp2->terp != NULL)  
+      { cancel_vpievents_toend(np, dlp2->terp, 1); dlp2->terp = NULL; }
+     goto bld_tev;
+    }
+   /* DBG remove --- */
+   if (dtyp != vpiPureTransportDelay) __vpi_terr(__FILE__, __LINE__);
+   /* --- */
+   /* pure transport - insert in right place in list */
+   /* if new delay is before all - insert at front */
+   if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL) 
+    { ins_after_dlp = NULL; goto bld_tev; }
+   /* if goes after list, end of list returned else place to ins after */
+   ins_after_dlp = dlp2; 
+  }   
+
+bld_tev:
+ /* allocate and schedule event */ 
+ alloc_tev_(tevpi, TE_VPIDRVDEL, __inst_ptr, schtim);
+ /* need to store scheduled driving value in event because can be many */
+ if (__teputvfreelst != NULL)
+  {
+   tepvp = __teputvfreelst;
+   __teputvfreelst = (struct teputv_t *) __teputvfreelst->np;
+  }
+ else tepvp = (struct teputv_t *) __my_malloc(sizeof(struct teputv_t));
+ /* this will be -1 for scalar else bit index */
+ tepvp->nbi = (!np->n_isavec) ? -1 : bi;
+ tepvp->np = np;
+ /* index from all vpi_ added drivers of the one being driven */
+ tepvp->di = npp->obnum;
+ /* assume non handle returning mode */
+ tepvp->evnt_hp = NULL;
+ /* drivers always 1 bit - i.e. for vector will only set low bit */
+ /* always allocate 8 byte unpacked */
+ tepvp->putv_wp = (word32 *) __my_malloc(2*WRDBYTES); 
+ if (np->n_stren)
+  {
+  /* copy the 1 low bit */
+   memcpy(tepvp->putv_wp, xsp->ap, 1);
+  }
+ else
+  {
+   /* this is 1 bit but still need the 8 byte unpacked */
+   /* need to access just the low bit */
+   tepvp->putv_wp[0] = (xsp->ap[0] & 1L);
+   tepvp->putv_wp[1] = (xsp->bp[0] & 1L);
+  }  
+ __tevtab[tevpi].tu.teputvp = tepvp;
+ /* schedule event */
+ /* case 1: schedule and add to list */
+ /* SJM 09/05/99 - was only adding to pound 0 at time 0 - WRONG */
+ if (ticksdel == 0ULL)
+  {
+   if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
+   else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
+  }
+ else __insert_event(tevpi);
+
+ /* build the dl tev lst */
+ if (__dltevfreelst != NULL)
+  { dlp = __dltevfreelst; __dltevfreelst = __dltevfreelst->terp; }
+ else dlp = (struct dltevlst_t *) __my_malloc(sizeof(struct dltevlst_t)); 
+ dlp->tevpi = tevpi;
+
+ /* insert at front of list */
+ if (ins_after_dlp == NULL)  
+  {
+   dlp2 = vpidrvp->putv_drv_tedlst[evi];
+   dlp->terp = dlp2;
+   if (dlp2 != NULL) dlp2->telp = dlp;
+   dlp->telp = NULL;
+   vpidrvp->putv_drv_tedlst[evi] = dlp;
+  }
+ /* insert after */
+ else
+  {  
+   dlp->terp = ins_after_dlp->terp; 
+   if (dlp->terp != NULL) dlp->terp->telp = dlp;
+   ins_after_dlp->terp = dlp;
+   dlp->telp = ins_after_dlp;
+  }
+ return(tevpi);
+}
+
+/*
+ * TIME PROCESSING ROUTINES
+ */
+
+/*
+ * get current time
+ */
+extern void vpi_get_time(vpiHandle object, p_vpi_time time_p)
+{
+ struct h_t *hp; 
+ struct mod_t *mdp;
+
+ if (__run_state != SS_SIM) { __sim_notbegun_err("vpi_get_time"); return; } 
+ hp = (struct h_t *) object;
+ if (hp != NULL) if (!__validate_handle("vpi_get_time", hp)) return;
+ if (!__validate_time_type("vpi_get_time", time_p->type)) return;
+
+ if (hp != NULL) mdp = hp->hin_itp->itip->imsym->el.emdp; else mdp = NULL;  
+ __set_vpi_time(time_p, &__simtime, time_p->type, mdp); 
+}
+
+/*
+ * VPI I/O ROUTINES
+ */
+
+/*
+ * open an mcd channel
+ *
+ * SJM 09/22/03 - LRM does not allow open file descriptor except in HDL
+ * but can open mcd channel - if fd opened in HDL, PLI routines can use
+ */
+extern PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filename)
+{
+ char *chp;
+
+ chp = __pv_stralloc(filename);
+ return(__mc1_fopen(chp, strlen(chp), TRUE));
+}
+
+/*
+ * close an mcd channel 
+ */
+extern PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd)
+{
+ if ((mcd & FIO_MSB) != 0)
+  {
+   return(__fd_do_fclose(mcd & ~FIO_FD));
+  }
+ return(__close_mcd(mcd, TRUE));
+}
+
+/*
+ * get the name of a channel descriptor (use first if more on)
+ */
+extern PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd)
+{
+ register int32 i;
+ int32 fd;
+
+ if ((mcd & FIO_MSB) != 0)
+  {
+   fd = mcd & ~(FIO_FD);
+   /* AIV 06/27/05 - fd cannot be greater than max file size */
+   if (fd >= MY_FOPEN_MAX || __fio_fdtab[fd] == NULL) return(NULL);
+   else return(__fio_fdtab[fd]->fd_name);
+  }
+ for (i = 2; i < 31; i++)
+  {
+   if (((mcd >> i) & 1L) == 0L) continue;
+   if (__mulchan_tab[i].mc_s == NULL)
+    {
+     __vpi_err(1894, vpiError,
+      "vpi_mcd_name bit %d on for channel that is unused", i + 1);
+     return(NULL);
+    }
+   return(__mulchan_tab[i].mc_fnam);
+  }
+ __vpi_err(1898, vpiError,
+  "vpi_mcd_name passed empty (0) multi-channel descriptor");
+ return(NULL);
+}
+
+/*
+ * printf to multi-channel descriptor - modern VPI form
+ *
+ * notice here mcd is word32 in in tf_ routines it is int32 by standard
+ * but functions almost same - returns value for last if many
+ */
+/*VARARGS*/
+extern PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *format, ...)
+{
+ va_list va, va2;
+ register int32 i;
+ int32 fd;
+ PLI_INT32 numch_prtfed = 0;
+
+ if ((mcd & FIO_MSB) != 0)
+  {
+   fd = mcd & ~(FIO_FD);
+   va_start(va, format);
+   /* AIV 06/27/05 - fd cannot be greater than max file size */
+   if (fd >= MY_FOPEN_MAX || __fio_fdtab[fd] == NULL) 
+    {
+     numch_prtfed = -1;
+    }
+   else
+    {
+     numch_prtfed = vfprintf(__fio_fdtab[fd]->fd_s, format, va);
+    }
+   va_end(va);
+   return(numch_prtfed);
+  }
+
+ /* SJM 03/26/00 - mcd 1 (bit 0) know both stdout and std log if open */
+ /* may be other mcd bits on (files open) too */
+ if ((mcd & 1) != 0)
+  {
+   va_start(va, format);
+   va_start(va2, format);
+   numch_prtfed = vprintf(format, va);
+   if (__log_s != NULL) vfprintf(__log_s, format, va2);
+   va_end(va);
+   va_end(va2);
+  }
+
+ /* mcd's may require writing to lots of files */
+ for (i = 1; i < 31; i++) 
+  {
+   if (((mcd >> i) & 1L) != 0L)
+    { 
+     if (__mulchan_tab[i].mc_s == NULL)
+      {
+       __vpi_err(2010, vpiWarning,
+        "vpi_mcd_printf: multi-channel descriptor bit %d on, but file not open",
+        i + 1);
+       numch_prtfed = -1;
+      }
+     /* using last since will always be same */
+     else
+      {
+       /* SJM 10/13/99 - ansii std says varargs not usable after vfprintf */
+       va_start(va, format);
+       numch_prtfed = vfprintf(__mulchan_tab[i].mc_s, format, va);
+       va_end(va);
+      }
+    }
+  }
+ if (((mcd >> 31) & 1) != 0)
+  {
+   __vpi_err(2020, vpiWarning,
+    "vpi_mcd_printf: multi-channel descriptor bit 31 on but file not open - unusable because reserved for new Verilog 2000 file I/O");
+  }
+ return(numch_prtfed);
+}
+
+/*
+ * formatted print to both standard output and log file (if open) 
+ *
+ * modern but almost same as io (tf_) form - code no larger to just duplicated 
+ * because of var args, return number of printed chars following ansi  
+ */
+/*VARARGS*/
+extern PLI_INT32 vpi_printf(PLI_BYTE8 *format, ...)
+{
+ va_list va, va2;
+ PLI_INT32 num_prtfed = 0;
+
+ va_start(va, format);
+ va_start(va2, format);
+ num_prtfed = vprintf(format, va);
+ if (__log_s != NULL) vfprintf(__log_s, format, va2);
+ va_end(va);
+ va_end(va2);
+ return(num_prtfed);
+}
+
+/*
+ * var args vpi_ printf routine
+ *
+ * this is vpi printf variant (goes to stdio and log file) where user
+ * has called va_start(ap) before and must call va_end(ap) after
+ *
+ * this must format to string so use giant (16k for now) buffer because
+ * can't effect varargs since caller started
+ */
+extern int32 vpi_vprintf(char *format, va_list ap)
+{
+ int32 num_prtfed;
+ char buf[RDBUFSIZ];
+
+ num_prtfed = vsnprintf(buf, RDBUFSIZ, format, ap);
+
+ fputs(buf, stdout);
+ if (__log_s != NULL) fputs(buf, __log_s);
+ return(num_prtfed);
+}
+
+/*
+ * var args vpi_ mcd_printf routine (can handle either file desc or mcd)
+ *
+ * this is vpi printf variant (goes to stdio and log file) where user
+ * has called va_start(ap) before and must call va_end(ap) after
+ *
+ * must print to string buffer since do not have
+ */
+extern PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format,
+ va_list ap)
+{
+ char buf[RDBUFSIZ];
+ register int32 i;
+ int32 fd;
+ PLI_INT32 numch_prtfed = 0;
+
+ if ((mcd & FIO_MSB) != 0)
+  {
+   fd = mcd & ~(FIO_FD);
+   /* AIV 06/27/05 - fd cannot be greater than max file size */
+   if (fd >= MY_FOPEN_MAX || __fio_fdtab[fd] == NULL) 
+    {
+     numch_prtfed = -1;
+    }
+   else
+    {
+     numch_prtfed = vfprintf(__fio_fdtab[fd]->fd_s, format, ap);
+    }
+   return(numch_prtfed);
+  }
+
+ /* assume at least one mcd or fd open */
+ numch_prtfed = vsnprintf(buf, RDBUFSIZ, format, ap);
+
+ /* SJM 03/26/00 - mcd 1 (bit 0) know both stdout and std log if open */
+ /* may be other mcd bits on (files open) too */
+ if ((mcd & 1) != 0)
+  {
+   fputs(buf, stdout);
+   if (__log_s != NULL) fputs(buf, __log_s);
+  }
+
+ /* mcd's may require writing to lots of files */
+ for (i = 1; i < 31; i++) 
+  {
+   if (((mcd >> i) & 1L) != 0L)
+    { 
+     if (__mulchan_tab[i].mc_s == NULL)
+      {
+       __vpi_err(1896, vpiError,
+        "vpi_mcd_printf: multi-channel descriptor bit %d on, but file not open",
+        i + 1);
+       numch_prtfed = -1;
+      }
+     /* using last since will always be same */
+     else fputs(buf, __mulchan_tab[i].mc_s);
+    }
+  }
+ if (((mcd >> 31) & 1) != 0)
+  {
+   __vpi_err(1896, vpiError,
+    "vpi_mcd_vprintf: multi-channel descriptor bit 31 on but file not open - unusable because reserved for new Verilog 2000 file I/O");
+  }
+ return(numch_prtfed);
+}
+
+/*
+ * flush std out and log file
+ *
+ * WRITEME
+ */
+extern PLI_INT32 vpi_flush(void)
+{
+ fflush(stdout);
+ if (__log_s != NULL) fflush(__log_s);
+ return(0);
+}
+
+extern PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd)
+{
+ register int32 i;
+ int32 fd;
+
+ if ((mcd & FIO_MSB) != 0)
+  {
+   fd = mcd & ~(FIO_FD);
+   /* know fd in range but if not open error */ 
+   /* AIV 06/27/05 - fd cannot be greater than max file size */
+   if (fd >= MY_FOPEN_MAX || __fio_fdtab[fd] == NULL) 
+    {
+     __vpi_err(1896, vpiError,
+      "vpi_mcd_vprintf: new 2001 style file descriptor %d - file not open",
+      fd);
+     return(1);
+    }
+      
+   fflush(__fio_fdtab[fd]->fd_s);
+   return(0);
+  } 
+
+ /* SJM 09/09/03 - bit 31 now not used for mcds */   
+ for (i = 1; i < 30; i++)
+  {
+   if (((mcd >> i) & 1L) != 0L)
+    {
+     if (__mulchan_tab[i].mc_s == NULL)
+      {
+       __vpi_err(2010, vpiWarning,
+        "multi-channel descriptor bit %d on, but file not open", i);
+      }
+     else fflush(__mulchan_tab[i].mc_s);
+    }
+  }
+ return(0);
+}
+
+/*
+ * NEW 2001 ROUTINES TO GET AND PUT DATA
+ */
+
+/*
+ * get and put data for $save/$restart
+ * 
+ * get/put user data for XL/NC save/restart but not supported since using
+ * OS process image save mechanism much better and no need to explicitly
+ * save anything
+ */
+extern PLI_INT32 vpi_get_data(PLI_INT32 id, PLI_BYTE8 *dataLoc,
+ PLI_INT32 numOfBytes)
+{
+ __vpi_err(1801, vpiError,
+  "new P1364 2001 vpi_get_data routine unsupported because $save/$restart not implemented - use OS save/restart");
+ return(0);
+}
+
+extern PLI_INT32 vpi_put_data(PLI_INT32 id, PLI_BYTE8 *dataLoc,
+ PLI_INT32 numOfBytes)
+{
+ __vpi_err(1801, vpiError,
+  "new P1364 2001 vpi_put_data routine unsupported because $save/$restart not implemented - use OS save/restart");
+ return(0);
+}
+
+/*
+ * get/put data associated with most recent user sys task or function call
+ *
+ * SJM 04/15/04 - add vpi save/get user data routines since PLI 1.0 deprecated 
+ */
+extern void *vpi_get_userdata(vpiHandle obj)
+{
+ register struct h_t *hp;
+ register struct hrec_t *hrp;
+ struct tskcall_t *tkcp;
+
+ /* notice can't get or put user data in compile tf cb - need elab. n.l. */
+ if (__run_state != SS_RESET && __run_state != SS_SIM)
+  {
+   __sim_notbegun_err("vpi_get_userdata");
+   return(NULL);
+  } 
+
+ hp = (struct h_t *) obj;
+ hrp = hp->hrec;
+ if (hrp->htyp == vpiSysFuncCall)
+  {
+   return(hrp->hu.hxp->lu.x->szu.vpi_sysf_datap);
+  }
+ else if (hrp->htyp == vpiSysTaskCall)
+  {
+   tkcp = &(hrp->hu.hstp->st.stkc);
+   return(tkcp->tkcaux.vpi_syst_datap);
+  }
+ __vpi_err(1839, vpiError,
+  "vpi_get_userdata argument %s illegal - must be vpiSysFuncCall or vpiSysTaskCall", 
+  __to_vpionam(__wrks1, hrp->htyp));
+ return(NULL);
+}
+
+extern PLI_INT32 vpi_put_userdata (vpiHandle obj, void *userdata) 
+{
+ register struct h_t *hp;
+ register struct hrec_t *hrp;
+ struct tskcall_t *tkcp;
+
+ /* notice can't get or put user data in compile tf cb - need elab. n.l. */
+ if (__run_state != SS_RESET && __run_state != SS_SIM)
+  {
+   __sim_notbegun_err("vpi_put_userdata");
+   return(0);
+  } 
+
+ hp = (struct h_t *) obj;
+ hrp = hp->hrec;
+ if (hrp->htyp == vpiSysFuncCall)
+  {
+   hrp->hu.hxp->lu.x->szu.vpi_sysf_datap = userdata;
+   return(1);
+  }
+ else if (hrp->htyp == vpiSysTaskCall)
+  {
+   tkcp = &(hrp->hu.hstp->st.stkc);
+   tkcp->tkcaux.vpi_syst_datap = userdata;
+   return(1);
+  }
+ __vpi_err(1839, vpiError,
+  "vpi_put_userdata first argument %s illegal - must be vpiSysFuncCall or vpiSysTaskCall", 
+  __to_vpionam(__wrks1, hrp->htyp));
+ return(0);
+}
+
+/* 
+ * VPI UTLITY ROUTINES
+ */
+
+/*
+ * compare two handle to determine if same object
+ * (i.e. same object in same itree instance)
+ * maybe better way than to compare all fields except links for freeing
+ */
+extern PLI_INT32 vpi_compare_objects(vpiHandle object1, vpiHandle object2)
+{
+ register struct h_t *hp1, *hp2;
+ register struct hrec_t *hrp1, *hrp2;
+ int32 biti;
+
+ hp1 = (struct h_t *) object1;
+ if (!__validate_handle("vpi_compare_objects (first)", hp1)) return(0);
+ hrp1 = hp1->hrec;
+ hp2 = (struct h_t *) object2;
+ if (!__validate_handle("vpi_compare_objects (second)", hp2)) return(0);
+ hrp2 = hp2->hrec;
+
+ /* types of handles must be same in same itre loc or can't compare equal */
+ if (hrp1->htyp != hrp2->htyp || hrp1->htyp2 != hrp2->htyp2) return(0);
+ if (hp1->hin_itp != hp2->hin_itp || hrp1->hin_tskp != hrp2->hin_tskp)
+  return(0);
+
+ /* only tricky part is for bit handles - bith ndx and expr can match */
+ switch (hrp1->htyp) {
+  case vpiNetBit: case vpiRegBit: case vpiVarSelect: case vpiMemoryWord:
+  /* for param array words only bith ndx form */
+  case vpiParamArrayWord:
+   if (hrp1->bith_ndx && hrp2->bith_ndx)
+    {
+     if (hrp1->hu.hanyp != hrp2->hu.hanyp) return(0);
+     if (hrp1->hi == hrp2->hi) return(1);
+     return(0);
+    }
+   /* if both expressions must be identical */ 
+   if (!hrp1->bith_ndx && !hrp2->bith_ndx)
+    {
+     if (hrp1->hu.hanyp != hrp2->hu.hanyp) return(0);
+     if (hrp1->hu.hxp == hrp2->hu.hxp) return(1);
+     return(0);
+    }
+   /* one expr. one not - only match if constant - can not compare hanyp */
+   if (hrp1->bith_ndx)
+    {
+     if (hrp1->hu.hnp != hrp2->hu.hxp->lu.sy->el.enp) return(0L);
+     /* if non constant mixed form never same */
+     if (!__expr_is_vpiconst(hrp2->hu.hxp->ru.x)) return(0);
+     __push_itstk(hp2->hin_itp);
+     biti = __comp_ndx(hrp2->hu.hxp->lu.sy->el.enp, hrp2->hu.hxp->ru.x);
+     __pop_itstk();
+     /* out of range can never match bith ndx form */
+     if (biti == -1) return(0);
+     if (hrp1->hi == biti) return(1); 
+     return(0);
+    }
+   if (hrp2->bith_ndx)
+    {
+     if (hrp2->hu.hnp != hrp1->hu.hxp->lu.sy->el.enp) return(0);
+     /* if non constant mixed form never same */
+     if (!__expr_is_vpiconst(hrp1->hu.hxp->ru.x)) return(0);
+     __push_itstk(hp1->hin_itp);
+     biti = __comp_ndx(hrp1->hu.hxp->lu.sy->el.enp, hrp1->hu.hxp->ru.x);
+     __pop_itstk();
+     if (biti == -1) return(0);
+     if (hrp1->hi == biti) return(1); 
+     return(0);
+    }
+ }
+ if (hrp1->hu.hanyp != hrp2->hu.hanyp) return(0);
+ if (hrp1->hi != hrp2->hi) return(0);
+ return(1);
+}
+
+/*
+ * check to see if last vpi routine returned an error
+ *
+ * always needs to be checked even if routine worked for warnings
+ * returns T on error
+ */
+extern int32 vpi_chk_error(p_vpi_error_info error_info_p)
+{
+ if (__last_eip == NULL) return(FALSE);
+ if (error_info_p == NULL) return(TRUE);
+ *error_info_p = __wrk_einfo;
+ return(TRUE);
+}
+
+/*
+ * ROUTINES TO FREE HANDLES
+ */
+
+/*
+ * free a handle and associated storage - return F on no free else T
+ *
+ * for iterator frees entire handle table
+ */
+extern PLI_INT32 vpi_free_object(vpiHandle object)
+{
+ register struct h_t *hp;
+ register struct hrec_t *hrp;
+
+ hp = (struct h_t *) object;
+ if (!__validate_handle("vpi_free_object", hp)) return(0);
+ hrp = hp->hrec;
+ if (hrp->in_iter)
+  {
+   __vpi_err(2019, vpiWarning,
+    "component of iterator can not be freed - use vpi_copy_object to save if needed");
+   return(FALSE);
+  }
+ if (hrp->htyp == vpiIterator) { __free_iterator(object); return(TRUE); }
+ if (hrp->htyp == vpiCallback || hrp->htyp == vpiUserSystf)
+  {
+   __vpi_err(2020, vpiWarning, "unable to free %s object - can not be freed",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+   return(FALSE);
+  }
+ /* for tab form scheduled entire vector must free ev. ptr table */
+ if (hrp->bith_ndx && hrp->htyp == vpiSchedEvent)
+  {
+   struct net_t *np;
+
+   np = hrp->hu.hevrec->evnp;
+   __my_free((char *) hrp->hu.hevrec->evndxtab, np->nwid*sizeof(i_tev_ndx));
+   __my_free((char *) hrp->hu.hevrec, sizeof(struct schdev_t));
+   hrp->hu.hevrec = NULL;
+  }
+ /* maybe free expr. */
+ if (hrp->free_xpr) __free_xtree(hrp->hu.hxp);
+ /* BEWARE - to free handle can only link on free list since may be in */
+ /* large iterator table */ 
+ __free_hp(hp);
+ return(TRUE);
+}
+
+/*
+ * free an iterator contents and handle
+ *
+ * only way to free in iterator handle and called automaticaly
+ * when iterator done or error
+ * internal routine always called with iterator handle
+ *
+ * FIXME - need to change to 8 bytes handle with rest in fixed type memory
+ *
+ * transitional algorithm - normally just turn off in_iter so user
+ * can free later if wanted if auto free option free handles and iter
+ * array (with real free)
+ */
+extern void __free_iterator(vpiHandle ihref)
+{
+ register int32 hi;
+ register struct h_t *hp, *hp2;
+ register struct hrec_t *hrp;
+ struct pviter_t *iterp;
+
+ hp = (struct h_t *) ihref;
+ hrp = hp->hrec;
+ /* DBG remove --- */
+ if (hrp->htyp != vpiIterator) __vpi_terr(__FILE__, __LINE__);
+ /* --- */
+ /* mark handles as separately freeable if user wants to later */
+ iterp = hrp->hu.hiterp;
+ /* must look for and free any expressions */
+ for (hi = 0; hi < iterp->numhs; hi++)
+  {
+   hp2 = &(iterp->scanhtab[hi]);
+   /* SJM 10/11/99 - must not free expr. since not freeing handle */
+   /* *** if (hp2->hrec->free_xpr) __free_xtree(hp2->hrec->hu.hxp); *** */
+   hp2->hrec->in_iter = FALSE;
+  }
+ /* SJM 03/16/00 - never free handles passed to user or does not match XL */
+
+ /* but free the small iterator record - stops further accessing of iter */
+ /* needed so handle magic number will fail */
+ __my_free((char *) iterp, sizeof(struct pviter_t));
+ __free_hp(hp);
+}
+
+/*
+ * free handle contents hp
+ *
+ * caller must have validated hp before calling this routine
+ * caller must also free hxp if needed
+ *
+ * notice this works because if freeing handle from iterator table puts
+ * all or some on free list for reuse
+ */
+extern void __free_hp(struct h_t *hp) 
+{
+ register struct hrec_t *hrp; 
+
+ hrp = hp->hrec;
+ /* zero so magic number test fails and link hrec onto hrec free list */
+ memset(hrp, 0, sizeof(struct hrec_t));
+ hrp->hu.hfreenxt = __vpi_hrecfree_hdr;
+ __vpi_hrecfree_hdr = hrp; 
+
+ /* zero and link hrp onto hp free list */
+ memset(hp, 0, sizeof(struct h_t));
+ hp->hin_itp = (struct itree_t *) __vpi_hfree_hdr;
+ __vpi_hfree_hdr = hp;
+}
+
+/*
+ * copy a handle and associated storage
+ * can not copy iterator (must recreate)
+ */
+extern vpiHandle vpi_copy_object(vpiHandle object)
+{
+ register struct h_t *hp, *hp2;
+ register struct hrec_t *hrp2;
+
+ /* SJM 08/08/99 - vpi scan may return nil and free so copy of nil is nil */
+ if (object == NULL) return(NULL);
+
+ hp = (struct h_t *) object;
+ if (!__validate_handle("vpi_copy_object", hp)) return(0);
+ if (hp->hrec->htyp == vpiIterator)
+  {
+   __vpi_err(1842, vpiError,
+    "iterator handle can not be copied - call vpi_iterate to create same contents handle");
+   return(NULL);
+  }
+ hp2 = (struct h_t *) __mk_handle(hp->hrec->htyp, (void *) NULL, NULL, NULL);
+ hp2->hin_itp = hp->hin_itp; 
+ hrp2 = hp2->hrec;
+ *(hrp2) = *(hp->hrec);
+ /* if copy from iterator, no longer in iterator */
+ hrp2->in_iter = FALSE; 
+ if (hrp2->free_xpr)
+  {
+   hrp2->hu.hxp = __sim_copy_expr(hp->hrec->hu.hxp);
+  }
+ return((vpiHandle) hp2);
+}
+
+/*
+ * ROUTINES TO IMPLEMENT SIM CONTROL MECHANISM
+ */
+
+/*
+ * send information from user application back to simulator
+ *
+ * main use is elminating need for tf_dofinish and tf_dostop but also for
+ * cver specific extensions 
+ */
+/*VARARGS*/
+extern PLI_INT32 vpi_control(PLI_INT32 operation, ...)
+{
+ int32 sav_err_cnt;
+ va_list va;
+ PLI_INT32 retv;
+ int32 diag_level, stop_val, reset_val;
+ vpiHandle scopobj, cbobj;
+ char *buf;
+
+ /* assume success */
+ retv = TRUE;
+ va_start(va, operation);
+ switch (operation) {
+  case vpiStop:
+   diag_level = va_arg(va, int32);
+   retv = __do_vpi_stop(diag_level);
+   break;
+  case vpiFinish:
+   diag_level = va_arg(va, int32);
+   __pli_dofinish(diag_level, "vpi_control");
+   break;
+  case vpiReset:
+   stop_val = va_arg(va, int32); 
+   reset_val = va_arg(va, int32);
+   diag_level = va_arg(va, int32);
+   /* this never returns */
+   __do_vpi_reset(stop_val, reset_val, diag_level);
+   break;
+  case vpiSetInteractiveScope:
+   scopobj = va_arg(va, vpiHandle);
+   retv = do_vpi_iact_scopchg(scopobj);
+   break;
+  case vpiDumpVars:
+   if (!__can_exec)
+    {
+     __vpi_err(1900, vpiError,
+      "vpi_control vpiDumpVars operation illegal - only callable during simulation");
+     retv = FALSE; 
+     break;
+    }
+   sav_err_cnt = __pv_err_cnt;
+   __exec_dumpvars(NULL);
+   if (__pv_err_cnt > sav_err_cnt) retv = FALSE; else retv = TRUE;
+   break;
+  case vpiInsertSource:
+   /* this is only callable from `language when `endlanguage hit */
+   if (__match_cdir(__langstr, "`endlanguage") == NULL)
+    {
+     __vpi_err(1888, vpiError,
+      "vpi_control vpiInsertSource operation illegal - not called at end of `language section");
+     retv = FALSE; 
+     break;
+    }
+   buf = va_arg(va, char *);
+   /* since outside any module - this does module source reading */
+   retv = __exec_rdinserted_src(buf);
+   break;
+  case vpiFlushLog:
+   /* flush internal files */
+   if (__dv_fd != -1) __my_dv_flush();
+   if (__log_s != NULL) fflush(__log_s);
+   if (__tr_s != NULL) fflush(__tr_s);
+   break; 
+  case vpiDisableCb:
+   cbobj = va_arg(va, vpiHandle);
+   retv = do_vpi_cb_onoff(cbobj, FALSE);
+   break;
+  case vpiEnableCb:
+   cbobj = va_arg(va, vpiHandle);
+   retv = do_vpi_cb_onoff(cbobj, TRUE);
+   break;
+  default:
+   __vpi_err(1888, vpiError,
+    "vpi_control first operation argument value %d illegal", operation);
+   retv = FALSE;
+ }
+ va_end(va);
+ return(retv);
+}
+
+/*
+ * change interactive scope from vpi_ user code
+ *
+ * notice need to call call back on scope change although may never
+ * actually enter interactive code
+ */
+static int32 do_vpi_iact_scopchg(vpiHandle newscopobj)
+{
+ register struct h_t *hp;
+
+ hp = (struct h_t *) newscopobj;
+ if (!__validate_handle("vpi_control vpiSetInteractiveScope operation", hp))
+  return(FALSE);
+
+ switch (hp->hrec->htyp) {
+  case vpiModule:
+   __scope_ptr = hp->hin_itp;
+   __scope_tskp = NULL;
+   break;
+  case vpiTask: case vpiFunction: case vpiNamedBegin: case vpiNamedFork:
+   __scope_ptr = hp->hin_itp;
+   __scope_tskp = hp->hrec->hin_tskp;
+   break;
+  default:
+   __vpi_err(1870, vpiError,
+    "vpi_control vpiSetInteractiveScope argument not scope handle - %s illegal",
+    __to_vpionam(__wrks1, hp->hrec->htyp));
+   return(FALSE);
+  }
+
+ /* because not really entering interactive mode no db line change */
+ if (__tfrec_hdr != NULL) __call_misctfs_scope();
+ if (__have_vpi_actions) __vpi_iactscopechg_trycall();
+ return(TRUE);
+}
+
+/*
+ * some error message output routines that need vpi_ mechanism
+ */
+extern void __emit_vpi_noiact_warn(void)
+{
+ __vpi_err(2029, vpiWarning,
+  "vpi_control vpiStop no effect - interactive environment disabled");
+}
+
+extern void __emit_vpi_iniact_warn(void)
+{
+ __vpi_err(2031, vpiWarning,
+  "vpi_control vpiStop no effect - already in interactive debugger");
+}
+
+/*
+ * turn on (enable) or off (disable) call back 
+ *
+ * works for any call back except time related
+ * LOOKATME - maybe should always re-enable on reset
+ */
+static int32 do_vpi_cb_onoff(vpiHandle cbobj, int32 turn_cb_on)
+{
+ register struct dceauxlst_t *dceauxlp;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+ struct cbrec_t *cbp;
+ char s1[RECLEN], s2[RECLEN];
+
+ if (turn_cb_on) strcpy(s1, "vpiEnableCb"); else strcpy(s1, "vpiDisableCb");
+ hp = (struct h_t *) cbobj;
+ sprintf(s2, "vpi_control %s operation", s1); 
+ if (!__validate_handle(s2, hp)) return(FALSE);
+ hrp = hp->hrec;
+ cbp = hrp->hu.hcbp;
+
+ if (hrp->htyp != vpiCallback)
+  {
+   __vpi_err(1832, vpiError,
+    "vpi_control %s operation requires vpiCallback handle - %s illegal",
+    s1,__to_vpionam(__wrks1, hrp->htyp));
+   return(FALSE);
+  }
+
+ switch (cbp->cb_reason) {
+  case cbAtStartOfSimTime: case cbReadWriteSynch: case cbReadOnlySynch: 
+  case cbNextSimTime: case cbAfterDelay: case cbLanguageLine:
+   __vpi_err(1930, vpiError,
+    "vpi_control %s illegal for time related %s call back",
+    s1, __cb_reason_to_nam(__xs, cbp->cb_reason));
+   return(FALSE);
+  default: break;
+ }
+
+ if (turn_cb_on) 
+  {
+   if (!cbp->cb_user_off)
+    {
+     /* SJM 07/26/00 - if call back run with reentry to itself turned off */
+     /* allow enabling so can be re-entered */
+     if (cbp->cb_reason == cbValueChange || cbp->cb_reason == cbForce
+      || cbp->cb_reason == cbRelease)
+      {
+       /* turn on all dce's - temporarily off */
+       for (dceauxlp = cbp->cbdcep; dceauxlp != NULL;
+        dceauxlp = dceauxlp->dclnxt)
+        {
+         dceauxlp->ldcep->dce_off = FALSE;
+        }
+       return(TRUE);
+      }
+     
+     __vpi_err(2033, vpiWarning,
+      "vpi_control %s no effect - attempt to enable already enabled %s call back",
+      s1, __cb_reason_to_nam(__xs, cbp->cb_reason));
+     return(FALSE);
+    }
+  }
+ else 
+  {
+   if (cbp->cb_user_off)
+    {
+     __vpi_err(2033, vpiWarning,
+      "vpi_control %s no effect - attempt to disable already disabled %s call back",
+     s1, __cb_reason_to_nam(__xs, cbp->cb_reason));
+     return(FALSE);
+    }
+  }
+ cbp->cb_user_off = (turn_cb_on) ? FALSE : TRUE;
+
+ /* change on/off state of each dc evetn */
+ /* LOOKATME - what happen with all forms force/release */
+ for (dceauxlp = cbp->cbdcep; dceauxlp != NULL; dceauxlp = dceauxlp->dclnxt)
+  {
+   dceauxlp->ldcep->dce_off = (turn_cb_on) ? FALSE : TRUE;
+  }
+ return(TRUE);
+}
+
+
+/*
+ * ROUTINES TO FREE VPI_ OBJECTS FOR RESET
+ */
+
+/*
+ * reinitialize the vpi_ mechanism
+ *
+ * possible net's putv rec left but driver reinitialized to z elsewhere
+ * do not free handles - DOCUMENT can be large source of memory drain
+ */
+extern void __reinit_vpi(void) 
+{
+ register struct cbrec_t *cbp, *cbp2;
+ int32 save_simstate;
+
+ /* free time related in lists that are not in event queues */ 
+ __rosync_slot = FALSE;
+
+ /* remove time related call backs only */ 
+ for (cbp = __vpi_cbrec_hdr; cbp != NULL;)
+  {
+   cbp2 = cbp->cbnxt;
+   /* only remove scheduled time related or value change related */
+   switch (cbp->cb_reason) {
+    /* remove all time and change cbs but leave all actions */
+    case cbAtStartOfSimTime: case cbReadWriteSynch: case cbReadOnlySynch:
+    case cbNextSimTime: case cbAfterDelay:
+     /* this links out but works because nxt if present always remains */
+     /* using user level routine but before sim has begun (fake sim) */
+     save_simstate = __run_state;
+     __run_state = SS_SIM;
+     if (!vpi_remove_cb((vpiHandle) cbp->cb_cbhp))
+       __vpi_terr(__FILE__, __LINE__);
+     __run_state = save_simstate;
+     break;
+    default:
+     break;
+   }
+   if (cbp2 == NULL) break;
+   cbp = cbp2;
+  }
+}
+
+/*
+ * ROUTINES TO ACCESS INTERNAL INFO
+ */
+
+/*
+ * get version information and set pointers to argv/argc
+ *
+ * this is passed struct - routines fills in ptrs
+ */
+extern PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p)
+{
+ char s1[RECLEN];
+
+ /* only build nested vpi format argv if first time */
+ if (__vpi_argv == NULL) __bld_vpi_argv();
+
+ vlog_info_p->argc = __vpi_argc; 
+ vlog_info_p->argv = __vpi_argv; 
+
+ sprintf(s1, "%s%s of %s (%s).\n", __vers, __vers2, __ofdt, __platform);
+ vlog_info_p->product = __pv_stralloc("Cver Verilog Simulator");
+ vlog_info_p->version = __pv_stralloc(s1);
+ return(TRUE);
+}
+
+/*
+ * undocumented (to users) debug routine for showing contents of handle
+ *
+ * LOOKATME - maybe should dump more information for some object types 
+ * LOOKATME - not portable because of addr cast
+ */
+extern int32 __vpi_show_object(vpiHandle obj)
+{
+ int32 bad_inst, bad_tsk, first_time, ttyp, tryget_name;
+ struct h_t *hp;
+ struct hrec_t *hrp;
+ char *chp, s1[RECLEN], s2[RECLEN]; 
+
+ __my_fprintf(stdout, ">>> showing vpi_ object:\n");
+ hp = (struct h_t *) obj;
+
+ if (!__chk_showobj(hp, &(bad_inst), &(bad_tsk))) return(0);
+ hrp = hp->hrec;
+
+ tryget_name = TRUE;
+ if (!__validate_otyp(hrp->htyp))
+  {
+   __my_fprintf(stdout,
+    "**object bad: object type %d illegal - showing anyway\n", hrp->htyp);
+   tryget_name = FALSE;
+  }
+ else
+  {
+   __my_fprintf(stdout, "Object type: %s (addr %lx)",
+    __to_vpionam(s1, hrp->htyp), (word32) hp);
+  }
+ if (hrp->htyp2 != 0) 
+  {
+   if (!__validate_otyp(hrp->htyp2))
+    {
+     __my_fprintf(stdout,
+      "\n**object bad: secondary type %d illegal\n", hrp->htyp2);
+     tryget_name = FALSE;
+    }
+   else
+    {
+     __my_fprintf(stdout, " (secondary type: %s)",
+      __to_vpionam(s1, hrp->htyp2));
+    }
+  }
+ if (!bad_inst && !bad_tsk)
+  {
+   if (hp->hin_itp == NULL)
+    {
+     __my_fprintf(stdout, " **no associated instance**");
+    }
+   else
+    {
+     __my_fprintf(stdout, " in %s", __msg_blditree(s1, hp->hin_itp,
+      hrp->hin_tskp));
+     if (hrp->hin_tskp != NULL)
+      {
+       ttyp = __to_vpi_tasktyp(hrp->hin_tskp->tsktyp); 
+       __my_fprintf(stdout, " (%s)\n", __to_vpionam(s1, ttyp));
+      }
+    }
+  }
+ else if (!bad_inst && bad_tsk)
+  {
+   if (hp->hin_itp != NULL)
+    {
+     __my_fprintf(stdout, " in %s (**task/func bad**)",
+      __msg2_blditree(s1, hp->hin_itp));
+    }
+   tryget_name = FALSE;
+  }
+ else if (bad_inst && !bad_tsk)
+  {
+   ttyp = __to_vpi_tasktyp(hrp->hin_tskp->tsktyp); 
+   __my_fprintf(stdout, " **bad instance** but in %s %s",
+    __to_vpionam(s1, ttyp), hrp->hin_tskp->tsksyp->synam);
+   tryget_name = FALSE;
+  }
+ else
+  {
+   __my_fprintf(stdout, " **bad instance and bad task**");
+   tryget_name = FALSE;
+  }
+
+ /* LOOKATME - maybe should try to get def name if can */
+ if (tryget_name)
+  {
+   __acc_vpi_erroff = TRUE;
+   /* this access error vpi_ error info and turns off vpi error cbs */  
+   /* for objects without names, expect fail here */
+   chp = vpi_get_str(vpiName, obj);
+   if (chp != NULL && !__my_vpi_chk_error())
+    {
+     __my_fprintf(stdout, " name=%s", chp); 
+    }
+  }
+ __my_fprintf(stdout, "\n");
+
+ /* build the telltales */
+ strcpy(s2, "  [");
+ first_time = TRUE;
+ if (hrp->hi != -1)
+  {
+   sprintf(s1, "index=%d", hrp->hi);
+   strcat(s2, s1);
+   if (first_time) first_time = FALSE; 
+  }
+ if (hrp->in_iter)
+  {
+   if (!first_time) strcat(s2, ", "); else first_time = FALSE;
+   strcat(s2, "in interator");
+  }
+ if (hrp->free_xpr)
+  {
+   if (!first_time) strcat(s2, ", "); else first_time = FALSE;
+   strcat(s2, "Created object");
+  }
+ if (hrp->htyp == vpiSchedEvent || hrp->htyp == vpiSchedBitEvent)
+  {
+   if (!first_time) strcat(s2, ", "); else first_time = FALSE;
+   sprintf(s1, "Schedule event done=%d", hrp->evnt_done);
+   strcat(s2, s1);
+  }
+ if (hrp->bith_ndx)
+  {
+   if (!first_time) strcat(s2, ", "); else first_time = FALSE;
+   strcat(s2, "Variable index");
+  }
+
+ if (!first_time) __my_fprintf(stdout, "%s]\n", s2); 
+
+ /* set globals for user to look at in case debugging turned on */
+ __cur_vpi_inst = hp;  
+ __cur_vpi_obj = hrp;
+ return(1);
+}
+
+/*
+ * show object check handle
+ */
+extern int32 __chk_showobj(struct h_t *hp, int32 *bad_inst, int32 *bad_task)
+{
+ struct hrec_t *hrp; 
+
+ /* if low value bad since ptr */
+ /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
+ if (hp == NULL || ((word32) hp) < 256)
+  {
+   __my_fprintf(stdout, 
+    "**object bad: address (%p) null or illegal low address\n", hp);
+   return(FALSE);
+  }
+ hrp = hp->hrec;
+ /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
+ if (hrp == NULL || ((word32) hrp) < 256)
+  {
+   __my_fprintf(stdout,
+    "**object bad: net list pointer (%p) null or illegal low address\n", hrp);
+   return(FALSE);
+  }
+ if (hrp->h_magic != PVH_MAGIC)
+  {
+   __my_fprintf(stdout,
+    "**object bad: illegal magic number (%x) - showing anyway\n",
+    hrp->h_magic);
+  }
+ *bad_inst = FALSE;
+ /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
+ if (hp->hin_itp != NULL && ((word32) hp->hin_itp) < 256)
+  {
+   __my_fprintf(stdout, 
+    "**object bad: instance address (%p) probably illegal\n", hp->hin_itp);
+   *bad_inst = TRUE;
+  }
+ *bad_task = FALSE;
+ /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
+ if (hrp->hin_tskp != NULL && ((word32) (hrp->hin_tskp)) < 256)
+  {
+   __my_fprintf(stdout, 
+    "**object bad: task/func address (%p) probably illegal\n",
+    hrp->hin_tskp);
+   *bad_task = TRUE;
+  }
+ return(TRUE);
+}
+
+/*
+ * VPI CONSTANT TO NAME CONVERSION ROUTINES
+ */
+
+/* dense table indexed by constant object value */
+/* fast indexing of dense table works because vpi object numbers */
+/* fixed for .o file interchangeabiliy */	 
+
+/* if vpi_user.h official LRM constant values change, must change this */
+/* constant in table so can use debugging code to check for dense order */
+static struct onamvpi_t onames_vpi[] = {
+ /* notice object types can also sometimes be access methods */
+ { "**unused-obj-const**", 0 }, 
+ { "vpiAlways", vpiAlways },
+ { "vpiAssignStmt", vpiAssignStmt },
+ { "vpiAssignment", vpiAssignment },
+ { "vpiBegin", vpiBegin },
+ { "vpiCase", vpiCase },
+ { "vpiCaseItem", vpiCaseItem },
+ { "vpiConstant", vpiConstant },
+ { "vpiContAssign", vpiContAssign },
+ { "vpiDeassign", vpiDeassign },
+ { "vpiDefParam", vpiDefParam },
+ { "vpiDelayControl", vpiDelayControl },
+ { "vpiDisable", vpiDisable },
+ { "vpiEventControl", vpiEventControl },
+ { "vpiEventStmt", vpiEventStmt },
+ { "vpiFor", vpiFor },
+ { "vpiForce", vpiForce },
+ { "vpiForever", vpiForever },
+ { "vpiFork", vpiFork },
+ { "vpiFuncCall", vpiFuncCall },
+ { "vpiFunction", vpiFunction },
+ { "vpiGate", vpiGate },
+ { "vpiIf", vpiIf },
+ { "vpiIfElse", vpiIfElse },
+ { "vpiInitial", vpiInitial },
+ { "vpiIntegerVar", vpiIntegerVar },
+ { "vpiInterModPath", vpiInterModPath },
+ { "vpiIterator", vpiIterator },
+ { "vpiIODecl", vpiIODecl },
+ { "vpiMemory", vpiMemory },
+ { "vpiMemoryWord", vpiMemoryWord },
+ { "vpiModPath", vpiModPath },
+ { "vpiModule", vpiModule },
+ { "vpiNamedBegin", vpiNamedBegin },
+ { "vpiNamedEvent", vpiNamedEvent },
+ { "vpiNamedFork", vpiNamedFork },
+ { "vpiNet", vpiNet },
+ { "vpiNetBit", vpiNetBit },
+ { "vpiNullStmt", vpiNullStmt },
+ { "vpiOperation", vpiOperation },
+ { "vpiParamAssign", vpiParamAssign },
+ { "vpiParameter", vpiParameter },
+ { "vpiPartSelect", vpiPartSelect },
+ { "vpiPathTerm", vpiPathTerm },
+ { "vpiPort", vpiPort },
+ { "vpiPortBit", vpiPortBit },
+ { "vpiPrimTerm", vpiPrimTerm },
+ { "vpiRealVar", vpiRealVar },
+ { "vpiReg", vpiReg },
+ { "vpiRegBit", vpiRegBit },
+ { "vpiRelease", vpiRelease },
+ { "vpiRepeat", vpiRepeat },
+ { "vpiRepeatControl", vpiRepeatControl },
+ { "vpiSchedEvent", vpiSchedEvent },
+ { "vpiSpecParam", vpiSpecParam },
+ { "vpiSwitch", vpiSwitch },
+ { "vpiSysFuncCall", vpiSysFuncCall },
+ { "vpiSysTaskCall", vpiSysTaskCall },
+ { "vpiTableEntry", vpiTableEntry },
+ { "vpiTask", vpiTask },
+ { "vpiTaskCall", vpiTaskCall },
+ { "vpiTchk", vpiTchk },
+ { "vpiTchkTerm", vpiTchkTerm },
+ { "vpiTimeVar", vpiTimeVar },
+ { "vpiTimeQueue", vpiTimeQueue },
+ { "vpiUdp", vpiUdp },
+ { "vpiUdpDefn", vpiUdpDefn },
+ { "vpiUserSystf", vpiUserSystf },
+ { "vpiVarSelect", vpiVarSelect },
+ { "vpiWait", vpiWait },
+ { "vpiWhile", vpiWhile },
+ /* methods */
+ { "vpiCondition", vpiCondition },
+ { "vpiDelay", vpiDelay },
+ { "vpiElseStmt", vpiElseStmt },
+ { "vpiForIncStmt", vpiForIncStmt },
+ { "vpiForInitStmt", vpiForInitStmt },
+ { "vpiHighConn", vpiHighConn },
+ { "vpiLhs", vpiLhs },
+ { "vpiIndex", vpiIndex },
+ { "vpiLeftRange", vpiLeftRange },
+ { "vpiLowConn", vpiLowConn },
+ { "vpiParent", vpiParent },
+ { "vpiRhs", vpiRhs },
+ { "vpiRightRange", vpiRightRange },
+ { "vpiScope", vpiScope },
+ /* notice this is only an iterator or 1-to-1 method */
+ { "vpiSysTfCall", vpiSysTfCall },
+ { "vpiTchkDataTerm", vpiTchkDataTerm },
+ { "vpiTchkNotifier", vpiTchkNotifier },
+ { "vpiTchkRefTerm", vpiTchkRefTerm },
+ /* 1 to many methods */
+ { "vpiArgument", vpiArgument },
+ { "vpiBit", vpiBit },
+ { "vpiDriver", vpiDriver },
+ { "vpiInternalScope", vpiInternalScope },
+ { "vpiLoad", vpiLoad },
+ { "vpiModDataPathIn", vpiModDataPathIn },
+ { "vpiModPathIn", vpiModPathIn },
+ { "vpiModPathOut", vpiModPathOut },
+ { "vpiOperand", vpiOperand },
+ { "vpiPortInst", vpiPortInst },
+ { "vpiProcess", vpiProcess },
+ { "vpiVariables", vpiVariables  },
+ { "vpiUse", vpiUse },
+ /* 1-to-1 or 1 to many methods */
+ { "vpiExpr", vpiExpr },
+ { "vpiPrimitive", vpiPrimitive },
+ { "vpiStmt", vpiStmt },
+
+ /* object types added for Verilog 2000 - some moved from cv vpi inc file */
+ { "vpiAttribute", vpiAttribute },
+ { "vpiBitSelect", vpiBitSelect },
+ { "vpiCallback", vpiCallback },
+ { "vpiDelayTerm", vpiDelayTerm },
+ { "vpiDelayDevice", vpiDelayDevice },
+ { "vpiFrame", vpiFrame },
+ { "vpiGateArray", vpiGateArray },
+ { "vpiModuleArray", vpiModuleArray },
+ { "vpiPrimitiveArray", vpiPrimitiveArray },
+ { "vpiNetArray", vpiNetArray },
+ { "vpiRange", vpiRange },
+ { "vpiRegArray", vpiRegArray },
+ { "vpiSwitchArray", vpiSwitchArray },
+ { "vpiUdpArray", vpiUdpArray },
+ /* methods added for Verilog 2000 - some moved from cv vpi inc file */
+ { "vpiActiveTimeFormat", vpiActiveTimeFormat },
+ { "vpiInTerm", vpiInTerm },
+ { "vpiInstanceArray", vpiInstanceArray },
+ { "vpiLocalDriver", vpiLocalDriver },
+ { "vpiLocalLoad", vpiLocalLoad },
+ { "vpiOutTerm", vpiOutTerm },
+ { "vpiPorts", vpiPorts },
+ { "vpiSimNet", vpiSimNet },
+ { "vpiTaskFunc", vpiTaskFunc },
+ { "vpiContAssignBit", vpiContAssignBit },
+ { "vpiNamedEventArray", vpiNamedEventArray }
+};
+#define NVOTYPS (sizeof(onames_vpi) / sizeof(struct onamvpi_t))
+
+/* added for Cver handles in separate range */
+/* Cver added handles - pending to be added to P1364 */
+/* position must match offset constant in .h file (not alphabetical) */
+static struct onamvpi_t cv_onames_vpi[] = {
+ { "vpiNetDriver", vpiNetDriver },
+ { "vpiNetBitDriver", vpiNetBitDriver },
+ { "vpiSchedBitEvent", vpiSchedBitEvent },
+ { "vpiParamArray", vpiParamArray },
+ { "vpiParamArrayWord", vpiParamArrayWord },
+ { "vpiPoundParam", vpiPoundParam },
+ { "vpiOneOfEachMod", vpiOneOfEachMod }
+};
+#define CV_NVOTYPS (sizeof(cv_onames_vpi) / sizeof(struct onamvpi_t))
+
+
+/*
+ * convert the vpi object constant value to a name 
+ * if out of range returns nil
+ * table dense and starting at 0
+ */
+extern char *__to_vpionam(char *s, word32 vpioval)
+{
+ if (vpioval < 1) goto outofrng;
+ if (vpioval < NVOTYPS)
+  {
+   strcpy(s, onames_vpi[vpioval].vpiobjnam);
+   return(s);
+  }
+ if (vpioval >= CV_START_ONUMS && vpioval < (CV_START_ONUMS + CV_NVOTYPS))
+  {
+   strcpy(s, cv_onames_vpi[vpioval - CV_START_ONUMS].vpiobjnam);
+   return(s);
+  }
+
+outofrng:
+ sprintf(s, "**out of range (%lu)", vpioval);
+ return(s);
+}
+
+/*
+ * return T if object type legal
+ * if out of range returns nil
+ * table dense and starting at 0
+ */
+extern int32 __validate_otyp(word32 vpioval)
+{
+ if (vpioval < 1) return(FALSE);
+ if (vpioval < NVOTYPS) return(TRUE);
+ if (vpioval >= CV_START_ONUMS && vpioval < (CV_START_ONUMS + CV_NVOTYPS))
+  return(TRUE);
+
+ return(FALSE);
+}
+
+/* dense array of vpi properties */
+/* position must match offset constant in .h file */
+static struct pnamvpi_t pnames_vpi[] = {
+ { "**unused-prop-const**", 0 }, 
+ { "vpiType", vpiType },
+ { "vpiName", vpiName },
+ { "vpiFullName", vpiFullName },
+ { "vpiSize", vpiSize },
+ { "vpiFile", vpiFile },
+ { "vpiLineNo", vpiLineNo },
+ /* module properties */
+ { "vpiTopModule", vpiTopModule },
+ { "vpiCellInstance", vpiCellInstance },
+ { "vpiDefName", vpiDefName },
+ { "vpiProtected", vpiProtected },
+ { "vpiTimeUnit", vpiTimeUnit },
+ { "vpiTimePrecision", vpiTimePrecision },
+ { "vpiDefNetType", vpiDefNetType },
+ { "vpiUnconnDrive", vpiUnconnDrive },
+ { "vpiDefFile", vpiDefFile },
+ { "vpiDefLineNo", vpiDefLineNo },
+ /* port and net properties */
+ { "vpiScalar", vpiScalar },
+ { "vpiVector", vpiVector },
+ { "vpiExplictName", vpiExplicitName },
+ { "vpiDirection", vpiDirection },
+ { "vpiConnByName", vpiConnByName },
+ { "vpiNetType", vpiNetType },
+ { "vpiExplicitScalared", vpiExplicitScalared },
+ { "vpiExplicitVectored", vpiExplicitVectored },
+ { "vpiExpanded", vpiExpanded },
+ { "vpiImplicitDecl", vpiImplicitDecl },
+ { "vpiChargeStrength", vpiChargeStrength  },
+ { "vpiArray", vpiArray },
+ { "vpiPortIndex", vpiPortIndex },
+ /* gate and terminal properties */
+ { "vpiTermIndex", vpiTermIndex },
+ { "vpiStrength0", vpiStrength0 },
+ { "vpiStrength1", vpiStrength1 },
+ { "vpiPrimType", vpiPrimType },
+ /* path, path terminal, timing check properties */
+ { "vpiPolarity", vpiPolarity },
+ { "vpiDataPolarity", vpiDataPolarity },
+ { "vpiEdge", vpiEdge },
+ { "vpiPathType", vpiPathType },
+ { "vpiTchkType", vpiTchkType },
+ /* expression properties */
+ { "vpiOpType", vpiOpType },
+ { "vpiConstType", vpiConstType },
+ { "vpiBlocking", vpiBlocking },
+ { "vpiCaseType", vpiCaseType },
+ { "vpiNetDeclAssign", vpiNetDeclAssign },
+ /* system taskfunc properties */
+ { "vpiFuncType", vpiFuncType },
+ { "vpiUserDefn", vpiUserDefn },
+ { "vpiScheduled", vpiScheduled },
+ { "vpiDefDelayMode", vpiDefDelayMode },
+ { "vpiDefDecayTime", vpiDefDecayTime },
+ { "vpiActive", vpiActive },
+ { "vpiAutomatic", vpiAutomatic },
+ { "vpiCell", vpiCell },
+ { "vpiConfig", vpiConfig },
+ { "vpiConstantSelect", vpiConstantSelect },
+ { "vpiDecompile", vpiDecompile },
+ { "vpiDefAttribute", vpiDefAttribute },
+ { "vpiDelayType", vpiDelayType },
+ { "vpiIteratorType", vpiIteratorType },
+ { "vpiLibrary", vpiLibrary },
+ { "vpiMultiArray", vpiMultiArray },
+ { "vpiOffset", vpiOffset },
+ { "vpiResolvedNetType", vpiResolvedNetType },
+ { "vpiSaveRestartID", vpiSaveRestartID },
+ { "vpiSaveRestartLocation", vpiSaveRestartLocation },
+ { "vpiValid", vpiValid },
+ { "vpiSigned", vpiSigned },
+ { "vpiStop", vpiStop },
+ { "vpiFinish", vpiFinish },
+ { "vpiReset", vpiReset },
+ { "vpiSetInteractiveScope", vpiSetInteractiveScope },
+ { "vpiLocalParam", vpiLocalParam },
+ { "vpiModPathHasIfNone", vpiModPathHasIfNone },
+};
+#define NVPTYPS (sizeof(pnames_vpi) / sizeof(struct pnamvpi_t))
+
+
+/* LOOKATME - is it true there are no Cver added properties? */
+
+
+/*
+ * routine to acess vpi property name given constant value
+ * could index but would not catch inconsistencies after standard changes
+ */
+extern char *__to_vpipnam(char *s, int32 pval)
+{
+ if (pval == vpiUndefined) { strcpy(s, "vpiUndefined"); return(s); }
+
+ if (pval >= 1 && pval < NVPTYPS) 
+  {
+   strcpy(s, pnames_vpi[pval].vpipropnam);
+   return(s);
+  }
+ sprintf(s, "**property out of range (%d)", pval);
+ return(s);
+}
+
+/* table of vpi_ operator names */
+static struct opnamvpi_t opnames_vpi[] = {
+ { "**unused-operator-const**", 0, "UNUSED" }, 
+ { "vpiMinusOp", vpiMinusOp, "-" },
+ { "vpiPlusOp", vpiPlusOp, "+" },
+ { "vpiNotOp", vpiNotOp, "!" },
+ { "vpiBitNegOp", vpiBitNegOp, "~" },
+ { "vpiUnaryAndOp", vpiUnaryAndOp, "&" },
+ { "vpiUnaryNandOp", vpiUnaryNandOp, "&~" },
+ { "vpiUnaryOrOp", vpiUnaryOrOp, "|" },
+ { "vpiUnaryNorOp", vpiUnaryNorOp, "^~" },
+ { "vpiUnaryXorOp", vpiUnaryXorOp, "^" },
+ { "vpiUnaryXNorOp", vpiUnaryXNorOp, "^~" },
+ { "vpiSubOp", vpiSubOp, "-" },
+ { "vpiDivOp", vpiDivOp, "/"  },
+ { "vpiModOp", vpiModOp, "%"  },
+ { "vpiEqOp", vpiEqOp, "==" },
+ { "vpiNeqOp", vpiNeqOp, "!=" },
+ { "vpiCaseEqOp", vpiCaseEqOp, "==="  },
+ { "vpiCaseNeqOp", vpiCaseNeqOp, "!=="  },
+ { "vpiGtOp", vpiGtOp, ">" },
+ { "vpiGeOp", vpiGeOp, ">=" },
+ { "vpiLtOp", vpiLtOp, "<" },
+ { "vpiLeOp", vpiLeOp, "<=" },
+ { "vpiLShiftOp", vpiLShiftOp, "<<" },
+ { "vpiRShiftOp", vpiRShiftOp, ">>" },
+ { "vpiAddOp", vpiAddOp, "+" },
+ { "vpiMultOp", vpiMultOp, "*" },
+ { "vpiLogAndOp", vpiLogAndOp, "&" },
+ { "vpiLogOrOp", vpiLogOrOp, "||" },
+ { "vpiBitAndOp", vpiBitAndOp, "&" },
+ { "vpiBitOrOp", vpiBitOrOp, "|" },
+ { "vpiBitXorOp", vpiBitXorOp, "^" },
+ { "vpiBitXNorOp", vpiBitXNorOp, "^~" },
+ { "vpiConditionOp", vpiConditionOp, "?" },
+ { "vpiConcatOp", vpiConcatOp, "{" },
+ { "vpiMultiConcatOp", vpiMultiConcatOp, "{" },
+ { "vpiEventOrOp", vpiEventOrOp, "OR" },
+ { "vpiNullOp", vpiNullOp, "" },
+ { "vpiListOp", vpiListOp, "," },
+ { "vpiMinTypMaxOp", vpiMinTypMaxOp, "(::)" },
+ { "vpiPosedgeOp", vpiPosedgeOp, "posedge" },
+ { "vpiNegedgeOp", vpiNegedgeOp, "negedge" }
+};
+#define NVOPTYPS (sizeof(opnames_vpi) / sizeof(struct opnamvpi_t))
+
+/*
+ * routine to acess vpi expression operator name given constant value
+ * could index but would not catch inconsistencies after standard changes
+ */
+extern char *__to_vpiopnam(char *s, int32 opval)
+{
+ if (opval == vpiUndefined) { strcpy(s, "vpiUndefined"); return(s); }
+ if (opval < 1 || opval >= NVOPTYPS)
+  { sprintf(s, "**operator out of range (%d)", opval); return(s); }
+ strcpy(s, opnames_vpi[opval].vpiopnam);
+ return(s);
+}
+
+/*
+ * routine to acess vpi expression operator name given constant value
+ * could index but would not catch inconsistencies after standard changes
+ */
+extern char *__to_vpiopchar(char *s, int32 opval)
+{
+ if (opval == vpiUndefined) { strcpy(s, "<UNDEF>"); return(s); }
+ if (opval < 1 || opval >= NVOPTYPS)
+  { sprintf(s, "**operator out of range (%d)", opval); return(s); }
+ strcpy(s, opnames_vpi[opval].vpiopchar);
+ return(s);
+}
+
+/*
+ * emit common simulation has not begun (or reset in progress) error
+ */
+extern void __sim_notbegun_err(char *rnam)
+{
+ __vpi_err(1927, vpiError,
+  "%s - routine not callable - simulation not started (or reset in progress)",
+  rnam); 
+}
+
+/*
+ * emit common compilation in progress (no n.l to traverse) message
+ */
+extern void __still_comp_err(char *rnam)
+{
+ __vpi_err(1923, vpiError,
+  "%s routine not callable - design translation not completed", rnam); 
+}
+
+/*
+ * emit common write or schedule during ro_synch section
+ */
+extern void __bad_rosync_err(char *rnam)
+{
+ __vpi_err(1922, vpiError,
+  "%s routine not callable during ro sync - schedule for current time or write", rnam);
+}
+
+/*
+ * validate a non iterator handle
+ */
+extern int32 __validate_nonit_handle(char *rnam, struct h_t *hp) 
+{
+ if (!__validate_handle(rnam, hp)) return(FALSE); 
+ if (hp->hrec->htyp != vpiIterator) return(TRUE);
+ __vpi_err(1815, vpiError,
+  "%s: iterator handle illegal in this context", rnam); 
+ return(FALSE);
+}
+
+/*
+ * validate a handle - returns F on error
+ * 
+ * LOOKATME - acc_ handle passed to here may work and not checked for
+ * FIXME - need compile -D switch than turns off most checking
+ */
+extern int32 __validate_handle(char *rnam, register struct h_t *hp) 
+{
+ register struct hrec_t *hrp;
+
+ /* if low value bad since ptr */
+ /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
+ if (hp == NULL || ((word32) hp) < 256)
+  {
+   strcpy(__wrks1, "** NULL OR LOW NUMBER **");
+   goto bad_handle;
+  }
+ hrp = hp->hrec;
+ /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
+ if (hrp == NULL || ((word32) hrp) < 256 || hrp->h_magic != PVH_MAGIC)
+  {
+   strcpy(__wrks1, "** PTR INTO DATA BASE ILLEGAL **");
+   goto bad_handle;
+  }
+ if (!__validate_otyp(hrp->htyp))
+  {
+   sprintf(__wrks1, "%d", hrp->htyp);
+   goto bad_handle;
+  }
+ return(TRUE);
+
+bad_handle:
+ __vpi_err(1818, vpiError,
+  "%s: handle illegal magic number or type %s illegal", rnam, __wrks1); 
+ return(FALSE);
+}
+
+/*
+ * validate access method handle
+ * returns F on error
+ */
+extern int32 __validate_accessm(char *rnam, int32 otype, char *accessm)
+{
+ if (!__validate_otyp(otype))
+  {
+   __vpi_err(1819, vpiError,
+    "%s: access method type (can be handle type) %d for %s illegal or out of range",
+    rnam, otype, accessm); 
+   return(FALSE);
+  }
+ return(TRUE);
+}
+
+/*
+ * validate a vpi time type field
+ */
+extern int32 __validate_time_type(char *rnam, int32 timtyp)
+{
+ if (timtyp == vpiScaledRealTime || timtyp == vpiSimTime 
+  || timtyp == vpiSuppressTime) return(TRUE);
+ __vpi_err(1820, vpiError,
+  "%s: vpi time type value (%d) illegal", rnam, timtyp);
+ return(FALSE);
+}
+
+/*
+ * validate a vpi value format field
+ */
+extern int32 __validate_value_fmt(char *rnam, int32 fmt)
+{
+ switch (fmt) {
+  case vpiBinStrVal: case vpiOctStrVal: case vpiHexStrVal:
+  case vpiDecStrVal: case vpiScalarVal: case vpiIntVal:
+  case vpiRealVal: case vpiStringVal: case vpiVectorVal:
+  case vpiStrengthVal: case vpiSuppressVal: case vpiTimeVal:
+  case vpiObjTypeVal:
+   return(TRUE);
+  default:
+   __vpi_err(1822, vpiError,
+   "%s: vpi value format value (%d) illegal", rnam, fmt);
+ }
+ return(FALSE);
+}
+
+/*
+ * vpi internal fatal error 
+ */
+extern void __vpi_terr(char *fnam, int32 lno)
+{
+ __vpi_err(303, vpiInternal,
+  "VPI INTERNAL ERROR** - source line **%s(%d) - maybe at **%s(%d) or **%s(%d)",
+  fnam, lno, __in_fils[__vpifnam_ind], __vpilin_cnt, __in_fils[__sfnam_ind],
+  __slin_cnt);
+}
+
+/*VARARGS*/
+extern void __vpi_err(int32 id_num, int32 level, char *s, ...)
+{
+ va_list va;
+
+ /* update error counts */
+ if (level == vpiNotice) __inform_cnt++;
+ else if (level == vpiWarning) __pv_warn_cnt++;
+ else if (level == vpiError) __pv_err_cnt++;
+
+ /* by line number suppression means inform or warring never seen */
+ /* command line opions ignored here since can be controlled by error */
+ /* handler */
+ if (level == vpiNotice || level == vpiWarning)
+  {
+   if (__em_suppr(id_num)) return;
+  }
+
+ init_pli_einfo(&__wrk_einfo, level, id_num);
+ va_start(va, s);
+ vsprintf(__wrk_vpiemsg, s, va);
+ va_end(va);
+ __wrk_einfo.message = __wrk_vpiemsg;
+ __last_eip = &(__wrk_einfo);
+ if (__have_vpi_actions) __vpi_plierror_trycall();
+}
+
+/*
+ * for cbError (called from Cver error routine) fill einfo record
+ *
+ * in cbError callback user must call vpi chk error to get error info
+ */
+extern void __cberror_fill_einfo(int32 esev, int32 ernum, char *emsg,
+ char *efnam, int32 elcnt)
+{
+ struct t_vpi_error_info *einfop;
+
+ einfop = &(__wrk_einfo);
+ __last_eip = einfop;
+
+ if (__run_state == SS_SIM) einfop->state = vpiRun;
+ else einfop->state = vpiCompile; 
+
+ einfop->level = to_vpierr_level(esev);
+ einfop->message = emsg;
+ /* FIXME - move to initialize routine */
+ sprintf(__wrk_vpi_product, "%s%s", __vers, __vers2);
+
+ einfop->product = __wrk_vpi_product;
+ einfop->code = __wrk_vpi_errcode;
+ sprintf(__wrk_vpi_errcode, "%d", ernum); 
+
+ einfop->file = efnam;
+ einfop->line = elcnt;
+}
+
+
+/*
+ * convert error message severity to vpi_ error message level
+ */
+static int32 to_vpierr_level(int32 esev)
+{
+ switch (esev) {
+  case INFORM: return(vpiNotice);
+  case WARN: return(vpiWarning);
+  case ERROR: return(vpiError);
+  case FATAL: return(vpiInternal); 
+  default:  __vpi_terr(__FILE__, __LINE__);
+ }
+ return(vpiInternal);
+}
+
+/*
+ * initialize constant for Cver and set else values for vpi error info rec
+ * when have more types, can pass args here
+ */
+static void init_pli_einfo(struct t_vpi_error_info *einfop, int32 elev, int32 ernum)
+{
+ einfop->state = vpiPLI;
+ einfop->level = elev;
+ einfop->message = __wrk_vpiemsg;
+
+ /* FIXME - move to initialize routine */
+ sprintf(__wrk_vpi_product, "%s%s", __vers, __vers2);
+
+ einfop->product = __wrk_vpi_product;
+ einfop->code = __wrk_vpi_errcode;
+ sprintf(__wrk_vpi_errcode, "%d", ernum); 
+ einfop->file = __in_fils[__vpifnam_ind];
+ einfop->line = __vpilin_cnt;
+} 
+
+/*
+ * clear wrk einfo record - can only call after user callback returns
+ */
+extern void __clear_wrk_einfo(void)
+{
+ __wrk_einfo.level = 0;
+ __wrk_einfo.message = NULL;
+ __wrk_einfo.file = NULL;
+ __wrk_vpi_timedbl = 0;
+}
diff --git a/src/veriuser.c b/src/veriuser.c
new file mode 100644
index 0000000..2d4d9f6
--- /dev/null
+++ b/src/veriuser.c
@@ -0,0 +1,12 @@
+/* dummy veriuser when not compiled into cverobj.o form */
+#include "veriuser.h"
+#include "cv_veriuser.h"
+
+/* Template table for defining user tasks and functions.
+   See file veriuser.h for structure definition
+*/ 
+
+s_tfcell veriusertfs[] =
+{
+ {0}
+};
diff --git a/src/vpiuser.c b/src/vpiuser.c
new file mode 100644
index 0000000..0b5cd11
--- /dev/null
+++ b/src/vpiuser.c
@@ -0,0 +1,18 @@
+
+/* dummy vpiuser.c when not compiled into cverobj.o form */
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+
+void (*vlog_startup_routines[]) () =
+{
+ 0
+};
diff --git a/tests_and_examples/README b/tests_and_examples/README
new file mode 100644
index 0000000..780b83e
--- /dev/null
+++ b/tests_and_examples/README
@@ -0,0 +1,39 @@
+
+
+                               RUNNING TESTS
+
+This directory contains a number of test directories.  Each directory
+contains a README file with specific instructions for running the
+tests (usually how to run the test shell script).  Directories are: 
+
+install.tst:
+
+ Installation test.  This test runs cver on various Verilog files to insure
+ correct build.  It should always be run.  
+
+examples.tf:
+
+  Examples of PLI 1.0 tf_ interface routines.  The test script uses
++loadpli1= option to make dynamic libraries (.so files) and then runs
+the test.
+
+examples.acc:
+
+  Examples of PLI 1.0 acc_ interface routines.  The test script uses
++loadpli1= option to make dynamic libraries (.so files) and then runs
+the test.
+
+examples.vpi:
+
+  Examples of PLI 1.0 acc_ interface routines.  The test script uses
++loadvpi= option to make dynamic libraries (.so files) and then runs
+the test.
+
+capacity.tst
+  This option test runs a 3.2 million gate circuit to show advantages of
+non flattened algorithm.  It requires about 150MB of free memory.  Running
+it is optional.
+
+v2001
+  This directory contains some tests for new verilog 2001 features supported
+by GPL Cver 2.xx.
diff --git a/tests_and_examples/capacity.tst/README b/tests_and_examples/capacity.tst/README
new file mode 100644
index 0000000..e385e6f
--- /dev/null
+++ b/tests_and_examples/capacity.tst/README
@@ -0,0 +1,21 @@
+
+                     RUNNING THE CAPACITY TEST
+
+This directory contains a 3.2 million gate circuit that requires about
+150MB of memory to run.  Circuit is a shift register from John Hillawi's
+DA Solutions bench marks and is used with permission.
+
+To run the test type:
+
+  ../../bin/cver -f lfsr.vc
+
+Then type: 
+
+  diff verilog.log lfsr.plg
+
+to check for correct output.  The diff command will print minor differences
+such as date, time, memory use depending on you system.
+The +printstats option prints out circuit size statistics.
+
+Also, try running the lfsr_udp.vc to see 50k gate version of same circuit
+coded using udps.
diff --git a/tests_and_examples/capacity.tst/lca100kgate/AN2.v b/tests_and_examples/capacity.tst/lca100kgate/AN2.v
new file mode 100644
index 0000000..79ca902
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/AN2.v
@@ -0,0 +1,8 @@
+module AN2(a, b, z);
+
+input	a, b;
+output	z;
+
+and #1 g1(z, a, b);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/AN3.v b/tests_and_examples/capacity.tst/lca100kgate/AN3.v
new file mode 100644
index 0000000..e915d8d
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/AN3.v
@@ -0,0 +1,8 @@
+module	AN3(a, b, c, z);
+
+input	a, b, c;
+output	z;
+
+and #1 g1(z, a, b, c);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/AN4.v b/tests_and_examples/capacity.tst/lca100kgate/AN4.v
new file mode 100644
index 0000000..361876f
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/AN4.v
@@ -0,0 +1,8 @@
+module	AN4(a, b, c, d, z);
+
+input	a, b, c, d;
+output	z;
+
+and #1 g1(z, a, b, c, d);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/AN5.v b/tests_and_examples/capacity.tst/lca100kgate/AN5.v
new file mode 100644
index 0000000..75dae1a
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/AN5.v
@@ -0,0 +1,8 @@
+module	AN5(a, b, c, d, e, z);
+
+input	a, b, c, d, e;
+output	z;
+
+and #1 g1(z, a, b, c, d, e);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/BUF8A.v b/tests_and_examples/capacity.tst/lca100kgate/BUF8A.v
new file mode 100644
index 0000000..66a7e93
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/BUF8A.v
@@ -0,0 +1,8 @@
+module 	BUF8A(a, z);
+
+input   a;
+output  z;
+
+buf #1 g1(z, a);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/EN.v b/tests_and_examples/capacity.tst/lca100kgate/EN.v
new file mode 100644
index 0000000..9b83d7e
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/EN.v
@@ -0,0 +1,8 @@
+module	EN (a, b, z);
+
+input	a, b;
+output	z;
+
+xnor #1 g1(z, a, b);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/FA1A.v b/tests_and_examples/capacity.tst/lca100kgate/FA1A.v
new file mode 100644
index 0000000..699ca7f
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/FA1A.v
@@ -0,0 +1,12 @@
+module	FA1A( ci, a, b, s, co );
+
+input	ci, a, b;
+output	s, co;
+
+xor	#1 l1(s, ci, a, b);
+and	l2(x1, ci, a );
+and	l3(x2, ci, b );
+and	l4(x3, a, b );
+or	#1 l5(co, x1, x2, x3);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/FD2.fix b/tests_and_examples/capacity.tst/lca100kgate/FD2.fix
new file mode 100644
index 0000000..9e0625d
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/FD2.fix
@@ -0,0 +1,20 @@
+module dflop (d, cp, cd, q); 
+
+  input d, cp, cd;
+  output q, qn;
+
+	nand	n1(a, d, cp),
+		n2(b, cp, cd),
+		n3(c, d, cd);
+
+
+	nand	n4(e, d, cp),
+		n5(f, cp, cd),
+		n6(g, d, cd);
+
+	nand	n7(h, a, b, c),
+		n8(g, e, f, g);
+
+	not	n9(q, h);
+
+endmodule  
diff --git a/tests_and_examples/capacity.tst/lca100kgate/FD2.v b/tests_and_examples/capacity.tst/lca100kgate/FD2.v
new file mode 100644
index 0000000..3439093
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/FD2.v
@@ -0,0 +1,21 @@
+module FD2 (d, cp, cd, q, qn); 
+
+  input d, cp, cd;
+  output q, qn;
+
+  nand #1   nand_2 (n2, d_, cp_),
+            nand_3 (n3, n1, n4),   
+            nand_7 (q, n5, qn);
+ 
+// SJM  nand #0   nand_1 (n1, d, cp_, cd),
+  nand   nand_1 (n1, d, cp_, cd),
+            nand_4 (n4, n2, n3, cd),
+            nand_5 (n5, n3, cp),
+            nand_6 (n6, n4, cp),
+            nand_8 (qn, n6, cd, q);  
+
+// SJM not  #0   inv_1 (cp_, cp),
+  not   inv_1 (cp_, cp),
+            inv_2 (d_, d);
+
+endmodule  
diff --git a/tests_and_examples/capacity.tst/lca100kgate/FD2v.orig b/tests_and_examples/capacity.tst/lca100kgate/FD2v.orig
new file mode 100644
index 0000000..c0ba626
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/FD2v.orig
@@ -0,0 +1,19 @@
+module FD2 (d, cp, cd, q, qn); 
+
+  input d, cp, cd;
+  output q, qn;
+
+  nand #1   nand_2 (n2, d_, cp_),
+            nand_3 (n3, n1, n4),   
+            nand_7 (q, n5, qn);
+ 
+  nand #0   nand_1 (n1, d, cp_, cd),
+            nand_4 (n4, n2, n3, cd),
+            nand_5 (n5, n3, cp),
+            nand_6 (n6, n4, cp),
+            nand_8 (qn, n6, cd, q);  
+
+  not  #0   inv_1 (cp_, cp),
+            inv_2 (d_, d);
+
+endmodule  
diff --git a/tests_and_examples/capacity.tst/lca100kgate/OR2.v b/tests_and_examples/capacity.tst/lca100kgate/OR2.v
new file mode 100644
index 0000000..b268429
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/OR2.v
@@ -0,0 +1,8 @@
+module	OR2(a, b, z);
+
+input	a, b;
+output	z;
+
+or #1 g1(z, a, b);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/OR3.v b/tests_and_examples/capacity.tst/lca100kgate/OR3.v
new file mode 100644
index 0000000..3da1430
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/OR3.v
@@ -0,0 +1,8 @@
+module	OR3(a, b, c, z);
+
+input	a, b, c;
+output	z;
+
+or #1 g1(z, a, b, c);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/OR4.v b/tests_and_examples/capacity.tst/lca100kgate/OR4.v
new file mode 100644
index 0000000..599c49f
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/OR4.v
@@ -0,0 +1,8 @@
+module	OR4(a, b, c, d, z);
+
+input	a, b, c, d;
+output	z;
+
+or #1 g1(z, a, b, c, d);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/OR5.v b/tests_and_examples/capacity.tst/lca100kgate/OR5.v
new file mode 100644
index 0000000..7ad1f62
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/OR5.v
@@ -0,0 +1,8 @@
+module	OR5(a, b, c, d, e, z);
+
+input	a, b, c, d, e;
+output	z;
+
+or #1 g1(z, a, b, c, d, e);
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lca100kgate/zero.v b/tests_and_examples/capacity.tst/lca100kgate/zero.v
new file mode 100644
index 0000000..c50c2e6
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lca100kgate/zero.v
@@ -0,0 +1,13 @@
+module zero ( LO );
+
+// Verilog Port Declaration section
+
+   output LO;
+
+
+// Verilog Structure section (in terms of gate prims)
+
+
+           buf  #1 ( LO , 1'b0 ) ;
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lfsr.plg b/tests_and_examples/capacity.tst/lfsr.plg
new file mode 100644
index 0000000..78af998
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lfsr.plg
@@ -0,0 +1,87 @@
+CVER_2.42_0a of 01/03/02 (Linux-elf).
+Copyright (c) 1991-2002 Pragmatic C Software Corp.
+  Licensed software containing confidential and proprietary
+  information belonging to Pragmatic C Software Corp.
+Today is Thu Jan  3 23:08:12 2002.
+  Verbose mode is on.
+  Invoked by: "/tmp/cver".
+  Delay annotation values read from SDF 3.0 file "lfsr.sdf" design context.
+  Directory "lca100kgate" searched for libraries from -y option.
+  +.v suffix(es) used for -y library extensions from +libext+ options.
+  Design content tables will be written.
+  Begin Translation:
+Compiling source file "lfsr32000.v"
+  Begin pass 2:
+  Approximately 399377 bytes storage allocated (excluding udps).
+Highest level modules:
+test
++++ Printing Design Statistics +++
+  Verbose mode statistics:
+  198 source lines read (includes -v/-y library files).
+  Design contains 9 module types.
+
+  Design Module Table: 9 modules (1 top level):
+Module            Level Cells-in Insts-in Primitives  Assigns    Nets  Insts-of
+lfsr                  1       11        0          0        0      24     32000
+lfsr10                2        0       10          0        0      13      3200
+lfsr100               3        0       10          0        0      13       320
+lfsr1000              4        0       10          0        0      13        32
+lfsr10000             5        0       10          0        0      13         3
+lfsr32000             6        0        5          0        0       8         1
+test                  7        0        1          3        0       8         1
+EN(C)                 0        0        0          1        0       3     32000
+FD2(C)                0        0        0         10        0      13    320000
+                          ------   ------     ------   ------  ------    ------
+Static Total:                 11       46         14        0     108
+Flat Total:               352000    35556    3232003        0 5070231    387557
+
+  Per Module Wiring Table (Task Variables Excluded):
+Module           Ports(Bits)   Wires(Bits) Registers(Bits) Memory(Cells, Bits)
+lfsr                    4(4)        20(20)                                    
+lfsr10                  4(4)          9(9)                                    
+lfsr100                 4(4)          9(9)                                    
+lfsr1000                4(4)          9(9)                                    
+lfsr10000               4(4)          9(9)                                    
+lfsr32000               4(4)          4(4)                                    
+test                                  4(4)           4(39)                    
+EN(C)                   3(3)                                                  
+FD2(C)                  5(5)          8(8)                                    
+                ------------ ------------- --------------- -------------------
+Flat total:    1838224(1838224)3232003(3232003)           4(39)                    
+
+  Design Usage Table:
+Type                      Class  Static   Flat   Location
+                                 Number  Number
+lfsr                      module     10   32000  lfsr32000.v:8
+lfsr10                    module     10    3200  lfsr32000.v:29
+lfsr100                   module     10     320  lfsr32000.v:48
+lfsr1000                  module     12      32  lfsr32000.v:68
+lfsr10000                 module      3       3  lfsr32000.v:87
+lfsr32000                 module      1       1  lfsr32000.v:104
+test                      top         0       0  lfsr32000.v:118
+EN                        cell        1   32000  lca100kgate/EN.v:1
+FD2                       cell       10  320000  lca100kgate/FD2.v:1
+and                       gate        1       1
+buf                       gate        1       1
+nand                      gate        8 2560000
+not                       gate        3  640001
+xnor                      gate        1   32000
+
+  Flattened Design: 387556 instances (352000 of cells), 0 udps (0 in cells),
+   3232003 gates (3232000 in cells) and 0 assigns (0 in cells).
++++ End of Design Statistics +++
+  Variable storage in bytes: 10140460 for scalars, 16 for vectors and 0 for reals.
+  Begin load/optimize:
+  Approximately 25440791 bytes storage allocated (excluding udps).
+  SDF delay +sdf_annotate completed for "lfsr.sdf" context scope **design**.
+  Begin simulation:
+  Approximately 148483376 bytes storage allocated (excluding udps).
+
+
+
+Results display
+Halted at location **lfsr32000.v(143) time 1100 from call to $finish.
+24768019 simulation events and 42816038 declarative immediate assigns processed.
+56 behavioral statements executed (18 procedural suspends).
+  Times (in sec.):  Translate 0.1, load/optimize 6.2, simulation 61.1.
+  There were 0 error(s), 0 warning(s), and 89 inform(s).
diff --git a/tests_and_examples/capacity.tst/lfsr.sdf b/tests_and_examples/capacity.tst/lfsr.sdf
new file mode 100644
index 0000000..75374e1
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lfsr.sdf
@@ -0,0 +1,24 @@
+(DELAYFILE 
+  (SDFVERSION "3.0") 
+  (TIMESCALE 10ns)
+  (CELL (CELLTYPE "FD2" ) (INSTANCE * nand_2) 
+   (DELAY (ABSOLUTE (DEVICE (:0.1:)))))
+  (CELL (CELLTYPE "FD2" ) (INSTANCE * nand_3) 
+   (DELAY (ABSOLUTE (DEVICE (:0.1:)))))
+  (CELL (CELLTYPE "FD2" ) (INSTANCE * nand_7)
+   (DELAY (ABSOLUTE (DEVICE (:0.1:)))))
+  (CELL (CELLTYPE "FD2" ) (INSTANCE * nand_1)
+   (DELAY (ABSOLUTE (DEVICE (:0.2:)))))
+  (CELL (CELLTYPE "FD2" ) (INSTANCE * nand_4)
+   (DELAY (ABSOLUTE (DEVICE (:0.1:)))))
+  (CELL (CELLTYPE "FD2" ) (INSTANCE * nand_5)
+   (DELAY (ABSOLUTE (DEVICE (:0:)))))
+  (CELL (CELLTYPE "FD2" ) (INSTANCE * nand_6)
+   (DELAY (ABSOLUTE (DEVICE (:0:)))))
+  (CELL (CELLTYPE "FD2" ) (INSTANCE * nand_8)
+   (DELAY (ABSOLUTE (DEVICE (:0:)))))
+  (CELL (CELLTYPE "FD2" ) (INSTANCE * inv_1)
+   (DELAY (ABSOLUTE (DEVICE (:0:)))))
+  (CELL (CELLTYPE "FD2" ) (INSTANCE * inv_2)
+   (DELAY (ABSOLUTE (DEVICE (:0:)))))
+)
diff --git a/tests_and_examples/capacity.tst/lfsr.vc b/tests_and_examples/capacity.tst/lfsr.vc
new file mode 100644
index 0000000..5530c8d
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lfsr.vc
@@ -0,0 +1,3 @@
++verbose lfsr32000.v +sdfannotate lfsr.sdf -y lca100kgate +libext+.v
++printstats
+  
diff --git a/tests_and_examples/capacity.tst/lfsr32000.v b/tests_and_examples/capacity.tst/lfsr32000.v
new file mode 100644
index 0000000..633ba5d
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lfsr32000.v
@@ -0,0 +1,169 @@
+// DA Solutions LFSR model used for sizing tests
+// Created by D. J. Wharton, 1-Sep-94
+// Model equivalent to 3,200,000 gates 
+// Equivalent model in VHDL
+
+`timescale 1ns / 1ns
+
+module lfsr (d, clk, reset, q);
+
+  input d, clk, reset;
+  output q;
+
+  EN  	en_1 (d, q7, xout);
+
+  FD2 	fd2_1 (xout, clk, reset, q1, q1b),
+        fd2_2 (q1, clk, reset, q2, q2b),
+        fd2_3 (q2, clk, reset, q3, q3b),
+        fd2_4 (q3, clk, reset, q4, q4b),
+        fd2_5 (q4, clk, reset, q5, q5b),
+        fd2_6 (q5, clk, reset, q6, q6b),
+        fd2_7 (q6, clk, reset, q7, q7b),
+        fd2_8 (q7, clk, reset, q8, q8b),
+        fd2_9 (q8, clk, reset, q9, q9b),
+        fd2_10 (q9, clk, reset, q, q10b);  
+
+endmodule
+
+
+module lfsr10 (d, clk, reset, q);
+
+  input d, clk, reset;
+  output q;
+
+  lfsr	 lfsr_1 (d,  clk, reset, d1),
+         lfsr_2 (d1, clk, reset, d2),
+         lfsr_3 (d2, clk, reset, d3),
+         lfsr_4 (d3, clk, reset, d4),
+         lfsr_5 (d4, clk, reset, d5),
+         lfsr_6 (d5, clk, reset, d6),
+         lfsr_7 (d6, clk, reset, d7),
+         lfsr_8 (d7, clk, reset, d8),
+         lfsr_9 (d8, clk, reset, d9),
+         lfsr_10(d9, clk, reset, q ); 
+
+endmodule  
+
+
+module lfsr100 (d, clk, reset, q);
+
+  input d, clk, reset;
+  output q;
+
+  lfsr10 lfsr10_1 (d , clk, reset, d1),
+         lfsr10_2 (d1, clk, reset, d2),
+         lfsr10_3 (d2, clk, reset, d3),
+         lfsr10_4 (d3, clk, reset, d4),
+         lfsr10_5 (d4, clk, reset, d5),
+         lfsr10_6 (d5, clk, reset, d6),
+         lfsr10_7 (d6, clk, reset, d7),
+         lfsr10_8 (d7, clk, reset, d8),
+         lfsr10_9 (d8, clk, reset, d9),
+         lfsr10_10(d9, clk, reset, q ); 
+
+
+endmodule  
+
+
+module lfsr1000 (d, clk, reset, q);
+
+  input d, clk, reset;
+  output q;
+
+  lfsr100 lfsr100_1(d , clk, reset, d1),  
+         lfsr100_2 (d1, clk, reset, d2),
+         lfsr100_3 (d2, clk, reset, d3),
+         lfsr100_4 (d3, clk, reset, d4),
+         lfsr100_5 (d4, clk, reset, d5), 
+         lfsr100_6 (d5, clk, reset, d6),
+         lfsr100_7 (d6, clk, reset, d7),
+         lfsr100_8 (d7, clk, reset, d8),
+         lfsr100_9 (d8, clk, reset, d9),
+         lfsr100_10(d9, clk, reset, q );
+
+
+endmodule  
+
+module lfsr10000 (d, clk, reset, q);
+
+  input d, clk, reset;
+  output q;
+
+  lfsr1000 	lfsr1000_1 (d, clk, reset, d1),
+		lfsr1000_2 (d1, clk, reset, d2),
+		lfsr1000_3 (d2, clk, reset, d3),
+		lfsr1000_4 (d3, clk, reset, d4),
+		lfsr1000_5 (d4, clk, reset, d5),
+		lfsr1000_6 (d5, clk, reset, d6),
+		lfsr1000_7 (d6, clk, reset, d7),
+		lfsr1000_8 (d7, clk, reset, d8),
+		lfsr1000_9 (d8, clk, reset, d9),
+		lfsr1000_10 (d9, clk, reset, q);
+endmodule
+
+module lfsr32000 (d, clk, reset, q);
+
+  input d, clk, reset;
+  output q;
+
+  lfsr10000	lfsr10000_1 (d, clk, reset, d1),
+		lfsr10000_2 (d1, clk, reset, d2),
+		lfsr10000_3 (d2, clk, reset, d3);
+
+  lfsr1000	lfsr1000_1 (d3, clk, reset, d4),
+		lfsr1000_2 (d4, clk, reset, q);
+
+endmodule
+
+module test;
+
+wire	d;
+
+reg 		reset, creset;
+wire		clk_out;
+wire		clk_in;
+
+reg	[0:31] 	tempword;
+reg	[0:4]	j;
+
+lfsr32000	lfsr32000_1 (d, clk_out, reset, q);
+
+buf		buf_1 (d,q);
+
+not 	#50	clk_1 (clk_in, clk_out);
+and		clk_2 (clk_out, clk_in, creset);
+
+  initial
+  begin
+		reset = 1;
+	#25	reset = 0; creset = 0;
+	#25	reset = 1;
+	#50	creset = 1;
+//    	#99900 	$finish(2);
+    	#1000 	$finish(2);
+  end
+
+// Results display code
+
+initial
+begin
+	tempword = 0; j = 0;
+	#25 $write ("\n");
+	    $display ("Results display");
+end
+
+always
+begin
+	@ (posedge clk_out)
+	begin
+	tempword[j] = d;
+	j = j + 1;
+	if ( j == 0)
+	begin
+	$display ($time,,"%b",tempword[0:7],,"%b",tempword[8:15],,"%b",tempword[16:23],,"%b",tempword[24:31],);
+	tempword = 0;
+	end
+	end
+end
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lfsr5udp.plg b/tests_and_examples/capacity.tst/lfsr5udp.plg
new file mode 100644
index 0000000..8af3361
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lfsr5udp.plg
@@ -0,0 +1,109 @@
+CVER_2.42_0a of 01/03/02 (Linux-elf).
+Copyright (c) 1991-2002 Pragmatic C Software Corp.
+  Licensed software containing confidential and proprietary
+  information belonging to Pragmatic C Software Corp.
+Today is Thu Jan  3 22:41:47 2002.
+  Verbose mode is on.
+  Invoked by: "/tmp/cver".
+  SDF annotation tracing verbose mode is on.
+  Design content tables will be written.
+  Begin Translation:
+Compiling source file "lfsr5udp.v"
+  Begin pass 2:
+  Approximately 396822 bytes storage allocated (excluding udps).
+Highest level modules:
+test
++++ Printing Design Statistics +++
+  Verbose mode statistics:
+  178 source lines read (includes -v/-y library files).
+  Design contains 7 module types.
+  1 instantiated udp tables of total size less than 1 million bytes.
+
+  Design Module Table: 7 modules (1 top level):
+Module            Level Cells-in Insts-in Primitives  Assigns    Nets  Insts-of
+fd2xl                 0        0        0          3        0       6      5000
+EN                    0        0        0          1        0       3       500
+lfsr                  1        0       11          0        0      24       500
+lfsr10                2        0       10          0        0      13        50
+lfsr100               3        0       10          0        0      13         5
+lfsr500               4        0        5          0        0       8         1
+test                  5        0        1          3        0       8         1
+                          ------   ------     ------   ------  ------    ------
+Static Total:                  0       37          7        0      75
+Flat Total:                    0     6056      15503        0   44231      6057
+
+  Per Module Wiring Table (Task Variables Excluded):
+Module           Ports(Bits)   Wires(Bits) Registers(Bits) Memory(Cells, Bits)
+fd2xl                   5(5)          1(1)                                    
+EN                      3(3)                                                  
+lfsr                    4(4)        20(20)                                    
+lfsr10                  4(4)          9(9)                                    
+lfsr100                 4(4)          9(9)                                    
+lfsr500                 4(4)          4(4)                                    
+test                                  4(4)           4(39)                    
+                ------------ ------------- --------------- -------------------
+Flat total:     28724(28724)  15503(15503)           4(39)                    
+
+  Design Usage Table:
+Type                      Class  Static   Flat   Location
+                                 Number  Number
+fd2xl                     module     10    5000  lfsr5udp.v:12
+EN                        module      1     500  lfsr5udp.v:42
+lfsr                      module     10     500  lfsr5udp.v:53
+lfsr10                    module     10      50  lfsr5udp.v:74
+lfsr100                   module      5       5  lfsr5udp.v:93
+lfsr500                   module      1       1  lfsr5udp.v:113
+test                      top         0       0  lfsr5udp.v:128
+xl_fd2                    udp         1    5000  lfsr5udp.v:22
+and                       gate        1       1
+buf                       gate        2    5001
+not                       gate        2    5001
+xnor                      gate        1     500
+
+  Flattened Design: 6056 instances, 5000 udps, 10503 gates and 0 assigns.
++++ End of Design Statistics +++
+  Variable storage in bytes: 88460 for scalars, 16 for vectors and 0 for reals.
+  Begin load/optimize:
+  Approximately 592391 bytes storage allocated (excluding udps).
+  Begin simulation:
+  Approximately 1610239 bytes storage allocated (excluding udps).
+
+
+
+Results display
+                3200 00000000 00111111 10001111 00000010 
+                6400 00111011 00000111 00110000 01010011 
+                9600 01001101 10110111 11111101 11111011 
+               12800 01110111 11001101 10010111 10110101 
+               16000 01111000 01010001 01001001 00111111 
+               19200 11001111 10010011 00111101 01001010 
+               22400 00111001 00000011 10111000 01100001 
+               25600 00100101 11111101 01111010 01010101 
+               28800 11000001 00001101 10100111 11011001 
+               32000 10111010 11100100 10001111 11000011 
+               35200 10001000 00001101 11100111 01001000 
+               38400 10111100 10101001 10000110 10010011 
+               41600 01111101 11011011 00111111 01001110 
+               44800 10110001 00110001 11010000 00101011 
+               48000 10100010 01010011 11001100 10010101 
+               51200 11110001 01100001 01100101 01101100 
+               54400 01111100 00011000 11001000 01011101 
+               57600 01010010 00001111 01100010 11100010 
+               60800 10000010 01011011 11011110 10110101 
+               64000 00111000 11000000 01001111 01110010 
+               67200 11000110 11000011 11001000 10011100 
+               70400 11100001 00000101 10110101 11111001 
+               73600 01110011 01000101 10100101 11011101 
+               76800 00110010 11010110 11100111 10001001 
+               80000 00001111 10100011 01010001 10001000 
+               83200 10001100 11000101 01000100 00100110 
+               86400 10111011 00100111 01111000 11010000 
+               89600 01101011 00110011 01010101 10000001 
+               92800 10011100 10100001 10010100 10110011 
+               96000 10110100 01111010 00010101 01010000 
+               99200 00001011 11101010 11010000 11101010 
+Halted at location **lfsr5udp.v(152) time 100000 from call to $finish.
+2773498 simulation events and 22838561 declarative immediate assigns processed.
+4074 behavioral statements executed (1007 procedural suspends).
+  Times (in sec.):  Translate 0.0, load/optimize 0.1, simulation 24.2.
+  There were 0 error(s), 0 warning(s), and 63 inform(s).
diff --git a/tests_and_examples/capacity.tst/lfsr5udp.v b/tests_and_examples/capacity.tst/lfsr5udp.v
new file mode 100644
index 0000000..7197760
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lfsr5udp.v
@@ -0,0 +1,178 @@
+// DA Solutions LFSR model used for sizing tests
+// Created by D. J. Wharton, 1-Sep-94
+// Model equivalent to 50,000 gates 
+// Equivalent model in VHDL
+
+/* --- 
+copied primitive from library to here
+--- */
+
+`timescale 1ns / 1ns
+
+module fd2xl(d, cp, cd, q, qn);
+ input d, cp, cd;
+ output q, qn;
+ wire xxx;
+
+ xl_fd2 #10 i0(xxx, d, cp, cd);
+ buf i1(q, xxx);
+ not i2(qn, xxx);
+endmodule
+
+primitive xl_fd2(q, d, cp, cd);
+ output q; reg q;
+ input d, cp, cd;
+
+ table
+  // d  cp  cd  :  q  :  q
+  // -  --  --  -  -  -  -
+     ?   ?   0  :  ?  :  0 ;
+     ?   ?   x  :  ?  :  x ;
+
+     0   r   1  :  ?  :  0 ;
+     1   r   1  :  ?  :  1 ;
+     x   r   1  :  ?  :  x ;
+
+     ?   f   1  :  ?  :  - ;
+     *   ?   1  :  ?  :  - ;
+     ?   ?   r  :  ?  :  - ;
+ endtable
+endprimitive
+
+module	EN (a, b, z);
+
+input	a, b;
+output	z;
+
+xnor #1 g1(z, a, b);
+
+endmodule
+
+/* --- end of library --- */
+
+module lfsr (d, clk, reset, q);
+
+  input d, clk, reset;
+  output q;
+
+  EN  	en_1 (d, q7, xout);
+
+  fd2xl 	fd2_1 (xout, clk, reset, q1, q1b),
+        fd2_2 (q1, clk, reset, q2, q2b),
+        fd2_3 (q2, clk, reset, q3, q3b),
+        fd2_4 (q3, clk, reset, q4, q4b),
+        fd2_5 (q4, clk, reset, q5, q5b),
+        fd2_6 (q5, clk, reset, q6, q6b),
+        fd2_7 (q6, clk, reset, q7, q7b),
+        fd2_8 (q7, clk, reset, q8, q8b),
+        fd2_9 (q8, clk, reset, q9, q9b),
+        fd2_10 (q9, clk, reset, q, q10b);  
+
+endmodule
+
+
+module lfsr10 (d, clk, reset, q);
+
+  input d, clk, reset;
+  output q;
+
+  lfsr	 lfsr_1 (d,  clk, reset, d1),
+         lfsr_2 (d1, clk, reset, d2),
+         lfsr_3 (d2, clk, reset, d3),
+         lfsr_4 (d3, clk, reset, d4),
+         lfsr_5 (d4, clk, reset, d5),
+         lfsr_6 (d5, clk, reset, d6),
+         lfsr_7 (d6, clk, reset, d7),
+         lfsr_8 (d7, clk, reset, d8),
+         lfsr_9 (d8, clk, reset, d9),
+         lfsr_10(d9, clk, reset, q ); 
+
+endmodule  
+
+
+module lfsr100 (d, clk, reset, q);
+
+  input d, clk, reset;
+  output q;
+
+  lfsr10 lfsr10_1 (d , clk, reset, d1),
+         lfsr10_2 (d1, clk, reset, d2),
+         lfsr10_3 (d2, clk, reset, d3),
+         lfsr10_4 (d3, clk, reset, d4),
+         lfsr10_5 (d4, clk, reset, d5),
+         lfsr10_6 (d5, clk, reset, d6),
+         lfsr10_7 (d6, clk, reset, d7),
+         lfsr10_8 (d7, clk, reset, d8),
+         lfsr10_9 (d8, clk, reset, d9),
+         lfsr10_10(d9, clk, reset, q ); 
+
+
+endmodule  
+
+
+module lfsr500 (d, clk, reset, q);
+
+  input d, clk, reset;
+  output q;
+
+  lfsr100 lfsr100_1(d , clk, reset, d1),  
+         lfsr100_2 (d1, clk, reset, d2),
+         lfsr100_3 (d2, clk, reset, d3),
+         lfsr100_4 (d3, clk, reset, d4),
+         lfsr100_5 (d4, clk, reset, q); 
+
+
+endmodule  
+
+
+module test;
+
+wire	d;
+
+reg 		reset, creset;
+wire		clk_out;
+wire		clk_in;
+
+reg	[0:31] 	tempword;
+reg	[0:4]	j;
+
+lfsr500	lfsr500_1 (d, clk_out, reset, q);
+
+buf		buf_1 (d,q);
+
+not 	#50	clk_1 (clk_in, clk_out);
+and		clk_2 (clk_out, clk_in, creset);
+
+  initial
+  begin
+		reset = 1;
+	#25	reset = 0; creset = 0;
+	#25	reset = 1;
+	#50	creset = 1;
+    	#99900 	$finish(2);
+  end
+
+// Results display code
+
+initial
+begin
+	tempword = 0; j = 0;
+	#25 $write ("\n");
+	    $display ("Results display");
+end
+
+always
+begin
+	@ (posedge clk_out)
+	begin
+	tempword[j] = d;
+	j = j + 1;
+	if ( j == 0)
+	begin
+	$display ($time,,"%b",tempword[0:7],,"%b",tempword[8:15],,"%b",tempword[16:23],,"%b",tempword[24:31],);
+	tempword = 0;
+	end
+	end
+end
+
+endmodule
diff --git a/tests_and_examples/capacity.tst/lfsr_udp.vc b/tests_and_examples/capacity.tst/lfsr_udp.vc
new file mode 100644
index 0000000..b553195
--- /dev/null
+++ b/tests_and_examples/capacity.tst/lfsr_udp.vc
@@ -0,0 +1 @@
++printstats +verbose lfsr5udp.v 
diff --git a/tests_and_examples/examples.acc/README b/tests_and_examples/examples.acc/README
new file mode 100644
index 0000000..3ed8000
--- /dev/null
+++ b/tests_and_examples/examples.acc/README
@@ -0,0 +1,66 @@
+To test PLI 1.0 acc_ interface:
+
+BEFORE STARTING:
+   Make sure binary Cver is installed in bin directory 2 levels up
+   (../../bin/cver) and run the shell script in install.tst directory to
+   verify correct installation of Cver.
+
+   This script assumes you are using new +loadpli1= dynamic library PLI
+   execution.  If you need to statically link your PLI libraries contact
+   Pragmatic C to obtain the libraries and test scripts.
+
+HOW TO RUN THE TEST SCRIPT FOR ALL SYSTEMS EXCEPT MAC OSX
+
+1) Run the shell script inst_pli.sh [OS name].  Various compiler and Verilog
+   output messages will be printed but there should be no diff command
+   differences printed.  You must pass the name of your system as the one
+   argument to the script.  Depending on your platform, names are:
+   for X86 linux (suffix lnx), Sparc (suffix sparc-gcc).
+
+   Run the shell script opt_inst_pli.sh [OS name] to test PLI using
+   optimizer (-O) incremental compiler.
+
+   The commands to run Cver with dynamically loaded user PLI library
+   explicitly access the user .so library in this directory.  For your
+   PLI libraries, it is better to set the LD_LIBRARY_PATH environment
+   variables so explicit "./" is not needed
+
+2) After completing the test, you can run clean.sh to remove work files.
+   The inst_pli.sh script removes each PLI library .so dynamic library after
+   running the test that uses it so unless something went wrong, you
+   do not need to run clean.sh.  
+
+3) Use makefile.[your OS] as a template for your PLI programs.
+
+HOW TO RUN THE TEST SCRIPT FOR MAC OSX
+
+1) Run the shell script inst_pli.osx.sh.  Notice you do not need the
+   OS shell argument here.  Various compiler and Verilog
+   output messages will be printed but there should be no diff command
+   differences printed.  You must run this different script for MAC OSX
+   because OSX uses .dylib suffix for dynamic libraries and uses the
+   mach dynamic library mechanism instead of normal .so and dlopen. 
+
+   By convention, makefile.osx assumes this test is run in release
+   directory tree with include files in pli_incs 2 directory levels up
+   and cver binary is in bin directory also 2 levels up.
+
+   The commands to run Cver with dynamically loaded user PLI library
+   explicitly access the user .dylib library in this directory.  For your
+   PLI libraries, it is better to set the LD_LIBRARY_PATH environment
+   variables so explicit "./" is not needed
+
+   Mac OSX linker (from mach OS) requires that a leading '_' be added to
+   each symbol name.  Cver does this automatically but you must make
+   sure that your bootstrap routine name does not start with underscore ('_').
+
+2) After completing the test, run clean.sh to remove work files.
+   The inst_pli.sh script removes each PLI library .so dynamic library after
+   running the test that uses it so unless something went wrong, you
+   do not need to run clean.sh.  
+
+3) Use makefile.osx as a template for your PLI models.  You must use
+   exactly the LFLAGS options and set and export LD_LIBRARY_PATH
+   environment variable, or your .dylib user PLI code will not load
+   properly.
+   
diff --git a/tests_and_examples/examples.acc/acc_nxtchld.c b/tests_and_examples/examples.acc/acc_nxtchld.c
new file mode 100644
index 0000000..51a8ace
--- /dev/null
+++ b/tests_and_examples/examples.acc/acc_nxtchld.c
@@ -0,0 +1,74 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * test of get_value using value change call back mechanism 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cv_veriuser.h>
+#include <veriuser.h>
+#include <acc_user.h>
+#include <cv_acc_user.h>
+
+/* int (*iproc_rtn)(handle); */
+
+/* local function prototypes */
+static void process_inst(handle); 
+
+/* global function prototypes */
+extern int process_all_insts(int, int);
+
+/*
+ * process instance from top
+ */
+int process_all_insts(int reason, int udata)
+{
+ int isiz;
+ handle topiref;
+
+ isiz = acc_count(acc_next_child, NULL);
+ io_printf("  There are %d top level modules.\n", isiz);
+ /* iproc_rtn = ???; */
+ /* build the iterator for each module */
+ for (topiref = NULL;;)
+  {
+   if ((topiref = acc_next_child(NULL, topiref)) == NULL) break;
+   process_inst(topiref);
+  }
+ io_printf("  >>> All instances processed by acc_.\n");
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static void process_inst(handle up_ihref) 
+{
+ int isiz;
+ handle ihref;
+
+ /* iproc_rtn(up_ihref); */
+ isiz = acc_count(acc_next_child, up_ihref);
+ io_printf("  There are %d instances in %s.\n", isiz,
+  acc_fetch_fullname(up_ihref));
+ for (ihref = NULL;;)
+  {
+   if ((ihref = acc_next_child(up_ihref, ihref)) == NULL) return;
+   process_inst(ihref);
+  }
+}
+
+s_tfcell veriusertfs[] = {
+ {usertask, 0, 0, 0, (int (*)()) process_all_insts, 0, "$dump_contents", 0 }, 
+ {0} /* this line must always be last */
+};
+
+/* dummy +loadpli1 boostrap routine - return old style veriusertfs tab */
+s_tfcell *pli1_compat_bootstrap(void)
+{
+ return(veriusertfs);
+}
diff --git a/tests_and_examples/examples.acc/acc_nxtchld.plg b/tests_and_examples/examples.acc/acc_nxtchld.plg
new file mode 100644
index 0000000..b4d51e0
--- /dev/null
+++ b/tests_and_examples/examples.acc/acc_nxtchld.plg
@@ -0,0 +1,88 @@
+**nc_fdsp.v(106) WARN** [653] $period timing check min:typ:max limit expression needs parentheses under 1364 - unportable
+  There are 1 top level modules.
+  There are 3 instances in test.
+  There are 0 instances in test.i1.
+  There are 0 instances in test.i2.
+  There are 0 instances in test.i3.
+  >>> All instances processed by acc_.
+         0 q=x, clk=x, data=x, clr=x, set=x
+testing set/clear logic
+      2000 q=x, clk=x, data=x, clr=x, set=0
+      2040 q=1, clk=x, data=x, clr=x, set=0
+      3000 q=1, clk=x, data=x, clr=0, set=0
+      4000 q=1, clk=x, data=x, clr=0, set=1
+      4050 q=0, clk=x, data=x, clr=0, set=1
+      5000 q=0, clk=x, data=x, clr=0, set=0
+      5040 q=1, clk=x, data=x, clr=0, set=0
+      6000 q=1, clk=x, data=x, clr=0, set=1
+      6050 q=0, clk=x, data=x, clr=0, set=1
+      7000 q=0, clk=x, data=x, clr=x, set=1
+      7040 q=x, clk=x, data=x, clr=x, set=1
+testing normal logic
+      8000 q=x, clk=x, data=0, clr=1, set=1
+      9000 q=x, clk=1, data=0, clr=1, set=1
+     10000 q=x, clk=0, data=0, clr=1, set=1
+     11000 q=x, clk=1, data=0, clr=1, set=1
+     11250 q=0, clk=1, data=0, clr=1, set=1
+     12000 q=0, clk=0, data=0, clr=1, set=1
+     13000 q=0, clk=1, data=0, clr=1, set=1
+     14000 q=0, clk=0, data=0, clr=1, set=1
+     15000 q=0, clk=x, data=0, clr=1, set=1
+     16000 q=0, clk=0, data=0, clr=1, set=1
+     17000 q=0, clk=z, data=0, clr=1, set=1
+     18000 q=0, clk=0, data=0, clr=1, set=1
+     19000 q=0, clk=x, data=0, clr=1, set=1
+**nc_fdsp.v(106) WARN** now 20000 [566] timing violation in test.i3 (diff. 1000)
+ $period((posedge clk):19000, (posedge clk):20000, 1200);
+     20000 q=0, clk=1, data=0, clr=1, set=1
+     21000 q=0, clk=1, data=1, clr=1, set=1
+     22000 q=0, clk=0, data=1, clr=1, set=1
+     23000 q=0, clk=1, data=1, clr=1, set=1
+     23140 q=1, clk=1, data=1, clr=1, set=1
+     24000 q=1, clk=0, data=1, clr=1, set=1
+     25000 q=1, clk=1, data=1, clr=1, set=1
+     26000 q=1, clk=0, data=1, clr=1, set=1
+**nc_fdsp.v(106) WARN** now 26100 [566] timing violation in test.i3 (diff. 1100)
+ $period((posedge clk):25000, (posedge clk):26100, 1200);
+**nc_fdsp.v(105) WARN** now 26100 [566] timing violation in test.i3 (diff. 100)
+ $width((negedge clk):26000, (posedge clk):26100, 500);
+     26100 q=1, clk=x, data=1, clr=1, set=1
+     27100 q=1, clk=0, data=1, clr=1, set=1
+     28100 q=1, clk=z, data=1, clr=1, set=1
+     29100 q=1, clk=0, data=1, clr=1, set=1
+     30100 q=1, clk=x, data=1, clr=1, set=1
+**nc_fdsp.v(106) WARN** now 31100 [566] timing violation in test.i3 (diff. 1000)
+ $period((posedge clk):30100, (posedge clk):31100, 1200);
+     31100 q=1, clk=1, data=1, clr=1, set=1
+**nc_fdsp.v(104) WARN** now 31130 [566] timing violation in test.i3 (diff. 30)
+ $width((posedge clk):31100, (negedge clk):31130, 600);
+     31130 q=1, clk=0, data=1, clr=1, set=1
+**nc_fdsp.v(106) WARN** now 31190 [566] timing violation in test.i3 (diff. 90)
+ $period((posedge clk):31100, (posedge clk):31190, 1200);
+**nc_fdsp.v(105) WARN** now 31190 [566] timing violation in test.i3 (diff. 60)
+ $width((negedge clk):31130, (posedge clk):31190, 500);
+     31190 q=1, clk=1, data=1, clr=1, set=1
+**nc_fdsp.v(102) WARN** now 31220 [566] timing violation in test.i3 (diff. 30)
+ hold(of setuphold)((posedge clk):31190, d:31220, 50);
+     31220 q=1, clk=1, data=0, clr=1, set=1
+**nc_fdsp.v(104) WARN** now 31250 [566] timing violation in test.i3 (diff. 60)
+ $width((posedge clk):31190, (negedge clk):31250, 600);
+     31250 q=1, clk=0, data=0, clr=1, set=1
+     31280 q=1, clk=0, data=1, clr=1, set=1
+**nc_fdsp.v(108) WARN** now 31310 [566] timing violation in test.i3 (diff. 30)
+ $recovery((posedge d):31280, clk:31310, 200);
+**nc_fdsp.v(106) WARN** now 31310 [566] timing violation in test.i3 (diff. 120)
+ $period((posedge clk):31190, (posedge clk):31310, 1200);
+**nc_fdsp.v(105) WARN** now 31310 [566] timing violation in test.i3 (diff. 60)
+ $width((negedge clk):31250, (posedge clk):31310, 500);
+**nc_fdsp.v(102) WARN** now 31310 [566] timing violation in test.i3 (diff. 30)
+ setup(of setuphold)(d:31280, (posedge clk):31310, 70);
+     31310 q=1, clk=1, data=1, clr=1, set=1
+**nc_fdsp.v(108) WARN** now 31410 [566] timing violation in test.i3 (diff. 130)
+ $recovery((posedge d):31280, clk:31410, 200);
+**nc_fdsp.v(104) WARN** now 31410 [566] timing violation in test.i3 (diff. 100)
+ $width((posedge clk):31310, (negedge clk):31410, 600);
+     31410 q=1, clk=0, data=1, clr=1, set=1
+**nc_fdsp.v(107) WARN** now 33510 [566] timing violation in test.i3 (diff. 2000)
+ $skew((posedge clk1):31510, (posedge clk):33510, 50);
+     33510 q=1, clk=1, data=1, clr=1, set=1
diff --git a/tests_and_examples/examples.acc/acc_probe.c b/tests_and_examples/examples.acc/acc_probe.c
new file mode 100644
index 0000000..2cb0f25
--- /dev/null
+++ b/tests_and_examples/examples.acc/acc_probe.c
@@ -0,0 +1,210 @@
+/* Copyright (c) 1994-2003 Pragmatic C Software Corp. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <veriuser.h>
+#include <cv_veriuser.h>
+#include <acc_user.h>
+
+#define MAXSIZE 500 
+/* #define MAXSIZE 1 */
+
+/* up to 10 parameters, MAXSIZE time values up to 64 bits long */ 
+/* but must be vector */ 
+/* (16 chars plus 0 end byte) */
+static char value_ar[10][MAXSIZE][17];  
+static int time_ar[MAXSIZE];
+static int *udata_ar;
+
+static int total_nump;
+static int last_entry = 0;
+static int setup_errors = FALSE;
+static handle setup_inst_p = NULL; 
+
+/* local function prototypes */
+static void vu_setup_values(void);
+static int vu_update_values(p_vc_record);
+static void vu_doupdate(handle, int);
+static void vu_flash_values(void);
+
+static void vu_setup_checktf(int data, int reason)
+{
+ register int nparam;
+ int htyp;
+ handle argh, instref;
+
+ acc_initialize();
+
+ total_nump = tf_nump();
+ /* get the setup instance for updating values */
+ instref = acc_handle_tfinst();
+ if (acc_error_flag)
+  {
+   tf_error("in vu_setup_check: acc_handle_tfinst failed.");
+   setup_errors = TRUE;
+  }
+ for (nparam = 1; nparam <= total_nump; nparam++)
+  { 
+   argh = acc_handle_tfarg(nparam);
+   htyp = acc_fetch_type(argh);
+   /* variables autmotically legal */  
+   if (htyp == accIntegerVar || htyp == accTimeVar) continue;
+
+   if (htyp != accNet && htyp != accReg)
+    {
+     tf_error(
+      "in vu_setup_check: argument pos. %d illegal - must be a variable");
+     setup_errors = TRUE;
+     continue;
+    }
+ 
+   /* net or reg must be vector */
+   if (acc_fetch_size(argh) == 1)
+    {
+     tf_error(
+      "in vu_setup_check: argument %s (pos. %d) illegal - must be vector",
+      acc_fetch_name(argh), nparam);
+     setup_errors = TRUE;
+    }
+  }
+ acc_close();
+}
+
+/*
+ * calltf routine called when $setup_value called
+ */
+static void vu_setup_values(void)
+{
+ register int nparam;
+ handle argh;
+
+ acc_initialize();
+ if (setup_errors)
+  {
+   tf_error(
+   "$setup_values did not setup value flashing - previous error");
+   return;
+  }
+ acc_initialize();
+ /* get total number of parameters */
+ total_nump = tf_nump();
+
+ /* get the setup instance for updating values */
+ setup_inst_p = acc_handle_tfinst();
+ if (acc_error_flag) tf_error("in vu_setup_value: acc_handle_tfinst failed.");
+  
+ last_entry = 0; 
+
+ /* if this is a second call to setup and asynchronous updating has been */
+ /* disabled then resume the asynchronous calls */
+ /* notice acc_ pnums start at 1 */
+ udata_ar = (int *) malloc((total_nump + 1)*sizeof(int)); 
+ for (nparam = 1; nparam <= total_nump; nparam++)
+ { 
+  argh = acc_handle_tfarg(nparam);
+  udata_ar[nparam] = nparam;
+  /* setup call back */
+  acc_vcl_add(argh, vu_update_values, (char *) &(udata_ar[nparam]),
+   vcl_verilog_logic);  
+  /* save initial value */
+  vu_doupdate(argh, nparam);
+ }
+ acc_close();
+}
+ 
+/* 
+ * here updating on any value change not just one at end of time slot
+ */
+static int vu_update_values(p_vc_record vcrp)
+{
+ handle argh;
+ int pnum;
+ char s1[1024];
+
+ acc_initialize();
+ /* SJM 01/10/02 - model was wrong - acc user_data is char - need cast */
+ pnum = *((int *) (vcrp->user_data));
+ argh = acc_handle_itfarg(pnum, setup_inst_p);
+ if (acc_error_flag)
+  {
+   tf_error("in vu_update_values: acc_handle_itfarg failed.");
+   return(0);
+  }
+ strcpy(s1, acc_fetch_name(argh));
+ io_printf("now %d parameter %d (name is %s) changed\n", tf_gettime(), pnum,
+  s1);
+ vu_doupdate(argh, pnum);
+ acc_close();
+ return(0);
+}
+
+/*
+ * update the value - version that does not use vcl info
+ */
+static void vu_doupdate(handle argh, int nparam)
+{
+ handle argh2;
+
+ /* if flash table filled - emit error and remove callback from every arg */
+ if (++last_entry == MAXSIZE)
+  {
+   io_printf("*** flash table filled - removing value change vcls ***\n");
+   for (nparam = 1; nparam <= total_nump; nparam++)
+    { 
+     argh2 = acc_handle_tfarg(nparam);
+     /* remove vcl */
+     acc_vcl_delete(argh2, vu_update_values, (char *) &(udata_ar[nparam]),
+      vcl_verilog_logic);  
+    }
+   return;
+  } 
+ /* after vcl's removed do nothing - LOOKATME - but think should get here */
+ if (last_entry > MAXSIZE) return;
+
+ /* obtain current simulation time */ 
+ time_ar[last_entry] = tf_gettime();
+ /* FIXME - also test acc_fetch_tfarg_str */
+ strcpy(value_ar[nparam][last_entry], acc_fetch_value(argh, "%d", NULL));
+ io_printf("** now %d assign %s to param %d\n", time_ar[last_entry],
+  value_ar[nparam][last_entry], nparam);
+}
+
+/* this routine displays the values of variables at a given time */
+static void vu_flash_values(void)
+{
+ int nparam, find_time, entry_num;
+
+ if (last_entry >= MAXSIZE)
+  {
+   io_printf("*** flash table filled - values not flashed ***\n");
+   return;
+  }
+
+ acc_initialize();
+ /* get the value of time which is the only param */
+ find_time = tf_getp(1);
+ for (entry_num = last_entry; (entry_num > 0); entry_num--)
+  if (time_ar[entry_num] <= find_time)
+   break;
+ io_printf("For time %d\n", find_time);
+ /* this needs to go from 1 to number of params since task not func */ 
+ for (nparam = 1; nparam <= total_nump; nparam++)
+  io_printf("    value of parameter %d = %s\n", nparam,
+   value_ar[nparam][entry_num]);
+ acc_close();
+} 
+
+s_tfcell veriusertfs[] = {
+ {usertask, 0, (int (*)()) vu_setup_checktf, 0, (int (*)()) vu_setup_values,
+  0, "$setup_values", 0 }, 
+ {usertask, 0, 0, 0, (int (*)()) vu_flash_values, 0, "$flash_values", 0 }, 
+ {0} /* this line must always be last */
+};
+
+/* dummy +loadpli1 boostrap routine - return old style veriusertfs tab */
+s_tfcell *pli1_compat_bootstrap(void)
+{
+ return(veriusertfs);
+}
diff --git a/tests_and_examples/examples.acc/acc_probe.plg b/tests_and_examples/examples.acc/acc_probe.plg
new file mode 100644
index 0000000..0700ae7
--- /dev/null
+++ b/tests_and_examples/examples.acc/acc_probe.plg
@@ -0,0 +1,69 @@
+** now 0 assign          x to param 1
+** now 0 assign          x to param 2
+** now 0 assign          x to param 3
+now 10 parameter 1 (name is a) changed
+** now 10 assign          3 to param 1
+now 10 parameter 3 (name is c) changed
+** now 10 assign          1 to param 3
+For time 5
+    value of parameter 1 = 
+    value of parameter 2 = 
+    value of parameter 3 =          x
+now 20 parameter 2 (name is b) changed
+** now 20 assign          3 to param 2
+now 20 parameter 3 (name is c) changed
+** now 20 assign          2 to param 3
+For time 10
+    value of parameter 1 = 
+    value of parameter 2 = 
+    value of parameter 3 =          1
+now 30 parameter 3 (name is c) changed
+** now 30 assign          3 to param 3
+For time 15
+    value of parameter 1 = 
+    value of parameter 2 = 
+    value of parameter 3 =          1
+now 40 parameter 1 (name is a) changed
+** now 40 assign         33 to param 1
+now 40 parameter 3 (name is c) changed
+** now 40 assign          9 to param 3
+For time 20
+    value of parameter 1 = 
+    value of parameter 2 = 
+    value of parameter 3 =          2
+now 50 parameter 2 (name is b) changed
+** now 50 assign         44 to param 2
+now 50 parameter 3 (name is c) changed
+** now 50 assign         22 to param 3
+For time 25
+    value of parameter 1 = 
+    value of parameter 2 = 
+    value of parameter 3 =          2
+now 60 parameter 1 (name is a) changed
+** now 60 assign         30 to param 1
+now 70 parameter 1 (name is a) changed
+** now 70 assign         50 to param 1
+now 70 parameter 2 (name is b) changed
+** now 70 assign        200 to param 2
+now 70 parameter 3 (name is c) changed
+** now 70 assign          0 to param 3
+For time 35
+    value of parameter 1 = 
+    value of parameter 2 = 
+    value of parameter 3 =          3
+now 80 parameter 3 (name is c) changed
+** now 80 assign         99 to param 3
+For time 40
+    value of parameter 1 = 
+    value of parameter 2 = 
+    value of parameter 3 =          9
+now 90 parameter 2 (name is b) changed
+** now 90 assign         90 to param 2
+now 100 parameter 2 (name is b) changed
+** now 100 assign         11 to param 2
+now 100 parameter 3 (name is c) changed
+** now 100 assign         19 to param 3
+For time 50
+    value of parameter 1 = 
+    value of parameter 2 = 
+    value of parameter 3 =         22
diff --git a/tests_and_examples/examples.acc/acc_prtchg.c b/tests_and_examples/examples.acc/acc_prtchg.c
new file mode 100644
index 0000000..904cdcf
--- /dev/null
+++ b/tests_and_examples/examples.acc/acc_prtchg.c
@@ -0,0 +1,288 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * test of acc vcls
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "acc_user.h"
+#include "cv_acc_user.h"
+#include "veriuser.h"
+#include "cv_veriuser.h"
+
+/* local function prototypes */
+static int process_inst(handle); 
+static void setup_1scope_chgcbs(handle);
+static void add_vcl(handle);
+
+/* global function prototypes */
+extern int process_all_insts(int, int);
+extern int setup_varchgcbs(handle);
+extern int wire_prt_vclchg(p_vc_record);
+extern int var_prt_vclchg(p_vc_record);
+
+/*
+ * routine to get and zero all delays in design 
+ */
+int process_all_insts(int reason, int udata)
+{
+ handle topinst;
+
+ for (topinst = NULL;;)
+  {
+   if ((topinst = acc_next_child(NULL, topinst)) == NULL) break;
+   process_inst(topinst);
+  }
+ io_printf("  >>> All instances processed\n");
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static int process_inst(handle upinst) 
+{
+ handle scope, inst, net, bit, var, prim, term, port;
+ static int varlist[] = { accReg, accIntegerVar, accTimeVar, 0 };
+
+ io_printf("... setting up vcls for instance %s\n",
+  acc_fetch_fullname(upinst));
+
+ /* first strength vcls on all nets */
+ /* first add vcls for nets */
+ io_printf("... vcls for wires\n");
+ for (net = acc_next_net(upinst, NULL); net != NULL;
+  net = acc_next_net(upinst, net))
+  {
+   if (acc_fetch_size(net) == 1) add_vcl(net);
+   else
+    {
+     /* for vector wires, must put vcl on bit - need to access strength */
+     for (bit = acc_next_bit(net, NULL); bit != NULL;
+      bit = acc_next_bit(net, bit)) add_vcl(bit);
+    }
+  }
+ /* then variables */
+ io_printf("... vcls for variables\n"); 
+ for (var = acc_next(varlist, upinst, NULL); var != NULL;
+  var = acc_next(varlist, upinst, var)) add_vcl(var);
+
+ io_printf("... vcls for primitive terminals\n"); 
+ /* then primitives output terminals */
+ for (prim = acc_next_primitive(upinst, NULL); prim != NULL;
+  prim = acc_next_primitive(upinst, prim))
+   {
+    for (term = acc_next_terminal(prim, NULL); term != NULL;
+     term = acc_next_terminal(prim, term))
+     {
+      /* only output terminals can have vcl added */
+      if (acc_fetch_direction(term) == accInput) continue;
+      add_vcl(term);
+     }
+   }
+
+ /* then module ports */
+ io_printf("... vcls for ports\n"); 
+ for (port = acc_next_port(upinst, NULL); port != NULL;
+  port = acc_next_port(upinst, port))
+  {
+   if (acc_fetch_size(port) == 1) add_vcl(port);
+   else
+    {
+     /* for vector ports, must put vcl on bit - need to access strength */
+     for (bit = acc_next_bit(port, NULL); bit != NULL;
+      bit = acc_next_bit(port, bit)) add_vcl(bit);
+    }
+  }
+
+ /* finally all variables in contained scopes */
+ for (scope = acc_next_scope(upinst, NULL); scope != NULL;
+  scope = acc_next_scope(upinst, scope))
+  {
+   /* final step setup vcls for contained scopes */
+   setup_1scope_chgcbs(scope);
+  }
+
+ for (inst = NULL;;)
+  {
+   if ((inst = acc_next_child(upinst, inst)) == NULL) break;
+   process_inst(inst);
+  }
+ return(0);
+}
+
+/*
+ * set up change call back for all nets/regs of some type in iter
+ *
+ * now sure how acc_supposed to work - scopes inside module instance
+ * are all tasks, functions, and labeled blocks in init/always blocks
+ */
+static void setup_1scope_chgcbs(handle scope)
+{
+ static int varlist[] = { accReg, accIntegerVar, accTimeVar, 0 };
+ handle inscope, var;
+
+ io_printf("... setting up vcls for scope %s\n", acc_fetch_fullname(scope));
+
+ /* set up value change call backs for all variables in this scope */
+ for (var = acc_next(varlist, scope, NULL); var != NULL;
+  var = acc_next(varlist, scope, var)) add_vcl(var);
+
+ /* also or all contained scopes */
+ for (inscope = acc_next_scope(scope, NULL); inscope != NULL;
+  inscope = acc_next_scope(scope, inscope)) setup_1scope_chgcbs(inscope);
+}
+
+/*
+ * routine to add vcl to one net/reg/var/event
+ */
+static void add_vcl(handle net)
+{
+ int typ, fulltyp;
+ char s1[1024];
+
+ /* DBG remove -- */
+ typ = acc_fetch_type(net);
+ fulltyp = acc_fetch_fulltype(net);
+ if (typ != accTerminal) strcpy(s1, acc_fetch_fullname(net));
+ else strcpy(s1, "**terminal**");
+ io_printf("Adding vcl for %s type %s (fulltype %s)\n", s1,
+  acc_fetch_type_str(typ), acc_fetch_type_str(fulltyp));
+ /* --- */
+
+ if (typ == accNet)
+  {
+   acc_vcl_add(net, wire_prt_vclchg, (void *) net, vcl_verilog_strength);  
+  }
+ else acc_vcl_add(net, var_prt_vclchg, (void *) net, vcl_verilog_logic);  
+}
+
+/*
+ * wire strength change value change call back routine
+ */
+int wire_prt_vclchg(p_vc_record vcp)
+{
+ /* unsigned long long now, chgtim; */
+ int typ, ltime, htime;
+ handle net;
+ char s1[1024], s2[1024], s3[1024];
+
+ /* current time */
+ ltime = tf_getlongsimtime(&htime);
+ /* ---
+ now = ((unsigned long long) ((unsigned long) htime)) << 32
+  | ((unsigned long long) ((unsigned long) ltime));
+
+ -* vc record time *- 
+ chgtim = ((unsigned long long) ((unsigned long) vcp->vc_hightime)) << 32
+  | ((unsigned long long) ((unsigned long) vcp->vc_lowtime));
+ --- */
+
+ /* net handle assigned to user data field */
+ net = (handle) vcp->user_data; 
+
+ /* build strength value string */
+ sprintf(s1, "<%d, %d>=%d", (int) vcp->out_value.strengths_s.strength1, 
+  (int) vcp->out_value.strengths_s.strength2,   
+  (int) vcp->out_value.strengths_s.logic_value);
+ 
+ /* also get value as internal strength %v string */
+ strcpy(s2, acc_fetch_value(net, "%v", NULL));
+
+ if (vcp->vc_reason != strength_value_change)
+  {
+   io_printf("*** ERROR: wire change reason %d - strength change expected\n",
+    vcp->vc_reason);
+  }
+ /* ---
+ io_printf("--> now %uL (chg time %uL): %s=%s(%s)\n", now, chgtim,
+ -- */
+
+ /* terminals do not have names */
+ typ = acc_fetch_type(net);
+ if (typ != accTerminal) strcpy(s3, acc_fetch_fullname(net));
+ else strcpy(s3, "**terminal**");
+
+ io_printf("--> now %d (chg time %d): %s=%s(%s)\n", ltime, vcp->vc_lowtime,
+  s3, s2, s1); 
+ return(0);
+}
+
+/*
+ * variable value change call back routine
+ */
+int var_prt_vclchg(p_vc_record vcp)
+{
+ /* unsigned long long now, chgtim; */
+ int otyp, ltime, htime;
+ handle net;
+ char s1[1024], s2[1024], s3[1024];
+
+ /* current time */
+ ltime = tf_getlongsimtime(&htime);
+ /* -- 
+ now = ((unsigned long long) ((unsigned long) htime)) << 32
+  | ((unsigned long long) ((unsigned long) ltime));
+
+ -* vc record time *- 
+ chgtim = ((unsigned long long) ((unsigned long) vcp->vc_hightime)) << 32
+  | ((unsigned long long) ((unsigned long) vcp->vc_lowtime));
+ -- */
+
+ /* net handle assigned to user data field */
+ net = (handle) vcp->user_data; 
+ otyp = acc_fetch_type(net);
+
+ if (vcp->vc_reason != event_value_change)
+  {
+   /* these do not have value, i.e. get va8ue return NULL with error */
+   if (otyp == accPort || otyp == accPortBit || otyp == accTerminal)
+    {
+     sprintf(s1, "obj=%s", acc_fetch_type_str(otyp));
+    }
+   else strcpy(s1, acc_fetch_value(net, "%b", NULL));
+  }
+
+ switch (vcp->vc_reason) {
+  case logic_value_change:
+   sprintf(s2, "scalar=%u(%s)", (unsigned) vcp->out_value.logic_value, s1); 
+   break;
+  case sregister_value_change:
+   sprintf(s2, "sr-scalar=%u(%s)", (unsigned) vcp->out_value.logic_value, s1); 
+   break;
+  case real_value_change: case realtime_value_change:
+   sprintf(s2, "**error**");
+   break;
+  case event_value_change:
+   strcpy(s2, "**event**");
+   break;
+  default:
+   sprintf(s2, "vector=%s", s1);
+ }  
+
+ /* --
+ io_printf("--> now %uL (chg time %uL): %s=%s\n", now, chgtim,
+ -- */
+
+ if (otyp != accTerminal) strcpy(s3, acc_fetch_fullname(net));
+ else strcpy(s3, "**terminal**");
+
+ io_printf("--> now %d (chg time %d): %s=%s\n", ltime, vcp->vc_lowtime, s3,
+  s2); 
+ return(0);
+}
+
+s_tfcell veriusertfs[] = {
+ { usertask, 0, 0, 0, (int (*)()) process_all_insts, 0, "$test", 0 }, 
+ {0} /* this line must always be last */
+};
+
+/* dummy +loadpli1 boostrap routine - return old style veriusertfs tab */
+s_tfcell *pli1_compat_bootstrap(void)
+{
+ return(veriusertfs);
+}
diff --git a/tests_and_examples/examples.acc/accxl_drvld.c b/tests_and_examples/examples.acc/accxl_drvld.c
new file mode 100644
index 0000000..83770b1
--- /dev/null
+++ b/tests_and_examples/examples.acc/accxl_drvld.c
@@ -0,0 +1,181 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * test of get_value using value change call back mechanism 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cv_veriuser.h"
+#include "veriuser.h"
+#include "acc_user.h"
+#include "cv_acc_user.h"
+
+/* int (*iproc_rtn)(handle); */
+
+/* local function prototypes */
+static void process_inst(handle); 
+static void mei_count_drivers(handle, handle);
+static void mei_count_loads(handle, handle);
+static void mei_count_cellloads(handle, handle);
+static int mei_isinside(handle, handle);
+
+/* global function prototypes */
+extern int process_all_insts(int, int);
+
+/*
+ * process instances top down
+ */
+int process_all_insts(int reason, int udata)
+{
+ handle topinst;
+
+ for (topinst = NULL;;)
+  {
+   if ((topinst = acc_next_child(NULL, topinst)) == NULL) break;
+   process_inst(topinst);
+  }
+ io_printf("  >>> All instances net drivers processed by acc_.\n");
+ tf_dofinish();
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static void process_inst(handle upinst) 
+{
+ handle inst, net;
+
+ io_printf("... processing instance %s.\n", acc_fetch_fullname(upinst));
+
+ for (net = acc_next_net(upinst, NULL); net != NULL;
+  net = acc_next_net(upinst, net))
+  {
+   mei_count_drivers(upinst, net);
+   mei_count_loads(upinst, net);
+   mei_count_cellloads(upinst, net);
+  }
+ 
+ for (inst = NULL;;)
+  {
+   if ((inst = acc_next_child(upinst, inst)) == NULL) return;
+   process_inst(inst);
+  }
+}
+
+/*
+ * count and list all acc world (prim terminal) drivers
+ */
+void mei_count_drivers(handle inst, handle net)
+{
+ int count = 0;
+ handle term;
+ char s1[1024], s2[1024];
+ 
+ io_printf(" ... processing drivers for %s:\n", acc_fetch_fullname(net));
+ for (term = acc_next_driver(net, NULL); term != NULL;
+  term = acc_next_driver(net, term))
+  {
+   if (mei_isinside(inst, term) == 1) { strcpy(s1, "inside"); count++; }
+   else strcpy(s1, "outside");
+
+   if (acc_fetch_type(term) == accTerminal)
+    {
+     sprintf(s2, "prim %s port %d", acc_fetch_fullname(acc_handle_parent(term)),
+      acc_fetch_index(term));
+    }
+   else strcpy(s2, acc_fetch_fullname(term));
+
+   io_printf(" +++ %s is %s driver of %s in %s.\n", s2,
+    s1, acc_fetch_fullname(net), acc_fetch_fullname(inst));
+  }
+ io_printf("net %s has %d inside drivers.\n", acc_fetch_name(net), count);
+}
+
+/*
+ * return 1 if obj inside inst
+ */
+int mei_isinside(handle inst, handle obj)
+{
+ handle parent;
+
+ for (parent = acc_handle_parent(obj); parent != NULL;
+  parent = acc_handle_parent(parent))
+  {
+   if (acc_compare_handles(parent, inst)) return(1);
+  }
+ return(0);
+}
+
+/*
+ * count and list all acc world (prim terminal) drivers
+ */
+void mei_count_loads(handle inst, handle net)
+{
+ int count = 0;
+ handle term;
+ char s1[1024], s2[1024];
+ 
+ io_printf(" ... processing loads for %s:\n", acc_fetch_fullname(net));
+ for (term = acc_next_load(net, NULL); term != NULL;
+  term = acc_next_load(net, term))
+  {
+   if (mei_isinside(inst, term) == 0) { strcpy(s1, "outside"); count++; }
+   else strcpy(s1, "inside");
+
+   if (acc_fetch_type(term) == accTerminal)
+    {
+     sprintf(s2, "prim %s port %d", acc_fetch_fullname(acc_handle_parent(term)),
+      acc_fetch_index(term));
+    }
+   else strcpy(s2, acc_fetch_fullname(term));
+
+   io_printf(" +++ %s is %s load of %s in %s.\n", s2,
+    s1, acc_fetch_fullname(net), acc_fetch_fullname(inst));
+  }
+ io_printf("net %s has %d outside loads.\n", acc_fetch_name(net), count);
+}
+
+/*
+ * count and list all acc world (prim terminal) drivers
+ */
+void mei_count_cellloads(handle inst, handle net)
+{
+ int count = 0;
+ handle term;
+ char s1[1024], s2[1024];
+ 
+ io_printf(" ... processing cell loads for %s:\n", acc_fetch_fullname(net));
+ for (term = acc_next_load(net, NULL); term != NULL;
+  term = acc_next_load(net, term))
+  {
+   if (mei_isinside(inst, term) == 1) { strcpy(s1, "inside"); count++; }
+   else strcpy(s1, "outside");
+
+   if (acc_fetch_type(term) == accTerminal)
+    {
+     sprintf(s2, "prim %s port %d", acc_fetch_fullname(acc_handle_parent(term)),
+      acc_fetch_index(term));
+    }
+   else strcpy(s2, acc_fetch_fullname(term));
+
+   io_printf(" +++ %s is %s load of %s in %s.\n", s2,
+    s1, acc_fetch_fullname(net), acc_fetch_fullname(inst));
+  }
+ io_printf("net %s has %d inside cell loads.\n", acc_fetch_name(net), count);
+}
+
+s_tfcell veriusertfs[] = {
+ { usertask, 0, 0, 0, (int (*)()) process_all_insts, 0, "$test", 0 }, 
+ {0} /* this line must always be last */
+};
+
+/* dummy +loadpli1 boostrap routine - return old style veriusertfs tab */
+s_tfcell *pli1_compat_bootstrap(void)
+{
+ return(veriusertfs);
+}
diff --git a/tests_and_examples/examples.acc/accxldrvtst.plg b/tests_and_examples/examples.acc/accxldrvtst.plg
new file mode 100644
index 0000000..e8db192
--- /dev/null
+++ b/tests_and_examples/examples.acc/accxldrvtst.plg
@@ -0,0 +1,263 @@
+... processing instance test.
+ ... processing drivers for test.t_clr0:
+net t_clr0 has 0 inside drivers.
+ ... processing loads for test.t_clr0:
+ +++ prim test.i1.i0 port 3 is inside load of test.t_clr0 in test.
+net t_clr0 has 0 outside loads.
+ ... processing cell loads for test.t_clr0:
+ +++ prim test.i1.i0 port 3 is inside load of test.t_clr0 in test.
+net t_clr0 has 1 inside cell loads.
+ ... processing drivers for test.t_clr1:
+net t_clr1 has 0 inside drivers.
+ ... processing loads for test.t_clr1:
+ +++ prim test.i2.i0 port 3 is inside load of test.t_clr1 in test.
+net t_clr1 has 0 outside loads.
+ ... processing cell loads for test.t_clr1:
+ +++ prim test.i2.i0 port 3 is inside load of test.t_clr1 in test.
+net t_clr1 has 1 inside cell loads.
+ ... processing drivers for test.t_d0:
+net t_d0 has 0 inside drivers.
+ ... processing loads for test.t_d0:
+ +++ prim test.i1.i0 port 1 is inside load of test.t_d0 in test.
+net t_d0 has 0 outside loads.
+ ... processing cell loads for test.t_d0:
+ +++ prim test.i1.i0 port 1 is inside load of test.t_d0 in test.
+net t_d0 has 1 inside cell loads.
+ ... processing drivers for test.t_d1:
+net t_d1 has 0 inside drivers.
+ ... processing loads for test.t_d1:
+ +++ prim test.i2.i0 port 1 is inside load of test.t_d1 in test.
+net t_d1 has 0 outside loads.
+ ... processing cell loads for test.t_d1:
+ +++ prim test.i2.i0 port 1 is inside load of test.t_d1 in test.
+net t_d1 has 1 inside cell loads.
+ ... processing drivers for test.t_q:
+ +++ prim test.i3.i1 port 0 is inside driver of test.t_q in test.
+net t_q has 1 inside drivers.
+ ... processing loads for test.t_q:
+net t_q has 0 outside loads.
+ ... processing cell loads for test.t_q:
+net t_q has 0 inside cell loads.
+ ... processing drivers for test.t_q0:
+ +++ prim test.i1.i1 port 0 is inside driver of test.t_q0 in test.
+net t_q0 has 1 inside drivers.
+ ... processing loads for test.t_q0:
+net t_q0 has 0 outside loads.
+ ... processing cell loads for test.t_q0:
+net t_q0 has 0 inside cell loads.
+ ... processing drivers for test.t_q1:
+ +++ prim test.i2.i1 port 0 is inside driver of test.t_q1 in test.
+net t_q1 has 1 inside drivers.
+ ... processing loads for test.t_q1:
+net t_q1 has 0 outside loads.
+ ... processing cell loads for test.t_q1:
+net t_q1 has 0 inside cell loads.
+ ... processing drivers for test.t_set0:
+net t_set0 has 0 inside drivers.
+ ... processing loads for test.t_set0:
+ +++ prim test.i1.i0 port 4 is inside load of test.t_set0 in test.
+net t_set0 has 0 outside loads.
+ ... processing cell loads for test.t_set0:
+ +++ prim test.i1.i0 port 4 is inside load of test.t_set0 in test.
+net t_set0 has 1 inside cell loads.
+ ... processing drivers for test.t_set1:
+net t_set1 has 0 inside drivers.
+ ... processing loads for test.t_set1:
+ +++ prim test.i2.i0 port 4 is inside load of test.t_set1 in test.
+net t_set1 has 0 outside loads.
+ ... processing cell loads for test.t_set1:
+ +++ prim test.i2.i0 port 4 is inside load of test.t_set1 in test.
+net t_set1 has 1 inside cell loads.
+... processing instance test.i1.
+ ... processing drivers for test.i1.clk:
+net clk has 0 inside drivers.
+ ... processing loads for test.i1.clk:
+ +++ prim test.i1.i0 port 2 is inside load of test.i1.clk in test.i1.
+net clk has 0 outside loads.
+ ... processing cell loads for test.i1.clk:
+ +++ prim test.i1.i0 port 2 is inside load of test.i1.clk in test.i1.
+net clk has 1 inside cell loads.
+ ... processing drivers for test.i1.clk1:
+net clk1 has 0 inside drivers.
+ ... processing loads for test.i1.clk1:
+net clk1 has 0 outside loads.
+ ... processing cell loads for test.i1.clk1:
+net clk1 has 0 inside cell loads.
+ ... processing drivers for test.i1.clr:
+net clr has 0 inside drivers.
+ ... processing loads for test.i1.clr:
+ +++ prim test.i1.i0 port 3 is inside load of test.i1.clr in test.i1.
+net clr has 0 outside loads.
+ ... processing cell loads for test.i1.clr:
+ +++ prim test.i1.i0 port 3 is inside load of test.i1.clr in test.i1.
+net clr has 1 inside cell loads.
+ ... processing drivers for test.i1.d:
+net d has 0 inside drivers.
+ ... processing loads for test.i1.d:
+ +++ prim test.i1.i0 port 1 is inside load of test.i1.d in test.i1.
+net d has 0 outside loads.
+ ... processing cell loads for test.i1.d:
+ +++ prim test.i1.i0 port 1 is inside load of test.i1.d in test.i1.
+net d has 1 inside cell loads.
+ ... processing drivers for test.i1.q:
+ +++ prim test.i1.i1 port 0 is inside driver of test.i1.q in test.i1.
+net q has 1 inside drivers.
+ ... processing loads for test.i1.q:
+net q has 0 outside loads.
+ ... processing cell loads for test.i1.q:
+net q has 0 inside cell loads.
+ ... processing drivers for test.i1.qn:
+ +++ prim test.i1.i2 port 0 is inside driver of test.i1.qn in test.i1.
+net qn has 1 inside drivers.
+ ... processing loads for test.i1.qn:
+net qn has 0 outside loads.
+ ... processing cell loads for test.i1.qn:
+net qn has 0 inside cell loads.
+ ... processing drivers for test.i1.set:
+net set has 0 inside drivers.
+ ... processing loads for test.i1.set:
+ +++ prim test.i1.i0 port 4 is inside load of test.i1.set in test.i1.
+net set has 0 outside loads.
+ ... processing cell loads for test.i1.set:
+ +++ prim test.i1.i0 port 4 is inside load of test.i1.set in test.i1.
+net set has 1 inside cell loads.
+ ... processing drivers for test.i1.xxx:
+ +++ prim test.i1.i0 port 0 is inside driver of test.i1.xxx in test.i1.
+net xxx has 1 inside drivers.
+ ... processing loads for test.i1.xxx:
+ +++ prim test.i1.i2 port 1 is inside load of test.i1.xxx in test.i1.
+ +++ prim test.i1.i1 port 1 is inside load of test.i1.xxx in test.i1.
+net xxx has 0 outside loads.
+ ... processing cell loads for test.i1.xxx:
+ +++ prim test.i1.i2 port 1 is inside load of test.i1.xxx in test.i1.
+ +++ prim test.i1.i1 port 1 is inside load of test.i1.xxx in test.i1.
+net xxx has 2 inside cell loads.
+... processing instance test.i2.
+ ... processing drivers for test.i2.clk:
+net clk has 0 inside drivers.
+ ... processing loads for test.i2.clk:
+ +++ prim test.i2.i0 port 2 is inside load of test.i2.clk in test.i2.
+net clk has 0 outside loads.
+ ... processing cell loads for test.i2.clk:
+ +++ prim test.i2.i0 port 2 is inside load of test.i2.clk in test.i2.
+net clk has 1 inside cell loads.
+ ... processing drivers for test.i2.clk1:
+net clk1 has 0 inside drivers.
+ ... processing loads for test.i2.clk1:
+net clk1 has 0 outside loads.
+ ... processing cell loads for test.i2.clk1:
+net clk1 has 0 inside cell loads.
+ ... processing drivers for test.i2.clr:
+net clr has 0 inside drivers.
+ ... processing loads for test.i2.clr:
+ +++ prim test.i2.i0 port 3 is inside load of test.i2.clr in test.i2.
+net clr has 0 outside loads.
+ ... processing cell loads for test.i2.clr:
+ +++ prim test.i2.i0 port 3 is inside load of test.i2.clr in test.i2.
+net clr has 1 inside cell loads.
+ ... processing drivers for test.i2.d:
+net d has 0 inside drivers.
+ ... processing loads for test.i2.d:
+ +++ prim test.i2.i0 port 1 is inside load of test.i2.d in test.i2.
+net d has 0 outside loads.
+ ... processing cell loads for test.i2.d:
+ +++ prim test.i2.i0 port 1 is inside load of test.i2.d in test.i2.
+net d has 1 inside cell loads.
+ ... processing drivers for test.i2.q:
+ +++ prim test.i2.i1 port 0 is inside driver of test.i2.q in test.i2.
+net q has 1 inside drivers.
+ ... processing loads for test.i2.q:
+net q has 0 outside loads.
+ ... processing cell loads for test.i2.q:
+net q has 0 inside cell loads.
+ ... processing drivers for test.i2.qn:
+ +++ prim test.i2.i2 port 0 is inside driver of test.i2.qn in test.i2.
+net qn has 1 inside drivers.
+ ... processing loads for test.i2.qn:
+net qn has 0 outside loads.
+ ... processing cell loads for test.i2.qn:
+net qn has 0 inside cell loads.
+ ... processing drivers for test.i2.set:
+net set has 0 inside drivers.
+ ... processing loads for test.i2.set:
+ +++ prim test.i2.i0 port 4 is inside load of test.i2.set in test.i2.
+net set has 0 outside loads.
+ ... processing cell loads for test.i2.set:
+ +++ prim test.i2.i0 port 4 is inside load of test.i2.set in test.i2.
+net set has 1 inside cell loads.
+ ... processing drivers for test.i2.xxx:
+ +++ prim test.i2.i0 port 0 is inside driver of test.i2.xxx in test.i2.
+net xxx has 1 inside drivers.
+ ... processing loads for test.i2.xxx:
+ +++ prim test.i2.i2 port 1 is inside load of test.i2.xxx in test.i2.
+ +++ prim test.i2.i1 port 1 is inside load of test.i2.xxx in test.i2.
+net xxx has 0 outside loads.
+ ... processing cell loads for test.i2.xxx:
+ +++ prim test.i2.i2 port 1 is inside load of test.i2.xxx in test.i2.
+ +++ prim test.i2.i1 port 1 is inside load of test.i2.xxx in test.i2.
+net xxx has 2 inside cell loads.
+... processing instance test.i3.
+ ... processing drivers for test.i3.clk:
+net clk has 0 inside drivers.
+ ... processing loads for test.i3.clk:
+ +++ prim test.i3.i0 port 2 is inside load of test.i3.clk in test.i3.
+net clk has 0 outside loads.
+ ... processing cell loads for test.i3.clk:
+ +++ prim test.i3.i0 port 2 is inside load of test.i3.clk in test.i3.
+net clk has 1 inside cell loads.
+ ... processing drivers for test.i3.clk1:
+net clk1 has 0 inside drivers.
+ ... processing loads for test.i3.clk1:
+net clk1 has 0 outside loads.
+ ... processing cell loads for test.i3.clk1:
+net clk1 has 0 inside cell loads.
+ ... processing drivers for test.i3.clr:
+net clr has 0 inside drivers.
+ ... processing loads for test.i3.clr:
+ +++ prim test.i3.i0 port 3 is inside load of test.i3.clr in test.i3.
+net clr has 0 outside loads.
+ ... processing cell loads for test.i3.clr:
+ +++ prim test.i3.i0 port 3 is inside load of test.i3.clr in test.i3.
+net clr has 1 inside cell loads.
+ ... processing drivers for test.i3.d:
+net d has 0 inside drivers.
+ ... processing loads for test.i3.d:
+ +++ prim test.i3.i0 port 1 is inside load of test.i3.d in test.i3.
+net d has 0 outside loads.
+ ... processing cell loads for test.i3.d:
+ +++ prim test.i3.i0 port 1 is inside load of test.i3.d in test.i3.
+net d has 1 inside cell loads.
+ ... processing drivers for test.i3.q:
+ +++ prim test.i3.i1 port 0 is inside driver of test.i3.q in test.i3.
+net q has 1 inside drivers.
+ ... processing loads for test.i3.q:
+net q has 0 outside loads.
+ ... processing cell loads for test.i3.q:
+net q has 0 inside cell loads.
+ ... processing drivers for test.i3.qn:
+ +++ prim test.i3.i2 port 0 is inside driver of test.i3.qn in test.i3.
+net qn has 1 inside drivers.
+ ... processing loads for test.i3.qn:
+net qn has 0 outside loads.
+ ... processing cell loads for test.i3.qn:
+net qn has 0 inside cell loads.
+ ... processing drivers for test.i3.set:
+net set has 0 inside drivers.
+ ... processing loads for test.i3.set:
+ +++ prim test.i3.i0 port 4 is inside load of test.i3.set in test.i3.
+net set has 0 outside loads.
+ ... processing cell loads for test.i3.set:
+ +++ prim test.i3.i0 port 4 is inside load of test.i3.set in test.i3.
+net set has 1 inside cell loads.
+ ... processing drivers for test.i3.xxx:
+ +++ prim test.i3.i0 port 0 is inside driver of test.i3.xxx in test.i3.
+net xxx has 1 inside drivers.
+ ... processing loads for test.i3.xxx:
+ +++ prim test.i3.i2 port 1 is inside load of test.i3.xxx in test.i3.
+ +++ prim test.i3.i1 port 1 is inside load of test.i3.xxx in test.i3.
+net xxx has 0 outside loads.
+ ... processing cell loads for test.i3.xxx:
+ +++ prim test.i3.i2 port 1 is inside load of test.i3.xxx in test.i3.
+ +++ prim test.i3.i1 port 1 is inside load of test.i3.xxx in test.i3.
+net xxx has 2 inside cell loads.
+  >>> All instances net drivers processed by acc_.
diff --git a/tests_and_examples/examples.acc/accxldrvtst.v b/tests_and_examples/examples.acc/accxldrvtst.v
new file mode 100644
index 0000000..1eee6d8
--- /dev/null
+++ b/tests_and_examples/examples.acc/accxldrvtst.v
@@ -0,0 +1,52 @@
+// specify test for fd clear/set flip flop
+module test;
+ wire t_q;  
+ reg t_clk, t_clk0, t_clk1, t_clk2, t_d, t_clr, t_set;
+
+ fd3noqn i1(t_q0, t_clk2, t_clk2, t_d0, t_clr0, t_set0);
+ fd3noqn i2(t_q1, t_clk2, t_clk2, t_d1, t_clr1, t_set1);
+ fd3noqn i3(t_q, t_clk, t_clk1, t_d, t_clr, t_set);
+
+ initial 
+  begin
+   $test;
+   $monitor($stime,, "q=%b, clk=%b, data=%b, clr=%b, set=%b",
+    t_q, t_clk, t_d, t_clr, t_set);
+  end
+endmodule
+
+module fd3noqn(q, clk, clk1, d, clr, set);
+ output q;
+ input clk, clk1, d, clr, set;
+ wire xxx;
+
+ xl_fd3 #10 i0(xxx, d, clk, clr, set);
+ buf i1(q, xxx);
+ not i2(qn, xxx);
+endmodule
+
+primitive xl_fd3(q, d, clk, clr, set);
+ output q; reg q;
+ input d, clk, clr, set;
+
+ table
+  // d  clk  clr  set  :  q  :  q
+  // -  ---  ---  ---  -  -  -  -
+  // set/clear low assertion 
+     ?   ?    ?    0   :  ?  :  1 ;
+     ?   ?    ?    x   :  ?  :  x ;
+     ?   ?    0    1   :  ?  :  0 ;
+     ?   ?    x    1   :  ?  :  x ;
+
+     0   r    1    1   :  ?  :  0 ;
+     1   r    1    1   :  ?  :  1 ;
+     x   r    1    1   :  ?  :  x ;
+
+     ?   f    1    1   :  ?  :  - ;
+     ?  (x?)  1    1   :  ?  :  - ;
+     ?  (?x)  1    1   :  ?  :  - ;
+     *   ?    1    1   :  ?  :  - ;
+     ?   ?    r    1   :  ?  :  - ;
+     ?   ?    1    r   :  ?  :  - ;
+ endtable
+endprimitive
diff --git a/tests_and_examples/examples.acc/clean.sh b/tests_and_examples/examples.acc/clean.sh
new file mode 100755
index 0000000..a9bde59
--- /dev/null
+++ b/tests_and_examples/examples.acc/clean.sh
@@ -0,0 +1 @@
+rm -f acc_probe acc_nxtchild accxl_drvld acc_prtchg *.o
diff --git a/tests_and_examples/examples.acc/inst_pli.osx.sh b/tests_and_examples/examples.acc/inst_pli.osx.sh
new file mode 100755
index 0000000..a098770
--- /dev/null
+++ b/tests_and_examples/examples.acc/inst_pli.osx.sh
@@ -0,0 +1,39 @@
+#!/bin/sh 
+# install test procedures
+
+OS=osx
+CVER=../../bin/cver
+
+if test ! -f ../../bin/cver 
+then
+  echo "ERROR - there is no cver in ../../bin/"
+  echo "Must make in src/ directory" 
+  exit;
+fi
+
+make -f makefile.$OS acc_probe.dylib
+$CVER -q +loadpli1=./acc_probe:pli1_compat_bootstrap probe.v >/dev/null
+./rmlic.pl
+diff verilog.log acc_probe.plg
+rm acc_probe.dylib acc_probe.o 
+
+make -f makefile.$OS acc_nxtchld.dylib
+$CVER -q +loadpli1=./acc_nxtchld:pli1_compat_bootstrap nc_fdsp.v >/dev/null
+./rmlic.pl
+diff verilog.log acc_nxtchld.plg
+rm acc_nxtchld.dylib acc_nxtchld.o
+
+make -f makefile.$OS accxl_drvld.dylib
+$CVER -q +loadpli1=./accxl_drvld:pli1_compat_bootstrap accxldrvtst.v >/dev/null
+./rmlic.pl
+diff verilog.log accxldrvtst.plg
+rm accxl_drvld.dylib accxl_drvld.o 
+
+make -f makefile.$OS acc_prtchg.dylib
+$CVER -q +loadpli1=./acc_prtchg:pli1_compat_bootstrap pchg_fdsp.v >/dev/null
+./rmlic.pl
+diff verilog.log pchg_fdsp.plg
+rm acc_prtchg.dylib acc_prtchg.o 
+
+echo ">>>> acc_ test Finished for Mac OSX- no diff differences should be printed."
+echo " "
diff --git a/tests_and_examples/examples.acc/inst_pli.sh b/tests_and_examples/examples.acc/inst_pli.sh
new file mode 100755
index 0000000..c637e42
--- /dev/null
+++ b/tests_and_examples/examples.acc/inst_pli.sh
@@ -0,0 +1,49 @@
+#!/bin/sh 
+# install test procedures
+
+# pass name for your OS as argument to shell script
+OS=$1 
+CVER=../../bin/cver
+
+if test ! -f ../../bin/cver 
+then
+  echo "ERROR - there is no cver in ../../bin/"
+  echo "Must make in src/ directory" 
+  exit;
+fi
+
+if [ "$OS" != "lnx" ]
+ then
+  if [ "$OS" != "sparc-gcc" ]
+   then
+      echo "must specify an OS(lnx, sparc-gcc) on command line" 
+      exit;
+  fi
+fi
+
+make -f makefile.$OS acc_probe.so
+$CVER -q +loadpli1=./acc_probe:pli1_compat_bootstrap probe.v >/dev/null
+./rmlic.pl
+diff verilog.log acc_probe.plg
+rm acc_probe.so acc_probe.o 
+
+make -f makefile.$OS acc_nxtchld.so
+$CVER -q +loadpli1=./acc_nxtchld:pli1_compat_bootstrap nc_fdsp.v >/dev/null
+./rmlic.pl
+diff verilog.log acc_nxtchld.plg
+rm acc_nxtchld.so acc_nxtchld.o
+
+make -f makefile.$OS accxl_drvld.so
+$CVER -q +loadpli1=./accxl_drvld:pli1_compat_bootstrap accxldrvtst.v >/dev/null
+./rmlic.pl
+diff verilog.log accxldrvtst.plg
+rm accxl_drvld.so accxl_drvld.o 
+
+make -f makefile.$OS acc_prtchg.so
+$CVER -q +loadpli1=./acc_prtchg:pli1_compat_bootstrap pchg_fdsp.v >/dev/null
+./rmlic.pl
+diff verilog.log pchg_fdsp.plg
+rm acc_prtchg.so acc_prtchg.o 
+
+echo ">>>> acc_ test Finished - no diff differences should be printed."
+echo " "
diff --git a/tests_and_examples/examples.acc/makefile.lnx b/tests_and_examples/examples.acc/makefile.lnx
new file mode 100644
index 0000000..9cecf82
--- /dev/null
+++ b/tests_and_examples/examples.acc/makefile.lnx
@@ -0,0 +1,37 @@
+
+# could add to CFLAGS to turn on warnings if you are using gcc
+WARNS=-Wall
+
+# change path if not running test from installed directory location
+INCS=-I../../pli_incs
+# maybe want -O<something> and/or -g, if you use -O use -m486
+CFLAGS= -fPIC -Wall $(INCS) 
+LFLAGS= -G -shared -export-dynamic
+
+# change to your compiler
+CC=gcc
+
+acc_probe.o:	acc_probe.c 
+	$(CC) $(CFLAGS) -c acc_probe.c
+
+acc_nxtchld.o:	acc_nxtchld.c 
+	$(CC) $(CFLAGS) -c acc_nxtchld.c
+
+accxl_drvld.o:	accxl_drvld.c 
+	$(CC) $(CFLAGS) -c accxl_drvld.c
+
+acc_prtchg.o:	acc_prtchg.c 
+	$(CC) $(CFLAGS) -c acc_prtchg.c
+
+# make rules for dynamic libraries
+acc_probe.so:	acc_probe.o
+	$(LD) $(LFLAGS) acc_probe.o -o acc_probe.so
+
+acc_nxtchld.so:	acc_nxtchld.o
+	$(LD) $(LFLAGS) acc_nxtchld.o -o acc_nxtchld.so
+
+accxl_drvld.so:	accxl_drvld.o
+	$(LD) $(LFLAGS) accxl_drvld.o -o accxl_drvld.so
+
+acc_prtchg.so:	acc_prtchg.o
+	$(LD) $(LFLAGS) acc_prtchg.o -o acc_prtchg.so
diff --git a/tests_and_examples/examples.acc/makefile.osx b/tests_and_examples/examples.acc/makefile.osx
new file mode 100644
index 0000000..90c160b
--- /dev/null
+++ b/tests_and_examples/examples.acc/makefile.osx
@@ -0,0 +1,38 @@
+
+# could add to CFLAGS to turn on warnings if you are using gcc
+WARNS=-Wall
+
+# change path if not running test from installed directory location
+INCS=-I../../pli_incs
+# maybe want -O<something> and/or -g, if you use -O use -m486
+CFLAGS= -fPIC -Wall $(INCS) -dynamic -fno-common 
+LFLAGS= -flat_namespace -bundle -undefined suppress
+
+# change to your compiler
+# CC=gcc
+
+acc_probe.o:	acc_probe.c 
+	$(CC) $(CFLAGS) -c acc_probe.c
+
+acc_nxtchld.o:	acc_nxtchld.c 
+	$(CC) $(CFLAGS) -c acc_nxtchld.c
+
+accxl_drvld.o:	accxl_drvld.c 
+	$(CC) $(CFLAGS) -c accxl_drvld.c
+
+acc_prtchg.o:	acc_prtchg.c 
+	$(CC) $(CFLAGS) -c acc_prtchg.c
+
+# make rules for dynamic libraries
+acc_probe.dylib:	acc_probe.o
+# notice for MAC OSX you must link with cc not ld
+	$(CC) $(LFLAGS) acc_probe.o -o acc_probe.dylib
+
+acc_nxtchld.dylib:	acc_nxtchld.o
+	$(CC) $(LFLAGS) acc_nxtchld.o -o acc_nxtchld.dylib
+
+accxl_drvld.dylib:	accxl_drvld.o
+	$(CC) $(LFLAGS) accxl_drvld.o -o accxl_drvld.dylib
+
+acc_prtchg.dylib:	acc_prtchg.o
+	$(CC) $(LFLAGS) acc_prtchg.o -o acc_prtchg.dylib
diff --git a/tests_and_examples/examples.acc/makefile.sparc-gcc b/tests_and_examples/examples.acc/makefile.sparc-gcc
new file mode 100644
index 0000000..1102308
--- /dev/null
+++ b/tests_and_examples/examples.acc/makefile.sparc-gcc
@@ -0,0 +1,37 @@
+
+# could add to CFLAGS to turn on warnings if you are using gcc
+WARNS=-Wall
+
+# change path if not running test from installed directory location
+INCS=-I../../pli_incs
+# maybe want -O<something> and/or -g, if you use -O use -m486
+CFLAGS= -Wall $(INCS)
+LFLAGS= -G 
+
+# change to your compiler
+CC=gcc
+ 
+acc_probe.o:	acc_probe.c 
+	$(CC) $(CFLAGS) -c acc_probe.c
+
+acc_nxtchld.o:	acc_nxtchld.c 
+	$(CC) $(CFLAGS) -c acc_nxtchld.c
+
+accxl_drvld.o:	accxl_drvld.c 
+	$(CC) $(CFLAGS) -c accxl_drvld.c
+
+acc_prtchg.o:	acc_prtchg.c 
+	$(CC) $(CFLAGS) -c acc_prtchg.c
+
+# make rules for dynamic libraries
+acc_probe.so:	acc_probe.o 
+	$(LD) $(LFLAGS) acc_probe.o -o acc_probe.so
+
+acc_nxtchld.so:	acc_nxtchld.o 
+	$(LD) $(LFLAGS) acc_nxtchld.o -o acc_nxtchld.so
+
+accxl_drvld.so:	accxl_drvld.o 
+	$(LD) $(LFLAGS) accxl_drvld.o -o accxl_drvld.so
+
+acc_prtchg.so:	acc_prtchg.o
+	$(LD) $(LFLAGS) acc_prtchg.o -o acc_prtchg.so
diff --git a/tests_and_examples/examples.acc/nc_fdsp.v b/tests_and_examples/examples.acc/nc_fdsp.v
new file mode 100644
index 0000000..e8c0e32
--- /dev/null
+++ b/tests_and_examples/examples.acc/nc_fdsp.v
@@ -0,0 +1,140 @@
+// specify test for fd clear/set flip flop
+module test;
+ wire t_q;  
+ reg t_clk, t_clk0, t_clk1, t_clk2, t_d, t_clr, t_set;
+
+ fd3noqn i1(t_q0, t_clk2, t_clk2, t_d0, t_clr0, t_set0);
+ fd3noqn i2(t_q1, t_clk2, t_clk2, t_d1, t_clr1, t_set1);
+ fd3noqn i3(t_q, t_clk, t_clk1, t_d, t_clr, t_set);
+
+ initial 
+  begin
+   $monitor($stime,, "q=%b, clk=%b, data=%b, clr=%b, set=%b",
+    t_q, t_clk, t_d, t_clr, t_set);
+   $dump_contents;
+   // test set/clear logic and delays - set overrides - low assertion 
+   #1000 $display("testing set/clear logic"); t_set = 1'bx;
+   #1000 t_set = 0;
+   #1000 t_clr = 0;
+   #1000 t_set = 1;
+   #1000 t_set = 0; 
+   #1000 t_set = 1; 
+   #1000 t_clr = 1'bx;
+   // test normal logic (set clear must be high)
+   #1000 $display("testing normal logic"); t_clr = 1; t_set = 1; t_d = 0;
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1'bx;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bz;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bx;
+   #1000 t_clk = 1;
+   #1000 t_d = 1; t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #100 t_clk = 1'bx;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bz;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bx;
+   #1000 t_clk = 1;
+   // test setup
+   #30 t_clk = 0;
+   #30 t_d = 1;
+   #30 t_clk = 1;
+   #30 t_d = 0;
+   #30 t_clk = 0;
+   #30 t_d = 1;
+   #30 t_clk = 1; t_d = 0; t_clk = 0; t_d = 1; t_clk = 1;
+   #100 t_clk = 0; t_clk1 = 0;
+   #100 t_clk1 = 1;
+   #2000 t_clk = 1;
+
+   /* ---
+   #100 t_d = 1; t_clk = 1;
+   #100 t_d = 1;
+   #450 t_clk = 1;
+   #550 t_clk = 0;
+   #200 t_d = 0;
+
+   #350 t_clk = 1;
+   #550 t_clk = 0;
+
+   #550 t_clk = 1;
+   #550 t_clk = 0;
+  --- */
+  end
+endmodule
+
+module fd3noqn(q, clk, clk1, d, clr, set);
+ output q;
+ input clk, clk1, d, clr, set;
+ // wire xxx;
+
+ specify
+  specparam tRise_clk_q = 140, tFall_clk_q = 250;
+  specparam tRise_control = 40, tFall_control= 50;
+  specparam tSetup=70, tHold=50;
+  specparam tWpos=600, tWneg=500;
+
+  // paths
+  (clk => q) = (tRise_clk_q, tFall_clk_q);
+  (clr,set *> q) = (tRise_control, tFall_control);
+
+  // timing checks
+  // setup time: d is reference, clk is data - setup > posedge clk - last data
+  // data must be stable > setup when clock triggers (pos. edge) 
+  // setup(ref, data, >setup);
+  // $setup(d, posedge clk, tSetup);
+
+  // hold time:  clk is reference, d is data - hold > d change after last clk
+  // hold(ref, data, >hold);
+  // $hold(posedge clk, d, tHold);
+
+  $setuphold(posedge clk, d, tSetup, tHold);
+
+  $width(posedge clk, tWpos);
+  $width(negedge clk, tWneg);
+  $period(posedge clk, 1000:1200:1400);
+  $skew(posedge clk1, posedge clk, 50);
+  $recovery(posedge d, clk, 200);
+ endspecify
+
+ xl_fd3 /* #10 */ i0(q, d, clk, clr, set);
+ // buf i1(q, xxx);
+ // not i2(qn, xxx);
+endmodule
+
+primitive xl_fd3(q, d, clk, clr, set);
+ output q; reg q;
+ input d, clk, clr, set;
+
+ table
+  // d  clk  clr  set  :  q  :  q
+  // -  ---  ---  ---  -  -  -  -
+  // set/clear low assertion 
+     ?   ?    ?    0   :  ?  :  1 ;
+     ?   ?    ?    x   :  ?  :  x ;
+     ?   ?    0    1   :  ?  :  0 ;
+     ?   ?    x    1   :  ?  :  x ;
+
+     0   r    1    1   :  ?  :  0 ;
+     1   r    1    1   :  ?  :  1 ;
+     x   r    1    1   :  ?  :  x ;
+
+     ?   f    1    1   :  ?  :  - ;
+     ?  (x?)  1    1   :  ?  :  - ;
+     ?  (?x)  1    1   :  ?  :  - ;
+     *   ?    1    1   :  ?  :  - ;
+     ?   ?    r    1   :  ?  :  - ;
+     ?   ?    1    r   :  ?  :  - ;
+ endtable
+endprimitive
diff --git a/tests_and_examples/examples.acc/pchg_fdsp.plg b/tests_and_examples/examples.acc/pchg_fdsp.plg
new file mode 100644
index 0000000..d6d7127
--- /dev/null
+++ b/tests_and_examples/examples.acc/pchg_fdsp.plg
@@ -0,0 +1,320 @@
+**pchg_fdsp.v(106) WARN** [653] $period timing check min:typ:max limit expression needs parentheses under 1364 - unportable
+... setting up vcls for instance test
+... vcls for wires
+Adding vcl for test.t_clr0 type accNet (fulltype accWire)
+Adding vcl for test.t_clr1 type accNet (fulltype accWire)
+Adding vcl for test.t_d0 type accNet (fulltype accWire)
+Adding vcl for test.t_d1 type accNet (fulltype accWire)
+Adding vcl for test.t_q type accNet (fulltype accWire)
+Adding vcl for test.t_q0 type accNet (fulltype accWire)
+Adding vcl for test.t_q1 type accNet (fulltype accWire)
+Adding vcl for test.t_set0 type accNet (fulltype accWire)
+Adding vcl for test.t_set1 type accNet (fulltype accWire)
+... vcls for variables
+Adding vcl for test.t_clk type accReg (fulltype accReg)
+Adding vcl for test.t_clk0 type accReg (fulltype accReg)
+Adding vcl for test.t_clk1 type accReg (fulltype accReg)
+Adding vcl for test.t_clk2 type accReg (fulltype accReg)
+Adding vcl for test.t_clr type accReg (fulltype accReg)
+Adding vcl for test.t_d type accReg (fulltype accReg)
+Adding vcl for test.t_set type accReg (fulltype accReg)
+... vcls for primitive terminals
+... vcls for ports
+... setting up vcls for instance test.i1
+... vcls for wires
+Adding vcl for test.i1.clk type accNet (fulltype accWire)
+Adding vcl for test.i1.clk1 type accNet (fulltype accWire)
+Adding vcl for test.i1.clr type accNet (fulltype accWire)
+Adding vcl for test.i1.d type accNet (fulltype accWire)
+Adding vcl for test.i1.q type accNet (fulltype accWire)
+Adding vcl for test.i1.set type accNet (fulltype accWire)
+... vcls for variables
+... vcls for primitive terminals
+Adding vcl for **terminal** type accTerminal (fulltype accOutputTerminal)
+... vcls for ports
+Adding vcl for test.i1.q type accPort (fulltype accScalarPort)
+Adding vcl for test.i1.clk type accPort (fulltype accScalarPort)
+Adding vcl for test.i1.clk1 type accPort (fulltype accScalarPort)
+Adding vcl for test.i1.d type accPort (fulltype accScalarPort)
+Adding vcl for test.i1.clr type accPort (fulltype accScalarPort)
+Adding vcl for test.i1.set type accPort (fulltype accScalarPort)
+... setting up vcls for instance test.i2
+... vcls for wires
+Adding vcl for test.i2.clk type accNet (fulltype accWire)
+Adding vcl for test.i2.clk1 type accNet (fulltype accWire)
+Adding vcl for test.i2.clr type accNet (fulltype accWire)
+Adding vcl for test.i2.d type accNet (fulltype accWire)
+Adding vcl for test.i2.q type accNet (fulltype accWire)
+Adding vcl for test.i2.set type accNet (fulltype accWire)
+... vcls for variables
+... vcls for primitive terminals
+Adding vcl for **terminal** type accTerminal (fulltype accOutputTerminal)
+... vcls for ports
+Adding vcl for test.i2.q type accPort (fulltype accScalarPort)
+Adding vcl for test.i2.clk type accPort (fulltype accScalarPort)
+Adding vcl for test.i2.clk1 type accPort (fulltype accScalarPort)
+Adding vcl for test.i2.d type accPort (fulltype accScalarPort)
+Adding vcl for test.i2.clr type accPort (fulltype accScalarPort)
+Adding vcl for test.i2.set type accPort (fulltype accScalarPort)
+... setting up vcls for instance test.i3
+... vcls for wires
+Adding vcl for test.i3.clk type accNet (fulltype accWire)
+Adding vcl for test.i3.clk1 type accNet (fulltype accWire)
+Adding vcl for test.i3.clr type accNet (fulltype accWire)
+Adding vcl for test.i3.d type accNet (fulltype accWire)
+Adding vcl for test.i3.q type accNet (fulltype accWire)
+Adding vcl for test.i3.set type accNet (fulltype accWire)
+... vcls for variables
+... vcls for primitive terminals
+Adding vcl for **terminal** type accTerminal (fulltype accOutputTerminal)
+... vcls for ports
+Adding vcl for test.i3.q type accPort (fulltype accScalarPort)
+Adding vcl for test.i3.clk type accPort (fulltype accScalarPort)
+Adding vcl for test.i3.clk1 type accPort (fulltype accScalarPort)
+Adding vcl for test.i3.d type accPort (fulltype accScalarPort)
+Adding vcl for test.i3.clr type accPort (fulltype accScalarPort)
+Adding vcl for test.i3.set type accPort (fulltype accScalarPort)
+  >>> All instances processed
+         0 q=x, clk=x, data=x, clr=x, set=x
+testing set/clear logic
+--> now 2000 (chg time 2000): test.i3.set=sr-scalar=0(obj=accPort)
+--> now 2000 (chg time 2000): test.t_set=sr-scalar=0(0)
+--> now 2000 (chg time 2000): test.i3.set=St0(<6, 6>=0)
+--> now 2000 (chg time 2000): **terminal**=scalar=1(obj=accTerminal)
+      2000 q=x, clk=x, data=x, clr=x, set=0
+--> now 2040 (chg time 2040): test.i3.q=scalar=1(obj=accPort)
+--> now 2040 (chg time 2040): test.i3.q=St1(<6, 6>=1)
+--> now 2040 (chg time 2040): test.t_q=St1(<6, 6>=1)
+      2040 q=1, clk=x, data=x, clr=x, set=0
+--> now 3000 (chg time 3000): test.i3.clr=sr-scalar=0(obj=accPort)
+--> now 3000 (chg time 3000): test.t_clr=sr-scalar=0(0)
+--> now 3000 (chg time 3000): test.i3.clr=St0(<6, 6>=0)
+      3000 q=1, clk=x, data=x, clr=0, set=0
+--> now 4000 (chg time 4000): test.i3.set=sr-scalar=1(obj=accPort)
+--> now 4000 (chg time 4000): test.t_set=sr-scalar=1(1)
+--> now 4000 (chg time 4000): test.i3.set=St1(<6, 6>=1)
+--> now 4000 (chg time 4000): **terminal**=scalar=0(obj=accTerminal)
+      4000 q=1, clk=x, data=x, clr=0, set=1
+--> now 4050 (chg time 4050): test.i3.q=scalar=0(obj=accPort)
+--> now 4050 (chg time 4050): test.i3.q=St0(<6, 6>=0)
+--> now 4050 (chg time 4050): test.t_q=St0(<6, 6>=0)
+      4050 q=0, clk=x, data=x, clr=0, set=1
+--> now 5000 (chg time 5000): test.i3.set=sr-scalar=0(obj=accPort)
+--> now 5000 (chg time 5000): test.t_set=sr-scalar=0(0)
+--> now 5000 (chg time 5000): test.i3.set=St0(<6, 6>=0)
+--> now 5000 (chg time 5000): **terminal**=scalar=1(obj=accTerminal)
+      5000 q=0, clk=x, data=x, clr=0, set=0
+--> now 5040 (chg time 5040): test.i3.q=scalar=1(obj=accPort)
+--> now 5040 (chg time 5040): test.i3.q=St1(<6, 6>=1)
+--> now 5040 (chg time 5040): test.t_q=St1(<6, 6>=1)
+      5040 q=1, clk=x, data=x, clr=0, set=0
+--> now 6000 (chg time 6000): test.i3.set=sr-scalar=1(obj=accPort)
+--> now 6000 (chg time 6000): test.t_set=sr-scalar=1(1)
+--> now 6000 (chg time 6000): test.i3.set=St1(<6, 6>=1)
+--> now 6000 (chg time 6000): **terminal**=scalar=0(obj=accTerminal)
+      6000 q=1, clk=x, data=x, clr=0, set=1
+--> now 6050 (chg time 6050): test.i3.q=scalar=0(obj=accPort)
+--> now 6050 (chg time 6050): test.i3.q=St0(<6, 6>=0)
+--> now 6050 (chg time 6050): test.t_q=St0(<6, 6>=0)
+      6050 q=0, clk=x, data=x, clr=0, set=1
+--> now 7000 (chg time 7000): test.i3.clr=sr-scalar=2(obj=accPort)
+--> now 7000 (chg time 7000): test.t_clr=sr-scalar=2(x)
+--> now 7000 (chg time 7000): test.i3.clr=StX(<6, 6>=2)
+--> now 7000 (chg time 7000): **terminal**=scalar=2(obj=accTerminal)
+      7000 q=0, clk=x, data=x, clr=x, set=1
+--> now 7040 (chg time 7040): test.i3.q=scalar=2(obj=accPort)
+--> now 7040 (chg time 7040): test.i3.q=StX(<6, 6>=2)
+--> now 7040 (chg time 7040): test.t_q=StX(<6, 6>=2)
+      7040 q=x, clk=x, data=x, clr=x, set=1
+testing normal logic
+--> now 8000 (chg time 8000): test.i3.clr=sr-scalar=1(obj=accPort)
+--> now 8000 (chg time 8000): test.t_clr=sr-scalar=1(1)
+--> now 8000 (chg time 8000): test.i3.d=sr-scalar=0(obj=accPort)
+--> now 8000 (chg time 8000): test.t_d=sr-scalar=0(0)
+--> now 8000 (chg time 8000): test.i3.clr=St1(<6, 6>=1)
+--> now 8000 (chg time 8000): test.i3.d=St0(<6, 6>=0)
+      8000 q=x, clk=x, data=0, clr=1, set=1
+--> now 9000 (chg time 9000): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 9000 (chg time 9000): test.t_clk=sr-scalar=1(1)
+--> now 9000 (chg time 9000): test.i3.clk=St1(<6, 6>=1)
+      9000 q=x, clk=1, data=0, clr=1, set=1
+--> now 10000 (chg time 10000): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 10000 (chg time 10000): test.t_clk=sr-scalar=0(0)
+--> now 10000 (chg time 10000): test.i3.clk=St0(<6, 6>=0)
+     10000 q=x, clk=0, data=0, clr=1, set=1
+--> now 11000 (chg time 11000): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 11000 (chg time 11000): test.t_clk=sr-scalar=1(1)
+--> now 11000 (chg time 11000): test.i3.clk=St1(<6, 6>=1)
+--> now 11000 (chg time 11000): **terminal**=scalar=0(obj=accTerminal)
+     11000 q=x, clk=1, data=0, clr=1, set=1
+--> now 11250 (chg time 11250): test.i3.q=scalar=0(obj=accPort)
+--> now 11250 (chg time 11250): test.i3.q=St0(<6, 6>=0)
+--> now 11250 (chg time 11250): test.t_q=St0(<6, 6>=0)
+     11250 q=0, clk=1, data=0, clr=1, set=1
+--> now 12000 (chg time 12000): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 12000 (chg time 12000): test.t_clk=sr-scalar=0(0)
+--> now 12000 (chg time 12000): test.i3.clk=St0(<6, 6>=0)
+     12000 q=0, clk=0, data=0, clr=1, set=1
+--> now 13000 (chg time 13000): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 13000 (chg time 13000): test.t_clk=sr-scalar=1(1)
+--> now 13000 (chg time 13000): test.i3.clk=St1(<6, 6>=1)
+     13000 q=0, clk=1, data=0, clr=1, set=1
+--> now 14000 (chg time 14000): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 14000 (chg time 14000): test.t_clk=sr-scalar=0(0)
+--> now 14000 (chg time 14000): test.i3.clk=St0(<6, 6>=0)
+     14000 q=0, clk=0, data=0, clr=1, set=1
+--> now 15000 (chg time 15000): test.i3.clk=sr-scalar=2(obj=accPort)
+--> now 15000 (chg time 15000): test.t_clk=sr-scalar=2(x)
+--> now 15000 (chg time 15000): test.i3.clk=StX(<6, 6>=2)
+     15000 q=0, clk=x, data=0, clr=1, set=1
+--> now 16000 (chg time 16000): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 16000 (chg time 16000): test.t_clk=sr-scalar=0(0)
+--> now 16000 (chg time 16000): test.i3.clk=St0(<6, 6>=0)
+     16000 q=0, clk=0, data=0, clr=1, set=1
+--> now 17000 (chg time 17000): test.i3.clk=sr-scalar=3(obj=accPort)
+--> now 17000 (chg time 17000): test.t_clk=sr-scalar=3(z)
+--> now 17000 (chg time 17000): test.i3.clk=HiZ(<6, 6>=3)
+     17000 q=0, clk=z, data=0, clr=1, set=1
+--> now 18000 (chg time 18000): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 18000 (chg time 18000): test.t_clk=sr-scalar=0(0)
+--> now 18000 (chg time 18000): test.i3.clk=St0(<6, 6>=0)
+     18000 q=0, clk=0, data=0, clr=1, set=1
+--> now 19000 (chg time 19000): test.i3.clk=sr-scalar=2(obj=accPort)
+--> now 19000 (chg time 19000): test.t_clk=sr-scalar=2(x)
+--> now 19000 (chg time 19000): test.i3.clk=StX(<6, 6>=2)
+     19000 q=0, clk=x, data=0, clr=1, set=1
+--> now 20000 (chg time 20000): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 20000 (chg time 20000): test.t_clk=sr-scalar=1(1)
+--> now 20000 (chg time 20000): test.i3.clk=St1(<6, 6>=1)
+**pchg_fdsp.v(106) WARN** now 20000 [566] timing violation in test.i3 (diff. 1000)
+ $period((posedge clk):19000, (posedge clk):20000, 1200);
+     20000 q=0, clk=1, data=0, clr=1, set=1
+--> now 21000 (chg time 21000): test.i3.d=sr-scalar=1(obj=accPort)
+--> now 21000 (chg time 21000): test.t_d=sr-scalar=1(1)
+--> now 21000 (chg time 21000): test.i3.d=St1(<6, 6>=1)
+     21000 q=0, clk=1, data=1, clr=1, set=1
+--> now 22000 (chg time 22000): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 22000 (chg time 22000): test.t_clk=sr-scalar=0(0)
+--> now 22000 (chg time 22000): test.i3.clk=St0(<6, 6>=0)
+     22000 q=0, clk=0, data=1, clr=1, set=1
+--> now 23000 (chg time 23000): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 23000 (chg time 23000): test.t_clk=sr-scalar=1(1)
+--> now 23000 (chg time 23000): test.i3.clk=St1(<6, 6>=1)
+--> now 23000 (chg time 23000): **terminal**=scalar=1(obj=accTerminal)
+     23000 q=0, clk=1, data=1, clr=1, set=1
+--> now 23140 (chg time 23140): test.i3.q=scalar=1(obj=accPort)
+--> now 23140 (chg time 23140): test.i3.q=St1(<6, 6>=1)
+--> now 23140 (chg time 23140): test.t_q=St1(<6, 6>=1)
+     23140 q=1, clk=1, data=1, clr=1, set=1
+--> now 24000 (chg time 24000): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 24000 (chg time 24000): test.t_clk=sr-scalar=0(0)
+--> now 24000 (chg time 24000): test.i3.clk=St0(<6, 6>=0)
+     24000 q=1, clk=0, data=1, clr=1, set=1
+--> now 25000 (chg time 25000): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 25000 (chg time 25000): test.t_clk=sr-scalar=1(1)
+--> now 25000 (chg time 25000): test.i3.clk=St1(<6, 6>=1)
+     25000 q=1, clk=1, data=1, clr=1, set=1
+--> now 26000 (chg time 26000): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 26000 (chg time 26000): test.t_clk=sr-scalar=0(0)
+--> now 26000 (chg time 26000): test.i3.clk=St0(<6, 6>=0)
+     26000 q=1, clk=0, data=1, clr=1, set=1
+--> now 26100 (chg time 26100): test.i3.clk=sr-scalar=2(obj=accPort)
+--> now 26100 (chg time 26100): test.t_clk=sr-scalar=2(x)
+--> now 26100 (chg time 26100): test.i3.clk=StX(<6, 6>=2)
+**pchg_fdsp.v(106) WARN** now 26100 [566] timing violation in test.i3 (diff. 1100)
+ $period((posedge clk):25000, (posedge clk):26100, 1200);
+**pchg_fdsp.v(105) WARN** now 26100 [566] timing violation in test.i3 (diff. 100)
+ $width((negedge clk):26000, (posedge clk):26100, 500);
+     26100 q=1, clk=x, data=1, clr=1, set=1
+--> now 27100 (chg time 27100): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 27100 (chg time 27100): test.t_clk=sr-scalar=0(0)
+--> now 27100 (chg time 27100): test.i3.clk=St0(<6, 6>=0)
+     27100 q=1, clk=0, data=1, clr=1, set=1
+--> now 28100 (chg time 28100): test.i3.clk=sr-scalar=3(obj=accPort)
+--> now 28100 (chg time 28100): test.t_clk=sr-scalar=3(z)
+--> now 28100 (chg time 28100): test.i3.clk=HiZ(<6, 6>=3)
+     28100 q=1, clk=z, data=1, clr=1, set=1
+--> now 29100 (chg time 29100): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 29100 (chg time 29100): test.t_clk=sr-scalar=0(0)
+--> now 29100 (chg time 29100): test.i3.clk=St0(<6, 6>=0)
+     29100 q=1, clk=0, data=1, clr=1, set=1
+--> now 30100 (chg time 30100): test.i3.clk=sr-scalar=2(obj=accPort)
+--> now 30100 (chg time 30100): test.t_clk=sr-scalar=2(x)
+--> now 30100 (chg time 30100): test.i3.clk=StX(<6, 6>=2)
+     30100 q=1, clk=x, data=1, clr=1, set=1
+--> now 31100 (chg time 31100): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 31100 (chg time 31100): test.t_clk=sr-scalar=1(1)
+--> now 31100 (chg time 31100): test.i3.clk=St1(<6, 6>=1)
+**pchg_fdsp.v(106) WARN** now 31100 [566] timing violation in test.i3 (diff. 1000)
+ $period((posedge clk):30100, (posedge clk):31100, 1200);
+     31100 q=1, clk=1, data=1, clr=1, set=1
+--> now 31130 (chg time 31130): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 31130 (chg time 31130): test.t_clk=sr-scalar=0(0)
+--> now 31130 (chg time 31130): test.i3.clk=St0(<6, 6>=0)
+**pchg_fdsp.v(104) WARN** now 31130 [566] timing violation in test.i3 (diff. 30)
+ $width((posedge clk):31100, (negedge clk):31130, 600);
+     31130 q=1, clk=0, data=1, clr=1, set=1
+--> now 31190 (chg time 31190): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 31190 (chg time 31190): test.t_clk=sr-scalar=1(1)
+--> now 31190 (chg time 31190): test.i3.clk=St1(<6, 6>=1)
+**pchg_fdsp.v(106) WARN** now 31190 [566] timing violation in test.i3 (diff. 90)
+ $period((posedge clk):31100, (posedge clk):31190, 1200);
+**pchg_fdsp.v(105) WARN** now 31190 [566] timing violation in test.i3 (diff. 60)
+ $width((negedge clk):31130, (posedge clk):31190, 500);
+     31190 q=1, clk=1, data=1, clr=1, set=1
+--> now 31220 (chg time 31220): test.i3.d=sr-scalar=0(obj=accPort)
+--> now 31220 (chg time 31220): test.t_d=sr-scalar=0(0)
+--> now 31220 (chg time 31220): test.i3.d=St0(<6, 6>=0)
+**pchg_fdsp.v(102) WARN** now 31220 [566] timing violation in test.i3 (diff. 30)
+ hold(of setuphold)((posedge clk):31190, d:31220, 50);
+     31220 q=1, clk=1, data=0, clr=1, set=1
+--> now 31250 (chg time 31250): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 31250 (chg time 31250): test.t_clk=sr-scalar=0(0)
+--> now 31250 (chg time 31250): test.i3.clk=St0(<6, 6>=0)
+**pchg_fdsp.v(104) WARN** now 31250 [566] timing violation in test.i3 (diff. 60)
+ $width((posedge clk):31190, (negedge clk):31250, 600);
+     31250 q=1, clk=0, data=0, clr=1, set=1
+--> now 31280 (chg time 31280): test.i3.d=sr-scalar=1(obj=accPort)
+--> now 31280 (chg time 31280): test.t_d=sr-scalar=1(1)
+--> now 31280 (chg time 31280): test.i3.d=St1(<6, 6>=1)
+     31280 q=1, clk=0, data=1, clr=1, set=1
+--> now 31310 (chg time 31310): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 31310 (chg time 31310): test.t_clk=sr-scalar=1(1)
+--> now 31310 (chg time 31310): test.i3.d=sr-scalar=0(obj=accPort)
+--> now 31310 (chg time 31310): test.t_d=sr-scalar=0(0)
+--> now 31310 (chg time 31310): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 31310 (chg time 31310): test.t_clk=sr-scalar=0(0)
+--> now 31310 (chg time 31310): test.i3.d=sr-scalar=1(obj=accPort)
+--> now 31310 (chg time 31310): test.t_d=sr-scalar=1(1)
+--> now 31310 (chg time 31310): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 31310 (chg time 31310): test.t_clk=sr-scalar=1(1)
+--> now 31310 (chg time 31310): test.i3.clk=St1(<6, 6>=1)
+**pchg_fdsp.v(108) WARN** now 31310 [566] timing violation in test.i3 (diff. 30)
+ $recovery((posedge d):31280, clk:31310, 200);
+**pchg_fdsp.v(106) WARN** now 31310 [566] timing violation in test.i3 (diff. 120)
+ $period((posedge clk):31190, (posedge clk):31310, 1200);
+**pchg_fdsp.v(105) WARN** now 31310 [566] timing violation in test.i3 (diff. 60)
+ $width((negedge clk):31250, (posedge clk):31310, 500);
+**pchg_fdsp.v(102) WARN** now 31310 [566] timing violation in test.i3 (diff. 30)
+ setup(of setuphold)(d:31280, (posedge clk):31310, 70);
+     31310 q=1, clk=1, data=1, clr=1, set=1
+--> now 31410 (chg time 31410): test.i3.clk=sr-scalar=0(obj=accPort)
+--> now 31410 (chg time 31410): test.t_clk=sr-scalar=0(0)
+--> now 31410 (chg time 31410): test.i3.clk1=sr-scalar=0(obj=accPort)
+--> now 31410 (chg time 31410): test.t_clk1=sr-scalar=0(0)
+--> now 31410 (chg time 31410): test.i3.clk=St0(<6, 6>=0)
+--> now 31410 (chg time 31410): test.i3.clk1=St0(<6, 6>=0)
+**pchg_fdsp.v(108) WARN** now 31410 [566] timing violation in test.i3 (diff. 130)
+ $recovery((posedge d):31280, clk:31410, 200);
+**pchg_fdsp.v(104) WARN** now 31410 [566] timing violation in test.i3 (diff. 100)
+ $width((posedge clk):31310, (negedge clk):31410, 600);
+     31410 q=1, clk=0, data=1, clr=1, set=1
+--> now 31510 (chg time 31510): test.i3.clk1=sr-scalar=1(obj=accPort)
+--> now 31510 (chg time 31510): test.t_clk1=sr-scalar=1(1)
+--> now 31510 (chg time 31510): test.i3.clk1=St1(<6, 6>=1)
+--> now 33510 (chg time 33510): test.i3.clk=sr-scalar=1(obj=accPort)
+--> now 33510 (chg time 33510): test.t_clk=sr-scalar=1(1)
+--> now 33510 (chg time 33510): test.i3.clk=St1(<6, 6>=1)
+**pchg_fdsp.v(107) WARN** now 33510 [566] timing violation in test.i3 (diff. 2000)
+ $skew((posedge clk1):31510, (posedge clk):33510, 50);
+     33510 q=1, clk=1, data=1, clr=1, set=1
diff --git a/tests_and_examples/examples.acc/pchg_fdsp.v b/tests_and_examples/examples.acc/pchg_fdsp.v
new file mode 100644
index 0000000..ee76a55
--- /dev/null
+++ b/tests_and_examples/examples.acc/pchg_fdsp.v
@@ -0,0 +1,140 @@
+// specify test for fd clear/set flip flop
+module test;
+ wire t_q;  
+ reg t_clk, t_clk0, t_clk1, t_clk2, t_d, t_clr, t_set;
+
+ fd3noqn i1(t_q0, t_clk2, t_clk2, t_d0, t_clr0, t_set0);
+ fd3noqn i2(t_q1, t_clk2, t_clk2, t_d1, t_clr1, t_set1);
+ fd3noqn i3(t_q, t_clk, t_clk1, t_d, t_clr, t_set);
+
+ initial 
+  begin
+   $monitor($stime,, "q=%b, clk=%b, data=%b, clr=%b, set=%b",
+    t_q, t_clk, t_d, t_clr, t_set);
+   $test;
+   // test set/clear logic and delays - set overrides - low assertion 
+   #1000 $display("testing set/clear logic"); t_set = 1'bx;
+   #1000 t_set = 0;
+   #1000 t_clr = 0;
+   #1000 t_set = 1;
+   #1000 t_set = 0; 
+   #1000 t_set = 1; 
+   #1000 t_clr = 1'bx;
+   // test normal logic (set clear must be high)
+   #1000 $display("testing normal logic"); t_clr = 1; t_set = 1; t_d = 0;
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1'bx;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bz;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bx;
+   #1000 t_clk = 1;
+   #1000 t_d = 1; t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #100 t_clk = 1'bx;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bz;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bx;
+   #1000 t_clk = 1;
+   // test setup
+   #30 t_clk = 0;
+   #30 t_d = 1;
+   #30 t_clk = 1;
+   #30 t_d = 0;
+   #30 t_clk = 0;
+   #30 t_d = 1;
+   #30 t_clk = 1; t_d = 0; t_clk = 0; t_d = 1; t_clk = 1;
+   #100 t_clk = 0; t_clk1 = 0;
+   #100 t_clk1 = 1;
+   #2000 t_clk = 1;
+
+   /* ---
+   #100 t_d = 1; t_clk = 1;
+   #100 t_d = 1;
+   #450 t_clk = 1;
+   #550 t_clk = 0;
+   #200 t_d = 0;
+
+   #350 t_clk = 1;
+   #550 t_clk = 0;
+
+   #550 t_clk = 1;
+   #550 t_clk = 0;
+  --- */
+  end
+endmodule
+
+module fd3noqn(q, clk, clk1, d, clr, set);
+ output q;
+ input clk, clk1, d, clr, set;
+ // wire xxx;
+
+ specify
+  specparam tRise_clk_q = 140, tFall_clk_q = 250;
+  specparam tRise_control = 40, tFall_control= 50;
+  specparam tSetup=70, tHold=50;
+  specparam tWpos=600, tWneg=500;
+
+  // paths
+  (clk => q) = (tRise_clk_q, tFall_clk_q);
+  (clr,set *> q) = (tRise_control, tFall_control);
+
+  // timing checks
+  // setup time: d is reference, clk is data - setup > posedge clk - last data
+  // data must be stable > setup when clock triggers (pos. edge) 
+  // setup(ref, data, >setup);
+  // $setup(d, posedge clk, tSetup);
+
+  // hold time:  clk is reference, d is data - hold > d change after last clk
+  // hold(ref, data, >hold);
+  // $hold(posedge clk, d, tHold);
+
+  $setuphold(posedge clk, d, tSetup, tHold);
+
+  $width(posedge clk, tWpos);
+  $width(negedge clk, tWneg);
+  $period(posedge clk, 1000:1200:1400);
+  $skew(posedge clk1, posedge clk, 50);
+  $recovery(posedge d, clk, 200);
+ endspecify
+
+ xl_fd3 /* #10 */ i0(q, d, clk, clr, set);
+ // buf i1(q, xxx);
+ // not i2(qn, xxx);
+endmodule
+
+primitive xl_fd3(q, d, clk, clr, set);
+ output q; reg q;
+ input d, clk, clr, set;
+
+ table
+  // d  clk  clr  set  :  q  :  q
+  // -  ---  ---  ---  -  -  -  -
+  // set/clear low assertion 
+     ?   ?    ?    0   :  ?  :  1 ;
+     ?   ?    ?    x   :  ?  :  x ;
+     ?   ?    0    1   :  ?  :  0 ;
+     ?   ?    x    1   :  ?  :  x ;
+
+     0   r    1    1   :  ?  :  0 ;
+     1   r    1    1   :  ?  :  1 ;
+     x   r    1    1   :  ?  :  x ;
+
+     ?   f    1    1   :  ?  :  - ;
+     ?  (x?)  1    1   :  ?  :  - ;
+     ?  (?x)  1    1   :  ?  :  - ;
+     *   ?    1    1   :  ?  :  - ;
+     ?   ?    r    1   :  ?  :  - ;
+     ?   ?    1    r   :  ?  :  - ;
+ endtable
+endprimitive
diff --git a/tests_and_examples/examples.acc/probe.v b/tests_and_examples/examples.acc/probe.v
new file mode 100644
index 0000000..2e32e86
--- /dev/null
+++ b/tests_and_examples/examples.acc/probe.v
@@ -0,0 +1,20 @@
+module probe;
+ reg [31:0] a, b, c;
+
+ initial 
+  begin
+   $setup_values(a, b, c); 
+   #10 a = 3; c = 1;
+   #10 b = 3; c = 2;
+   #10 c = 3;
+   #10 a = 33; c = 9;
+   #10 b = 44; c = 22;
+   #10 a = 30;
+   #10 a = 50; b = 200; c = 0;
+   #10 a = 50; c = 99;
+   #10 b = 90; c = 99;
+   #10 b = 11; c = 19;
+  end
+ // do the flash
+ always @(c) $flash_values($stime/2);
+endmodule
diff --git a/tests_and_examples/examples.acc/rmlic.pl b/tests_and_examples/examples.acc/rmlic.pl
new file mode 100755
index 0000000..39c7ade
--- /dev/null
+++ b/tests_and_examples/examples.acc/rmlic.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+use strict;
+my $file;
+my $i;
+my $line;
+ 
+ $file = 'verilog.log';
+ if (@ARGV == 1)
+ {
+     $file = $ARGV[0];
+ }
+
+ open(FILE, $file) or die "Can't open $file\n";
+ open(TMP, '>tmp') or die "Can't open tmp file\n";
+ for($i = 0; $i < 3; $i++)
+ {
+      $line = <FILE>;
+ }
+ while(<FILE>)
+ {
+      print TMP $_;
+ }
+ close TMP;
+ close FILE;
+ rename 'tmp', $file;
diff --git a/tests_and_examples/examples.tf/README b/tests_and_examples/examples.tf/README
new file mode 100644
index 0000000..95113af
--- /dev/null
+++ b/tests_and_examples/examples.tf/README
@@ -0,0 +1,70 @@
+To test PLI 1.0 tf_ interface:
+
+BEFORE STARTING:
+   Make a binary Cver (see INSTALL or README file in src directory) and
+   run the shell script in install.tst directory to verify correct build.
+
+   This script assumes you are using new +loadpli1= dynamic library PLI
+   execution.  If you need to statically link your PLI libraries contact
+   Pragmatic C to obtain the libraries and test scripts.
+
+HOW TO RUN THE TEST SCRIPT FOR ALL SYSTEMS EXCEPT MAC OSX
+
+1) Run the shell script inst_pli.sh [OS name].  Various compiler and Verilog
+   output messages will be printed but there should be no diff command
+   differences printed.  You must pass the name of your system as the one
+   argument to the script.  This directory contains sample make files
+   for X86 linux (suffix lnx), Sparc (suffix sparc-gcc).  See below for
+   running PLI1 tf_ routine install test on MAC OSX.
+
+   Run the shell script opt_inst_pli.sh [OS name] to test PLI using
+   optimizer (-O) incremental compiler.
+
+   By convention makefile.[OS name] assumes this test is run in release
+   directory tree with include files in pli_incs 2 directory levels up
+   and cver binary is in bin directory also 2 levels up.
+
+   The commands to run Cver with dynamically loaded user PLI library
+   explicitly access the user .so library in this directory.  For your
+   PLI libraries, it is better to set the LD_LIBRARY_PATH environment
+   variables so explicit "./" is not needed
+
+2) After completing the test, run clean.sh to remove work files.
+   The inst_pli.sh script removes each PLI library .so dynamic library after
+   running the test that uses it so unless something went wrong, you
+   do not need to run clean.sh.  
+
+3) Use makefile.[your OS] as a template for your PLI models.
+
+HOW TO RUN THE TEST SCRIPT FOR MAC OSX
+
+1) Run the shell script inst_pli.osx.sh.  Notice you do not need the
+   OS shell argument here.  Various compiler and Verilog
+   output messages will be printed but there should be no diff command
+   differences printed.  You must run this different script for MAC OSX
+   because OSX uses .dylib suffix for dynamic libraries and uses the
+   mach dynamic library mechanism instead of normal .so and dlopen. 
+
+   By convention, makefile.osx assumes this test is run in release
+   directory tree with include files in pli_incs 2 directory levels up
+   and cver binary is in bin directory also 2 levels up.
+
+   The commands to run Cver with dynamically loaded user PLI library
+   explicitly access the user .dylib library in this directory.  For your
+   PLI libraries, it is better to set the LD_LIBRARY_PATH environment
+   variables so explicit "./" is not needed
+
+   Mac OSX linker (from mach OS) requires that a leading '_' be added to
+   each symbol name.  Cver does this automatically but you must make
+   sure that your bootstrap routine name does not start with underscore ('_').
+
+2) After completing the test, run clean.sh to remove work files.
+   The inst_pli.sh script removes each PLI library .so dynamic library after
+   running the test that uses it so unless something went wrong, you
+   do not need to run clean.sh.  
+
+3) Use makefile.osx as a template for your PLI models.  You must use
+   exactly the LFLAGS options and set and export LD_LIBRARY_PATH
+   environment variable, or your .dylib user PLI code will not load
+   properly.
+   
diff --git a/tests_and_examples/examples.tf/clean.sh b/tests_and_examples/examples.tf/clean.sh
new file mode 100755
index 0000000..77a2cce
--- /dev/null
+++ b/tests_and_examples/examples.tf/clean.sh
@@ -0,0 +1 @@
+rm probe tfclk plimfil plimfil2 *.o *.dylib verilog.log
diff --git a/tests_and_examples/examples.tf/inst_pli.osx.sh b/tests_and_examples/examples.tf/inst_pli.osx.sh
new file mode 100755
index 0000000..049ec0b
--- /dev/null
+++ b/tests_and_examples/examples.tf/inst_pli.osx.sh
@@ -0,0 +1,40 @@
+#!/bin/sh 
+# install test procedures
+
+# pass name for your OS as argument to shell script
+OS=OSX 
+CVER=../../bin/cver
+
+if test ! -f ../../bin/cver 
+then
+  echo "ERROR - there is no cver in ../../bin/"
+  echo "Must make in src/ directory" 
+  exit;
+fi
+
+make -f makefile.$OS probe.dylib
+$CVER -q +loadpli1=./probe:pli1_compat_bootstrap probe.v >/dev/null
+./rmlic.pl
+diff verilog.log probe.plg
+rm probe.dylib probe.o
+
+make -f makefile.$OS tfclk.dylib
+$CVER -q tfclk.v +loadpli1=./tfclk:pli1_compat_bootstrap >/dev/null
+./rmlic.pl
+diff verilog.log tfclk.plg
+rm tfclk.dylib tfclk.o
+
+make -f makefile.$OS plimfil.dylib
+$CVER +memfile+testmem.dat -q +loadpli1=./plimfil:pli1_compat_bootstrap plimfil.v >/dev/null
+./rmlic.pl
+diff verilog.log plimfil.plg
+rm plimfil.dylib plimfil.o
+
+make -f makefile.$OS plimfil2.dylib
+$CVER +memfile+testmem2.dat -q +loadpli1=./plimfil2:pli1_compat_bootstrap plimfil2.v >/dev/null
+./rmlic.pl
+diff verilog.log plimfil2.plg
+rm plimfil2.dylib plimfil2.o
+
+echo ">>>> MAC OSX PLI 1.0 test finished - no diff differences should be printed."
+echo " "
diff --git a/tests_and_examples/examples.tf/inst_pli.sh b/tests_and_examples/examples.tf/inst_pli.sh
new file mode 100755
index 0000000..da164d6
--- /dev/null
+++ b/tests_and_examples/examples.tf/inst_pli.sh
@@ -0,0 +1,50 @@
+#!/bin/sh 
+# install test procedures
+
+# pass name for your OS as argument to shell script
+OS=$1 
+CVER=../../bin/cver
+
+if test ! -f ../../bin/cver 
+then
+  echo "ERROR - there is no cver in ../../bin/"
+  echo "Must make in src/ directory" 
+  exit;
+fi
+
+
+if [ "$OS" != "lnx" ]
+ then
+  if [ "$OS" != "sparc-gcc" ]
+   then
+      echo "must specify an OS(lnx, sparc-gcc) on command line" 
+      exit;
+  fi
+fi
+
+make -f makefile.$OS probe.so
+$CVER -q +loadpli1=./probe:pli1_compat_bootstrap probe.v >/dev/null
+./rmlic.pl
+diff verilog.log probe.plg
+rm probe.so probe.o
+
+make -f makefile.$OS tfclk.so
+$CVER -q tfclk.v +loadpli1=./tfclk:pli1_compat_bootstrap >/dev/null
+./rmlic.pl
+diff verilog.log tfclk.plg
+rm tfclk.so tfclk.o
+
+make -f makefile.$OS plimfil.so
+$CVER +memfile+testmem.dat -q +loadpli1=./plimfil:pli1_compat_bootstrap plimfil.v >/dev/null
+./rmlic.pl
+diff verilog.log plimfil.plg
+rm plimfil.so plimfil.o
+
+make -f makefile.$OS plimfil2.so
+$CVER +memfile+testmem2.dat -q +loadpli1=./plimfil2:pli1_compat_bootstrap plimfil2.v >/dev/null
+./rmlic.pl
+diff verilog.log plimfil2.plg
+rm plimfil2.so plimfil2.o
+
+echo ">>>> PLI 1.0 test finished - no diff differences should be printed."
+echo " "
diff --git a/tests_and_examples/examples.tf/makefile.lnx b/tests_and_examples/examples.tf/makefile.lnx
new file mode 100644
index 0000000..6e4b65c
--- /dev/null
+++ b/tests_and_examples/examples.tf/makefile.lnx
@@ -0,0 +1,37 @@
+
+# could add to CFLAGS to turn on warnings if you are using gcc
+WARNS=-Wall
+
+# change path if not running test from installed directory location
+INCS=-I../../pli_incs
+# maybe want -O<something> and/or -g, if you use -O use -march=
+CFLAGS= -fPIC -Wall $(INCS)
+LFLAGS= -G -shared -export-dynamic
+
+# change to your compiler
+CC=gcc
+
+probe.o:	probe.c 
+	$(CC) $(CFLAGS) -c probe.c
+
+tfclk.o:	tfclk.c 
+	$(CC) $(CFLAGS) -c tfclk.c
+
+plimfil.o:	plimfil.c
+	$(CC) $(CFLAGS) -c plimfil.c
+
+plimfil2.o:	plimfil2.c
+	$(CC) $(CFLAGS) -c plimfil2.c
+
+# make rules for dynamic libaries
+probe.so:	probe.o
+	$(LD) $(LFLAGS) probe.o -o probe.so
+
+tfclk.so:	tfclk.o
+	$(LD) $(LFLAGS) tfclk.o $(LFLAGS) -o tfclk.so
+
+plimfil.so:	plimfil.o
+	$(LD) $(LFLAGS) plimfil.o $(LFLAGS) -o plimfil.so
+
+plimfil2.so:	plimfil2.o
+	$(LD) $(LFLAGS) plimfil2.o $(LFLAGS) -o plimfil2.so
diff --git a/tests_and_examples/examples.tf/makefile.osx b/tests_and_examples/examples.tf/makefile.osx
new file mode 100644
index 0000000..020a126
--- /dev/null
+++ b/tests_and_examples/examples.tf/makefile.osx
@@ -0,0 +1,37 @@
+
+# could add to CFLAGS to turn on warnings if you are using gcc
+WARNS=-Wall
+
+# change path if not running test from installed directory location
+INCS=-I../../pli_incs
+# maybe want -O<something> and/or -g, if you use -O use -march=
+CFLAGS= -fPIC  -Wall $(INCS) -dynamic -fno-common 
+LFLAGS= -flat_namespace -bundle -undefined suppress
+
+# change to your compiler
+# CC=gcc
+
+probe.o:	probe.c 
+	$(CC) $(CFLAGS) -c probe.c
+
+tfclk.o:	tfclk.c 
+	$(CC) $(CFLAGS) -c tfclk.c
+
+plimfil.o:	plimfil.c
+	$(CC) $(CFLAGS) -c plimfil.c
+
+plimfil2.o:	plimfil2.c
+	$(CC) $(CFLAGS) -c plimfil2.c
+
+# make rules for dynamic libaries
+probe.dylib:	probe.o
+	$(CC) $(LFLAGS) probe.o -o probe.dylib
+
+tfclk.dylib:	tfclk.o
+	$(CC) $(LFLAGS) tfclk.o $(LFLAGS) -o tfclk.dylib
+
+plimfil.dylib:	plimfil.o
+	$(CC) $(LFLAGS) plimfil.o $(LFLAGS) -o plimfil.dylib
+
+plimfil2.dylib:	plimfil2.o
+	$(CC) $(LFLAGS) plimfil2.o $(LFLAGS) -o plimfil2.dylib
diff --git a/tests_and_examples/examples.tf/makefile.sparc-gcc b/tests_and_examples/examples.tf/makefile.sparc-gcc
new file mode 100644
index 0000000..864fc94
--- /dev/null
+++ b/tests_and_examples/examples.tf/makefile.sparc-gcc
@@ -0,0 +1,43 @@
+
+# version for gcc,  Sunworks cc, or others same except use different "CC="
+# could add to CFLAGS to turn on warnings if you are using gcc
+WARNS=-Wall
+
+# change path if not running test from installed directory location
+INCS=-I../../pli_incs
+# maybe want -O<something> and/or -g, also maybe -march= option
+CFLAGS= -Wall $(INCS)
+LFLAGS= -G 
+
+CC=gcc
+
+dig_main.o:	dig_main.c 
+	$(CC) $(CFLAGS) -c dig_main.c
+
+vpiuser.o:	vpiuser.c 
+	$(CC) $(CFLAGS) -c vpiuser.c
+
+probe.o:	probe.c
+	$(CC) $(CFLAGS) -c probe.c
+
+tfclk.o:	tfclk.c
+	$(CC) $(CFLAGS) -c tfclk.c
+
+plimfil.o:	plimfil.c
+	$(CC) $(CFLAGS) -c plimfil.c
+
+plimfil2.o:	plimfil2.c
+	$(CC) $(CFLAGS) -c plimfil2.c
+
+# make rules for dynamic libaries
+probe.so:	probe.o
+	$(CC) $(LFLAGS) probe.o -o probe.so
+
+tfclk.so:	tfclk.o 
+	$(CC) $(LFLAGS) tfclk.o -o tfclk.so
+
+plimfil.so:	plimfil.o 
+	$(CC) $(LFLAGS) plimfil.o -o plimfil.so
+
+plimfil2.so:	plimfil2.o 
+	$(CC) $(LFLAGS) plimfil2.o -o plimfil2.so
diff --git a/tests_and_examples/examples.tf/plimfil.c b/tests_and_examples/examples.tf/plimfil.c
new file mode 100644
index 0000000..91156f9
--- /dev/null
+++ b/tests_and_examples/examples.tf/plimfil.c
@@ -0,0 +1,151 @@
+/* Copyright (c) 1994-2003 Pragmatic C Software Corp. */
+
+/* 
+ * example illustrating using PLI tf_ utility routines to fill memory
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "veriuser.h"
+#include "cv_veriuser.h"
+
+/* define this to use Cver's immediate assign tf_strputp routine */
+/* #define __HAS_STRPUTP__ */
+
+int memsiz, memwid, last_i;
+FILE *memval_s;
+
+/* local prototypes */
+int intsize(int, int);
+static void plisetupmemfill(int, int);
+static void check_plimemfill(int, int);
+static void plimemfill(int, int);
+
+int intsize(int data, int reason)
+{
+ return(32);
+}
+
+/*
+ * routine to setup memory filling routine - set param to 0 on error else 1
+ * function: $plisetupmemfill(memsiz, memwid)
+ */
+static void plisetupmemfill(int data, int reason)
+{
+ char *chp;
+
+ /* get file name as + verilog argument */
+ if ((chp = mc_scan_plusargs("memfile+")) == NULL || strcmp(chp, "") == 0)
+  {
+   tf_error("missing or empty +memfile+[file name] memory file argument");
+   tf_putp(0, 0);
+   return;
+  }
+ /* open the file */
+ if ((memval_s = fopen(chp, "r")) == NULL)
+  {  
+   tf_error("unable to open +memfile+ memory file %s", chp); 
+   tf_putp(0, 0);
+   return;
+  }
+ /* need memory size for checking */
+ memsiz = tf_getp(1);
+ memwid = tf_getp(2);
+ tf_putp(0, 1);
+ /* assume memory goes from 1 to size */
+ last_i = 0; 
+}
+
+/*
+ * check the fill memory user PLI function
+ * notice calling tf_error here will inhibit simulation
+ * probably sould also check 2nd index argument 
+ */
+static void check_plimemfill(int data, int reason)
+{
+ struct t_tfexprinfo xinfo;
+
+ if (tf_nump() != 2)
+  {
+   tf_error("$pli_memfill has %d arguments - 2 required", tf_nump());
+   return;
+  }
+ tf_exprinfo(1, &xinfo);
+ if (xinfo.expr_type != TF_RWMEMSELECT)
+  {
+   tf_error("$pli_memfill first argument not read/write memory select");
+   return;
+  }
+}
+
+/*
+ * routine to set memory 
+ * function: $pli_memfill(mem[i], i)
+ */
+static void plimemfill(int data, int reason)
+{
+ int i;
+ char memval[1024];
+
+ i = tf_getp(2);
+ if (i < 0 || i > memsiz) 
+  {
+   tf_error("cannot fill memory location %d - memory has only %d cells");
+   tf_putp(0, 0);
+   return;
+  }
+ if (fscanf(memval_s, "%s", memval) != 1)
+  {
+   /* problably should access OS error name here */
+   tf_error("error reading memory value for cell %d", i);
+   tf_putp(0, 0);
+   return;
+  }
+ /* probably should add code to check for memval as legal binary number */
+ /* but can be any width since putp assignment will widen or truncate */
+
+ /* make sure index i is legal - since must have used i in memory select */
+ /* only for checking */
+ if (i != last_i + 1)
+  {
+   tf_error("memory index %d non in sequence - %d expected", i, last_i + 1);
+   tf_putp(0, 0);
+   return;
+  }
+ last_i = i;
+
+ /* this is #0, in Cver you would use extension routine tf_strputp */
+ /* it is identical to tf_strdelputp except string assignment immediate */
+#ifdef __HAS_STRPUTP__
+ /* notice need final delay type parameter since may need to cancel */
+ /* events if delay form used elsewhere */
+ printf("*** using tf_strputp\n"); 
+ if (tf_strputp(1, memwid, 'b', memval) == 0)
+#else
+ if (tf_strdelputp(1, memwid, 'b', memval, 0, 0) == 0)
+#endif
+  {
+   tf_error("strdelput of index memory failed");
+   tf_putp(0, 0);
+   return;
+  }
+ tf_putp(0, 1);
+}
+
+/* example that goes in user code */
+s_tfcell veriusertfs[] = 
+{ 
+ { userfunction, 0, 0, (int (*)()) intsize, (int (*)()) plisetupmemfill, 0,
+   "$pli_setupmemfill", 0},
+ { userfunction, 0, (int (*)()) check_plimemfill, (int (*)()) intsize,
+  (int (*)()) plimemfill, 0, "$pli_memfill", 0},
+ /* -- add extra entries here -- */
+ {0} /* -- this line must always be last -- */
+};
+
+/* dummy +loadpli1 boostrap routine - return old style veriusertfs tab */
+s_tfcell *pli1_compat_bootstrap(void)
+{
+ return(veriusertfs);
+}
diff --git a/tests_and_examples/examples.tf/plimfil.plg b/tests_and_examples/examples.tf/plimfil.plg
new file mode 100644
index 0000000..52ea711
--- /dev/null
+++ b/tests_and_examples/examples.tf/plimfil.plg
@@ -0,0 +1,12 @@
+writing filled memory values:
+1: 0000000000000000000000000000000000000000000000000000000000000000000
+2: 1111111111111111111111111111111111111111111111111111111111111111111
+3: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+4: zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
+5: 0101010101010101010101010101010101010101010101010101010101010101010
+6: x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x1x
+7: 1010101010101010101010101010101010101010101010101010101010101010101
+8: 1100110011110011001111001100111100110011110011001111001100111100110
+9: z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z1z
+10: 01xz01xz0101xz01xz0101xz01xz0101xz01xz0101xz01xz0101xz01xz0101xz01x
+
diff --git a/tests_and_examples/examples.tf/plimfil.v b/tests_and_examples/examples.tf/plimfil.v
new file mode 100644
index 0000000..4afc67a
--- /dev/null
+++ b/tests_and_examples/examples.tf/plimfil.v
@@ -0,0 +1,33 @@
+module xx; 
+ reg [66:0] mem1[1:10];
+
+initial
+  begin
+   fillmem;  
+   $display("writing filled memory values:"); 
+   writemem;
+  end
+
+ task fillmem;
+  integer i; 
+  begin
+   if ($pli_setupmemfill(10, 67) == 0) $finish;
+   for (i = 1; i <= 10; i = i + 1) 
+    begin  
+     if ($pli_memfill(mem1[i], i) == 0) $finish;
+     // notice must delay after call because value of i cannot change 
+     // but if mem fill used extension tf_strputp routine not needed
+     // if you do not need portability, tf_strputp is better
+     #10; 
+    end
+  end
+ endtask
+
+ task writemem; 
+  integer i;
+  begin
+   for (i = 1; i <= 10; i = i + 1) $display("%0d: %b", i, mem1[i]);
+   $write("\n");
+  end
+ endtask
+endmodule
diff --git a/tests_and_examples/examples.tf/plimfil2.c b/tests_and_examples/examples.tf/plimfil2.c
new file mode 100644
index 0000000..d69fe6d
--- /dev/null
+++ b/tests_and_examples/examples.tf/plimfil2.c
@@ -0,0 +1,158 @@
+/* Copyright (c) 1994-2003 Pragmatic C Software Corp. */
+
+/* 
+ * example illustrating using PLI tf_ utility routines to fill memory
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "veriuser.h"
+#include "cv_veriuser.h"
+
+int memsiz, memwid, last_i;
+FILE *memval_s;
+struct t_tfnodeinfo ninfo;
+struct t_tfexprinfo xinfo;
+
+/* static prototypes */
+static int intsize(int, int);
+static void plisetupmemfil2(int, int);
+static void check_plimemfil2(int, int);
+static void plimemfil2(int, int);
+
+static int intsize(int data, int reason)
+{
+ return(32);
+}
+
+/*
+ * routine to setup memory filling routine - set param to 0 on error else 1
+ * function: $plisetupmemfill(memsiz, memwid)
+ */
+static void plisetupmemfil2(int data, int reason)
+{
+ char *chp;
+
+ /* get file name as + verilog argument */
+ if ((chp = mc_scan_plusargs("memfile+")) == NULL || strcmp(chp, "") == 0)
+  {
+   tf_error("missing or empty +memfile+[file name] memory file argument");
+   tf_putp(0, 0);
+   return;
+  }
+ /* open the file */
+ if ((memval_s = fopen(chp, "r")) == NULL)
+  {  
+   tf_error("unable to open +memfile+ memory file %s", chp); 
+   tf_putp(0, 0);
+   return;
+  }
+ /* need memory size for checking */
+ memsiz = tf_getp(1);
+ memwid = tf_getp(2);
+ if (memwid > 32)
+  {
+   tf_error("for tf_propagatep routine can only use scanf for < 32 bits");
+   tf_putp(0, 0);
+   return;
+  }
+ tf_putp(0, 1);
+ /* assume memory goes from 1 to size */
+ last_i = 0; 
+}
+
+/*
+ * check the fill memory user PLI function
+ * notice calling tf_error here will inhibit simulation
+ * probably sould also check 2nd index argument 
+ */
+static void check_plimemfil2(int data, int reason)
+{
+ if (tf_nump() != 2)
+  {
+   tf_error("$pli_memfil2 has %d arguments - 2 required", tf_nump());
+   return;
+  }
+ /* this associates nodeinfo struct with argument */
+ tf_nodeinfo(1, &ninfo);
+ if (ninfo.node_type != TF_MEMORY_NODE)
+  {
+   tf_error("$pli_memfil2 first argument not read/write memory select");
+   return;
+  }
+}
+
+/*
+ * routine to set memory using tf_propagatep method  
+ *
+ * must be 32 bits or less otherwise would need to write vecval manipulation
+ * routines
+ *
+ * function: $pli_memfil2(mem[i], i)
+ * here tfputp would be better choice since only allows non x/z forms 
+ */
+static void plimemfil2(int data, int reason)
+{
+ int i;
+ unsigned memval;
+ struct t_vecval *vecp;
+
+ i = tf_getp(2);
+ if (i < 0 || i > memsiz) 
+  {
+   tf_error("cannot fill memory location %d - memory has only %d cells");
+   tf_putp(0, 0);
+   return;
+  }
+ if (fscanf(memval_s, "%u", &memval) != 1)
+  {
+   /* problably should access OS error name here */
+   tf_error("error reading memory value for cell %d", i);
+   tf_putp(0, 0);
+   return;
+  }
+ /* probably should add code to check for memval as legal binary number */
+ /* but can be any width since putp assignment will widen or truncate */
+
+ /* make sure index i is legal - since must have used i in memory select */
+ /* only for checking */
+ if (i != last_i + 1)
+  {
+   tf_error("memory index %d non in sequence - %d expected", i, last_i + 1);
+   tf_putp(0, 0);
+   return;
+  }
+ last_i = i;
+
+ tf_exprinfo(1, &xinfo);
+ /* set value  - using 32 bit value else would need string to 0*/
+ vecp = xinfo.expr_value_p;
+ vecp[0].avalbits = (int) memval;
+ vecp[0].bvalbits = 0;
+ /* do assign - notice this forces re-evaluate of argument during assign */
+ /* SJM 12/20/02 - following LRM, fail is 1 not 0 */
+ if (tf_propagatep(1) == 1)
+  {  
+   tf_error("tf_propagatep of indexed memory failed");
+   tf_putp(0, 0);
+  }
+ else tf_putp(0, 1);
+}
+
+/* example that goes in user code */
+s_tfcell veriusertfs[] = 
+{ 
+ { userfunction, 0, 0, (int (*)()) intsize, (int (*)()) plisetupmemfil2, 0,
+  "$pli_setupmemfil2", 0},
+ { userfunction, 0, (int (*)()) check_plimemfil2, (int (*)()) intsize,
+  (int (*)()) plimemfil2, 0, "$pli_memfil2", 0},
+ /* -- add extra entries here -- */
+ {0} /* -- this line must always be last -- */
+};
+
+/* dummy +loadpli1 boostrap routine - return old style veriusertfs tab */
+s_tfcell *pli1_compat_bootstrap(void)
+{
+ return(veriusertfs);
+}
diff --git a/tests_and_examples/examples.tf/plimfil2.plg b/tests_and_examples/examples.tf/plimfil2.plg
new file mode 100644
index 0000000..7027766
--- /dev/null
+++ b/tests_and_examples/examples.tf/plimfil2.plg
@@ -0,0 +1,7 @@
+writing filled memory values:
+1: 0
+2: 1
+3: 1024
+4: 16383
+5: 12345
+
diff --git a/tests_and_examples/examples.tf/plimfil2.v b/tests_and_examples/examples.tf/plimfil2.v
new file mode 100644
index 0000000..40c4463
--- /dev/null
+++ b/tests_and_examples/examples.tf/plimfil2.v
@@ -0,0 +1,32 @@
+module xx; 
+ reg [31:0] mem2[1:5];
+
+initial
+  begin
+   fillmem;  
+   $display("writing filled memory values:"); 
+   writemem;
+  end
+
+ task fillmem;
+  integer i; 
+  begin
+   if ($pli_setupmemfil2(5, 32) == 0) $finish;
+   // since propagatep assignment immediate evaluate of drivers
+   // do not need delay here
+   for (i = 1; i <= 5; i = i + 1) 
+    begin  
+     // only need 2nd index argument for checking */
+     if ($pli_memfil2(mem2[i], i) == 0) $finish;
+    end
+  end
+ endtask
+
+ task writemem; 
+  integer i;
+  begin
+   for (i = 1; i <= 5; i = i + 1) $display("%0d: %0d", i, mem2[i]);
+   $write("\n");
+  end
+ endtask
+endmodule
diff --git a/tests_and_examples/examples.tf/probe.c b/tests_and_examples/examples.tf/probe.c
new file mode 100644
index 0000000..5756485
--- /dev/null
+++ b/tests_and_examples/examples.tf/probe.c
@@ -0,0 +1,122 @@
+/* Copyright (c) 1994-2003 Pragmatic C Software Corp. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "veriuser.h"
+#include "cv_veriuser.h"
+ 
+#define MAXSIZE 500
+/* upto 10 parameters, MAXSIZE time values upto 64 bits long */ 
+/* (16 chars plus 0 end byte) */
+static char value_ar[10][MAXSIZE][17];  
+
+static int time_ar[MAXSIZE];
+static int total_nump;
+static int last_entry = 0;
+static char *setup_inst_p; 
+
+/* local function prototypes */
+static void vu_setup_values(void);
+static void vu_update_values(int, int, int);
+static void vu_doupdate(void);
+static void vu_flash_values(void);
+
+static void vu_setup_values(void)
+{
+ int nparam;
+
+ s_tfexprinfo einfo_s;
+ p_tfexprinfo info_p = &einfo_s;
+ /* get total number of parameters */
+ total_nump = tf_nump();
+ /* get the setup instance for updating values */
+ setup_inst_p = tf_getinstance();
+ /* if this is a second call to setup and asynchronous updating has been */
+ /* disabled then resume the asynchronous calls */
+ tf_asynchon();
+ for (nparam = 1; nparam <= total_nump; nparam++)
+ { 
+  /* check param lengths */
+  tf_exprinfo(nparam, info_p);
+  if (info_p->expr_ngroups > 2)
+   {
+    tf_error("parameters msut be less than 65 bits");
+   }
+ }
+ /* save initial values */
+ last_entry = 0; 
+ vu_doupdate();
+}
+
+/* this routine is aynchronously called during simulation */
+static void vu_update_values(int data, int reason, int pnum)
+{
+ /* test reason called */ 
+ if (reason == reason_paramvc)
+  {
+   io_printf("now %d parameter %d changed - reason paramvc_sync\n",
+    tf_gettime(), pnum);
+   tf_synchronize();
+  }
+ else if (reason == reason_synch)
+  {
+   io_printf("now %d misctf called for #0 reason_sync\n", tf_gettime());
+   vu_doupdate();
+  }
+}
+
+static void vu_doupdate(void)
+{
+ int nparam;
+
+ if (++last_entry == MAXSIZE)
+  {
+   /* the array is full. stop calling this routine */
+   tf_asynchoff();
+   return;
+  } 
+ /* obtain current simulation time */ 
+ time_ar[last_entry] = tf_gettime();
+ for (nparam = 1; nparam <= total_nump; nparam++)
+  /* obtain hex value of the parameter number nparam */
+  {
+  strcpy(value_ar[nparam][last_entry], tf_istrgetp(nparam, 'h', setup_inst_p));
+   io_printf("** now %d assign %s to param %d\n", time_ar[last_entry],
+   value_ar[nparam][last_entry], nparam);
+  }
+}
+
+/* this routine displays the values of variables at a given time */
+static void vu_flash_values(void)
+{
+ int nparam, find_time, entry_num;
+ /* get the value of time which is the only param */
+ find_time = tf_getp(1);
+ for (entry_num = last_entry; (entry_num > 0); entry_num--)
+  if (time_ar[entry_num] <= find_time)
+   break;
+ io_printf("For time %d\n", find_time);
+ /* this needs to go from 1 to number of params since task not func */ 
+ for (nparam = 1; nparam <= total_nump; nparam++)
+  io_printf("    value of parameter %d = %s\n", 
+   nparam, value_ar[nparam][entry_num]);
+} 
+
+s_tfcell veriusertfs[] =
+{
+ {usertask, 0,
+  0, 0, (int (*)()) vu_setup_values, (int (*)()) vu_update_values,
+  "$setup_values", 0 }, 
+ {usertask, 0,
+  0, 0, (int (*)()) vu_flash_values, 0,
+  "$flash_values", 0 }, 
+ {0} /* this line must always be last */
+};
+
+/* dummy +loadpli1 boostrap routine - return old style veriusertfs tab */
+s_tfcell *pli1_compat_bootstrap(void)
+{
+ return(veriusertfs);
+}
diff --git a/tests_and_examples/examples.tf/probe.plg b/tests_and_examples/examples.tf/probe.plg
new file mode 100644
index 0000000..405768f
--- /dev/null
+++ b/tests_and_examples/examples.tf/probe.plg
@@ -0,0 +1,92 @@
+** now 0 assign xxxxxxxx to param 1
+** now 0 assign xxxxxxxx to param 2
+** now 0 assign xxxxxxxx to param 3
+now 10 parameter 1 changed - reason paramvc_sync
+now 10 parameter 3 changed - reason paramvc_sync
+For time 5
+    value of parameter 1 = xxxxxxxx
+    value of parameter 2 = xxxxxxxx
+    value of parameter 3 = xxxxxxxx
+now 10 misctf called for #0 reason_sync
+** now 10 assign 00000003 to param 1
+** now 10 assign xxxxxxxx to param 2
+** now 10 assign 00000001 to param 3
+now 20 parameter 2 changed - reason paramvc_sync
+now 20 parameter 3 changed - reason paramvc_sync
+For time 10
+    value of parameter 1 = 00000003
+    value of parameter 2 = xxxxxxxx
+    value of parameter 3 = 00000001
+now 20 misctf called for #0 reason_sync
+** now 20 assign 00000003 to param 1
+** now 20 assign 00000003 to param 2
+** now 20 assign 00000002 to param 3
+now 30 parameter 3 changed - reason paramvc_sync
+For time 15
+    value of parameter 1 = 00000003
+    value of parameter 2 = xxxxxxxx
+    value of parameter 3 = 00000001
+now 30 misctf called for #0 reason_sync
+** now 30 assign 00000003 to param 1
+** now 30 assign 00000003 to param 2
+** now 30 assign 00000003 to param 3
+now 40 parameter 1 changed - reason paramvc_sync
+now 40 parameter 3 changed - reason paramvc_sync
+For time 20
+    value of parameter 1 = 00000003
+    value of parameter 2 = 00000003
+    value of parameter 3 = 00000002
+now 40 misctf called for #0 reason_sync
+** now 40 assign 00000021 to param 1
+** now 40 assign 00000003 to param 2
+** now 40 assign 00000009 to param 3
+now 50 parameter 2 changed - reason paramvc_sync
+now 50 parameter 3 changed - reason paramvc_sync
+For time 25
+    value of parameter 1 = 00000003
+    value of parameter 2 = 00000003
+    value of parameter 3 = 00000002
+now 50 misctf called for #0 reason_sync
+** now 50 assign 00000021 to param 1
+** now 50 assign 0000002c to param 2
+** now 50 assign 00000016 to param 3
+now 60 parameter 1 changed - reason paramvc_sync
+now 60 misctf called for #0 reason_sync
+** now 60 assign 0000001e to param 1
+** now 60 assign 0000002c to param 2
+** now 60 assign 00000016 to param 3
+now 70 parameter 1 changed - reason paramvc_sync
+now 70 parameter 2 changed - reason paramvc_sync
+now 70 parameter 3 changed - reason paramvc_sync
+For time 35
+    value of parameter 1 = 00000003
+    value of parameter 2 = 00000003
+    value of parameter 3 = 00000003
+now 70 misctf called for #0 reason_sync
+** now 70 assign 00000032 to param 1
+** now 70 assign 000000c8 to param 2
+** now 70 assign 00000000 to param 3
+now 80 parameter 3 changed - reason paramvc_sync
+For time 40
+    value of parameter 1 = 00000021
+    value of parameter 2 = 00000003
+    value of parameter 3 = 00000009
+now 80 misctf called for #0 reason_sync
+** now 80 assign 00000032 to param 1
+** now 80 assign 000000c8 to param 2
+** now 80 assign 00000063 to param 3
+now 90 parameter 2 changed - reason paramvc_sync
+now 90 misctf called for #0 reason_sync
+** now 90 assign 00000032 to param 1
+** now 90 assign 0000005a to param 2
+** now 90 assign 00000063 to param 3
+now 100 parameter 2 changed - reason paramvc_sync
+now 100 parameter 3 changed - reason paramvc_sync
+For time 50
+    value of parameter 1 = 00000021
+    value of parameter 2 = 0000002c
+    value of parameter 3 = 00000016
+now 100 misctf called for #0 reason_sync
+** now 100 assign 00000032 to param 1
+** now 100 assign 0000000b to param 2
+** now 100 assign 00000013 to param 3
diff --git a/tests_and_examples/examples.tf/probe.v b/tests_and_examples/examples.tf/probe.v
new file mode 100644
index 0000000..2e32e86
--- /dev/null
+++ b/tests_and_examples/examples.tf/probe.v
@@ -0,0 +1,20 @@
+module probe;
+ reg [31:0] a, b, c;
+
+ initial 
+  begin
+   $setup_values(a, b, c); 
+   #10 a = 3; c = 1;
+   #10 b = 3; c = 2;
+   #10 c = 3;
+   #10 a = 33; c = 9;
+   #10 b = 44; c = 22;
+   #10 a = 30;
+   #10 a = 50; b = 200; c = 0;
+   #10 a = 50; c = 99;
+   #10 b = 90; c = 99;
+   #10 b = 11; c = 19;
+  end
+ // do the flash
+ always @(c) $flash_values($stime/2);
+endmodule
diff --git a/tests_and_examples/examples.tf/rmlic.pl b/tests_and_examples/examples.tf/rmlic.pl
new file mode 100755
index 0000000..39c7ade
--- /dev/null
+++ b/tests_and_examples/examples.tf/rmlic.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+use strict;
+my $file;
+my $i;
+my $line;
+ 
+ $file = 'verilog.log';
+ if (@ARGV == 1)
+ {
+     $file = $ARGV[0];
+ }
+
+ open(FILE, $file) or die "Can't open $file\n";
+ open(TMP, '>tmp') or die "Can't open tmp file\n";
+ for($i = 0; $i < 3; $i++)
+ {
+      $line = <FILE>;
+ }
+ while(<FILE>)
+ {
+      print TMP $_;
+ }
+ close TMP;
+ close FILE;
+ rename 'tmp', $file;
diff --git a/tests_and_examples/examples.tf/testmem.dat b/tests_and_examples/examples.tf/testmem.dat
new file mode 100644
index 0000000..e356cd6
--- /dev/null
+++ b/tests_and_examples/examples.tf/testmem.dat
@@ -0,0 +1,10 @@
+0000000000_0000000000_0000000000_0000000000_0000000000_0000000000_0000000
+1111111111_1111111111_1111111111_1111111111_1111111111_1111111111_1111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101_0101010101_0101010
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x
+1010101010_1010101010_1010101010_1010101010_1010101010_1010101010_1010101
+1100110011_1100110011_1100110011_1100110011_1100110011_1100110011_1100110
+z1z1z1z1z1_z1z1z1z1z1_z1z1z1z1z1_z1z1z1z1z1_z1z1z1z1z1_z1z1z1z1z1_z1z1z1z
+01xz01xz01_01xz01xz01_01xz01xz01_01xz01xz01_01xz01xz01_01xz01xz01_01xz01x
diff --git a/tests_and_examples/examples.tf/testmem2.dat b/tests_and_examples/examples.tf/testmem2.dat
new file mode 100644
index 0000000..110621b
--- /dev/null
+++ b/tests_and_examples/examples.tf/testmem2.dat
@@ -0,0 +1,5 @@
+0
+1
+1024
+16383
+12345
diff --git a/tests_and_examples/examples.tf/tfclk.c b/tests_and_examples/examples.tf/tfclk.c
new file mode 100644
index 0000000..f712474
--- /dev/null
+++ b/tests_and_examples/examples.tf/tfclk.c
@@ -0,0 +1,144 @@
+/* Copyright (c) 1994-2003 Pragmatic C Software Corp. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "veriuser.h"
+#include "cv_veriuser.h"
+
+#define CLK_PER 100
+/* set DBG to 1 to print some trace message */
+#define DBG 0
+
+static char *tfip;
+
+/* local prototypes */
+static void tfclk_checktf(void);
+static void tfclkonoff_checktf(void);
+static int tfclkoff_sizetf(void);
+static void tfclk_calltf(int, int);
+static void tfclk_misctf(int, int);
+static void tfclkoff_calltf(int, int);
+static void tfclkon_calltf(int, int);
+
+
+/*
+ * check parameters passed to tf system task/function call
+ * must be one and must be rw non wire
+ */
+static void tfclk_checktf(void)
+{
+ int lno;
+ char *ip, *chp;
+ struct t_tfnodeinfo tfnode, *nip;
+ 
+ ip = tf_getinstance();
+ chp = tf_igetsourceloc(&lno, ip);
+ 
+ if (tf_nump() != 1)
+  tf_error(
+  "$tfclk pli task called with %d arguments one expected from **%s(%d)",
+   tf_nump(), chp, lno);    
+ nip = &tfnode;
+ nip = tf_nodeinfo(1, nip);
+ if (nip == NULL || (nip->node_type != TF_REG_NODE
+  && nip->node_type != TF_INTEGER_NODE && nip->node_type != TF_TIME_NODE)) 
+  tf_error(
+   "$tfclk invoked at **%s(%d) pli task argument must be read-write register",
+   chp, lno);
+ free(chp);
+}
+
+static void tfclkonoff_checktf(void)
+{
+ if (tf_nump() != 0)
+  tf_error("$tfclkoff pli task called with %d arguments none allowed",
+   tf_nump());    
+}
+
+/* clock off returns the time clock turned off */
+static int tfclkoff_sizetf(void)
+{
+ return(64);
+}
+
+/*
+ * start the set delay test clock
+ * this assumes there will only be one call of tfclk since tfip overwritten
+ * should add code to check for tfip already set and should initialize
+ */
+static void tfclk_calltf(int data, int reason)
+{
+ /* need to save instance for turning clock off */
+ tfip = tf_getinstance();
+ tf_putp(1, 0);
+ tf_setdelay(CLK_PER);
+}
+
+static void tfclk_misctf(int data, int reason)
+{
+ int lno;
+ char *ip, *chp;
+
+ if (DBG == 1)
+  {
+   ip = tf_getinstance();
+   chp = tf_igetsourceloc(&lno, ip);
+   io_printf(
+    "called misctf reason %d instance handle from file %s line %d\n",
+    reason, chp, lno); 
+   free(chp);
+  }
+ if (reason == REASON_REACTIVATE)
+  {
+   if ((chp = tf_strgetp(1, 'b')) == NULL)
+    tf_message(ERR_INTERNAL, "", "",
+    "$tfclk strgetp of misctf from delay expiration - strgetp failed");
+
+   if (strcmp(chp, "0") == 0) tf_putp(1, 1); else tf_putp(1, 0);
+   tf_setdelay(CLK_PER);
+  }
+ /* for ieee PLI lots of reasons that must just be ignored */
+}
+
+/*
+ * clock off returns time clock stopped
+ */
+static void tfclkoff_calltf(int data, int reason)
+{
+ int ltime, htime;
+
+ tf_iclearalldelays(tfip);
+ ltime = tf_igetlongtime(&htime, tfip);
+ tf_putlongp(0, ltime, htime);
+}
+
+static void tfclkon_calltf(int data, int reason)
+{
+ char *chp;
+
+ if ((chp = tf_strgetp(1, 'b')) == NULL)
+  tf_message(ERR_INTERNAL, "", "", "$tfclkon strgetp in calltf failed");
+ 
+ if (strcmp(chp, "0") == 0) tf_iputp(1, 1, tfip); else tf_putp(1, 0);
+ tf_setdelay(CLK_PER);
+}
+
+/* example that goes in user code */
+s_tfcell veriusertfs[] = { 
+ { usertask, 0, (int (*)()) tfclk_checktf, 0, (int (*)()) tfclk_calltf,
+  (int (*)()) tfclk_misctf, "$tfclk", 0},
+ { userfunction, 0, (int (*)()) tfclkonoff_checktf,
+  (int (*)()) tfclkoff_sizetf, (int (*)()) tfclkoff_calltf, 0, "$tfclkoff", 0},
+ { usertask, 0, (int (*)()) tfclkonoff_checktf, 0,
+  (int (*)()) tfclkon_calltf, 0, "$tfclkon", 0},
+ /* -- add extra entries here -- */
+ {0} /* -- this line must always be last -- */
+};
+
+/* dummy +loadpli1 boostrap routine - return old style veriusertfs tab */
+s_tfcell *pli1_compat_bootstrap(void)
+{
+ return(veriusertfs);
+}
diff --git a/tests_and_examples/examples.tf/tfclk.plg b/tests_and_examples/examples.tf/tfclk.plg
new file mode 100644
index 0000000..2426a74
--- /dev/null
+++ b/tests_and_examples/examples.tf/tfclk.plg
@@ -0,0 +1,22 @@
+                   0 x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+                  20 0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+                 120 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+                 220 0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+                 320 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+                 420 0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+                 520 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+                 620 0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+                 720 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+                 820 0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+                 920 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+clock turned off at                 1020
+                1220 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx0xx
+                1320 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx1xx
+                1420 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx0xx
+                1520 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx1xx
+                1620 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx0xx
+                1720 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx1xx
+                1820 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx0xx
+                1920 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx1xx
+                2020 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx0xx
+                2120 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx1xx
diff --git a/tests_and_examples/examples.tf/tfclk.v b/tests_and_examples/examples.tf/tfclk.v
new file mode 100644
index 0000000..3dcdfde
--- /dev/null
+++ b/tests_and_examples/examples.tf/tfclk.v
@@ -0,0 +1,21 @@
+
+`define CLK_PER 100
+
+module top;
+ setdel i1();
+endmodule
+
+module setdel;
+ reg clk;
+ reg [31:0] clk2;
+ time t;
+ initial 
+  begin
+   $monitor($time,, "%b %b", clk, clk2);
+   #20 $tfclk(clk);
+   #1000 t = $tfclkoff;
+   $display("clock turned off at %t", t); 
+   #200 $tfclk(clk2[2]);
+   #1000 $finish;
+  end
+endmodule
diff --git a/tests_and_examples/examples.vpi/README b/tests_and_examples/examples.vpi/README
new file mode 100644
index 0000000..945b40a
--- /dev/null
+++ b/tests_and_examples/examples.vpi/README
@@ -0,0 +1,168 @@
+
+       PLI 2.0 VPI ROUTINE EXAMPLES AND INSTALLATION TEST
+
+This directory contains PLI 2.0 API vpi_ routine examples to illustrate use 
+of PLI 2.0.  To test for correct installation run the inst_pli.sh script that
+compiles vpi_ programs into .so libraries which are dynamically loaded
+using new +loadvpi= Cver command line option and run.
+
+To see an example asynchronously driven PLI 2.0 vpi_ model, look
+at async.c (and async.v) test below.  The other tests show various
+PLI 2.0 vpi_ routine capabilities but are not complete models.
+
+To learn more about PLI 2.0 capabilities, read the various examples.  To
+learn how to use a particular vpi_ routine, access method, or to get
+properties from a particular object, run "grep [object or routine name] *.c".
+
+This script assumes you are using new +loadvpi= dynamic library PLI
+execution.  If you need to statically link your PLI libraries contact
+Pragmatic C to obtain the libraries and test scripts.
+
+HOW TO RUN THE TEST SCRIPT FOR ALL SYSTEMS EXCEPT MAC OSX AND CYGWIN (below) 
+
+1) Run the shell script inst_pli.sh [OS name].  Various compiler and Verilog
+   output messages will be printed but there should be no diff command
+   differences printed.  You must pass the name of your system as the one
+   argument to the script.  Depending on your platform, names are:
+   for X86 linux (suffix lnx), Sparc (suffix sparc-gcc).
+
+   Run the shell script opt_inst_pli.sh [OS name] to test PLI using
+   optimizer (-O) incremental compiler.
+
+   By convention makefile.[OS name] assumes this test is run in release
+   directory tree with include files in pli_incs 2 directory levels up
+   and Cver binary also 2 levels up.
+
+   The commands to run Cver with dynamically loaded user PLI library
+   explicitly access the user .so library in this directory.  For your
+   PLI libraries, it is better to set the LD_LIBRARY_PATH environment
+   variables so explicit "./" is not needed
+
+2) After completing the test, run clean.sh to remove work files.
+   The inst_pli.sh script removes each PLI library .so dynamic library after
+   running the test that uses it so unless something went wrong, you
+   do not need to run clean.sh.  
+
+3) Use makefile.[your OS] as a template for your vpi_ PLI 2.0 models.
+   Notice to use the PLI1 user defined PLI system/task function interface,
+   you must use +loadpli1= option.  To use newer PLI2 vpi_ user defined PLI
+   system/task function interface you must use +loadvpi=.  You should
+   use the +loadvpi= option for all new PLI code because of the additional
+   capabilities.  +loadpli1= system tasks can't be used with new vpi_
+   system task and function access methods because +loadpli1 system tasks
+   and functions must support old behavior.
+
+HOW TO RUN THE TEST SCRIPT FOR MAC OSX
+
+1) Run the shell script inst_pli.osx.sh.  Notice you do not need the
+   OS shell argument here.  Various compiler and Verilog
+   output messages will be printed but there should be no diff command
+   differences printed.  You must run this different script for MAC OSX
+   because OSX uses .dylib suffix for dynamic libraries and uses the
+   mach dynamic library mechanism instead of normal .so and dlopen. 
+
+   By convention, makefile.osx assumes this test is run in release
+   directory tree with include files in pli_incs 2 directory levels up
+   and Cver binary is in bin directory also 2 levels up.
+
+   The commands to run Cver with dynamically loaded user PLI library
+   explicitly access the user .dylib library in this directory.  For your
+   PLI libraries, it is better to set the LD_LIBRARY_PATH environment
+   variables so explicit "./" is not needed
+
+   Mac OSX linker (from mach OS) requires that a leading '_' be added to
+   each symbol name.  Cver does this automatically but you must make
+   sure that your bootstrap routine name does not start with underscore ('_').
+
+2) After completing the test, run clean.sh to remove work files.
+   The inst_pli.osx.sh script removes each PLI library .so dynamic library
+   after running the test that uses it so unless something went wrong, you
+   do not need to run clean.sh.  
+
+3) Use makefile.osx as a template for your PLI models.  You must use
+   exactly the LFLAGS options and set and export LD_LIBRARY_PATH
+   environment variable, or your .dylib user PLI code will not load
+   properly.
+
+HOW TO RUN PLI ON CYGWIN 
+   ****IMPORTANT - as of 02/02/04 the latest version of Cygwin contains a
+       bug which doesn't run the PLI correctly.  To run the PLI you will need 
+       Cygwin version 1.5.5 or earlier.
+
+1) First, you must make a cver dll and executable.  Go to the objs directory
+   (gplcver-*/objs/), and type the following commands:
+        
+       make -f makefile.dll dll                 #makes the dll library
+       make -f makefile.dll exe                 #make the new cver.exe
+
+2) Next copy the libcver.dll library to the lib directory:
+
+       cp libcver.dll /lib/ 
+
+3) In the vpi examples directory (this one), type the following commands:
+
+       make -f makefile.cygwin dll                #compiles libvfopen1.c
+       make -f makefile.cygwin run                #runs the PLI example
+
+4) All of these should compile correctly, and 'make -f makefile.vpi run', 
+   runs the PLI example vfopen1.v after making the libvopen1 library.
+
+---------------------------------------------------------------------------
+
+Tests are:
+
+  1. async.c is asynchronously switching not gate implemented using vpi_.
+
+  2. vhello1.c and vhello2.c are "hello world" tests that also show use
+     of environment determing vpi_ routines.
+
+  3. vhelbad.c is a "hello world" test with some vpi_ errors to illustrate
+     vpi_ error checking.
+
+  4. findcaus.c is test that traverses Verilog design hierarchy.
+
+  5. vcabtsts.c is a test that registers every call back and prints a message
+     when it occurs.
+
+  6. vprtchg.c adds cbValueChange callbacks to every .v file varaibles and
+     prints a message on every change.
+
+  7. vprtchg2.c test also prints every variable change in a design
+     except it uses vpi_get_value and vpi_get_time instead of the built in
+     value change callback values.
+
+  8. vprtchg3.c prints new and old variable values using an on change call
+     back.
+
+  9. vprtdels.c accesses and prints every delay in a design.
+
+  10. vprtdel2.c illustrates vpi_ timscale handling.
+
+  11. vsetdels.c use vpi_ to set delays.
+
+  12. vsetval1.c tests various vpi_put_value uses.
+
+  13. vtimcbs.c illustrates use of various delay callbacks.
+
+  14. vfopen1.c implements $fopen built in system function using PLI 2.0.
+
+  15. vfopen2.c is  variant of the vfopen1.c test using vpi_ system task
+      instead of vpi_ system function.
+
+  16. vconta1.c tests continous assignments and non lvalue expression
+      decomposition.
+
+  17. vchkprt1.c tests most port and vpiHighConn/vpiLowConn one to one
+      and one to many iterators.  It is possible that either the .c model
+      or Cver's interpretation of the LRM are not right because Cver
+      assumes all bit iterators are LSB to MSB in terms of vpi_scan order.
+
+  18. vdrvld1.c tests vpiDriver and vpiLoad iterators for nets.
+
+  19. vdrvld2.c tests vpiDriver and vpiLoad iterators for bits of nets.
+
+  20. dfpsetd.c tests vpi_put_value to defparam and specparam during
+      cbEndOfCompile call back for delay annotation (allows delay annotation
+      to procedural delay controls and continuous assignments).  Test
+      sets same delays and produces same results using vpi_ as dfpsetd.vc
+      in install.tst directory that uses 2 SDF delay annotation files.
diff --git a/tests_and_examples/examples.vpi/async.c b/tests_and_examples/examples.vpi/async.c
new file mode 100644
index 0000000..fd3f2b0
--- /dev/null
+++ b/tests_and_examples/examples.vpi/async.c
@@ -0,0 +1,195 @@
+/*
+ * simplest asynchronously driven not "CPU" model 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* better to install the in include directory and use <> */
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* really need per instance for each of these probably in malloced storage */
+static vpiHandle outdrvh;  
+
+/* local function prototypes */
+static PLI_INT32 pli_not(void);
+static int do_pli_not(s_cb_data *);
+static int my_error_handler(struct t_cb_data *);
+
+/* global function prototypes */
+extern void register_my_systfs(void);
+extern void register_cbs(void);
+
+/*
+ * one call in procedural code to set up not model
+ *
+ * returns 0 since required by vpi_user.h types but unused
+ */
+static PLI_INT32 pli_not(void)
+{
+    int numargs;
+    vpiHandle href, iter, inh, outh;
+    s_vpi_time tmptim;
+    s_vpi_value outval, inval;
+    s_cb_data cbrec, *cbp;
+
+    href = vpi_handle(vpiSysTfCall, NULL); 
+    iter = vpi_iterate(vpiArgument, href);
+    /* maybe ... <code to check arguments (include bad_args label)> */
+    numargs = vpi_get(vpiSize, iter);
+
+    if ((outh = vpi_scan(iter)) == NULL)
+     {
+bad_args:
+      /* need error message here */
+      return(0);
+     }
+    if ((inh = vpi_scan(iter)) == NULL) goto bad_args;
+
+    /* add the driver */
+    outdrvh = vpi_put_value(outh, NULL, NULL, vpiAddDriver);
+
+    /* make sure output starts as x */
+    outval.format = vpiScalarVal;
+    outval.value.scalar = vpiX; 
+    /* because driver always initialized to z (tristate), must set to x */
+    vpi_put_value(outdrvh, &outval, NULL, vpiNoDelay);
+
+    /* cb records must be in global storage because used inside PLI */
+    cbp = &cbrec;
+    cbp->reason = cbValueChange;
+    cbp->cb_rtn = do_pli_not;
+    cbp->obj = inh;
+    /* do not need to have input handle change time recorded */
+    tmptim.type = vpiSuppressTime; 
+    cbp->time = &tmptim;
+
+    /* but need changed input value - records value on change */
+    inval.format = vpiScalarVal; 
+    cbp->value = &inval;
+
+    cbp->user_data = NULL;
+    vpi_register_cb(cbp);
+    return(0);
+}
+
+/*
+ * call back routine - called whenever not input changes (model goes here)
+ */
+static int do_pli_not(s_cb_data *cbp)
+{
+    int outv, inv;
+    vpiHandle eventh;
+    s_vpi_value outval;
+    s_vpi_time tmptim;
+
+    /* better would be to use callback value field */
+    inv = cbp->value->value.scalar;
+    if (inv == vpi1) outv = vpi0;
+    else if (inv == vpi0) outv = vpi1;
+    else outv = vpiX;
+
+    /* assume all nots have delay 5 - could be vpiNoDelay */
+    tmptim.type = vpiScaledRealTime;
+    tmptim.real = 5.0;
+    outval.format = vpiScalarVal;
+    outval.value.scalar = outv; 
+    /* return event but not used in "not" version 1 */
+    /* could use eventh to implement CPU pin C code timing checks */
+    eventh = vpi_put_value(outdrvh, &outval, &tmptim,
+      (vpiInertialDelay | vpiReturnEvent));
+    return(0);
+}
+
+/*
+ * routine to build an error indication string
+ * I usually start by running under debugger with breakpoint here
+ */
+static int my_error_handler(struct t_cb_data *cbp)
+{
+    struct t_vpi_error_info einfotab;
+    struct t_vpi_error_info *einfop;
+    char s1[128];
+
+    einfop = &einfotab;
+    vpi_chk_error(einfop);
+
+    if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+    else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+    else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+    else strcpy(s1, "**unknown**");
+
+    vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+       einfop->code, s1, einfop->level, einfop->file, einfop->line,
+       einfop->message);
+
+    /* if serious error give up */
+    if (einfop->level == vpiError || einfop->level == vpiSystem
+      || einfop->level == vpiInternal)
+      {
+         vpi_printf("**FATAL: encountered error - giving up\n");
+         vpi_sim_control(vpiFinish, 0);
+      }
+    return(0);
+}
+
+void register_cbs(void)
+{
+    vpiHandle href;
+    p_cb_data ecbp;
+    s_cb_data ecbrec;
+
+    /* notice cb records must be in global storage */
+    ecbp = &ecbrec;
+    ecbp->reason = cbPLIError;
+    ecbp->cb_rtn = my_error_handler; 
+    ecbp->obj = NULL;
+    ecbp->time = NULL;
+    ecbp->value = NULL; 
+    ecbp->user_data = NULL;
+
+    /* probably should check for error here */
+    if ((href = vpi_register_cb(ecbp)) == NULL)
+       vpi_printf("**ERR: can not regiser register error handler callback.\n");
+}
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+void (*vlog_startup_routines[]) () =
+{
+    register_my_systfs, 
+    register_cbs,
+    0
+};
+
+void register_my_systfs(void)
+{
+    p_vpi_systf_data systf_data_p;
+
+    static s_vpi_systf_data systf_data_list[] = {
+       { vpiSysTask, 0, "$pli_not", pli_not, NULL, NULL, NULL },
+       { 0, 0, NULL, NULL, NULL, NULL, NULL }
+    };
+
+    systf_data_p = &(systf_data_list[0]);
+    while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/async.plg b/tests_and_examples/examples.vpi/async.plg
new file mode 100644
index 0000000..1857dc5
--- /dev/null
+++ b/tests_and_examples/examples.vpi/async.plg
@@ -0,0 +1,8 @@
+         0 z=x, a=x
+        10 z=x, a=z
+        20 z=x, a=1
+        25 z=0, a=1
+        30 z=0, a=0
+        35 z=1, a=0
+        40 z=1, a=1
+        41 z=1, a=0
diff --git a/tests_and_examples/examples.vpi/async.v b/tests_and_examples/examples.vpi/async.v
new file mode 100644
index 0000000..50d9f26
--- /dev/null
+++ b/tests_and_examples/examples.vpi/async.v
@@ -0,0 +1,21 @@
+/*
+ * async driven not gate cpu PLI model .v file
+ */
+module top;
+    wire z;
+    reg a;
+    initial
+        begin
+            $monitor($stime,, "z=%b, a=%b", z, a);   
+            $pli_not(z, a);
+        end
+    initial
+        begin
+           #10 a = 1'bz;
+           #10 a = 1;
+           #10 a = 0;
+           #10 a = 1;
+           // notice glitch that PLI model maybe should catch 
+            #1 a = 0;
+        end
+endmodule
diff --git a/tests_and_examples/examples.vpi/cacatmd1.v b/tests_and_examples/examples.vpi/cacatmd1.v
new file mode 100644
index 0000000..96f1cd1
--- /dev/null
+++ b/tests_and_examples/examples.vpi/cacatmd1.v
@@ -0,0 +1,21 @@
+module xx;
+ wire [31:0] w;
+ wire [15:0] a, b, c;
+ reg [31:0] w_r;
+
+ assign {a[7:2], b, c[9:3]} = w;
+ assign w = w_r;
+ assign w = 32'hzzzzzzzz;
+ assign b[1] = w[9]; 
+
+ initial
+  begin
+   $monitor($stime,, "a=%b, b=%b, c=%b, w=%h", a, b, c, w);
+   #10 w_r = 0;
+   #10 w_r = 32'hffffffff;
+   #10 w_r = 32'haaaaaaaa;
+   #10 w_r = 32'h55555555;
+   #10 w_r = 32'hffffffff;
+   #10 w_r = 0;
+  end
+endmodule
diff --git a/tests_and_examples/examples.vpi/clean.sh b/tests_and_examples/examples.vpi/clean.sh
new file mode 100755
index 0000000..6376758
--- /dev/null
+++ b/tests_and_examples/examples.vpi/clean.sh
@@ -0,0 +1 @@
+rm *.o *.dylib verilog.log fff9
diff --git a/tests_and_examples/examples.vpi/dfpsetd.c b/tests_and_examples/examples.vpi/dfpsetd.c
new file mode 100644
index 0000000..df4c6ca
--- /dev/null
+++ b/tests_and_examples/examples.vpi/dfpsetd.c
@@ -0,0 +1,167 @@
+/*
+ * simplest asynchronously driven not "CPU" model 
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+/* better to install the in include directory and use <> */
+/* do not need the PLI 1.0 includes, but do not hurt */
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+#define TRUE 1
+#define FALSE 0
+
+
+/* global function prototypes */
+extern int my_delay_calculator(struct t_cb_data *);
+extern int my_error_handler(struct t_cb_data *);
+static void register_cbs(void);
+
+/*
+ * routine to calculate delays - this has dfpsetd.v connectivity built in
+ *
+ * real delay calculator would traverse design and process each cell type
+ * according to probably some external tables
+ */
+int my_delay_calculator(struct t_cb_data *cbp)
+{
+ vpiHandle op, scope;
+ s_vpi_delay drec;
+ s_vpi_time delarr[12];
+ s_vpi_value pval;
+
+ /* set defparam for later evaluation to change delay control */
+ /* this will change #d to #100 */ 
+ op = vpi_handle_by_name("ffnand_test.d", NULL);
+ /* DBG to test bad path op = vpi_handle_by_name("ffnand_test.dxx", NULL); */
+ if (op == NULL)
+  {
+   vpi_mcd_printf(1, "**ERR unable to find instance for setting delays in");
+   return(0);
+  }
+ pval.format = vpiIntVal;
+ pval.value.integer = 100;
+ vpi_put_value(op, &pval, NULL, vpiNoDelay);
+
+ /* set ff1 r and f specparams - used to set path delays during elaboration */
+ scope = vpi_handle_by_name("ffnand_test.ff1", NULL);
+ op = vpi_handle_by_name("pr", scope);
+ pval.format = vpiIntVal;
+ pval.value.integer = 10;
+ vpi_put_value(op, &pval, NULL, vpiNoDelay);
+
+ op = vpi_handle_by_name("pf", scope);
+ pval.format = vpiIntVal;
+ pval.value.integer = 10;
+ vpi_put_value(op, &pval, NULL, vpiNoDelay);
+
+ op = vpi_handle_by_name("q1", scope);
+ drec.da = &(delarr[0]);
+ drec.no_of_delays = 2;
+ drec.time_type = vpiSimTime;
+ drec.mtm_flag = FALSE;
+ drec.pulsere_flag = FALSE;
+ drec.append_flag = FALSE;
+ drec.da[0].type = vpiSimTime;
+ drec.da[0].high = 0;
+ drec.da[0].low = 6;
+ drec.da[1].type = vpiSimTime;
+ drec.da[1].high = 0;
+ drec.da[1].low = 6;
+ vpi_put_delays(op, &drec);
+
+ op = vpi_handle_by_name("q2", scope);
+ vpi_put_delays(op, &drec);
+ 
+ vpi_mcd_printf(1, "... PLI delay setting complete.\n");  
+ return(0);
+}
+
+/*
+ * routine to build an error indication string
+ * I usually start by running under debugger with breakpoint here
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+    struct t_vpi_error_info einfotab;
+    struct t_vpi_error_info *einfop;
+    char s1[128];
+
+    einfop = &einfotab;
+    vpi_chk_error(einfop);
+
+    if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+    else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+    else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+    else strcpy(s1, "**unknown**");
+
+    vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+       einfop->code, s1, einfop->level, einfop->file, einfop->line,
+       einfop->message);
+
+    /* if serious error give up */
+    if (einfop->level == vpiError || einfop->level == vpiSystem
+      || einfop->level == vpiInternal)
+      {
+         vpi_printf("**FATAL: encountered error - giving up\n");
+	 vpi_sim_control(vpiFinish, 0);
+      }
+    return(0);
+}
+
+void register_cbs(void)
+{
+    vpiHandle href;
+    p_cb_data ecbp, cbp;
+    /* really need per instanc for these probably should b malloced */
+    s_cb_data cbrec, ecbrec;
+
+    /* notice cb records must be in global storage */
+    ecbp = &ecbrec;
+    ecbp->reason = cbPLIError;
+    ecbp->cb_rtn = my_error_handler; 
+    ecbp->obj = NULL;
+    ecbp->time = NULL;
+    ecbp->value = NULL; 
+    ecbp->user_data = NULL;
+
+    /* probably should access and emit explanatory error msg here */
+    if ((href = vpi_register_cb(ecbp)) == NULL)
+       vpi_printf("**ERR: can not register error handler callback.\n");
+
+    /* register cbEndOfCompile call back */
+    /* delay setting must be done here because internal net list built */
+    /* so design traversal possible, but delays not yet elaborated */
+    cbp = &cbrec;
+    cbp->reason = cbEndOfCompile;
+    cbp->cb_rtn = my_delay_calculator; 
+    cbp->obj = NULL;
+    cbp->time = NULL;
+    cbp->value = NULL; 
+    cbp->user_data = NULL;
+
+    if ((href = vpi_register_cb(cbp)) == NULL)
+       vpi_printf("**ERR: can not register end of compile callback.\n");
+
+}
+
+void (*vlog_startup_routines[]) () =
+{
+    register_cbs,
+    0
+};
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/dfpsetd.plg b/tests_and_examples/examples.vpi/dfpsetd.plg
new file mode 100644
index 0000000..d7521e1
--- /dev/null
+++ b/tests_and_examples/examples.vpi/dfpsetd.plg
@@ -0,0 +1,10 @@
+... PLI delay setting complete.
+                   0 preset=x clear=x q=x qbar=x
+                 100 preset=0 clear=1 q=x qbar=x
+                 110 preset=0 clear=1 q=1 qbar=x
+                 116 preset=0 clear=1 q=1 qbar=0
+                 200 preset=1 clear=1 q=1 qbar=0
+                 300 preset=1 clear=0 q=1 qbar=0
+                 306 preset=1 clear=0 q=1 qbar=1
+                 312 preset=1 clear=0 q=0 qbar=1
+                 400 preset=1 clear=1 q=0 qbar=1
diff --git a/tests_and_examples/examples.vpi/dfpsetd.v b/tests_and_examples/examples.vpi/dfpsetd.v
new file mode 100644
index 0000000..f22b794
--- /dev/null
+++ b/tests_and_examples/examples.vpi/dfpsetd.v
@@ -0,0 +1,31 @@
+module ffnand_test;
+ wire q, qbar;
+ reg preset, clear;
+
+ parameter d = 10;
+
+ ffnand ff1(q, qbar, preset, clear);
+ initial 
+  begin
+   #d preset = 0; clear = 1;
+   #d preset = 1;
+   #d clear = 0;
+   #d clear = 1;
+  end
+ initial $monitor($time,, "preset=%b clear=%b q=%b qbar=%b",
+  preset, clear,q, qbar);
+endmodule
+
+module ffnand(ffq, ffqbar, ffpreset, ffclear);
+ output ffq, ffqbar;
+ input ffpreset, ffclear;
+  
+ nand #(1, 1) q1(ffq, ffqbar, ffpreset), q2(ffqbar, ffq, ffclear); 
+ specify
+  specparam pr = 5;
+  specparam pf = 5;
+  // notice error because no path delay to ffqbar
+  (ffpreset => ffq) = (pr, pf);
+  (ffclear => ffq) = (pr, pf);
+ endspecify
+endmodule
diff --git a/tests_and_examples/examples.vpi/fdspec01.v b/tests_and_examples/examples.vpi/fdspec01.v
new file mode 100644
index 0000000..0af9d32
--- /dev/null
+++ b/tests_and_examples/examples.vpi/fdspec01.v
@@ -0,0 +1,139 @@
+// specify test for fd clear/set flip flop
+module test;
+ wire t_q;  
+ reg t_clk, t_clk0, t_clk1, t_clk2, t_d, t_clr, t_set;
+
+ fd3noqn i1(t_q0, t_clk2, t_clk2, t_d0, t_clr0, t_set0);
+ fd3noqn i2(t_q1, t_clk2, t_clk2, t_d1, t_clr1, t_set1);
+ fd3noqn i3(t_q, t_clk, t_clk1, t_d, t_clr, t_set);
+
+ initial 
+  begin
+   $monitor($stime,, "q=%b, clk=%b, data=%b, clr=%b, set=%b",
+    t_q, t_clk, t_d, t_clr, t_set);
+   // test set/clear logic and delays - set overrides - low assertion 
+   #1000 $display("testing set/clear logic"); t_set = 1'bx;
+   #1000 t_set = 0;
+   #1000 t_clr = 0;
+   #1000 t_set = 1;
+   #1000 t_set = 0; 
+   #1000 t_set = 1; 
+   #1000 t_clr = 1'bx;
+   // test normal logic (set clear must be high)
+   #1000 $display("testing normal logic"); t_clr = 1; t_set = 1; t_d = 0;
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1'bx;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bz;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bx;
+   #1000 t_clk = 1;
+   #1000 t_d = 1; t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #1000 t_clk = 1; 
+   #1000 t_clk = 0; 
+   #100 t_clk = 1'bx;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bz;
+   #1000 t_clk = 0;
+   #1000 t_clk = 1'bx;
+   #1000 t_clk = 1;
+   // test setup
+   #30 t_clk = 0;
+   #30 t_d = 1;
+   #30 t_clk = 1;
+   #30 t_d = 0;
+   #30 t_clk = 0;
+   #30 t_d = 1;
+   #30 t_clk = 1; t_d = 0; t_clk = 0; t_d = 1; t_clk = 1;
+   #100 t_clk = 0; t_clk1 = 0;
+   #100 t_clk1 = 1;
+   #2000 t_clk = 1;
+
+   /* ---
+   #100 t_d = 1; t_clk = 1;
+   #100 t_d = 1;
+   #450 t_clk = 1;
+   #550 t_clk = 0;
+   #200 t_d = 0;
+
+   #350 t_clk = 1;
+   #550 t_clk = 0;
+
+   #550 t_clk = 1;
+   #550 t_clk = 0;
+  --- */
+  end
+endmodule
+
+module fd3noqn(q, clk, clk1, d, clr, set);
+ output q;
+ input clk, clk1, d, clr, set;
+ // wire xxx;
+
+ specify
+  specparam tRise_clk_q = 140, tFall_clk_q = 250;
+  specparam tRise_control = 40, tFall_control= 50;
+  specparam tSetup=70, tHold=50;
+  specparam tWpos=600, tWneg=500;
+
+  // paths
+  (clk => q) = (tRise_clk_q, tFall_clk_q);
+  (clr,set *> q) = (tRise_control, tFall_control);
+
+  // timing checks
+  // setup time: d is reference, clk is data - setup > posedge clk - last data
+  // data must be stable > setup when clock triggers (pos. edge) 
+  // setup(ref, data, >setup);
+  // $setup(d, posedge clk, tSetup);
+
+  // hold time:  clk is reference, d is data - hold > d change after last clk
+  // hold(ref, data, >hold);
+  // $hold(posedge clk, d, tHold);
+
+  $setuphold(posedge clk, d, tSetup, tHold);
+
+  $width(posedge clk, tWpos);
+  $width(negedge clk, tWneg);
+  $period(posedge clk, 1000:1200:1400);
+  $skew(posedge clk1, posedge clk, 50);
+  $recovery(posedge d, clk, 200);
+ endspecify
+
+ xl_fd3 /* #10 */ i0(q, d, clk, clr, set);
+ // buf i1(q, xxx);
+ // not i2(qn, xxx);
+endmodule
+
+primitive xl_fd3(q, d, clk, clr, set);
+ output q; reg q;
+ input d, clk, clr, set;
+
+ table
+  // d  clk  clr  set  :  q  :  q
+  // -  ---  ---  ---  -  -  -  -
+  // set/clear low assertion 
+     ?   ?    ?    0   :  ?  :  1 ;
+     ?   ?    ?    x   :  ?  :  x ;
+     ?   ?    0    1   :  ?  :  0 ;
+     ?   ?    x    1   :  ?  :  x ;
+
+     0   r    1    1   :  ?  :  0 ;
+     1   r    1    1   :  ?  :  1 ;
+     x   r    1    1   :  ?  :  x ;
+
+     ?   f    1    1   :  ?  :  - ;
+     ?  (x?)  1    1   :  ?  :  - ;
+     ?  (?x)  1    1   :  ?  :  - ;
+     *   ?    1    1   :  ?  :  - ;
+     ?   ?    r    1   :  ?  :  - ;
+     ?   ?    1    r   :  ?  :  - ;
+ endtable
+endprimitive
diff --git a/tests_and_examples/examples.vpi/fff9 b/tests_and_examples/examples.vpi/fff9
new file mode 100644
index 0000000..f1fb4fb
--- /dev/null
+++ b/tests_and_examples/examples.vpi/fff9
@@ -0,0 +1,118 @@
+  There are 1 top level modules.
+  There are 1 instances in test.
+  Processing port test.Mux554.Select (index 0):
+Port 0 bit 0 vpiLowConn test.Mux554.Select[1] connects to vpiHighConn test.net_31[3].
+Port 0 bit 1 vpiLowConn test.Mux554.Select[0] connects to vpiHighConn test.net_31[2].
+  Processing port test.Mux554.Output (index 1):
+Port 1 bit 0 vpiLowConn test.Mux554.Output[31] connects to vpiHighConn test.net_44[31].
+Port 1 bit 1 vpiLowConn test.Mux554.Output[30] connects to vpiHighConn test.net_44[30].
+Port 1 bit 2 vpiLowConn test.Mux554.Output[29] connects to vpiHighConn test.net_44[29].
+Port 1 bit 3 vpiLowConn test.Mux554.Output[28] connects to vpiHighConn test.net_44[28].
+Port 1 bit 4 vpiLowConn test.Mux554.Output[27] connects to vpiHighConn test.net_44[27].
+Port 1 bit 5 vpiLowConn test.Mux554.Output[26] connects to vpiHighConn test.net_44[26].
+Port 1 bit 6 vpiLowConn test.Mux554.Output[25] connects to vpiHighConn test.net_44[25].
+Port 1 bit 7 vpiLowConn test.Mux554.Output[24] connects to vpiHighConn test.net_44[24].
+Port 1 bit 8 vpiLowConn test.Mux554.Output[23] connects to vpiHighConn test.net_44[23].
+Port 1 bit 9 vpiLowConn test.Mux554.Output[22] connects to vpiHighConn test.net_44[22].
+Port 1 bit 10 vpiLowConn test.Mux554.Output[21] connects to vpiHighConn test.net_44[21].
+Port 1 bit 11 vpiLowConn test.Mux554.Output[20] connects to vpiHighConn test.net_44[20].
+Port 1 bit 12 vpiLowConn test.Mux554.Output[19] connects to vpiHighConn test.net_44[19].
+Port 1 bit 13 vpiLowConn test.Mux554.Output[18] connects to vpiHighConn test.net_44[18].
+Port 1 bit 14 vpiLowConn test.Mux554.Output[17] connects to vpiHighConn test.net_44[17].
+Port 1 bit 15 vpiLowConn test.Mux554.Output[16] connects to vpiHighConn test.net_44[16].
+Port 1 bit 16 vpiLowConn test.Mux554.Output[15] connects to vpiHighConn test.net_44[15].
+Port 1 bit 17 vpiLowConn test.Mux554.Output[14] connects to vpiHighConn test.net_44[14].
+Port 1 bit 18 vpiLowConn test.Mux554.Output[13] connects to vpiHighConn test.net_44[13].
+Port 1 bit 19 vpiLowConn test.Mux554.Output[12] connects to vpiHighConn test.net_44[12].
+Port 1 bit 20 vpiLowConn test.Mux554.Output[11] connects to vpiHighConn test.net_44[11].
+Port 1 bit 21 vpiLowConn test.Mux554.Output[10] connects to vpiHighConn test.net_44[10].
+Port 1 bit 22 vpiLowConn test.Mux554.Output[9] connects to vpiHighConn test.net_44[9].
+Port 1 bit 23 vpiLowConn test.Mux554.Output[8] connects to vpiHighConn test.net_44[8].
+Port 1 bit 24 vpiLowConn test.Mux554.Output[7] connects to vpiHighConn test.net_44[7].
+Port 1 bit 25 vpiLowConn test.Mux554.Output[6] connects to vpiHighConn test.net_44[6].
+Port 1 bit 26 vpiLowConn test.Mux554.Output[5] connects to vpiHighConn test.net_44[5].
+Port 1 bit 27 vpiLowConn test.Mux554.Output[4] connects to vpiHighConn test.net_44[4].
+Port 1 bit 28 vpiLowConn test.Mux554.Output[3] connects to vpiHighConn test.net_44[3].
+Port 1 bit 29 vpiLowConn test.Mux554.Output[2] connects to vpiHighConn test.net_44[2].
+Port 1 bit 30 vpiLowConn test.Mux554.Output[1] connects to vpiHighConn test.net_44[1].
+Port 1 bit 31 vpiLowConn test.Mux554.Output[0] connects to vpiHighConn test.net_44[0].
+  Processing port test.Mux554.In0 (index 2):
+Also port test.Mux554.In3 is a vpiPortInst.
+Also port test.Mux554.In2 is a vpiPortInst.
+Also port test.Mux554.In1 is a vpiPortInst.
+Port 2 bit 0 vpiLowConn test.Mux554.In0[31] connects to vpiHighConn test.Data_In[127].
+Port 2 bit 1 vpiLowConn test.Mux554.In0[30] connects to vpiHighConn test.Data_In[126].
+Port 2 bit 2 vpiLowConn test.Mux554.In0[29] connects to vpiHighConn test.Data_In[125].
+Port 2 bit 3 vpiLowConn test.Mux554.In0[28] connects to vpiHighConn test.Data_In[124].
+Port 2 bit 4 vpiLowConn test.Mux554.In0[27] connects to vpiHighConn test.Data_In[123].
+Port 2 bit 5 vpiLowConn test.Mux554.In0[26] connects to vpiHighConn test.Data_In[122].
+Port 2 bit 6 vpiLowConn test.Mux554.In0[25] connects to vpiHighConn test.Data_In[121].
+Port 2 bit 7 vpiLowConn test.Mux554.In0[24] connects to vpiHighConn test.Data_In[120].
+Port 2 bit 8 vpiLowConn test.Mux554.In0[23] connects to vpiHighConn test.Data_In[119].
+Port 2 bit 9 vpiLowConn test.Mux554.In0[22] connects to vpiHighConn test.Data_In[118].
+Port 2 bit 10 vpiLowConn test.Mux554.In0[21] connects to vpiHighConn test.Data_In[117].
+Port 2 bit 11 vpiLowConn test.Mux554.In0[20] connects to vpiHighConn test.Data_In[116].
+Port 2 bit 12 vpiLowConn test.Mux554.In0[19] connects to vpiHighConn test.Data_In[115].
+Port 2 bit 13 vpiLowConn test.Mux554.In0[18] connects to vpiHighConn test.Data_In[114].
+Port 2 bit 14 vpiLowConn test.Mux554.In0[17] connects to vpiHighConn test.Data_In[113].
+Port 2 bit 15 vpiLowConn test.Mux554.In0[16] connects to vpiHighConn test.Data_In[112].
+Port 2 bit 16 vpiLowConn test.Mux554.In0[15] connects to vpiHighConn test.Data_In[111].
+Port 2 bit 17 vpiLowConn test.Mux554.In0[14] connects to vpiHighConn test.Data_In[110].
+Port 2 bit 18 vpiLowConn test.Mux554.In0[13] connects to vpiHighConn test.Data_In[109].
+Port 2 bit 19 vpiLowConn test.Mux554.In0[12] connects to vpiHighConn test.Data_In[108].
+Port 2 bit 20 vpiLowConn test.Mux554.In0[11] connects to vpiHighConn test.Data_In[107].
+Port 2 bit 21 vpiLowConn test.Mux554.In0[10] connects to vpiHighConn test.Data_In[106].
+Port 2 bit 22 vpiLowConn test.Mux554.In0[9] connects to vpiHighConn test.Data_In[105].
+Port 2 bit 23 vpiLowConn test.Mux554.In0[8] connects to vpiHighConn test.Data_In[104].
+Port 2 bit 24 vpiLowConn test.Mux554.In0[7] connects to vpiHighConn test.Data_In[103].
+Port 2 bit 25 vpiLowConn test.Mux554.In0[6] connects to vpiHighConn test.Data_In[102].
+Port 2 bit 26 vpiLowConn test.Mux554.In0[5] connects to vpiHighConn test.Data_In[101].
+Port 2 bit 27 vpiLowConn test.Mux554.In0[4] connects to vpiHighConn test.Data_In[100].
+Port 2 bit 28 vpiLowConn test.Mux554.In0[3] connects to vpiHighConn test.Data_In[99].
+Port 2 bit 29 vpiLowConn test.Mux554.In0[2] connects to vpiHighConn test.Data_In[98].
+Port 2 bit 30 vpiLowConn test.Mux554.In0[1] connects to vpiHighConn test.Data_In[97].
+Port 2 bit 31 vpiLowConn test.Mux554.In0[0] connects to vpiHighConn test.Data_In[96].
+  Processing port test.Mux554.In1 (index 3):
+--WARN: port In1 (index 3) width 32 but connection width 1.
+Also port test.Mux554.In3 is a vpiPortInst.
+Also port test.Mux554.In2 is a vpiPortInst.
+Also port test.Mux554.In0 is a vpiPortInst.
+Port 3 bit 31 vpiLowConn test.Mux554.In1[0] connects to vpiHighConn test.Data_In[96].
+  Processing port test.Mux554.In2 (index 4):
+--WARN: port In2 (index 4) width 32 but connection width 1.
+Also port test.Mux554.In3 is a vpiPortInst.
+Also port test.Mux554.In1 is a vpiPortInst.
+Also port test.Mux554.In0 is a vpiPortInst.
+Port 4 bit 31 vpiLowConn test.Mux554.In2[0] connects to vpiHighConn test.Data_In[96].
+  Processing port test.Mux554.In3 (index 5):
+--WARN: port In3 (index 5) width 32 but connection width 1.
+Also port test.Mux554.In2 is a vpiPortInst.
+Also port test.Mux554.In1 is a vpiPortInst.
+Also port test.Mux554.In0 is a vpiPortInst.
+Port 5 bit 31 vpiLowConn test.Mux554.In3[0] connects to vpiHighConn test.Data_In[96].
+  Processing port test.Mux554.In4 (index 6):
+++INFORM: port In4 (index 6) connection not simple lvalue.
+  Processing port test.Mux554.In5 (index 7):
+++INFORM: port In5 (index 7) connection not simple lvalue.
+  Processing port test.Mux554.In6 (index 8):
+++INFORM: port In6 (index 8) connection not simple lvalue.
+  Processing port test.Mux554.In7 (index 9):
+++INFORM: port In7 (index 9) connection not simple lvalue.
+  Processing port test.Mux554.In8 (index 10):
+++INFORM: port In8 (index 10) connection not simple lvalue.
+  Processing port test.Mux554.In9 (index 11):
+++INFORM: port In9 (index 11) connection not simple lvalue.
+  Processing port test.Mux554.In10 (index 12):
+++INFORM: port In10 (index 12) connection not simple lvalue.
+  Processing port test.Mux554.In11 (index 13):
+++INFORM: port In11 (index 13) connection not simple lvalue.
+  Processing port test.Mux554.In12 (index 14):
+++INFORM: port In12 (index 14) connection not simple lvalue.
+  Processing port test.Mux554.In13 (index 15):
+++INFORM: port In13 (index 15) connection not simple lvalue.
+  Processing port test.Mux554.In14 (index 16):
+++INFORM: port In14 (index 16) connection not simple lvalue.
+  Processing port test.Mux554.In15 (index 17):
+++INFORM: port In15 (index 17) connection not simple lvalue.
+name of extra output file is [fff9].
+  >>> All instances processed - done - using Cver PLI only for checking.
diff --git a/tests_and_examples/examples.vpi/fff9.exp b/tests_and_examples/examples.vpi/fff9.exp
new file mode 100644
index 0000000..f1fb4fb
--- /dev/null
+++ b/tests_and_examples/examples.vpi/fff9.exp
@@ -0,0 +1,118 @@
+  There are 1 top level modules.
+  There are 1 instances in test.
+  Processing port test.Mux554.Select (index 0):
+Port 0 bit 0 vpiLowConn test.Mux554.Select[1] connects to vpiHighConn test.net_31[3].
+Port 0 bit 1 vpiLowConn test.Mux554.Select[0] connects to vpiHighConn test.net_31[2].
+  Processing port test.Mux554.Output (index 1):
+Port 1 bit 0 vpiLowConn test.Mux554.Output[31] connects to vpiHighConn test.net_44[31].
+Port 1 bit 1 vpiLowConn test.Mux554.Output[30] connects to vpiHighConn test.net_44[30].
+Port 1 bit 2 vpiLowConn test.Mux554.Output[29] connects to vpiHighConn test.net_44[29].
+Port 1 bit 3 vpiLowConn test.Mux554.Output[28] connects to vpiHighConn test.net_44[28].
+Port 1 bit 4 vpiLowConn test.Mux554.Output[27] connects to vpiHighConn test.net_44[27].
+Port 1 bit 5 vpiLowConn test.Mux554.Output[26] connects to vpiHighConn test.net_44[26].
+Port 1 bit 6 vpiLowConn test.Mux554.Output[25] connects to vpiHighConn test.net_44[25].
+Port 1 bit 7 vpiLowConn test.Mux554.Output[24] connects to vpiHighConn test.net_44[24].
+Port 1 bit 8 vpiLowConn test.Mux554.Output[23] connects to vpiHighConn test.net_44[23].
+Port 1 bit 9 vpiLowConn test.Mux554.Output[22] connects to vpiHighConn test.net_44[22].
+Port 1 bit 10 vpiLowConn test.Mux554.Output[21] connects to vpiHighConn test.net_44[21].
+Port 1 bit 11 vpiLowConn test.Mux554.Output[20] connects to vpiHighConn test.net_44[20].
+Port 1 bit 12 vpiLowConn test.Mux554.Output[19] connects to vpiHighConn test.net_44[19].
+Port 1 bit 13 vpiLowConn test.Mux554.Output[18] connects to vpiHighConn test.net_44[18].
+Port 1 bit 14 vpiLowConn test.Mux554.Output[17] connects to vpiHighConn test.net_44[17].
+Port 1 bit 15 vpiLowConn test.Mux554.Output[16] connects to vpiHighConn test.net_44[16].
+Port 1 bit 16 vpiLowConn test.Mux554.Output[15] connects to vpiHighConn test.net_44[15].
+Port 1 bit 17 vpiLowConn test.Mux554.Output[14] connects to vpiHighConn test.net_44[14].
+Port 1 bit 18 vpiLowConn test.Mux554.Output[13] connects to vpiHighConn test.net_44[13].
+Port 1 bit 19 vpiLowConn test.Mux554.Output[12] connects to vpiHighConn test.net_44[12].
+Port 1 bit 20 vpiLowConn test.Mux554.Output[11] connects to vpiHighConn test.net_44[11].
+Port 1 bit 21 vpiLowConn test.Mux554.Output[10] connects to vpiHighConn test.net_44[10].
+Port 1 bit 22 vpiLowConn test.Mux554.Output[9] connects to vpiHighConn test.net_44[9].
+Port 1 bit 23 vpiLowConn test.Mux554.Output[8] connects to vpiHighConn test.net_44[8].
+Port 1 bit 24 vpiLowConn test.Mux554.Output[7] connects to vpiHighConn test.net_44[7].
+Port 1 bit 25 vpiLowConn test.Mux554.Output[6] connects to vpiHighConn test.net_44[6].
+Port 1 bit 26 vpiLowConn test.Mux554.Output[5] connects to vpiHighConn test.net_44[5].
+Port 1 bit 27 vpiLowConn test.Mux554.Output[4] connects to vpiHighConn test.net_44[4].
+Port 1 bit 28 vpiLowConn test.Mux554.Output[3] connects to vpiHighConn test.net_44[3].
+Port 1 bit 29 vpiLowConn test.Mux554.Output[2] connects to vpiHighConn test.net_44[2].
+Port 1 bit 30 vpiLowConn test.Mux554.Output[1] connects to vpiHighConn test.net_44[1].
+Port 1 bit 31 vpiLowConn test.Mux554.Output[0] connects to vpiHighConn test.net_44[0].
+  Processing port test.Mux554.In0 (index 2):
+Also port test.Mux554.In3 is a vpiPortInst.
+Also port test.Mux554.In2 is a vpiPortInst.
+Also port test.Mux554.In1 is a vpiPortInst.
+Port 2 bit 0 vpiLowConn test.Mux554.In0[31] connects to vpiHighConn test.Data_In[127].
+Port 2 bit 1 vpiLowConn test.Mux554.In0[30] connects to vpiHighConn test.Data_In[126].
+Port 2 bit 2 vpiLowConn test.Mux554.In0[29] connects to vpiHighConn test.Data_In[125].
+Port 2 bit 3 vpiLowConn test.Mux554.In0[28] connects to vpiHighConn test.Data_In[124].
+Port 2 bit 4 vpiLowConn test.Mux554.In0[27] connects to vpiHighConn test.Data_In[123].
+Port 2 bit 5 vpiLowConn test.Mux554.In0[26] connects to vpiHighConn test.Data_In[122].
+Port 2 bit 6 vpiLowConn test.Mux554.In0[25] connects to vpiHighConn test.Data_In[121].
+Port 2 bit 7 vpiLowConn test.Mux554.In0[24] connects to vpiHighConn test.Data_In[120].
+Port 2 bit 8 vpiLowConn test.Mux554.In0[23] connects to vpiHighConn test.Data_In[119].
+Port 2 bit 9 vpiLowConn test.Mux554.In0[22] connects to vpiHighConn test.Data_In[118].
+Port 2 bit 10 vpiLowConn test.Mux554.In0[21] connects to vpiHighConn test.Data_In[117].
+Port 2 bit 11 vpiLowConn test.Mux554.In0[20] connects to vpiHighConn test.Data_In[116].
+Port 2 bit 12 vpiLowConn test.Mux554.In0[19] connects to vpiHighConn test.Data_In[115].
+Port 2 bit 13 vpiLowConn test.Mux554.In0[18] connects to vpiHighConn test.Data_In[114].
+Port 2 bit 14 vpiLowConn test.Mux554.In0[17] connects to vpiHighConn test.Data_In[113].
+Port 2 bit 15 vpiLowConn test.Mux554.In0[16] connects to vpiHighConn test.Data_In[112].
+Port 2 bit 16 vpiLowConn test.Mux554.In0[15] connects to vpiHighConn test.Data_In[111].
+Port 2 bit 17 vpiLowConn test.Mux554.In0[14] connects to vpiHighConn test.Data_In[110].
+Port 2 bit 18 vpiLowConn test.Mux554.In0[13] connects to vpiHighConn test.Data_In[109].
+Port 2 bit 19 vpiLowConn test.Mux554.In0[12] connects to vpiHighConn test.Data_In[108].
+Port 2 bit 20 vpiLowConn test.Mux554.In0[11] connects to vpiHighConn test.Data_In[107].
+Port 2 bit 21 vpiLowConn test.Mux554.In0[10] connects to vpiHighConn test.Data_In[106].
+Port 2 bit 22 vpiLowConn test.Mux554.In0[9] connects to vpiHighConn test.Data_In[105].
+Port 2 bit 23 vpiLowConn test.Mux554.In0[8] connects to vpiHighConn test.Data_In[104].
+Port 2 bit 24 vpiLowConn test.Mux554.In0[7] connects to vpiHighConn test.Data_In[103].
+Port 2 bit 25 vpiLowConn test.Mux554.In0[6] connects to vpiHighConn test.Data_In[102].
+Port 2 bit 26 vpiLowConn test.Mux554.In0[5] connects to vpiHighConn test.Data_In[101].
+Port 2 bit 27 vpiLowConn test.Mux554.In0[4] connects to vpiHighConn test.Data_In[100].
+Port 2 bit 28 vpiLowConn test.Mux554.In0[3] connects to vpiHighConn test.Data_In[99].
+Port 2 bit 29 vpiLowConn test.Mux554.In0[2] connects to vpiHighConn test.Data_In[98].
+Port 2 bit 30 vpiLowConn test.Mux554.In0[1] connects to vpiHighConn test.Data_In[97].
+Port 2 bit 31 vpiLowConn test.Mux554.In0[0] connects to vpiHighConn test.Data_In[96].
+  Processing port test.Mux554.In1 (index 3):
+--WARN: port In1 (index 3) width 32 but connection width 1.
+Also port test.Mux554.In3 is a vpiPortInst.
+Also port test.Mux554.In2 is a vpiPortInst.
+Also port test.Mux554.In0 is a vpiPortInst.
+Port 3 bit 31 vpiLowConn test.Mux554.In1[0] connects to vpiHighConn test.Data_In[96].
+  Processing port test.Mux554.In2 (index 4):
+--WARN: port In2 (index 4) width 32 but connection width 1.
+Also port test.Mux554.In3 is a vpiPortInst.
+Also port test.Mux554.In1 is a vpiPortInst.
+Also port test.Mux554.In0 is a vpiPortInst.
+Port 4 bit 31 vpiLowConn test.Mux554.In2[0] connects to vpiHighConn test.Data_In[96].
+  Processing port test.Mux554.In3 (index 5):
+--WARN: port In3 (index 5) width 32 but connection width 1.
+Also port test.Mux554.In2 is a vpiPortInst.
+Also port test.Mux554.In1 is a vpiPortInst.
+Also port test.Mux554.In0 is a vpiPortInst.
+Port 5 bit 31 vpiLowConn test.Mux554.In3[0] connects to vpiHighConn test.Data_In[96].
+  Processing port test.Mux554.In4 (index 6):
+++INFORM: port In4 (index 6) connection not simple lvalue.
+  Processing port test.Mux554.In5 (index 7):
+++INFORM: port In5 (index 7) connection not simple lvalue.
+  Processing port test.Mux554.In6 (index 8):
+++INFORM: port In6 (index 8) connection not simple lvalue.
+  Processing port test.Mux554.In7 (index 9):
+++INFORM: port In7 (index 9) connection not simple lvalue.
+  Processing port test.Mux554.In8 (index 10):
+++INFORM: port In8 (index 10) connection not simple lvalue.
+  Processing port test.Mux554.In9 (index 11):
+++INFORM: port In9 (index 11) connection not simple lvalue.
+  Processing port test.Mux554.In10 (index 12):
+++INFORM: port In10 (index 12) connection not simple lvalue.
+  Processing port test.Mux554.In11 (index 13):
+++INFORM: port In11 (index 13) connection not simple lvalue.
+  Processing port test.Mux554.In12 (index 14):
+++INFORM: port In12 (index 14) connection not simple lvalue.
+  Processing port test.Mux554.In13 (index 15):
+++INFORM: port In13 (index 15) connection not simple lvalue.
+  Processing port test.Mux554.In14 (index 16):
+++INFORM: port In14 (index 16) connection not simple lvalue.
+  Processing port test.Mux554.In15 (index 17):
+++INFORM: port In15 (index 17) connection not simple lvalue.
+name of extra output file is [fff9].
+  >>> All instances processed - done - using Cver PLI only for checking.
diff --git a/tests_and_examples/examples.vpi/findcaus.c b/tests_and_examples/examples.vpi/findcaus.c
new file mode 100644
index 0000000..fe70976
--- /dev/null
+++ b/tests_and_examples/examples.vpi/findcaus.c
@@ -0,0 +1,201 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+/*
+ * example to find cause statements only in top module initial/always 
+ *
+ * real program would descend to all instances to find all modules
+ * and keep track of seen module types to not repeat search
+ */
+
+#include <stdio.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+#include <string.h>
+
+static int num_causes;
+
+/* local prototypes */
+static void blk_findcaus(vpiHandle);
+static void blk_findcaus(vpiHandle);
+
+/* global prototypes */
+extern int findcaus(struct t_cb_data *);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb(void);
+
+int findcaus(struct t_cb_data *cbp)
+{
+ int iatyp, sttyp, isiz;
+ vpiHandle href, href2, href3;
+ vpiHandle modiref, ia_iref;
+
+ /* build the iterator for each module */
+ modiref = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, modiref);
+ vpi_printf("module iterator has size %d.\n", isiz);
+ 
+ for (num_causes = 0;;)
+  {
+   if ((href = vpi_scan(modiref)) == NULL) break;
+   vpi_printf("... processing instance %s\n", vpi_get_str(vpiFullName, href));
+   
+   /* build the initial/always process iterator */
+   ia_iref = vpi_iterate(vpiProcess, href);
+   isiz = vpi_get(vpiSize, ia_iref);
+   vpi_printf("init/always iterator has size %d.\n", isiz);
+   for (;;)
+    {
+     if ((href2 = vpi_scan(ia_iref)) == NULL) break;
+     iatyp = vpi_get(vpiType, href2);
+     if (iatyp == vpiInitial) vpi_printf("... processing initial\n");
+     else if (iatyp == vpiAlways) vpi_printf("...processing always\n");
+     else vpi_printf("... expected initial/always not found");
+
+     href3 = vpi_handle(vpiStmt, href2); 
+     sttyp = vpi_get(vpiType, href3);
+     vpi_printf("... processing %d type.\n", sttyp);
+     switch (sttyp) { 
+      case vpiEventStmt: num_causes++; break;  
+      case vpiBegin: case vpiFork: case vpiNamedBegin: case vpiNamedFork:  
+       blk_findcaus(href3);
+       break;
+      default: ; /* anything else just ignored */
+     }
+    }
+  }
+ vpi_printf("There were %d total cause statements in top modules.\n",
+  num_causes);
+ return(0);
+}
+
+/*
+ * find causes in blocks (maybe named and can be nested)
+ */
+static void blk_findcaus(vpiHandle blkhref)
+{
+ int sttyp, isiz;
+ vpiHandle ihref, href;
+
+ /* build the list of statements in block iterator */
+ ihref = vpi_iterate(vpiStmt, blkhref);
+ isiz = vpi_get(vpiSize, ihref);
+ vpi_printf("block stmt iterator has size %d.\n", isiz);
+ for (;;)
+  {
+   if ((href = vpi_scan(ihref)) == NULL) break;
+   sttyp = vpi_get(vpiType, href);
+   vpi_printf("... processing %d type.\n", sttyp);
+   switch (sttyp) { 
+    case vpiEventStmt: num_causes++; break;  
+    case vpiBegin: case vpiFork: case vpiNamedBegin: case vpiNamedFork:  
+     blk_findcaus(href);
+     break;
+    default: ; /* anything else just ignored */
+   }
+  }
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("%s: %s error (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not saved (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+ struct t_cb_data cbrec, cbrec2;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf(
+   "**ERR: $hello PLI 2.0 task cannot register end of compile check routine");
+
+ cbp = &cbrec2;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = findcaus;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: $hello PLI 2.0 task cannot register end of compile check routine");
+ /* if not registered will be no call backs */
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/findcaus.plg b/tests_and_examples/examples.vpi/findcaus.plg
new file mode 100644
index 0000000..4321de6
--- /dev/null
+++ b/tests_and_examples/examples.vpi/findcaus.plg
@@ -0,0 +1,45 @@
+module iterator has size 1.
+... processing instance task10
+init/always iterator has size 4.
+... processing initial
+... processing 3 type.
+... processing initial
+... processing 4 type.
+block stmt iterator has size 18.
+... processing 3 type.
+... processing 11 type.
+... processing 3 type.
+... processing 3 type.
+... processing 3 type.
+... processing 3 type.
+... processing 57 type.
+... processing 60 type.
+... processing 57 type.
+... processing 3 type.
+... processing 3 type.
+... processing 14 type.
+... processing 60 type.
+... processing 57 type.
+... processing 3 type.
+... processing 3 type.
+... processing 60 type.
+... processing 57 type.
+... processing initial
+... processing 4 type.
+block stmt iterator has size 2.
+... processing 13 type.
+... processing 11 type.
+...processing always
+... processing 4 type.
+block stmt iterator has size 1.
+... processing 13 type.
+There were 1 total cause statements in top modules.
+        10 start   x: ffffffff  y: 1  count: 0
+        10 t1 started
+        30 t1 finished
+        30 return  x: 00000000  y: 0  count: 1
+        30 t1 started
+        35 return  x: 00000000  y: 0  count: 1
+        35 t1 started
+        55 t1 finished
+        55 return  x: 00000002  y: 0  count: 2
diff --git a/tests_and_examples/examples.vpi/inst_pli.osx.sh b/tests_and_examples/examples.vpi/inst_pli.osx.sh
new file mode 100755
index 0000000..fa81ba0
--- /dev/null
+++ b/tests_and_examples/examples.vpi/inst_pli.osx.sh
@@ -0,0 +1,149 @@
+#!/bin/sh 
+# install test procedures
+
+OS=OSX
+CVER=../../bin/cver
+
+if test ! -f ../../bin/cver 
+then
+  echo "ERROR - there is no cver in ../../bin/"
+  echo "Must make in src/ directory" 
+  exit;
+fi
+
+make -f makefile.$OS async.dylib
+$CVER -q +loadvpi=./async:vpi_compat_bootstrap async.v >/dev/null
+./rmlic.pl
+diff verilog.log async.plg
+rm async.dylib async.o
+
+make -f makefile.$OS vhello1.dylib
+$CVER -q +loadvpi=./vhello1:vpi_compat_bootstrap vhello1.v >/dev/null
+./rmlic.pl
+diff verilog.log vhello1.plg
+rm vhello1.dylib vhello1.o
+
+make -f makefile.$OS vhello2.dylib
+$CVER -q +loadvpi=./vhello2:vpi_compat_bootstrap vhello2.v >/dev/null
+./rmlic.pl
+diff verilog.log vhello2.plg
+rm vhello2.dylib vhello2.o
+
+make -f makefile.$OS vhelbad.dylib
+$CVER -q +loadvpi=./vhelbad:vpi_compat_bootstrap vhelbad.v >/dev/null
+./rmlic.pl
+diff verilog.log vhelbad.plg
+rm vhelbad.dylib vhelbad.o
+
+make -f makefile.$OS findcaus.dylib
+$CVER -q +loadvpi=./findcaus:vpi_compat_bootstrap task10.v >/dev/null
+./rmlic.pl
+diff verilog.log findcaus.plg
+rm findcaus.dylib findcaus.o
+
+make -f makefile.$OS vacbtst.dylib
+$CVER -q +loadvpi=./vacbtst:vpi_compat_bootstrap -s -i vacbtst.inp task10.v >/dev/null
+./rmlic.pl
+diff verilog.log vacbtst.plg
+rm vacbtst.dylib vacbtst.o
+
+make -f makefile.$OS vprtchg.dylib
+$CVER -q +loadvpi=./vprtchg:vpi_compat_bootstrap  task10.v >/dev/null
+./rmlic.pl
+diff verilog.log vprtchg.plg
+rm vprtchg.dylib vprtchg.o 
+
+make -f makefile.$OS vprtchg2.dylib
+$CVER -q +loadvpi=./vprtchg2:vpi_compat_bootstrap task10.v >/dev/null
+./rmlic.pl
+diff verilog.log vprtchg2.plg
+rm vprtchg2.dylib vprtchg2.o
+
+make -f makefile.$OS vprtchg3.dylib
+$CVER -q +loadvpi=./vprtchg3:vpi_compat_bootstrap task10.v >/dev/null
+./rmlic.pl
+diff verilog.log vprtchg3.plg
+rm vprtchg3.dylib vprtchg3.o
+
+make -f makefile.$OS vprtdels.dylib
+$CVER -q +loadvpi=./vprtdels:vpi_compat_bootstrap fdspec01.v >/dev/null
+./rmlic.pl
+diff verilog.log vprtdels.plg
+rm vprtdels.dylib vprtdels.o
+
+make -f makefile.$OS vprtdel2.dylib
+$CVER -q +loadvpi=./vprtdel2:vpi_compat_bootstrap timtst03.v >/dev/null
+./rmlic.pl
+diff verilog.log vprtdel2.plg
+rm vprtdel2.dylib vprtdel2.o
+
+make -f makefile.$OS vsetdels.dylib
+$CVER -q +loadvpi=./vsetdels:vpi_compat_bootstrap fdspec01.v >/dev/null
+./rmlic.pl
+diff verilog.log vsetdels.plg
+rm vsetdels.dylib vsetdels.o
+
+make -f makefile.$OS vsetval1.dylib
+$CVER -q +loadvpi=./vsetval1:vpi_compat_bootstrap vsetval1.v >/dev/null
+./rmlic.pl
+diff verilog.log vsetval1.plg
+rm vsetval1.dylib vsetval1.o 
+
+make -f makefile.$OS vsetval2.dylib
+$CVER -q +loadvpi=./vsetval2:vpi_compat_bootstrap vsetval2.v >/dev/null
+./rmlic.pl
+diff verilog.log vsetval2.plg
+rm vsetval2.dylib vsetval2.o
+
+make -f makefile.$OS vtimcbs.dylib
+$CVER -q +loadvpi=./vtimcbs:vpi_compat_bootstrap task10.v >/dev/null
+./rmlic.pl
+diff verilog.log vtimcbs.plg
+rm vtimcbs.dylib vtimcbs.o 
+
+make -f makefile.$OS vfopen1.dylib
+$CVER -q +loadvpi=./vfopen1:vpi_compat_bootstrap vfopen1.v >/dev/null
+./rmlic.pl
+diff verilog.log vfopen1.plg
+diff vpifout.fil vpifout.xfl
+rm vfopen1.dylib vfopen1.o
+
+make -f makefile.$OS vfopen2.dylib
+$CVER -q +loadvpi=./vfopen2:vpi_compat_bootstrap vfopen2.v >/dev/null
+./rmlic.pl
+diff verilog.log vfopen2.plg
+diff vpitout.fil vpitout.xfl
+rm vfopen2.dylib vfopen2.o
+
+make -f makefile.$OS vconta1.dylib
+$CVER -q +loadvpi=./vconta1:vpi_compat_bootstrap cacatmd1.v >/dev/null
+./rmlic.pl
+diff verilog.log vconta1.plg
+rm vconta1.dylib vconta1.o
+
+make -f makefile.$OS vchkprt1.dylib
+$CVER -q +loadvpi=./vchkprt1:vpi_compat_bootstrap prtbg09.v >/dev/null
+# cannot compare verilog.log because has vpi_get_vlog_info
+diff fff9 fff9.exp
+rm vchkprt1.dylib vchkprt1.o
+
+make -f makefile.$OS vdrvld1.dylib
+$CVER -q +loadvpi=./vdrvld1:vpi_compat_bootstrap fdspec01.v >/dev/null
+./rmlic.pl
+diff verilog.log vdrvld1.plg
+rm vdrvld1.dylib vdrvld1.o
+
+make -f makefile.$OS vdrvld2.dylib
+$CVER -q +loadvpi=./vdrvld2:vpi_compat_bootstrap cacatmd1.v >/dev/null
+./rmlic.pl
+diff verilog.log vdrvld2.plg
+rm vdrvld2.dylib vdrvld2.o
+
+make -f makefile.$OS dfpsetd.dylib
+$CVER -q +loadvpi=./dfpsetd:vpi_compat_bootstrap dfpsetd.v >/dev/null
+./rmlic.pl
+diff verilog.log dfpsetd.plg
+rm dfpsetd.dylib dfpsetd.o
+
+echo ">>>> PLI 2.0 OSX Install test Finished - no diff differences should be printed."
+echo " "
diff --git a/tests_and_examples/examples.vpi/inst_pli.sh b/tests_and_examples/examples.vpi/inst_pli.sh
new file mode 100755
index 0000000..0310e0d
--- /dev/null
+++ b/tests_and_examples/examples.vpi/inst_pli.sh
@@ -0,0 +1,160 @@
+#!/bin/sh 
+# install test procedures
+
+# set $1 to your OS
+OS=$1 
+CVER=../../bin/cver
+
+if test ! -f ../../bin/cver 
+then
+  echo "ERROR - there is no cver in ../../bin/"
+  echo "Must make in src/ directory" 
+  exit;
+fi
+
+
+if [ "$OS" != "lnx" ]
+ then
+  if [ "$OS" != "sparc-gcc" ]
+   then
+      echo "must specify an OS(lnx, sparc-gcc) on command line" 
+      exit;
+  fi
+fi
+
+make -f makefile.$OS async.so
+$CVER -q +loadvpi=./async:vpi_compat_bootstrap async.v >/dev/null
+./rmlic.pl
+diff verilog.log async.plg
+rm async.so async.o
+
+make -f makefile.$OS vhello1.so
+$CVER -q +loadvpi=./vhello1:vpi_compat_bootstrap vhello1.v >/dev/null
+./rmlic.pl
+diff verilog.log vhello1.plg
+rm vhello1.so vhello1.o
+
+make -f makefile.$OS vhello2.so
+$CVER -q +loadvpi=./vhello2:vpi_compat_bootstrap vhello2.v >/dev/null
+./rmlic.pl
+diff verilog.log vhello2.plg
+rm vhello2.so vhello2.o
+
+make -f makefile.$OS vhelbad.so
+$CVER -q +loadvpi=./vhelbad:vpi_compat_bootstrap vhelbad.v >/dev/null
+./rmlic.pl
+diff verilog.log vhelbad.plg
+rm vhelbad.so vhelbad.o
+
+make -f makefile.$OS findcaus.so
+$CVER -q +loadvpi=./findcaus:vpi_compat_bootstrap task10.v >/dev/null
+./rmlic.pl
+diff verilog.log findcaus.plg
+rm findcaus.so findcaus.o
+
+make -f makefile.$OS vacbtst.so
+$CVER -q +loadvpi=./vacbtst:vpi_compat_bootstrap -s -i vacbtst.inp task10.v >/dev/null
+./rmlic.pl
+diff verilog.log vacbtst.plg
+rm vacbtst.so vacbtst.o
+
+make -f makefile.$OS vprtchg.so
+$CVER -q +loadvpi=./vprtchg:vpi_compat_bootstrap  task10.v >/dev/null
+./rmlic.pl
+diff verilog.log vprtchg.plg
+rm vprtchg.so vprtchg.o 
+
+make -f makefile.$OS vprtchg2.so
+$CVER -q +loadvpi=./vprtchg2:vpi_compat_bootstrap task10.v >/dev/null
+./rmlic.pl
+diff verilog.log vprtchg2.plg
+rm vprtchg2.so vprtchg2.o
+
+make -f makefile.$OS vprtchg3.so
+$CVER -q +loadvpi=./vprtchg3:vpi_compat_bootstrap task10.v >/dev/null
+./rmlic.pl
+diff verilog.log vprtchg3.plg
+rm vprtchg3.so vprtchg3.o
+
+make -f makefile.$OS vprtdels.so
+$CVER -q +loadvpi=./vprtdels:vpi_compat_bootstrap fdspec01.v >/dev/null
+./rmlic.pl
+diff verilog.log vprtdels.plg
+rm vprtdels.so vprtdels.o
+
+make -f makefile.$OS vprtdel2.so
+$CVER -q +loadvpi=./vprtdel2:vpi_compat_bootstrap timtst03.v >/dev/null
+./rmlic.pl
+diff verilog.log vprtdel2.plg
+rm vprtdel2.so vprtdel2.o
+
+make -f makefile.$OS vsetdels.so
+$CVER -q +loadvpi=./vsetdels:vpi_compat_bootstrap fdspec01.v >/dev/null
+./rmlic.pl
+diff verilog.log vsetdels.plg
+rm vsetdels.so vsetdels.o
+
+make -f makefile.$OS vsetval1.so
+$CVER -q +loadvpi=./vsetval1:vpi_compat_bootstrap vsetval1.v >/dev/null
+./rmlic.pl
+diff verilog.log vsetval1.plg
+rm vsetval1.so vsetval1.o 
+
+make -f makefile.$OS vsetval2.so
+$CVER -q +loadvpi=./vsetval2:vpi_compat_bootstrap vsetval2.v >/dev/null
+./rmlic.pl
+diff verilog.log vsetval2.plg
+rm vsetval2.so vsetval2.o
+
+make -f makefile.$OS vtimcbs.so
+$CVER -q +loadvpi=./vtimcbs:vpi_compat_bootstrap task10.v >/dev/null
+./rmlic.pl
+diff verilog.log vtimcbs.plg
+rm vtimcbs.so vtimcbs.o 
+
+make -f makefile.$OS vfopen1.so
+$CVER -q +loadvpi=./vfopen1:vpi_compat_bootstrap vfopen1.v >/dev/null
+./rmlic.pl
+diff verilog.log vfopen1.plg
+diff vpifout.fil vpifout.xfl
+rm vfopen1.so vfopen1.o
+
+make -f makefile.$OS vfopen2.so
+$CVER -q +loadvpi=./vfopen2:vpi_compat_bootstrap vfopen2.v >/dev/null
+./rmlic.pl
+diff verilog.log vfopen2.plg
+diff vpitout.fil vpitout.xfl
+rm vfopen2.so vfopen2.o
+
+make -f makefile.$OS vconta1.so
+$CVER -q +loadvpi=./vconta1:vpi_compat_bootstrap cacatmd1.v >/dev/null
+./rmlic.pl
+diff verilog.log vconta1.plg
+rm vconta1.so vconta1.o
+
+make -f makefile.$OS vchkprt1.so
+$CVER -q +loadvpi=./vchkprt1:vpi_compat_bootstrap prtbg09.v >/dev/null
+# cannot compare verilog.log because has vpi_get_vlog_info
+diff fff9 fff9.exp
+rm vchkprt1.so vchkprt1.o
+
+make -f makefile.$OS vdrvld1.so
+$CVER -q +loadvpi=./vdrvld1:vpi_compat_bootstrap fdspec01.v >/dev/null
+./rmlic.pl
+diff verilog.log vdrvld1.plg
+rm vdrvld1.so vdrvld1.o
+
+make -f makefile.$OS vdrvld2.so
+$CVER -q +loadvpi=./vdrvld2:vpi_compat_bootstrap cacatmd1.v >/dev/null
+./rmlic.pl
+diff verilog.log vdrvld2.plg
+rm vdrvld2.so vdrvld2.o
+
+make -f makefile.$OS dfpsetd.so
+$CVER -q +loadvpi=./dfpsetd:vpi_compat_bootstrap dfpsetd.v >/dev/null
+./rmlic.pl
+diff verilog.log dfpsetd.plg
+rm dfpsetd.so dfpsetd.o
+
+echo ">>>> PLI 2.0 Install test Finished - no diff differences should be printed."
+echo " "
diff --git a/tests_and_examples/examples.vpi/makefile.cygwin b/tests_and_examples/examples.vpi/makefile.cygwin
new file mode 100644
index 0000000..7558263
--- /dev/null
+++ b/tests_and_examples/examples.vpi/makefile.cygwin
@@ -0,0 +1,22 @@
+# Make file for creating a vfopen1 VPI PLI function DLL
+#
+
+SHELL=/bin/bash
+
+CC=gcc
+CVER=../../objs/cver
+
+DLLSRCS=vfopen1.c
+DLLOBJS=vfopen1.o
+VSRCS=vfopen1.v
+
+dll: $(DLLOBJS)
+	$(CC) -shared -o libvfopen1.dll -Wl,--out-implib=libvfopen1.dll.a \
+		-Wl,--export-all -Wl,--enable-auto-image-base \
+		-Wl,--export-dynamic -Wl,--output-def=libvfopen1.def $(DLLOBJS) -lcver
+
+run: libvfopen1.dll
+	$(CVER) -q +loadvpi=./libvfopen1.dll:vpi_compat_bootstrap $(VSRCS)
+
+.c.o: $(DLLSRCS)
+	$(CC) -c -I./ -I../../pli_incs $<
diff --git a/tests_and_examples/examples.vpi/makefile.lnx b/tests_and_examples/examples.vpi/makefile.lnx
new file mode 100644
index 0000000..c305c5d
--- /dev/null
+++ b/tests_and_examples/examples.vpi/makefile.lnx
@@ -0,0 +1,144 @@
+# could add to CFLAGS to turn on warnings if you are using gcc
+WARNS=-Wall
+
+# change path if not running test from installed directory location
+INCS=-I../../pli_incs
+# maybe want -O<something> and/or -g
+CFLAGS= -fPIC -Wall -g $(INCS)
+LFLAGS= -G -shared -export-dynamic
+
+# change to your compiler
+CC=gcc
+
+async.o:	async.c 
+	$(CC) $(CFLAGS) -c async.c
+ 
+vhello1.o:	vhello1.c 
+	$(CC) $(CFLAGS) -c vhello1.c
+
+vhello2.o:	vhello2.c 
+	$(CC) $(CFLAGS) -c vhello2.c
+
+vhelbad.o:	vhelbad.c 
+	$(CC) $(CFLAGS) -c vhelbad.c
+
+findcaus.o:	findcaus.c 
+	$(CC) $(CFLAGS) -c findcaus.c
+
+vacbtst.o:	vacbtst.c 
+	$(CC) $(CFLAGS) -c vacbtst.c
+
+vprtchg.o:	vprtchg.c 
+	$(CC) $(CFLAGS) -c vprtchg.c
+
+vprtchg2.o:	vprtchg2.c 
+	$(CC) $(CFLAGS) -c vprtchg2.c
+
+vprtchg3.o:	vprtchg3.c 
+	$(CC) $(CFLAGS) -c vprtchg3.c
+
+vprtdels.o:	vprtdels.c 
+	$(CC) $(CFLAGS) -c vprtdels.c
+
+vprtdel2.o:	vprtdel2.c 
+	$(CC) $(CFLAGS) -c vprtdel2.c
+
+vsetdels.o:	vsetdels.c 
+	$(CC) $(CFLAGS) -c vsetdels.c
+
+vsetval1.o:	vsetval1.c 
+	$(CC) $(CFLAGS) -c vsetval1.c
+
+vsetval2.o:	vsetval2.c 
+	$(CC) $(CFLAGS) -c vsetval2.c
+
+vtimcbs.o:	vtimcbs.c 
+	$(CC) $(CFLAGS) -c vtimcbs.c
+
+vfopen1.o:	vfopen1.c 
+	$(CC) $(CFLAGS) -c vfopen1.c
+
+vfopen2.o:	vfopen2.c 
+	$(CC) $(CFLAGS) -c vfopen2.c
+
+vconta1.o:	vconta1.c 
+	$(CC) $(CFLAGS) -c vconta1.c
+
+vchkprt1.o:	vchkprt1.c 
+	$(CC) $(CFLAGS) -c vchkprt1.c
+
+vdrvld1.o:	vdrvld1.c 
+	$(CC) $(CFLAGS) -c vdrvld1.c
+
+vdrvld2.o:	vdrvld2.c 
+	$(CC) $(CFLAGS) -c vdrvld2.c
+
+dfpsetd.o:	dfpsetd.c
+	$(CC) $(CFLAGS) -c dfpsetd.c
+
+# make rules for dynamic libaries
+async.so:	async.o
+	$(LD) $(LFLAGS) async.o -o async.so
+
+vhello1.so:	vhello1.o
+	$(LD) $(LFLAGS) vhello1.o -o vhello1.so
+
+vhello2.so:	vhello2.o
+	$(LD) $(LFLAGS) vhello2.o -o vhello2.so
+
+vhelbad.so:	vhelbad.o
+	$(LD) $(LFLAGS) vhelbad.o -o vhelbad.so
+
+findcaus.so:	findcaus.o
+	$(LD) $(LFLAGS) findcaus.o -o findcaus.so
+
+vacbtst.so:	vacbtst.o
+	$(LD) $(LFLAGS) vacbtst.o -o vacbtst.so
+
+vprtchg.so:	vprtchg.o
+	$(LD) $(LFLAGS) vprtchg.o -o vprtchg.so
+
+vprtchg2.so:	vprtchg2.o
+	$(LD) $(LFLAGS) vprtchg2.o -o vprtchg2.so
+
+vprtchg3.so:	vprtchg3.o
+	$(LD) $(LFLAGS) vprtchg3.o -o vprtchg3.so
+
+vprtdels.so:	vprtdels.o
+	$(LD) $(LFLAGS) vprtdels.o -o vprtdels.so
+
+vprtdel2.so:	vprtdel2.o
+	$(LD) $(LFLAGS) vprtdel2.o -o vprtdel2.so
+
+vsetdels.so:	vsetdels.o
+	$(LD) $(LFLAGS) vsetdels.o -o vsetdels.so
+
+vsetval1.so:	vsetval1.o
+	$(LD) $(LFLAGS) vsetval1.o -o vsetval1.so
+
+vsetval2.so:	vsetval2.o
+	$(LD) $(LFLAGS) vsetval2.o -o vsetval2.so
+
+vtimcbs.so:	vtimcbs.o
+	$(LD) $(LFLAGS) vtimcbs.o -o vtimcbs.so
+
+vfopen1.so:	vfopen1.o
+	$(LD) $(LFLAGS) vfopen1.o -o vfopen1.so
+
+vfopen2.so:	vfopen2.o
+	$(LD) $(LFLAGS) vfopen2.o -o vfopen2.so
+
+vconta1.so:	vconta1.o
+	$(LD) $(LFLAGS) vconta1.o -o vconta1.so
+
+vchkprt1.so:	vchkprt1.o
+	$(LD) $(LFLAGS) vchkprt1.o -o vchkprt1.so
+
+vdrvld1.so:	vdrvld1.o
+	$(LD) $(LFLAGS) vdrvld1.o -o vdrvld1.so
+
+vdrvld2.so:	vdrvld2.o
+	$(LD) $(LFLAGS) vdrvld2.o -o vdrvld2.so
+
+dfpsetd.so:	dfpsetd.o
+	$(LD) $(LFLAGS) dfpsetd.o -o dfpsetd.so
diff --git a/tests_and_examples/examples.vpi/makefile.osx b/tests_and_examples/examples.vpi/makefile.osx
new file mode 100644
index 0000000..868efc2
--- /dev/null
+++ b/tests_and_examples/examples.vpi/makefile.osx
@@ -0,0 +1,144 @@
+# could add to CFLAGS to turn on warnings if you are using gcc
+WARNS=-Wall
+
+# change path if not running test from installed directory location
+INCS=-I../../pli_incs
+# you must use exactly these flags for OSX
+CFLAGS= -fPIC  -Wall $(INCS) -dynamic -fno-common 
+LFLAGS= -flat_namespace -bundle -undefined suppress
+
+# change to your compiler
+# CC=gcc
+
+async.o:	async.c 
+	$(CC) $(CFLAGS) -c async.c
+ 
+vhello1.o:	vhello1.c 
+	$(CC) $(CFLAGS) -c vhello1.c
+
+vhello2.o:	vhello2.c 
+	$(CC) $(CFLAGS) -c vhello2.c
+
+vhelbad.o:	vhelbad.c 
+	$(CC) $(CFLAGS) -c vhelbad.c
+
+findcaus.o:	findcaus.c 
+	$(CC) $(CFLAGS) -c findcaus.c
+
+vacbtst.o:	vacbtst.c 
+	$(CC) $(CFLAGS) -c vacbtst.c
+
+vprtchg.o:	vprtchg.c 
+	$(CC) $(CFLAGS) -c vprtchg.c
+
+vprtchg2.o:	vprtchg2.c 
+	$(CC) $(CFLAGS) -c vprtchg2.c
+
+vprtchg3.o:	vprtchg3.c 
+	$(CC) $(CFLAGS) -c vprtchg3.c
+
+vprtdels.o:	vprtdels.c 
+	$(CC) $(CFLAGS) -c vprtdels.c
+
+vprtdel2.o:	vprtdel2.c 
+	$(CC) $(CFLAGS) -c vprtdel2.c
+
+vsetdels.o:	vsetdels.c 
+	$(CC) $(CFLAGS) -c vsetdels.c
+
+vsetval1.o:	vsetval1.c 
+	$(CC) $(CFLAGS) -c vsetval1.c
+
+vsetval2.o:	vsetval2.c 
+	$(CC) $(CFLAGS) -c vsetval2.c
+
+vtimcbs.o:	vtimcbs.c 
+	$(CC) $(CFLAGS) -c vtimcbs.c
+
+vfopen1.o:	vfopen1.c 
+	$(CC) $(CFLAGS) -c vfopen1.c
+
+vfopen2.o:	vfopen2.c 
+	$(CC) $(CFLAGS) -c vfopen2.c
+
+vconta1.o:	vconta1.c 
+	$(CC) $(CFLAGS) -c vconta1.c
+
+vchkprt1.o:	vchkprt1.c 
+	$(CC) $(CFLAGS) -c vchkprt1.c
+
+vdrvld1.o:	vdrvld1.c 
+	$(CC) $(CFLAGS) -c vdrvld1.c
+
+vdrvld2.o:	vdrvld2.c 
+	$(CC) $(CFLAGS) -c vdrvld2.c
+
+dfpsetd.o:	dfpsetd.c
+	$(CC) $(CFLAGS) -c dfpsetd.c
+
+# make rules for dynamic libaries
+async.dylib:	async.o
+	$(CC) $(LFLAGS) async.o -o async.dylib
+
+vhello1.dylib:	vhello1.o
+	$(CC) $(LFLAGS) vhello1.o -o vhello1.dylib
+
+vhello2.dylib:	vhello2.o
+	$(CC) $(LFLAGS) vhello2.o -o vhello2.dylib
+
+vhelbad.dylib:	vhelbad.o
+	$(CC) $(LFLAGS) vhelbad.o -o vhelbad.dylib
+
+findcaus.dylib:	findcaus.o
+	$(CC) $(LFLAGS) findcaus.o -o findcaus.dylib
+
+vacbtst.dylib:	vacbtst.o
+	$(CC) $(LFLAGS) vacbtst.o -o vacbtst.dylib
+
+vprtchg.dylib:	vprtchg.o
+	$(CC) $(LFLAGS) vprtchg.o -o vprtchg.dylib
+
+vprtchg2.dylib:	vprtchg2.o
+	$(CC) $(LFLAGS) vprtchg2.o -o vprtchg2.dylib
+
+vprtchg3.dylib:	vprtchg3.o
+	$(CC) $(LFLAGS) vprtchg3.o -o vprtchg3.dylib
+
+vprtdels.dylib:	vprtdels.o
+	$(CC) $(LFLAGS) vprtdels.o -o vprtdels.dylib
+
+vprtdel2.dylib:	vprtdel2.o
+	$(CC) $(LFLAGS) vprtdel2.o -o vprtdel2.dylib
+
+vsetdels.dylib:	vsetdels.o
+	$(CC) $(LFLAGS) vsetdels.o -o vsetdels.dylib
+
+vsetval1.dylib:	vsetval1.o
+	$(CC) $(LFLAGS) vsetval1.o -o vsetval1.dylib
+
+vsetval2.dylib:	vsetval2.o
+	$(CC) $(LFLAGS) vsetval2.o -o vsetval2.dylib
+
+vtimcbs.dylib:	vtimcbs.o
+	$(CC) $(LFLAGS) vtimcbs.o -o vtimcbs.dylib
+
+vfopen1.dylib:	vfopen1.o
+	$(CC) $(LFLAGS) vfopen1.o -o vfopen1.dylib
+
+vfopen2.dylib:	vfopen2.o
+	$(CC) $(LFLAGS) vfopen2.o -o vfopen2.dylib
+
+vconta1.dylib:	vconta1.o
+	$(CC) $(LFLAGS) vconta1.o -o vconta1.dylib
+
+vchkprt1.dylib:	vchkprt1.o
+	$(CC) $(LFLAGS) vchkprt1.o -o vchkprt1.dylib
+
+vdrvld1.dylib:	vdrvld1.o
+	$(CC) $(LFLAGS) vdrvld1.o -o vdrvld1.dylib
+
+vdrvld2.dylib:	vdrvld2.o
+	$(CC) $(LFLAGS) vdrvld2.o -o vdrvld2.dylib
+
+dfpsetd.dylib:	dfpsetd.o
+	$(CC) $(LFLAGS) dfpsetd.o -o dfpsetd.dylib
diff --git a/tests_and_examples/examples.vpi/makefile.sparc-gcc b/tests_and_examples/examples.vpi/makefile.sparc-gcc
new file mode 100644
index 0000000..7cd92af
--- /dev/null
+++ b/tests_and_examples/examples.vpi/makefile.sparc-gcc
@@ -0,0 +1,144 @@
+# could add to CFLAGS to turn on warnings if you are using gcc
+WARNS=-Wall
+
+# change path if not running test from installed directory location
+INCS=-I../../pli_incs
+# maybe want -O<something> and/or -g
+CFLAGS= -Wall -g $(INCS)
+LFLAGS= -G 
+
+# change to your compiler
+CC=gcc
+
+async.o:	async.c 
+	$(CC) $(CFLAGS) -c async.c
+ 
+vhello1.o:	vhello1.c 
+	$(CC) $(CFLAGS) -c vhello1.c
+
+vhello2.o:	vhello2.c 
+	$(CC) $(CFLAGS) -c vhello2.c
+
+vhelbad.o:	vhelbad.c 
+	$(CC) $(CFLAGS) -c vhelbad.c
+
+findcaus.o:	findcaus.c 
+	$(CC) $(CFLAGS) -c findcaus.c
+
+vacbtst.o:	vacbtst.c 
+	$(CC) $(CFLAGS) -c vacbtst.c
+
+vprtchg.o:	vprtchg.c 
+	$(CC) $(CFLAGS) -c vprtchg.c
+
+vprtchg2.o:	vprtchg2.c 
+	$(CC) $(CFLAGS) -c vprtchg2.c
+
+vprtchg3.o:	vprtchg3.c 
+	$(CC) $(CFLAGS) -c vprtchg3.c
+
+vprtdels.o:	vprtdels.c 
+	$(CC) $(CFLAGS) -c vprtdels.c
+
+vprtdel2.o:	vprtdel2.c 
+	$(CC) $(CFLAGS) -c vprtdel2.c
+
+vsetdels.o:	vsetdels.c 
+	$(CC) $(CFLAGS) -c vsetdels.c
+
+vsetval1.o:	vsetval1.c 
+	$(CC) $(CFLAGS) -c vsetval1.c
+
+vsetval2.o:	vsetval2.c 
+	$(CC) $(CFLAGS) -c vsetval2.c
+
+vtimcbs.o:	vtimcbs.c 
+	$(CC) $(CFLAGS) -c vtimcbs.c
+
+vfopen1.o:	vfopen1.c 
+	$(CC) $(CFLAGS) -c vfopen1.c
+
+vfopen2.o:	vfopen2.c 
+	$(CC) $(CFLAGS) -c vfopen2.c
+
+vconta1.o:	vconta1.c 
+	$(CC) $(CFLAGS) -c vconta1.c
+
+vchkprt1.o:	vchkprt1.c 
+	$(CC) $(CFLAGS) -c vchkprt1.c
+
+vdrvld1.o:	vdrvld1.c 
+	$(CC) $(CFLAGS) -c vdrvld1.c
+
+vdrvld2.o:	vdrvld2.c 
+	$(CC) $(CFLAGS) -c vdrvld2.c
+
+dfpsetd.o:	dfpsetd.c
+	$(CC) $(CFLAGS) -c dfpsetd.c
+
+# make rules for dynamic libaries
+async.so:	async.o
+	$(LD) $(LFLAGS) async.o -o async.so
+
+vhello1.so:	vhello1.o
+	$(LD) $(LFLAGS) vhello1.o -o vhello1.so
+
+vhello2.so:	vhello2.o
+	$(LD) $(LFLAGS) vhello2.o -o vhello2.so
+
+vhelbad.so:	vhelbad.o
+	$(LD) $(LFLAGS) vhelbad.o -o vhelbad.so
+
+findcaus.so:	findcaus.o
+	$(LD) $(LFLAGS) findcaus.o -o findcaus.so
+
+vacbtst.so:	vacbtst.o
+	$(LD) $(LFLAGS) vacbtst.o -o vacbtst.so
+
+vprtchg.so:	vprtchg.o
+	$(LD) $(LFLAGS) vprtchg.o -o vprtchg.so
+
+vprtchg2.so:	vprtchg2.o
+	$(LD) $(LFLAGS) vprtchg2.o -o vprtchg2.so
+
+vprtchg3.so:	vprtchg3.o
+	$(LD) $(LFLAGS) vprtchg3.o -o vprtchg3.so
+
+vprtdels.so:	vprtdels.o
+	$(LD) $(LFLAGS) vprtdels.o -o vprtdels.so
+
+vprtdel2.so:	vprtdel2.o
+	$(LD) $(LFLAGS) vprtdel2.o -o vprtdel2.so
+
+vsetdels.so:	vsetdels.o
+	$(LD) $(LFLAGS) vsetdels.o -o vsetdels.so
+
+vsetval1.so:	vsetval1.o
+	$(LD) $(LFLAGS) vsetval1.o -o vsetval1.so
+
+vsetval2.so:	vsetval2.o
+	$(LD) $(LFLAGS) vsetval2.o -o vsetval2.so
+
+vtimcbs.so:	vtimcbs.o
+	$(LD) $(LFLAGS) vtimcbs.o -o vtimcbs.so
+
+vfopen1.so:	vfopen1.o
+	$(LD) $(LFLAGS) vfopen1.o -o vfopen1.so
+
+vfopen2.so:	vfopen2.o
+	$(LD) $(LFLAGS) vfopen2.o -o vfopen2.so
+
+vconta1.so:	vconta1.o
+	$(LD) $(LFLAGS) vconta1.o -o vconta1.so
+
+vchkprt1.so:	vchkprt1.o
+	$(LD) $(LFLAGS) vchkprt1.o -o vchkprt1.so
+
+vdrvld1.so:	vdrvld1.o
+	$(LD) $(LFLAGS) vdrvld1.o -o vdrvld1.so
+
+vdrvld2.so:	vdrvld2.o
+	$(LD) $(LFLAGS) vdrvld2.o -o vdrvld2.so
+
+dfpsetd.so:	dfpsetd.o
+	$(LD) $(LFLAGS) dfpsetd.o -o dfpsetd.so
diff --git a/tests_and_examples/examples.vpi/opt_vacbtst.inp b/tests_and_examples/examples.vpi/opt_vacbtst.inp
new file mode 100644
index 0000000..67a5173
--- /dev/null
+++ b/tests_and_examples/examples.vpi/opt_vacbtst.inp
@@ -0,0 +1,13 @@
+// remove C[number]> prefixes and output messages from log file
+.
+$remove_all_actions;
+$reg_all_actions;
+$remove_all_actions;
+$reg_all_actions;
+$display("---> reset %d times.\n", $reset_count);
+if ($reset_count < 3) $reset; else; 
+$remove_all_actions;
+$reg_all_actions;
+$remove_all_actions;
+$reg_all_actions;
+.
diff --git a/tests_and_examples/examples.vpi/opt_vacbtst.plg b/tests_and_examples/examples.vpi/opt_vacbtst.plg
new file mode 100644
index 0000000..ba6c2ee
--- /dev/null
+++ b/tests_and_examples/examples.vpi/opt_vacbtst.plg
@@ -0,0 +1,15 @@
+*** at end of compilation callback ***
+*** entering interactive mode callback ***
+C1 > // remove C[number]> prefixes and output messages from log file
+C1 > .
+*** exiting interactive mode callback ***
+        10 start   x: ffffffff  y: 1  count: 0
+        10 t1 started
+        30 t1 finished
+        30 return  x: 00000000  y: 0  count: 1
+        30 t1 started
+        35 return  x: 00000000  y: 0  count: 1
+        35 t1 started
+        55 t1 finished
+        55 return  x: 00000002  y: 0  count: 2
+*** at end of simulation callback ***
diff --git a/tests_and_examples/examples.vpi/prtbg09.v b/tests_and_examples/examples.vpi/prtbg09.v
new file mode 100644
index 0000000..04f7399
--- /dev/null
+++ b/tests_and_examples/examples.vpi/prtbg09.v
@@ -0,0 +1,95 @@
+
+
+module test;
+ wire [31:0] net_31;
+ wire [31:0] net_44;
+ wire [127:96] Data_In;
+
+        Mux #(4,32,2) Mux554(.Select(net_31[3:2]), .Output(net_44[31:0]),
+                .In0(Data_In[127:96]), .In1(Data_In[95:64]), .In2(Data_In[63:32]),
+                .In3(Data_In[31:0]), .In4(), .In5(), .In6(), .In7(), .In8(), .In9(),
+                .In10(), .In11(), .In12(), .In13(), .In14(), .In15() );
+endmodule
+
+module Mux (Select, Output, In0, In1, In2, In3, In4,
+                            In5, In6, In7, In8, In9,
+                            In10,In11,In12,In13,In14,
+                            In15);
+
+
+        parameter       ninputs=2,
+                        width=4,
+                        select_width=1;
+
+        input   [width-1:0]     In0;
+        input   [width-1:0]     In1;
+        input   [width-1:0]     In2;
+        input   [width-1:0]     In3;
+        input   [width-1:0]     In4;
+        input   [width-1:0]     In5;
+        input   [width-1:0]     In6;
+        input   [width-1:0]     In7;
+        input   [width-1:0]     In8;
+        input   [width-1:0]     In9;
+        input   [width-1:0]     In10;
+        input   [width-1:0]     In11;
+        input   [width-1:0]     In12;
+        input   [width-1:0]     In13;
+        input   [width-1:0]     In14;
+        input   [width-1:0]     In15;
+
+        input   [select_width-1:0]      Select;
+
+        output  [width-1:0]     Output;
+        reg     [width-1:0]     Output;
+
+        integer selection;
+        integer temp;
+
+        always begin
+          deassign Output;
+          selection = Select;
+          if (select_width == ninputs) begin
+            // Non-decoded select inputs
+            temp = 0;
+            if ((selection & 'hff00) != 0) begin
+              temp = temp + 8;
+              selection = selection >> 8;
+            end
+            if ((selection & 'hf0) != 0) begin
+              temp = temp + 4;
+              selection = selection >> 4;
+            end
+            if ((selection & 'hc) != 0) begin
+              temp = temp + 2;
+              selection = selection >> 2;
+            end
+            if ((selection & 'h2) != 0) begin
+              temp = temp + 1;
+            end
+            selection = temp;
+          end
+          // Decoded select inputs
+          case (selection & 15)
+            4'b0000 : assign Output = In0;
+            4'b0001 : assign Output = In1;
+            4'b0010 : assign Output = In2;
+            4'b0011 : assign Output = In3;
+            4'b0100 : assign Output = In4;
+            4'b0100 : assign Output = In5;
+            4'b0110 : assign Output = In6;
+            4'b0111 : assign Output = In7;
+            4'b1000 : assign Output = In8;
+            4'b1001 : assign Output = In9;
+            4'b1010 : assign Output = In10;
+            4'b1011 : assign Output = In11;
+            4'b1100 : assign Output = In12;
+            4'b1101 : assign Output = In13;
+            4'b1110 : assign Output = In14;
+            4'b1111 : assign Output = In15;
+            default : assign Output = In0 & In1;
+          endcase
+          @(Select);
+        end // always
+
+endmodule               // mux
diff --git a/tests_and_examples/examples.vpi/rmlic.pl b/tests_and_examples/examples.vpi/rmlic.pl
new file mode 100755
index 0000000..39c7ade
--- /dev/null
+++ b/tests_and_examples/examples.vpi/rmlic.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+use strict;
+my $file;
+my $i;
+my $line;
+ 
+ $file = 'verilog.log';
+ if (@ARGV == 1)
+ {
+     $file = $ARGV[0];
+ }
+
+ open(FILE, $file) or die "Can't open $file\n";
+ open(TMP, '>tmp') or die "Can't open tmp file\n";
+ for($i = 0; $i < 3; $i++)
+ {
+      $line = <FILE>;
+ }
+ while(<FILE>)
+ {
+      print TMP $_;
+ }
+ close TMP;
+ close FILE;
+ rename 'tmp', $file;
diff --git a/tests_and_examples/examples.vpi/sparc.old b/tests_and_examples/examples.vpi/sparc.old
new file mode 100644
index 0000000..b84c9ee
--- /dev/null
+++ b/tests_and_examples/examples.vpi/sparc.old
@@ -0,0 +1,181 @@
+# version for gcc, for other compiler change CC=
+# could add to CFLAGS to turn on warnings if you are using gcc
+WARNS=-Wall
+
+# change path if not running test from installed directory location
+INCS=-I../../pli_incs
+# maybe want -O<something> and/or -g also maybe -march=
+CFLAGS= -Wall $(INCS)
+
+
+# change to your compiler
+CC=gcc
+
+PLIOBJS=cv_main.o veriuser.o
+
+LFLAGS=
+# probably not all of these are really needed
+LIBS= -lm -lnsl -lsocket -lintl -ldl 
+# change path if not running test from installed directory location
+CVOLOC=../../lib/cverobj.o
+
+cv_main.o:	cv_main.c 
+	$(CC) $(CFLAGS) -c cv_main.c
+
+veriuser.o:	veriuser.c 
+	$(CC) $(CFLAGS) -c veriuser.c
+
+async.o:	async.c 
+	$(CC) $(CFLAGS) -c async.c
+
+vhello1.o:	vhello1.c 
+	$(CC) $(CFLAGS) -c vhello1.c
+
+vhello2.o:	vhello2.c 
+	$(CC) $(CFLAGS) -c vhello2.c
+
+vhelbad.o:	vhelbad.c 
+	$(CC) $(CFLAGS) -c vhelbad.c
+
+findcaus.o:	findcaus.c 
+	$(CC) $(CFLAGS) -c findcaus.c
+
+vacbtst.o:	vacbtst.c 
+	$(CC) $(CFLAGS) -c vacbtst.c
+
+vprtchg.o:	vprtchg.c 
+	$(CC) $(CFLAGS) -c vprtchg.c
+
+vprtchg2.o:	vprtchg2.c 
+	$(CC) $(CFLAGS) -c vprtchg2.c
+
+vprtchg3.o:	vprtchg3.c 
+	$(CC) $(CFLAGS) -c vprtchg3.c
+
+vprtdels.o:	vprtdels.c 
+	$(CC) $(CFLAGS) -c vprtdels.c
+
+vprtdel2.o:	vprtdel2.c 
+	$(CC) $(CFLAGS) -c vprtdel2.c
+
+vsetdels.o:	vsetdels.c 
+	$(CC) $(CFLAGS) -c vsetdels.c
+
+vsetval1.o:	vsetval1.c 
+	$(CC) $(CFLAGS) -c vsetval1.c
+
+vsetval2.o:	vsetval2.c 
+	$(CC) $(CFLAGS) -c vsetval2.c
+
+vtimcbs.o:	vtimcbs.c 
+	$(CC) $(CFLAGS) -c vtimcbs.c
+
+vfopen1.o:	vfopen1.c 
+	$(CC) $(CFLAGS) -c vfopen1.c
+
+vfopen2.o:	vfopen2.c 
+	$(CC) $(CFLAGS) -c vfopen2.c
+
+vconta1.o:	vconta1.c 
+	$(CC) $(CFLAGS) -c vconta1.c
+
+vchkprt1.o:	vchkprt1.c 
+	$(CC) $(CFLAGS) -c vchkprt1.c
+
+vdrvld1.o:	vdrvld1.c 
+	$(CC) $(CFLAGS) -c vdrvld1.c
+
+vdrvld2.o:	vdrvld2.c 
+	$(CC) $(CFLAGS) -c vdrvld2.c
+
+dfpsetd.o:	dfpsetd.c
+	$(CC) $(CFLAGS) -c dfpsetd.c
+
+# would normally use make variables for lists of objects and sources
+async:	async.o $(PLIOBJS)  
+	$(CC) $(LFLAGS) $(CVOLOC) async.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o async
+
+vhello1:	vhello1.o $(PLIOBJS)  
+	$(CC) $(LFLAGS) $(CVOLOC) vhello1.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vhello1
+
+vhello2:	vhello2.o $(PLIOBJS)  
+	$(CC) $(LFLAGS) $(CVOLOC) vhello2.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vhello2
+
+vhelbad:	vhelbad.o $(PLIOBJS)  
+	$(CC) $(LFLAGS) $(CVOLOC) vhelbad.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vhelbad
+
+findcaus:	findcaus.o $(PLIOBJS)  
+	$(CC) $(LFLAGS) $(CVOLOC) findcaus.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o findcaus
+
+vacbtst:	vacbtst.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vacbtst.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vacbtst
+
+vprtchg:	vprtchg.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vprtchg.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vprtchg
+
+vprtchg2:	vprtchg2.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vprtchg2.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vprtchg2
+
+vprtchg3:	vprtchg3.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vprtchg3.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vprtchg3
+
+vprtdels:	vprtdels.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vprtdels.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vprtdels
+
+vprtdel2:	vprtdel2.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vprtdel2.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vprtdel2
+
+vsetdels:	vsetdels.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vsetdels.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vsetdels
+
+vsetval1:	vsetval1.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vsetval1.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vsetval1
+
+vsetval2:	vsetval2.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vsetval2.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vsetval2
+
+vtimcbs:	vtimcbs.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vtimcbs.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vtimcbs
+
+vfopen1:	vfopen1.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vfopen1.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vfopen1
+
+vfopen2:	vfopen2.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vfopen2.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vfopen2
+
+vconta1:	vconta1.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vconta1.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vconta1
+
+vchkprt1:	vchkprt1.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vchkprt1.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vchkprt1
+
+vdrvld1:	vdrvld1.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vdrvld1.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vdrvld1
+
+vdrvld2:	vdrvld2.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) vdrvld2.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o vdrvld2
+
+dfpsetd:	dfpsetd.o $(PLIOBJS) 
+	$(CC) $(LFLAGS) $(CVOLOC) dfpsetd.o $(PLIOBJS) $(LFLAGS) \
+	$(LIBS) -o dfpsetd
diff --git a/tests_and_examples/examples.vpi/task10.v b/tests_and_examples/examples.vpi/task10.v
new file mode 100644
index 0000000..1e2db88
--- /dev/null
+++ b/tests_and_examples/examples.vpi/task10.v
@@ -0,0 +1,58 @@
+module task10;
+    reg [31:0] aa, x;
+    reg bb, y, nochg;
+    integer count;
+    initial count = 0;
+
+    event e1;
+
+    task t1;
+	input [31:0] a;
+	input b;
+	output [31:0] c;
+	output  d;
+	reg d;
+	reg [31:0] c;
+	begin
+	    $display($stime, " t1 started"); 
+
+	    d = b;
+	    #10 c = a;
+	    #10 count = count + 1;
+	    $display($stime, " t1 finished"); 
+
+	    end
+	endtask
+
+    initial begin
+        x = 31'hxxxxxxxx;
+        #10;    
+        aa = 0;
+	bb = 0;
+	x = -1;
+	y = 1;
+	$display($stime," start   x: %x  y: %x  count: %0d", x, y, count);
+        t1(aa, bb, x, y);
+	$display($stime," return  x: %x  y: %x  count: %0d", x, y, count);
+
+	aa = aa + 1;
+	bb = ~bb;
+	->e1;
+        t1(aa, bb, x, y);
+	$display($stime," return  x: %x  y: %x  count: %0d", x, y, count);
+
+	aa = aa + 1;
+	bb = ~bb;
+        t1(aa, bb, x, y);
+	$display($stime," return  x: %x  y: %x  count: %0d", x, y, count);
+
+	end
+
+    initial begin
+	@e1 ;
+	#5  disable t1;
+	end
+    
+    always begin @nochg ; end
+
+    endmodule
diff --git a/tests_and_examples/examples.vpi/timtst03.v b/tests_and_examples/examples.vpi/timtst03.v
new file mode 100644
index 0000000..6562b69
--- /dev/null
+++ b/tests_and_examples/examples.vpi/timtst03.v
@@ -0,0 +1,15 @@
+`timescale 10 ns / 1 ns 
+module test;
+ reg set;
+ wire a, b, c;
+ parameter p = 1.55;
+
+ and #p i1(a, b, c);
+
+ initial
+  begin
+   $monitor($realtime,,"set=", set);
+   #p set = 0;
+   #p set = 1;
+  end
+endmodule
diff --git a/tests_and_examples/examples.vpi/vacbtst.c b/tests_and_examples/examples.vpi/vacbtst.c
new file mode 100644
index 0000000..cd809a4
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vacbtst.c
@@ -0,0 +1,443 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+/*
+ * test of all action call backs
+ * shows sequences of events for action user callbacks
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* local prototypes */
+static char *cb_val_to_nam(char *, int);
+static void prt_reg_cbs(char *);
+
+/* global prototypes */
+extern PLI_INT32 remove_all_actions(p_vpi_systf_data);
+extern PLI_INT32 reg_all_actions(p_vpi_systf_data);
+extern int setup_callbacks(struct t_cb_data *);
+extern int cb_compend(p_cb_data);
+extern int cbsimstart(p_cb_data);
+extern int cbsimstart2(p_cb_data);
+extern int cbresetstart(p_cb_data);
+extern int cbresetend(p_cb_data);
+extern int cbsimend(p_cb_data);
+extern int cbtchkerr(p_cb_data);
+extern int cbenteriact(p_cb_data);
+extern int cbexitiact(p_cb_data);
+extern int cbiactscopchg(p_cb_data);
+
+extern int my_error_handler(struct t_cb_data *);
+extern void register_cbs(void);
+extern void register_systfs(void);
+
+vpiHandle action_cbtab[64];
+
+/*
+ * remove all register action cbs
+ */
+PLI_INT32 remove_all_actions(p_vpi_systf_data tfdatp)
+{
+ vpiHandle cbhref;
+
+ prt_reg_cbs("callbacks before $remove_all_actions");
+ /* can't remove start of sim reset? */
+
+ if ((cbhref = action_cbtab[cbStartOfReset]) != NULL)
+  {
+   vpi_remove_cb(cbhref);
+   action_cbtab[cbStartOfReset] = NULL;
+  }
+ if ((cbhref = action_cbtab[cbEndOfReset]) != NULL)
+  {
+   vpi_remove_cb(cbhref);
+   action_cbtab[cbEndOfReset] = NULL;
+  }
+ if ((cbhref = action_cbtab[cbEndOfSimulation]) != NULL)
+  {
+   vpi_remove_cb(cbhref);
+   action_cbtab[cbEndOfSimulation] = NULL;
+  }
+ if ((cbhref = action_cbtab[cbTchkViolation]) != NULL)
+  {
+   vpi_remove_cb(cbhref);
+   action_cbtab[cbTchkViolation] = NULL;
+  }
+ if ((cbhref = action_cbtab[cbEnterInteractive]) != NULL)
+  {
+   vpi_remove_cb(cbhref);
+   action_cbtab[cbEnterInteractive] = NULL;
+  }
+ if ((cbhref = action_cbtab[cbExitInteractive]) != NULL)
+  {
+   vpi_remove_cb(cbhref);
+   action_cbtab[cbExitInteractive] = NULL;
+  }
+ if ((cbhref = action_cbtab[cbInteractiveScopeChange]) != NULL)
+  {
+   vpi_remove_cb(cbhref);
+   action_cbtab[cbInteractiveScopeChange] = NULL;
+  }
+ prt_reg_cbs("callbacks after $remove_all_actions");
+ return(0);
+}
+
+/*
+ * print all register call backs
+ */
+static void prt_reg_cbs(char *label)
+{
+ vpiHandle iter, cbref; 
+ s_cb_data cb_inf;
+ p_cb_data cbinfp;
+ char s1[1025];
+ 
+ vpi_printf(">>> %s <<<\n", label);
+ /* get iterator of all registered callbacks */
+ if ((iter = vpi_iterate(vpiCallback, NULL)) == NULL) 
+  { vpi_printf("  **NONE**\n"); return; }
+
+ /* user provides record that is filled but following current semantics */
+ /* values pointed to by contents are shared (i.e. must be left as is) */
+ cbinfp = &cb_inf;
+ cbinfp->obj = NULL;
+ cbinfp->time = NULL;
+ cbinfp->value = NULL;
+ cbinfp->index = 0;
+ for (;;)
+  {
+   if ((cbref = vpi_scan(iter)) == NULL) break;
+   vpi_get_cb_info(cbref, cbinfp);
+
+   vpi_printf("  vpi_ callback type %s registered\n",
+    cb_val_to_nam(s1, cbinfp->reason));
+  }
+}
+
+/*
+ * convert a callback reason constant to a name 
+ *
+ * some here not supported by Cver - will just never see 
+ */
+static char *cb_val_to_nam(char *s, int cbtyp)
+{
+ switch (cbtyp) {
+  case cbValueChange: strcpy(s, "cbValueChange"); break;
+  case cbStmt: strcpy(s, "cbStmt"); break;
+  case cbForce: strcpy(s, "cbForce"); break;
+  case cbRelease: strcpy(s, "cbRelease"); break;
+  case cbAtStartOfSimTime: strcpy(s, "cbAtStartOfSimTime"); break;
+  case cbReadWriteSynch: strcpy(s, "cbReadWriteSynch"); break;
+  case cbReadOnlySynch: strcpy(s, "cbReadOnlySynch"); break;
+  case cbNextSimTime: strcpy(s, "cbNextSimTime"); break;
+  case cbAfterDelay: strcpy(s, "cbAfterDelay"); break;
+  case cbEndOfCompile: strcpy(s, "cbEndOfCompile"); break;
+  case cbStartOfSimulation: strcpy(s, "cbStartOfSimulation"); break;
+  case cbEndOfSimulation: strcpy(s, "cbEndOfSimulation"); break;
+  case cbError: strcpy(s, "cbError"); break;
+  case cbPLIError: strcpy(s, "cbPLIError"); break;
+  case cbTchkViolation: strcpy(s, "cbTchkViolation"); break;
+  case cbStartOfSave: strcpy(s, "cbStartOfSave"); break; 
+  case cbEndOfSave: strcpy(s, "cbEndOfSave"); break;
+  case cbStartOfRestart: strcpy(s, "cbStartOfRestart"); break;
+  case cbEndOfRestart: strcpy(s, "cbEndOfRestart"); break;
+  case cbStartOfReset: strcpy(s, "cbStartOfReset"); break;
+  case cbEndOfReset: strcpy(s, "cbEndOfReset"); break;
+  case cbEnterInteractive: strcpy(s, "cbEnterInteractive"); break;
+  case cbExitInteractive: strcpy(s, "cbExitInteractive"); break;
+  case cbInteractiveScopeChange: strcpy(s, "cbInteractiveScopeChange"); break;
+  case cbUnresolvedSystf: strcpy(s, "cbUnresolvedSystf"); break;
+  default: strcpy(s, "**unknown**"); break;
+ }
+ return(s);
+}
+
+/*
+ * reg all action cbs 
+ * if user does not call after remove - will have 2 registerd
+ */
+int reg_all_actions(p_vpi_systf_data tfdatp)
+{
+ prt_reg_cbs("callbacks before $reg_all_actions");
+ setup_callbacks(NULL);
+ prt_reg_cbs("callbacks after $reg_all_actions");
+ return(0);
+}
+
+/*
+ * routine to setup call backs (called from start of simulation cb)
+ */
+int setup_callbacks(struct t_cb_data *cbp)
+{
+ vpiHandle cbhref;
+ struct t_cb_data cbrec;
+
+ /* these must be NULL or given well formed records maybe vpiSuppress... */
+ cbrec.obj = NULL;
+ cbrec.time = NULL;
+ cbrec.value = NULL;
+ cbrec.user_data = NULL;
+ /* this schedules event so same action cb from action routine should work? */
+ if (action_cbtab[cbStartOfSimulation] == NULL)
+  {
+   cbrec.reason = cbStartOfSimulation;
+   cbrec.cb_rtn = cbsimstart2;
+   cbhref = vpi_register_cb(&cbrec); 
+   action_cbtab[cbStartOfSimulation] = cbhref;
+  }
+
+ if (action_cbtab[cbStartOfReset] == NULL)
+  {
+   cbrec.reason = cbStartOfReset;
+   cbrec.cb_rtn = cbresetstart;
+   cbhref = vpi_register_cb(&cbrec); 
+   action_cbtab[cbStartOfReset] = cbhref;
+  }
+
+ if (action_cbtab[cbEndOfReset] == NULL)
+  {
+   cbrec.reason = cbEndOfReset;
+   cbrec.cb_rtn = cbresetend;
+   cbhref = vpi_register_cb(&cbrec); 
+   action_cbtab[cbEndOfReset] = cbhref;
+  }
+
+ if (action_cbtab[cbEndOfSimulation] == NULL)
+  {
+   cbrec.reason = cbEndOfSimulation;
+   cbrec.cb_rtn = cbsimend;
+   cbhref = vpi_register_cb(&cbrec); 
+   action_cbtab[cbEndOfSimulation] = cbhref;
+  }
+
+ if (action_cbtab[cbTchkViolation] == NULL)
+  {
+   cbrec.reason = cbTchkViolation;
+   cbrec.cb_rtn = cbtchkerr;
+   cbhref = vpi_register_cb(&cbrec); 
+   action_cbtab[cbTchkViolation] = cbhref;
+  }
+
+ if (action_cbtab[cbEnterInteractive] == NULL)
+  {
+   cbrec.reason = cbEnterInteractive;
+   cbrec.cb_rtn = cbenteriact;
+   cbhref = vpi_register_cb(&cbrec); 
+   action_cbtab[cbEnterInteractive] = cbhref;
+  }
+
+ if (action_cbtab[cbExitInteractive] == NULL)
+  {
+   cbrec.reason = cbExitInteractive;
+   cbrec.cb_rtn = cbexitiact;
+   cbhref = vpi_register_cb(&cbrec); 
+   action_cbtab[cbExitInteractive] = cbhref;
+  }
+
+ if (action_cbtab[cbInteractiveScopeChange] == NULL)
+  {
+   cbrec.reason = cbInteractiveScopeChange;
+   cbrec.cb_rtn = cbiactscopchg;
+   cbhref = vpi_register_cb(&cbrec); 
+   action_cbtab[cbInteractiveScopeChange] = cbhref;
+  }
+ return(0);
+}
+
+int cb_compend(p_cb_data cbp)
+{
+ vpi_printf("*** at end of compilation callback ***\n");
+ return(0);
+}
+
+int cbsimstart(p_cb_data cbp)
+{
+ vpi_printf("*** at start of simulation callback (from vlog startup) ***\n");
+ return(0);
+}
+
+int cbsimstart2(p_cb_data cbp)
+{
+ vpi_printf("*** at start of simulation callback ***\n");
+ return(0);
+}
+
+int cbresetstart(p_cb_data cbp)
+{
+ vpi_printf("*** at start of reset callback ***\n");
+ return(0);
+}
+
+int cbresetend(p_cb_data cbp)
+{
+ vpi_printf("*** at end of reset callback ***\n");
+ return(0);
+}
+ 
+int cbsimend(p_cb_data cbp)
+{
+ vpi_printf("*** at end of simulation callback ***\n");
+ return(0);
+}
+
+int cbtchkerr(p_cb_data cbp)
+{
+ char s1[1024];
+
+ if (cbp->obj != NULL) strcpy(s1, vpi_get_str(vpiFullName, cbp->obj));
+ vpi_printf("*** timing check violation at **%s(%d) in %s callback\n",
+  vpi_get_str(vpiFile, cbp->obj), vpi_get(vpiLineNo, cbp->obj), s1);
+ return(0);
+}
+
+
+int cbenteriact(p_cb_data cbp)
+{
+ vpi_printf("*** entering interactive mode callback ***\n");
+ return(0);
+}
+
+int cbexitiact(p_cb_data cbp)
+{
+ vpi_printf("*** exiting interactive mode callback ***\n");
+ return(0);
+}
+
+int cbiactscopchg(p_cb_data cbp)
+{
+ vpi_printf("*** changing interactive scope to %s callback ***\n",
+  vpi_get_str(vpiFullName, cbp->obj));
+ return(0);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up, ingore normal errors */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_cbs, 
+ register_systfs,
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register start of sim call backs and set up error handling
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ * start of sim is first when internal data base completed
+ */
+void register_cbs(void)
+{
+ vpiHandle href;
+ struct t_cb_data *ecbp, *cbp;
+ struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: can not register register error handler callback.\n");
+
+ /* for this test only - setup cbs before start of sim */
+ cbp = &cbrec; 
+ cbp->cb_rtn = cb_compend;
+ cbp->reason = cbEndOfCompile;
+ /* notice rest already initialized from ecbp register */
+ href = vpi_register_cb(cbp); 
+ action_cbtab[cbEndOfCompile] = href;
+
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = setup_callbacks;
+ /* notice rest already initialized from ecbp register */
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(cbp)) == NULL)
+  vpi_printf("**ERR: cannot register start of sim callback.\n");
+ action_cbtab[cbStartOfSimulation] = href;
+}
+
+/*
+ * register remove call back system task - to be called interactively
+ */
+void register_systfs(void)
+{
+ static struct t_vpi_systf_data tfdat, tfdat2;
+ char s1[1024];
+ 
+ tfdat.type = vpiSysTask;
+ strcpy(s1, "$remove_all_actions");
+ tfdat.tfname = malloc(strlen(s1) + 1);
+ strcpy(tfdat.tfname, s1);
+ tfdat.calltf = remove_all_actions;
+ vpi_register_systf(&tfdat);
+
+ tfdat2.type = vpiSysTask;
+ strcpy(s1, "$reg_all_actions");
+ tfdat2.tfname = malloc(strlen(s1) + 1);
+ strcpy(tfdat2.tfname, s1);
+ tfdat2.calltf = reg_all_actions;
+
+ vpi_register_systf(&tfdat2);
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vacbtst.inp b/tests_and_examples/examples.vpi/vacbtst.inp
new file mode 100644
index 0000000..1fc1809
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vacbtst.inp
@@ -0,0 +1,20 @@
+// remove C[number]> prefixes and output messages from log file
+,
+$remove_all_actions;
+,
+$reg_all_actions;
+,
+$remove_all_actions;
+,
+$reg_all_actions;
+$display("---> reset %d times.\n", $reset_count);
+if ($reset_count < 3) $reset; else; 
+,
+$remove_all_actions;
+,
+$reg_all_actions;
+,
+$remove_all_actions;
+,
+$reg_all_actions;
+.
diff --git a/tests_and_examples/examples.vpi/vacbtst.plg b/tests_and_examples/examples.vpi/vacbtst.plg
new file mode 100644
index 0000000..f472aa5
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vacbtst.plg
@@ -0,0 +1,441 @@
+*** at end of compilation callback ***
+*** entering interactive mode callback ***
+C1 > // remove C[number]> prefixes and output messages from log file
+C1 > ,
+*** exiting interactive mode callback ***
+task10 (task10.v line 5) time 0
+5	    initial count = 0;
+*** entering interactive mode callback ***
+*** changing interactive scope to task10 callback ***
+C1 > $remove_all_actions;
+>>> callbacks before $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+>>> callbacks after $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+C2 > ,
+29	        #10;    
+C2 > $reg_all_actions;
+>>> callbacks before $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+>>> callbacks after $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+C3 > ,
+*** exiting interactive mode callback ***
+task10 (task10.v line 30) time 10
+30	        aa = 0;
+*** entering interactive mode callback ***
+*** changing interactive scope to task10 callback ***
+C3 > $remove_all_actions;
+>>> callbacks before $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+>>> callbacks after $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+C4 > ,
+31		bb = 0;
+C4 > $reg_all_actions;
+>>> callbacks before $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+>>> callbacks after $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+C5 > $display("---> reset %d times.\n", $reset_count);
+---> reset          0 times.
+
+C6 > if ($reset_count < 3) $reset; else; 
+*** at start of reset callback ***
+*** at end of reset callback ***
+*** entering interactive mode callback ***
+C7 > // remove C[number]> prefixes and output messages from log file
+C7 > ,
+*** exiting interactive mode callback ***
+task10 (task10.v line 5) time 0
+5	    initial count = 0;
+*** entering interactive mode callback ***
+*** changing interactive scope to task10 callback ***
+C7 > $remove_all_actions;
+>>> callbacks before $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+>>> callbacks after $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+C8 > ,
+29	        #10;    
+C8 > $reg_all_actions;
+>>> callbacks before $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+>>> callbacks after $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+C9 > ,
+*** exiting interactive mode callback ***
+task10 (task10.v line 30) time 10
+30	        aa = 0;
+*** entering interactive mode callback ***
+*** changing interactive scope to task10 callback ***
+C9 > $remove_all_actions;
+>>> callbacks before $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+>>> callbacks after $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+C10 > ,
+31		bb = 0;
+C10 > $reg_all_actions;
+>>> callbacks before $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+>>> callbacks after $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+C11 > $display("---> reset %d times.\n", $reset_count);
+---> reset          1 times.
+
+C12 > if ($reset_count < 3) $reset; else; 
+*** at start of reset callback ***
+*** at end of reset callback ***
+*** entering interactive mode callback ***
+C13 > // remove C[number]> prefixes and output messages from log file
+C13 > ,
+*** exiting interactive mode callback ***
+task10 (task10.v line 5) time 0
+5	    initial count = 0;
+*** entering interactive mode callback ***
+*** changing interactive scope to task10 callback ***
+C13 > $remove_all_actions;
+>>> callbacks before $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+>>> callbacks after $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+C14 > ,
+29	        #10;    
+C14 > $reg_all_actions;
+>>> callbacks before $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+>>> callbacks after $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+C15 > ,
+*** exiting interactive mode callback ***
+task10 (task10.v line 30) time 10
+30	        aa = 0;
+*** entering interactive mode callback ***
+*** changing interactive scope to task10 callback ***
+C15 > $remove_all_actions;
+>>> callbacks before $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+>>> callbacks after $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+C16 > ,
+31		bb = 0;
+C16 > $reg_all_actions;
+>>> callbacks before $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+>>> callbacks after $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+C17 > $display("---> reset %d times.\n", $reset_count);
+---> reset          2 times.
+
+C18 > if ($reset_count < 3) $reset; else; 
+*** at start of reset callback ***
+*** at end of reset callback ***
+*** entering interactive mode callback ***
+C19 > // remove C[number]> prefixes and output messages from log file
+C19 > ,
+*** exiting interactive mode callback ***
+task10 (task10.v line 5) time 0
+5	    initial count = 0;
+*** entering interactive mode callback ***
+*** changing interactive scope to task10 callback ***
+C19 > $remove_all_actions;
+>>> callbacks before $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+>>> callbacks after $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+C20 > ,
+29	        #10;    
+C20 > $reg_all_actions;
+>>> callbacks before $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+>>> callbacks after $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+C21 > ,
+*** exiting interactive mode callback ***
+task10 (task10.v line 30) time 10
+30	        aa = 0;
+*** entering interactive mode callback ***
+*** changing interactive scope to task10 callback ***
+C21 > $remove_all_actions;
+>>> callbacks before $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+>>> callbacks after $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+C22 > ,
+31		bb = 0;
+C22 > $reg_all_actions;
+>>> callbacks before $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+>>> callbacks after $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+C23 > $display("---> reset %d times.\n", $reset_count);
+---> reset          3 times.
+
+C24 > if ($reset_count < 3) $reset; else; 
+C25 > ,
+*** exiting interactive mode callback ***
+32		x = -1;
+*** entering interactive mode callback ***
+*** changing interactive scope to task10 callback ***
+C25 > $remove_all_actions;
+>>> callbacks before $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+>>> callbacks after $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+C26 > ,
+33		y = 1;
+C26 > $reg_all_actions;
+>>> callbacks before $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+>>> callbacks after $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+C27 > ,
+*** exiting interactive mode callback ***
+34		$display($stime," start   x: %x  y: %x  count: %0d", x, y, count);
+*** entering interactive mode callback ***
+*** changing interactive scope to task10 callback ***
+C27 > $remove_all_actions;
+>>> callbacks before $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+>>> callbacks after $remove_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+C28 > ,
+        10 start   x: ffffffff  y: 1  count: 0
+35	        t1(aa, bb, x, y);
+C28 > $reg_all_actions;
+>>> callbacks before $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+>>> callbacks after $reg_all_actions <<<
+  vpi_ callback type cbError registered
+  vpi_ callback type cbEndOfCompile registered
+  vpi_ callback type cbStartOfSimulation registered
+  vpi_ callback type cbStartOfReset registered
+  vpi_ callback type cbEndOfReset registered
+  vpi_ callback type cbEndOfSimulation registered
+  vpi_ callback type cbTchkViolation registered
+  vpi_ callback type cbEnterInteractive registered
+  vpi_ callback type cbExitInteractive registered
+  vpi_ callback type cbInteractiveScopeChange registered
+C29 > .
+*** exiting interactive mode callback ***
+        10 t1 started
+        30 t1 finished
+        30 return  x: 00000000  y: 0  count: 1
+        30 t1 started
+        35 return  x: 00000000  y: 0  count: 1
+        35 t1 started
+        55 t1 finished
+        55 return  x: 00000002  y: 0  count: 2
+*** at end of simulation callback ***
diff --git a/tests_and_examples/examples.vpi/vchkprt1.c b/tests_and_examples/examples.vpi/vchkprt1.c
new file mode 100644
index 0000000..f9250a9
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vchkprt1.c
@@ -0,0 +1,519 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * for every port in design check various acess methods
+ *
+ * FIXME - there are port expression cases for which this will core dump
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+#define TRUE 1
+#define FALSE 0
+
+unsigned mcd;
+int (*iproc_rtn)();
+
+/* local function prototypes */
+static void process_inst(vpiHandle);
+static int obj_in_iterator(vpiHandle, vpiHandle);
+static char *bld_varbitnam(char *, vpiHandle);
+static int is_lvalue(vpiHandle);
+static vpiHandle map_lvalue_to_var(vpiHandle);
+static void my_prt_vlog_info(void);
+static void print_nest_argv(char **, int);
+
+/* global function prototypes */
+extern int chk_ports(vpiHandle);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb(void);
+
+/*
+ * process all instances calling processing routine for each
+ */
+int process_all_insts(struct t_cb_data *cbp)
+{
+ int isiz;
+ vpiHandle topiter, topiref;
+
+ /* build the iterator for each module */
+ topiter = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, topiter);
+ vpi_mcd_printf(mcd, "  There are %d top level modules.\n", isiz);
+ for (;;)
+  {
+   if ((topiref = vpi_scan(topiter)) == NULL) break;
+   process_inst(topiref);
+  }
+ vpi_mcd_printf(mcd, "name of extra output file is [%s].\n",  
+  vpi_mcd_name(mcd & ~0x1)); 
+ vpi_mcd_printf(mcd,
+  "  >>> All instances processed - done - using Cver PLI only for checking.\n");
+ vpi_mcd_close(mcd & ~0x1);
+ vpi_sim_control(vpiFinish, 0);
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ *
+ * processing is top down depth first 
+ */
+static void process_inst(vpiHandle up_ihref)
+{
+ int isiz;
+ vpiHandle iter, ihref;
+
+ iproc_rtn(up_ihref);
+ /* ignore all but bottom (no containing instances) */  
+ if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return;
+
+ isiz = vpi_get(vpiSize, iter);
+ vpi_mcd_printf(mcd, "  There are %d instances in %s.\n", isiz,
+  vpi_get_str(vpiFullName, up_ihref));
+ for (;;)
+  {
+   if ((ihref = vpi_scan(iter)) == NULL) break;
+   process_inst(ihref);
+  }
+}
+
+/*
+ * from instance if has ports check cross and back for same object
+ */
+int chk_ports(vpiHandle ihref)
+{
+ int iconn_siz, mdprt_siz, pndx, bi, prtwid;
+ int ntyp;
+ vpiHandle iter, iter2, ihref2, pref, icref, mpref, varef;
+ vpiHandle pbref, p2ref;
+ char nnam[1025], s1[1025], s2[1025];
+
+ /* case 1: no ports */
+ if ((iter = vpi_iterate(vpiPort, ihref)) == NULL) return(0);
+ /* case 2: has ports */
+ for (;;)
+  {
+   if ((pref = vpi_scan(iter)) == NULL) break;
+   pndx = vpi_get(vpiPortIndex, pref);
+
+   strcpy(s1, vpi_get_str(vpiFullName, ihref));
+   vpi_mcd_printf(mcd, "  Processing port %s.%s (index %d):\n", s1,
+    vpi_get_str(vpiName, pref), pndx);
+
+   ihref2 = vpi_handle(vpiModule, pref);
+   if (ihref2 == NULL || !vpi_compare_objects(ihref, ihref2))
+    {
+     vpi_mcd_printf(mcd,
+      "**ERR: port %s (index %d) vpiModule (in 1-to-1 method) failed.\n",
+      vpi_get_str(vpiName, pref), pndx);
+    }
+
+   /* this is up instance connection */
+   icref = vpi_handle(vpiHighConn, pref);
+   /* this is down module port expression */
+   mpref = vpi_handle(vpiLowConn, pref);
+
+   /* DBG remove ---
+   if ((ntyp = vpi_get(vpiType, icref)) == vpiNet || ntyp == vpiNetBit)
+    vpi_printf("Net type %d\n", vpi_get(vpiNetType, icref)); 
+   if ((ntyp = vpi_get(vpiType, mpref)) == vpiNet || ntyp == vpiNetBit)
+    vpi_printf("Net type %d\n", vpi_get(vpiNetType, mpref)); 
+   --- */
+ if ((ntyp = vpi_get(vpiType, icref)) == vpiNet || ntyp == vpiNetBit) {
+     vpi_printf("    high conn: %s; net type: %d\n",
+                vpi_get_str(vpiFullName, icref),
+                vpi_get(vpiNetType, icref));
+ }
+ if ((ntyp = vpi_get(vpiType, mpref)) == vpiNet || ntyp == vpiNetBit) {
+     vpi_printf("    low conn: %s; net type: %d\n",
+                vpi_get_str(vpiFullName, mpref),
+                vpi_get(vpiNetType, mpref));
+ }
+
+   /* check for width mismatch */
+   iconn_siz = vpi_get(vpiSize, icref);
+   mdprt_siz = vpi_get(vpiSize, mpref);
+   if (iconn_siz != mdprt_siz)
+    {
+     vpi_mcd_printf(mcd,
+      "--WARN: port %s (index %d) width %d but connection width %d.\n",
+      vpi_get_str(vpiName, pref), pndx, mdprt_siz, iconn_siz);
+    }
+   /* get up net if lvalue - check to make sure net connects to port */ 
+   if (!is_lvalue(icref))
+    {
+     vpi_mcd_printf(mcd,
+      "++INFORM: port %s (index %d) connection not simple lvalue.\n",
+      vpi_get_str(vpiName, pref), pndx);
+    }
+   else
+    {
+     varef = map_lvalue_to_var(icref);
+     /* iterator for High Conn wire instance ports it connects to */
+     /* notice in looping scanning iter, if used here will over-write */
+     iter2 = vpi_iterate(vpiPortInst, varef);
+     if (iter2 == NULL || !obj_in_iterator(iter2, pref))
+      {
+       strcpy(nnam, vpi_get_str(vpiName, icref));
+       vpi_mcd_printf(mcd,
+        "**ERR: port %s (index %d) variable %s no vpiPortInst connection.\n",
+        vpi_get_str(vpiName, pref), pndx, nnam);
+      }
+     else
+      {
+       /* in Cver, this frees handle (standard needs to define) */
+       if (iter2 != NULL) vpi_free_object(iter2);
+       /* since for non nil case (usual), traversed iterator, must */
+       /* recreate the iterator */
+       iter2 = vpi_iterate(vpiPortInst, varef);
+       for (;;)
+        {
+         if ((p2ref = vpi_scan(iter2)) == NULL) break;
+         if (vpi_compare_objects(p2ref, pref)) continue; 
+         strcpy(s1, vpi_get_str(vpiFullName, ihref)); 
+         vpi_mcd_printf(mcd, "Also port %s.%s is a vpiPortInst.\n", s1,
+          vpi_get_str(vpiName, p2ref));
+        }
+      }
+    }
+
+   /* get down net (ignore concatenate) - check to make sure net connects */
+   if (mpref == NULL || !is_lvalue(mpref))
+    {
+     vpi_mcd_printf(mcd,
+      "**ERR: port %s (index %d) expression not simple lvalue.\n",
+      vpi_get_str(vpiName, pref), pndx);
+    }
+   else
+    {
+     varef = map_lvalue_to_var(mpref);
+     /* get net's module connecting ports (usually just 1) */
+     iter2 = vpi_iterate(vpiPort, varef);
+     if (iter2 == NULL || !obj_in_iterator(iter2, pref))
+      {
+       if (mpref == NULL) strcpy(nnam, "*none*");
+       else strcpy(nnam, vpi_get_str(vpiName, varef));
+       vpi_mcd_printf(mcd,
+        "**ERR: port %s (index %d) variable %s no vpiPortInst connection.\n",
+        vpi_get_str(vpiName, pref), pndx, nnam);
+      }
+     else
+      {
+       /* in Cver, this frees handle (standard needs to define) */
+       if (iter2 != NULL) vpi_free_object(iter2);
+       /* since for non nil case (usual), traversed iterator, must */
+       /* recreate the iterator */
+       iter2 = vpi_iterate(vpiPort, varef);
+       for (;;)
+        {
+         if ((p2ref = vpi_scan(iter2)) == NULL) break;
+         if (vpi_compare_objects(p2ref, pref)) continue; 
+         vpi_mcd_printf(mcd, "Also port %s is a vpiPort.\n",
+          vpi_get_str(vpiName, p2ref));
+        }
+      }
+    }
+   /* final test - for every vector port - get bit high and low conns */
+   if (vpi_get(vpiScalar, pref)) continue;
+   vpi_printf("... processing port %s\n", vpi_get_str(vpiName, pref));
+   if ((iter2 = vpi_iterate(vpiBit, pref)) == NULL)
+    {    
+     vpi_mcd_printf(mcd,
+      "**ERR: vector port %s (index %d) vpiBit iterator failed.\n",
+       vpi_get_str(vpiName, pref), pndx);
+     continue;
+    }
+   /* just assuming high to low for port bits (not port connecting net) */
+   prtwid = vpi_get(vpiSize, pref);
+   /* bit iterators always go from lsb to msb - needed for unc. */
+   for (bi = 0; bi < prtwid; bi++)
+    {
+     if ((pbref = vpi_scan(iter2)) == NULL) break;
+     /* notice ref's here either variable or vpiNetBit or vpiRegBit */ 
+     /* but for vpiPort (not port bit) conn's are expressions */
+     if ((icref = vpi_handle(vpiHighConn, pbref)) == NULL) continue;
+     if ((mpref = vpi_handle(vpiLowConn, pbref)) == NULL) continue;
+     vpi_mcd_printf(mcd,
+      "Port %d bit %d vpiLowConn %s connects to vpiHighConn %s.\n",
+      pndx, bi, bld_varbitnam(s1, mpref), bld_varbitnam(s2, icref));
+    }
+  }
+ return(0);
+}
+
+/*
+ * return T if object is simple lvalue (non concatenate) 
+ * can be reg 
+ */
+static int is_lvalue(vpiHandle xref)
+{
+ int xtyp;
+
+ xtyp = vpi_get(vpiType, xref);
+ switch (xtyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+  case vpiNetBit: case vpiRegBit: case vpiVarSelect: case vpiMemoryWord:
+  case vpiPartSelect:
+   break; 
+  default:
+   return(FALSE);
+ } 
+ return(TRUE);
+}
+
+/*
+ * map lvalue to variable
+ *
+ * for variables returns argument else for selects returns parent
+ */
+static vpiHandle map_lvalue_to_var(vpiHandle lvalref)
+{
+ int lvtyp;
+ vpiHandle varef;
+
+ lvtyp = vpi_get(vpiType, lvalref);
+ switch (lvtyp) {
+  case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
+   break;
+  case vpiNetBit: case vpiRegBit: case vpiVarSelect: case vpiMemoryWord:
+  case vpiPartSelect:
+   varef = vpi_handle(vpiParent, lvalref);
+   return(varef);
+  default: 
+   /* this is error that should never happen - will catch later */
+   break;
+ } 
+ return(lvalref);
+}
+
+/*
+ * return T if object in iterator 
+ * notice this scans so must free iterator and use vpi_iterate to scan again
+ */
+static int obj_in_iterator(vpiHandle iter, vpiHandle obj)
+{
+ vpiHandle iobj;
+
+ for (;;)
+  {
+   if ((iobj = vpi_scan(iter)) == NULL) break;
+   if (vpi_compare_objects(iobj, obj)) return(TRUE); 
+  }
+ /* notice T and F constants come from veriuser.h include */ 
+ return(FALSE);
+}
+
+/*
+ * build a 1 bit scalar or variable bit handle full (qualified) name
+ */
+static char *bld_varbitnam(char *s, vpiHandle href)
+{
+ int i1;
+ int otyp = vpi_get(vpiType, href); 
+ vpiHandle ndxref, varef;
+ s_vpi_value tmpval;
+ char s1[1025];
+ 
+ varef = map_lvalue_to_var(href);
+ strcpy(s, vpi_get_str(vpiFullName, varef));
+ if (otyp == vpiRegBit || otyp == vpiNetBit)
+  {
+   strcpy(s1, s);
+   ndxref = vpi_handle(vpiIndex, href);
+   tmpval.format = vpiIntVal;
+   vpi_get_value(ndxref, &tmpval);
+   i1 = tmpval.value.integer;
+   sprintf(s, "%s[%d]", s1, i1);
+  }
+ return(s);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if fatal error give up - continue after vpiError */
+ if (einfop->level == vpiSystem || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered System/Internal error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{ 
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+ struct t_cb_data cbrec, cbrec2;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec2;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = process_all_insts;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+
+ /* open a file to write to in addition to stdout and log */
+ if ((mcd = vpi_mcd_open("fff9")) == 0)
+  vpi_printf("***ERR: unable to open additional output file fff9\n");  
+ mcd |= 5;
+ /* set the processing routine */
+ iproc_rtn = chk_ports;
+ /* print out verilog information - mostly simulator specific */
+ my_prt_vlog_info();
+}
+
+/*
+ * print out simulator information to stdout and log file
+ */
+static void my_prt_vlog_info(void)
+{
+ register int i;
+ s_vpi_vlog_info vlog_inf;
+ p_vpi_vlog_info infp;
+
+ /* user must provide record filled by routine */
+ infp = &vlog_inf; 
+ if (!vpi_get_vlog_info(infp))
+  {
+   vpi_printf("**ERR: call to vpi_get_vlog_info failed.\n"); 
+   return;
+  } 
+ 
+ vpi_printf("--------------------------------------------------------------\n");
+ vpi_printf("VLOG PRODUCT: %s - VERSION: %s\n", infp->product, infp->version); 
+ if (infp->argc == 0) vpi_printf("  There are no command line arguments.\n");
+ else  
+  {
+   for (i = 0; i < infp->argc; i++)
+    {
+     if (strcmp(infp->argv[i], "-f") == 0)
+      {
+       vpi_printf("  Argument %d: %s\n", i, infp->argv[i]); 
+       vpi_printf("  Argument %d: NESTED ARGV\n", i + 1); 
+       if (i + 1 < infp->argc)
+        {
+         print_nest_argv((char **) infp->argv[i + 1], 1);
+         /* move past nested **argv structure */
+         i++;
+        }
+      }
+     else vpi_printf("  Argument %d: %s\n", i, infp->argv[i]); 
+    }
+  }
+ vpi_printf("--------------------------------------------------------------\n");
+}
+
+/*
+ * print nested argument list (recursive)
+ *
+ * format is -f followed by pointer to argv list with no argc but nil end
+ */
+static void print_nest_argv(char **argv, int lev)
+{
+ register int i;
+
+ if (argv[0] == NULL)
+  {
+   vpi_printf("  Level %d: No Arguments\n", lev);
+   return;
+  }
+ for (i = 0;; i++)
+  {
+   if (argv[i] == NULL)
+    {
+     vpi_printf("  Level %d: Argument %d: **NULL**\n", lev, i);
+     break;
+    }
+
+   if (strcmp(argv[i], "-f") == 0)
+    {
+     vpi_printf("  Level %d: Argument %d: %s\n", lev, i, argv[i]); 
+     vpi_printf("  Level %d: Argument %d: NESTED ARGV\n", lev, i + 1); 
+     print_nest_argv((char **) argv[i + 1], lev + 1);
+     i++;
+    }
+   else vpi_printf("  Level %d: Argument %d: %s\n", lev, i, argv[i]); 
+  }
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vconta1.c b/tests_and_examples/examples.vpi/vconta1.c
new file mode 100644
index 0000000..b56af5c
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vconta1.c
@@ -0,0 +1,322 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * test of continous assign (decomposition and handle by lookup routines) 
+ *
+ * unit test of various ways to process lavlue expressions
+ * test does nothing
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+#define TRUE 1
+#define FALSE 0
+
+int (*iproc_rtn)();
+
+/* local function prototypes */
+static void process_inst(vpiHandle); 
+static int decompose_expr(vpiHandle, int);
+
+/* global function prototypes */
+extern void register_scan_cb();
+extern int process_contas(vpiHandle);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb(void);
+
+/*
+ * process all instances calling processing routine for each
+ */
+int process_all_insts(struct t_cb_data *cbp)
+{
+ int isiz;
+ vpiHandle topiter, topiref;
+
+ /* build the iterator for each module */
+ topiter = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, topiter);
+ vpi_printf("  There are %d top level modules.\n", isiz);
+ for (;;)
+  {
+   if ((topiref = vpi_scan(topiter)) == NULL) break;
+   process_inst(topiref);
+  }
+ vpi_printf("  >>> All instances processed - continuing with simulation.\n");
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static void process_inst(vpiHandle up_ihref) 
+{
+ int isiz;
+ vpiHandle iter, ihref;
+
+ iproc_rtn(up_ihref);
+ if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return;
+ isiz = vpi_get(vpiSize, iter);
+ vpi_printf("  There are %d instances in %s.\n", isiz,
+  vpi_get_str(vpiFullName, up_ihref));
+ for (;;)
+  {
+   if ((ihref = vpi_scan(iter)) == NULL) break;
+   process_inst(ihref);
+  }
+}
+
+/*
+ * process all continuous assignments
+ */
+int process_contas(vpiHandle ihref)
+{
+ vpiHandle iter, caref, lhsref, rhsref;
+ 
+ if ((iter = vpi_iterate(vpiContAssign, ihref)) == NULL) return(0);
+ for (;;)
+  {
+   if ((caref = vpi_scan(iter)) == NULL) break;
+   lhsref = vpi_handle(vpiLhs, caref); 
+   if (!decompose_expr(lhsref, TRUE))
+    vpi_printf("  Why is concatenate left hand side not lvalue at **%s(%d)\n",  
+     vpi_get_str(vpiFile, caref), vpi_get(vpiLineNo, caref)); 
+
+   rhsref = vpi_handle(vpiRhs, caref); 
+   decompose_expr(rhsref, FALSE);
+  }
+ return(0);
+}
+
+/*
+ * process an expression - build most decomposed handles and print each
+ * also look up names and compare to original handle
+ */
+static int decompose_expr(vpiHandle xref, int islhs)
+{
+ register int i;
+ int xtyp, otyp, bad_lvalue, ps1, ps2, i2;
+ vpiHandle varef, varef2, iter, scopref, ndxref, href, xref2;
+ s_vpi_value tmpval;
+ char nam[1025];
+
+ xtyp = vpi_get(vpiType, xref);
+ /* case 1: all lvalues except concatenate */
+ if (xtyp != vpiOperation && xtyp != vpiConstant)
+  {
+   varef = xref;
+
+   /* get scope for selects, need to get scope from parent */
+   if (xtyp == vpiNetBit || xtyp == vpiRegBit || xtyp == vpiPartSelect)
+    {
+     varef = vpi_handle(vpiParent, varef);
+     scopref = vpi_handle(vpiScope, varef);
+     strcpy(nam, vpi_get_str(vpiName, varef)); 
+    }
+   else
+    {
+     scopref = vpi_handle(vpiScope, varef);
+     /* test handle by name */
+     /* strcpy(nam, vpi_get_str(vpiName, varef)); */ 
+     strcpy(nam, vpi_get_str(vpiName, varef)); 
+    }  
+   
+   /* if ((varef2 = vpi_handle_by_name(nam, NULL)) == NULL) */
+   if ((varef2 = vpi_handle_by_name(nam, scopref)) == NULL)
+    {
+     vpi_printf("--- why is variable %s not in scope %s?\n", nam,
+      vpi_get_str(vpiFullName, scopref));
+     return(TRUE);
+    }
+
+   if (!vpi_compare_objects(varef, varef2))  
+    vpi_printf("--- why did handle by name not return same object (%s)?\n",
+     vpi_get_str(vpiFullName, varef));
+
+   if (xtyp == vpiPartSelect)
+    {
+     ndxref = vpi_handle(vpiLeftRange, xref);
+     tmpval.format = vpiIntVal;
+     vpi_get_value(ndxref, &tmpval);
+     ps1 = tmpval.value.integer;
+     ndxref = vpi_handle(vpiRightRange, xref);
+     tmpval.format = vpiIntVal;
+     vpi_get_value(ndxref, &tmpval);
+     ps2 = tmpval.value.integer;
+     /* notice not normalized to h:0 form */
+     if (ps1 > ps2) { i2 = ps1; ps1 = ps2; ps2 = i2; } 
+     for (i = ps2; i >= ps1; i--)
+      {
+       /* notice must index variable part selected from not part select */
+       href = vpi_handle_by_index(varef, i);
+       ndxref = vpi_handle(vpiIndex, href);
+       tmpval.format = vpiIntVal;
+       vpi_get_value(ndxref, &tmpval);
+       i2 = tmpval.value.integer;
+       if (i2 != i)
+        {
+         vpi_printf(
+          "--- part select index of %s by one method %d and by other %d\n",
+          vpi_get_str(vpiFullName, varef), i2, i);
+        } 
+       else
+        {
+         vpi_printf("  Part select %s index %d processed.\n",
+          vpi_get_str(vpiFullName, varef), i2);
+        }
+      }
+    }
+   else if (xtyp == vpiNetBit || xtyp == vpiRegBit)
+    {
+     ndxref = vpi_handle(vpiIndex, xref);
+     tmpval.format = vpiIntVal;
+     vpi_get_value(ndxref, &tmpval);
+     i = tmpval.value.integer;
+     href = vpi_handle_by_index(varef, i);
+     ndxref = vpi_handle(vpiIndex, href);
+     tmpval.format = vpiIntVal;
+     vpi_get_value(ndxref, &tmpval);
+     i2 = tmpval.value.integer;
+     if (i2 != i)
+      {
+       vpi_printf("--- index of %s by one method %d and by other %d\n",
+        vpi_get_str(vpiFullName, varef));
+      }
+     else
+      {
+       vpi_printf("  Bit select %s index %d processed.\n",
+        vpi_get_str(vpiFullName, varef), i2);
+      }
+    }
+   else vpi_printf("  Variable %s processed.\n",
+    vpi_get_str(vpiFullName, varef), i2);
+   return(TRUE);
+  }
+ /* non lvalue expression just ignore */
+ if (xtyp != vpiOperation) return(FALSE);
+ otyp = vpi_get(vpiOpType, xref); 
+ if (otyp != vpiConcatOp) return(FALSE);
+
+ vpi_printf(" --- processing a concatenate:\n");
+ /* case 2: concatenate - notice use expr. handle not concat operator */
+ iter = vpi_iterate(vpiOperand, xref);
+ for (bad_lvalue = FALSE;;)
+  {
+   if ((xref2 = vpi_scan(iter)) == NULL) break;
+   if (!decompose_expr(xref2, islhs)) bad_lvalue = TRUE;
+  }
+ vpi_printf(" === end of concatenate\n");
+ return(!bad_lvalue);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+ struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = process_all_insts;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+ /* if not registered will be no call backs */
+
+ /* set the processing routine */
+ iproc_rtn = process_contas;
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vconta1.plg b/tests_and_examples/examples.vpi/vconta1.plg
new file mode 100644
index 0000000..04dc11e
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vconta1.plg
@@ -0,0 +1,31 @@
+  There are 1 top level modules.
+ --- processing a concatenate:
+  Part select xx.a index 7 processed.
+  Part select xx.a index 6 processed.
+  Part select xx.a index 5 processed.
+  Part select xx.a index 4 processed.
+  Part select xx.a index 3 processed.
+  Part select xx.a index 2 processed.
+  Variable xx.b processed.
+  Part select xx.c index 9 processed.
+  Part select xx.c index 8 processed.
+  Part select xx.c index 7 processed.
+  Part select xx.c index 6 processed.
+  Part select xx.c index 5 processed.
+  Part select xx.c index 4 processed.
+  Part select xx.c index 3 processed.
+ === end of concatenate
+  Variable xx.w processed.
+  Variable xx.w processed.
+  Variable xx.w_r processed.
+  Variable xx.w processed.
+  Bit select xx.b index 1 processed.
+  Bit select xx.w index 9 processed.
+  >>> All instances processed - continuing with simulation.
+         0 a=zzzzzzzzxxxxxxzz, b=xxxxxxxxxxxxxxxx, c=zzzzzzxxxxxxxzzz, w=xxxxxxxx
+        10 a=zzzzzzzz000000zz, b=0000000000000000, c=zzzzzz0000000zzz, w=00000000
+        20 a=zzzzzzzz111111zz, b=1111111111111111, c=zzzzzz1111111zzz, w=ffffffff
+        30 a=zzzzzzzz010101zz, b=01010101010101x1, c=zzzzzz0101010zzz, w=aaaaaaaa
+        40 a=zzzzzzzz101010zz, b=10101010101010x0, c=zzzzzz1010101zzz, w=55555555
+        50 a=zzzzzzzz111111zz, b=1111111111111111, c=zzzzzz1111111zzz, w=ffffffff
+        60 a=zzzzzzzz000000zz, b=0000000000000000, c=zzzzzz0000000zzz, w=00000000
diff --git a/tests_and_examples/examples.vpi/vdrvld1.c b/tests_and_examples/examples.vpi/vdrvld1.c
new file mode 100644
index 0000000..8cf5380
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vdrvld1.c
@@ -0,0 +1,325 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * print out all drives and loads for wire and regs
+ *
+ * this shows the advantage of type information carrying handles - values
+ * can be printed without knowing much about Verilog constructs
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+int (*iproc_rtn)();
+
+/* local function prototypes */
+static void process_inst(vpiHandle); 
+static void prt_1iter_drvlds(vpiHandle, vpiHandle);
+static void prt_iter(vpiHandle, vpiHandle);
+static void prt_1task_drvlds(vpiHandle);
+
+/* global function prototypes */
+extern int process_all_insts(struct t_cb_data *);
+extern int prt_drvlds(vpiHandle);
+extern int my_prt_vchg();
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb(void);
+
+/*
+ * routine to get and zero all delays in design 
+ */
+int process_all_insts(struct t_cb_data *cbp)
+{
+ int isiz;
+ vpiHandle topiter, topiref;
+
+ /* build the iterator for each module */
+ topiter = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, topiter);
+ vpi_printf("  There are %d top level modules.\n", isiz);
+ for (;;)
+  {
+   if ((topiref = vpi_scan(topiter)) == NULL) break;
+   process_inst(topiref);
+  }
+ vpi_printf("  >>> All instances processed - continuing with simulation.\n");
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static void process_inst(vpiHandle up_ihref) 
+{
+ int isiz;
+ vpiHandle iter, ihref;
+
+ iproc_rtn(up_ihref);
+ if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return;
+ isiz = vpi_get(vpiSize, iter);
+ vpi_printf("  There are %d instances in %s.\n", isiz,
+  vpi_get_str(vpiFullName, up_ihref));
+  for (;;)
+  {
+   if ((ihref = vpi_scan(iter)) == NULL) break;
+   process_inst(ihref);
+  }
+}
+
+/*
+ * print the loads and drivers for all wires in instance ihref
+ */
+int prt_drvlds(vpiHandle ihref)
+{
+ vpiHandle iter, thref;
+ 
+ /* first all instance regs, wires, and variables */ 
+ iter = vpi_iterate(vpiNet, ihref);
+ if (iter != NULL) prt_1iter_drvlds(iter, ihref);
+ iter = vpi_iterate(vpiReg, ihref);
+ if (iter != NULL) prt_1iter_drvlds(iter, ihref);
+ iter = vpi_iterate(vpiVariables, ihref);
+ if (iter != NULL) prt_1iter_drvlds(iter, ihref);
+
+ /* also monitor in scopes */
+ iter = vpi_iterate(vpiInternalScope, ihref);
+ for (;;)
+  {
+   if ((thref = vpi_scan(iter)) == NULL) break;
+   prt_1task_drvlds(thref);
+  }
+ return(0);
+}
+
+/*
+ * print all loads and drivers for nets in iter inside instance ihref
+ *
+ * for task variables ihref will be nil since only needed for ports
+ */
+static void prt_1iter_drvlds(vpiHandle iter, vpiHandle ihref)
+{
+ int ntyp;
+ vpiHandle href, lditer, drviter;
+
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   /* can not pass real variable to load/driver iterator or will get err */  
+   /* bits selects form real illegal in Verilog */
+   if ((ntyp = vpi_get(vpiType, href)) == vpiRealVar) continue;
+
+   /* print the drives and loads for 1 net */ 
+   vpi_printf("... printing drivers and loads for %s:\n", 
+    vpi_get_str(vpiFullName, href));
+
+   lditer = vpi_iterate(vpiLocalLoad, href);
+   if (lditer != NULL)
+    {
+     vpi_printf("  Loads:\n");
+     prt_iter(lditer, ihref);
+    }    
+
+   /* regs can only have loads because in Cver force/assign properties */
+   /* not drivers */
+   if (ntyp != vpiNet && ntyp != vpiNetBit) continue;
+
+   drviter = vpi_iterate(vpiLocalDriver, href);
+   if (drviter != NULL)
+    {
+     vpi_printf("  Drivers:\n");
+     prt_iter(drviter, ihref);
+    }
+
+   lditer = vpi_iterate(vpiPathTerm, href);
+   if (lditer != NULL)
+    {
+     vpi_printf("  Path terminals:\n");
+     prt_iter(lditer, ihref);
+    }
+
+   lditer = vpi_iterate(vpiTchkTerm, href);
+   if (lditer != NULL)
+    {
+     vpi_printf("  Timing check terminals:\n");
+     prt_iter(lditer, ihref);
+    }
+  }
+}
+
+/*
+ * print contents of one loads or drivers iterator iter inside instance ihref
+ * 
+ * when called to print loads of task variables ihref will be nil
+ */
+static void prt_iter(vpiHandle iter, vpiHandle ihref)
+{
+ int htyp;
+ vpiHandle href, portihref;
+ char *chp, s1[1025];
+
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+  
+   htyp = vpi_get(vpiType, href);
+   /* must handle port as special case because can be module port */
+   /* or up instance port connection */
+   if (htyp == vpiModPathIn || htyp == vpiModPathOut) strcpy(s1, "**NONE(0)"); 
+   else
+    {
+     if ((chp = vpi_get_str(vpiFile, href)) == NULL)
+      strcpy(s1, "**NONE(0)"); 
+     else sprintf(s1, "**%s(%d)", chp, vpi_get(vpiLineNo, href));
+    } 
+   if (htyp == vpiPort)
+    {
+     /* if ld/drv net in same instance as port then module port */ 
+     /* else up instance connection */
+     portihref = vpi_handle(vpiModule, href);
+     if (vpi_compare_objects(ihref, portihref))
+      {
+       vpi_printf("   Port (vpiLowConn) object at %s\n", s1);
+      }
+     else
+      {
+       sprintf(s1, "**%s(%d)", vpi_get_str(vpiFile, portihref),
+        vpi_get(vpiLineNo, portihref));
+       vpi_printf("   Port (vpiHighConn) object at %s\n", s1);
+      }
+    }
+   else vpi_printf("    %s object at %s\n", vpi_get_str(vpiType, href), s1);
+  }
+}
+
+/*
+ * print the drivers and loads for one task (should be no drivers?)
+ */
+static void prt_1task_drvlds(vpiHandle thref)
+{
+ vpiHandle iter;
+
+ iter = vpi_iterate(vpiReg, thref);
+ if (iter != NULL) prt_1iter_drvlds(iter, NULL);
+ iter = vpi_iterate(vpiVariables, thref);
+ if (iter != NULL) prt_1iter_drvlds(iter, NULL);
+
+ /* include all contained named blocks */
+ iter = vpi_iterate(vpiInternalScope, thref);
+ for (;;)
+  {
+   if ((thref = vpi_scan(iter)) == NULL) break;
+   prt_1task_drvlds(thref);
+  }
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = process_all_insts;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+ /* if not registered will be no call backs */
+
+ /* set the processing routine */
+ iproc_rtn = prt_drvlds;
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vdrvld1.plg b/tests_and_examples/examples.vpi/vdrvld1.plg
new file mode 100644
index 0000000..3ac7ee2
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vdrvld1.plg
@@ -0,0 +1,278 @@
+**fdspec01.v(105) WARN** [653] $period timing check min:typ:max limit expression needs parentheses under 1364 - unportable
+  There are 1 top level modules.
+... printing drivers and loads for test.t_clr0:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(6)
+... printing drivers and loads for test.t_clr1:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(7)
+... printing drivers and loads for test.t_d0:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(6)
+... printing drivers and loads for test.t_d1:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(7)
+... printing drivers and loads for test.t_q:
+  Drivers:
+   Port (vpiHighConn) object at **fdspec01.v(8)
+... printing drivers and loads for test.t_q0:
+  Drivers:
+   Port (vpiHighConn) object at **fdspec01.v(6)
+... printing drivers and loads for test.t_q1:
+  Drivers:
+   Port (vpiHighConn) object at **fdspec01.v(7)
+... printing drivers and loads for test.t_set0:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(6)
+... printing drivers and loads for test.t_set1:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(7)
+... printing drivers and loads for test.t_clk:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(8)
+... printing drivers and loads for test.t_clk0:
+... printing drivers and loads for test.t_clk1:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(8)
+... printing drivers and loads for test.t_clk2:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(7)
+   Port (vpiHighConn) object at **fdspec01.v(7)
+   Port (vpiHighConn) object at **fdspec01.v(6)
+   Port (vpiHighConn) object at **fdspec01.v(6)
+... printing drivers and loads for test.t_clr:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(8)
+... printing drivers and loads for test.t_d:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(8)
+... printing drivers and loads for test.t_set:
+  Loads:
+   Port (vpiHighConn) object at **fdspec01.v(8)
+  There are 3 instances in test.
+... printing drivers and loads for test.i1.clk:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Path terminals:
+    vpiModPathIn object at **NONE(0)
+  Timing check terminals:
+    vpiTchkTerm object at **fdspec01.v(104)
+    vpiTchkTerm object at **fdspec01.v(104)
+    vpiTchkTerm object at **fdspec01.v(103)
+    vpiTchkTerm object at **fdspec01.v(103)
+    vpiTchkTerm object at **fdspec01.v(101)
+... printing drivers and loads for test.i1.clk1:
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Timing check terminals:
+    vpiTchkTerm object at **fdspec01.v(106)
+... printing drivers and loads for test.i1.clr:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Path terminals:
+    vpiModPathIn object at **NONE(0)
+... printing drivers and loads for test.i1.d:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Timing check terminals:
+    vpiTchkTerm object at **fdspec01.v(107)
+    vpiTchkTerm object at **fdspec01.v(101)
+... printing drivers and loads for test.i1.q:
+  Loads:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Drivers:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Path terminals:
+    vpiModPathOut object at **NONE(0)
+    vpiModPathOut object at **NONE(0)
+... printing drivers and loads for test.i1.set:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Path terminals:
+    vpiModPathIn object at **NONE(0)
+... printing drivers and loads for test.i2.clk:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Path terminals:
+    vpiModPathIn object at **NONE(0)
+  Timing check terminals:
+    vpiTchkTerm object at **fdspec01.v(104)
+    vpiTchkTerm object at **fdspec01.v(104)
+    vpiTchkTerm object at **fdspec01.v(103)
+    vpiTchkTerm object at **fdspec01.v(103)
+    vpiTchkTerm object at **fdspec01.v(101)
+... printing drivers and loads for test.i2.clk1:
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Timing check terminals:
+    vpiTchkTerm object at **fdspec01.v(106)
+... printing drivers and loads for test.i2.clr:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Path terminals:
+    vpiModPathIn object at **NONE(0)
+... printing drivers and loads for test.i2.d:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Timing check terminals:
+    vpiTchkTerm object at **fdspec01.v(107)
+    vpiTchkTerm object at **fdspec01.v(101)
+... printing drivers and loads for test.i2.q:
+  Loads:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Drivers:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Path terminals:
+    vpiModPathOut object at **NONE(0)
+    vpiModPathOut object at **NONE(0)
+... printing drivers and loads for test.i2.set:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Path terminals:
+    vpiModPathIn object at **NONE(0)
+... printing drivers and loads for test.i3.clk:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Path terminals:
+    vpiModPathIn object at **NONE(0)
+  Timing check terminals:
+    vpiTchkTerm object at **fdspec01.v(104)
+    vpiTchkTerm object at **fdspec01.v(104)
+    vpiTchkTerm object at **fdspec01.v(103)
+    vpiTchkTerm object at **fdspec01.v(103)
+    vpiTchkTerm object at **fdspec01.v(101)
+... printing drivers and loads for test.i3.clk1:
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Timing check terminals:
+    vpiTchkTerm object at **fdspec01.v(106)
+... printing drivers and loads for test.i3.clr:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Path terminals:
+    vpiModPathIn object at **NONE(0)
+... printing drivers and loads for test.i3.d:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Timing check terminals:
+    vpiTchkTerm object at **fdspec01.v(107)
+    vpiTchkTerm object at **fdspec01.v(101)
+... printing drivers and loads for test.i3.q:
+  Loads:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Drivers:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Path terminals:
+    vpiModPathOut object at **NONE(0)
+    vpiModPathOut object at **NONE(0)
+... printing drivers and loads for test.i3.set:
+  Loads:
+    vpiPrimTerm object at **fdspec01.v(110)
+  Drivers:
+   Port (vpiLowConn) object at **fdspec01.v(76)
+  Path terminals:
+    vpiModPathIn object at **NONE(0)
+  >>> All instances processed - continuing with simulation.
+         0 q=x, clk=x, data=x, clr=x, set=x
+testing set/clear logic
+      2000 q=x, clk=x, data=x, clr=x, set=0
+      2040 q=1, clk=x, data=x, clr=x, set=0
+      3000 q=1, clk=x, data=x, clr=0, set=0
+      4000 q=1, clk=x, data=x, clr=0, set=1
+      4050 q=0, clk=x, data=x, clr=0, set=1
+      5000 q=0, clk=x, data=x, clr=0, set=0
+      5040 q=1, clk=x, data=x, clr=0, set=0
+      6000 q=1, clk=x, data=x, clr=0, set=1
+      6050 q=0, clk=x, data=x, clr=0, set=1
+      7000 q=0, clk=x, data=x, clr=x, set=1
+      7040 q=x, clk=x, data=x, clr=x, set=1
+testing normal logic
+      8000 q=x, clk=x, data=0, clr=1, set=1
+      9000 q=x, clk=1, data=0, clr=1, set=1
+     10000 q=x, clk=0, data=0, clr=1, set=1
+     11000 q=x, clk=1, data=0, clr=1, set=1
+     11250 q=0, clk=1, data=0, clr=1, set=1
+     12000 q=0, clk=0, data=0, clr=1, set=1
+     13000 q=0, clk=1, data=0, clr=1, set=1
+     14000 q=0, clk=0, data=0, clr=1, set=1
+     15000 q=0, clk=x, data=0, clr=1, set=1
+     16000 q=0, clk=0, data=0, clr=1, set=1
+     17000 q=0, clk=z, data=0, clr=1, set=1
+     18000 q=0, clk=0, data=0, clr=1, set=1
+     19000 q=0, clk=x, data=0, clr=1, set=1
+**fdspec01.v(105) WARN** now 20000 [566] timing violation in test.i3 (diff. 1000)
+ $period((posedge clk):19000, (posedge clk):20000, 1200);
+     20000 q=0, clk=1, data=0, clr=1, set=1
+     21000 q=0, clk=1, data=1, clr=1, set=1
+     22000 q=0, clk=0, data=1, clr=1, set=1
+     23000 q=0, clk=1, data=1, clr=1, set=1
+     23140 q=1, clk=1, data=1, clr=1, set=1
+     24000 q=1, clk=0, data=1, clr=1, set=1
+     25000 q=1, clk=1, data=1, clr=1, set=1
+     26000 q=1, clk=0, data=1, clr=1, set=1
+**fdspec01.v(105) WARN** now 26100 [566] timing violation in test.i3 (diff. 1100)
+ $period((posedge clk):25000, (posedge clk):26100, 1200);
+**fdspec01.v(104) WARN** now 26100 [566] timing violation in test.i3 (diff. 100)
+ $width((negedge clk):26000, (posedge clk):26100, 500);
+     26100 q=1, clk=x, data=1, clr=1, set=1
+     27100 q=1, clk=0, data=1, clr=1, set=1
+     28100 q=1, clk=z, data=1, clr=1, set=1
+     29100 q=1, clk=0, data=1, clr=1, set=1
+     30100 q=1, clk=x, data=1, clr=1, set=1
+**fdspec01.v(105) WARN** now 31100 [566] timing violation in test.i3 (diff. 1000)
+ $period((posedge clk):30100, (posedge clk):31100, 1200);
+     31100 q=1, clk=1, data=1, clr=1, set=1
+**fdspec01.v(103) WARN** now 31130 [566] timing violation in test.i3 (diff. 30)
+ $width((posedge clk):31100, (negedge clk):31130, 600);
+     31130 q=1, clk=0, data=1, clr=1, set=1
+**fdspec01.v(105) WARN** now 31190 [566] timing violation in test.i3 (diff. 90)
+ $period((posedge clk):31100, (posedge clk):31190, 1200);
+**fdspec01.v(104) WARN** now 31190 [566] timing violation in test.i3 (diff. 60)
+ $width((negedge clk):31130, (posedge clk):31190, 500);
+     31190 q=1, clk=1, data=1, clr=1, set=1
+**fdspec01.v(101) WARN** now 31220 [566] timing violation in test.i3 (diff. 30)
+ hold(of setuphold)((posedge clk):31190, d:31220, 50);
+     31220 q=1, clk=1, data=0, clr=1, set=1
+**fdspec01.v(103) WARN** now 31250 [566] timing violation in test.i3 (diff. 60)
+ $width((posedge clk):31190, (negedge clk):31250, 600);
+     31250 q=1, clk=0, data=0, clr=1, set=1
+     31280 q=1, clk=0, data=1, clr=1, set=1
+**fdspec01.v(107) WARN** now 31310 [566] timing violation in test.i3 (diff. 30)
+ $recovery((posedge d):31280, clk:31310, 200);
+**fdspec01.v(105) WARN** now 31310 [566] timing violation in test.i3 (diff. 120)
+ $period((posedge clk):31190, (posedge clk):31310, 1200);
+**fdspec01.v(104) WARN** now 31310 [566] timing violation in test.i3 (diff. 60)
+ $width((negedge clk):31250, (posedge clk):31310, 500);
+**fdspec01.v(101) WARN** now 31310 [566] timing violation in test.i3 (diff. 30)
+ setup(of setuphold)(d:31280, (posedge clk):31310, 70);
+     31310 q=1, clk=1, data=1, clr=1, set=1
+**fdspec01.v(107) WARN** now 31410 [566] timing violation in test.i3 (diff. 130)
+ $recovery((posedge d):31280, clk:31410, 200);
+**fdspec01.v(103) WARN** now 31410 [566] timing violation in test.i3 (diff. 100)
+ $width((posedge clk):31310, (negedge clk):31410, 600);
+     31410 q=1, clk=0, data=1, clr=1, set=1
+**fdspec01.v(106) WARN** now 33510 [566] timing violation in test.i3 (diff. 2000)
+ $skew((posedge clk1):31510, (posedge clk):33510, 50);
+     33510 q=1, clk=1, data=1, clr=1, set=1
diff --git a/tests_and_examples/examples.vpi/vdrvld2.c b/tests_and_examples/examples.vpi/vdrvld2.c
new file mode 100644
index 0000000..fdd0060
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vdrvld2.c
@@ -0,0 +1,341 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * print out all drives and loads for wire and regs
+ *
+ * this shows the advantage of type information carrying handles - values
+ * can be printed without knowing much about Verilog constructs
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+int (*iproc_rtn)();
+
+/* local function prototypes */
+static void process_inst(vpiHandle); 
+static void prt_1iter_drvlds(vpiHandle, vpiHandle);
+static void prt_iter(vpiHandle, vpiHandle);
+static void prt_1task_drvlds(vpiHandle);
+
+/* global function prototypes */
+extern int my_prt_vchg();
+extern int prt_drvlds(vpiHandle);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb(void);
+
+/*
+ * routine to get and zero all delays in design 
+ */
+int process_all_insts(struct t_cb_data *cbp)
+{
+ int isiz;
+ vpiHandle topiter, topiref;
+
+ /* build the iterator for each module */
+ topiter = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, topiter);
+ vpi_printf("  There are %d top level modules.\n", isiz);
+ for (;;)
+  {
+   if ((topiref = vpi_scan(topiter)) == NULL) break;
+   process_inst(topiref);
+  }
+ vpi_printf("  >>> All instances processed - continuing with simulation.\n");
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static void process_inst(vpiHandle up_ihref) 
+{
+ int isiz;
+ vpiHandle iter, ihref;
+
+ iproc_rtn(up_ihref);
+ if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return;
+ isiz = vpi_get(vpiSize, iter);
+ vpi_printf("  There are %d instances in %s.\n", isiz,
+  vpi_get_str(vpiFullName, up_ihref));
+  for (;;)
+  {
+   if ((ihref = vpi_scan(iter)) == NULL) break;
+   process_inst(ihref);
+  }
+}
+
+/*
+ * print the loads and drivers for all nets in instance ihref
+ */
+int prt_drvlds(vpiHandle ihref)
+{
+ vpiHandle iter, thref;
+ 
+ /* first all instance regs, wires, and variables */ 
+ iter = vpi_iterate(vpiNet, ihref);
+ if (iter != NULL) prt_1iter_drvlds(iter, ihref);
+ iter = vpi_iterate(vpiReg, ihref);
+ if (iter != NULL) prt_1iter_drvlds(iter, ihref);
+ iter = vpi_iterate(vpiVariables, ihref);
+ if (iter != NULL) prt_1iter_drvlds(iter, ihref);
+
+ /* also monitor in scopes */
+ iter = vpi_iterate(vpiInternalScope, ihref);
+ for (;;)
+  {
+   if ((thref = vpi_scan(iter)) == NULL) break;
+   prt_1task_drvlds(thref);
+  }
+ return(0);
+}
+
+/*
+ * print all loads and drivers for nets in one iterator
+ */
+static void prt_1iter_drvlds(vpiHandle iter, vpiHandle ihref)
+{
+ register int bi;
+ int ntyp;
+ vpiHandle href, bref, bititer, lditer, drviter, ndxref;
+ s_vpi_value tmpval;
+
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   /* can not pass real variable to load/driver iterator or will get err */  
+   /* bits selects form real illegal in Verilog */
+   if ((ntyp = vpi_get(vpiType, href)) == vpiRealVar) continue;
+
+   /* for this test ignore scalars */
+   if (vpi_get(vpiScalar, href)) continue; 
+
+   /* should never be nil */
+   if ((bititer = vpi_iterate(vpiBit, href)) == NULL) continue;
+   for (;;)
+    {
+     if ((bref = vpi_scan(bititer)) == NULL) break;
+     
+     ndxref = vpi_handle(vpiIndex, bref);
+     tmpval.format = vpiIntVal;
+     /* need to evalate expr. even though since from iter know constant */
+     vpi_get_value(ndxref, &tmpval);
+     bi = tmpval.value.integer;
+
+     /* print the drives and loads for 1 net */ 
+     vpi_printf("... printing drivers and loads for %s[%d]:\n", 
+      vpi_get_str(vpiFullName, bref), bi);
+
+     lditer = vpi_iterate(vpiLocalLoad, bref);
+     if (lditer != NULL)
+      {
+       vpi_printf("  Loads:\n");
+       prt_iter(lditer, ihref);
+      }    
+
+     /* regs can only have loads because in Cver force/assign properties */
+     /* not drivers */
+     if (ntyp != vpiNetBit) continue;
+  
+     drviter = vpi_iterate(vpiLocalDriver, bref);
+     if (drviter != NULL)
+      {
+       vpi_printf("  Drivers:\n");
+       prt_iter(drviter, ihref);
+      }
+
+     lditer = vpi_iterate(vpiPathTerm, bref);
+     if (lditer != NULL)
+      {
+       vpi_printf("  Path terminals:\n");
+       prt_iter(lditer, ihref);
+      }
+
+     lditer = vpi_iterate(vpiTchkTerm, bref);
+     if (lditer != NULL)
+      {
+       vpi_printf("  Timing check terminals:\n");
+       prt_iter(lditer, ihref);
+      }
+    }
+  }
+}
+
+/*
+ * print contents of one iterator (any? non NULL)
+ */
+static void prt_iter(vpiHandle iter, vpiHandle ihref)
+{
+ int htyp;
+ vpiHandle href, portihref;
+ char *chp, s1[1025];
+
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+  
+   htyp = vpi_get(vpiType, href);
+   /* must handle port as special case because can be module port */
+   /* or up instance port connection */
+   if (htyp == vpiModPathIn || htyp == vpiModPathOut) strcpy(s1, "**NONE(0)"); 
+   else
+    {
+     if ((chp = vpi_get_str(vpiFile, href)) == NULL)
+      strcpy(s1, "**NONE(0)"); 
+     else sprintf(s1, "**%s(%d)", chp, vpi_get(vpiLineNo, href));
+    } 
+   if (htyp == vpiPort)
+    {
+     /* if ld/drv net in same instance as port then module port */ 
+     /* else up instance connection */
+     portihref = vpi_handle(vpiModule, href);
+     if (vpi_compare_objects(ihref, portihref))
+      {
+       vpi_printf("   Port (vpiLowConn) object at %s\n", s1);
+      }
+     else
+      {
+       sprintf(s1, "**%s(%d)", vpi_get_str(vpiFile, portihref),
+        vpi_get(vpiLineNo, portihref));
+       vpi_printf("   Port (vpiHighConn) object at %s\n", s1);
+      }
+    }
+   else vpi_printf("    %s object at %s\n", vpi_get_str(vpiType, href), s1);
+  }
+}
+
+/*
+ * print the drivers and loads for one task (should be no drivers?)
+ *
+ * drive and load print iterator routines passed nil instance context
+ * because only needed for ports that are impossible in tasks
+ */
+static void prt_1task_drvlds(vpiHandle thref)
+{
+ vpiHandle iter;
+
+ iter = vpi_iterate(vpiReg, NULL);
+ if (iter != NULL) prt_1iter_drvlds(iter, NULL);
+ iter = vpi_iterate(vpiVariables, thref);
+ if (iter != NULL) prt_1iter_drvlds(iter, NULL);
+
+ /* include all contained named blocks */
+ iter = vpi_iterate(vpiInternalScope, thref);
+ for (;;)
+  {
+   if ((thref = vpi_scan(iter)) == NULL) break;
+   prt_1task_drvlds(thref);
+  }
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = process_all_insts;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+ /* if not registered will be no call backs */
+
+ /* set the processing routine */
+ iproc_rtn = prt_drvlds;
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vdrvld2.plg b/tests_and_examples/examples.vpi/vdrvld2.plg
new file mode 100644
index 0000000..4fb7f92
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vdrvld2.plg
@@ -0,0 +1,250 @@
+  There are 1 top level modules.
+... printing drivers and loads for xx.a[15]:
+... printing drivers and loads for xx.a[14]:
+... printing drivers and loads for xx.a[13]:
+... printing drivers and loads for xx.a[12]:
+... printing drivers and loads for xx.a[11]:
+... printing drivers and loads for xx.a[10]:
+... printing drivers and loads for xx.a[9]:
+... printing drivers and loads for xx.a[8]:
+... printing drivers and loads for xx.a[7]:
+... printing drivers and loads for xx.a[6]:
+... printing drivers and loads for xx.a[5]:
+... printing drivers and loads for xx.a[4]:
+... printing drivers and loads for xx.a[3]:
+... printing drivers and loads for xx.a[2]:
+... printing drivers and loads for xx.a[1]:
+... printing drivers and loads for xx.a[0]:
+... printing drivers and loads for xx.b[15]:
+... printing drivers and loads for xx.b[14]:
+... printing drivers and loads for xx.b[13]:
+... printing drivers and loads for xx.b[12]:
+... printing drivers and loads for xx.b[11]:
+... printing drivers and loads for xx.b[10]:
+... printing drivers and loads for xx.b[9]:
+... printing drivers and loads for xx.b[8]:
+... printing drivers and loads for xx.b[7]:
+... printing drivers and loads for xx.b[6]:
+... printing drivers and loads for xx.b[5]:
+... printing drivers and loads for xx.b[4]:
+... printing drivers and loads for xx.b[3]:
+... printing drivers and loads for xx.b[2]:
+... printing drivers and loads for xx.b[1]:
+... printing drivers and loads for xx.b[0]:
+... printing drivers and loads for xx.c[15]:
+... printing drivers and loads for xx.c[14]:
+... printing drivers and loads for xx.c[13]:
+... printing drivers and loads for xx.c[12]:
+... printing drivers and loads for xx.c[11]:
+... printing drivers and loads for xx.c[10]:
+... printing drivers and loads for xx.c[9]:
+... printing drivers and loads for xx.c[8]:
+... printing drivers and loads for xx.c[7]:
+... printing drivers and loads for xx.c[6]:
+... printing drivers and loads for xx.c[5]:
+... printing drivers and loads for xx.c[4]:
+... printing drivers and loads for xx.c[3]:
+... printing drivers and loads for xx.c[2]:
+... printing drivers and loads for xx.c[1]:
+... printing drivers and loads for xx.c[0]:
+... printing drivers and loads for xx.w[31]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[30]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[29]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[28]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[27]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[26]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[25]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[24]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[23]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[22]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[21]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[20]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[19]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[18]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[17]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[16]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[15]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[14]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[13]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[12]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[11]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[10]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[9]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+    vpiContAssign object at **cacatmd1.v(9)
+... printing drivers and loads for xx.w[8]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[7]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[6]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[5]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[4]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[3]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[2]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[1]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w[0]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(6)
+... printing drivers and loads for xx.w_r[31]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[30]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[29]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[28]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[27]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[26]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[25]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[24]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[23]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[22]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[21]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[20]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[19]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[18]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[17]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[16]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[15]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[14]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[13]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[12]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[11]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[10]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[9]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[8]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[7]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[6]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[5]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[4]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[3]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[2]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[1]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+... printing drivers and loads for xx.w_r[0]:
+  Loads:
+    vpiContAssign object at **cacatmd1.v(7)
+  >>> All instances processed - continuing with simulation.
+         0 a=zzzzzzzzxxxxxxzz, b=xxxxxxxxxxxxxxxx, c=zzzzzzxxxxxxxzzz, w=xxxxxxxx
+        10 a=zzzzzzzz000000zz, b=0000000000000000, c=zzzzzz0000000zzz, w=00000000
+        20 a=zzzzzzzz111111zz, b=1111111111111111, c=zzzzzz1111111zzz, w=ffffffff
+        30 a=zzzzzzzz010101zz, b=01010101010101x1, c=zzzzzz0101010zzz, w=aaaaaaaa
+        40 a=zzzzzzzz101010zz, b=10101010101010x0, c=zzzzzz1010101zzz, w=55555555
+        50 a=zzzzzzzz111111zz, b=1111111111111111, c=zzzzzz1111111zzz, w=ffffffff
+        60 a=zzzzzzzz000000zz, b=0000000000000000, c=zzzzzz0000000zzz, w=00000000
diff --git a/tests_and_examples/examples.vpi/vfopen1.c b/tests_and_examples/examples.vpi/vfopen1.c
new file mode 100644
index 0000000..e88db01
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vfopen1.c
@@ -0,0 +1,162 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/* implement Verilog $fopen using PLI 2.0 vpi_ routines */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+
+/* local function prototypes */
+
+/* global function prototypes */
+extern int vpi_fopen(void);
+extern int fopensiz(void);
+int my_error_handler(struct t_cb_data *);
+extern void register_my_systfs(void); 
+
+/*
+ * ignore the user data field
+ */
+int vpi_fopen(void)
+{
+ unsigned int mcd;
+ vpiHandle href, iter, aref;
+ struct t_vpi_value valrec;
+ s_vpi_value tmpval;
+
+ valrec.format = vpiIntVal;
+
+ valrec.value.integer = (int) 0; 
+
+ href = vpi_handle(vpiSysTfCall, NULL); 
+ /* if error after here will return 0 */
+ vpi_put_value(href, &valrec, NULL, vpiNoDelay);
+
+ if ((iter = vpi_iterate(vpiArgument, href)) == NULL) return(0);
+ if (vpi_get(vpiSize, iter) != 1) return(0);
+
+ if ((aref = vpi_scan(iter)) == NULL) return(0);
+
+ tmpval.format = vpiStringVal;
+ /* evaluate expression */
+ vpi_get_value(aref, &tmpval);
+
+ mcd = vpi_mcd_open(tmpval.value.str);
+ if (mcd != 0) valrec.value.integer = (int) mcd;
+ vpi_put_value(href, &valrec, NULL, vpiNoDelay);
+ return(0);
+}
+
+/*
+ * fopen return 32 bit size (unsigned) mcd descriptor word
+ */
+int fopensiz(void)
+{
+ return(32);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiSystem || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ /* will just return and leave 0 in vpi_fopen return value */
+ return(0);
+}
+
+/*
+ * register call backs
+ */
+void register_cbs(void)
+{
+ vpiHandle href;
+ struct t_cb_data *ecbp;
+ struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+}
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register system tasks */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_my_systfs, 
+ register_cbs, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf registering is done here */
+
+/*
+ * register all vpi_ PLI 2.0 style user system tasks and functions
+ */
+void register_my_systfs()
+{
+ p_vpi_systf_data systf_data_p;
+
+ /* use predefined table form - could fill systf_data_list dynamically */
+ static s_vpi_systf_data systf_data_list[] = {
+  { vpiSysFunc, vpiSizedFunc, "$vpi_fopen", vpi_fopen, NULL, fopensiz, NULL },
+  { 0, 0, NULL, NULL, NULL, NULL, NULL }
+ };
+
+ systf_data_p = &(systf_data_list[0]);
+ while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vfopen1.plg b/tests_and_examples/examples.vpi/vfopen1.plg
new file mode 100644
index 0000000..1ec6d62
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vfopen1.plg
@@ -0,0 +1,2 @@
+... writing to file vpifout.fil.
+tmp_channel           4
diff --git a/tests_and_examples/examples.vpi/vfopen1.v b/tests_and_examples/examples.vpi/vfopen1.v
new file mode 100644
index 0000000..154437f
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vfopen1.v
@@ -0,0 +1,25 @@
+module test;
+
+reg		clk;
+
+integer         tmp_channel;
+    initial
+      begin
+	clk = 0;
+
+	#2000 tmp_channel = $vpi_fopen("vpifout.fil");
+        $display("... writing to file vpifout.fil.");
+	$fdisplay(tmp_channel | 5,"tmp_channel %d",tmp_channel);
+	$fclose(tmp_channel);	
+
+	#4000 $finish;
+
+      end
+
+  always
+    begin
+      #1000 clk = ~clk;
+    end
+
+endmodule
+
diff --git a/tests_and_examples/examples.vpi/vfopen2.c b/tests_and_examples/examples.vpi/vfopen2.c
new file mode 100644
index 0000000..bbfbae4
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vfopen2.c
@@ -0,0 +1,161 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/* implement Verilog $fopen using PLI 2.0 vpi_ routines */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* local function prototypes */
+
+/* global function prototypes */
+extern int vpi_fopen_task(void);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_cbs(void);
+extern void register_my_systfs(void); 
+
+/*
+ * ignore the user data field
+ * this needs error messages
+ */
+int vpi_fopen_task(void)
+{
+ int mcdhtyp;
+ unsigned int mcd;
+ vpiHandle href, iter, a1ref, a2ref;
+ struct t_vpi_value valrec;
+ struct t_vpi_time tmptim;
+ s_vpi_value tmpval;
+
+ href = vpi_handle(vpiSysTfCall, NULL); 
+ if ((iter = vpi_iterate(vpiArgument, href)) == NULL) return(0);
+ if (vpi_get(vpiSize, iter) != 2) return(0);
+
+ if ((a1ref = vpi_scan(iter)) == NULL) return(0);
+ /* get the 2nd argument vpiReg handle */
+ if ((a2ref = vpi_scan(iter)) == NULL) return(0);
+ mcdhtyp = vpi_get(vpiType, a2ref);
+ if ((mcdhtyp != vpiReg && mcdhtyp != vpiIntegerVar)
+  || vpi_get(vpiSize, a2ref) != 32) return(0);
+ 
+ valrec.format = vpiIntVal;
+ valrec.value.integer = (int) 0; 
+ /* if error after here will return 0 */
+ vpi_put_value(a2ref, &valrec, NULL, vpiNoDelay);
+
+ tmpval.format = vpiStringVal;
+ /* evaluate expression */
+ vpi_get_value(a1ref, &tmpval);
+
+ mcd = vpi_mcd_open(tmpval.value.str);
+ if (mcd != 0) valrec.value.integer = (int) mcd;
+ /* Changed in 1.52 to allow NULL for ignored time field */
+ tmptim.type = vpiSuppressTime;
+ vpi_put_value(a2ref, &valrec, &tmptim, vpiNoDelay);
+ return(0);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiSystem || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ /* will just return and leave 0 in vpi_fopen return 2nd argument */
+ return(0);
+}
+
+/*
+ * register call backs
+ */
+void register_cbs(void)
+{
+ vpiHandle href;
+ struct t_cb_data *ecbp;
+ struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+}
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register system tasks */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_my_systfs, 
+ register_cbs, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf registering is done here */
+
+/*
+ * register all vpi_ PLI 2.0 style user system tasks and functions
+ */
+void register_my_systfs(void)
+{
+ p_vpi_systf_data systf_data_p;
+
+ /* use predefined table form - could fill systf_data_list dynamically */
+ static s_vpi_systf_data systf_data_list[] = {
+  { vpiSysTask, 0, "$vpi_fopen_task", vpi_fopen_task, NULL, NULL },
+  { 0, 0, NULL, NULL, NULL, NULL, NULL }
+ };
+
+ systf_data_p = &(systf_data_list[0]);
+ while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vfopen2.plg b/tests_and_examples/examples.vpi/vfopen2.plg
new file mode 100644
index 0000000..a098a56
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vfopen2.plg
@@ -0,0 +1,2 @@
+writing to vpitout.fil.
+tmp_channel           4
diff --git a/tests_and_examples/examples.vpi/vfopen2.v b/tests_and_examples/examples.vpi/vfopen2.v
new file mode 100644
index 0000000..78dd8be
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vfopen2.v
@@ -0,0 +1,25 @@
+module test;
+
+reg		clk;
+
+integer         tmp_channel;
+    initial
+      begin
+	clk = 0;
+
+	#2000 $vpi_fopen_task("vpitout.fil", tmp_channel);
+        $display("writing to vpitout.fil.");
+	$fdisplay(tmp_channel | 5,"tmp_channel %d",tmp_channel);
+	$fclose(tmp_channel);	
+
+	#4000 $finish;
+
+      end
+
+  always
+    begin
+      #1000 clk = ~clk;
+    end
+
+endmodule
+
diff --git a/tests_and_examples/examples.vpi/vhelbad.c b/tests_and_examples/examples.vpi/vhelbad.c
new file mode 100644
index 0000000..566fb6f
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vhelbad.c
@@ -0,0 +1,174 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/* version of hello that does not work */
+/* shows problem with tf_ style checking in vpi_ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* local prototypes */
+static void prtvpiemsg(struct t_vpi_error_info *);
+static int count_systf_args(vpiHandle);
+
+/* global prototypes */
+extern PLI_INT32 hello_setup(char *);
+extern PLI_INT32 hello_chk(struct t_cb_data *);
+extern void register_my_systfs(void); 
+
+/*
+ * possible pattern for register vpi_ system tasks and functions
+ */
+
+/*
+ * this is routine to implement registered systf call back
+ *
+ * notice vpi_user.h requires function return int so using dummy 0
+ */
+PLI_INT32 hello(void)
+{
+ vpi_printf("hello world\n");
+ return(0);
+}
+
+/*
+ * check each hello call, in struct as short but passed as int 
+ *
+ * dynamic nature of PLI 2.0 requires checking just before simulation 
+ * because need to wait until simulation data structure is built
+ */
+PLI_INT32 hello_setup(char *data)
+{
+ vpiHandle href;
+ struct t_cb_data *cbp;
+ struct t_cb_data cbrec;
+ 
+ vpi_printf("... executing vpi_ systf compiletf routine.\n");
+ cbp = &cbrec;
+ cbp->reason = cbEndOfCompile;
+ cbp->cb_rtn = hello_chk;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: $hello PLI 2.0 task cannot register end of compile check routine");
+ /* if not registered will be no call backs */
+ return(0);
+}
+
+/*
+ * check - must be at end of compile after sim data structure set up
+ */
+PLI_INT32 hello_chk(struct t_cb_data *cbp)
+{
+ vpiHandle href, iref;
+ struct t_vpi_error_info einfotab;
+
+ vpi_printf("... executing EndOfCompile callback for checking.\n");
+ href = vpi_handle(vpiSysTfCall, NULL); 
+ if (vpi_chk_error(&einfotab))
+  {  
+   if (href != NULL) vpi_printf("... why is handle not nil\n"); 
+   vpi_printf("** ERR: $hello PLI 2.0 can not access systf call handle\n");
+   prtvpiemsg(&einfotab);
+   /* vpi_sim_control(vpiFinish, 0); */
+  }
+ iref = vpi_iterate(vpiArgument, href);
+ if (vpi_chk_error(&einfotab))
+  {
+   vpi_printf("** ERR: vpi_iterate error:\n");
+   prtvpiemsg(&einfotab);
+   vpi_sim_control(vpiFinish, 0);
+  }
+ if (iref != NULL) 
+  { 
+   vpi_printf(
+    "** ERR: $hello PLI 2.0 task called with %d arguments but none allowed",
+    count_systf_args(iref));
+   vpi_free_object(iref);
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+static void prtvpiemsg(struct t_vpi_error_info *einfop)
+{
+ char s1[128];
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("%s: %s error (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+}
+
+/*
+ * count arguments
+ */
+static int count_systf_args(vpiHandle iref)
+{
+ int anum = 0;
+
+ while (vpi_scan(iref) != NULL) anum++;
+ return(anum);
+}
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register system tasks */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_my_systfs, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf registering is done here */
+
+/*
+ * register all vpi_ PLI 2.0 style user system tasks and functions
+ */
+void register_my_systfs(void)
+{
+ p_vpi_systf_data systf_data_p;
+
+ /* use predefined table form - could fill systf_data_list dynamically */
+ static s_vpi_systf_data systf_data_list[] = {
+  { vpiSysTask, 0, "$hello", hello, hello_setup, NULL, NULL },
+  { 0, 0, NULL, NULL, NULL, NULL, NULL }
+ };
+
+ systf_data_p = &(systf_data_list[0]);
+ while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vhelbad.plg b/tests_and_examples/examples.vpi/vhelbad.plg
new file mode 100644
index 0000000..c1c76ea
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vhelbad.plg
@@ -0,0 +1,8 @@
+... executing vpi_ systf compiletf routine.
+... executing EndOfCompile callback for checking.
+** ERR: $hello PLI 2.0 can not access systf call handle
+1840: vpiPLI error (level 3) at ***none*(0):
+  vpi_handle with vpiSysTfCall not called from inside vpi_ systf callback
+** ERR: vpi_iterate error:
+1854: vpiPLI error (level 3) at ***none*(0):
+  vpi_iterate type vpiArgument passed illegal NULL handle
diff --git a/tests_and_examples/examples.vpi/vhelbad.v b/tests_and_examples/examples.vpi/vhelbad.v
new file mode 100644
index 0000000..f6c7957
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vhelbad.v
@@ -0,0 +1,12 @@
+module xx;
+ integer i;
+ real r;
+
+ initial
+  begin
+   $hello(3);
+   i = $stime;
+   /* r = $realfhello; */
+   $display("done with PLI 2.0 calls returned i=%0d and r=%0g", i, r);
+  end
+endmodule
diff --git a/tests_and_examples/examples.vpi/vhello1.c b/tests_and_examples/examples.vpi/vhello1.c
new file mode 100644
index 0000000..d615992
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vhello1.c
@@ -0,0 +1,110 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/* simple hello world pli 2.0 task */
+/* this is simplest vpi_ 2.0 style c program */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+#define TRUE 1
+#define FALSE 0
+
+/* local prototypes */
+static int count_systf_args(vpiHandle);
+
+/* global prototypes */
+PLI_INT32 hello(void);
+extern void register_my_systfs(void); 
+extern void register_my_systfs(void);
+
+/*
+ * possible pattern for register vpi_ system tasks and functions
+ */
+
+/*
+ * this is routine to implement registered systf call back
+ *
+ * notice vpi_user.h requires function return int so using dummy 0
+ */
+PLI_INT32 hello(void)
+{
+ vpiHandle href, iref;
+
+ href = vpi_handle(vpiSysTfCall, NULL); 
+ if (href == NULL) 
+  {
+   vpi_printf("** ERR: $hello PLI 2.0 can not access systf call handle\n");
+   return(0);
+  }
+ if ((iref = vpi_iterate(vpiArgument, href)) != NULL)
+  { 
+   vpi_printf(
+    "**ERR: $hello PLI 2.0 task called with %d arguments but none allowed\n",
+    count_systf_args(iref));
+   return(0);
+  }
+ vpi_printf("hello world\n");
+ return(0);
+}
+
+/*
+ * count arguments
+ */
+static int count_systf_args(vpiHandle iref)
+{
+ int anum = 0;
+
+ while (vpi_scan(iref) != NULL) anum++;
+ return(anum);
+}
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register system tasks */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_my_systfs, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf registering is done here */
+
+/*
+ * register all vpi_ PLI 2.0 style user system tasks and functions
+ */
+void register_my_systfs(void)
+{
+ p_vpi_systf_data systf_data_p;
+
+ /* use predefined table form - could fill systf_data_list dynamically */
+ static s_vpi_systf_data systf_data_list[] = {
+  { vpiSysTask, 0, "$hello", hello, NULL, NULL, NULL },
+  { 0, 0, NULL, NULL, NULL, NULL, NULL }
+ };
+
+ systf_data_p = &(systf_data_list[0]);
+ while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vhello1.plg b/tests_and_examples/examples.vpi/vhello1.plg
new file mode 100644
index 0000000..f5d0c06
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vhello1.plg
@@ -0,0 +1,3 @@
+hello world
+**ERR: $hello PLI 2.0 task called with 1 arguments but none allowed
+done with PLI 2.0 calls returned i=0 and r=0
diff --git a/tests_and_examples/examples.vpi/vhello1.v b/tests_and_examples/examples.vpi/vhello1.v
new file mode 100644
index 0000000..2a2c053
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vhello1.v
@@ -0,0 +1,12 @@
+module xx;
+ integer i;
+ real r;
+
+ initial
+  begin
+   $hello;
+   i = $stime;
+   $hello(i);
+   $display("done with PLI 2.0 calls returned i=%0d and r=%0g", i, r);
+  end
+endmodule
diff --git a/tests_and_examples/examples.vpi/vhello2.c b/tests_and_examples/examples.vpi/vhello2.c
new file mode 100644
index 0000000..0a7265b
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vhello2.c
@@ -0,0 +1,210 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/* simple hello world pli 2.0 task and real function */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* local prototypes */
+static void print_systfs(void);
+static int count_systf_args(vpiHandle);
+static void vpiset_to_real(vpiHandle, double);
+static void prtvpiemsg(struct t_vpi_error_info *);
+
+/* global prototypes */
+extern PLI_INT32 hello(void);
+extern void register_my_systfs(void); 
+
+/*
+ * this is routine to implement registered systf call back
+ *
+ * notice vpi_user.h requires function return int so using dummy 0
+ */
+PLI_INT32 hello(void)
+{
+ vpiHandle href, iref;
+
+ /* quick test of systf iterator */
+ print_systfs();
+
+ href = vpi_handle(vpiSysTfCall, NULL); 
+ if (href == NULL) 
+  {
+   vpi_printf("**ERR: $hello PLI 2.0 task registeration problem\n");
+   return(0);
+  }
+ if ((iref = vpi_iterate(vpiArgument, href)) != NULL)
+  { 
+   vpi_printf(
+    "**ERR: $hello PLI 2.0 task called with %d arguments but none allowed\n",
+    count_systf_args(iref));
+   return(0);
+  }
+ vpi_printf("hello world\n");
+ return(0);
+}
+
+/*
+ * print a list of register systf routines
+ */
+static void print_systfs(void)
+{
+ vpiHandle iter, tfref; 
+ s_vpi_systf_data systf_inf;
+ p_vpi_systf_data tfinfp;
+
+ vpi_printf("--------------------------------------------------------------\n");
+ if ((iter = vpi_iterate(vpiUserSystf, NULL)) == NULL) 
+  {
+   vpi_printf("  No registers vpi_ system tasks or functions.\n");
+   vpi_printf(
+    "--------------------------------------------------------------\n");
+   return;
+  }
+ /* user provides record that is filled but following current semantics */
+ /* values pointed to by contents are shared (i.e. must be left as is) */
+ tfinfp = &systf_inf;
+ for (;;)
+  {
+   if ((tfref = vpi_scan(iter)) == NULL) break;
+   vpi_get_systf_info(tfref, tfinfp);
+   if (tfinfp->type == vpiSysTask)
+    vpi_printf("vpi_ system task %s registered.\n", tfinfp->tfname);
+   else
+    {
+     vpi_printf("vpi_ system function %s (ret. type %d) registered.\n",
+     tfinfp->tfname, tfinfp->sysfunctype);
+    }
+  }
+ vpi_printf(
+  "--------------------------------------------------------------\n");
+}
+
+/*
+ * count arguments
+ */
+static int count_systf_args(vpiHandle iref)
+{
+ int anum = 0;
+
+ while (vpi_scan(iref) != NULL) anum++;
+ return(anum);
+}
+
+/*
+ * real function that returns something and prints hello world
+ * 
+ * should probably call vpi_chk_error - not just check for null handle 
+ * returns 0 because vpi_user.h requires register funcs be int returning
+ */
+PLI_INT32 realfhello(void)
+{
+ vpiHandle href, iref;
+
+ href = vpi_handle(vpiSysTfCall, NULL); 
+ if (href == NULL) 
+  {
+   vpi_printf("** ERR: $realfhello PLI 2.0 can not access sysf call handle\n");
+   return(0);
+  }
+ if ((iref = vpi_iterate(vpiArgument, href)) != NULL)
+  { 
+   vpi_printf(
+    "**ERR: $realfhello PLI 2.0 task called with %d arguments but none allowed\n",
+    count_systf_args(iref));
+   return(0);
+  }
+ vpiset_to_real(href, 19.0);
+ vpi_printf("hello world\n");
+ return(0);
+}
+
+/*
+ * set a handle to a real value
+ *
+ * user must make sure href can have have a value put into it
+ * notice the key to vpi_ processing is to save and pass handles
+ */
+static void vpiset_to_real(vpiHandle href, double d1)
+{
+ struct t_vpi_value valrec;
+ struct t_vpi_error_info einfotab;
+
+ valrec.format = vpiRealVal;
+  valrec.value.real = d1; 
+ vpi_put_value(href, &valrec, NULL, vpiNoDelay);
+ if (vpi_chk_error(&einfotab))
+  {
+   vpi_printf("** ERR: vpi_put_value of real error:\n");
+   prtvpiemsg(&einfotab);
+  }
+}
+
+/*
+ * routine to build an error indication string 
+ */
+static void prtvpiemsg(struct t_vpi_error_info *einfop)
+{
+ char s1[128];
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("%s: %s error (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+}
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register system tasks */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_my_systfs, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf registering is done here */
+
+/*
+ * register all vpi_ PLI 2.0 style user system tasks and functions
+ */
+void register_my_systfs(void)
+{
+ p_vpi_systf_data systf_data_p;
+
+ /* use predefined table form - could fill systf_data_list dynamically */
+ static s_vpi_systf_data systf_data_list[] = {
+  { vpiSysTask, 0, "$hello", hello, NULL, NULL, NULL },
+  { vpiSysFunc, vpiRealFunc, "$realfhello", realfhello, NULL, NULL, NULL },
+  { 0, 0, NULL, NULL, NULL, NULL, NULL }
+ };
+
+ systf_data_p = &(systf_data_list[0]);
+ while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vhello2.plg b/tests_and_examples/examples.vpi/vhello2.plg
new file mode 100644
index 0000000..94041a2
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vhello2.plg
@@ -0,0 +1,7 @@
+--------------------------------------------------------------
+vpi_ system task $hello registered.
+vpi_ system function $realfhello (ret. type 2) registered.
+--------------------------------------------------------------
+hello world
+hello world
+done with PLI 2.0 calls returned i=0 and r=19
diff --git a/tests_and_examples/examples.vpi/vhello2.v b/tests_and_examples/examples.vpi/vhello2.v
new file mode 100644
index 0000000..0b47841
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vhello2.v
@@ -0,0 +1,12 @@
+module xx;
+ integer i;
+ real r;
+
+ initial
+  begin
+   $hello;
+   r = $realfhello;
+   i = $stime;
+   $display("done with PLI 2.0 calls returned i=%0d and r=%0g", i, r);
+  end
+endmodule
diff --git a/tests_and_examples/examples.vpi/vpifout.fil b/tests_and_examples/examples.vpi/vpifout.fil
new file mode 100644
index 0000000..b4eb011
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vpifout.fil
@@ -0,0 +1 @@
+tmp_channel           4
diff --git a/tests_and_examples/examples.vpi/vpifout.xfl b/tests_and_examples/examples.vpi/vpifout.xfl
new file mode 100644
index 0000000..b4eb011
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vpifout.xfl
@@ -0,0 +1 @@
+tmp_channel           4
diff --git a/tests_and_examples/examples.vpi/vpiret.m01 b/tests_and_examples/examples.vpi/vpiret.m01
new file mode 100644
index 0000000..ac12cf0
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vpiret.m01
@@ -0,0 +1,29 @@
+
+Why do vpi_ do call back registered functions return 'int' instead of 'void'
+
+It seems to me the vpi_ simulation related registered call back function
+in the s_cb_data type (LRM section 23.34, p. 584) and system task or
+function call back routines in s_vpi_systf_data (LRM section 23.25, p. 589)
+should have type "void returning function" instead of "int returning
+function".  And in fact the example on page 588 is code this way and
+I think wrong since a void returning call back function 'get_current_cputime'
+is registered in the example. 
+
+I discovered this trying to run some vpi_ code through a lint program. 
+In order to take advantage of the checking ability of ansii C, registered
+functions must be declared as int returning and must explicitly return
+some kind of dummy value (probably 0).
+
+In addition to the advantage of allowing lint warning checking changing
+the fields to void returning allows optimizing C compilers to
+produce much better code.
+
+The s_vpi_vlog_info type defined in vpi_user.h for defining start up
+call back routines does require void returning routines. 
+
+I could not find any use for either s_cb_data call back or s_vpi_systf_data
+routine int return value in the LRM.  Is there something I am missing on
+this?   Since the s_vpi_time type is already being changed, now might be
+a good time to also change the cb_rtn declarations.  
+/Steve
+
diff --git a/tests_and_examples/examples.vpi/vpitout.fil b/tests_and_examples/examples.vpi/vpitout.fil
new file mode 100644
index 0000000..b4eb011
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vpitout.fil
@@ -0,0 +1 @@
+tmp_channel           4
diff --git a/tests_and_examples/examples.vpi/vpitout.xfl b/tests_and_examples/examples.vpi/vpitout.xfl
new file mode 100644
index 0000000..b4eb011
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vpitout.xfl
@@ -0,0 +1 @@
+tmp_channel           4
diff --git a/tests_and_examples/examples.vpi/vprtchg.c b/tests_and_examples/examples.vpi/vprtchg.c
new file mode 100644
index 0000000..0a25902
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vprtchg.c
@@ -0,0 +1,273 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * test of value change call backs
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+int (*iproc_rtn)();
+
+/* local function prototypes */
+static int process_inst(vpiHandle); 
+static void setup_1iter_chgcbs(vpiHandle);
+static void setup_1task_chgcbs(vpiHandle);
+
+/* global function prototypes */
+extern int process_all_insts(struct t_cb_data *);
+extern int setup_varchgcbs(vpiHandle);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb();
+extern int my_prt_vchg(p_cb_data);
+
+/*
+ * routine to get and zero all delays in design 
+ */
+int process_all_insts(struct t_cb_data *cbp)
+{
+ int isiz;
+ vpiHandle topiter, topiref;
+
+ /* build the iterator for each module */
+ topiter = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, topiter);
+ vpi_printf("  There are %d top level modules.\n", isiz);
+ for (;;)
+  {
+   if ((topiref = vpi_scan(topiter)) == NULL) break;
+   process_inst(topiref);
+  }
+ vpi_printf("  >>> All instances processed - continuing with simulation.\n");
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static int process_inst(vpiHandle up_ihref) 
+{
+ int isiz;
+ vpiHandle iter, ihref;
+
+ iproc_rtn(up_ihref);
+ if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return(0);
+ isiz = vpi_get(vpiSize, iter);
+ vpi_printf("  There are %d instances in %s.\n", isiz,
+  vpi_get_str(vpiFullName, up_ihref));
+  for (;;)
+  {
+   if ((ihref = vpi_scan(iter)) == NULL) break;
+   process_inst(ihref);
+  }
+ return(0);
+}
+
+/*
+ * simplest processing routine - just print full path name
+ */
+int setup_varchgcbs(vpiHandle ihref)
+{
+ vpiHandle iter, thref;
+ 
+ /* first all instance regs, wires, and variables */ 
+ iter = vpi_iterate(vpiNet, ihref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+ iter = vpi_iterate(vpiReg, ihref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+ iter = vpi_iterate(vpiVariables, ihref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+
+ /* also monitor in scopes */
+ iter = vpi_iterate(vpiInternalScope, ihref);
+ for (;;)
+  {
+   if ((thref = vpi_scan(iter)) == NULL) break;
+   setup_1task_chgcbs(thref);
+  }
+ return(0);
+}
+
+/*
+ * set up change call back for all nets/regs of some type in iter
+ */
+static void setup_1iter_chgcbs(vpiHandle iter)
+{
+ int ntyp;
+ vpiHandle href;
+ p_cb_data cbp;
+ p_vpi_time timp;
+ p_vpi_value valp;
+
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   /*  illegal to monitor change value of events */
+   /* if (vpi_get(vpiNetType, href) == vpiNamedEvent) continue; */
+
+   /* DBG remove --- */
+   if ((ntyp = vpi_get(vpiType, href)) == vpiNet || ntyp == vpiNetBit)
+    vpi_printf("Net type %d\n", vpi_get(vpiNetType, href)); 
+
+   /* notice this must persistent until cb removed */
+   cbp = (p_cb_data) malloc(sizeof(s_cb_data));
+   cbp->reason = cbValueChange;
+   cbp->cb_rtn = my_prt_vchg;  
+
+   timp = (p_vpi_time) malloc(sizeof(s_vpi_time));
+   timp->type = vpiSimTime;
+   timp->high = timp->low = 0;
+   cbp->time = timp;
+   valp = (p_vpi_value) malloc(sizeof(s_vpi_value)); 
+   valp->format = vpiBinStrVal;
+   /* standard called for value in work string where call back sets ptr to */
+   valp->value.str = NULL;
+   cbp->value = valp;
+   cbp->obj = href; 
+   vpi_register_cb(cbp);
+  }
+}
+
+/*
+ * setup variables in task for monitoring
+ */
+static void setup_1task_chgcbs(vpiHandle thref)
+{
+ vpiHandle iter;
+
+ iter = vpi_iterate(vpiReg, thref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+ iter = vpi_iterate(vpiVariables, thref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+
+ /* include all contained named blocks */
+ iter = vpi_iterate(vpiInternalScope, thref);
+ for (;;)
+  {
+   if ((thref = vpi_scan(iter)) == NULL) break;
+   setup_1task_chgcbs(thref);
+  }
+}
+
+/*
+ * value change call back routine - print the value information
+ */
+int my_prt_vchg(p_cb_data cbp)
+{
+ vpi_printf("--> now %d: %s=%s.\n", cbp->time->low,  
+  vpi_get_str(vpiFullName, cbp->obj), cbp->value->value.str);
+ return(0);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = process_all_insts;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+ /* if not registered will be no call backs */
+
+ /* set the processing routine */
+ iproc_rtn = setup_varchgcbs;
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vprtchg.plg b/tests_and_examples/examples.vpi/vprtchg.plg
new file mode 100644
index 0000000..26ed72f
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vprtchg.plg
@@ -0,0 +1,37 @@
+  There are 1 top level modules.
+  >>> All instances processed - continuing with simulation.
+--> now 0: task10.count=00000000000000000000000000000000.
+--> now 0: task10.x=0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
+--> now 10: task10.aa=00000000000000000000000000000000.
+--> now 10: task10.bb=0.
+--> now 10: task10.x=11111111111111111111111111111111.
+--> now 10: task10.y=1.
+        10 start   x: ffffffff  y: 1  count: 0
+--> now 10: task10.t1.a=00000000000000000000000000000000.
+--> now 10: task10.t1.b=0.
+        10 t1 started
+--> now 10: task10.t1.d=0.
+--> now 20: task10.t1.c=00000000000000000000000000000000.
+--> now 30: task10.count=00000000000000000000000000000001.
+        30 t1 finished
+--> now 30: task10.x=00000000000000000000000000000000.
+--> now 30: task10.y=0.
+        30 return  x: 00000000  y: 0  count: 1
+--> now 30: task10.aa=00000000000000000000000000000001.
+--> now 30: task10.bb=1.
+--> now 30: task10.t1.a=00000000000000000000000000000001.
+--> now 30: task10.t1.b=1.
+        30 t1 started
+--> now 30: task10.t1.d=1.
+        35 return  x: 00000000  y: 0  count: 1
+--> now 35: task10.aa=00000000000000000000000000000010.
+--> now 35: task10.bb=0.
+--> now 35: task10.t1.a=00000000000000000000000000000010.
+--> now 35: task10.t1.b=0.
+        35 t1 started
+--> now 35: task10.t1.d=0.
+--> now 45: task10.t1.c=00000000000000000000000000000010.
+--> now 55: task10.count=00000000000000000000000000000010.
+        55 t1 finished
+--> now 55: task10.x=00000000000000000000000000000010.
+        55 return  x: 00000002  y: 0  count: 2
diff --git a/tests_and_examples/examples.vpi/vprtchg2.c b/tests_and_examples/examples.vpi/vprtchg2.c
new file mode 100644
index 0000000..3cd54c2
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vprtchg2.c
@@ -0,0 +1,341 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * test of get_value using value change call back mechanism 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+int (*iproc_rtn)();
+
+/* local function prototypes */
+static void process_inst(vpiHandle); 
+static void setup_1iter_chgcbs(vpiHandle);
+static void setup_1task_chgcbs(vpiHandle);
+static char *vpival_to_str(char *, p_vpi_value, int);
+
+/* global function prototypes */
+extern int process_all_insts(struct t_cb_data *);
+extern int setup_varchgcbs(vpiHandle);
+extern int my_prt2_vchg(p_cb_data);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb(void);
+
+/*
+ * routine to get and zero all delays in design 
+ */
+int process_all_insts(struct t_cb_data *cbp)
+{
+ int isiz;
+ vpiHandle topiter, topiref;
+
+ /* build the iterator for each module */
+ topiter = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, topiter);
+ vpi_printf("  There are %d top level modules.\n", isiz);
+ for (;;)
+  {
+   if ((topiref = vpi_scan(topiter)) == NULL) break;
+   process_inst(topiref);
+  }
+ vpi_printf("  >>> All instances processed - continuing with simulation.\n");
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static void process_inst(vpiHandle up_ihref) 
+{
+ int isiz;
+ vpiHandle iter, ihref;
+
+ iproc_rtn(up_ihref);
+ if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return;
+ isiz = vpi_get(vpiSize, iter);
+ vpi_printf("  There are %d instances in %s.\n", isiz,
+  vpi_get_str(vpiFullName, up_ihref));
+  for (;;)
+  {
+   if ((ihref = vpi_scan(iter)) == NULL) break;
+   process_inst(ihref);
+  }
+}
+
+/*
+ * simplest processing routine - just print full path name
+ */
+int setup_varchgcbs(vpiHandle ihref)
+{
+ vpiHandle iter, thref;
+ 
+ /* first all instance regs, wires, and variables */ 
+ iter = vpi_iterate(vpiNet, ihref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+ iter = vpi_iterate(vpiReg, ihref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+ iter = vpi_iterate(vpiVariables, ihref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+
+ /* also monitor in scopes */
+ iter = vpi_iterate(vpiInternalScope, ihref);
+ for (;;)
+  {
+   if ((thref = vpi_scan(iter)) == NULL) break;
+   setup_1task_chgcbs(thref);
+  }
+ return(0);
+}
+
+/*
+ * set up change call back for all nets/regs of some type in iter
+ * user cb routine handles getting values and time
+ */
+static void setup_1iter_chgcbs(vpiHandle iter)
+{
+ vpiHandle href;
+ p_cb_data cbp;
+ p_vpi_time timp;
+ p_vpi_value valp;
+
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+
+   /* notice this must persistent until cb removed */
+   cbp = (p_cb_data) malloc(sizeof(s_cb_data));
+   cbp->reason = cbValueChange;
+   cbp->cb_rtn = my_prt2_vchg;  
+
+   /* do not care about time or value - but must set to unused */
+   /* nil here according to the standard causes core dump? */
+   cbp->obj = href; 
+   timp = (p_vpi_time) malloc(sizeof(s_vpi_time));
+   timp->type = vpiSuppressTime;
+   cbp->time = timp;
+   valp = (p_vpi_value) malloc(sizeof(s_vpi_value)); 
+   valp->format = vpiSuppressVal;
+   cbp->value = valp;
+   cbp->index = 0;
+
+   vpi_register_cb(cbp);
+  }
+}
+
+/*
+ * setup variables in task for monitoring
+ */
+static void setup_1task_chgcbs(vpiHandle thref)
+{
+ vpiHandle iter;
+
+ iter = vpi_iterate(vpiReg, thref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+ iter = vpi_iterate(vpiVariables, thref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+
+ /* include all contained named blocks */
+ iter = vpi_iterate(vpiInternalScope, thref);
+ for (;;)
+  {
+   if ((thref = vpi_scan(iter)) == NULL) break;
+   setup_1task_chgcbs(thref);
+  }
+}
+
+/*
+ * value change call back routine - print the value information
+ *
+ * since just print can reuse one handle
+ */
+int my_prt2_vchg(p_cb_data cbp)
+{
+ int blen;
+ s_vpi_value val;
+ s_vpi_time tim;
+ char s1[1024];
+
+ val.format = vpiObjTypeVal;
+ vpi_get_value(cbp->obj, &val); 
+ blen = vpi_get(vpiSize, cbp->obj);
+ vpival_to_str(s1, &val, blen);
+
+ tim.type = vpiScaledRealTime;
+ vpi_get_time(cbp->obj, &tim);
+
+ vpi_printf("--> now %g: %s changed to %s.\n", tim.real,  
+  vpi_get_str(vpiFullName, cbp->obj), s1);
+ return(0);
+}
+
+static char *vpival_to_str(char *s, p_vpi_value valp, int blen)
+{
+ register int i;
+ int numvals;
+ char s1[1024];
+
+ switch (valp->format) {
+  case vpiBinStrVal: case vpiOctStrVal: case vpiDecStrVal: case vpiHexStrVal:
+  case vpiStringVal:
+   strcpy(s, valp->value.str);
+   break;
+  case vpiScalarVal:
+   if (valp->value.scalar < 2) sprintf(s, "%x", valp->value.scalar);
+   else if (valp->value.scalar == 3) strcpy(s, "x");
+   else if (valp->value.scalar == 2) strcpy(s, "z");
+   else strcpy(s, "?");  
+   break;
+  case vpiIntVal:
+   sprintf(s, "%d", valp->value.integer);
+   break;
+  case vpiRealVal:
+   sprintf(s, "%g", valp->value.real);
+   break;
+  case vpiVectorVal:
+   /* not bothing to build a Verilog style value - just printing pairs */ 
+   /* assuming int type always 32 bits */ 
+   numvals = (blen + 31) >> 5;
+   /* notice t_vpi_vecval is really array of the 2 integer a/b sections */
+   strcpy(s, "");
+   for (i = numvals - 1; i >= 0; i--)
+    {
+     sprintf(s1, "(av=%x,bv=%x)", valp->value.vector[i].aval,
+      valp->value.vector[i].bval);
+     strcat(s, s1);
+    }
+   break;
+  case vpiStrengthVal:
+   sprintf(s, "<s0=%d,s1=%d,v=%d>", valp->value.strength->s0,
+    valp->value.strength->s1, valp->value.strength->logic);
+   break;
+  case vpiTimeVal:
+   if (valp->value.time->type == vpiScaledRealTime)
+    sprintf(s, "%f", valp->value.time->real);
+   else sprintf(s, "%d", valp->value.time->low);
+   break;
+  case vpiObjTypeVal: case vpiSuppressVal:
+   vpi_printf(
+    "**ERR: can not copy vpiObjTypeVal or vpiSuppressVal formats - not for filled records.\n");
+   return(NULL);
+  default: 
+   vpi_printf(
+    "**ERR: can not copy t_vpi_value record - format code %d illegal.\n",
+   valp->format);
+  return(NULL);
+ }
+ return(s);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+ struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = process_all_insts;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+ /* if not registered will be no call backs */
+
+ /* set the processing routine */
+ iproc_rtn = setup_varchgcbs;
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vprtchg2.plg b/tests_and_examples/examples.vpi/vprtchg2.plg
new file mode 100644
index 0000000..6865bf8
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vprtchg2.plg
@@ -0,0 +1,37 @@
+  There are 1 top level modules.
+  >>> All instances processed - continuing with simulation.
+--> now 0: task10.count changed to 0.
+--> now 0: task10.x changed to (av=7fffffff,bv=7fffffff).
+--> now 10: task10.aa changed to (av=0,bv=0).
+--> now 10: task10.bb changed to 0.
+--> now 10: task10.x changed to (av=ffffffff,bv=0).
+--> now 10: task10.y changed to 1.
+        10 start   x: ffffffff  y: 1  count: 0
+--> now 10: task10.t1.a changed to (av=0,bv=0).
+--> now 10: task10.t1.b changed to 0.
+        10 t1 started
+--> now 10: task10.t1.d changed to 0.
+--> now 20: task10.t1.c changed to (av=0,bv=0).
+--> now 30: task10.count changed to 1.
+        30 t1 finished
+--> now 30: task10.x changed to (av=0,bv=0).
+--> now 30: task10.y changed to 0.
+        30 return  x: 00000000  y: 0  count: 1
+--> now 30: task10.aa changed to (av=1,bv=0).
+--> now 30: task10.bb changed to 1.
+--> now 30: task10.t1.a changed to (av=1,bv=0).
+--> now 30: task10.t1.b changed to 1.
+        30 t1 started
+--> now 30: task10.t1.d changed to 1.
+        35 return  x: 00000000  y: 0  count: 1
+--> now 35: task10.aa changed to (av=2,bv=0).
+--> now 35: task10.bb changed to 0.
+--> now 35: task10.t1.a changed to (av=2,bv=0).
+--> now 35: task10.t1.b changed to 0.
+        35 t1 started
+--> now 35: task10.t1.d changed to 0.
+--> now 45: task10.t1.c changed to (av=2,bv=0).
+--> now 55: task10.count changed to 2.
+        55 t1 finished
+--> now 55: task10.x changed to (av=2,bv=0).
+        55 return  x: 00000002  y: 0  count: 2
diff --git a/tests_and_examples/examples.vpi/vprtchg3.c b/tests_and_examples/examples.vpi/vprtchg3.c
new file mode 100644
index 0000000..4e445f7
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vprtchg3.c
@@ -0,0 +1,397 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * test of get_value using value change call back mechanism 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* added local record for saving old variable values */
+struct fullpath_var_t {
+ char *fullpthnam;
+ s_vpi_value *oldvalp;
+ struct fullpath_var_t *fullpnxt;
+};
+
+struct fullpath_var_t *full_path_vars;
+int (*iproc_rtn)();
+
+/* local function prototypes */
+static void process_inst(vpiHandle); 
+static void setup_1iter_chgcbs(vpiHandle);
+static void setup_1task_chgcbs(vpiHandle);
+static struct fullpath_var_t *find_add_fullpath_var(char *);
+static char *vpival_to_str(char *, p_vpi_value, int);
+
+/* global function prototypes */
+extern int process_all_insts(struct t_cb_data *);
+extern int setup_varchgcbs(vpiHandle);
+extern int my_prt3_vchg(p_cb_data);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb(void);
+
+/*
+ * routine to get and zero all delays in design 
+ */
+int process_all_insts(struct t_cb_data *cbp)
+{
+ int isiz;
+ vpiHandle topiter, topiref;
+
+ /* build the iterator for each module */
+ topiter = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, topiter);
+ vpi_printf("  There are %d top level modules.\n", isiz);
+ for (;;)
+  {
+   if ((topiref = vpi_scan(topiter)) == NULL) break;
+   process_inst(topiref);
+  }
+ vpi_printf("  >>> All instances processed - continuing with simulation.\n");
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static void process_inst(vpiHandle up_ihref) 
+{
+ int isiz;
+ vpiHandle iter, ihref;
+
+ iproc_rtn(up_ihref);
+ if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return;
+ isiz = vpi_get(vpiSize, iter);
+ vpi_printf("  There are %d instances in %s.\n", isiz,
+  vpi_get_str(vpiFullName, up_ihref));
+  for (;;)
+  {
+   if ((ihref = vpi_scan(iter)) == NULL) break;
+   process_inst(ihref);
+  }
+}
+
+/*
+ * simplest processing routine - just print full path name
+ */
+int setup_varchgcbs(vpiHandle ihref)
+{
+ vpiHandle iter, thref;
+ 
+ /* first all instance regs, wires, and variables */ 
+ iter = vpi_iterate(vpiNet, ihref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+ iter = vpi_iterate(vpiReg, ihref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+ iter = vpi_iterate(vpiVariables, ihref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+
+ /* also monitor in scopes */
+ iter = vpi_iterate(vpiInternalScope, ihref);
+ for (;;)
+  {
+   if ((thref = vpi_scan(iter)) == NULL) break;
+   setup_1task_chgcbs(thref);
+  }
+ return(0);
+}
+
+/*
+ * set up change call back for all nets/regs of some type in iter
+ * user cb routine handles getting values and time
+ */
+static void setup_1iter_chgcbs(vpiHandle iter)
+{
+ vpiHandle href;
+ p_cb_data cbp;
+ p_vpi_time timp;
+ p_vpi_value valp;
+
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+
+   /* notice this must persistent until cb removed */
+   cbp = (p_cb_data) malloc(sizeof(s_cb_data));
+   cbp->reason = cbValueChange;
+   cbp->cb_rtn = my_prt3_vchg;  
+
+   /* do not care about time or value - but must set to unused */
+   /* nil here according to the standard causes core dump? */
+   cbp->obj = href; 
+   timp = (p_vpi_time) malloc(sizeof(s_vpi_time));
+   timp->type = vpiSuppressTime;
+   cbp->time = timp;
+   valp = (p_vpi_value) malloc(sizeof(s_vpi_value)); 
+   valp->format = vpiSuppressVal;
+   cbp->value = valp;
+   cbp->index = 0;
+
+   vpi_register_cb(cbp);
+  }
+}
+
+/*
+ * setup variables in task for monitoring
+ */
+static void setup_1task_chgcbs(vpiHandle thref)
+{
+ vpiHandle iter;
+
+ iter = vpi_iterate(vpiReg, thref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+ iter = vpi_iterate(vpiVariables, thref);
+ if (iter != NULL) setup_1iter_chgcbs(iter);
+
+ /* include all contained named blocks */
+ iter = vpi_iterate(vpiInternalScope, thref);
+ for (;;)
+  {
+   if ((thref = vpi_scan(iter)) == NULL) break;
+   setup_1task_chgcbs(thref);
+  }
+}
+
+/*
+ * value change call back routine - print the value information
+ *
+ * since just print can reuse one handle
+ */
+int my_prt3_vchg(p_cb_data cbp)
+{
+ int blen;
+ s_vpi_value val;
+ s_vpi_time tim;
+ struct fullpath_var_t *varp;
+ char s1[1024], s2[1024], s3[1024];
+
+ /* convert new value to string */
+ val.format = vpiObjTypeVal;
+ vpi_get_value(cbp->obj, &val); 
+ blen = vpi_get(vpiSize, cbp->obj);
+ vpival_to_str(s3, &val, blen);
+
+ strcpy(s1, vpi_get_str(vpiFullName, cbp->obj));
+
+ /* this will create first time variable changes */
+ varp = find_add_fullpath_var(s1);   
+ /* naybe should use x for first old value */
+ if (varp->oldvalp == NULL) strcpy(s2, "<unknown>");
+ else vpival_to_str(s2, varp->oldvalp, blen);
+
+ tim.type = vpiScaledRealTime;
+ vpi_get_time(cbp->obj, &tim);
+
+ vpi_printf("--> now %g: %s changed from %s to %s.\n", tim.real,  
+  s1, s2, s3);
+
+ /* save old value - notice memory leak for malloced fields inside */
+ /* s_vpi_val struct - should free */
+ if (varp->oldvalp == NULL)
+  varp->oldvalp = (p_vpi_value) malloc(sizeof(s_vpi_value));
+ *(varp->oldvalp) = val;
+ return(0);
+}
+
+/*
+ * find-add value to symbol table - return NULL if first time seen
+ *
+ * note: should use hashing or binary search for this symbol table
+ */
+static struct fullpath_var_t *find_add_fullpath_var(char *s)
+{
+ register struct fullpath_var_t *varp, *last_varp;
+
+ last_varp = NULL;
+ for (varp = full_path_vars; varp != NULL; varp = varp->fullpnxt)
+  {
+   if (strcmp(varp->fullpthnam, s) == 0)
+    return(varp); 
+   last_varp = varp;
+  }
+ varp = (struct fullpath_var_t *) malloc(sizeof(struct fullpath_var_t));
+ varp->fullpthnam = malloc(strlen(s) + 1);
+ strcpy(varp->fullpthnam, s);
+ varp->oldvalp = NULL;
+ varp->fullpnxt = NULL;
+
+ if (last_varp == NULL) full_path_vars = varp;
+ else last_varp->fullpnxt = varp;
+ return(varp);
+}
+
+static char *vpival_to_str(char *s, p_vpi_value valp, int blen)
+{
+ register int i;
+ int numvals;
+ char s1[1024];
+
+ switch (valp->format) {
+  case vpiBinStrVal: case vpiOctStrVal: case vpiDecStrVal: case vpiHexStrVal:
+  case vpiStringVal:
+   strcpy(s, valp->value.str);
+   break;
+  case vpiScalarVal:
+   if (valp->value.scalar < 2) sprintf(s, "%x", valp->value.scalar);
+   else if (valp->value.scalar == 3) strcpy(s, "x");
+   else if (valp->value.scalar == 2) strcpy(s, "z");
+   else strcpy(s, "?");  
+   break;
+  case vpiIntVal:
+   sprintf(s, "%d", valp->value.integer);
+   break;
+  case vpiRealVal:
+   sprintf(s, "%g", valp->value.real);
+   break;
+  case vpiVectorVal:
+   /* not bothing to build a Verilog style value - just printing pairs */ 
+   /* assuming int type always 32 bits */ 
+   numvals = (blen + 31) >> 5;
+   /* notice t_vpi_vecval is really array of the 2 integer a/b sections */
+   strcpy(s, "");
+   for (i = numvals - 1; i >= 0; i--)
+    {
+     sprintf(s1, "(av=%x,bv=%x)", valp->value.vector[i].aval,
+      valp->value.vector[i].bval);
+     strcat(s, s1);
+    }
+   break;
+  case vpiStrengthVal:
+   sprintf(s, "<s0=%d,s1=%d,v=%d>", valp->value.strength->s0,
+    valp->value.strength->s1, valp->value.strength->logic);
+   break;
+  case vpiTimeVal:
+   if (valp->value.time->type == vpiScaledRealTime)
+    sprintf(s, "%f", valp->value.time->real);
+   else sprintf(s, "%d", valp->value.time->low);
+   break;
+  case vpiObjTypeVal: case vpiSuppressVal:
+   vpi_printf(
+    "**ERR: can not copy vpiObjTypeVal or vpiSuppressVal formats - not for filled records.\n");
+   return(NULL);
+  default: 
+   vpi_printf(
+    "**ERR: can not copy t_vpi_value record - format code %d illegal.\n",
+   valp->format);
+  return(NULL);
+ }
+ return(s);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+ struct t_cb_data cbrec;
+
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = process_all_insts;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+ /* if not registered will be no call backs */
+
+ /* set the processing routine */
+ iproc_rtn = setup_varchgcbs;
+
+ /* my variable initializes */
+ full_path_vars = NULL;
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vprtchg3.plg b/tests_and_examples/examples.vpi/vprtchg3.plg
new file mode 100644
index 0000000..c44a3ee
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vprtchg3.plg
@@ -0,0 +1,37 @@
+  There are 1 top level modules.
+  >>> All instances processed - continuing with simulation.
+--> now 0: task10.count changed from <unknown> to 0.
+--> now 0: task10.x changed from <unknown> to (av=7fffffff,bv=7fffffff).
+--> now 10: task10.aa changed from <unknown> to (av=0,bv=0).
+--> now 10: task10.bb changed from <unknown> to 0.
+--> now 10: task10.x changed from (av=ffffffff,bv=0) to (av=ffffffff,bv=0).
+--> now 10: task10.y changed from <unknown> to 1.
+        10 start   x: ffffffff  y: 1  count: 0
+--> now 10: task10.t1.a changed from <unknown> to (av=0,bv=0).
+--> now 10: task10.t1.b changed from <unknown> to 0.
+        10 t1 started
+--> now 10: task10.t1.d changed from <unknown> to 0.
+--> now 20: task10.t1.c changed from <unknown> to (av=0,bv=0).
+--> now 30: task10.count changed from 0 to 1.
+        30 t1 finished
+--> now 30: task10.x changed from (av=0,bv=0) to (av=0,bv=0).
+--> now 30: task10.y changed from 1 to 0.
+        30 return  x: 00000000  y: 0  count: 1
+--> now 30: task10.aa changed from (av=1,bv=0) to (av=1,bv=0).
+--> now 30: task10.bb changed from 0 to 1.
+--> now 30: task10.t1.a changed from (av=1,bv=0) to (av=1,bv=0).
+--> now 30: task10.t1.b changed from 0 to 1.
+        30 t1 started
+--> now 30: task10.t1.d changed from 0 to 1.
+        35 return  x: 00000000  y: 0  count: 1
+--> now 35: task10.aa changed from (av=2,bv=0) to (av=2,bv=0).
+--> now 35: task10.bb changed from 1 to 0.
+--> now 35: task10.t1.a changed from (av=2,bv=0) to (av=2,bv=0).
+--> now 35: task10.t1.b changed from 1 to 0.
+        35 t1 started
+--> now 35: task10.t1.d changed from 1 to 0.
+--> now 45: task10.t1.c changed from (av=2,bv=0) to (av=2,bv=0).
+--> now 55: task10.count changed from 1 to 2.
+        55 t1 finished
+--> now 55: task10.x changed from (av=2,bv=0) to (av=2,bv=0).
+        55 return  x: 00000002  y: 0  count: 2
diff --git a/tests_and_examples/examples.vpi/vprtdel2.c b/tests_and_examples/examples.vpi/vprtdel2.c
new file mode 100644
index 0000000..755e5e4
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vprtdel2.c
@@ -0,0 +1,283 @@
+/*
+ * test of get delays vpi_ tasks (some commented out but all cases)
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+#define TRUE 1
+#define FALSE 0
+
+int (*iproc_rtn)();
+
+/* local function prototypes */
+static void process_inst(vpiHandle); 
+static char *get_tchknam(char *, int);
+
+/* global function prototypes */
+extern int process_all_insts(struct t_cb_data *);
+extern int prt_inst_delays(vpiHandle);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb(void);
+
+/*
+ * routine to get and zero all delays in design 
+ */
+int process_all_insts(struct t_cb_data *cbp)
+{
+ int isiz, tunit, tprec;
+ vpiHandle topiter, topiref;
+
+ /* should convert these into unit names */
+ tunit = vpi_get(vpiTimeUnit, NULL);
+ tprec = vpi_get(vpiTimePrecision, NULL);
+
+ /* build the iterator for each module */
+ topiter = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, topiter);
+ vpi_printf("  There are %d top level modules (timescale %d / %d).\n", isiz,
+  tunit, tprec);
+ for (;;)
+  {
+   if ((topiref = vpi_scan(topiter)) == NULL) break;
+   process_inst(topiref);
+  }
+ vpi_printf("  All instances processed.\n");
+ /* notice Verilog model is not run, just data for PLI */
+ vpi_sim_control(vpiFinish, 0);
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static void process_inst(vpiHandle up_ihref) 
+{
+ int isiz, tunit, tprec;
+ vpiHandle iter, ihref;
+
+ iproc_rtn(up_ihref);
+ iter = vpi_iterate(vpiModule, up_ihref);
+ if (iter == NULL) isiz = 0; else isiz = vpi_get(vpiSize, iter);
+
+ tunit = vpi_get(vpiTimeUnit, up_ihref);
+ tprec = vpi_get(vpiTimePrecision, up_ihref);
+
+ vpi_printf("  There are %d instances in %s (timescale: %d / %d).\n", isiz,
+  vpi_get_str(vpiFullName, up_ihref), tunit, tprec);
+ if (iter == NULL) return;
+ for (;;)
+  {
+   if ((ihref = vpi_scan(iter)) == NULL) break;
+   process_inst(ihref);
+  }
+}
+
+/*
+ * simplest processing routine - just print full path name
+ */
+int prt_inst_delays(vpiHandle ihref)
+{
+ vpiHandle iter, href;
+ s_vpi_delay drec;
+ s_vpi_time delarr[12];
+ char s1[1024], s2[1024];
+
+ drec.da = &(delarr[0]);
+ /* drec.time_type = vpiSimTime; */
+ drec.time_type = vpiScaledRealTime;
+ drec.mtm_flag = FALSE;
+ drec.append_flag = FALSE;
+ drec.pulsere_flag = FALSE;
+ /* gates - use scan returns nil, nil iterator pattern */ 
+ drec.no_of_delays = 2;
+ iter = vpi_iterate(vpiPrimitive, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   if (vpi_iterate(vpiDelay, href) == NULL) continue;
+
+   vpi_get_delays(href, &drec);
+   /* expect delays to always fit in 31 bits */
+   if (vpi_get(vpiType, href) == vpiUdp) strcpy(s1, "udp");
+   else strcpy(s1, "gate");
+   strcpy(s2, vpi_get_str(vpiDefName, href));
+   vpi_printf("  %s %s %s has delay #(%g, %g).\n",
+    s2, s1, vpi_get_str(vpiFullName, href), drec.da[0].real, drec.da[1].real);
+  }
+ /* contas */
+ iter = vpi_iterate(vpiContAssign, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   if (vpi_iterate(vpiDelay, href) == NULL) continue;
+
+   vpi_get_delays(href, &drec);
+   /* expect delays to always fit in 31 bits */
+   vpi_printf("  continuous assign at **%s(%d) has delay #(%g, %g).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    drec.da[0].real, drec.da[1].real);
+  }
+ /* paths */
+ drec.no_of_delays = 6;
+ drec.time_type = vpiScaledRealTime; 
+ iter = vpi_iterate(vpiModPath, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+
+   vpi_get_delays(href, &drec);
+   /* expect delays to always fit in 31 bits */
+   vpi_printf("  path at **%s(%d) has delay #(%g, %g, %g, %g, %g, %g).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    drec.da[0].real, drec.da[1].real, drec.da[2].real, drec.da[3].real,
+    drec.da[4].real, drec.da[5].real);
+  }
+ /* timing checks */
+ /* paths */
+ /* drec.no_of_delays = 2; */
+ drec.no_of_delays = 1;
+ /* drec.time_type = vpiSimTime; */
+ drec.time_type = vpiScaledRealTime; 
+ iter = vpi_iterate(vpiTchk, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   vpi_get_delays(href, &drec);
+   get_tchknam(s1, vpi_get(vpiTchkType, href));
+   vpi_printf("  %s timing check at **%s(%d) limit %g.\n",
+    s1, vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href), drec.da[0].real);
+  }
+ return(0);
+}
+
+/*
+ * notice need user routine - no str property
+ */
+static char *get_tchknam(char *s, int ttyp)
+{
+ switch (ttyp) {
+  case vpiSetup: strcpy(s, "$setup"); break;
+  case vpiHold: strcpy(s, "$hold"); break;
+  case vpiPeriod: strcpy(s, "$period"); break;
+  case vpiWidth: strcpy(s, "$width"); break;
+  case vpiSkew: strcpy(s, "$skew"); break;
+  case vpiRecovery: strcpy(s, "$recovery"); break;
+  case vpiNoChange: strcpy(s, "$nochange"); break;
+  case vpiSetupHold: strcpy(s,  "$setuphold"); break;
+  default: strcpy(s, "**out of range**");  break;
+ } 
+ return(s);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+ struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = process_all_insts;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+ /* if not registered will be no call backs */
+
+ /* set the processing routine */
+ iproc_rtn = prt_inst_delays;
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vprtdel2.plg b/tests_and_examples/examples.vpi/vprtdel2.plg
new file mode 100644
index 0000000..5c96f63
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vprtdel2.plg
@@ -0,0 +1,4 @@
+  There are 1 top level modules (timescale -9 / -9).
+  and gate test.i1 has delay #(1.6, 1.6).
+  There are 0 instances in test (timescale: -8 / -9).
+  All instances processed.
diff --git a/tests_and_examples/examples.vpi/vprtdels.c b/tests_and_examples/examples.vpi/vprtdels.c
new file mode 100644
index 0000000..c38bf47
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vprtdels.c
@@ -0,0 +1,324 @@
+/*
+ * test of get delays vpi_ tasks (some commented out but all cases)
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+#define TRUE 1
+#define FALSE 0
+
+int (*iproc_rtn)();
+
+/* local function prototypes */
+static int process_inst(vpiHandle); 
+static char *get_tchknam(char *, int);
+
+/* global function prototypes */
+extern int process_all_insts(struct t_cb_data *);
+extern int prt_inst_delays(vpiHandle);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb(void);
+extern void register_builtin_ams_systfs(void);
+
+/*
+ * routine to get and zero all delays in design 
+ */
+int process_all_insts(struct t_cb_data *cbp)
+{
+ int isiz, tunit, tprec;
+ vpiHandle topiter, topiref;
+
+ /* should convert these into unit names */
+ tunit = vpi_get(vpiTimeUnit, NULL);
+ tprec = vpi_get(vpiTimePrecision, NULL);
+
+ /* build the iterator for each module */
+ topiter = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, topiter);
+ vpi_printf("  There are %d top level modules (timescale %d / %d).\n", isiz,
+  tunit, tprec);
+ for (;;)
+  {
+   if ((topiref = vpi_scan(topiter)) == NULL) break;
+   process_inst(topiref);
+  }
+ vpi_printf("  All instances processed.\n");
+ /* notice Verilog model is not run, just data for PLI */
+ vpi_sim_control(vpiFinish, 0);
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static int process_inst(vpiHandle up_ihref) 
+{
+ int isiz, tunit, tprec;
+ vpiHandle iter, ihref;
+
+ iproc_rtn(up_ihref);
+ if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return(0);
+ isiz = vpi_get(vpiSize, iter);
+
+ tunit = vpi_get(vpiTimeUnit, up_ihref);
+ tprec = vpi_get(vpiTimePrecision, up_ihref);
+
+ vpi_printf("  There are %d instances in %s (timescale: %d / %d).\n", isiz,
+  vpi_get_str(vpiFullName, up_ihref), tunit, tprec);
+ for (;;)
+  {
+   if ((ihref = vpi_scan(iter)) == NULL) break;
+   process_inst(ihref);
+  }
+ return(0);
+}
+
+/*
+ * simplest processing routine - just print full path name
+ */
+int prt_inst_delays(vpiHandle ihref)
+{
+ vpiHandle iter, href;
+ s_vpi_delay drec;
+ s_vpi_time delarr[12];
+ char s1[1024], s2[1024];
+
+ drec.da = &(delarr[0]);
+ drec.time_type = vpiSimTime;
+ /* drec.time_type = vpiScaledRealTime; */
+ drec.mtm_flag = FALSE;
+ drec.append_flag = FALSE;
+ drec.pulsere_flag = FALSE;
+ /* gates - use scan returns nil, nil iterator pattern */ 
+ drec.no_of_delays = 2;
+ iter = vpi_iterate(vpiPrimitive, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+
+   /* following LRM 22.5.9 vpiDelay one to many method to get source delay */
+   /* as iterator of expressions */
+   /* if iterator empty, this is no delays gate */
+   if (vpi_iterate(vpiDelay, href) == NULL) continue;
+
+   vpi_get_delays(href, &drec);
+   /* expect delays to always fit in 31 bits */
+   if (vpi_get(vpiType, href) == vpiUdp) strcpy(s1, "udp");
+   else strcpy(s1, "gate");
+   strcpy(s2, vpi_get_str(vpiDefName, href));
+   /* --
+   vpi_printf("  %s %s %s has delay #(%d, %d, %d).\n",
+    s2, s1, vpi_get_str(vpiFullName, href), drec.da[0].low, drec.da[1].low,
+    drec.da[2].low);
+   --- */
+   vpi_printf("  %s %s %s has delay #(%d, %d).\n",
+    s2, s1, vpi_get_str(vpiFullName, href), drec.da[0].low, drec.da[1].low);
+  /* ---
+   vpi_printf("  %s %s %s has delay #(%5.2f, %5.2f).\n",
+    s2, s1, vpi_get_str(vpiFullName, href), drec.da[0].real, drec.da[1].real);
+  --- */
+  }
+ /* contas */
+ iter = vpi_iterate(vpiContAssign, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   if (vpi_iterate(vpiDelay, href) == NULL) continue;
+
+   vpi_get_delays(href, &drec);
+   /* expect delays to always fit in 31 bits */
+   vpi_printf("  continuous assign at **%s(%d) has delay #(%d, %d, %d).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    drec.da[0].low, drec.da[1].low, drec.da[2].low);
+  }
+ /* paths */
+ drec.no_of_delays = 6;
+ drec.time_type = vpiScaledRealTime; 
+ iter = vpi_iterate(vpiModPath, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+
+   vpi_get_delays(href, &drec);
+   /* expect delays to always fit in 31 bits */
+   /* --- */
+   vpi_printf("  path at **%s(%d) has delay #(%g, %g, %g, %g, %g, %g).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    drec.da[0].real, drec.da[1].real, drec.da[2].real, drec.da[3].real,
+    drec.da[4].real, drec.da[5].real);
+   /* --- */ 
+   /* ---
+   vpi_printf("  path at **%s(%d) has delay #(%d, %d, %d, %d, %d, %d).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    drec.da[0].low, drec.da[1].low, drec.da[2].low, drec.da[3].low,
+    drec.da[4].low, drec.da[5].low);
+   --- */
+   /* ---
+   vpi_printf(
+    "  path at **%s(%d) has delay #(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    drec.da[0].low, drec.da[1].low, drec.da[2].low, drec.da[3].low,
+    drec.da[4].low, drec.da[5].low, drec.da[6].low, drec.da[7].low,
+    drec.da[8].low, drec.da[9].low, drec.da[10].low, drec.da[11].low);
+   --- */
+   /* ---
+   vpi_printf("  path at **%s(%d) has delay #(%d, %d).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    drec.da[0].low, drec.da[1].low, drec.da[2].low);
+   --- */
+  }
+ /* timing checks - notice will see warnings for timing checks that need */
+ /* two delays */
+ /* drec.no_of_delays = 2; */
+ drec.no_of_delays = 1;
+ drec.time_type = vpiSimTime;
+ /* drec.time_type = vpiScaledRealTime; */ 
+ drec.time_type = vpiScaledRealTime; 
+ iter = vpi_iterate(vpiTchk, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   vpi_get_delays(href, &drec);
+   get_tchknam(s1, vpi_get(vpiTchkType, href));
+   vpi_printf("  %s timing check at **%s(%d) limit %g.\n",
+    s1, vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href), drec.da[0].real);
+   /* ---
+   vpi_printf("  %s timing check at **%s(%d) 1st limit %d, 2nd limit %d.\n",
+    s1, vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    drec.da[0].low, drec.da[1].low);
+   --- */    
+  }
+ return(0);
+}
+
+/*
+ * notice need user routine - no str property
+ */
+static char *get_tchknam(char *s, int ttyp)
+{
+ switch (ttyp) {
+  case vpiSetup: strcpy(s, "$setup"); break;
+  case vpiHold: strcpy(s, "$hold"); break;
+  case vpiPeriod: strcpy(s, "$period"); break;
+  case vpiWidth: strcpy(s, "$width"); break;
+  case vpiSkew: strcpy(s, "$skew"); break;
+  case vpiRecovery: strcpy(s, "$recovery"); break;
+  case vpiNoChange: strcpy(s, "$nochange"); break;
+  case vpiSetupHold: strcpy(s,  "$setuphold"); break;
+  default: strcpy(s, "**out of range**");  break;
+ } 
+ return(s);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+ struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = process_all_insts;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+ /* if not registered will be no call backs */
+
+ /* set the processing routine */
+ iproc_rtn = prt_inst_delays;
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vprtdels.plg b/tests_and_examples/examples.vpi/vprtdels.plg
new file mode 100644
index 0000000..f9bc515
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vprtdels.plg
@@ -0,0 +1,46 @@
+**fdspec01.v(105) WARN** [653] $period timing check min:typ:max limit expression needs parentheses under 1364 - unportable
+  There are 1 top level modules (timescale -9 / -9).
+  There are 3 instances in test (timescale: -9 / -9).
+  path at **fdspec01.v(88) has delay #(140, 250, 140, 140, 250, 250).
+  path at **fdspec01.v(89) has delay #(40, 50, 40, 40, 50, 50).
+**ERR(2021) vpiPLI (level 2) at ***none*(0):
+  vpi_get_delays called for object $setuphold vpiTchk delay number 1 wrong - missing 2nd omitted
+  $setuphold timing check at **fdspec01.v(101) limit 70.
+**ERR(2021) vpiPLI (level 2) at ***none*(0):
+  vpi_get_delays called for object $width vpiTchk delay number 1 wrong - missing 2nd omitted
+  $width timing check at **fdspec01.v(103) limit 600.
+**ERR(2021) vpiPLI (level 2) at ***none*(0):
+  vpi_get_delays called for object $width vpiTchk delay number 1 wrong - missing 2nd omitted
+  $width timing check at **fdspec01.v(104) limit 500.
+  $period timing check at **fdspec01.v(105) limit 1200.
+  $skew timing check at **fdspec01.v(106) limit 50.
+  $recovery timing check at **fdspec01.v(107) limit 200.
+  path at **fdspec01.v(88) has delay #(140, 250, 140, 140, 250, 250).
+  path at **fdspec01.v(89) has delay #(40, 50, 40, 40, 50, 50).
+**ERR(2021) vpiPLI (level 2) at ***none*(0):
+  vpi_get_delays called for object $setuphold vpiTchk delay number 1 wrong - missing 2nd omitted
+  $setuphold timing check at **fdspec01.v(101) limit 70.
+**ERR(2021) vpiPLI (level 2) at ***none*(0):
+  vpi_get_delays called for object $width vpiTchk delay number 1 wrong - missing 2nd omitted
+  $width timing check at **fdspec01.v(103) limit 600.
+**ERR(2021) vpiPLI (level 2) at ***none*(0):
+  vpi_get_delays called for object $width vpiTchk delay number 1 wrong - missing 2nd omitted
+  $width timing check at **fdspec01.v(104) limit 500.
+  $period timing check at **fdspec01.v(105) limit 1200.
+  $skew timing check at **fdspec01.v(106) limit 50.
+  $recovery timing check at **fdspec01.v(107) limit 200.
+  path at **fdspec01.v(88) has delay #(140, 250, 140, 140, 250, 250).
+  path at **fdspec01.v(89) has delay #(40, 50, 40, 40, 50, 50).
+**ERR(2021) vpiPLI (level 2) at ***none*(0):
+  vpi_get_delays called for object $setuphold vpiTchk delay number 1 wrong - missing 2nd omitted
+  $setuphold timing check at **fdspec01.v(101) limit 70.
+**ERR(2021) vpiPLI (level 2) at ***none*(0):
+  vpi_get_delays called for object $width vpiTchk delay number 1 wrong - missing 2nd omitted
+  $width timing check at **fdspec01.v(103) limit 600.
+**ERR(2021) vpiPLI (level 2) at ***none*(0):
+  vpi_get_delays called for object $width vpiTchk delay number 1 wrong - missing 2nd omitted
+  $width timing check at **fdspec01.v(104) limit 500.
+  $period timing check at **fdspec01.v(105) limit 1200.
+  $skew timing check at **fdspec01.v(106) limit 50.
+  $recovery timing check at **fdspec01.v(107) limit 200.
+  All instances processed.
diff --git a/tests_and_examples/examples.vpi/vsetdels.c b/tests_and_examples/examples.vpi/vsetdels.c
new file mode 100644
index 0000000..aff3687
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vsetdels.c
@@ -0,0 +1,335 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * test of set delays vpi_ tasks - read and sets (puts) same delay value
+ * for primitives and paths only
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+#define TRUE 1
+#define FALSE 0
+
+int (*iproc_rtn)();
+
+/* local function prototypes */
+static void process_inst(vpiHandle); 
+static char *get_tchknam(char *, int);
+
+/* global function prototypes */
+extern int process_all_insts(struct t_cb_data *);
+extern int prt_inst_delays(vpiHandle);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_scan_cb(void);
+
+/*
+ * routine to get and zero all delays in design 
+ */
+int process_all_insts(struct t_cb_data *cbp)
+{
+ int isiz;
+ vpiHandle topiter, topiref;
+
+ /* build the iterator for each module */
+ topiter = vpi_iterate(vpiModule, NULL);
+ isiz = vpi_get(vpiSize, topiter);
+ vpi_printf("  There are %d top level modules.\n", isiz);
+ for (;;)
+  {
+   if ((topiref = vpi_scan(topiter)) == NULL) break;
+   process_inst(topiref);
+  }
+ vpi_printf("  All instances processed.\n");
+ /* notice Verilog model is not run, just data for PLI */
+ vpi_sim_control(vpiFinish, 0);
+ return(0);
+}
+
+/*
+ * process one instance and recursively process all under instances
+ * processing is top down depth first
+ */
+static void process_inst(vpiHandle up_ihref) 
+{
+ int isiz;
+ vpiHandle iter, ihref;
+
+ iproc_rtn(up_ihref);
+ if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return;
+ isiz = vpi_get(vpiSize, iter);
+ vpi_printf("  There are %d instances in %s.\n", isiz,
+  vpi_get_str(vpiFullName, up_ihref));
+  for (;;)
+  {
+   if ((ihref = vpi_scan(iter)) == NULL) break;
+   process_inst(ihref);
+  }
+}
+
+/*
+ * simplest processing routine - just print delays
+ */
+int prt_inst_delays(vpiHandle ihref)
+{
+ register int di;
+ int tctyp;
+ vpiHandle iter, href;
+ s_vpi_delay idrec, odrec;
+ s_vpi_time idelarr[12], odelarr[12];
+ char s1[1024], s2[1024];
+
+ idrec.da = &(idelarr[0]);
+ idrec.time_type = vpiSimTime;
+ /* idrec.time_type = vpiScaledRealTime; */
+ idrec.mtm_flag = FALSE;
+ idrec.append_flag = FALSE;
+ idrec.pulsere_flag = FALSE;
+ /* gates - use scan returns nil, nil iterator pattern */ 
+ idrec.no_of_delays = 3;
+
+ odrec.da = &(odelarr[0]);
+ odrec.time_type = idrec.time_type;
+ odrec.mtm_flag = FALSE;
+ odrec.append_flag = TRUE;
+ odrec.pulsere_flag = FALSE;
+ /* gates - use scan returns nil, nil iterator pattern */ 
+ odrec.no_of_delays = 3;
+
+ iter = vpi_iterate(vpiPrimitive, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   if (vpi_iterate(vpiDelay, href) == NULL) continue;
+
+   vpi_get_delays(href, &idrec);
+   for (di = 0; di < idrec.no_of_delays; di++) odrec.da[di] = idrec.da[di]; 
+   vpi_put_delays(href, &odrec);
+   vpi_get_delays(href, &idrec);
+
+   /* expect delays to always fit in 31 bits */
+   if (vpi_get(vpiType, href) == vpiUdp) strcpy(s1, "udp");
+   else strcpy(s1, "gate");
+   strcpy(s2, vpi_get_str(vpiDefName, href));
+   /* -- */
+   vpi_printf("  %s %s %s has delay #(%d, %d, %d).\n",
+    s2, s1, vpi_get_str(vpiFullName, href), idrec.da[0].low, idrec.da[1].low,
+    idrec.da[2].low);
+   /* --- */
+   /* ---
+   vpi_printf("  %s %s %s has delay #(%d, %d).\n",
+    s2, s1, vpi_get_str(vpiFullName, href), idrec.da[0].low, idrec.da[1].low);
+   --- */
+  /* ---
+   vpi_printf("  %s %s %s has delay #(%5.2f, %5.2f).\n",
+    s2, s1, vpi_get_str(vpiFullName, href), idrec.da[0].real,
+    idrec.da[1].real);
+  --- */
+  }
+ /* contas */
+ iter = vpi_iterate(vpiContAssign, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   if (vpi_iterate(vpiDelay, href) == NULL) continue;
+
+   vpi_get_delays(href, &idrec);
+   /* expect delays to always fit in 31 bits */
+   vpi_printf("  continuous assign at **%s(%d) has delay #(%d, %d, %d).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    idrec.da[0].low, idrec.da[1].low, idrec.da[2].low);
+  }
+ /* paths */
+ idrec.no_of_delays = 6;
+ idrec.time_type = vpiScaledRealTime; 
+ iter = vpi_iterate(vpiModPath, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+
+   vpi_get_delays(href, &idrec);
+   for (di = 0; di < idrec.no_of_delays; di++) odrec.da[di] = idrec.da[di]; 
+   vpi_put_delays(href, &odrec);
+   vpi_get_delays(href, &idrec);
+   /* expect delays to always fit in 31 bits */
+   /* --- */
+   vpi_printf("  path at **%s(%d) has delay #(%g, %g, %g, %g, %g, %g).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    idrec.da[0].real, idrec.da[1].real, idrec.da[2].real, idrec.da[3].real,
+    idrec.da[4].real, idrec.da[5].real);
+   /* --- */ 
+   /* ---
+   vpi_printf("  path at **%s(%d) has delay #(%d, %d, %d, %d, %d, %d).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    idrec.da[0].low, idrec.da[1].low, idrec.da[2].low, idrec.da[3].low,
+    idrec.da[4].low, idrec.da[5].low);
+   --- */
+   /* ---
+   vpi_printf(
+    "  path at **%s(%d) has delay #(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    idrec.da[0].low, idrec.da[1].low, idrec.da[2].low, idrec.da[3].low,
+    idrec.da[4].low, idrec.da[5].low, idrec.da[6].low, idrec.da[7].low,
+    idrec.da[8].low, idrec.da[9].low, idrec.da[10].low, idrec.da[11].low);
+   --- */
+   /* ---
+   vpi_printf("  path at **%s(%d) has delay #(%d, %d).\n",
+    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    idrec.da[0].low, idrec.da[1].low, idrec.da[2].low);
+   --- */
+  }
+ /* timing checks */
+ /* paths */
+ /* drec.no_of_delays = 2; */
+ idrec.time_type = vpiSimTime;
+ /* drec.time_type = vpiScaledRealTime; */ 
+ idrec.time_type = vpiScaledRealTime; 
+ iter = vpi_iterate(vpiTchk, ihref);
+ for (;;)
+  {
+   if ((href = vpi_scan(iter)) == NULL) break;
+   tctyp = vpi_get(vpiTchkType, href);
+   if (tctyp == vpiWidth || tctyp == vpiSetupHold) idrec.no_of_delays = 2;
+   else idrec.no_of_delays = 1;
+   vpi_get_delays(href, &idrec);
+   get_tchknam(s1, tctyp);
+   vpi_printf("  %s timing check at **%s(%d) limit %g.\n",
+    s1, vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href), idrec.da[0].real);
+   /* ---
+   vpi_printf("  %s timing check at **%s(%d) 1st limit %d, 2nd limit %d.\n",
+    s1, vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
+    idrec.da[0].low, idrec.da[1].low);
+   --- */    
+  }
+ return(0);
+}
+
+/*
+ * notice need user routine - no str property
+ */
+char *get_tchknam(char *s, int ttyp)
+{
+ switch (ttyp) {
+  case vpiSetup: strcpy(s, "$setup"); break;
+  case vpiHold: strcpy(s, "$hold"); break;
+  case vpiPeriod: strcpy(s, "$period"); break;
+  case vpiWidth: strcpy(s, "$width"); break;
+  case vpiSkew: strcpy(s, "$skew"); break;
+  case vpiRecovery: strcpy(s, "$recovery"); break;
+  case vpiNoChange: strcpy(s, "$nochange"); break;
+  case vpiSetupHold: strcpy(s,  "$setuphold"); break;
+  default: strcpy(s, "**out of range**");  break;
+ } 
+ return(s);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_scan_cb, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_scan_cb(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+ struct t_cb_data cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = process_all_insts;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+ /* if not registered will be no call backs */
+
+ /* set the processing routine */
+ iproc_rtn = prt_inst_delays;
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vsetdels.plg b/tests_and_examples/examples.vpi/vsetdels.plg
new file mode 100644
index 0000000..c25531d
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vsetdels.plg
@@ -0,0 +1,52 @@
+**fdspec01.v(105) WARN** [653] $period timing check min:typ:max limit expression needs parentheses under 1364 - unportable
+  There are 1 top level modules.
+  There are 3 instances in test.
+**ERR(2106) vpiPLI (level 1) at ***none*(0):
+  vpi_put_delays to object vpiModPath after simulation started - non standard feature
+**ERR(2006) vpiPLI (level 2) at ***none*(0):
+  vpi_put_delays append mode more new delays (3) than old (2) - extra ignored
+  path at **fdspec01.v(88) has delay #(280, 500, 280, 280, 500, 500).
+**ERR(2106) vpiPLI (level 1) at ***none*(0):
+  vpi_put_delays to object vpiModPath after simulation started - non standard feature
+**ERR(2006) vpiPLI (level 2) at ***none*(0):
+  vpi_put_delays append mode more new delays (3) than old (2) - extra ignored
+  path at **fdspec01.v(89) has delay #(80, 100, 80, 80, 100, 100).
+  $setuphold timing check at **fdspec01.v(101) limit 70.
+  $width timing check at **fdspec01.v(103) limit 600.
+  $width timing check at **fdspec01.v(104) limit 500.
+  $period timing check at **fdspec01.v(105) limit 1200.
+  $skew timing check at **fdspec01.v(106) limit 50.
+  $recovery timing check at **fdspec01.v(107) limit 200.
+**ERR(2106) vpiPLI (level 1) at ***none*(0):
+  vpi_put_delays to object vpiModPath after simulation started - non standard feature
+**ERR(2006) vpiPLI (level 2) at ***none*(0):
+  vpi_put_delays append mode more new delays (3) than old (2) - extra ignored
+  path at **fdspec01.v(88) has delay #(280, 500, 280, 280, 500, 500).
+**ERR(2106) vpiPLI (level 1) at ***none*(0):
+  vpi_put_delays to object vpiModPath after simulation started - non standard feature
+**ERR(2006) vpiPLI (level 2) at ***none*(0):
+  vpi_put_delays append mode more new delays (3) than old (2) - extra ignored
+  path at **fdspec01.v(89) has delay #(80, 100, 80, 80, 100, 100).
+  $setuphold timing check at **fdspec01.v(101) limit 70.
+  $width timing check at **fdspec01.v(103) limit 600.
+  $width timing check at **fdspec01.v(104) limit 500.
+  $period timing check at **fdspec01.v(105) limit 1200.
+  $skew timing check at **fdspec01.v(106) limit 50.
+  $recovery timing check at **fdspec01.v(107) limit 200.
+**ERR(2106) vpiPLI (level 1) at ***none*(0):
+  vpi_put_delays to object vpiModPath after simulation started - non standard feature
+**ERR(2006) vpiPLI (level 2) at ***none*(0):
+  vpi_put_delays append mode more new delays (3) than old (2) - extra ignored
+  path at **fdspec01.v(88) has delay #(280, 500, 280, 280, 500, 500).
+**ERR(2106) vpiPLI (level 1) at ***none*(0):
+  vpi_put_delays to object vpiModPath after simulation started - non standard feature
+**ERR(2006) vpiPLI (level 2) at ***none*(0):
+  vpi_put_delays append mode more new delays (3) than old (2) - extra ignored
+  path at **fdspec01.v(89) has delay #(80, 100, 80, 80, 100, 100).
+  $setuphold timing check at **fdspec01.v(101) limit 70.
+  $width timing check at **fdspec01.v(103) limit 600.
+  $width timing check at **fdspec01.v(104) limit 500.
+  $period timing check at **fdspec01.v(105) limit 1200.
+  $skew timing check at **fdspec01.v(106) limit 50.
+  $recovery timing check at **fdspec01.v(107) limit 200.
+  All instances processed.
diff --git a/tests_and_examples/examples.vpi/vsetval1.c b/tests_and_examples/examples.vpi/vsetval1.c
new file mode 100644
index 0000000..5036e99
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vsetval1.c
@@ -0,0 +1,363 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/* vpi put value and tf_ style system task emulation test */
+/* also shows how to keep track of one vpi_ task called from multiple */
+/* instances */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+#define TRUE 1
+#define FALSE 0
+
+/* should allocate dynamically depending on number of instances */
+/* my local storage */
+struct t_my_instid {
+ int id;
+ char *ifullnam;
+};
+
+vpiHandle last_schd_evh[100];
+char *instnam_tab[100]; 
+int last_evh;
+
+/* local function prototypes */
+static int getadd_inst_id(vpiHandle);
+static p_vpi_value bld_valrec(p_vpi_value, int);
+
+/* global function prototypes */
+extern int vsetval(void);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_my_systfs(void); 
+extern void register_cbs(void);
+
+/*
+ * set a variable to value after delay
+ *
+ * form: vsetval([net/reg[bit] lvalue], value, delay, [optional delay mode]);
+ * shows code similar to PLI 1.0 tf_strdelputp or tf_setdelay and tf_putp
+ *
+ * if put value event scheduled, sets global, call with no schedule leaves
+ * last as it was
+ *
+ * here task follows Verilog semantics where only 1 set of of storage
+ * even if multiple calls in one instance
+ */
+int vsetval(void)
+{
+ int numargs, inst_id, vtyp, lhs_wire;
+ vpiHandle href, mhref, iter, aref, lvalref, assign_ref; 
+ p_vpi_value valp;
+ s_vpi_value tmpval;
+ p_vpi_time timp;
+
+ /* get the task call handle */
+ href = vpi_handle(vpiSysTfCall, NULL); 
+ /* need vpiModule (instance) call in handle */ 
+ mhref = vpi_handle(vpiScope, href);
+ /* if $vsetval task invoked from system task, get module task def. in */  
+ if (vpi_get(vpiType, mhref) != vpiModule)
+  mhref = vpi_handle(vpiModule, mhref); 
+ inst_id = getadd_inst_id(mhref);
+ 
+ iter = vpi_iterate(vpiArgument, href);
+
+ /* not sure if vpiSize property really in standard for iterators */
+ numargs = vpi_get(vpiSize, iter);
+
+ /* should set flags and check each inst first time called */
+ /* or maybe better just save processed arg handles */
+ /* 4th delay type name as string optional */
+ if (iter == NULL || numargs < 3)
+  {
+bad_args:
+   vpi_printf(
+    "**ERR: $vsetval bad args, form: (net/reg[bit], value, time, [delay type])\n");
+   return(0);
+  }
+ /* know iterator components must be expressions */
+ /* first argument assigned to lvalue */
+ if ((lvalref = vpi_scan(iter)) == NULL) goto bad_args;
+
+ vtyp = vpi_get(vpiType, lvalref);
+ /* must be lvalue */ 
+ /* notice not allowing assignment to part select handle */
+ /* could add part select assignments by decomposing to bit handles */ 
+ if (vtyp == vpiMemoryWord || vtyp == vpiConstant || vtyp == vpiOperation
+  || vtyp == vpiPartSelect) goto bad_args; 
+
+ /* allocate driver handle if non reg */
+ if (vtyp == vpiNet || vtyp == vpiNetBit)
+  {
+   if ((assign_ref = vpi_put_value(lvalref, NULL, NULL, vpiAddDriver)) == NULL)
+    goto bad_args;
+  }
+ else { assign_ref = lvalref; lhs_wire = FALSE; }
+
+ if ((aref = vpi_scan(iter)) == NULL) goto bad_args;
+ /* idea here is let passed value object (net) type determine format */
+ /* notice because get value uses internal reused works */
+ tmpval.format = vpiObjTypeVal;
+ vpi_get_value(aref, &tmpval);
+ /* size is size of passed rhs new value expression */
+ valp = bld_valrec(&tmpval, vpi_get(vpiSize, aref));
+
+ if ((aref = vpi_scan(iter)) == NULL) goto bad_args;
+ tmpval.format = vpiTimeVal;
+ vpi_get_value(aref, &tmpval);
+ timp = (p_vpi_time) malloc(sizeof(s_vpi_time));
+ *timp = *(tmpval.value.time);
+
+ /* if 4th arg omitted - assume inertial */
+ if ((aref = vpi_scan(iter)) != NULL)
+  {
+   /* since user file needs vpi_user.h anyway, should use numeric constant */
+   tmpval.format = vpiStringVal; 
+   vpi_get_value(aref, &tmpval);
+   if (strcmp(tmpval.value.str, "vpiInertialDelay") == 0)
+    {
+     /* works because already replaced lvalue with driver for wires */  
+     last_schd_evh[inst_id] = vpi_put_value(assign_ref, valp, timp,
+      vpiInertialDelay | vpiReturnEvent);
+     return(0);
+    }
+   if (strcmp(tmpval.value.str, "vpiTransportDelay") == 0)
+    {
+     last_schd_evh[inst_id] = vpi_put_value(assign_ref, valp, timp,
+      vpiTransportDelay | vpiReturnEvent);
+     return(0);
+    }
+   if (strcmp(tmpval.value.str, "vpiPureTransportDelay") == 0)
+    {
+     last_schd_evh[inst_id] = vpi_put_value(assign_ref, valp, timp,
+      vpiPureTransportDelay | vpiReturnEvent);
+     return(0);
+    }
+   if (strcmp(tmpval.value.str, "vpiNoDelay") == 0)
+    { vpi_put_value(assign_ref, valp, NULL, vpiNoDelay); return(0); }
+
+   if (strcmp(tmpval.value.str, "vpiForceFlag") == 0)
+    { vpi_put_value(lvalref, valp, NULL, vpiForceFlag); return(0); }
+   /* here, value after release placed in valp - better be big enough */
+   if (strcmp(tmpval.value.str, "vpiReleaseFlag") == 0)
+    { vpi_put_value(lvalref, valp, NULL, vpiReleaseFlag); return(0); }
+   if (strcmp(tmpval.value.str, "vpiCancelEvent") == 0)
+    {
+     /* cancel last scheduled event if has not yet happened */
+     if (last_schd_evh[inst_id] == NULL
+      || !vpi_get(vpiScheduled, last_schd_evh[inst_id]))
+      {
+       vpi_printf(
+        "**WARN: no previous scheduled event or previous event occurred\n");
+      }
+     /* for wire this will be event from driver assign */
+     /* for vector this is table handle with even (if present) per bit */
+     else vpi_put_value(last_schd_evh[inst_id], NULL, NULL, vpiCancelEvent);
+     return(0);
+    }
+   vpi_printf("**WARN: unrecognized delay type %s - vpiInertialDelay used\n",
+    tmpval.value.str); 
+  }
+ /* none or unknown, use inertial */
+ last_schd_evh[inst_id] = vpi_put_value(assign_ref, valp, timp,
+  vpiInertialDelay | vpiReturnEvent);
+ return(0);
+}
+
+/*
+ * add-get unique instance index
+ *
+ * better to use hashing or or least sorted array here
+ * or, if an iterator to get all instances of a given were added to P1364
+ * standard, this could be just a table index
+ */
+static int getadd_inst_id(vpiHandle mhref)
+{
+ register int i;
+ char *chp;
+ 
+ chp = vpi_get_str(vpiFullName, mhref);
+ for (i = 0; i <= last_evh; i++)  
+  { if (strcmp(instnam_tab[i], chp) == 0) return(i); }
+ instnam_tab[++last_evh] = malloc(strlen(chp) + 1);
+ strcpy(instnam_tab[last_evh], chp);
+ return(last_evh);
+} 
+
+/*
+ * routine to allocate and copy a t_vpi_value record
+ *
+ * needed because t_vpi_value filled value fields use one internal 
+ * buffer that is over-written by next call to vpi_get_value
+ *
+ * if passed non valp will probably crash
+ * needs width only for vpiVectorVal format, ignored otherwise
+ */
+static p_vpi_value bld_valrec(p_vpi_value valp, int blen)
+{
+ int numvals;
+ s_vpi_value wrkval;
+ p_vpi_value newvalp;
+
+ /* copy to avoid need to fill non pointer cases */
+ wrkval = *valp;
+ switch (valp->format) {
+  case vpiBinStrVal: case vpiOctStrVal: case vpiDecStrVal: case vpiHexStrVal:
+  case vpiStringVal:
+   wrkval.value.str = malloc(strlen(valp->value.str) + 1);
+   strcpy(wrkval.value.str, valp->value.str);
+   break;
+  case vpiScalarVal: case vpiIntVal: case vpiRealVal:
+   break;  
+  case vpiVectorVal:
+   /* assuming int type always 32 bits */ 
+   numvals = (blen + 31) >> 5;
+   /* notice t_vpi_vecval is really array of the 2 integer a/b sections */
+   wrkval.value.vector = (p_vpi_vecval) malloc(numvals*sizeof(s_vpi_vecval));
+#ifdef __sparc__
+   /* notice this copies from arg1 to arg2 */
+   bcopy((char *) valp->value.vector, (char *) wrkval.value.vector,
+    numvals*sizeof(s_vpi_vecval));
+#else
+   memmove((char *) wrkval.value.vector, (char *) valp->value.vector,
+    numvals*sizeof(s_vpi_vecval));
+#endif
+   break;
+  case vpiStrengthVal:
+   wrkval.value.strength = (p_vpi_strengthval)
+    malloc(sizeof(s_vpi_strengthval));
+   *(wrkval.value.strength) = *(valp->value.strength);
+   break;
+  case vpiTimeVal:
+   wrkval.value.time = (p_vpi_time) malloc(sizeof(s_vpi_time));
+   *(wrkval.value.time) = *(valp->value.time);
+  case vpiObjTypeVal: case vpiSuppressVal:
+   vpi_printf(
+    "**ERR: can not copy vpiObjTypeVal or vpiSuppressVal formats - not for filled records.\n");
+   return(NULL);
+  default: 
+   vpi_printf(
+    "**ERR: can not copy t_vpi_value record - format code %d illegal.\n",
+    valp->format);
+  return(NULL);
+ }
+ newvalp = (p_vpi_value) malloc(sizeof(s_vpi_value));
+ *newvalp = wrkval;
+ return(newvalp);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register start of sim call backs and set up error handling
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ * start of sim is first when internal data base completed
+ */
+void register_cbs(void)
+{
+ register int i;
+ vpiHandle href;
+ struct t_cb_data *ecbp, cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: can not regiser register error handler callback.\n");
+
+ /* my variable initialization can go here */
+ for (i = 0; i < 100; i++) last_schd_evh[i] = NULL; 
+ last_evh = -1;
+}
+
+/* Template function table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register system tasks */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_my_systfs, 
+ register_cbs,
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf registering is done here */
+
+/*
+ * register all vpi_ PLI 2.0 style user system tasks and functions
+ */
+void register_my_systfs(void)
+{
+ p_vpi_systf_data systf_data_p;
+
+ /* use predefined table form - could fill systf_data_list dynamically */
+ static s_vpi_systf_data systf_data_list[] = {
+  { vpiSysTask, 0, "$vsetval", vsetval, NULL, NULL, NULL },
+  { 0, 0, NULL, NULL, NULL, NULL, NULL }
+ };
+
+ systf_data_p = &(systf_data_list[0]);
+ while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vsetval1.col b/tests_and_examples/examples.vpi/vsetval1.col
new file mode 100644
index 0000000..36701ce
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vsetval1.col
@@ -0,0 +1,332 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/* vpi put value and tf_ style system task emulation test */
+/* also shows how to keep track of one vpi_ task called from multiple */
+/* instances */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../pli_incs/veriuser.h"
+#include "../pli_incs/cv_veriuser.h"
+#include "../pli_incs/vpi_user.h"
+#include "../pli_incs/cv_vpi_user.h"
+
+/* should allocate dynamically depending on number of instances */
+/* my local storage */
+struct t_my_instid {
+ int id;
+ char *ifullnam;
+};
+
+struct t_cb_data cbrec;
+vpiHandle last_schd_evh[100];
+char *instnam_tab[100]; 
+int last_evh;
+
+/* local function prototypes */
+static int getadd_inst_id(vpiHandle);
+static p_vpi_value bld_valrec(p_vpi_value, int);
+
+/* global function prototypes */
+extern int vsetval(void);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_my_systfs(void); 
+extern void register_cbs(void);
+
+/*
+ * set a variable to value after delay
+ *
+ * form: vsetval([net/reg[bit] lvalue], value, delay, [optional delay mode]);
+ * shows code similar to PLI 1.0 tf_strdelputp or tf_setdelay and tf_putp
+ *
+ * if put value event scheduled, sets global, call with no schedule leaves
+ * last as it was
+ *
+ * here task follows Verilog semantics where only 1 set of of storage
+ * even if multiple calls in one instance
+ */
+int vsetval(void)
+{
+ int numargs, inst_id;
+ vpiHandle href, mhref, iter, aref;
+ p_vpi_value valp;
+ s_vpi_value tmpval;
+ p_vpi_time timp;
+
+ /* get the task call handle */
+ href = vpi_handle(vpiSysTfCall, NULL); 
+ /* need vpiModule (instance) call in handle */ 
+ mhref = vpi_handle(vpiScope, href);
+ /* if $vsetval task invoked from system task, get module task def. in */  
+ if (vpi_get(vpiType, mhref) != vpiModule)
+  mhref = vpi_handle(vpiModule, mhref); 
+ inst_id = getadd_inst_id(mhref);
+ 
+ iter = vpi_iterate(vpiArgument, href);
+
+ /* not sure if vpiSize property really in standard for iterators */
+ numargs = vpi_get(vpiSize, iter);
+
+ /* should set flags and check each inst first time called */
+ /* or maybe better just save processed arg handles */
+ /* 4th delay type name as string optional */
+ if (iter == NULL || numargs < 3)
+  {
+bad_args:
+   vpi_printf(
+    "**ERR: $vsetval bad args, form: (net/reg[bit], value, time, [delay type])\n");
+   return(0);
+  }
+ /* know iterator components must be expressions */
+ /* first lvalue expression */
+ if ((aref = vpi_scan(iter)) == NULL) goto bad_args;
+ if (vpi_get(vpiType, aref) == vpiMemoryWord) goto bad_args; 
+
+ if ((aref = vpi_scan(iter)) == NULL) goto bad_args;
+ /* idea here is let passed value object (net) type determine format */
+ /* notice because get value uses internal reused works */
+ tmpval.format = vpiObjTypeVal;
+ vpi_get_value(aref, &tmpval);
+ /* size is size of passed rhs new value expression */
+ valp = bld_valrec(&tmpval, vpi_get(vpiSize, aref));
+
+ if ((aref = vpi_scan(iter)) == NULL) goto bad_args;
+ tmpval.format = vpiTimeVal;
+ vpi_get_value(aref, &tmpval);
+ timp = (p_vpi_time) malloc(sizeof(s_vpi_time));
+ *timp = *(tmpval.value.time);
+
+ /* if 4th arg omitted - assume inertial */
+ if ((aref = vpi_scan(iter)) != NULL)
+  {
+   /* since user file needs vpi_user.h anyway, should use numeric constant */
+   tmpval.format = vpiStringVal; 
+   vpi_get_value(aref, &tmpval);
+   if (strcmp(tmpval.value.str, "vpiInertialDelay") == 0)
+    {
+     last_schd_evh[inst_id] = vpi_put_value(aref, valp, timp,
+      vpiInertialDelay | vpiReturnEvent);
+     return(0);
+    }
+   if (strcmp(tmpval.value.str, "vpiTransportDelay") == 0)
+    {
+     last_schd_evh[inst_id] = vpi_put_value(aref, valp, timp,
+      vpiTransportDelay | vpiReturnEvent);
+     return(0);
+    }
+   if (strcmp(tmpval.value.str, "vpiPureTransportDelay") == 0)
+    {
+     last_schd_evh[inst_id] = vpi_put_value(aref, valp, timp,
+      vpiPureTransportDelay | vpiReturnEvent);
+     return(0);
+    }
+   if (strcmp(tmpval.value.str, "vpiNoDelay") == 0)
+    { vpi_put_value(aref, valp, NULL, vpiNoDelay); return(0); }
+   if (strcmp(tmpval.value.str, "vpiForceFlag") == 0)
+    { vpi_put_value(aref, valp, NULL, vpiForceFlag); return(0); }
+   /* here, value after release placed in valp - better be big enough */
+   if (strcmp(tmpval.value.str, "vpiReleaseFlag") == 0)
+    { vpi_put_value(aref, valp, NULL, vpiReleaseFlag); return(0); }
+   if (strcmp(tmpval.value.str, "vpiCancelEvent") == 0)
+    {
+     /* cancel last scheduled event if has not yet happened */
+     if (last_schd_evh[inst_id] == NULL
+      || !vpi_get(vpiScheduled, last_schd_evh[inst_id]))
+      {
+       vpi_printf(
+        "**WARN: no previous scheduled event or previous event occurred\n");
+      }
+     else vpi_put_value(last_schd_evh[inst_id], NULL, NULL, vpiCancelEvent);
+     return(0);
+    }
+   vpi_printf("**WARN: unrecognized delay type %s - vpiInertialDelay used\n",
+    tmpval.value.str); 
+  }
+ /* none or unknown, use inertial */
+ last_schd_evh[inst_id] = vpi_put_value(aref, valp, timp,
+  vpiInertialDelay | vpiReturnEvent);
+ return(0);
+}
+
+/*
+ * add-get unique instance index
+ *
+ * better to use hashing or or least sorted array here
+ * or, if an iterator to get all instances of a given were added to P1364
+ * standard, this could be just a table index
+ */
+static int getadd_inst_id(vpiHandle mhref)
+{
+ register int i;
+ char *chp;
+ 
+ chp = vpi_get_str(vpiFullName, mhref);
+ for (i = 0; i <= last_evh; i++)  
+  { if (strcmp(instnam_tab[i], chp) == 0) return(i); }
+ instnam_tab[++last_evh] = malloc(strlen(chp) + 1);
+ strcpy(instnam_tab[last_evh], chp);
+ return(last_evh);
+} 
+
+/*
+ * routine to allocate and copy a t_vpi_value record
+ *
+ * needed because t_vpi_value filled value fields use one internal 
+ * buffer that is over-written by next call to vpi_get_value
+ *
+ * if passed non valp will probably crash
+ * needs width only for vpiVectorVal format, ignored otherwise
+ */
+static p_vpi_value bld_valrec(p_vpi_value valp, int blen)
+{
+ int numvals;
+ s_vpi_value wrkval;
+ p_vpi_value newvalp;
+
+ /* copy to avoid need to fill non pointer cases */
+ wrkval = *valp;
+ switch (valp->format) {
+  case vpiBinStrVal: case vpiOctStrVal: case vpiDecStrVal: case vpiHexStrVal:
+  case vpiStringVal:
+   wrkval.value.str = malloc(strlen(valp->value.str) + 1);
+   strcpy(wrkval.value.str, valp->value.str);
+   break;
+  case vpiScalarVal: case vpiIntVal: case vpiRealVal:
+   break;  
+  case vpiVectorVal:
+   /* assuming int type always 32 bits */ 
+   numvals = (blen + 31) >> 5;
+   /* notice t_vpi_vecval is really array of the 2 integer a/b sections */
+   wrkval.value.vector = (p_vpi_vecval) malloc(numvals*sizeof(s_vpi_vecval));
+#ifdef __sparc__
+   /* notice this copies from arg1 to arg2 */
+   bcopy((char *) valp->value.vector, (char *) wrkval.value.vector,
+    numvals*sizeof(s_vpi_vecval));
+#else
+   memmove((char *) wrkval.value.vector, (char *) valp->value.vector,
+    numvals*sizeof(s_vpi_vecval));
+#endif
+   break;
+  case vpiStrengthVal:
+   wrkval.value.strength = (p_vpi_strengthval)
+    malloc(sizeof(s_vpi_strengthval));
+   *(wrkval.value.strength) = *(valp->value.strength);
+   break;
+  case vpiTimeVal:
+   wrkval.value.time = (p_vpi_time) malloc(sizeof(s_vpi_time));
+   *(wrkval.value.time) = *(valp->value.time);
+  case vpiObjTypeVal: case vpiSuppressVal:
+   vpi_printf(
+    "**ERR: can not copy vpiObjTypeVal or vpiSuppressVal formats - not for filled records.\n");
+   return(NULL);
+  default: 
+   vpi_printf(
+    "**ERR: can not copy t_vpi_value record - format code %d illegal.\n",
+    valp->format);
+  return(NULL);
+ }
+ newvalp = (p_vpi_value) malloc(sizeof(s_vpi_value));
+ *newvalp = wrkval;
+ return(newvalp);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   tf_dofinish();
+  }
+ return(0);
+}
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register start of sim call backs and set up error handling
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ * start of sim is first when internal data base completed
+ */
+void register_cbs(void)
+{
+ register int i;
+ vpiHandle href;
+ struct t_cb_data *ecbp;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: can not regiser register error handler callback.\n");
+
+ /* my variable initialization can go here */
+ for (i = 0; i < 100; i++) last_schd_evh[i] = NULL; 
+ last_evh = -1;
+}
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register system tasks */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_my_systfs, 
+ register_cbs,
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf registering is done here */
+
+/*
+ * register all vpi_ PLI 2.0 style user system tasks and functions
+ */
+void register_my_systfs(void)
+{
+ p_vpi_systf_data systf_data_p;
+
+ /* use predefined table form - could fill systf_data_list dynamically */
+ static s_vpi_systf_data systf_data_list[] = {
+  { vpiSysTask, 0, "$vsetval", vsetval, NULL, NULL, NULL },
+  { 0, 0, NULL, NULL, NULL, NULL, NULL }
+ };
+
+ systf_data_p = &(systf_data_list[0]);
+ while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
diff --git a/tests_and_examples/examples.vpi/vsetval1.plg b/tests_and_examples/examples.vpi/vsetval1.plg
new file mode 100644
index 0000000..403abca
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vsetval1.plg
@@ -0,0 +1,12 @@
+         0 a=0000, w=0 (rw=0), wa=00000000000000000000000000000000 (rwa=00000000000000000000000000000000)
+        25 a=0020, w=0 (rw=0), wa=00000000000000000000000000000000 (rwa=00000000000000000000000000000000)
+       190 a=55aa, w=0 (rw=0), wa=00000000000000000000000000000000 (rwa=00000000000000000000000000000000)
+       290 a=55aa, w=x (rw=0), wa=00000000000000000000000000000000 (rwa=00000000000000000000000000000000)
+       420 a=55aa, w=1 (rw=z), wa=00000000000000000000000000000000 (rwa=00000000000000000000000000000000)
+       500 a=55aa, w=x (rw=z), wa=00000000000000000000000000000000 (rwa=00000000000000000000000000000000)
+      1125 a=55aa, w=x (rw=z), wa=00000000000000000000000000x00000 (rwa=00000000000000000000000000000000)
+      1300 a=55aa, w=x (rw=z), wa=zzzzzzzzzzzzzzzzzzzzzzzzzzxzzzzz (rwa=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)
+      1310 a=55aa, w=x (rw=z), wa=11111111111111111111111111111111 (rwa=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)
+      1320 a=55aa, w=x (rw=z), wa=zzzzzzzzzzzzzzzzzzzzzzzzzzxzzzzz (rwa=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)
+      1390 a=55aa, w=x (rw=z), wa=00000000000001011010101001x10101 (rwa=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)
+      1480 a=55aa, w=x (rw=z), wa=000000000000xxxxxxxxxxxxxxxxxxxx (rwa=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)
diff --git a/tests_and_examples/examples.vpi/vsetval1.v b/tests_and_examples/examples.vpi/vsetval1.v
new file mode 100644
index 0000000..dc6a6ce
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vsetval1.v
@@ -0,0 +1,62 @@
+//
+// test of strdelputp - copy from input system task to output then
+// compare results to make same
+//
+
+module top;
+ xx i1();
+ xx i2();
+ xx i3();
+ xx i4();
+ initial
+  begin  
+   $monitor($stime,, "a=%h, w=%b (rw=%b), wa=%b (rwa=%b)", 
+     i2.a, i2.w, i2.rw, i2.wa, i2.rwa); 
+  end
+endmodule
+
+module xx;
+ reg [31:0] rwa; 
+ reg rw;
+ reg [15:0] a, b;
+ wire w;
+ wire [31:0] wa; 
+ parameter d = 500; 
+
+ assign wa = rwa;
+ assign w = rw;
+
+ initial
+  begin
+   a = 0; rw = 0;
+   // blocks changes a 15 reg and w (1 bit wire) only */
+   $vsetval(a[5], 1'b1, 25, "vpiInertialDelay");
+   /* schedule put value to register - just assigns */
+   #100 $vsetval(a, 16'h55aa, 90);  
+   /* notice minor bug here since w is a scalar vector is 16 bits, it */
+   /* happens that at least in Cver narrowing width change assigns work, */
+   /* but widening especially into a higher word probably core dumps */
+   /* also this will schedule transition to x at 290 since other driver 0 */
+   #100 $vsetval(w, 16'haa55, 90);  
+   /* remove vpi_set_value driver conflict, so schedule back to 0 at 340 */ 
+   #100 $vsetval(w, 16'hzzzz, 40);
+   /* cancel schedule of one bit to z, uses last event, w just place holder */
+   #20 $vsetval(w, 0, 0, "vpiCancelEvent");  
+   #100 rw = 1'bz; $vsetval(w, 1, 63); 
+   /* this is inertial reschedule (remove early, save late) */ 
+   #30 $vsetval(w, 0, 50);
+  end
+
+ initial
+  begin
+   // blocks changes wire wa only */
+   rwa = 32'b0;
+   #1000 
+   #100 $vsetval(wa[5], 1'b1, 25, "vpiInertialDelay");
+   #100 $vsetval(wa[5], 1'b0, 25, "vpiInertialDelay");
+   #100 $vsetval(wa, 20'h5aa55, 90); rwa = 32'bz;  
+   #10 $vsetval(wa, 32'hffffffff, 0, "vpiForceFlag");
+   #10 $vsetval(wa, 0, 0, "vpiReleaseFlag");
+   #80 $vsetval(wa, 20'ha55aa, 80);  
+  end
+endmodule
diff --git a/tests_and_examples/examples.vpi/vsetval2.c b/tests_and_examples/examples.vpi/vsetval2.c
new file mode 100644
index 0000000..ae1cea1
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vsetval2.c
@@ -0,0 +1,446 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/* vpi put value and tf_ style system task emulation test */
+/* also shows how to keep track of one vpi_ task called from multiple */
+/* instances */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+/* should allocate dynamically depending on number of instances */
+/* my local storage */
+struct t_my_instid {
+ int id;
+ char *ifullnam;
+};
+
+vpiHandle last_schd_evh[100];
+char *instnam_tab[100]; 
+int last_evh;
+
+/* local function prototypes */
+static int getadd_inst_id(vpiHandle);
+static vpiHandle get_vpi_driver(vpiHandle);
+static p_vpi_value bld_valrec(p_vpi_value, int);
+
+/* global function prototypes */
+extern int vsetval(void);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_my_systfs(void); 
+extern void register_cbs(void);
+
+/*
+ * set a variable to value after delay
+ *
+ * form: vsetval([net/reg[bit] lvalue], value, delay, [optional delay mode]);
+ * shows code similar to PLI 1.0 tf_strdelputp or tf_setdelay and tf_putp
+ *
+ * if put value event scheduled, sets global, call with no schedule leaves
+ * last as it was
+ *
+ * here task follows Verilog semantics where only 1 set of of storage
+ * even if multiple calls in one instance
+ */
+int vsetval(void)
+{
+ int numargs, inst_id, vtyp, flags;
+ vpiHandle href, mhref, iter, aref, lvalref, assign_ref; 
+ p_vpi_value valp;
+ s_vpi_value tmpval;
+ p_vpi_time timp;
+ char putv_type[128];
+
+ /* get the task call handle */
+ href = vpi_handle(vpiSysTfCall, NULL); 
+ /* need vpiModule (instance) call in handle */ 
+ mhref = vpi_handle(vpiScope, href);
+ /* if $vsetval task invoked from system task, get module task def. in */  
+ if (vpi_get(vpiType, mhref) != vpiModule)
+  mhref = vpi_handle(vpiModule, mhref); 
+ inst_id = getadd_inst_id(mhref);
+ 
+ iter = vpi_iterate(vpiArgument, href);
+
+ /* not sure if vpiSize property really in standard for iterators */
+ numargs = vpi_get(vpiSize, iter);
+
+ /* should set flags and check each inst first time called */
+ /* or maybe better just save processed arg handles */
+ /* 4th delay type name as string optional */
+ if (iter == NULL || numargs < 3)
+  {
+bad_args:
+   vpi_printf(
+    "**ERR: $vsetval bad args, form: (net/reg[bit], value, time, [delay type])\n");
+   return(0);
+  }
+ /* know iterator components must be expressions */
+ /* first argument assigned to lvalue */
+ if ((lvalref = vpi_scan(iter)) == NULL) goto bad_args;
+
+ vtyp = vpi_get(vpiType, lvalref);
+ /* must be lvalue */ 
+ /* notice not allowing assignment to part select handle */
+ /* could add part select assignments by decomposing to bit handles */ 
+ if (vtyp == vpiMemoryWord || vtyp == vpiConstant || vtyp == vpiOperation
+  || vtyp == vpiPartSelect) goto bad_args; 
+
+ if ((aref = vpi_scan(iter)) == NULL) goto bad_args;
+ /* idea here is let passed value object (net) type determine format */
+ /* notice because get value uses internal reused works */
+ tmpval.format = vpiObjTypeVal;
+ vpi_get_value(aref, &tmpval);
+ /* size is size of passed rhs new value expression */
+ valp = bld_valrec(&tmpval, vpi_get(vpiSize, aref));
+
+ if ((aref = vpi_scan(iter)) == NULL) goto bad_args;
+ tmpval.format = vpiTimeVal;
+ vpi_get_value(aref, &tmpval);
+ timp = (p_vpi_time) malloc(sizeof(s_vpi_time));
+ *timp = *(tmpval.value.time);
+
+ /* if 4th arg omitted - assume inertial */
+ if ((aref = vpi_scan(iter)) != NULL)
+  {
+   /* since user file needs vpi_user.h anyway, should use numeric constant */
+   tmpval.format = vpiStringVal; 
+   vpi_get_value(aref, &tmpval);
+   strcpy(putv_type, tmpval.value.str); 
+   if (strcmp(putv_type, "vpiInertialDelay") == 0)
+    flags = vpiInertialDelay;  
+   else if (strcmp(putv_type, "vpiTransportDelay") == 0)
+    flags = vpiTransportDelay;  
+   else if (strcmp(putv_type, "vpiPureTransportDelay") == 0)
+    flags = vpiPureTransportDelay;  
+   else if (strcmp(putv_type, "vpiNoDelay") == 0) flags = vpiNoDelay;
+   else if (strcmp(putv_type, "vpiForceFlag") == 0) flags = vpiForceFlag;
+   else if (strcmp(putv_type, "vpiReleaseFlag") == 0) flags = vpiReleaseFlag;
+   else if (strcmp(putv_type, "vpiCancelEvent") == 0) flags = vpiCancelEvent;
+   else goto bad_args;
+  }
+ else { strcpy(putv_type, "vpiInertialDelay"); flags = vpiInertialDelay; }
+
+ /* allocate driver handle if non reg and non force/release/deschedule flag */
+ if (vtyp == vpiNet || vtyp == vpiNetBit)
+  {
+   if (flags == vpiInertialDelay || flags == vpiTransportDelay
+    || flags == vpiPureTransportDelay || flags == vpiNoDelay)
+    {
+     if ((assign_ref = get_vpi_driver(lvalref)) == NULL)
+      {
+       if ((assign_ref = vpi_put_value(lvalref, NULL, NULL, vpiAddDriver))
+        == NULL) goto bad_args;
+      }
+    }
+   else assign_ref = lvalref; 
+  }
+ /* for non wire lval and assign handles same */
+ else assign_ref = lvalref; 
+
+ if (flags == vpiInertialDelay)
+  {
+   /* works because already replaced lvalue with driver for wires */  
+   last_schd_evh[inst_id] = vpi_put_value(assign_ref, valp, timp,
+    flags | vpiReturnEvent);
+  }
+ else if (flags == vpiTransportDelay)
+  {
+   last_schd_evh[inst_id] = vpi_put_value(assign_ref, valp, timp,
+    flags | vpiReturnEvent);
+  }
+ else if (flags == vpiPureTransportDelay)
+  {
+   last_schd_evh[inst_id] = vpi_put_value(assign_ref, valp, timp,
+    flags | vpiReturnEvent);
+  }
+ else if (flags == vpiNoDelay)
+  { 
+   vpi_put_value(assign_ref, valp, NULL, vpiNoDelay);
+  }
+ else if (flags == vpiForceFlag)
+  {
+   /* here need wire not vpi_ added driver */
+   vpi_put_value(lvalref, valp, NULL, vpiForceFlag);
+  }
+ /* here, value after release placed in valp - better be big enough */
+ else if (flags == vpiReleaseFlag)
+  {
+   vpi_put_value(lvalref, valp, NULL, vpiReleaseFlag);
+  }
+ else if (flags == vpiCancelEvent) 
+  {
+   /* cancel last scheduled event if has not yet happened */
+   if (last_schd_evh[inst_id] == NULL
+    || !vpi_get(vpiScheduled, last_schd_evh[inst_id]))
+     {
+      vpi_printf(
+       "**WARN: no previous scheduled event or previous event occurred\n");
+     }
+    /* for wire this will be event from driver assign */
+    /* for vector this is table handle with even (if present) per bit */
+    else vpi_put_value(last_schd_evh[inst_id], NULL, NULL, vpiCancelEvent);
+  }
+ else goto bad_args;
+ return(0);
+}
+
+/*
+ * get a vpi driver
+ *
+ * for vpiNetBit must be smae bit driver 
+ * for vpiNet must be entire net driver
+ */
+static vpiHandle get_vpi_driver(vpiHandle wref)
+{
+ int wtyp, drvtyp;
+ vpiHandle drviter, drvref, parref;
+ s_vpi_value tmpval;
+ char sval[1024], s1[1024];
+ 
+ /* need to provide string storage for get value */
+ tmpval.value.str = sval;
+
+ wtyp = vpi_get(vpiType, wref);
+ drviter = vpi_iterate(vpiDriver, wref);
+ for (;;)
+  {
+   if ((drvref = vpi_scan(drviter)) == NULL) break;
+
+   drvtyp = vpi_get(vpiType, drvref);
+   if (wtyp == vpiNetBit)
+    {
+     if (drvtyp != vpiNetBitDriver) continue;
+     parref = vpi_handle(vpiParent, drvref); 
+     if (vpi_compare_objects(wref, parref))
+      {
+       strcpy(s1, vpi_get_str(vpiType, drvref));
+       tmpval.format = vpiBinStrVal; 
+       vpi_get_value(drvref, &tmpval);
+       vpi_printf("reusing %s bit driver of %s current value %s.\n",
+        s1, vpi_get_str(vpiFullName, parref), tmpval.value.str);
+
+       return(drvref);
+      }
+    }
+   else if (wtyp == vpiNet)
+    {
+     if (drvtyp != vpiNetDriver) continue;
+
+     strcpy(s1, vpi_get_str(vpiType, drvref));
+     tmpval.format = vpiBinStrVal; 
+     vpi_get_value(drvref, &tmpval);
+     vpi_printf("reusing %s entire net driver of %s current value %s.\n",
+      s1, vpi_get_str(vpiFullName, wref), tmpval.value.str);
+
+     return(drvref);
+    }
+   else
+    { 
+     vpi_printf("**ERR: illegal value %s passed to get_vpi_driver.\n",
+      vpi_get_str(vpiType, wref));
+     return(NULL);
+    }
+  }
+ strcpy(s1, vpi_get_str(vpiType, wref));
+ vpi_printf("new driver added for %s %s.\n", s1,
+  vpi_get_str(vpiFullName, wref));
+ return(NULL);
+}
+
+/*
+ * add-get unique instance index
+ *
+ * better to use hashing or or least sorted array here
+ * or, if an iterator to get all instances of a given were added to P1364
+ * standard, this could be just a table index
+ */
+static int getadd_inst_id(vpiHandle mhref)
+{
+ register int i;
+ char *chp;
+ 
+ chp = vpi_get_str(vpiFullName, mhref);
+ for (i = 0; i <= last_evh; i++)  
+  { if (strcmp(instnam_tab[i], chp) == 0) return(i); }
+ instnam_tab[++last_evh] = malloc(strlen(chp) + 1);
+ strcpy(instnam_tab[last_evh], chp);
+ return(last_evh);
+} 
+
+/*
+ * routine to allocate and copy a t_vpi_value record
+ *
+ * needed because t_vpi_value filled value fields use one internal 
+ * buffer that is over-written by next call to vpi_get_value
+ *
+ * if passed non valp will probably crash
+ * needs width only for vpiVectorVal format, ignored otherwise
+ */
+static p_vpi_value bld_valrec(p_vpi_value valp, int blen)
+{
+ int numvals;
+ s_vpi_value wrkval;
+ p_vpi_value newvalp;
+
+ /* copy to avoid need to fill non pointer cases */
+ wrkval = *valp;
+ switch (valp->format) {
+  case vpiBinStrVal: case vpiOctStrVal: case vpiDecStrVal: case vpiHexStrVal:
+  case vpiStringVal:
+   wrkval.value.str = malloc(strlen(valp->value.str) + 1);
+   strcpy(wrkval.value.str, valp->value.str);
+   break;
+  case vpiScalarVal: case vpiIntVal: case vpiRealVal:
+   break;  
+  case vpiVectorVal:
+   /* assuming int type always 32 bits */ 
+   numvals = (blen + 31) >> 5;
+   /* notice t_vpi_vecval is really array of the 2 integer a/b sections */
+   wrkval.value.vector = (p_vpi_vecval) malloc(numvals*sizeof(s_vpi_vecval));
+#ifdef __sparc__
+   /* notice this copies from arg1 to arg2 */
+   bcopy((char *) valp->value.vector, (char *) wrkval.value.vector,
+    numvals*sizeof(s_vpi_vecval));
+#else
+   memmove((char *) wrkval.value.vector, (char *) valp->value.vector,
+    numvals*sizeof(s_vpi_vecval));
+#endif
+   break;
+  case vpiStrengthVal:
+   wrkval.value.strength = (p_vpi_strengthval)
+    malloc(sizeof(s_vpi_strengthval));
+   *(wrkval.value.strength) = *(valp->value.strength);
+   break;
+  case vpiTimeVal:
+   wrkval.value.time = (p_vpi_time) malloc(sizeof(s_vpi_time));
+   *(wrkval.value.time) = *(valp->value.time);
+  case vpiObjTypeVal: case vpiSuppressVal:
+   vpi_printf(
+    "**ERR: can not copy vpiObjTypeVal or vpiSuppressVal formats - not for filled records.\n");
+   return(NULL);
+  default: 
+   vpi_printf(
+    "**ERR: can not copy t_vpi_value record - format code %d illegal.\n",
+    valp->format);
+  return(NULL);
+ }
+ newvalp = (p_vpi_value) malloc(sizeof(s_vpi_value));
+ *newvalp = wrkval;
+ return(newvalp);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register start of sim call backs and set up error handling
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ * start of sim is first when internal data base completed
+ */
+void register_cbs(void)
+{
+ register int i;
+ vpiHandle href;
+ struct t_cb_data *ecbp, cbrec;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: can not regiser register error handler callback.\n");
+
+ /* my variable initialization can go here */
+ for (i = 0; i < 100; i++) last_schd_evh[i] = NULL; 
+ last_evh = -1;
+}
+
+/* Template function table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register system tasks */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_my_systfs, 
+ register_cbs,
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf registering is done here */
+
+/*
+ * register all vpi_ PLI 2.0 style user system tasks and functions
+ */
+void register_my_systfs(void)
+{
+ p_vpi_systf_data systf_data_p;
+
+ /* use predefined table form - could fill systf_data_list dynamically */
+ static s_vpi_systf_data systf_data_list[] = {
+  { vpiSysTask, 0, "$vsetval", vsetval, NULL, NULL, NULL },
+  { 0, 0, NULL, NULL, NULL, NULL, NULL }
+ };
+
+ systf_data_p = &(systf_data_list[0]);
+ while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vsetval2.plg b/tests_and_examples/examples.vpi/vsetval2.plg
new file mode 100644
index 0000000..cfd73cf
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vsetval2.plg
@@ -0,0 +1,10 @@
+         0 a=0000000000000000
+       125 a=0000000000100000
+       225 a=0000000000000000
+       325 a=0000000000100000
+       425 a=0000000000000000
+       525 a=0000000000100000
+       625 a=0000000000000000
+       725 a=0000000000100000
+       825 a=0000000000000000
+       925 a=0000000000100000
diff --git a/tests_and_examples/examples.vpi/vsetval2.v b/tests_and_examples/examples.vpi/vsetval2.v
new file mode 100644
index 0000000..18bc57f
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vsetval2.v
@@ -0,0 +1,33 @@
+//
+// test of strdelputp - copy from input system task to output then
+// compare results to make same
+//
+
+module top;
+ xx i1();
+endmodule
+
+module xx;
+ integer i;
+ reg [31:0] rwa; 
+ reg rw;
+ reg [15:0] a, b;
+ wire w;
+ wire [31:0] wa; 
+ parameter d = 500; 
+
+ assign wa = rwa;
+ assign w = rw;
+
+ initial
+  begin
+   $monitor($stime,, "a=%b", a); 
+   a = 0; rwa = 0;
+   for (i = 0; i < 1000; i = i + 100) 
+    begin
+     $vsetval(a[5], rwa, i + 25, "vpiPureTransportDelay");
+     rwa[0] = ~rwa[0];
+    end
+   #2000; 
+  end
+endmodule
diff --git a/tests_and_examples/examples.vpi/vtimcbs.c b/tests_and_examples/examples.vpi/vtimcbs.c
new file mode 100644
index 0000000..3c0fa2a
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vtimcbs.c
@@ -0,0 +1,261 @@
+/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
+
+/*
+ * test of time related cbs
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpi_user.h"
+#include "cv_vpi_user.h"
+
+int num_simstarttime_cbs;
+int num_after_cbs;
+
+/* local function prototypes */
+
+/* global function prototypes */
+extern int setup_delcbs(p_cb_data);
+extern int cbtimstart_rtn(struct t_cb_data *);
+extern int cbdel_rtn(p_cb_data);
+extern int cbwrsync_rtn(p_cb_data);
+extern int cbrosync_rtn(p_cb_data);
+extern int cbnxttim_rtn(p_cb_data);
+extern int my_error_handler(struct t_cb_data *);
+extern void register_cbs(void);
+
+int setup_delcbs(struct t_cb_data *cbp)
+{
+ struct t_cb_data cbrec;
+ p_vpi_time timp;
+
+ cbrec.reason = cbAtStartOfSimTime;
+ cbrec.cb_rtn = cbtimstart_rtn;
+ cbrec.obj = NULL; 
+ /* just allocate once */
+ timp = (p_vpi_time) malloc(sizeof(s_vpi_time));
+ timp->type = vpiSimTime;
+ timp->high = 0;
+ timp->low = 22;
+ cbrec.time = timp;
+ cbrec.value = NULL;
+ cbrec.index = 0;
+ vpi_register_cb(&cbrec); 
+
+ cbrec.reason = cbAfterDelay;
+ cbrec.obj = NULL; 
+ cbrec.cb_rtn = cbdel_rtn;
+ timp->type = vpiSimTime;
+ timp->high = 0;
+ timp->low = 43;
+ cbrec.time = timp;
+ cbrec.value = NULL;
+ cbrec.index = 0;
+ vpi_register_cb(&cbrec); 
+ return(0);
+}
+
+/*
+ * call back for start of sim delays - schedule another one (total of 20)
+ */
+int cbtimstart_rtn(p_cb_data cbp)
+{
+ vpi_printf("*** start of simulation time wake up at %d\n", cbp->time->low);
+
+ /* notice reusing passed call back for new register is really illegal */
+ cbp->cb_rtn = cbtimstart_rtn;
+ cbp->time->high = 0;
+ cbp->time->low = 6;
+ if (++num_simstarttime_cbs < 50) vpi_register_cb(cbp); 
+ return(0);
+}
+
+/*
+ * call back for normal delays 
+ */
+int cbdel_rtn(p_cb_data cbp)
+{
+ vpi_printf("*** normal delay time wake up at %d\n", cbp->time->low);
+
+ /* notice reusing passed call back for new register is really illegal */
+ cbp->reason = cbReadWriteSynch;
+ cbp->cb_rtn = cbwrsync_rtn;
+ cbp->time->high = 0;
+ cbp->time->low = 0;
+ vpi_register_cb(cbp); 
+ return(0);
+}
+
+/*
+ * ro sync cb routine
+ */
+int cbwrsync_rtn(p_cb_data cbp)
+{
+ vpi_printf("*** rw sync time wake up at %d\n", cbp->time->low);
+
+ /* not sure if legal to usurp t_cb_data since removed when event happens */
+ cbp->reason = cbReadOnlySynch;
+ cbp->cb_rtn = cbrosync_rtn;
+ cbp->obj = NULL;
+ cbp->time->high = 0;
+ cbp->time->low = 0;
+ cbp->value = NULL;
+ cbp->index = 0;
+ vpi_register_cb(cbp); 
+ return(0);
+}
+
+/*
+ * ro sync cb routine - schedules 2 events
+ */
+int cbrosync_rtn(p_cb_data cbp)
+{
+ struct t_cb_data cbrec;
+ p_vpi_time timp;
+
+ vpi_printf("*** ro sync time wake up at %d\n", cbp->time->low);
+
+ cbp->reason = cbNextSimTime;
+ cbp->cb_rtn = cbnxttim_rtn;
+ cbp->obj = NULL;
+ cbp->time->high = 0;
+ cbp->time->low = 0;
+ cbp->value = NULL;
+ cbp->index = 0;
+ vpi_register_cb(cbp); 
+
+ if (++num_after_cbs > 20) return(0);
+
+ cbrec.reason = cbAfterDelay;
+ cbrec.cb_rtn = cbdel_rtn;
+ cbrec.obj = NULL;
+ timp = (p_vpi_time) malloc(sizeof(s_vpi_time));
+ timp->type = vpiSimTime;
+ timp->high = 0;
+ timp->low = 87;
+ cbrec.time = timp;
+ cbrec.value = NULL;
+ cbrec.index = 0;
+ vpi_register_cb(&cbrec); 
+ return(0);
+}
+
+/*
+ * next sim time cb routine - no new scheduling from here
+ */
+int cbnxttim_rtn(p_cb_data cbp)
+{
+ vpi_printf("*** next sim time wake up at %d\n", cbp->time->low);
+ return(0);
+}
+
+/*
+ * routine to build an error indication string 
+ */
+int my_error_handler(struct t_cb_data *cbp)
+{
+ struct t_vpi_error_info einfotab;
+ struct t_vpi_error_info *einfop;
+ char s1[128];
+
+ einfop = &einfotab;
+ vpi_chk_error(einfop);
+
+ if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
+ else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
+ else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
+ else strcpy(s1, "**unknown**");
+
+ vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
+  einfop->code, s1, einfop->level, einfop->file, einfop->line,
+  einfop->message);
+
+ /* if serious error give up */
+ if (einfop->level == vpiError || einfop->level == vpiSystem
+  || einfop->level == vpiInternal)
+  {
+   vpi_printf("**FATAL: encountered error - giving up\n");
+   vpi_sim_control(vpiFinish, 0);
+  }
+ return(0);
+}
+
+
+/* Template functin table for added user systf tasks and functions.
+   See file vpi_user.h for structure definition
+   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
+   do not access the simulation data base may be called from these routines
+*/ 
+
+/* all routines are called to register cbs */
+/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
+/* before source is read */ 
+void (*vlog_startup_routines[]) () =
+{
+ register_cbs, 
+ 0
+};
+
+/* routine to do the systf registering - probably should go in other file */
+/* usually only vpi_ PLI 2.0 systf or cb registering is done here */
+
+/*
+ * register the start of sim scan call back and set up error handling
+ *
+ * notice making version of Cver that prints some stuff to start but
+ * is a normal Cver 
+ *
+ * since handle not save (passed back?), no way to find out cb info
+ */
+void register_cbs(void)
+{
+ vpiHandle href, href2;
+ struct t_cb_data *ecbp, *cbp;
+ struct t_cb_data cbrec;
+
+ num_simstarttime_cbs = 0;
+ num_after_cbs = 0;
+
+ /* notice cb records must be in global storage */
+ ecbp = &cbrec;
+ ecbp->reason = cbPLIError;
+ ecbp->cb_rtn = my_error_handler; 
+ ecbp->obj = NULL;
+ ecbp->time = NULL;
+ ecbp->value = NULL; 
+ ecbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href = vpi_register_cb(ecbp)) == NULL)
+  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
+
+ cbp = &cbrec;
+ cbp->reason = cbStartOfSimulation;
+ cbp->cb_rtn = setup_delcbs;
+ cbp->obj = NULL;
+ cbp->time = NULL;
+ cbp->value = NULL; 
+ cbp->user_data = NULL;
+
+ /* probably should check for error here */
+ if ((href2 = vpi_register_cb(cbp)) == NULL)
+  vpi_printf(
+   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
+ /* if not registered will be no call backs */
+
+}
+
+/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
+/* in standard PLI vlog_startup_routines table */
+void vpi_compat_bootstrap(void)
+{
+ int i;
+
+ for (i = 0;; i++) 
+  {
+   if (vlog_startup_routines[i] == NULL) break; 
+   vlog_startup_routines[i]();
+  }
+}
diff --git a/tests_and_examples/examples.vpi/vtimcbs.plg b/tests_and_examples/examples.vpi/vtimcbs.plg
new file mode 100644
index 0000000..7160d44
--- /dev/null
+++ b/tests_and_examples/examples.vpi/vtimcbs.plg
@@ -0,0 +1,142 @@
+        10 start   x: ffffffff  y: 1  count: 0
+        10 t1 started
+*** start of simulation time wake up at 22
+*** start of simulation time wake up at 28
+        30 t1 finished
+        30 return  x: 00000000  y: 0  count: 1
+        30 t1 started
+*** start of simulation time wake up at 34
+        35 return  x: 00000000  y: 0  count: 1
+        35 t1 started
+*** start of simulation time wake up at 40
+*** normal delay time wake up at 43
+*** rw sync time wake up at 43
+*** ro sync time wake up at 43
+*** next sim time wake up at 45
+*** start of simulation time wake up at 46
+*** start of simulation time wake up at 52
+        55 t1 finished
+        55 return  x: 00000002  y: 0  count: 2
+*** start of simulation time wake up at 58
+*** start of simulation time wake up at 64
+*** start of simulation time wake up at 70
+*** start of simulation time wake up at 76
+*** start of simulation time wake up at 82
+*** start of simulation time wake up at 88
+*** start of simulation time wake up at 94
+*** start of simulation time wake up at 100
+*** start of simulation time wake up at 106
+*** start of simulation time wake up at 112
+*** start of simulation time wake up at 118
+*** start of simulation time wake up at 124
+*** start of simulation time wake up at 130
+*** normal delay time wake up at 130
+*** rw sync time wake up at 130
+*** ro sync time wake up at 130
+*** next sim time wake up at 136
+*** start of simulation time wake up at 136
+*** start of simulation time wake up at 142
+*** start of simulation time wake up at 148
+*** start of simulation time wake up at 154
+*** start of simulation time wake up at 160
+*** start of simulation time wake up at 166
+*** start of simulation time wake up at 172
+*** start of simulation time wake up at 178
+*** start of simulation time wake up at 184
+*** start of simulation time wake up at 190
+*** start of simulation time wake up at 196
+*** start of simulation time wake up at 202
+*** start of simulation time wake up at 208
+*** start of simulation time wake up at 214
+*** normal delay time wake up at 217
+*** rw sync time wake up at 217
+*** ro sync time wake up at 217
+*** next sim time wake up at 220
+*** start of simulation time wake up at 220
+*** start of simulation time wake up at 226
+*** start of simulation time wake up at 232
+*** start of simulation time wake up at 238
+*** start of simulation time wake up at 244
+*** start of simulation time wake up at 250
+*** start of simulation time wake up at 256
+*** start of simulation time wake up at 262
+*** start of simulation time wake up at 268
+*** start of simulation time wake up at 274
+*** start of simulation time wake up at 280
+*** start of simulation time wake up at 286
+*** start of simulation time wake up at 292
+*** start of simulation time wake up at 298
+*** start of simulation time wake up at 304
+*** normal delay time wake up at 304
+*** rw sync time wake up at 304
+*** ro sync time wake up at 304
+*** next sim time wake up at 310
+*** start of simulation time wake up at 310
+*** start of simulation time wake up at 316
+*** normal delay time wake up at 391
+*** rw sync time wake up at 391
+*** ro sync time wake up at 391
+*** next sim time wake up at 478
+*** normal delay time wake up at 478
+*** rw sync time wake up at 478
+*** ro sync time wake up at 478
+*** next sim time wake up at 565
+*** normal delay time wake up at 565
+*** rw sync time wake up at 565
+*** ro sync time wake up at 565
+*** next sim time wake up at 652
+*** normal delay time wake up at 652
+*** rw sync time wake up at 652
+*** ro sync time wake up at 652
+*** next sim time wake up at 739
+*** normal delay time wake up at 739
+*** rw sync time wake up at 739
+*** ro sync time wake up at 739
+*** next sim time wake up at 826
+*** normal delay time wake up at 826
+*** rw sync time wake up at 826
+*** ro sync time wake up at 826
+*** next sim time wake up at 913
+*** normal delay time wake up at 913
+*** rw sync time wake up at 913
+*** ro sync time wake up at 913
+*** next sim time wake up at 1000
+*** normal delay time wake up at 1000
+*** rw sync time wake up at 1000
+*** ro sync time wake up at 1000
+*** next sim time wake up at 1087
+*** normal delay time wake up at 1087
+*** rw sync time wake up at 1087
+*** ro sync time wake up at 1087
+*** next sim time wake up at 1174
+*** normal delay time wake up at 1174
+*** rw sync time wake up at 1174
+*** ro sync time wake up at 1174
+*** next sim time wake up at 1261
+*** normal delay time wake up at 1261
+*** rw sync time wake up at 1261
+*** ro sync time wake up at 1261
+*** next sim time wake up at 1348
+*** normal delay time wake up at 1348
+*** rw sync time wake up at 1348
+*** ro sync time wake up at 1348
+*** next sim time wake up at 1435
+*** normal delay time wake up at 1435
+*** rw sync time wake up at 1435
+*** ro sync time wake up at 1435
+*** next sim time wake up at 1522
+*** normal delay time wake up at 1522
+*** rw sync time wake up at 1522
+*** ro sync time wake up at 1522
+*** next sim time wake up at 1609
+*** normal delay time wake up at 1609
+*** rw sync time wake up at 1609
+*** ro sync time wake up at 1609
+*** next sim time wake up at 1696
+*** normal delay time wake up at 1696
+*** rw sync time wake up at 1696
+*** ro sync time wake up at 1696
+*** next sim time wake up at 1783
+*** normal delay time wake up at 1783
+*** rw sync time wake up at 1783
+*** ro sync time wake up at 1783
diff --git a/tests_and_examples/install.tst/JK_Q.v b/tests_and_examples/install.tst/JK_Q.v
new file mode 100644
index 0000000..b4d0510
--- /dev/null
+++ b/tests_and_examples/install.tst/JK_Q.v
@@ -0,0 +1,69 @@
+ 
+primitive JK_Q (q, j, k, clk, pre, clr);
+ 
+// FUNCTION : POSITIVE EDGE TRIGGERED JK FLIP FLOP, WITH ACTIVE LOW 
+//            ASYNCHRONOUS CLEAR AND  SET  ( Q OUTPUT UDP ). 
+
+
+    output q;
+    reg    q;  
+    input  j,k,
+            clk,                                  // Clock.
+            clr,                                  // Clear input.
+            pre;                                  // Set input.
+                                  
+
+    table
+      // j   k   clk  pre  clr   : Qtn : Qtn+1
+
+         0   0  (01)  1    1     :  ?  :   - ;    // Output retains the 
+
+         0   1  (01)  1    1     :  ?  :   0 ;    // Clocked J and K.
+         0   1  (01)  1    x     :  ?  :   0 ;    // pessimism
+         ?   ?   ?    1    x     :  0  :   0 ;    // pessimism
+
+         1   0  (01)  1    1     :  ?  :   1 ;    
+         1   0  (01)  x    1     :  ?  :   1 ;    // pessimism
+         ?   ?   ?    x    1     :  1  :   1 ;    // pessimism
+
+         1   1  (01)  1    1     :  0  :   1 ;    // Clocked toggle.
+         1   1  (01)  1    1     :  1  :   0 ;
+                                                     
+         ?   1  (01)  1    x     :  1  :   0 ;     //pessimism
+         1   ?  (01)  x    1     :  0  :   1 ;
+  
+         0   0  (x1)  1    1     :  ?  :   - ;   //possible clocked JK
+         0   1  (x1)  1    1     :  0  :   0 ;   
+         1   0  (x1)  1    1     :  1  :   1 ;
+         0   0  (0x)  1    1     :  ?  :   - ;
+         0   1  (0x)  1    1     :  0  :   0 ;
+         1   0  (0x)  1    1     :  1  :   1 ;
+
+                                 
+         *   ?   ?    1    1     :  ?  :   - ;    // Insensitive to 
+         ?   *   ?    1    1     :  ?  :   - ;    // transitions on J and K
+                                                 // with steady clock.
+
+         ?   ?   ?    0    1     :  ?  :  1  ;    // Set.
+         ?   ?   ?    ?    0     :  ?  :  0  ;    // clear and  clear override.
+
+         ?   ? (?0)   1    1     :   ? :  -  ;    //ignore falling clock.
+         ?   ? (1x)   1    1     :   ? :  -  ;
+    
+         x   0   r    1    1     :   1  :   1 ;         // reducing pessimism for unknown J 
+         x   1   r    1    1     :   1  :   0 ;         // reducing pessimism for unknown J 
+         0   x   r    1    1     :   0  :   0 ;         // reducing pessimism for unknown K 
+         1   x   r    1    1     :   0  :   1 ;         // reducing pessimism for unknown K 
+
+         x   0  (x1)  1    1     :   1  :   1 ;        //possible clocked with
+         0   x  (x1)  1    1     :   0  :   0 ;        //possible J & K                                 
+         x   0  (0x)  1    1     :   1  :   1 ;
+         0   x  (0x)  1    1     :   0  :   0 ;
+
+         ?   ?   ?    1  (?1)    :  ?   :  -  ;    //ignore changes on set and
+         ?   ?   ?   (?1)  1     :  ?   :  -  ;    //reset.
+
+
+    endtable
+
+endprimitive
diff --git a/tests_and_examples/install.tst/JK_QBAR.v b/tests_and_examples/install.tst/JK_QBAR.v
new file mode 100644
index 0000000..7862d72
--- /dev/null
+++ b/tests_and_examples/install.tst/JK_QBAR.v
@@ -0,0 +1,71 @@
+
+ 
+primitive JK_QBAR (qbar, j, k, clk, pre, clr);
+ 
+// FUNCTION : POSITIVE EDGE TRIGGERED JK FLIP FLOP, WITH ACTIVE LOW 
+//            ASYNCHRONOUS CLEAR AND  SET  ( qbar OUTPUT UDP ).  
+
+
+    output qbar;
+    reg    qbar;  
+    input  j,k,
+            clk,                                  // Clock.
+            clr,                                  // Clear input.
+            pre;                                  // Set input.
+                                  
+
+    table
+      // j   k   clk  pre  clr   : Qtn : Qtn+1
+
+         0   0  (01)  1    1     :  ?  :   - ;    // Output retains the 
+
+         0   1  (01)  1    1     :  ?  :   1 ;    // Clocked J and K.
+         0   1  (01)  1    x     :  ?  :   1 ;    // pessimism
+         ?   ?   ?    1    x     :  1  :   1 ;    // pessimism
+
+         1   0  (01)  1    1     :  ?  :   0 ;    
+         1   0  (01)  x    1     :  ?  :   0 ;    // pessimism
+         ?   ?   ?    x    1     :  0  :   0 ;    // pessimism
+
+         1   1  (01)  1    1     :  1  :   0 ;    // Clocked toggle.
+         1   1  (01)  1    1     :  0  :   1 ;
+                                                     
+         ?   1  (01)  1    x     :  0  :   1 ;     //pessimism
+         1   ?  (01)  x    1     :  1  :   0 ;
+  
+         0   0  (x1)  1    1     :  ?  :   - ;   //possible clocked JK
+         0   1  (x1)  1    1     :  1  :   1 ;   
+         1   0  (x1)  1    1     :  0  :   0 ;
+         0   0  (0x)  1    1     :  ?  :   - ;
+         0   1  (0x)  1    1     :  1  :   1 ;
+         1   0  (0x)  1    1     :  0  :   0 ;
+
+                                 
+         *   ?   ?    1    1     :  ?  :   - ;    // Insensitive to 
+         ?   *   ?    1    1     :  ?  :   - ;    // transitions on J and K
+                                                 // with steady clock.
+
+         ?   ?   ?    0    1     :  ?  :  0  ;    // Set.
+         ?   ?   ?    1    0     :  ?  :  1  ;    // clear 
+         ?   ?   ?    0    0     :  ?  :  0  ;    // clear and  clear override. 
+
+         ?   ? (?0)   1    1     :   ? :  -  ;    //ignore falling clock.
+         ?   ? (1x)   1    1     :   ? :  -  ;
+    
+         x   0   r    1    1     :   0  :   0 ;         // reducing pessimism for unknown J 
+         x   1   r    1    1     :   0  :   1 ;         // reducing pessimism for unknown J 
+         0   x   r    1    1     :   1  :   1 ;         // reducing pessimism for unknown K 
+         1   x   r    1    1     :   1  :   0 ;         // reducing pessimism for unknown K 
+
+         x   0  (x1)  1    1     :   0  :   0 ;        //possible clocked with
+         0   x  (x1)  1    1     :   1  :   1 ;        //possible J & K                                 
+         x   0  (0x)  1    1     :   0  :   0 ;
+         0   x  (0x)  1    1     :   1  :   1 ;
+
+         ?   ?   ?  (?1)   1     :  ?   :  -  ;    //ignore changes on set and
+         ?   ?   ?   1   (?1)    :  ?   :  -  ;    //reset.
+
+
+    endtable
+
+endprimitive
diff --git a/tests_and_examples/install.tst/README b/tests_and_examples/install.tst/README
new file mode 100644
index 0000000..fdaa50a
--- /dev/null
+++ b/tests_and_examples/install.tst/README
@@ -0,0 +1,176 @@
+
+               RUNNING THE GPL CVER INSTALLATION TEST
+
+First run Cver without any arguments to make sure Cver binary is
+correctly installed.  Type "../../bin/cver" or if you have installed cver
+somewhere on your shell PATH just type "cver".  The first line output
+Cver version number must match the version of your release directory.  If
+version number does not match, you probably have your shell PATH environment
+variable set to execute an old version.
+
+If you are running on Unix/Linux based platforms, run the shell command
+script by typing:
+
+inst_tst.sh 
+
+Correct installation is indicated by the following message with no diff
+command output lines before the message:
+
+>>>> Install test completed (this should be only printed message).
+
+The inst_tst.sh test script must either be in a directory on your PATH or in
+your current working directory.  The inst_tst.sh script assumes you are
+running this test from the original Cver distribution directory tree.
+If you have already installed cver somewhere accessible from your OS
+shell PATH, edit the inst_tst.sh script and change:
+
+CVER="../../bin/cver -q " 
+
+to 
+
+CVER="cver -q"
+
+By convention the expected output files end with .plg suffix.
+
+-------------------------------------------------------------------------
+
+The installation script contains the following Verilog designs:
+
+minisim.v - the minisim model from the Thomas Moorby book used with
+    permission.  This is a rather complicated behavioral model with
+    expected output supplied by Thomas/Moorby.
+
+instid.v - a test of defparam module customization (copying because Cver
+    does not flatten but rather uses improved non flattened based
+    addressing algorithm).
+
+aspike1.v - a test circuit that has a possibly questionable pulse/glitch
+    because it involves stL and stX.  Five versions are run: 1) default
+    case with no pulse/glitch warnings or showing of X, 2) case that uses
+    +warn_canceled_e to cause warning messages to be emitted for pulses 
+    (transitions that occur more frequently that gate or path delay),
+    3) case that uses +show_canceled_e to cause transition to X (showing of X) 
+    at default leading edge of pulse.  Output stays at X until next gate
+    transition because for pulses, a gate (or path) may or may not switch.
+    4) case that uses +show_canceled_e and +pulse_e_style_on_detect to test
+    transition to X (showing of X) when a pulse is detected instead of the
+    default at leading edge of pulse/glitch.  5) case that turns on event
+    tracing but does not use pulse/glitch analysis.  The trace output
+    messages can also be used to detect potential pulse problems.
+
+    This example illustrates use of the various P1364 pulse analysis
+    options. 
+
+    Notice because Cver scheduler is based on the more accurate Tegas
+    scheduler (c.f. various old papers by Syzgenda et. al.
+    - papers on www.pragmatic-c.com web site contains references),
+    spike analysis works for both path delays and gate delays.
+    
+
+updjkff.v - a test using 2, 6 state udps from the Vcmp Valid SIM library.
+
+xx2bdel.v,xx2bpth.v,xx2bpth2.v - three variations on a small hierarchical
+    circuit.  xx2bdel.v illustrates the new $openscanf, $scanf, and
+    $isetdelay distributed primitive delay annotation method.  Unfortunately,
+    these system tasks do not follow the new Verilog 2000 P1364 file I/O
+    standard - we are working on changing to P1364 standard.  xx2bpth.v uses
+    path delays instead of gate delays and xx2bpth2.v is encoded in terms of
+    a module that implements a not gate with a path delay.
+
+c880.v - flattened 700 gate level circuit from ISCAS.
+
+force01.v - force/release example 11.2 from OVI LRM 2.0 (p. 11-4).  This
+    also tests interactive mode.
+
+vermemfil.v - example of how to use $scanf added system function (again
+    not yet same as Verilog 2000 File I/O options) to fill a memory using
+    just Cver functions.  See the plimemfil.v (and .c) files for an example
+    of how to use PLI tf_strdelputp to fill a memory and plimemfil2.v for an
+    example of how to use PLI tf_propagatep to fill a memory.
+
+gatenots.v - a 13.8k gate hierarchical circuit.  Since all outputs are
+    monitored at some time, it tests unoptimizable circuit.   This
+    type of inverter chain circuit is used to bring up new ASIC processes.
+    Only a few patterns are run.
+
+The +printstats and +verbose statistics for this circuit are: 
+
+-----------------------------------------------------------------------------
++++ Printing Design Statistics +++
+  Verbose mode statistics:
+  Design contains 3 module types.
+  112 (2300 flattened) ports collapsed.
+  9 gates (5400 flat) and 0 assigns (0 flat) disconnected by gate eater.
+  109 nets (5500 flat) disconnected by gate eater.
+
+  Design Module Table: 3 modules (1 top level):
+Module          Level Cells-in Insts-in Primitives  Assigns    Nets  Insts-of
+example_2b          2        0       10          0        1     653         1
+mod1                1        0       60          0        0     110        10
+dmod                0        0        0         23        0      24       600
+                        ------   ------     ------   ------  ------    ------
+Static Total:                0       70         23        1     787
+Flat Total:                  0      610      13800        1   16153       611
+
+  Per Module Wiring Table (Task Variables Excluded):
+Module           Ports(Bits)   Wires(Bits) Registers(Bits) Memory(Cells, Bits)
+example_2b                        650(650)           2(82)          1(10, 500)
+mod1                110(110)                                                  
+dmod                    2(2)        22(22)                                    
+                ------------ ------------- --------------- -------------------
+Flat total:       2300(2300)  13850(13850)           2(82)          1(10, 500)
+
+  Design Usage Table:
+Type                      Class  Static   Flat   Location
+                                 Number  Number
+example_2b                top         0       0  gatenots.v:1
+mod1                      module     10      10  gatenots.v:312
+dmod                      module     60     600  gatenots.v:357
+not                       gate       23   13800
+wide-assign               assign      1       1
+
+  Flattened Design: 610 instances, 0 udps, 13800 gates and 1 assigns.
++++ End of Design Statistics +++
+  Verbose mode statistics:
+  Design contains 3 module types.
+  112 (2300 flattened) ports collapsed.
+  9 gates (5400 flat) and 0 assigns (0 flat) disconnected by gate eater.
+  109 nets (5500 flat) disconnected by gate eater.
+
+  Begin load/optimize:
+  Approximately 396636 bytes storage allocated (excluding udps).
+  Begin simulation:
+  Approximately 718978 bytes storage allocated (excluding udps).
+  Verilog memories require 160 bytes (0.02% of total).
+-----------------------------------------------------------------------------
+
+arms_sim.v and armscnt.v - behavioral arms counter with large time scale
+    to test time scales.  The circuit was part of the bench marks presented
+    by S. Coumeri from CMU at the 1994 IVC conference.
+
+dfpsetd.v - simple flip flop test, but shows SDF delay annotation using both 
+    top level (no +[context]) +sdfannotate option and another file with
+    context.  The dfpsetv.c PLI 2.0 model in examples.vpi uses the same
+    circuit but sets same delays using PLI vpi_put_delays and vpi_put_value
+    calls.  SDF annotation also illustrates how assignment to defparams and
+    specparams used in delay expressions works.  This example shows the
+    command line method for specifying SDF file.  See systasks man page
+    for documentation on how to use $sdf_annotate system task to specify
+    SDF files. 
+
+mipdnot1.v - simple not gate circuit that show how SDF MIPD delays work.
+
+sdfia04.v - example of use of instance and gate arrays with SDF back 
+    annotation.   
+
+dffn.v - pipeline pound parameters example from 1995 P1364 LRM section 7.1.6
+
+xplipnd.v - version of instid.v (above) that is changed to illustrate 
+    new Verilog 2001 named pound parameter feature.  Feature allows 
+    passing only pound parameters to instances that need to be overridden. 
+
+defsplt1.v - small example to test new parameter setting algorithm.   
+    Example if difficult and it requires splitting module types because
+    vectors widths different between instance and re-evaluating parameters
+    because right hand side parameter definition expressions are set by 
+    defparams.  This example will fail in older versions of GPL Cver.
diff --git a/tests_and_examples/install.tst/arms.plg b/tests_and_examples/install.tst/arms.plg
new file mode 100644
index 0000000..7cbaefe
--- /dev/null
+++ b/tests_and_examples/install.tst/arms.plg
@@ -0,0 +1,20 @@
+                2580  COUT !== 4'b0000
+                7230  COUT !== 4'b0000
+               11880  COUT !== 4'b0000
+               16530  COUT !== 4'b0000
+               21180  COUT !== 4'b0000
+               25830  COUT !== 4'b0000
+               30480  COUT !== 4'b0000
+               35130  COUT !== 4'b0000
+               39780  COUT !== 4'b0000
+               44430  COUT !== 4'b0000
+               49080  COUT !== 4'b0000
+               53730  COUT !== 4'b0000
+               58380  COUT !== 4'b0000
+               63030  COUT !== 4'b0000
+               67680  COUT !== 4'b0000
+               72330  COUT !== 4'b0000
+               76980  COUT !== 4'b0000
+               81630  COUT !== 4'b0000
+               86280  COUT !== 4'b0000
+               90930  COUT !== 4'b0000
diff --git a/tests_and_examples/install.tst/arms_sim.v b/tests_and_examples/install.tst/arms_sim.v
new file mode 100644
index 0000000..3ab42fc
--- /dev/null
+++ b/tests_and_examples/install.tst/arms_sim.v
@@ -0,0 +1,395 @@
+////////////////////////////////////////////////////////////////////////////////
+// ARMS_COUNTER test vectors
+// translated to Verilog from VHDL by Sari Coumeri 
+// original VHDL obtained from the '92 High Level Synthesis Benchmarks
+// January 1994
+////////////////////////////////////////////////////////////////////////////////
+
+`timescale 1ns / 100ps
+module ARMS_COUNTER_sim;
+
+   reg CLK;
+   reg STRB;
+   reg [1:0] CON;
+   reg [3:0] DATA;
+   wire [3:0] COUT;
+
+   integer i;
+   ARMS_COUNTER ARMS_COUNTER_1 (CLK,STRB,CON,DATA,COUT);
+
+    // SJM add for debugging
+    // initial $monitor($stime,, "CLK=%b, STRB=%b, CON=%b, DATA=%b, COUT=%b",
+    //  CLK, STRB, CON, DATA, COUT);
+
+//////- The Clock always
+
+   always
+   begin
+#1;
+      CLK =  1'b0;
+#49;
+      CLK =  1'b1;
+   end
+
+//////- The Counter always
+
+   initial
+   begin
+ //  $dumpvars;
+ //  CLK = 1'b0;
+ //  STRB = 1'b0;
+ //  CON = 2'b00;
+ //  DATA = 4'b0000;
+   // repeat(10000)
+   repeat(20)
+   begin
+#30;
+
+// TEST 1 start off with simple test of reset, count up, && count down, && limit
+
+      // reset the counter
+      CON = 2'b00;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+
+#50;
+if (COUT !== 4'b0000) $display($time,,,"COUT !== 4'b0000");
+      
+      // load the LIMIT to 2
+      DATA = 4'b0010;
+      CON = 2'b01;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+
+      // count up
+      CON = 2'b10;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0001) $display($time,,,"COUT !== 4'b0001");
+      
+      // count up again
+#50;
+if (COUT !== 4'b0010) $display($time,,,"COUT !== 4'b0010");
+
+      // count up, should not increment since hit limit
+#50;
+if (COUT !== 4'b0010) $display($time,,,"COUT !== 4'b0010");
+      
+      // count up, should not increment since limit is hit eventhough countup signal is enabled
+      CON = 2'b10;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0011) $display($time,,,"COUT !== 4'b0011");
+      
+      // count down, cannot decrement since limit is hit && we do not know from which
+      // direction the limit is hit
+      CON = 2'b11;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0010) $display($time,,,"COUT !== 4'b0010");
+      
+      // load the LIMIT to 0
+      DATA = 4'b0000;
+      CON = 2'b01;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+      
+      // count down
+      CON = 2'b11;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0001) $display($time,,,"COUT !== 4'b0001");
+
+// TEST2 Perform some extensive testing of the counter's limit handling
+
+      // set limit to 13
+      DATA = 4'b1101;
+      CON = 2'b01;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+
+      // reset the counter
+      CON = 2'b00;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0000) $display($time,,,"COUT !== 4'b0000");
+      
+      // count up to 13
+      CON = 2'b10;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+      for (i = 1; i <= 13; i = i + 1)
+begin
+
+#50;
+      end
+if (COUT !== 4'b1101) $display($time,,,"COUT !== 4'b1101");
+ 
+      // count up, should not increment since hit limit
+#50;
+if (COUT !== 4'b1101) $display($time,,,"COUT !== 4'b1101");
+      
+      // count up, should not increment since hit limit
+      CON = 2'b10;
+#50;
+if (COUT !== 4'b1101) $display($time,,,"COUT !== 4'b1101");
+      
+      // change limit to 15
+      DATA = 4'b1111;
+      CON = 2'b01;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+
+      // count up
+      CON = 2'b10;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b1110) $display($time,,,"COUT !== 4'b1110");
+
+      // count up
+#50;
+if (COUT !== 4'b1111) $display($time,,,"COUT !== 4'b1111");
+
+      // count up, should not increment since hit limit
+#50;
+if (COUT !== 4'b1111) $display($time,,,"COUT !== 4'b1111");
+      
+      // change limit to 7 
+      DATA = 4'b0111;
+      CON = 2'b01;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+
+      // count down, try counting below 7
+      CON = 2'b11;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+      for (i = 1; i <= 10; i = i + 1)
+begin
+
+#50;
+      end
+if (COUT !== 4'b0111) $display($time,,,"COUT !== 4'b0111");
+         
+      // change limit to 0 
+      DATA = 4'b0000;
+      CON = 2'b01;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+ 
+      // count down, try counting below 8
+      CON = 2'b11;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+      for (i = 1; i <= 8; i = i + 1)
+begin
+
+#50;
+      end
+if (COUT !== 4'b0000) $display($time,,,"COUT !== 4'b0000");
+         
+      // count up, should not increment since hit limit
+      CON = 2'b10;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0000) $display($time,,,"COUT !== 4'b0000");
+      
+// TEST3 Try counting beyond the range, i.e. above 15 && below 0
+
+      // reset the counter
+      CON = 2'b00;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0000) $display($time,,,"COUT !== 4'b0000");
+
+      // change limit to 7 
+      DATA = 4'b0111;
+      CON = 2'b01;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+
+      // count up 1 
+      CON = 2'b10;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0001) $display($time,,,"COUT !== 4'b0001");
+      
+      // count down  
+      CON = 2'b11;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0000) $display($time,,,"COUT !== 4'b0000");
+    
+      // count down  
+#50;
+if (COUT !== 4'b1111) $display($time,,,"COUT !== 4'b1111");
+      
+      // count down  
+#50;
+if (COUT !== 4'b1110) $display($time,,,"COUT !== 4'b1110");
+      
+      // count up 
+      CON = 2'b10;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b1111) $display($time,,,"COUT !== 4'b1111");
+      
+      // count up 
+      CON = 2'b10;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0000) $display($time,,,"COUT !== 4'b0000");
+
+// TEST4 Checking for counting sequence from 0 to 15 && from 15 to 0
+
+      // reset the counter
+      CON = 2'b00;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+if (COUT !== 4'b0000) $display($time,,,"COUT !== 4'b0000");
+
+      // change limit to 15
+      DATA = 4'b1111;
+      CON = 2'b01;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+
+      // count up 15 times
+      CON = 2'b10;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+
+#50;
+if (COUT !== 4'b0001) $display($time,,,"COUT !== 4'b0001");
+
+#50;
+if (COUT !== 4'b0010) $display($time,,,"COUT !== 4'b0010");
+
+#50;
+if (COUT !== 4'b0011) $display($time,,,"COUT !== 4'b0011");
+
+#50;
+if (COUT !== 4'b0100) $display($time,,,"COUT !== 4'b0100");
+
+#50;
+if (COUT !== 4'b0101) $display($time,,,"COUT !== 4'b0101");
+
+#50;
+if (COUT !== 4'b0110) $display($time,,,"COUT !== 4'b0110");
+
+#50;
+if (COUT !== 4'b0111) $display($time,,,"COUT !== 4'b0111");
+
+#50;
+if (COUT !== 4'b1000) $display($time,,,"COUT !== 4'b1000");
+
+#50;
+if (COUT !== 4'b1001) $display($time,,,"COUT !== 4'b1001");
+
+#50;
+if (COUT !== 4'b1010) $display($time,,,"COUT !== 4'b1010");
+
+#50;
+if (COUT !== 4'b1011) $display($time,,,"COUT !== 4'b1011");
+
+#50;
+if (COUT !== 4'b1100) $display($time,,,"COUT !== 4'b1100");
+
+#50;
+if (COUT !== 4'b1101) $display($time,,,"COUT !== 4'b1101");
+
+#50;
+if (COUT !== 4'b1110) $display($time,,,"COUT !== 4'b1110");
+
+#50;
+if (COUT !== 4'b1111) $display($time,,,"COUT !== 4'b1111");
+      
+      // change limit to 0
+      DATA = 4'b0000;
+      CON = 2'b01;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+#50;
+
+      // count down 15 times 
+      CON = 2'b11;
+	STRB <= #10 1'b1;
+	STRB <= #20 1'b0;
+
+#50;
+if (COUT !== 4'b1110) $display($time,,,"COUT !== 4'b1110");
+
+#50;
+if (COUT !== 4'b1101) $display($time,,,"COUT !== 4'b1101");
+
+#50;
+if (COUT !== 4'b1100) $display($time,,,"COUT !== 4'b1100");
+
+#50;
+if (COUT !== 4'b1011) $display($time,,,"COUT !== 4'b1011");
+
+#50;
+if (COUT !== 4'b1010) $display($time,,,"COUT !== 4'b1010");
+
+#50;
+if (COUT !== 4'b1001) $display($time,,,"COUT !== 4'b1001");
+
+#50;
+if (COUT !== 4'b1000) $display($time,,,"COUT !== 4'b1000");
+
+#50;
+if (COUT !== 4'b0111) $display($time,,,"COUT !== 4'b0111");
+
+#50;
+if (COUT !== 4'b0110) $display($time,,,"COUT !== 4'b0110");
+
+#50;
+if (COUT !== 4'b0101) $display($time,,,"COUT !== 4'b0101");
+
+#50;
+if (COUT !== 4'b0100) $display($time,,,"COUT !== 4'b0100");
+
+#50;
+if (COUT !== 4'b0011) $display($time,,,"COUT !== 4'b0011");
+
+#50;
+if (COUT !== 4'b0010) $display($time,,,"COUT !== 4'b0010");
+
+#50;
+if (COUT !== 4'b0001) $display($time,,,"COUT !== 4'b0001");
+
+#50;
+if (COUT !== 4'b0000) $display($time,,,"COUT !== 4'b0001");
+#20;    
+end
+   $finish(2);
+   end
+endmodule
+
+
+
+
+
+
+
diff --git a/tests_and_examples/install.tst/armscnt.v b/tests_and_examples/install.tst/armscnt.v
new file mode 100644
index 0000000..7afc529
--- /dev/null
+++ b/tests_and_examples/install.tst/armscnt.v
@@ -0,0 +1,158 @@
+////////////////////////////////////////////////////////////////////////////////
+// ARMS_COUNTER
+// translated to Verilog from VHDL by Sari Coumeri 
+// original VHDL obtained from the '92 High Level Synthesis Benchmarks
+// January 1994
+////////////////////////////////////////////////////////////////////////////////
+
+// `timescale 1ns / 100ps
+module ARMS_COUNTER(CLK,STRB,CON,DATA,COUT);
+   input CLK;
+   input STRB;
+   input [1:0] CON;
+   input [3:0] DATA;
+   output [3:0] COUT;
+
+//VSS: design_style behavioural
+
+   reg ENIT, RENIT;
+   reg EN;
+   reg [3:0] CONSIG;
+   reg [3:0] LIM;
+   reg [3:0] CNT;
+
+   reg [1:0] CONREG;
+
+   reg CNTE;
+
+   assign COUT=CNT;
+////////////////  The decoder ////////////////////////////////////-
+initial
+begin
+   CONREG = 2'b00;
+   CNTE = 1'b0;
+   
+end
+
+always @(posedge STRB)
+begin
+
+    CONREG = CON;
+
+    case (CONREG)
+         2'b00:
+begin
+ CONSIG = 4'b0001;
+end
+         2'b01:
+begin
+ CONSIG = 4'b0010;
+end
+         2'b10:
+begin
+ CONSIG = 4'b0100; ENIT = 1'b1;
+end
+         2'b11:
+begin
+ CONSIG = 4'b1000; ENIT = 1'b1;
+end
+         default: ;
+    endcase
+
+end // Rising edge of STRB
+
+always @(posedge RENIT)
+begin
+
+    ENIT = 1'b0;
+  end
+
+
+////////////////  The limit loader ////////////////////////////////////-
+
+always @(negedge STRB)
+begin
+
+  if( (CONSIG[1] == 1'b1)  )
+begin
+
+    LIM = DATA;
+  end
+
+end
+
+
+////////////////  The counter ////////////////////////////////////-
+
+
+always @(posedge CONSIG[0])
+begin
+
+    CNT = 4'b0000;
+  end
+
+always @(posedge EN)
+begin
+
+      CNTE = 1'b1;
+    end
+always @(negedge EN)
+begin
+
+      CNTE = 1'b0;
+    end
+
+always @(posedge CLK)
+begin
+  if( (CNTE == 1'b1) )
+begin
+
+    if( (CONSIG[2] == 1'b1) )
+
+      CNT = CNT + 4'b0001;
+    else if (CONSIG[3] == 1'b1) 
+          CNT = CNT - 4'b0001;
+  end
+end
+
+
+////////////////  The comparator ////////////////////////////////////-
+
+always  @(ENIT)
+begin
+if (ENIT == 1'b1) 
+begin
+  EN = 1'b1; RENIT = 1'b1;
+  if( (EN == 1'b1) && (CNT == LIM) )
+begin
+
+    EN = 1'b0;
+  end
+end
+else
+begin
+
+  RENIT = 1'b0;
+  if( (EN == 1'b1) && (CNT == LIM) )
+begin
+
+    EN = 1'b0;
+  end
+end
+end
+
+
+always @(CNT)
+begin
+  if( (EN == 1'b1) && (CNT == LIM) )
+begin
+
+    EN = 1'b0;
+  end
+
+end
+
+
+
+endmodule
+
diff --git a/tests_and_examples/install.tst/aspike1.plg b/tests_and_examples/install.tst/aspike1.plg
new file mode 100644
index 0000000..67004b7
--- /dev/null
+++ b/tests_and_examples/install.tst/aspike1.plg
@@ -0,0 +1,12 @@
+         0 out=x,in=0,w1=x,w2=x
+         2 out=x,in=0,w1=0,w2=x
+         5 out=z,in=0,w1=0,w2=1
+       100 out=z,in=1,w1=0,w2=1
+       101 out=z,in=1,w1=1,w2=1
+       105 out=1,in=1,w1=1,w2=0
+       111 out=0,in=1,w1=1,w2=0
+       200 out=0,in=x,w1=1,w2=0
+       201 out=0,in=x,w1=x,w2=0
+       204 out=0,in=x,w1=x,w2=x
+       209 out=x,in=x,w1=x,w2=x
+       300 out=x,in=z,w1=x,w2=x
diff --git a/tests_and_examples/install.tst/aspike1.v b/tests_and_examples/install.tst/aspike1.v
new file mode 100644
index 0000000..ca15247
--- /dev/null
+++ b/tests_and_examples/install.tst/aspike1.v
@@ -0,0 +1,17 @@
+module test;
+reg in;
+wire w1,w2,out;
+
+buf #(1,2) (w1,in);
+not #(3,4) (w2,w1);
+
+bufif1 #(5,6) (out,w2,in);
+
+initial begin
+ $monitor($stime,, "out=%b,in=%b,w1=%b,w2=%b", out, in, w1, w2);
+ #0 in=1'b0;	
+ #100 in=1'b1;	
+ #100 in=1'bx;	
+ #100 in=1'bz;	
+end
+endmodule
diff --git a/tests_and_examples/install.tst/aspike1a.plg b/tests_and_examples/install.tst/aspike1a.plg
new file mode 100644
index 0000000..18b895c
--- /dev/null
+++ b/tests_and_examples/install.tst/aspike1a.plg
@@ -0,0 +1,13 @@
+         0 out=x,in=0,w1=x,w2=x
+         2 out=x,in=0,w1=0,w2=x
+         5 out=z,in=0,w1=0,w2=1
+       100 out=z,in=1,w1=0,w2=1
+       101 out=z,in=1,w1=1,w2=1
+       105 out=1,in=1,w1=1,w2=0
+       111 out=0,in=1,w1=1,w2=0
+       200 out=0,in=x,w1=1,w2=0
+       201 out=0,in=x,w1=x,w2=0
+**aspike1.v(8) WARN** now 204 [592] bufif1 gate test.__gate$$3 unstable (edge at 205 replaced by new at 209) - old St0, scheduled StL, new StX
+       204 out=0,in=x,w1=x,w2=x
+       209 out=x,in=x,w1=x,w2=x
+       300 out=x,in=z,w1=x,w2=x
diff --git a/tests_and_examples/install.tst/aspike1b.plg b/tests_and_examples/install.tst/aspike1b.plg
new file mode 100644
index 0000000..cb3008a
--- /dev/null
+++ b/tests_and_examples/install.tst/aspike1b.plg
@@ -0,0 +1,12 @@
+         0 out=x,in=0,w1=x,w2=x
+         2 out=x,in=0,w1=0,w2=x
+         5 out=z,in=0,w1=0,w2=1
+       100 out=z,in=1,w1=0,w2=1
+       101 out=z,in=1,w1=1,w2=1
+       105 out=1,in=1,w1=1,w2=0
+       111 out=0,in=1,w1=1,w2=0
+       200 out=0,in=x,w1=1,w2=0
+       201 out=0,in=x,w1=x,w2=0
+       204 out=0,in=x,w1=x,w2=x
+       205 out=x,in=x,w1=x,w2=x
+       300 out=x,in=z,w1=x,w2=x
diff --git a/tests_and_examples/install.tst/aspike1c.plg b/tests_and_examples/install.tst/aspike1c.plg
new file mode 100644
index 0000000..7ba5fcd
--- /dev/null
+++ b/tests_and_examples/install.tst/aspike1c.plg
@@ -0,0 +1,11 @@
+         0 out=x,in=0,w1=x,w2=x
+         2 out=x,in=0,w1=0,w2=x
+         5 out=z,in=0,w1=0,w2=1
+       100 out=z,in=1,w1=0,w2=1
+       101 out=z,in=1,w1=1,w2=1
+       105 out=1,in=1,w1=1,w2=0
+       111 out=0,in=1,w1=1,w2=0
+       200 out=0,in=x,w1=1,w2=0
+       201 out=0,in=x,w1=x,w2=0
+       204 out=x,in=x,w1=x,w2=x
+       300 out=x,in=z,w1=x,w2=x
diff --git a/tests_and_examples/install.tst/aspike1d.plg b/tests_and_examples/install.tst/aspike1d.plg
new file mode 100644
index 0000000..6b66b26
--- /dev/null
+++ b/tests_and_examples/install.tst/aspike1d.plg
@@ -0,0 +1,111 @@
+-- adding initial procedural start at statement **aspike1.v(11)
+-- assign buf test.__gate$$1(x, x) event output gate, x to w1
+-- assign not test.__gate$$2(x, x) event output gate, x to w2
+-- assign bufif1 test.__gate$$3(StX, x, x) event output gate, StX to out
+
+>>>> wire initialization complete <<<<<
+-- resuming at statement **aspike1.v(11)
+-- scheduling delay resume at **aspike1.v(12) for time 0
+-- evaluating loads of reg/wire test.w1
+-- not gate test.__gate$$2 input 1 value unchanged
+-- evaluating loads of reg/wire test.w2
+-- bufif1 gate test.__gate$$3 input 1 value unchanged
+-- resuming at statement **aspike1.v(12)
+-- scheduling delay resume at **aspike1.v(13) for time 100
+-- evaluating loads of reg/wire test.in
+-- bufif1 gate test.__gate$$3 input 2 changed to 0:
+ DEL, SCHD AT 5 <OV=StX, NSV=HiZ>
+-- buf gate test.__gate$$1 input 1 changed to 0:
+ DEL, SCHD AT 2 <OV=x, NSV=0>
+         0 out=x,in=0,w1=x,w2=x
+
+<<< event tracing at time 2
+-- buf gate test.__gate$$1 processing store event to output, the fi=1 driver: 0
+-- assign buf test.__gate$$1(0, 0) event output gate, 0 to w1
+-- evaluating loads of reg/wire test.w1
+-- not gate test.__gate$$2 input 1 changed to 0:
+ DEL, SCHD AT 5 <OV=x, NSV=1>
+         2 out=x,in=0,w1=0,w2=x
+
+<<< event tracing at time 5
+-- bufif1 gate test.__gate$$3 processing store event to output, the fi=1 driver: HiZ
+-- assign bufif1 test.__gate$$3(HiZ, x, 0) event output gate, HiZ to out
+-- not gate test.__gate$$2 processing store event to output, the fi=1 driver: 1
+-- assign not test.__gate$$2(1, 0) event output gate, 1 to w2
+-- evaluating loads of reg/wire test.w2
+-- bufif1 gate test.__gate$$3 input 1 changed to 1:
+ DEL, NOCHG <OV=HiZ>
+         5 out=z,in=0,w1=0,w2=1
+
+<<< event tracing at time 100
+-- resuming at statement **aspike1.v(13)
+-- scheduling delay resume at **aspike1.v(14) for time 200
+-- evaluating loads of reg/wire test.in
+-- bufif1 gate test.__gate$$3 input 2 changed to 1:
+ DEL, SCHD AT 105 <OV=HiZ, NSV=St1>
+-- buf gate test.__gate$$1 input 1 changed to 1:
+ DEL, SCHD AT 101 <OV=0, NSV=1>
+       100 out=z,in=1,w1=0,w2=1
+
+<<< event tracing at time 101
+-- buf gate test.__gate$$1 processing store event to output, the fi=1 driver: 1
+-- assign buf test.__gate$$1(1, 1) event output gate, 1 to w1
+-- evaluating loads of reg/wire test.w1
+-- not gate test.__gate$$2 input 1 changed to 1:
+ DEL, SCHD AT 105 <OV=1, NSV=0>
+       101 out=z,in=1,w1=1,w2=1
+
+<<< event tracing at time 105
+-- bufif1 gate test.__gate$$3 processing store event to output, the fi=1 driver: St1
+-- assign bufif1 test.__gate$$3(St1, 1, 1) event output gate, St1 to out
+-- not gate test.__gate$$2 processing store event to output, the fi=1 driver: 0
+-- assign not test.__gate$$2(0, 1) event output gate, 0 to w2
+-- evaluating loads of reg/wire test.w2
+-- bufif1 gate test.__gate$$3 input 1 changed to 0:
+ DEL, SCHD AT 111 <OV=St1, NSV=St0>
+       105 out=1,in=1,w1=1,w2=0
+
+<<< event tracing at time 111
+-- bufif1 gate test.__gate$$3 processing store event to output, the fi=1 driver: St0
+-- assign bufif1 test.__gate$$3(St0, 0, 1) event output gate, St0 to out
+       111 out=0,in=1,w1=1,w2=0
+
+<<< event tracing at time 200
+-- resuming at statement **aspike1.v(14)
+-- scheduling delay resume at **aspike1.v(15) for time 300
+-- evaluating loads of reg/wire test.in
+-- bufif1 gate test.__gate$$3 input 2 changed to x:
+ DEL, SCHD AT 205 <OV=St0, NSV=StL>
+-- buf gate test.__gate$$1 input 1 changed to x:
+ DEL, SCHD AT 201 <OV=1, NSV=x>
+       200 out=0,in=x,w1=1,w2=0
+
+<<< event tracing at time 201
+-- buf gate test.__gate$$1 processing store event to output, the fi=1 driver: x
+-- assign buf test.__gate$$1(x, x) event output gate, x to w1
+-- evaluating loads of reg/wire test.w1
+-- not gate test.__gate$$2 input 1 changed to x:
+ DEL, SCHD AT 204 <OV=0, NSV=x>
+       201 out=0,in=x,w1=x,w2=0
+
+<<< event tracing at time 204
+-- not gate test.__gate$$2 processing store event to output, the fi=1 driver: x
+-- assign not test.__gate$$2(x, x) event output gate, x to w2
+-- evaluating loads of reg/wire test.w2
+-- bufif1 gate test.__gate$$3 input 1 changed to x:
+ DEL, PEND, UNSTABLE RESCHD <OV=St0, OSV=StL AT 205, NSV=StX AT 209>
+       204 out=0,in=x,w1=x,w2=x
+
+<<< event tracing at time 209
+-- bufif1 gate test.__gate$$3 processing store event to output, the fi=1 driver: StX
+-- assign bufif1 test.__gate$$3(StX, x, x) event output gate, StX to out
+       209 out=x,in=x,w1=x,w2=x
+
+<<< event tracing at time 300
+-- resuming at statement **aspike1.v(15)
+-- evaluating loads of reg/wire test.in
+-- bufif1 gate test.__gate$$3 input 2 changed to z:
+ DEL, NOCHG <OV=StX>
+-- buf gate test.__gate$$1 input 1 changed to z:
+ DEL, NOCHG <OV=x>
+       300 out=x,in=z,w1=x,w2=x
diff --git a/tests_and_examples/install.tst/c880.plg b/tests_and_examples/install.tst/c880.plg
new file mode 100644
index 0000000..d7a968e
--- /dev/null
+++ b/tests_and_examples/install.tst/c880.plg
@@ -0,0 +1,8 @@
+                   0 00000111101000000000000000
+                   1 11111100010111100111111111
+                   2 xxxxxxxxxxxxxxxxxxxxxxxxxx
+                   4 10000111101000111101011111
+                   5 1xxxxxxxxxxxxx1xx1x1x11111
+                   6 00000110111100011110100101
+                   7 00000111101100100111101111
+                   8 xxxxxxxxxxxxxxxxxxxxxxxxxx
diff --git a/tests_and_examples/install.tst/c880.v b/tests_and_examples/install.tst/c880.v
new file mode 100644
index 0000000..4586d59
--- /dev/null
+++ b/tests_and_examples/install.tst/c880.v
@@ -0,0 +1,740 @@
+// C880.blif
+module foobar(i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1);
+input a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1;
+output i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2;
+not(i2, h1);
+and(j2, c1, g1);
+and(k2, c1, e1);
+and(l2, c1, d1);
+or(m2, v0, u0);
+not(t_0, v0);
+not(t_1, u0);
+or(n2, t_0, t_1);
+or(o2, t0, s0);
+not(t_2, t0);
+not(t_3, s0);
+or(p2, t_2, t_3);
+or(q2, r0, q0);
+not(t_4, r0);
+not(t_5, q0);
+or(r2, t_4, t_5);
+or(s2, p0, o0);
+not(t_6, p0);
+not(t_7, o0);
+or(t2, t_6, t_7);
+and(u2, l0, h0);
+and(v2, x0, d0);
+or(w2, e0, d0);
+not(t_8, e0);
+not(t_9, d0);
+or(x2, t_8, t_9);
+and(y2, x0, c0);
+and(z2, x0, b0);
+or(a3, c0, b0);
+not(t_10, c0);
+not(t_11, b0);
+or(b3, t_10, t_11);
+and(c3, x0, a0);
+and(d3, x0, z);
+or(e3, a0, z);
+not(t_12, a0);
+not(t_13, z);
+or(f3, t_12, t_13);
+and(g3, x0, y);
+and(h3, x0, x);
+or(i3, y, x);
+not(t_14, y);
+not(t_15, x);
+or(j3, t_14, t_15);
+or(k3, u, t);
+and(l1, r, s);
+not(t_16, n0);
+not(t_17, k);
+or(m3, t_16, t_17);
+and(n3, k, p, q);
+not(t_18, o);
+not(t_19, l);
+not(t_20, k);
+or(o3, t_18, t_19, t_20);
+and(p3, i, h0);
+and(q3, k, p, h);
+not(t_21, m);
+not(t_22, l);
+not(t_23, h);
+not(t_24, k);
+or(r3, t_21, t_22, t_23, t_24);
+and(s3, k, g, h);
+and(t3, k, g, q);
+and(k1, f, g, h);
+and(j1, f, g, q);
+and(i1, f, p, h);
+and(x3, f, p, q);
+not(t_25, l);
+not(t_26, f);
+or(y3, t_25, t_26);
+and(z3, f, g, h);
+and(a4, d, h);
+not(t_27, d);
+not(t_28, h);
+and(b4, t_27, t_28);
+and(c4, d, h0);
+and(d4, b, h0);
+not(t_29, j);
+not(t_30, c);
+not(t_31, b);
+not(t_32, a);
+or(e4, t_29, t_30, t_31, t_32);
+not(t_33, d);
+not(t_34, i);
+not(t_35, b);
+not(t_36, a);
+or(f4, t_33, t_34, t_35, t_36);
+and(g4, a, e, i);
+not(t_37, d);
+not(t_38, c);
+not(t_39, e);
+not(t_40, a);
+or(h4, t_37, t_38, t_39, t_40);
+not(t_41, d);
+not(t_42, c);
+not(t_43, b);
+not(t_44, a);
+or(i4, t_41, t_42, t_43, t_44);
+not(j4, i2);
+not(t_45, m2);
+not(t_46, n2);
+or(k4, t_45, t_46);
+not(t_47, o2);
+not(t_48, p2);
+or(l4, t_47, t_48);
+not(t_49, q2);
+not(t_50, r2);
+or(m4, t_49, t_50);
+not(t_51, s2);
+not(t_52, t2);
+or(n4, t_51, t_52);
+not(t_53, w2);
+not(t_54, x2);
+or(o4, t_53, t_54);
+not(t_55, a3);
+not(t_56, b3);
+or(p4, t_55, t_56);
+not(t_57, e3);
+not(t_58, f3);
+or(q4, t_57, t_58);
+not(t_59, i3);
+not(t_60, j3);
+or(r4, t_59, t_60);
+and(r1, w, k3);
+not(t_61, k3);
+not(t_62, v);
+or(t4, t_61, t_62);
+not(o1, n3);
+or(v4, o3, e4);
+not(w4, q3);
+not(t_63, e4);
+not(t_64, r3);
+and(x4, t_63, t_64);
+not(q1, s3);
+not(p1, t3);
+or(a5, y3, e4);
+not(b5, z3);
+or(n1, z3, h4);
+not(t_65, b4);
+not(t_66, a4);
+and(d5, t_65, t_66);
+not(e5, f4);
+not(f5, g4);
+not(g5, g4);
+not(m1, i4);
+and(i5, x0, j4);
+not(j5, k4);
+and(k5, l4, k4);
+not(l5, l4);
+not(m5, m4);
+and(n5, n4, m4);
+not(o5, n4);
+not(p5, o4);
+and(q5, p4, o4);
+not(r5, p4);
+not(s5, q4);
+and(t5, r4, q4);
+not(u5, r4);
+not(w1, t4);
+and(w5, x4, n);
+not(v1, v4);
+not(t_67, w4);
+not(t_68, e5);
+or(y5, t_67, t_68);
+not(u1, a5);
+not(a6, f5);
+not(t1, g5);
+or(s1, b5, h4);
+and(d6, l5, j5);
+and(e6, o5, m5);
+and(f6, r5, p5);
+and(g6, u5, s5);
+not(h6, w5);
+not(t_69, a6);
+not(t_70, n0);
+not(t_71, k);
+not(t_72, d5);
+or(i6, t_69, t_70, t_71, t_72);
+not(t_73, j);
+not(t_74, x3);
+not(t_75, a6);
+or(j6, t_73, t_74, t_75);
+and(k6, m3, a6, j);
+not(t_76, d);
+not(t_77, m3);
+not(t_78, a6);
+or(l6, t_76, t_77, t_78);
+and(m6, a6, d, x3);
+or(n6, j6, j4);
+or(o6, j6, j4);
+or(p6, j6, j4);
+or(q6, j6, j4);
+and(r6, i2, m6);
+and(s6, i2, m6);
+and(t6, i2, m6);
+and(u6, i2, m6);
+not(t_79, k5);
+not(t_80, d6);
+and(v6, t_79, t_80);
+not(t_81, n5);
+not(t_82, e6);
+and(w6, t_81, t_82);
+and(x6, m0, k6);
+and(y6, k0, k6);
+and(z6, j0, k6);
+and(a7, i0, k6);
+not(t_83, q5);
+not(t_84, f6);
+and(b7, t_83, t_84);
+not(t_85, t5);
+not(t_86, g6);
+and(c7, t_85, t_86);
+not(d7, h6);
+not(t_87, y5);
+not(t_88, i6);
+or(e7, t_87, t_88);
+not(t_89, a);
+not(t_90, l6);
+or(f7, t_89, t_90);
+not(t_91, a7);
+not(t_92, r6);
+and(g7, t_91, t_92);
+not(t_93, z6);
+not(t_94, s6);
+and(h7, t_93, t_94);
+not(t_95, y6);
+not(t_96, t6);
+and(i7, t_95, t_96);
+not(t_97, x6);
+not(t_98, u6);
+and(j7, t_97, t_98);
+or(k7, w0, v6);
+not(t_99, w0);
+not(t_100, v6);
+or(l7, t_99, t_100);
+not(t_101, v0);
+not(t_102, d7);
+or(m7, t_101, t_102);
+not(t_103, u0);
+not(t_104, d7);
+or(n7, t_103, t_104);
+not(t_105, t0);
+not(t_106, d7);
+or(o7, t_105, t_106);
+and(p7, d7, s0);
+and(q7, d7, r0);
+and(r7, d7, q0);
+and(s7, d7, p0);
+and(t7, d7, o0);
+and(u7, m0, f7);
+and(v7, k0, f7);
+and(w7, j0, f7);
+and(x7, i0, f7);
+or(y7, g0, b7);
+not(t_107, g0);
+not(t_108, b7);
+or(z7, t_107, t_108);
+or(a8, w6, f0);
+not(t_109, w6);
+not(t_110, f0);
+or(b8, t_109, t_110);
+or(c8, c7, f0);
+not(t_111, c7);
+not(t_112, f0);
+or(d8, t_111, t_112);
+and(e8, e0, e7);
+and(f8, d0, e7);
+and(g8, c0, e7);
+and(h8, b0, e7);
+and(i8, a0, e7);
+and(j8, z, e7);
+and(k8, y, e7);
+and(l8, x, e7);
+not(t_113, k7);
+not(t_114, l7);
+or(m8, t_113, t_114);
+not(t_115, u7);
+not(t_116, e8);
+and(n8, t_115, t_116);
+not(t_117, v7);
+not(t_118, f8);
+and(o8, t_117, t_118);
+not(t_119, w7);
+not(t_120, g8);
+and(p8, t_119, t_120);
+not(t_121, x7);
+not(t_122, h8);
+and(q8, t_121, t_122);
+not(t_123, u2);
+not(t_124, i8);
+and(r8, t_123, t_124);
+not(t_125, y7);
+not(t_126, z7);
+or(s8, t_125, t_126);
+not(t_127, a8);
+not(t_128, b8);
+or(t8, t_127, t_128);
+not(t_129, c8);
+not(t_130, d8);
+or(u8, t_129, t_130);
+not(t_131, p3);
+not(t_132, k8);
+and(v8, t_131, t_132);
+not(t_133, c4);
+not(t_134, j8);
+and(w8, t_133, t_134);
+not(t_135, d4);
+not(t_136, l8);
+and(x8, t_135, t_136);
+not(t_137, q8);
+not(t_138, n6);
+or(y8, t_137, t_138);
+not(t_139, p8);
+not(t_140, o6);
+or(z8, t_139, t_140);
+not(t_141, o8);
+not(t_142, p6);
+or(a9, t_141, t_142);
+not(t_143, n8);
+not(t_144, q6);
+or(b9, t_143, t_144);
+not(t_145, g7);
+not(t_146, x8);
+or(c9, t_145, t_146);
+not(t_147, h7);
+not(t_148, v8);
+or(d9, t_147, t_148);
+not(t_149, i7);
+not(t_150, w8);
+or(e9, t_149, t_150);
+not(t_151, j7);
+not(t_152, r8);
+or(f9, t_151, t_152);
+not(g9, m8);
+and(h9, t8, m8);
+not(i9, s8);
+and(j9, u8, s8);
+not(k9, t8);
+not(l9, u8);
+and(m9, b1, b9);
+and(n9, b1, a9);
+and(o9, b1, z8);
+and(p9, b1, y8);
+and(q9, b1, f9);
+and(r9, b1, e9);
+and(s9, b1, d9);
+and(t9, b1, c9);
+and(u9, k9, g9);
+or(v9, v0, b9);
+not(t_153, v0);
+not(t_154, b9);
+or(w9, t_153, t_154);
+or(x9, u0, a9);
+not(t_155, u0);
+not(t_156, a9);
+or(y9, t_155, t_156);
+or(z9, t0, z8);
+not(t_157, t0);
+not(t_158, z8);
+or(a10, t_157, t_158);
+or(b10, s0, y8);
+not(t_159, s0);
+not(t_160, y8);
+or(c10, t_159, t_160);
+or(d10, r0, f9);
+not(t_161, r0);
+not(t_162, f9);
+or(e10, t_161, t_162);
+or(f10, q0, e9);
+not(t_163, q0);
+not(t_164, e9);
+or(g10, t_163, t_164);
+or(h10, p0, d9);
+not(t_165, p0);
+not(t_166, d9);
+or(i10, t_165, t_166);
+or(j10, o0, c9);
+not(t_167, o0);
+not(t_168, c9);
+or(k10, t_167, t_168);
+and(l10, l9, i9);
+not(t_169, f1);
+not(t_170, v9);
+not(t_171, x9);
+not(t_172, z9);
+or(m10, t_169, t_170, t_171, t_172);
+not(t_173, f1);
+not(t_174, v9);
+not(t_175, x9);
+or(n10, t_173, t_174, t_175);
+not(t_176, f1);
+not(t_177, v9);
+or(o10, t_176, t_177);
+not(t_178, j2);
+not(t_179, m9);
+and(p10, t_178, t_179);
+not(t_180, k2);
+not(t_181, n9);
+and(q10, t_180, t_181);
+not(t_182, l2);
+not(t_183, o9);
+and(r10, t_182, t_183);
+not(t_184, h9);
+not(t_185, u9);
+and(y1, t_184, t_185);
+and(t10, v9, w9);
+not(u10, w9);
+and(v10, x9, y9);
+not(w10, y9);
+and(x10, z9, a10);
+not(y10, a10);
+and(z10, b10, c10);
+not(a11, c10);
+not(t_186, p9);
+not(t_187, p7);
+and(b11, t_186, t_187);
+and(c11, d10, e10);
+not(d11, e10);
+not(t_188, q9);
+not(t_189, q7);
+and(e11, t_188, t_189);
+and(f11, f10, g10);
+not(g11, g10);
+not(t_190, r9);
+not(t_191, r7);
+and(h11, t_190, t_191);
+and(i11, h10, i10);
+not(j11, i10);
+not(t_192, s9);
+not(t_193, s7);
+and(k11, t_192, t_193);
+and(l11, j10, k10);
+not(m11, k10);
+not(t_194, t9);
+not(t_195, t7);
+and(n11, t_194, t_195);
+not(t_196, j9);
+not(t_197, l10);
+and(x1, t_196, t_197);
+and(p11, t10, f1);
+not(t_198, t10);
+not(t_199, f1);
+and(q11, t_198, t_199);
+and(r11, a1, u10);
+and(s11, a1, w10);
+and(t11, a1, y10);
+and(u11, a1, a11);
+and(v11, a1, d11);
+and(w11, a1, g11);
+and(x11, a1, j11);
+and(y11, a1, m11);
+and(z11, z0, t10);
+and(a12, z0, v10);
+and(b12, z0, x10);
+and(c12, z0, z10);
+and(d12, z0, c11);
+and(e12, z0, f11);
+and(f12, z0, i11);
+and(g12, z0, l11);
+not(h12, u10);
+not(t_200, u10);
+not(t_201, x9);
+or(i12, t_200, t_201);
+not(t_202, u10);
+not(t_203, x9);
+not(t_204, z9);
+or(j12, t_202, t_203, t_204);
+not(k12, w10);
+not(t_205, w10);
+not(t_206, z9);
+or(l12, t_205, t_206);
+not(m12, y10);
+not(n12, a11);
+not(o12, d11);
+not(t_207, d11);
+not(t_208, f10);
+or(p12, t_207, t_208);
+not(t_209, d11);
+not(t_210, f10);
+not(t_211, h10);
+or(q12, t_209, t_210, t_211);
+not(r12, g11);
+not(t_212, g11);
+not(t_213, h10);
+or(s12, t_212, t_213);
+not(t12, j11);
+not(u12, m11);
+not(t_214, q11);
+not(t_215, p11);
+and(v12, t_214, t_215);
+not(t_216, m10);
+not(t_217, j12);
+not(t_218, l12);
+not(t_219, m12);
+or(w12, t_216, t_217, t_218, t_219);
+not(t_220, n10);
+not(t_221, i12);
+not(t_222, k12);
+or(x12, t_220, t_221, t_222);
+not(t_223, o10);
+not(t_224, h12);
+or(y12, t_223, t_224);
+not(t_225, z11);
+not(t_226, r11);
+and(z12, t_225, t_226);
+not(t_227, a12);
+not(t_228, s11);
+and(a13, t_227, t_228);
+not(t_229, b12);
+not(t_230, t11);
+and(b13, t_229, t_230);
+not(t_231, c12);
+not(t_232, u11);
+and(c13, t_231, t_232);
+not(t_233, d12);
+not(t_234, v11);
+and(d13, t_233, t_234);
+not(t_235, e12);
+not(t_236, w11);
+and(e13, t_235, t_236);
+not(t_237, f12);
+not(t_238, x11);
+and(f13, t_237, t_238);
+not(t_239, g12);
+not(t_240, y11);
+and(g13, t_239, t_240);
+and(h13, y0, v12);
+not(t_241, v10);
+not(t_242, y12);
+and(i13, t_241, t_242);
+and(j13, v10, y12);
+not(t_243, x10);
+not(t_244, x12);
+and(k13, t_243, t_244);
+and(l13, x10, x12);
+not(t_245, z10);
+not(t_246, w12);
+and(m13, t_245, t_246);
+and(n13, z10, w12);
+not(t_247, w12);
+not(t_248, b10);
+or(o13, t_247, t_248);
+not(t_249, i13);
+not(t_250, j13);
+and(p13, t_249, t_250);
+not(t_251, k13);
+not(t_252, l13);
+and(q13, t_251, t_252);
+not(t_253, m13);
+not(t_254, n13);
+and(r13, t_253, t_254);
+not(t_255, n12);
+not(t_256, o13);
+or(s13, t_255, t_256);
+not(t_257, v2);
+not(t_258, h13);
+and(t13, t_257, t_258);
+and(u13, y0, p13);
+and(v13, y0, q13);
+and(w13, y0, r13);
+not(t_259, m7);
+not(t_260, p10);
+not(t_261, z12);
+not(t_262, t13);
+or(x13, t_259, t_260, t_261, t_262);
+not(t_263, c11);
+not(t_264, s13);
+and(y13, t_263, t_264);
+and(z13, c11, s13);
+not(t_265, s13);
+not(t_266, d10);
+or(a14, t_265, t_266);
+not(t_267, s13);
+not(t_268, d10);
+not(t_269, f10);
+or(b14, t_267, t_268, t_269);
+not(t_270, s13);
+not(t_271, d10);
+not(t_272, f10);
+not(t_273, h10);
+or(c14, t_270, t_271, t_272, t_273);
+not(d14, x13);
+not(t_274, y13);
+not(t_275, z13);
+and(e14, t_274, t_275);
+not(t_276, a14);
+not(t_277, o12);
+or(f14, t_276, t_277);
+not(t_278, b14);
+not(t_279, p12);
+not(t_280, r12);
+or(g14, t_278, t_279, t_280);
+not(t_281, c14);
+not(t_282, q12);
+not(t_283, s12);
+not(t_284, t12);
+or(h14, t_281, t_282, t_283, t_284);
+not(t_285, y2);
+not(t_286, u13);
+and(i14, t_285, t_286);
+not(t_287, z2);
+not(t_288, v13);
+and(j14, t_287, t_288);
+not(t_289, c3);
+not(t_290, w13);
+and(k14, t_289, t_290);
+and(l14, y0, e14);
+not(z1, d14);
+not(t_291, n7);
+not(t_292, q10);
+not(t_293, a13);
+not(t_294, i14);
+or(n14, t_291, t_292, t_293, t_294);
+not(t_295, o7);
+not(t_296, r10);
+not(t_297, b13);
+not(t_298, j14);
+or(o14, t_295, t_296, t_297, t_298);
+not(t_299, b11);
+not(t_300, c13);
+not(t_301, k14);
+or(p14, t_299, t_300, t_301);
+not(t_302, f11);
+not(t_303, f14);
+and(q14, t_302, t_303);
+and(r14, f11, f14);
+not(t_304, i11);
+not(t_305, g14);
+and(s14, t_304, t_305);
+and(t14, i11, g14);
+not(t_306, l11);
+not(t_307, h14);
+and(u14, t_306, t_307);
+and(v14, l11, h14);
+not(t_308, j10);
+not(t_309, h14);
+or(w14, t_308, t_309);
+not(x14, n14);
+not(y14, o14);
+not(z14, p14);
+not(t_310, q14);
+not(t_311, r14);
+and(a15, t_310, t_311);
+not(t_312, s14);
+not(t_313, t14);
+and(b15, t_312, t_313);
+not(t_314, u14);
+not(t_315, v14);
+and(c15, t_314, t_315);
+and(d15, u12, w14);
+not(t_316, d3);
+not(t_317, l14);
+and(e15, t_316, t_317);
+and(f15, y0, a15);
+and(g15, y0, b15);
+and(h15, y0, c15);
+not(c2, x14);
+not(b2, y14);
+not(a2, z14);
+not(t_318, e11);
+not(t_319, d13);
+not(t_320, e15);
+or(l15, t_318, t_319, t_320);
+not(d2, d15);
+not(t_321, i5);
+not(t_322, h15);
+and(n15, t_321, t_322);
+not(o15, l15);
+not(t_323, g3);
+not(t_324, f15);
+and(p15, t_323, t_324);
+not(t_325, h3);
+not(t_326, g15);
+and(q15, t_325, t_326);
+not(e2, o15);
+not(t_327, h11);
+not(t_328, e13);
+not(t_329, p15);
+or(s15, t_327, t_328, t_329);
+not(t_330, k11);
+not(t_331, f13);
+not(t_332, q15);
+or(t15, t_330, t_331, t_332);
+not(t_333, n11);
+not(t_334, g13);
+not(t_335, n15);
+or(u15, t_333, t_334, t_335);
+not(v15, s15);
+not(w15, t15);
+not(x15, u15);
+not(h2, v15);
+not(g2, w15);
+not(f2, x15);
+endmodule
+module top;
+	parameter in_width = 60,
+		// patterns = 5000,
+		patterns = 8,
+		step = 1;
+	reg [1:in_width] in_mem[1:patterns];
+	integer index;
+
+	wire i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,
+		i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,
+		i20,i21,i22,i23,i24,i25,i26,i27,i28,i29,
+		i30,i31,i32,i33,i34,i35,i36,i37,i38,i39,
+		i40,i41,i42,i43,i44,i45,i46,i47,i48,i49,
+		i50,i51,i52,i53,i54,i55,i56,i57,i58,i59;
+
+	assign {i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,
+		i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,
+		i20,i21,i22,i23,i24,i25,i26,i27,i28,i29,
+		i30,i31,i32,i33,i34,i35,i36,i37,i38,i39,
+		i40,i41,i42,i43,i44,i45,i46,i47,i48,i49,
+		i50,i51,i52,i53,i54,i55,i56,i57,i58,i59} = 
+		$getpattern(in_mem[index]);
+
+	initial $monitor($time,,o0,o1,o2,o3,o4,o5,o6,o7,o8,o9,
+		o10,o11,o12,o13,o14,o15,o16,o17,o18,o19,
+		o20,o21,o22,o23,o24,o25);
+	initial
+		begin
+			$readmemb("patt.mem", in_mem);
+			for(index = 1; index <= patterns; index = index + 1)
+				#step;
+		end
+
+	foobar cct(o0,o1,o2,o3,o4,o5,o6,o7,o8,o9,
+		o10,o11,o12,o13,o14,o15,o16,o17,o18,o19,
+		o20,o21,o22,o23,o24,o25,i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,
+		i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,
+		i20,i21,i22,i23,i24,i25,i26,i27,i28,i29,
+		i30,i31,i32,i33,i34,i35,i36,i37,i38,i39,
+		i40,i41,i42,i43,i44,i45,i46,i47,i48,i49,
+		i50,i51,i52,i53,i54,i55,i56,i57,i58,i59);
+endmodule
diff --git a/tests_and_examples/install.tst/defsplt1.plg b/tests_and_examples/install.tst/defsplt1.plg
new file mode 100644
index 0000000..b25e3da
--- /dev/null
+++ b/tests_and_examples/install.tst/defsplt1.plg
@@ -0,0 +1 @@
+** WARN** [614] no pending statements or events after initialization - nothing to do
diff --git a/tests_and_examples/install.tst/defsplt1.v b/tests_and_examples/install.tst/defsplt1.v
new file mode 100644
index 0000000..bca81a7
--- /dev/null
+++ b/tests_and_examples/install.tst/defsplt1.v
@@ -0,0 +1,38 @@
+
+module complex_mul;
+  defparam UMLP.N=12;
+  defparam UMLP.M=13;
+  Mult0 UMLP (); //end of Mult0 UMLP
+
+  defparam UMLR.N=12;
+  defparam UMLR.M=13;
+  Mult0 UMLR (); //end of Mult0 UMLR
+
+endmodule
+
+module Mult0 ;
+  parameter N=12;
+  parameter M=12;
+  parameter Q=N+M;
+  reg  [M:0] datab;
+
+  defparam U_MULT00.MULT_N=N-1;
+  defparam U_MULT00.MULT_M=M-1;
+  mult U_MULT00 (
+    .b(datab[M-1:0]),
+    .r(aXb)
+  );
+
+endmodule
+
+module mult (
+    b,
+    r
+  );
+  parameter MULT_N =8;
+  parameter MULT_M =8;
+  parameter MULT_NM=MULT_M + MULT_N + 2;
+  input  [MULT_M :0] b;
+  output [MULT_NM:0] r;
+
+endmodule
diff --git a/tests_and_examples/install.tst/dffn.plg b/tests_and_examples/install.tst/dffn.plg
new file mode 100644
index 0000000..550b73b
--- /dev/null
+++ b/tests_and_examples/install.tst/dffn.plg
@@ -0,0 +1,66 @@
+         0 in=xxx, out=xxx, clk=x
+        10 in=000, out=xxx, clk=x
+        20 in=000, out=xxx, clk=0
+        30 -- top.pipe1.p[1].dff[2]: positive clock edge old q=x d=x
+        30 -- top.pipe1.p[1].dff[1]: positive clock edge old q=x d=x
+        30 -- top.pipe1.p[1].dff[0]: positive clock edge old q=x d=x
+        30 -- top.pipe1.p[2].dff[2]: positive clock edge old q=x d=x
+        30 -- top.pipe1.p[2].dff[1]: positive clock edge old q=x d=x
+        30 -- top.pipe1.p[2].dff[0]: positive clock edge old q=x d=x
+        30 -- top.pipe1.p[3].dff[2]: positive clock edge old q=x d=x
+        30 -- top.pipe1.p[3].dff[1]: positive clock edge old q=x d=x
+        30 -- top.pipe1.p[3].dff[0]: positive clock edge old q=x d=x
+        30 -- top.pipe1.p[4].dff[2]: positive clock edge old q=x d=0
+        30 -- top.pipe1.p[4].dff[1]: positive clock edge old q=x d=0
+        30 -- top.pipe1.p[4].dff[0]: positive clock edge old q=x d=0
+        30 in=000, out=xxx, clk=1
+        40 in=000, out=xxx, clk=x
+        50 in=000, out=xxx, clk=0
+        60 in=111, out=xxx, clk=0
+        80 -- top.pipe1.p[1].dff[2]: positive clock edge old q=x d=x
+        80 -- top.pipe1.p[1].dff[1]: positive clock edge old q=x d=x
+        80 -- top.pipe1.p[1].dff[0]: positive clock edge old q=x d=x
+        80 -- top.pipe1.p[2].dff[2]: positive clock edge old q=x d=x
+        80 -- top.pipe1.p[2].dff[1]: positive clock edge old q=x d=x
+        80 -- top.pipe1.p[2].dff[0]: positive clock edge old q=x d=x
+        80 -- top.pipe1.p[3].dff[2]: positive clock edge old q=x d=0
+        80 -- top.pipe1.p[3].dff[1]: positive clock edge old q=x d=0
+        80 -- top.pipe1.p[3].dff[0]: positive clock edge old q=x d=0
+        80 -- top.pipe1.p[4].dff[2]: positive clock edge old q=0 d=1
+        80 -- top.pipe1.p[4].dff[1]: positive clock edge old q=0 d=1
+        80 -- top.pipe1.p[4].dff[0]: positive clock edge old q=0 d=1
+        80 in=111, out=xxx, clk=1
+        90 in=111, out=xxx, clk=x
+       100 in=111, out=xxx, clk=0
+       110 in=000, out=xxx, clk=0
+       130 -- top.pipe1.p[1].dff[2]: positive clock edge old q=x d=x
+       130 -- top.pipe1.p[1].dff[1]: positive clock edge old q=x d=x
+       130 -- top.pipe1.p[1].dff[0]: positive clock edge old q=x d=x
+       130 -- top.pipe1.p[2].dff[2]: positive clock edge old q=x d=0
+       130 -- top.pipe1.p[2].dff[1]: positive clock edge old q=x d=0
+       130 -- top.pipe1.p[2].dff[0]: positive clock edge old q=x d=0
+       130 -- top.pipe1.p[3].dff[2]: positive clock edge old q=0 d=1
+       130 -- top.pipe1.p[3].dff[1]: positive clock edge old q=0 d=1
+       130 -- top.pipe1.p[3].dff[0]: positive clock edge old q=0 d=1
+       130 -- top.pipe1.p[4].dff[2]: positive clock edge old q=1 d=0
+       130 -- top.pipe1.p[4].dff[1]: positive clock edge old q=1 d=0
+       130 -- top.pipe1.p[4].dff[0]: positive clock edge old q=1 d=0
+       130 in=000, out=xxx, clk=1
+       140 in=000, out=xxx, clk=x
+       150 in=000, out=xxx, clk=0
+       160 in=111, out=xxx, clk=0
+       180 -- top.pipe1.p[1].dff[2]: positive clock edge old q=x d=0
+       180 -- top.pipe1.p[1].dff[1]: positive clock edge old q=x d=0
+       180 -- top.pipe1.p[1].dff[0]: positive clock edge old q=x d=0
+       180 -- top.pipe1.p[2].dff[2]: positive clock edge old q=0 d=1
+       180 -- top.pipe1.p[2].dff[1]: positive clock edge old q=0 d=1
+       180 -- top.pipe1.p[2].dff[0]: positive clock edge old q=0 d=1
+       180 -- top.pipe1.p[3].dff[2]: positive clock edge old q=1 d=0
+       180 -- top.pipe1.p[3].dff[1]: positive clock edge old q=1 d=0
+       180 -- top.pipe1.p[3].dff[0]: positive clock edge old q=1 d=0
+       180 -- top.pipe1.p[4].dff[2]: positive clock edge old q=0 d=1
+       180 -- top.pipe1.p[4].dff[1]: positive clock edge old q=0 d=1
+       180 -- top.pipe1.p[4].dff[0]: positive clock edge old q=0 d=1
+       180 in=111, out=000, clk=1
+       190 in=111, out=000, clk=x
+       200 in=111, out=000, clk=0
diff --git a/tests_and_examples/install.tst/dffn.v b/tests_and_examples/install.tst/dffn.v
new file mode 100644
index 0000000..f7c2f13
--- /dev/null
+++ b/tests_and_examples/install.tst/dffn.v
@@ -0,0 +1,72 @@
+// pipeline model from LRM section 7.1.6 
+module DFF(q, d, clk);
+ output q;
+ input d, clk;
+ reg q;
+ 
+ always @(posedge clk)
+  begin
+   $display($stime,, "-- %m: positive clock edge old q=%b d=%b", q, d);
+   q = d;
+  end
+endmodule
+
+module dffn(q, d, clk); 
+ parameter bits = 1;
+
+ input [bits-1:0] d;
+ output [bits-1:0] q;
+ input clk;
+
+ DFF dff[bits-1:0] (q, d, clk);
+endmodule
+
+module MxN_pipeline(in, out, clk);
+ parameter M = 3, N = 4;
+
+ input [M-1:0] in;
+ output [M-1:0] out;
+ input clk;
+
+ wire [M*(N-1):1] t;
+
+ dffn #(M) p[1:N] ({out, t}, {t, in}, clk);
+endmodule
+
+module top;
+ reg [M-1:0] in;
+ reg clk;
+ wire [M-1:0] out;
+ parameter M = 3, N = 4;
+
+ MxN_pipeline #(M, N) pipe1(in, out, clk);
+
+ initial
+  begin
+   $monitor($stime,, "in=%b, out=%b, clk=%b", in, out, clk);
+   #10 in = 3'b0;
+   #10 clk = 0;
+   #10 clk = 1;
+   #10 clk = 1'bx;
+   #10 clk = 0;
+
+   #10 in = 3'b111;
+   #10 clk = 0;
+   #10 clk = 1;
+   #10 clk = 1'bx;
+   #10 clk = 0;
+
+   #10 in = 3'b0;
+   #10 clk = 0;
+   #10 clk = 111;
+   #10 clk = 1'bx;
+   #10 clk = 0;
+
+   // notice values do not propagate through pipeline until here 
+   #10 in = 3'b111;
+   #10 clk = 0;
+   #10 clk = 1;
+   #10 clk = 1'bx;
+   #10 clk = 0;
+  end
+endmodule
diff --git a/tests_and_examples/install.tst/dfpsetd.plg b/tests_and_examples/install.tst/dfpsetd.plg
new file mode 100644
index 0000000..4321d46
--- /dev/null
+++ b/tests_and_examples/install.tst/dfpsetd.plg
@@ -0,0 +1,10 @@
+**dfpsetd1.sdf(6) WARN** [2304] (LABEL form back annotation to parameter d non standard - will need to change to module scope specparam for Verilog 2000
+                   0 preset=x clear=x q=x qbar=x
+                 100 preset=0 clear=1 q=x qbar=x
+                 110 preset=0 clear=1 q=1 qbar=x
+                 116 preset=0 clear=1 q=1 qbar=0
+                 200 preset=1 clear=1 q=1 qbar=0
+                 300 preset=1 clear=0 q=1 qbar=0
+                 306 preset=1 clear=0 q=1 qbar=1
+                 312 preset=1 clear=0 q=0 qbar=1
+                 400 preset=1 clear=1 q=0 qbar=1
diff --git a/tests_and_examples/install.tst/dfpsetd.v b/tests_and_examples/install.tst/dfpsetd.v
new file mode 100644
index 0000000..f22b794
--- /dev/null
+++ b/tests_and_examples/install.tst/dfpsetd.v
@@ -0,0 +1,31 @@
+module ffnand_test;
+ wire q, qbar;
+ reg preset, clear;
+
+ parameter d = 10;
+
+ ffnand ff1(q, qbar, preset, clear);
+ initial 
+  begin
+   #d preset = 0; clear = 1;
+   #d preset = 1;
+   #d clear = 0;
+   #d clear = 1;
+  end
+ initial $monitor($time,, "preset=%b clear=%b q=%b qbar=%b",
+  preset, clear,q, qbar);
+endmodule
+
+module ffnand(ffq, ffqbar, ffpreset, ffclear);
+ output ffq, ffqbar;
+ input ffpreset, ffclear;
+  
+ nand #(1, 1) q1(ffq, ffqbar, ffpreset), q2(ffqbar, ffq, ffclear); 
+ specify
+  specparam pr = 5;
+  specparam pf = 5;
+  // notice error because no path delay to ffqbar
+  (ffpreset => ffq) = (pr, pf);
+  (ffclear => ffq) = (pr, pf);
+ endspecify
+endmodule
diff --git a/tests_and_examples/install.tst/dfpsetd.vc b/tests_and_examples/install.tst/dfpsetd.vc
new file mode 100644
index 0000000..d896a16
--- /dev/null
+++ b/tests_and_examples/install.tst/dfpsetd.vc
@@ -0,0 +1,6 @@
+// use this option to determine SDF delay setting sequence
+// +sdfverbose
+dfpsetd.v
+// two different files on showing no context paths and one with context paths
++sdfannotate dfpsetd1.sdf
++sdfannotate dfpsetd2.sdf+ffnand_test
diff --git a/tests_and_examples/install.tst/dfpsetd1.sdf b/tests_and_examples/install.tst/dfpsetd1.sdf
new file mode 100644
index 0000000..a99c39e
--- /dev/null
+++ b/tests_and_examples/install.tst/dfpsetd1.sdf
@@ -0,0 +1,8 @@
+(DELAYFILE 
+  (SDFVERSION "3.0") 
+  (CELL 
+   (CELLTYPE "ffnand_test" ) 
+   (INSTANCE ffnand_test)
+   (LABEL (ABSOLUTE (d 100)))
+  )
+)
diff --git a/tests_and_examples/install.tst/dfpsetd2.sdf b/tests_and_examples/install.tst/dfpsetd2.sdf
new file mode 100644
index 0000000..619ca29
--- /dev/null
+++ b/tests_and_examples/install.tst/dfpsetd2.sdf
@@ -0,0 +1,20 @@
+// context here [+<scope>] is ffnand_test
+(DELAYFILE 
+  (SDFVERSION "3.0") 
+  (CELL 
+   (CELLTYPE "ffnand" ) 
+   (INSTANCE ff1)
+    (LABEL (ABSOLUTE (pr 10) (pf 10)))
+  )
+  (CELL 
+   (CELLTYPE "nand" ) 
+   (INSTANCE ff1.q1)
+    // since source has 2 delays (3rd toz computed), need 3 for increment
+    (DELAY (INCREMENT (DEVICE (5) (5))))
+  )
+  (CELL 
+   (CELLTYPE "nand" ) 
+   (INSTANCE ff1.q2)
+    (DELAY (INCREMENT (DEVICE (5) (5))))
+  )
+)
diff --git a/tests_and_examples/install.tst/force01.inp b/tests_and_examples/install.tst/force01.inp
new file mode 100644
index 0000000..76bc78f
--- /dev/null
+++ b/tests_and_examples/install.tst/force01.inp
@@ -0,0 +1,10 @@
+   // also test input from $input();
+   force d = (a | b | c);
+   force e = (a | b | c);
+   #10 $stop;
+   .
+   release d;
+   release e;
+   c = 0;
+   #10 $finish;
+   .
diff --git a/tests_and_examples/install.tst/force01.plg b/tests_and_examples/install.tst/force01.plg
new file mode 100644
index 0000000..dfd9305
--- /dev/null
+++ b/tests_and_examples/install.tst/force01.plg
@@ -0,0 +1,13 @@
+d=0,e=0
+C1 >    // also test input from $input();
+C1 >    force d = (a | b | c);
+C2 >    force e = (a | b | c);
+C3 >    #10 $stop;
+C4 >    .
+d=1,e=1
+C4 >    release d;
+C5 >    release e;
+C6 >    c = 0;
+C7 >    #10 $finish;
+C8 >    .
+d=0,e=0
diff --git a/tests_and_examples/install.tst/force01.v b/tests_and_examples/install.tst/force01.v
new file mode 100644
index 0000000..0842b6d
--- /dev/null
+++ b/tests_and_examples/install.tst/force01.v
@@ -0,0 +1,20 @@
+module test;
+ reg a, // = 1'hx, x 
+     b, // = 1'hx, x 
+     c, // = 1'hx, x 
+     d; // = 1'hx, x 
+ wire e; // = StX
+ and and1(e, a, b, c); 
+
+ initial
+  begin
+   // $list;
+   $monitor("d=%b,e=%b", d, e);
+   a = 1;
+   b = 0;
+   c = 1;
+   assign d = a & b & c;
+   #10 ;
+   $stop;
+ end
+endmodule
diff --git a/tests_and_examples/install.tst/gatenots.plg b/tests_and_examples/install.tst/gatenots.plg
new file mode 100644
index 0000000..dfdd8f3
--- /dev/null
+++ b/tests_and_examples/install.tst/gatenots.plg
@@ -0,0 +1,21 @@
+         0 input 0000000000000 outputs(m0) xxxxxxxxxxxxx
+        56 input 0000000000000 outputs(m0) 0000000000000
+       200 input 3ffffffffffff outputs(m1) 0000000000000
+       256 input 3ffffffffffff outputs(m1) 3ffffffffffff
+       400 input xxxxxxxxxxxxx outputs(m2) 3ffffffffffff
+       442 input xxxxxxxxxxxxx outputs(m2) xxxxxxxxxxxxx
+       600 input zzzzzzzzzzzzz outputs(m3) xxxxxxxxxxxxx
+       800 input 1555555555555 outputs(m4) xxxxxxxxxxxxx
+       856 input 1555555555555 outputs(m4) 1555555555555
+      1000 input XXXXXXXXXXXXX outputs(m5) 1555555555555
+      1042 input XXXXXXXXXXXXX outputs(m5) XXXXXXXXXXXXX
+      1200 input 2aaaaaaaaaaaa outputs(m6) XXXXXXXXXXXXX
+      1256 input 2aaaaaaaaaaaa outputs(m6) 2aaaaaaaaaaaa
+      1400 input 333ccf33ccf33 outputs(m7) 2aaaaaaaaaaaa
+      1456 input 333ccf33ccf33 outputs(m7) 333ccf33ccf33
+      1600 input 0000000000000 outputs(m8) 333ccf33ccf33
+      1656 input 0000000000000 outputs(m8) 0000000000000
+      1800 input 3ffffffffffff outputs(m9) 0000000000000
+      1856 input 3ffffffffffff outputs(m9) 3ffffffffffff
+      2000 input xxxxxxxxxxxxx outputs(m9) 3ffffffffffff
+      2042 input xxxxxxxxxxxxx outputs(m9) xxxxxxxxxxxxx
diff --git a/tests_and_examples/install.tst/gatenots.v b/tests_and_examples/install.tst/gatenots.v
new file mode 100644
index 0000000..dea9145
--- /dev/null
+++ b/tests_and_examples/install.tst/gatenots.v
@@ -0,0 +1,367 @@
+module example_2b;
+parameter
+	in_width = 50,
+	patterns = 10,
+	out_width = 60,
+	step = 200,
+        // 0 no monitor, 1 - monitor, 2 - end of period strobe
+	mon_flag = 1;
+
+mod1 cct(o1, o2, o3, o4, o5, o6, o7, o8, o9, o10,
+ o11, o12, o13, o14, o15, o16, o17, o18, o19, o20,
+ o21, o22, o23, o24, o25, o26, o27, o28, o29, o30,
+ o31, o32, o33, o34, o35, o36, o37, o38, o39, o40,
+ o41, o42, o43, o44, o45, o46, o47, o48, o49, o50,
+ o51, o52, o53, o54, o55, o56, o57, o58, o59, o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct1(m1_o1, m1_o2, m1_o3, m1_o4, m1_o5, m1_o6, m1_o7, m1_o8, m1_o9, m1_o10,
+ m1_o11, m1_o12, m1_o13, m1_o14, m1_o15, m1_o16, m1_o17, m1_o18, m1_o19, m1_o20,
+ m1_o21, m1_o22, m1_o23, m1_o24, m1_o25, m1_o26, m1_o27, m1_o28, m1_o29, m1_o30,
+ m1_o31, m1_o32, m1_o33, m1_o34, m1_o35, m1_o36, m1_o37, m1_o38, m1_o39, m1_o40,
+ m1_o41, m1_o42, m1_o43, m1_o44, m1_o45, m1_o46, m1_o47, m1_o48, m1_o49, m1_o50,
+ m1_o51, m1_o52, m1_o53, m1_o54, m1_o55, m1_o56, m1_o57, m1_o58, m1_o59, m1_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct2(m2_o1, m2_o2, m2_o3, m2_o4, m2_o5, m2_o6, m2_o7, m2_o8, m2_o9, m2_o10,
+ m2_o11, m2_o12, m2_o13, m2_o14, m2_o15, m2_o16, m2_o17, m2_o18, m2_o19, m2_o20,
+ m2_o21, m2_o22, m2_o23, m2_o24, m2_o25, m2_o26, m2_o27, m2_o28, m2_o29, m2_o30,
+ m2_o31, m2_o32, m2_o33, m2_o34, m2_o35, m2_o36, m2_o37, m2_o38, m2_o39, m2_o40,
+ m2_o41, m2_o42, m2_o43, m2_o44, m2_o45, m2_o46, m2_o47, m2_o48, m2_o49, m2_o50,
+ m2_o51, m2_o52, m2_o53, m2_o54, m2_o55, m2_o56, m2_o57, m2_o58, m2_o59, m2_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct3(m3_o1, m3_o2, m3_o3, m3_o4, m3_o5, m3_o6, m3_o7, m3_o8, m3_o9, m3_o10,
+ m3_o11, m3_o12, m3_o13, m3_o14, m3_o15, m3_o16, m3_o17, m3_o18, m3_o19, m3_o20,
+ m3_o21, m3_o22, m3_o23, m3_o24, m3_o25, m3_o26, m3_o27, m3_o28, m3_o29, m3_o30,
+ m3_o31, m3_o32, m3_o33, m3_o34, m3_o35, m3_o36, m3_o37, m3_o38, m3_o39, m3_o40,
+ m3_o41, m3_o42, m3_o43, m3_o44, m3_o45, m3_o46, m3_o47, m3_o48, m3_o49, m3_o50,
+ m3_o51, m3_o52, m3_o53, m3_o54, m3_o55, m3_o56, m3_o57, m3_o58, m3_o59, m3_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct4(m4_o1, m4_o2, m4_o3, m4_o4, m4_o5, m4_o6, m4_o7, m4_o8, m4_o9, m4_o10,
+ m4_o11, m4_o12, m4_o13, m4_o14, m4_o15, m4_o16, m4_o17, m4_o18, m4_o19, m4_o20,
+ m4_o21, m4_o22, m4_o23, m4_o24, m4_o25, m4_o26, m4_o27, m4_o28, m4_o29, m4_o30,
+ m4_o31, m4_o32, m4_o33, m4_o34, m4_o35, m4_o36, m4_o37, m4_o38, m4_o39, m4_o40,
+ m4_o41, m4_o42, m4_o43, m4_o44, m4_o45, m4_o46, m4_o47, m4_o48, m4_o49, m4_o50,
+ m4_o51, m4_o52, m4_o53, m4_o54, m4_o55, m4_o56, m4_o57, m4_o58, m4_o59, m4_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct5(m5_o1, m5_o2, m5_o3, m5_o4, m5_o5, m5_o6, m5_o7, m5_o8, m5_o9, m5_o10,
+ m5_o11, m5_o12, m5_o13, m5_o14, m5_o15, m5_o16, m5_o17, m5_o18, m5_o19, m5_o20,
+ m5_o21, m5_o22, m5_o23, m5_o24, m5_o25, m5_o26, m5_o27, m5_o28, m5_o29, m5_o30,
+ m5_o31, m5_o32, m5_o33, m5_o34, m5_o35, m5_o36, m5_o37, m5_o38, m5_o39, m5_o40,
+ m5_o41, m5_o42, m5_o43, m5_o44, m5_o45, m5_o46, m5_o47, m5_o48, m5_o49, m5_o50,
+ m5_o51, m5_o52, m5_o53, m5_o54, m5_o55, m5_o56, m5_o57, m5_o58, m5_o59, m5_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct6(m6_o1, m6_o2, m6_o3, m6_o4, m6_o5, m6_o6, m6_o7, m6_o8, m6_o9, m6_o10,
+ m6_o11, m6_o12, m6_o13, m6_o14, m6_o15, m6_o16, m6_o17, m6_o18, m6_o19, m6_o20,
+ m6_o21, m6_o22, m6_o23, m6_o24, m6_o25, m6_o26, m6_o27, m6_o28, m6_o29, m6_o30,
+ m6_o31, m6_o32, m6_o33, m6_o34, m6_o35, m6_o36, m6_o37, m6_o38, m6_o39, m6_o40,
+ m6_o41, m6_o42, m6_o43, m6_o44, m6_o45, m6_o46, m6_o47, m6_o48, m6_o49, m6_o50,
+ m6_o51, m6_o52, m6_o53, m6_o54, m6_o55, m6_o56, m6_o57, m6_o58, m6_o59, m6_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct7(m7_o1, m7_o2, m7_o3, m7_o4, m7_o5, m7_o6, m7_o7, m7_o8, m7_o9, m7_o10,
+ m7_o11, m7_o12, m7_o13, m7_o14, m7_o15, m7_o16, m7_o17, m7_o18, m7_o19, m7_o20,
+ m7_o21, m7_o22, m7_o23, m7_o24, m7_o25, m7_o26, m7_o27, m7_o28, m7_o29, m7_o30,
+ m7_o31, m7_o32, m7_o33, m7_o34, m7_o35, m7_o36, m7_o37, m7_o38, m7_o39, m7_o40,
+ m7_o41, m7_o42, m7_o43, m7_o44, m7_o45, m7_o46, m7_o47, m7_o48, m7_o49, m7_o50,
+ m7_o51, m7_o52, m7_o53, m7_o54, m7_o55, m7_o56, m7_o57, m7_o58, m7_o59, m7_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct8(m8_o1, m8_o2, m8_o3, m8_o4, m8_o5, m8_o6, m8_o7, m8_o8, m8_o9, m8_o10,
+ m8_o11, m8_o12, m8_o13, m8_o14, m8_o15, m8_o16, m8_o17, m8_o18, m8_o19, m8_o20,
+ m8_o21, m8_o22, m8_o23, m8_o24, m8_o25, m8_o26, m8_o27, m8_o28, m8_o29, m8_o30,
+ m8_o31, m8_o32, m8_o33, m8_o34, m8_o35, m8_o36, m8_o37, m8_o38, m8_o39, m8_o40,
+ m8_o41, m8_o42, m8_o43, m8_o44, m8_o45, m8_o46, m8_o47, m8_o48, m8_o49, m8_o50,
+ m8_o51, m8_o52, m8_o53, m8_o54, m8_o55, m8_o56, m8_o57, m8_o58, m8_o59, m8_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct9(m9_o1, m9_o2, m9_o3, m9_o4, m9_o5, m9_o6, m9_o7, m9_o8, m9_o9, m9_o10,
+ m9_o11, m9_o12, m9_o13, m9_o14, m9_o15, m9_o16, m9_o17, m9_o18, m9_o19, m9_o20,
+ m9_o21, m9_o22, m9_o23, m9_o24, m9_o25, m9_o26, m9_o27, m9_o28, m9_o29, m9_o30,
+ m9_o31, m9_o32, m9_o33, m9_o34, m9_o35, m9_o36, m9_o37, m9_o38, m9_o39, m9_o40,
+ m9_o41, m9_o42, m9_o43, m9_o44, m9_o45, m9_o46, m9_o47, m9_o48, m9_o49, m9_o50,
+ m9_o51, m9_o52, m9_o53, m9_o54, m9_o55, m9_o56, m9_o57, m9_o58, m9_o59, m9_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+ reg [1:in_width] in, in_mem[1:patterns];
+ integer index;
+
+ assign {
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50 }
+  = $getpattern(in_mem[index]);
+
+ // monitor control
+ initial
+  begin
+   if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m0) %h", in_mem[index], 
+     { o1, o2, o3, o4, o5, o6, o7, o8, o9, o10,
+     o11, o12, o13, o14, o15, o16, o17, o18, o19, o20,
+     o21, o22, o23, o24, o25, o26, o27, o28, o29, o30,
+      o31, o32, o33, o34, o35, o36, o37, o38, o39, o40,
+     o41, o42, o43, o44, o45, o46, o47, o48, o49, o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m1) %h", in_mem[index], 
+    {m1_o1, m1_o2, m1_o3, m1_o4, m1_o5, m1_o6, m1_o7, m1_o8, m1_o9, m1_o10,
+     m1_o11, m1_o12, m1_o13, m1_o14, m1_o15, m1_o16, m1_o17, m1_o18, m1_o19,
+     m1_o20, m1_o21, m1_o22, m1_o23, m1_o24, m1_o25, m1_o26, m1_o27, m1_o28,
+     m1_o29, m1_o30, m1_o31, m1_o32, m1_o33, m1_o34, m1_o35, m1_o36, m1_o37,
+     m1_o38, m1_o39, m1_o40, m1_o41, m1_o42, m1_o43, m1_o44, m1_o45, m1_o46,
+     m1_o47, m1_o48, m1_o49, m1_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m2) %h", in_mem[index], 
+    {m2_o1, m2_o2, m2_o3, m2_o4, m2_o5, m2_o6, m2_o7, m2_o8, m2_o9, m2_o10,
+     m2_o11, m2_o12, m2_o13, m2_o14, m2_o15, m2_o16, m2_o17, m2_o18, m2_o19,
+     m2_o20, m2_o21, m2_o22, m2_o23, m2_o24, m2_o25, m2_o26, m2_o27, m2_o28,
+     m2_o29, m2_o30, m2_o31, m2_o32, m2_o33, m2_o34, m2_o35, m2_o36, m2_o37,
+     m2_o38, m2_o39, m2_o40, m2_o41, m2_o42, m2_o43, m2_o44, m2_o45, m2_o46,
+     m2_o47, m2_o48, m2_o49, m2_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m3) %h", in_mem[index], 
+    {m3_o1, m3_o2, m3_o3, m3_o4, m3_o5, m3_o6, m3_o7, m3_o8, m3_o9, m3_o10,
+     m3_o11, m3_o12, m3_o13, m3_o14, m3_o15, m3_o16, m3_o17, m3_o18, m3_o19,
+     m3_o20, m3_o21, m3_o22, m3_o23, m3_o24, m3_o25, m3_o26, m3_o27, m3_o28,
+     m3_o29, m3_o30, m3_o31, m3_o32, m3_o33, m3_o34, m3_o35, m3_o36, m3_o37,
+     m3_o38, m3_o39, m3_o40, m3_o41, m3_o42, m3_o43, m3_o44, m3_o45, m3_o46,
+     m3_o47, m3_o48, m3_o49, m3_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m4) %h", in_mem[index], 
+    {m4_o1, m4_o2, m4_o3, m4_o4, m4_o5, m4_o6, m4_o7, m4_o8, m4_o9, m4_o10,
+     m4_o11, m4_o12, m4_o13, m4_o14, m4_o15, m4_o16, m4_o17, m4_o18, m4_o19,
+     m4_o20, m4_o21, m4_o22, m4_o23, m4_o24, m4_o25, m4_o26, m4_o27, m4_o28,
+     m4_o29, m4_o30, m4_o31, m4_o32, m4_o33, m4_o34, m4_o35, m4_o36, m4_o37,
+     m4_o38, m4_o39, m4_o40, m4_o41, m4_o42, m4_o43, m4_o44, m4_o45, m4_o46,
+     m4_o47, m4_o48, m4_o49, m4_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m5) %h", in_mem[index], 
+    {m5_o1, m5_o2, m5_o3, m5_o4, m5_o5, m5_o6, m5_o7, m5_o8, m5_o9, m5_o10,
+     m5_o11, m5_o12, m5_o13, m5_o14, m5_o15, m5_o16, m5_o17, m5_o18, m5_o19,
+     m5_o20, m5_o21, m5_o22, m5_o23, m5_o24, m5_o25, m5_o26, m5_o27, m5_o28,
+     m5_o29, m5_o30, m5_o31, m5_o32, m5_o33, m5_o34, m5_o35, m5_o36, m5_o37,
+     m5_o38, m5_o39, m5_o40, m5_o41, m5_o42, m5_o43, m5_o44, m5_o45, m5_o46,
+     m5_o47, m5_o48, m5_o49, m5_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m6) %h", in_mem[index], 
+    {m6_o1, m6_o2, m6_o3, m6_o4, m6_o5, m6_o6, m6_o7, m6_o8, m6_o9, m6_o10,
+     m6_o11, m6_o12, m6_o13, m6_o14, m6_o15, m6_o16, m6_o17, m6_o18, m6_o19,
+     m6_o20, m6_o21, m6_o22, m6_o23, m6_o24, m6_o25, m6_o26, m6_o27, m6_o28,
+     m6_o29, m6_o30, m6_o31, m6_o32, m6_o33, m6_o34, m6_o35, m6_o36, m6_o37,
+     m6_o38, m6_o39, m6_o40, m6_o41, m6_o42, m6_o43, m6_o44, m6_o45, m6_o46,
+     m6_o47, m6_o48, m6_o49, m6_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m7) %h", in_mem[index], 
+    {m7_o1, m7_o2, m7_o3, m7_o4, m7_o5, m7_o6, m7_o7, m7_o8, m7_o9, m7_o10,
+     m7_o11, m7_o12, m7_o13, m7_o14, m7_o15, m7_o16, m7_o17, m7_o18, m7_o19,
+     m7_o20, m7_o21, m7_o22, m7_o23, m7_o24, m7_o25, m7_o26, m7_o27, m7_o28,
+     m7_o29, m7_o30, m7_o31, m7_o32, m7_o33, m7_o34, m7_o35, m7_o36, m7_o37,
+     m7_o38, m7_o39, m7_o40, m7_o41, m7_o42, m7_o43, m7_o44, m7_o45, m7_o46,
+     m7_o47, m7_o48, m7_o49, m7_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m8) %h", in_mem[index], 
+    {m8_o1, m8_o2, m8_o3, m8_o4, m8_o5, m8_o6, m8_o7, m8_o8, m8_o9, m8_o10,
+     m8_o11, m8_o12, m8_o13, m8_o14, m8_o15, m8_o16, m8_o17, m8_o18, m8_o19,
+     m8_o20, m8_o21, m8_o22, m8_o23, m8_o24, m8_o25, m8_o26, m8_o27, m8_o28,
+     m8_o29, m8_o30, m8_o31, m8_o32, m8_o33, m8_o34, m8_o35, m8_o36, m8_o37,
+     m8_o38, m8_o39, m8_o40, m8_o41, m8_o42, m8_o43, m8_o44, m8_o45, m8_o46,
+     m8_o47, m8_o48, m8_o49, m8_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m9) %h", in_mem[index], 
+    {m9_o1, m9_o2, m9_o3, m9_o4, m9_o5, m9_o6, m9_o7, m9_o8, m9_o9, m9_o10,
+     m9_o11, m9_o12, m9_o13, m9_o14, m9_o15, m9_o16, m9_o17, m9_o18, m9_o19,
+     m9_o20, m9_o21, m9_o22, m9_o23, m9_o24, m9_o25, m9_o26, m9_o27, m9_o28,
+     m9_o29, m9_o30, m9_o31, m9_o32, m9_o33, m9_o34, m9_o35, m9_o36, m9_o37,
+     m9_o38, m9_o39, m9_o40, m9_o41, m9_o42, m9_o43, m9_o44, m9_o45, m9_o46,
+     m9_o47, m9_o48, m9_o49, m9_o50 });
+  end
+
+ initial
+  begin
+   // $dumpvars;
+   $readmemb("gn.mem", in_mem, 1, patterns);
+
+   for (index = 1; index <= patterns; index = index + 1)
+    begin
+     fork
+      #(step/2)
+       if (mon_flag == 2) 
+        case (10*$time/(patterns*step))
+         0: $strobe($stime,, "in=%h out(m0)=%h", in_mem[index], 
+          { o1, o2, o3, o4, o5, o6, o7, o8, o9, o10,
+           o11, o12, o13, o14, o15, o16, o17, o18, o19, o20,
+           o21, o22, o23, o24, o25, o26, o27, o28, o29, o30,
+           o31, o32, o33, o34, o35, o36, o37, o38, o39, o40,
+           o41, o42, o43, o44, o45, o46, o47, o48, o49, o50 });
+         1: $strobe($stime,, "in=%h out(m2)=%h", in_mem[index], 
+          {m1_o1, m1_o2, m1_o3, m1_o4, m1_o5, m1_o6, m1_o7, m1_o8, m1_o9, m1_o10,
+          m1_o11, m1_o12, m1_o13, m1_o14, m1_o15, m1_o16, m1_o17, m1_o18, m1_o19,
+          m1_o20, m1_o21, m1_o22, m1_o23, m1_o24, m1_o25, m1_o26, m1_o27, m1_o28,
+          m1_o29, m1_o30, m1_o31, m1_o32, m1_o33, m1_o34, m1_o35, m1_o36, m1_o37,
+          m1_o38, m1_o39, m1_o40, m1_o41, m1_o42, m1_o43, m1_o44, m1_o45, m1_o46,
+          m1_o47, m1_o48, m1_o49, m1_o50 });
+         2: $strobe($stime,, "in=%h out(m2)=%h", in_mem[index], 
+          {m2_o1, m2_o2, m2_o3, m2_o4, m2_o5, m2_o6, m2_o7, m2_o8, m2_o9, m2_o10,
+          m2_o11, m2_o12, m2_o13, m2_o14, m2_o15, m2_o16, m2_o17, m2_o18, m2_o19,
+          m2_o20, m2_o21, m2_o22, m2_o23, m2_o24, m2_o25, m2_o26, m2_o27, m2_o28,
+          m2_o29, m2_o30, m2_o31, m2_o32, m2_o33, m2_o34, m2_o35, m2_o36, m2_o37,
+          m2_o38, m2_o39, m2_o40, m2_o41, m2_o42, m2_o43, m2_o44, m2_o45, m2_o46,
+          m2_o47, m2_o48, m2_o49, m2_o50 });
+         3: $strobe($stime,, "in=%h out(m3)=%h", in_mem[index], 
+          {m3_o1, m3_o2, m3_o3, m3_o4, m3_o5, m3_o6, m3_o7, m3_o8, m3_o9, m3_o10,
+          m3_o11, m3_o12, m3_o13, m3_o14, m3_o15, m3_o16, m3_o17, m3_o18, m3_o19,
+          m3_o20, m3_o21, m3_o22, m3_o23, m3_o24, m3_o25, m3_o26, m3_o27, m3_o28,
+          m3_o29, m3_o30, m3_o31, m3_o32, m3_o33, m3_o34, m3_o35, m3_o36, m3_o37,
+          m3_o38, m3_o39, m3_o40, m3_o41, m3_o42, m3_o43, m3_o44, m3_o45, m3_o46,
+          m3_o47, m3_o48, m3_o49, m3_o50 });
+         4: $strobe($stime,, "in=%h out(m4)=%h", in_mem[index], 
+          {m4_o1, m4_o2, m4_o3, m4_o4, m4_o5, m4_o6, m4_o7, m4_o8, m4_o9, m4_o10,
+          m4_o11, m4_o12, m4_o13, m4_o14, m4_o15, m4_o16, m4_o17, m4_o18, m4_o19,
+          m4_o20, m4_o21, m4_o22, m4_o23, m4_o24, m4_o25, m4_o26, m4_o27, m4_o28,
+          m4_o29, m4_o30, m4_o31, m4_o32, m4_o33, m4_o34, m4_o35, m4_o36, m4_o37,
+          m4_o38, m4_o39, m4_o40, m4_o41, m4_o42, m4_o43, m4_o44, m4_o45, m4_o46,
+          m4_o47, m4_o48, m4_o49, m4_o50 });
+         5: $strobe($stime,, "in=%h out(m5)=%h", in_mem[index], 
+          {m5_o1, m5_o2, m5_o3, m5_o4, m5_o5, m5_o6, m5_o7, m5_o8, m5_o9, m5_o10,
+          m5_o11, m5_o12, m5_o13, m5_o14, m5_o15, m5_o16, m5_o17, m5_o18, m5_o19,
+          m5_o20, m5_o21, m5_o22, m5_o23, m5_o24, m5_o25, m5_o26, m5_o27, m5_o28,
+          m5_o29, m5_o30, m5_o31, m5_o32, m5_o33, m5_o34, m5_o35, m5_o36, m5_o37,
+          m5_o38, m5_o39, m5_o40, m5_o41, m5_o42, m5_o43, m5_o44, m5_o45, m5_o46,
+          m5_o47, m5_o48, m5_o49, m5_o50 });
+         6: $strobe($stime,, "in=%h out(m6)=%h", in_mem[index], 
+          {m6_o1, m6_o2, m6_o3, m6_o4, m6_o5, m6_o6, m6_o7, m6_o8, m6_o9, m6_o10,
+          m6_o11, m6_o12, m6_o13, m6_o14, m6_o15, m6_o16, m6_o17, m6_o18, m6_o19,
+          m6_o20, m6_o21, m6_o22, m6_o23, m6_o24, m6_o25, m6_o26, m6_o27, m6_o28,
+          m6_o29, m6_o30, m6_o31, m6_o32, m6_o33, m6_o34, m6_o35, m6_o36, m6_o37,
+          m6_o38, m6_o39, m6_o40, m6_o41, m6_o42, m6_o43, m6_o44, m6_o45, m6_o46,
+          m6_o47, m6_o48, m6_o49, m6_o50 });
+         7: $strobe($stime,, "in=%h out(m7)=%h", in_mem[index], 
+          {m7_o1, m7_o2, m7_o3, m7_o4, m7_o5, m7_o6, m7_o7, m7_o8, m7_o9, m7_o10,
+          m7_o11, m7_o12, m7_o13, m7_o14, m7_o15, m7_o16, m7_o17, m7_o18, m7_o19,
+          m7_o20, m7_o21, m7_o22, m7_o23, m7_o24, m7_o25, m7_o26, m7_o27, m7_o28,
+          m7_o29, m7_o30, m7_o31, m7_o32, m7_o33, m7_o34, m7_o35, m7_o36, m7_o37,
+          m7_o38, m7_o39, m7_o40, m7_o41, m7_o42, m7_o43, m7_o44, m7_o45, m7_o46,
+          m7_o47, m7_o48, m7_o49, m7_o50 });
+         8: $strobe($stime,, "in=%h out(m8)=%h", in_mem[index], 
+          {m8_o1, m8_o2, m8_o3, m8_o4, m8_o5, m8_o6, m8_o7, m8_o8, m8_o9, m8_o10,
+          m8_o11, m8_o12, m8_o13, m8_o14, m8_o15, m8_o16, m8_o17, m8_o18, m8_o19,
+          m8_o20, m8_o21, m8_o22, m8_o23, m8_o24, m8_o25, m8_o26, m8_o27, m8_o28,
+          m8_o29, m8_o30, m8_o31, m8_o32, m8_o33, m8_o34, m8_o35, m8_o36, m8_o37,
+          m8_o38, m8_o39, m8_o40, m8_o41, m8_o42, m8_o43, m8_o44, m8_o45, m8_o46,
+          m8_o47, m8_o48, m8_o49, m8_o50 });
+         9: $strobe($stime,, "in=%h out(m9)=%h", in_mem[index], 
+          {m9_o1, m9_o2, m9_o3, m9_o4, m9_o5, m9_o6, m9_o7, m9_o8, m9_o9, m9_o10,
+          m9_o11, m9_o12, m9_o13, m9_o14, m9_o15, m9_o16, m9_o17, m9_o18, m9_o19,
+          m9_o20, m9_o21, m9_o22, m9_o23, m9_o24, m9_o25, m9_o26, m9_o27, m9_o28,
+          m9_o29, m9_o30, m9_o31, m9_o32, m9_o33, m9_o34, m9_o35, m9_o36, m9_o37,
+          m9_o38, m9_o39, m9_o40, m9_o41, m9_o42, m9_o43, m9_o44, m9_o45, m9_o46,
+          m9_o47, m9_o48, m9_o49, m9_o50 });
+        endcase
+      #step;
+     join
+    end 
+  end
+endmodule 
+
+module mod1(o1, o2, o3, o4, o5, o6, o7, o8, o9, o10,
+ o11, o12, o13, o14, o15, o16, o17, o18, o19, o20,
+ o21, o22, o23, o24, o25, o26, o27, o28, o29, o30,
+ o31, o32, o33, o34, o35, o36, o37, o38, o39, o40,
+ o41, o42, o43, o44, o45, o46, o47, o48, o49, o50,
+ o51, o52, o53, o54, o55, o56, o57, o58, o59, o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+ output o1, o2, o3, o4, o5, o6, o7, o8, o9, o10,
+ o11, o12, o13, o14, o15, o16, o17, o18, o19, o20,
+ o21, o22, o23, o24, o25, o26, o27, o28, o29, o30,
+ o31, o32, o33, o34, o35, o36, o37, o38, o39, o40,
+ o41, o42, o43, o44, o45, o46, o47, o48, o49, o50,
+ o51, o52, o53, o54, o55, o56, o57, o58, o59, o60;
+
+ input i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50;
+
+ dmod
+  mi1(o1, i1), mi2(o2, i2), mi3(o3, i3), mi4(o4, i4),
+  mi5(o5, i5),  mi6(o6, i6), mi7(o7, i7), mi8(o8, i8),
+  mi9(o9, i9), mi10(o10, i10),  mi11(o11, i11), mi12(o12, i12),
+  mi13(o13, i13), mi14(o14, i14), mi15(o15, i15), mi16(o16, i16),
+  mi17(o17, i17), mi18(o18, i18), mi19(o19, i19), mi110(o20, i20),
+  mi21(o21, i21), mi22(o22, i22), mi23(o23, i23), mi24(o24, i24),
+  mi25(o25, i25),  mi26(o26, i26), mi27(o27, i27), mi28(o28, i28),
+  mi29(o29, i29), mi30(o30, i30),  mi31(o31, i31), mi32(o32, i32),
+  mi33(o33, i33), mi34(o34, i34),  mi35(o35, i35), mi36(o36, i36),
+  mi37(o37, i37), mi38(o38, i38),  mi39(o39, i39), mi40(o40, i40),
+  mi41(o41, i41), mi42(o42, i42),  mi43(o43, i43), mi44(o44, i44),
+  mi45(o45, i45),  mi46(o46, i46), mi47(o47, i47), mi48(o48, i48),
+  mi49(o49, i49), mi50(o50, i50),
+  mi51(o51, i1), mi52(o52, i2), mi53(o53, i3), mi54(o54, i4),
+  mi55(o55, i5), mi56(o56, i6), mi57(o57, i7), mi58(o58, i8),
+  mi59(o59, i9), mi60(o60, i10);
+endmodule
+
+/* odd number of nots - input inverted to output */
+module dmod(o, i);
+ output o;
+ input i;
+
+ not #(5,3) g0(o, w1), g1(w1, w2), g2(w2, w3),
+ g3(w3, w4), g4(w4, w5), g5(w5, w6), g6(w6, w7), g7(w7, w8),
+ g8(w8, w9), g9(w9, w10), g10(w10, w11), g11(w11, w12), g12(w12, w13),
+ // notice broken chain  
+ g13(w13, i), g14(w14, w15), g15(w15, w16), g16(w16, w17), g17(w17, w18),
+ g18(w18, w19), g19(w19, w20), g20(w20, w21), g21(w21, w22), g22(w22, i);
+endmodule
diff --git a/tests_and_examples/install.tst/gn.mem b/tests_and_examples/install.tst/gn.mem
new file mode 100644
index 0000000..8b2f195
--- /dev/null
+++ b/tests_and_examples/install.tst/gn.mem
@@ -0,0 +1,11 @@
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
diff --git a/tests_and_examples/install.tst/inst_tst.sh b/tests_and_examples/install.tst/inst_tst.sh
new file mode 100755
index 0000000..d8101c3
--- /dev/null
+++ b/tests_and_examples/install.tst/inst_tst.sh
@@ -0,0 +1,96 @@
+#!/bin/sh 
+# install test procedures
+
+CVER="../../bin/cver -q " 
+
+if test ! -f ../../bin/cver 
+then
+  echo "ERROR - there is no cver in ../../bin/"
+  echo "Must make in src/ directory" 
+  exit;
+fi
+
+$CVER instid.v >/dev/null
+./rmlic.pl
+diff verilog.log instid.plg
+
+$CVER instpnd3.v >/dev/null
+./rmlic.pl
+diff verilog.log instpnd3.plg
+
+$CVER aspike1.v >/dev/null
+./rmlic.pl
+diff verilog.log aspike1.plg
+$CVER +warn_canceled_e aspike1.v >/dev/null
+./rmlic.pl
+diff verilog.log aspike1a.plg
+$CVER +show_canceled_e aspike1.v >/dev/null
+./rmlic.pl
+diff verilog.log aspike1b.plg
+$CVER +show_canceled_e +pulse_e_style_ondetect aspike1.v >/dev/null
+./rmlic.pl
+diff verilog.log aspike1c.plg
+$CVER aspike1.v -et >/dev/null
+./rmlic.pl
+diff verilog.log aspike1d.plg
+
+$CVER +warn_canceled_e -v JK_Q.v -v JK_QBAR.v udpjkff.v >/dev/null
+./rmlic.pl
+diff verilog.log udpjkff.plg
+
+$CVER xx2bdel.v >/dev/null
+./rmlic.pl
+diff verilog.log xx2bdel.plg
+$CVER xx2bpth.v >/dev/null
+./rmlic.pl
+diff verilog.log xx2bpth.plg
+$CVER xx2bpth2.v >/dev/null
+./rmlic.pl
+diff verilog.log xx2bpth2.plg
+
+$CVER c880.v >/dev/null
+./rmlic.pl
+diff verilog.log c880.plg
+
+$CVER -i force01.inp force01.v >/dev/null
+./rmlic.pl
+diff verilog.log force01.plg
+
+$CVER smrd04.v -f smrd04.vc >/dev/null
+./rmlic.pl
+diff verilog.log smrd04.plg
+
+$CVER gatenots.v >/dev/null
+./rmlic.pl
+diff verilog.log gatenots.plg
+
+$CVER arms_sim.v armscnt.v >/dev/null
+./rmlic.pl
+diff verilog.log arms.plg
+
+$CVER -f dfpsetd.vc >/dev/null
+./rmlic.pl
+diff verilog.log dfpsetd.plg
+
+$CVER -f mipdnot1.vc >/dev/null
+./rmlic.pl
+diff verilog.log mipdnot1.plg
+
+$CVER -f sdfia04.vc >/dev/null
+./rmlic.pl
+diff verilog.log sdfia04.plg
+
+$CVER dffn.v >/dev/null
+./rmlic.pl
+diff verilog.log dffn.plg
+
+$CVER xplipnd.v >/dev/null
+./rmlic.pl
+diff verilog.log xplipnd.plg
+
+$CVER defsplt1.v >/dev/null
+./rmlic.pl
+diff verilog.log defsplt1.plg
+
+echo ">>>> Install test completed (this should be only message printed)."
+echo " "
diff --git a/tests_and_examples/install.tst/instid.plg b/tests_and_examples/install.tst/instid.plg
new file mode 100644
index 0000000..b53865d
--- /dev/null
+++ b/tests_and_examples/install.tst/instid.plg
@@ -0,0 +1,16 @@
+i=         0,p1=          1,p2=          0
+i=         1,p1=          2,p2=          0
+i=         2,p1=          3,p2=          0
+i=         3,p1=          4,p2=          0
+i=         6,p1=          5,p2=          0
+i=         7,p1=          6,p2=          0
+i=         8,p1=          7,p2=          0
+i=         9,p1=          8,p2=          0
+i=        24,p1=          9,p2=          0
+i=        25,p1=         10,p2=          0
+i=        26,p1=         11,p2=          0
+i=        27,p1=         12,p2=          0
+i=        30,p1=         13,p2=          0
+i=        31,p1=         14,p2=          0
+i=        32,p1=         15,p2=          0
+i=        33,p1=         16,p2=          0
diff --git a/tests_and_examples/install.tst/instid.v b/tests_and_examples/install.tst/instid.v
new file mode 100644
index 0000000..0bf13bb
--- /dev/null
+++ b/tests_and_examples/install.tst/instid.v
@@ -0,0 +1,64 @@
+// instance identity test
+
+module level1(i);
+ input [31:0] i;
+ parameter p1 = 0, p2 = 0;
+ initial
+  begin
+   #1 $display("i=%d,p1=%d,p2=%d", i, p1, p2);
+  end
+endmodule
+
+module level2(i);
+ input [31:0] i;
+ parameter p1 = 0, p2 = 0;
+ level1 x1(2*i);
+ level1 x2(2*i + 1);
+endmodule
+
+module level3(i);
+ input [31:0] i;
+ parameter p1 = 0, p2 = 0;
+ level2 x1(3*i);
+ level2 x2(3*i + 1);
+endmodule
+
+module level4(i);
+ input [31:0] i;
+ parameter p1 = 0, p2 = 0;
+ level3 x1(4*i);
+ level3 x2(4*i + 1);
+endmodule
+
+module level5(i);
+ input [31:0] i;
+ parameter p1 = 0, p2 = 0;
+ level4 x1(4*i);
+ level4 x2(4*i + 1);
+endmodule
+
+module top;
+ integer i;
+
+ initial i = 0;
+ level5 t1(i);
+ defparam t1.x1.x1.x1.x1.p1 = 1;
+ defparam t1.x1.x1.x1.x2.p1 = 2;
+ defparam t1.x1.x1.x2.x1.p1 = 3;
+ defparam t1.x1.x1.x2.x2.p1 = 4;
+
+ defparam t1.x1.x2.x1.x1.p1 = 5;
+ defparam t1.x1.x2.x1.x2.p1 = 6;
+ defparam t1.x1.x2.x2.x1.p1 = 7;
+ defparam t1.x1.x2.x2.x2.p1 = 8;
+
+ defparam t1.x2.x1.x1.x1.p1 = 9;
+ defparam t1.x2.x1.x1.x2.p1 = 10;
+ defparam t1.x2.x1.x2.x1.p1 = 11;
+ defparam t1.x2.x1.x2.x2.p1 = 12;
+
+ defparam t1.x2.x2.x1.x1.p1 = 13;
+ defparam t1.x2.x2.x1.x2.p1 = 14;
+ defparam t1.x2.x2.x2.x1.p1 = 15;
+ defparam t1.x2.x2.x2.x2.p1 = 16;
+endmodule
diff --git a/tests_and_examples/install.tst/instpnd3.plg b/tests_and_examples/install.tst/instpnd3.plg
new file mode 100644
index 0000000..093fde8
--- /dev/null
+++ b/tests_and_examples/install.tst/instpnd3.plg
@@ -0,0 +1,46 @@
+**instpnd3.v(17) WARN** [602] x1(level1$$15) input port i (line **instpnd3.v(3)) width 16 mismatch with 2 * i width 32
+**instpnd3.v(18) WARN** [602] x2(level1) input port i (line **instpnd3.v(3)) width 17 mismatch with (2 * i) + 1 width 32
+**instpnd3.v(25) WARN** [602] x1(level2$$7) input port i (line **instpnd3.v(13)) width 25 mismatch with 3 * i width 32
+**instpnd3.v(26) WARN** [602] x2(level2) input port i (line **instpnd3.v(13)) width 25 mismatch with (3 * i) + 1 width 32
+**instpnd3.v(33) WARN** [602] x1(level3$$3) input port i (line **instpnd3.v(21)) width 25 mismatch with 4 * i width 32
+**instpnd3.v(34) WARN** [602] x2(level3) input port i (line **instpnd3.v(21)) width 25 mismatch with (4 * i) + 1 width 32
+**instpnd3.v(41) WARN** [602] x1(level4$$1) input port i (line **instpnd3.v(29)) width 25 mismatch with 4 * i width 32
+**instpnd3.v(42) WARN** [602] x2(level4) input port i (line **instpnd3.v(29)) width 25 mismatch with (4 * i) + 1 width 32
+**instpnd3.v(49) WARN** [602] t1(level5) input port i (line **instpnd3.v(37)) width 25 mismatch with i width 32
+**instpnd3.v(33) WARN** [602] x1(level3$$1) input port i (line **instpnd3.v(21)) width 25 mismatch with 4 * i width 32
+**instpnd3.v(34) WARN** [602] x2(level3$$2) input port i (line **instpnd3.v(21)) width 25 mismatch with (4 * i) + 1 width 32
+**instpnd3.v(25) WARN** [602] x1(level2$$5) input port i (line **instpnd3.v(13)) width 25 mismatch with 3 * i width 32
+**instpnd3.v(26) WARN** [602] x2(level2$$6) input port i (line **instpnd3.v(13)) width 25 mismatch with (3 * i) + 1 width 32
+**instpnd3.v(25) WARN** [602] x1(level2$$3) input port i (line **instpnd3.v(13)) width 25 mismatch with 3 * i width 32
+**instpnd3.v(26) WARN** [602] x2(level2$$4) input port i (line **instpnd3.v(13)) width 25 mismatch with (3 * i) + 1 width 32
+**instpnd3.v(25) WARN** [602] x1(level2$$1) input port i (line **instpnd3.v(13)) width 25 mismatch with 3 * i width 32
+**instpnd3.v(26) WARN** [602] x2(level2$$2) input port i (line **instpnd3.v(13)) width 25 mismatch with (3 * i) + 1 width 32
+**instpnd3.v(17) WARN** [602] x1(level1$$13) input port i (line **instpnd3.v(3)) width 10 mismatch with 2 * i width 32
+**instpnd3.v(18) WARN** [602] x2(level1$$14) input port i (line **instpnd3.v(3)) width 11 mismatch with (2 * i) + 1 width 32
+**instpnd3.v(17) WARN** [602] x1(level1$$11) input port i (line **instpnd3.v(3)) width 12 mismatch with 2 * i width 32
+**instpnd3.v(18) WARN** [602] x2(level1$$12) input port i (line **instpnd3.v(3)) width 13 mismatch with (2 * i) + 1 width 32
+**instpnd3.v(17) WARN** [602] x1(level1$$9) input port i (line **instpnd3.v(3)) width 6 mismatch with 2 * i width 32
+**instpnd3.v(18) WARN** [602] x2(level1$$10) input port i (line **instpnd3.v(3)) width 7 mismatch with (2 * i) + 1 width 32
+**instpnd3.v(17) WARN** [602] x1(level1$$7) input port i (line **instpnd3.v(3)) width 8 mismatch with 2 * i width 32
+**instpnd3.v(18) WARN** [602] x2(level1$$8) input port i (line **instpnd3.v(3)) width 9 mismatch with (2 * i) + 1 width 32
+**instpnd3.v(18) WARN** [602] x2(level1$$6) input port i (line **instpnd3.v(3)) width 3 mismatch with (2 * i) + 1 width 32
+**instpnd3.v(17) WARN** [602] x1(level1$$3) input port i (line **instpnd3.v(3)) width 4 mismatch with 2 * i width 32
+**instpnd3.v(18) WARN** [602] x2(level1$$4) input port i (line **instpnd3.v(3)) width 5 mismatch with (2 * i) + 1 width 32
+**instpnd3.v(17) WARN** [602] x1(level1$$1) input port i (line **instpnd3.v(3)) width 14 mismatch with 2 * i width 32
+**instpnd3.v(18) WARN** [602] x2(level1$$2) input port i (line **instpnd3.v(3)) width 15 mismatch with (2 * i) + 1 width 32
+i=         0,h=         31,p1=          1,p2=          0
+i=1,h=          2,p1=          2,p2=          0
+i= 2,h=          3,p1=          3,p2=          0
+i= 3,h=          4,p1=          4,p2=          0
+i= 6,h=          5,p1=          5,p2=          0
+i=  7,h=          6,p1=          6,p2=          0
+i=  8,h=          7,p1=          7,p2=          0
+i=  9,h=          8,p1=          8,p2=          0
+i=  24,h=          9,p1=          9,p2=          0
+i=  25,h=         10,p1=         10,p2=          0
+i=  26,h=         11,p1=         11,p2=          0
+i=  27,h=         12,p1=         12,p2=          0
+i=   30,h=         13,p1=         13,p2=          0
+i=   31,h=         14,p1=         14,p2=          0
+i=   32,h=         15,p1=         15,p2=          0
+i=    33,h=         16,p1=         16,p2=          0
diff --git a/tests_and_examples/install.tst/instpnd3.v b/tests_and_examples/install.tst/instpnd3.v
new file mode 100644
index 0000000..fcf463b
--- /dev/null
+++ b/tests_and_examples/install.tst/instpnd3.v
@@ -0,0 +1,89 @@
+// instance identity test
+
+module level1(i);
+ input [h:0] i;
+ parameter h = 31;
+ parameter p1 = 0, p2 = 0;
+ initial
+  begin
+   #1 $display("i=%d,h=%d,p1=%d,p2=%d", i, h, p1, p2);
+  end
+endmodule
+
+module level2(i);
+ input [h:0] i;
+ parameter h = 31;
+ parameter p1 = 0, p2 = 0;
+ level1 #(h) x1(2*i);
+ level1 #(h) x2(2*i + 1);
+endmodule
+
+module level3(i);
+ input [h:0] i;
+ parameter h = 31;
+ parameter p1 = 0, p2 = 0;
+ level2 #(h) x1(3*i);
+ level2 #(h) x2(3*i + 1);
+endmodule
+
+module level4(i);
+ input [h:0] i;
+ parameter h = 31;
+ parameter p1 = 0, p2 = 0;
+ level3 #(h) x1(4*i);
+ level3 #(h) x2(4*i + 1);
+endmodule
+
+module level5(i);
+ input [h:0] i;
+ parameter h = 31;
+ parameter p1 = 0, p2 = 0;
+ level4 #(h) x1(4*i);
+ level4 #(h) x2(4*i + 1);
+endmodule
+
+module top;
+ integer i;
+
+ initial i = 0;
+ level5 #(24) t1(i);
+ defparam t1.x1.x1.x1.x1.p1 = 1;
+ defparam t1.x1.x1.x1.x2.p1 = 2;
+ defparam t1.x1.x1.x2.x1.p1 = 3;
+ defparam t1.x1.x1.x2.x2.p1 = 4;
+
+ defparam t1.x1.x2.x1.x1.p1 = 5;
+ defparam t1.x1.x2.x1.x2.p1 = 6;
+ defparam t1.x1.x2.x2.x1.p1 = 7;
+ defparam t1.x1.x2.x2.x2.p1 = 8;
+
+ defparam t1.x2.x1.x1.x1.p1 = 9;
+ defparam t1.x2.x1.x1.x2.p1 = 10;
+ defparam t1.x2.x1.x2.x1.p1 = 11;
+ defparam t1.x2.x1.x2.x2.p1 = 12;
+
+ defparam t1.x2.x2.x1.x1.p1 = 13;
+ defparam t1.x2.x2.x1.x2.p1 = 14;
+ defparam t1.x2.x2.x2.x1.p1 = 15;
+ defparam t1.x2.x2.x2.x2.p1 = 16;
+
+ defparam t1.x1.x1.x1.x1.h = 31;
+ defparam t1.x1.x1.x1.x2.h = 2;
+ defparam t1.x1.x1.x2.x1.h = 3;
+ defparam t1.x1.x1.x2.x2.h = 4;
+
+ defparam t1.x1.x2.x1.x1.h = 5;
+ defparam t1.x1.x2.x1.x2.h = 6;
+ defparam t1.x1.x2.x2.x1.h = 7;
+ defparam t1.x1.x2.x2.x2.h = 8;
+
+ defparam t1.x2.x1.x1.x1.h = 9;
+ defparam t1.x2.x1.x1.x2.h = 10;
+ defparam t1.x2.x1.x2.x1.h = 11;
+ defparam t1.x2.x1.x2.x2.h = 12;
+
+ defparam t1.x2.x2.x1.x1.h = 13;
+ defparam t1.x2.x2.x1.x2.h = 14;
+ defparam t1.x2.x2.x2.x1.h = 15;
+ defparam t1.x2.x2.x2.x2.h = 16;
+endmodule
diff --git a/tests_and_examples/install.tst/jkff.v b/tests_and_examples/install.tst/jkff.v
new file mode 100644
index 0000000..da38d96
--- /dev/null
+++ b/tests_and_examples/install.tst/jkff.v
@@ -0,0 +1,14 @@
+/******************************************************************************/
+
+module jkff (t, tbar, j, k, ck, s, r);  
+
+  parameter rise = 0, fall = 0;
+
+  input  j, k, ck, s, r;    	// J, K, clock, s, clear
+  output t, tbar;               // data outputs
+
+  JK_Q    #(rise, fall) (t, j, k, ck, s, r);
+  JK_QBAR #(rise, fall) (tbar, j, k, ck, s, r);
+
+endmodule    // jkff
+
diff --git a/tests_and_examples/install.tst/mem.dat b/tests_and_examples/install.tst/mem.dat
new file mode 100644
index 0000000..ec318de
--- /dev/null
+++ b/tests_and_examples/install.tst/mem.dat
@@ -0,0 +1,9 @@
+00000_00000
+11111_11111
+xxxxx_xxxxx
+zzzzz_zzzzz
+01010_10101
+x1x1x_1x1x1
+10101_01010
+11001_10011
+// 00110_01100
diff --git a/tests_and_examples/install.tst/minisim.plg b/tests_and_examples/install.tst/minisim.plg
new file mode 100644
index 0000000..e6256c0
--- /dev/null
+++ b/tests_and_examples/install.tst/minisim.plg
@@ -0,0 +1,43 @@
+Loading toggle circuit
+Loading element 1, type DEdgeFF, with initial value 1(00000000_01000000)
+Loading element 2, type DEdgeFF, with initial value 1(00000000_01000000)
+Loading element 3, type Nand, with initial value 0(01000000_00000000)
+Loading element 4, type DEdgeFF, with initial value 1(00000000_01000000)
+Applying 2 clocks to input element 1
+At 1,0 Element 1, type DEdgeFF, changes to 0(01000000_00000000)
+At 2,0 Element 1, type DEdgeFF, changes to 1(00000000_01000000)
+At 2,1 Element 4, type DEdgeFF, changes to 0(01000000_00000000)
+At 2,2 Element 3, type Nand, changes to 1(00000000_01000000)
+At 3,0 Element 1, type DEdgeFF, changes to 0(01000000_00000000)
+At 4,0 Element 1, type DEdgeFF, changes to 1(00000000_01000000)
+At 4,1 Element 4, type DEdgeFF, changes to 1(00000000_01000000)
+At 4,2 Element 3, type Nand, changes to 0(01000000_00000000)
+Changing element 2 to value 0 and applying 1 clock
+At 5,0 Element 1, type DEdgeFF, changes to 0(01000000_00000000)
+At 5,0 Element 2, type DEdgeFF, changes to 0(01000000_00000000)
+At 5,1 Element 3, type Nand, changes to 1(00000000_01000000)
+At 6,0 Element 1, type DEdgeFF, changes to 1(00000000_01000000)
+
+Loading open-collector and pullup circuit
+Loading element 1, type DEdgeFF, with initial value 1(00000000_01000000)
+Loading element 2, type DEdgeFF, with initial value 0(01000000_00000000)
+Loading element 3, type Nand, with initial value 0(01000000_00000000)
+Loading element 4, type Nand, with initial value Z(00000000_00000001)
+Loading element 5, type Wire, with initial value 0(01000000_00000000)
+Loading element 6, type DEdgeFF, with initial value 1(00000000_00100000)
+Loading element 7, type Wire, with initial value 0(01000000_00000000)
+Changing element 1 to value 0
+At 7,0 Element 1, type DEdgeFF, changes to 0(01000000_00000000)
+At 7,1 Element 3, type Nand, changes to Z(00000000_00000001)
+At 7,2 Element 5, type Wire, changes to Z(00000000_00000001)
+At 7,3 Element 7, type Wire, changes to 1(00000000_00100000)
+Changing element 2 to value 1
+At 8,0 Element 2, type DEdgeFF, changes to 1(00000000_01000000)
+At 8,1 Element 4, type Nand, changes to 0(01000000_00000000)
+At 8,2 Element 5, type Wire, changes to 0(01000000_00000000)
+At 8,3 Element 7, type Wire, changes to 0(01000000_00000000)
+Changing element 2 to value X
+At 9,0 Element 2, type DEdgeFF, changes to X(01111111_01111111)
+At 9,1 Element 4, type Nand, changes to X(01111111_00000001)
+At 9,2 Element 5, type Wire, changes to X(01111111_00000001)
+At 9,3 Element 7, type Wire, changes to X(01111111_00111111)
diff --git a/tests_and_examples/install.tst/minisim.v b/tests_and_examples/install.tst/minisim.v
new file mode 100644
index 0000000..ecf1352
--- /dev/null
+++ b/tests_and_examples/install.tst/minisim.v
@@ -0,0 +1,489 @@
+/*-------------------
+minisim.v included with the permission of Kluwer Academic Publishers
+
+Copyright (r)
+
+THE VERILOG(tm) HARDWARE DESCRIPTION LANGUAGE, Second Edition by
+Donald E. Thomas and Philip Moorby, Copyright 1995 by Kluwer Academic
+Publishers.  Used by permission.
+
+Ordering information:
+THE VERILOG(tm) HARDWARE DESCRIPTION LANGUAGE, Second Edition by
+Donald E. Thomas and Philip R. Moorby, ISBN: 0-7923-9523-9, 304pp.,
+ cloth, $98.00
+
+Kluwer Academic Publishers           Phone 617-871-6600
+101 Philip Drive                     fax 617-871-6528
+Norwell, MA 02061                    email: kluwer at world.std.com
+
+Disk included:
+The Verilog(tm) Hardware Description Language, Second Edition includes
+a disk that contains a DOS version of the Veriwell(tm) Verilog simulator
+that can simulator up to 1000 lines of Verilog or 2000 total source lines
+as well as other examples from the book. The simulator can also be used
+to solve the exercices.
+--------------------*/
+
+//THE MINISIM EXAMPLE
+module miniSim;
+
+// element types being modeled
+`define Nand 0
+`define DEdgeFF 1
+`define Wire 2
+
+// literal values with strength:
+//   format is 8 0-strength bits in decreasing strength order
+//   followed by 8 1-strength bits in decreasing strength order
+`define Strong0 16'b01000000_00000000
+`define Strong1 16'b00000000_01000000
+`define StrongX 16'b01111111_01111111
+`define Pull0   16'b00100000_00000000
+`define Pull1   16'b00000000_00100000
+`define Highz0  16'b00000001_00000000
+`define Highz1  16'b00000000_00000001
+
+// three-valued logic set
+`define Val0 3'd0
+`define Val1 3'd1
+`define ValX 3'd2
+
+parameter
+    DebugFlags =               'b11000, //set to 1 for message
+//                               |||||
+//  loading                   <--+||||
+//  event value changes      <----+|||
+//  wire calculation        <------+||
+//  evaluation             <--------+|
+//  scheduling           <-----------+
+
+    IndexSize = 16,     //maximum size for index pointers
+    MaxElements = 50,   //maximum number of elements
+    TypeSize = 12;      //maximum number of types
+
+reg [IndexSize-1:0]
+    eventElement,             //output value change element
+    evalElement,              //evaluation element on fanout
+    fo0Index[1:MaxElements],  //first fanout index of eventElement
+    fo1Index[1:MaxElements],  //second fanout index of eventElement
+    currentList,              //current time scheduled event list
+    nextList,                 //unit delay scheduled event list
+    schedList[1:MaxElements]; //scheduled event list index
+reg [TypeSize-1:0]
+    eleType[1:MaxElements]; //element type
+reg
+    fo0TermNum[1:MaxElements],   //first fanout input terminal number
+    fo1TermNum[1:MaxElements],   //second fanout input terminal number
+    schedPresent[1:MaxElements]; //element is in scheduled event list flags
+reg [15:0]
+    eleStrength[1:MaxElements], //element strength indication
+    outVal[1:MaxElements],      //element output value
+    in0Val[1:MaxElements],      //element first input value
+    in1Val[1:MaxElements],      //element second input value
+    in0, in1, out, oldIn0;      //temporary value storage
+
+integer pattern, simTime; //time keepers
+
+initial
+  begin
+    // initialize variables
+    pattern = 0;
+    currentList = 0;
+    nextList = 0;
+
+    $display("Loading toggle circuit");
+    loadElement(1, `DEdgeFF, 0, `Strong1,0,0, 4,0,0,0);
+    loadElement(2, `DEdgeFF, 0, `Strong1,0,0, 3,0,0,0); 
+    loadElement(3, `Nand, (`Strong0|`Strong1),
+        `Strong0,`Strong1,`Strong1, 4,0,1,0); 
+    loadElement(4, `DEdgeFF, (`Strong0|`Strong1),
+        `Strong1,`Strong1,`Strong0, 3,0,1,0); 
+
+    // apply stimulus and simulate
+    $display("Applying 2 clocks to input element 1");
+    applyClock(2, 1);
+    $display("Changing element 2 to value 0 and applying 1 clock");
+    setupStim(2, `Strong0);
+    applyClock(1, 1);
+
+    $display("\nLoading open-collector and pullup circuit");
+    loadElement(1, `DEdgeFF, 0, `Strong1,0,0, 3,0,0,0);
+    loadElement(2, `DEdgeFF, 0, `Strong0,0,0, 4,0,0,0);
+    loadElement(3, `Nand, (`Strong0|`Highz1),
+        `Strong0,`Strong1,`Strong1, 5,0,0,0);
+    loadElement(4, `Nand, (`Strong0|`Highz1),
+        `Highz1,`Strong0,`Strong1, 5,0,1,0);
+    loadElement(5, `Wire, 0,
+        `Strong0,`Strong0,`Highz1, 7,0,1,0);
+    loadElement(6, `DEdgeFF, 0, `Pull1,0,0, 7,0,0,0);
+    loadElement(7, `Wire, 0,
+        `Strong0,`Pull1,`Strong0, 0,0,0,0);
+
+    // apply stimulus and simulate
+    $display("Changing element 1 to value 0");
+    pattern = pattern + 1;
+    setupStim(1, `Strong0);
+    executeEvents;
+    $display("Changing element 2 to value 1");
+    pattern = pattern + 1;
+    setupStim(2, `Strong1);
+    executeEvents;
+    $display("Changing element 2 to value X");
+    pattern = pattern + 1;
+    setupStim(2, `StrongX);
+    executeEvents;
+  end
+
+// Initialize data structure for a given element.
+task loadElement;
+input [IndexSize-1:0] loadAtIndex; //element index being loaded
+input [TypeSize-1:0] type;         //type of element
+input [15:0] strengthCoercion;     //strength specification of element
+input [15:0] oVal, i0Val, i1Val;   //output and input values
+input [IndexSize-1:0] fo0, fo1;    //fanout element indexes
+input fo0Term, fo1Term;            //fanout element input terminal indicators
+  begin
+    if (DebugFlags[4])
+        $display(
+            "Loading element %0d, type %0s, with initial value %s(%b_%b)",
+            loadAtIndex, typeString(type),
+            valString(oVal), oVal[15:8], oVal[7:0]);
+    eleType[loadAtIndex] = type;
+    eleStrength[loadAtIndex] = strengthCoercion;
+    outVal[loadAtIndex] = oVal;
+    in0Val[loadAtIndex] = i0Val;
+    in1Val[loadAtIndex] = i1Val;
+    fo0Index[loadAtIndex] = fo0;
+    fo1Index[loadAtIndex] = fo1;
+    fo0TermNum[loadAtIndex] = fo0Term;
+    fo1TermNum[loadAtIndex] = fo1Term;
+    schedPresent[loadAtIndex] = 0;
+  end
+endtask
+
+// Given a type number, return a type string
+function [32*8:1] typeString;
+input [TypeSize-1:0] type;
+    case (type)
+      `Nand: typeString = "Nand";
+      `DEdgeFF: typeString = "DEdgeFF";
+      `Wire: typeString = "Wire";
+      default: typeString = "*** Unknown element type";
+    endcase
+endfunction
+
+// Setup a value change on an element.
+task setupStim;
+input [IndexSize-1:0] vcElement; //element index
+input [15:0] newVal;           //new element value
+  begin
+    if (! schedPresent[vcElement])
+      begin
+        schedList[vcElement] = currentList;
+        currentList = vcElement;
+        schedPresent[vcElement] = 1;
+      end
+    outVal[vcElement] = newVal;
+  end
+endtask
+
+// Setup and simulate a given number of clock pulses to a given element.
+task applyClock;
+input [7:0] nClocks;
+input [IndexSize-1:0] vcElement;
+    repeat(nClocks)
+      begin
+        pattern = pattern + 1;
+        setupStim(vcElement, `Strong0);
+        executeEvents;
+        pattern = pattern + 1;
+        setupStim(vcElement, `Strong1);
+        executeEvents;
+      end
+endtask
+
+// Execute all events in the current event list.
+// Then move the events in the next event list to the current event
+// list and loop back to execute these events. Continue this loop
+// until no more events to execute.
+// For each event executed, evaluate the two fanout elements if present.
+task executeEvents;
+reg [15:0] newVal;
+  begin
+    simTime = 0;
+    while (currentList)
+      begin
+        eventElement = currentList;
+        currentList = schedList[eventElement];
+        schedPresent[eventElement] = 0;
+        newVal = outVal[eventElement];
+        if (DebugFlags[3])
+            $display(
+                "At %0d,%0d Element %0d, type %0s, changes to %s(%b_%b)",
+                pattern, simTime,
+                eventElement, typeString(eleType[eventElement]),
+                valString(newVal), newVal[15:8], newVal[7:0]);
+        if (fo0Index[eventElement]) evalFo(0);
+        if (fo1Index[eventElement]) evalFo(1);
+        if (! currentList) // if empty move to next time unit
+          begin
+            currentList = nextList;
+            nextList = 0;
+            simTime = simTime + 1;
+          end
+      end
+  end
+endtask
+
+// Evaluate a fanout element by testing its type and calling the
+// appropriate evaluation routine.
+task evalFo;
+input fanout; //first or second fanout indicator
+  begin
+    evalElement = fanout ? fo1Index[eventElement] : 
+                           fo0Index[eventElement];
+    if (DebugFlags[1])
+        $display("Evaluating Element %0d type is %0s",
+            evalElement, typeString(eleType[evalElement]));
+    case (eleType[evalElement])
+      `Nand: evalNand(fanout);
+      `DEdgeFF: evalDEdgeFF(fanout);
+      `Wire: evalWire(fanout);
+    endcase
+  end
+endtask
+
+// Store output value of event element into
+// input value of evaluation element.
+task storeInVal;
+input fanout; //first or second fanout indicator
+  begin
+    // store new input value
+    if (fanout ? fo1TermNum[eventElement] : fo0TermNum[eventElement])
+        in1Val[evalElement] = outVal[eventElement];
+    else
+        in0Val[evalElement] = outVal[eventElement];
+  end
+endtask
+
+// Convert a given full strength value to three-valued logic (0, 1 or X)
+function [1:0] log3;
+input [15:0] inVal;
+    casez (inVal)
+      16'b00000000_00000000: log3 = `ValX;
+      16'b???????0_00000000: log3 = `Val0;
+      16'b00000000_???????0: log3 = `Val1;
+      default:               log3 = `ValX;
+    endcase
+endfunction
+
+// Convert a given full strength value to four-valued logic (0, 1, X or Z),
+// returning a 1 character string
+function [8:1] valString;
+input [15:0] inVal;
+    case (log3(inVal))
+      `Val0: valString = "0";
+      `Val1: valString = "1";
+      `ValX: valString = (inVal & 16'b11111110_11111110) ? "X" : "Z";
+    endcase
+endfunction
+
+// Coerce a three-valued logic output value to a full output strength value
+// for the scheduling of the evaluation element
+function [15:0] strengthVal;
+input [1:0] logVal;
+    case (logVal)
+      `Val0: strengthVal = eleStrength[evalElement] & 16'b11111111_00000000;
+      `Val1: strengthVal = eleStrength[evalElement] & 16'b00000000_11111111;
+      `ValX: strengthVal = fillBits(eleStrength[evalElement]);
+    endcase
+endfunction
+
+// Given an incomplete strength value, fill the missing strength bits.
+// The filling is only necessary when the value is unknown.
+function [15:0] fillBits;
+input [15:0] val;
+  begin
+    fillBits = val;
+    if (log3(val) == `ValX)
+      begin
+        casez (val)
+  16'b1???????_????????: fillBits = fillBits | 16'b11111111_00000001;
+  16'b01??????_????????: fillBits = fillBits | 16'b01111111_00000001;
+  16'b001?????_????????: fillBits = fillBits | 16'b00111111_00000001;
+  16'b0001????_????????: fillBits = fillBits | 16'b00011111_00000001;
+  16'b00001???_????????: fillBits = fillBits | 16'b00001111_00000001;
+  16'b000001??_????????: fillBits = fillBits | 16'b00000111_00000001;
+  16'b0000001?_????????: fillBits = fillBits | 16'b00000011_00000001;
+        endcase
+        casez (val)
+  16'b????????_1???????: fillBits = fillBits | 16'b00000001_11111111;
+  16'b????????_01??????: fillBits = fillBits | 16'b00000001_01111111;
+  16'b????????_001?????: fillBits = fillBits | 16'b00000001_00111111;
+  16'b????????_0001????: fillBits = fillBits | 16'b00000001_00011111;
+  16'b????????_00001???: fillBits = fillBits | 16'b00000001_00001111;
+  16'b????????_000001??: fillBits = fillBits | 16'b00000001_00000111;
+  16'b????????_0000001?: fillBits = fillBits | 16'b00000001_00000011;
+       endcase
+     end
+  end
+endfunction
+
+// Evaluate a 'Nand' gate primitive.
+task evalNand;
+input fanout; //first or second fanout indicator
+  begin
+    storeInVal(fanout);
+    // calculate new output value
+    in0 = log3(in0Val[evalElement]);
+    in1 = log3(in1Val[evalElement]);
+    out = ((in0 == `Val0) || (in1 == `Val0)) ?
+        strengthVal(`Val1) :
+        ((in0 == `ValX) || (in1 == `ValX)) ?
+            strengthVal(`ValX):
+            strengthVal(`Val0);
+    // schedule if output value is different
+    if (out != outVal[evalElement])
+        schedule(out);
+  end
+endtask
+
+// Evaluate a D positive edge-triggered flip flop
+task evalDEdgeFF;
+input fanout; //first or second fanout indicator
+    // check value change is on clock input
+    if (fanout ? (fo1TermNum[eventElement] == 0) :
+                 (fo0TermNum[eventElement] == 0))
+      begin
+        // get old clock value
+        oldIn0 = log3(in0Val[evalElement]);
+        storeInVal(fanout);
+        in0 = log3(in0Val[evalElement]);
+        // test for positive edge on clock input
+        if ((oldIn0 == `Val0) && (in0 == `Val1))
+          begin
+            out = strengthVal(log3(in1Val[evalElement]));
+            if (out != outVal[evalElement])
+              schedule(out);
+          end
+      end
+    else
+        storeInVal(fanout); // store data input value
+endtask
+
+// Evaluate a wire with full strength values
+task evalWire;
+input fanout;
+reg [7:0] mask;
+  begin
+    storeInVal(fanout);
+
+    in0 = in0Val[evalElement];
+    in1 = in1Val[evalElement];
+    mask = getMask(in0[15:8]) & getMask(in0[7:0]) &
+           getMask(in1[15:8]) & getMask(in1[7:0]);
+    out = fillBits((in0 | in1) & {mask, mask});
+
+    if (out != outVal[evalElement])
+        schedule(out);
+
+    if (DebugFlags[2])
+        $display("in0 = %b_%b\nin1 = %b_%b\nmask= %b %b\nout = %b_%b",
+            in0[15:8],in0[7:0], in1[15:8],in1[7:0],
+            mask,mask, out[15:8],out[7:0]);
+  end
+endtask
+
+// Given either a 0-strength or 1-strength half of a strength value
+// return a masking pattern for use in a wire evaluation.
+function [7:0] getMask;
+input [7:0] halfVal; //half a full strength value
+    casez (halfVal)
+      8'b???????1: getMask = 8'b11111111;
+      8'b??????10: getMask = 8'b11111110;
+      8'b?????100: getMask = 8'b11111100;
+      8'b????1000: getMask = 8'b11111000;
+      8'b???10000: getMask = 8'b11110000;
+      8'b??100000: getMask = 8'b11100000;
+      8'b?1000000: getMask = 8'b11000000;
+      8'b10000000: getMask = 8'b10000000;
+      8'b00000000: getMask = 8'b11111111;
+    endcase
+endfunction
+
+// Schedule the evaluation element to change to a new value.
+// If the element is already scheduled then just insert the new value.
+task schedule;
+input [15:0] newVal; // new value to change to
+  begin
+    if (DebugFlags[0])
+        $display(
+            "Element %0d, type %0s, scheduled to change to %s(%b_%b)",
+            evalElement, typeString(eleType[evalElement]),
+            valString(newVal), newVal[15:8], newVal[7:0]);
+    if (! schedPresent[evalElement])
+      begin
+        schedList[evalElement] = nextList;
+        schedPresent[evalElement] = 1;
+        nextList = evalElement;
+      end
+    outVal[evalElement] = newVal;
+  end
+endtask
+endmodule
+
+/*******************  PLEASE NOTE:  ************************************
+
+The values printed out in the book section 7.1.3 have the wrong
+format. The 0 and 1 strength bits need to be swapped around. For
+example, the first value printed in the book should read
+1(00000000_01000000) and not 1(0100000_00000000). The value format you
+get from running the above minisim description through Verilog should
+be correct.
+
+Here is a listing of the results:
+
+Loading toggle circuit
+Loading element 1, type DEdgeFF, with initial value 1(00000000_01000000)
+Loading element 2, type DEdgeFF, with initial value 1(00000000_01000000)
+Loading element 3, type Nand, with initial value 0(01000000_00000000)
+Loading element 4, type DEdgeFF, with initial value 1(00000000_01000000)
+Applying 2 clocks to input element 1
+At 1,0 Element 1, type DEdgeFF, changes to 0(01000000_00000000)
+At 2,0 Element 1, type DEdgeFF, changes to 1(00000000_01000000)
+At 2,1 Element 4, type DEdgeFF, changes to 0(01000000_00000000)
+At 2,2 Element 3, type Nand, changes to 1(00000000_01000000)
+At 3,0 Element 1, type DEdgeFF, changes to 0(01000000_00000000)
+At 4,0 Element 1, type DEdgeFF, changes to 1(00000000_01000000)
+At 4,1 Element 4, type DEdgeFF, changes to 1(00000000_01000000)
+At 4,2 Element 3, type Nand, changes to 0(01000000_00000000)
+Changing element 2 to value 0 and applying 1 clock
+At 5,0 Element 1, type DEdgeFF, changes to 0(01000000_00000000)
+At 5,0 Element 2, type DEdgeFF, changes to 0(01000000_00000000)
+At 5,1 Element 3, type Nand, changes to 1(00000000_01000000)
+At 6,0 Element 1, type DEdgeFF, changes to 1(00000000_01000000)
+
+Loading open-collector and pullup circuit
+Loading element 1, type DEdgeFF, with initial value 1(00000000_01000000)
+Loading element 2, type DEdgeFF, with initial value 0(01000000_00000000)
+Loading element 3, type Nand, with initial value 0(01000000_00000000)
+Loading element 4, type Nand, with initial value Z(00000000_00000001)
+Loading element 5, type Wire, with initial value 0(01000000_00000000)
+Loading element 6, type DEdgeFF, with initial value 1(00000000_00100000)
+Loading element 7, type Wire, with initial value 0(01000000_00000000)
+Changing element 1 to value 0
+At 7,0 Element 1, type DEdgeFF, changes to 0(01000000_00000000)
+At 7,1 Element 3, type Nand, changes to Z(00000000_00000001)
+At 7,2 Element 5, type Wire, changes to Z(00000000_00000001)
+At 7,3 Element 7, type Wire, changes to 1(00000000_00100000)
+Changing element 2 to value 1
+At 8,0 Element 2, type DEdgeFF, changes to 1(00000000_01000000)
+At 8,1 Element 4, type Nand, changes to 0(01000000_00000000)
+At 8,2 Element 5, type Wire, changes to 0(01000000_00000000)
+At 8,3 Element 7, type Wire, changes to 0(01000000_00000000)
+Changing element 2 to value X
+At 9,0 Element 2, type DEdgeFF, changes to X(01111111_01111111)
+At 9,1 Element 4, type Nand, changes to X(01111111_00000001)
+At 9,2 Element 5, type Wire, changes to X(01111111_00000001)
+At 9,3 Element 7, type Wire, changes to X(01111111_00111111)
+*****************************************************************/
diff --git a/tests_and_examples/install.tst/mipdnot1.plg b/tests_and_examples/install.tst/mipdnot1.plg
new file mode 100644
index 0000000..7651bf4
--- /dev/null
+++ b/tests_and_examples/install.tst/mipdnot1.plg
@@ -0,0 +1,29 @@
+         0 w1=x, r1=x, w2=x, r2=x
+       100 w1=x, r1=0, w2=x, r2=x
+       110 w1=1, r1=0, w2=x, r2=x
+       200 w1=1, r1=0, w2=x, r2=0
+       208 w1=1, r1=0, w2=1, r2=0
+       300 w1=1, r1=1, w2=1, r2=0
+       315 w1=0, r1=1, w2=1, r2=0
+       400 w1=0, r1=1, w2=1, r2=1
+       412 w1=0, r1=1, w2=0, r2=1
+       500 w1=0, r1=0, w2=0, r2=1
+       510 w1=1, r1=0, w2=0, r2=1
+       600 w1=1, r1=0, w2=0, r2=0
+       608 w1=1, r1=0, w2=1, r2=0
+       700 w1=1, r1=x, w2=1, r2=0
+       705 w1=x, r1=x, w2=1, r2=0
+       800 w1=x, r1=x, w2=1, r2=x
+       804 w1=x, r1=x, w2=x, r2=x
+       900 w1=x, r1=0, w2=x, r2=x
+       910 w1=1, r1=0, w2=x, r2=x
+      1000 w1=1, r1=0, w2=x, r2=0
+      1008 w1=1, r1=0, w2=1, r2=0
+      1100 w1=1, r1=z, w2=1, r2=0
+      1105 w1=x, r1=z, w2=1, r2=0
+      1200 w1=x, r1=z, w2=1, r2=z
+      1204 w1=x, r1=z, w2=x, r2=z
+      1300 w1=x, r1=1, w2=x, r2=z
+      1315 w1=0, r1=1, w2=x, r2=z
+      1400 w1=0, r1=1, w2=x, r2=1
+      1412 w1=0, r1=1, w2=0, r2=1
diff --git a/tests_and_examples/install.tst/mipdnot1.sdf b/tests_and_examples/install.tst/mipdnot1.sdf
new file mode 100644
index 0000000..43545f0
--- /dev/null
+++ b/tests_and_examples/install.tst/mipdnot1.sdf
@@ -0,0 +1,9 @@
+(DELAYFILE 
+  (SDFVERSION "3.0") 
+  (CELL 
+   (CELLTYPE "xx" ) 
+   (INSTANCE xx) 
+   (DELAY (ABSOLUTE (PORT i1.a (15) (10) (5))))
+   (DELAY (ABSOLUTE (PORT i2.a (12) (8) (4))))
+  )
+)
diff --git a/tests_and_examples/install.tst/mipdnot1.v b/tests_and_examples/install.tst/mipdnot1.v
new file mode 100644
index 0000000..17d6e8c
--- /dev/null
+++ b/tests_and_examples/install.tst/mipdnot1.v
@@ -0,0 +1,40 @@
+module xx;
+ wire w1, w2; 
+ reg r1, r2;
+
+ modnot i1(w1, r1);
+ modnot i2(w2, r2);
+
+ initial 
+  begin
+   $monitor($stime,, "w1=%b, r1=%b, w2=%b, r2=%b", w1, r1, w2, r2);
+   #100 r1 = 0;
+   #100 r2 = 0;
+
+   #100 r1 = 1;
+   #100 r2 = 1;
+
+   #100 r1 = 0;
+   #100 r2 = 0;
+
+   #100 r1 = 1'bx;
+   #100 r2 = 1'bx;
+
+   #100 r1 = 0;
+   #100 r2 = 0;
+
+   #100 r1 = 1'bz;
+   #100 r2 = 1'bz;
+
+   #100 r1 = 1;
+   #100 r2 = 1;
+  end
+endmodule
+
+module modnot(out, a);
+ output out;
+ input a;
+
+ not (out, a); 
+endmodule
+
diff --git a/tests_and_examples/install.tst/mipdnot1.vc b/tests_and_examples/install.tst/mipdnot1.vc
new file mode 100644
index 0000000..c5c26dd
--- /dev/null
+++ b/tests_and_examples/install.tst/mipdnot1.vc
@@ -0,0 +1,2 @@
+mipdnot1.v
++sdfannotate mipdnot1.sdf
diff --git a/tests_and_examples/install.tst/patt.mem b/tests_and_examples/install.tst/patt.mem
new file mode 100644
index 0000000..f6cca0f
--- /dev/null
+++ b/tests_and_examples/install.tst/patt.mem
@@ -0,0 +1,8 @@
+00000_00000_00000_00000_00000_00000_00000_00000_00000_00000_00000_00000
+11111_11111_11111_11111_11111_11111_11111_11111_11111_11111_11111_11111
+xxxxx_xxxxx_xxxxx_xxxxx_xxxxx_xxxxx_xxxxx_xxxxx_xxxxx_xxxxx_xxxxx_xxxxx
+zzzzz_zzzzz_zzzzz_zzzzz_zzzzz_zzzzz_zzzzz_zzzzz_zzzzz_zzzzz_zzzzz_zzzzz
+01010_10101_01010_10101_01010_10101_01010_10101_01010_10101_01010_10101
+x1x1x_1x1x1_x1x1x_1x1x1_x1x1x_1x1x1_x1x1x_1x1x1_x1x1x_1x1x1_x1x1x_1x1x1
+10101_01010_10101_01010_10101_01010_10101_01010_10101_01010_10101_01010
+11001_10011_11001_10011_11001_10011_11001_10011_11001_10011_11001_10011
diff --git a/tests_and_examples/install.tst/rmlic.pl b/tests_and_examples/install.tst/rmlic.pl
new file mode 100755
index 0000000..39c7ade
--- /dev/null
+++ b/tests_and_examples/install.tst/rmlic.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+use strict;
+my $file;
+my $i;
+my $line;
+ 
+ $file = 'verilog.log';
+ if (@ARGV == 1)
+ {
+     $file = $ARGV[0];
+ }
+
+ open(FILE, $file) or die "Can't open $file\n";
+ open(TMP, '>tmp') or die "Can't open tmp file\n";
+ for($i = 0; $i < 3; $i++)
+ {
+      $line = <FILE>;
+ }
+ while(<FILE>)
+ {
+      print TMP $_;
+ }
+ close TMP;
+ close FILE;
+ rename 'tmp', $file;
diff --git a/tests_and_examples/install.tst/sdfia04.plg b/tests_and_examples/install.tst/sdfia04.plg
new file mode 100644
index 0000000..699b80c
--- /dev/null
+++ b/tests_and_examples/install.tst/sdfia04.plg
@@ -0,0 +1,11 @@
+                   0 preset[1]=x clear[1]=x q[18]=x qbar[18]=x
+                  10 preset[1]=0 clear[1]=1 q[18]=x qbar[18]=x
+                  13 preset[1]=0 clear[1]=1 q[18]=1 qbar[18]=x
+                  16 preset[1]=0 clear[1]=1 q[18]=1 qbar[18]=0
+                  20 preset[1]=1 clear[1]=1 q[18]=1 qbar[18]=0
+                  30 preset[1]=1 clear[1]=0 q[18]=1 qbar[18]=0
+                  31 preset[1]=1 clear[1]=0 q[18]=1 qbar[18]=x
+                  32 preset[1]=1 clear[1]=0 q[18]=x qbar[18]=x
+                  33 preset[1]=1 clear[1]=0 q[18]=x qbar[18]=1
+                  36 preset[1]=1 clear[1]=0 q[18]=0 qbar[18]=1
+                  40 preset[1]=1 clear[1]=1 q[18]=0 qbar[18]=1
diff --git a/tests_and_examples/install.tst/sdfia04.sdf b/tests_and_examples/install.tst/sdfia04.sdf
new file mode 100644
index 0000000..dc4bbba
--- /dev/null
+++ b/tests_and_examples/install.tst/sdfia04.sdf
@@ -0,0 +1,13 @@
+(DELAYFILE 
+  (SDFVERSION "3.0") 
+  (CELL 
+   (CELLTYPE "and" ) 
+   (INSTANCE q1[18]) 
+   (DELAY (INCREMENT (DEVICE (:2:1))))
+  )
+  (CELL 
+   (CELLTYPE "and" ) 
+   (INSTANCE q2[18]) 
+   (DELAY (INCREMENT (DEVICE (1:2:))))
+  )
+)
diff --git a/tests_and_examples/install.tst/sdfia04.v b/tests_and_examples/install.tst/sdfia04.v
new file mode 100644
index 0000000..86e5811
--- /dev/null
+++ b/tests_and_examples/install.tst/sdfia04.v
@@ -0,0 +1,26 @@
+module ffnand_test;
+ wire [1:18] q, qbar;
+ reg [18:1] preset, clear;
+
+ parameter d = 10;
+
+ ffnand #(.wide(17)) ff1[1:18](q, qbar, preset, clear);
+ initial 
+  begin
+   #d preset[1] = 0; clear[1] = 1;
+   #d preset[1] = 1;
+   #d clear[1] = 0;
+   #d clear[1] = 1;
+  end
+ initial $monitor($time,, "preset[1]=%b clear[1]=%b q[18]=%b qbar[18]=%b",
+  preset[1], clear[1], q[18], qbar[18]);
+endmodule
+
+module ffnand(ffq, ffqbar, ffpreset, ffclear);
+ output [1:wide + 1] ffq, ffqbar;
+ input [wide + 1:1] ffpreset, ffclear;
+ parameter wide = 1;
+ 
+ nand #1 q1[1:wide + 1] (ffq, ffqbar, ffpreset),
+  q2[1:wide + 1] (ffqbar, ffq, ffclear); 
+endmodule
diff --git a/tests_and_examples/install.tst/sdfia04.vc b/tests_and_examples/install.tst/sdfia04.vc
new file mode 100644
index 0000000..7affb39
--- /dev/null
+++ b/tests_and_examples/install.tst/sdfia04.vc
@@ -0,0 +1,2 @@
++sdfannotate sdfia04.sdf+ffnand_test.ff1[18]
+sdfia04.v
diff --git a/tests_and_examples/install.tst/smrd04.plg b/tests_and_examples/install.tst/smrd04.plg
new file mode 100644
index 0000000..2fed380
--- /dev/null
+++ b/tests_and_examples/install.tst/smrd04.plg
@@ -0,0 +1,2 @@
+idprom[1]=0010011011
+idprom[2]=0000001111
diff --git a/tests_and_examples/install.tst/smrd04.v b/tests_and_examples/install.tst/smrd04.v
new file mode 100644
index 0000000..071e6a4
--- /dev/null
+++ b/tests_and_examples/install.tst/smrd04.v
@@ -0,0 +1,22 @@
+module top;
+ parameter idprom_width = 10, idprom_depth = 2, step = 20;
+ reg [8*idprom_width:1] s1, s2;
+ integer index;
+
+ reg [idprom_width:1] idprom[1:idprom_depth];
+
+ initial
+  begin
+   // probably should do some checking here
+   if ($scan$plusargs("idprom1=", s1) == 0
+    || $scan$plusargs("idprom2=", s2) == 0) 
+    begin
+     $display("missing or bad idprom option(s)"); 
+     $finish;
+    end
+   $sreadmemb(idprom,,, s1, s2);
+   for (index = 0; index < idprom_depth; index = index + 1) #step;
+   for (index = 1; index <= idprom_depth; index = index + 1)   
+    $display("idprom[%0d]=%b", index, idprom[index]); 
+  end
+endmodule
diff --git a/tests_and_examples/install.tst/smrd04.vc b/tests_and_examples/install.tst/smrd04.vc
new file mode 100644
index 0000000..ded1f59
--- /dev/null
+++ b/tests_and_examples/install.tst/smrd04.vc
@@ -0,0 +1,2 @@
++idprom1=0010011011
++idprom2=00001111
diff --git a/tests_and_examples/install.tst/testmem.dat b/tests_and_examples/install.tst/testmem.dat
new file mode 100644
index 0000000..e356cd6
--- /dev/null
+++ b/tests_and_examples/install.tst/testmem.dat
@@ -0,0 +1,10 @@
+0000000000_0000000000_0000000000_0000000000_0000000000_0000000000_0000000
+1111111111_1111111111_1111111111_1111111111_1111111111_1111111111_1111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101_0101010101_0101010
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x
+1010101010_1010101010_1010101010_1010101010_1010101010_1010101010_1010101
+1100110011_1100110011_1100110011_1100110011_1100110011_1100110011_1100110
+z1z1z1z1z1_z1z1z1z1z1_z1z1z1z1z1_z1z1z1z1z1_z1z1z1z1z1_z1z1z1z1z1_z1z1z1z
+01xz01xz01_01xz01xz01_01xz01xz01_01xz01xz01_01xz01xz01_01xz01xz01_01xz01x
diff --git a/tests_and_examples/install.tst/udpjkff.plg b/tests_and_examples/install.tst/udpjkff.plg
new file mode 100644
index 0000000..98554c9
--- /dev/null
+++ b/tests_and_examples/install.tst/udpjkff.plg
@@ -0,0 +1,35 @@
+                   0 t=x,tbar=x,j=0,k=0,clock= x,s=1,r=1
+                  10 t=1,tbar=0,j=0,k=0,clock= x,s=0,r=1
+                  30 t=0,tbar=0,j=0,k=0,clock= x,s=0,r=0
+                  40 t=1,tbar=0,j=0,k=0,clock= x,s=0,r=1
+                  60 t=1,tbar=0,j=0,k=0,clock= 0,s=0,r=1
+                  70 t=1,tbar=0,j=0,k=0,clock= 1,s=0,r=1
+                  80 t=1,tbar=0,j=0,k=1,clock= 1,s=0,r=1
+                  90 t=1,tbar=0,j=0,k=1,clock= 0,s=0,r=1
+                 100 t=1,tbar=0,j=0,k=1,clock= 1,s=0,r=1
+                 110 t=1,tbar=0,j=1,k=0,clock= 1,s=0,r=1
+                 120 t=1,tbar=0,j=1,k=0,clock= 0,s=0,r=1
+                 130 t=1,tbar=0,j=1,k=0,clock= 1,s=0,r=1
+                 140 t=1,tbar=0,j=1,k=1,clock= 1,s=0,r=1
+                 150 t=1,tbar=0,j=1,k=1,clock= 0,s=0,r=1
+                 160 t=1,tbar=0,j=1,k=1,clock= 1,s=0,r=1
+                 170 t=1,tbar=0,j=0,k=1,clock= 1,s=0,r=1
+                 180 t=1,tbar=0,j=0,k=1,clock= 0,s=0,r=1
+                 190 t=1,tbar=0,j=0,k=1,clock= 1,s=0,r=1
+                 200 t=1,tbar=0,j=0,k=0,clock= 1,s=0,r=1
+                 210 t=1,tbar=0,j=0,k=0,clock= 0,s=0,r=1
+                 220 t=1,tbar=0,j=0,k=0,clock= 1,s=0,r=1
+                 230 t=0,tbar=0,j=0,k=0,clock= 1,s=0,r=0
+                 240 t=0,tbar=0,j=0,k=0,clock= 0,s=0,r=0
+                 250 t=0,tbar=0,j=0,k=0,clock= 1,s=0,r=0
+                 270 t=0,tbar=1,j=0,k=0,clock= 1,s=1,r=0
+                 280 t=0,tbar=1,j=0,k=0,clock= 0,s=1,r=0
+                 290 t=0,tbar=1,j=0,k=0,clock= 1,s=1,r=0
+                 300 t=0,tbar=1,j=0,k=0,clock= 1,s=1,r=1
+                 310 t=1,tbar=0,j=0,k=0,clock= 1,s=0,r=1
+                 320 t=0,tbar=1,j=0,k=0,clock= 1,s=1,r=0
+                 330 t=0,tbar=1,j=0,k=0,clock= 1,s=1,r=1
+**udpjkff.v(66) WARN** now 340 [592] JK_Q gate top.inst1.__gate$$1 drives glitch (edge at 340 replaced by new at 340) - old 0, scheduled 1, new 0
+                 340 t=0,tbar=0,j=0,k=0,clock= 1,s=0,r=0
+                 350 t=0,tbar=1,j=0,k=0,clock= 1,s=1,r=0
+                 360 t=1,tbar=0,j=0,k=0,clock= 1,s=0,r=1
diff --git a/tests_and_examples/install.tst/udpjkff.v b/tests_and_examples/install.tst/udpjkff.v
new file mode 100644
index 0000000..243fe07
--- /dev/null
+++ b/tests_and_examples/install.tst/udpjkff.v
@@ -0,0 +1,69 @@
+module top;
+
+reg r_clock,j,k,s,r;
+assign clock = r_clock;
+
+jkff inst1 (t, tbar, j, k, clock, s, r);  
+
+initial begin
+$monitor ($time,,"t=%b,tbar=%b,j=%b,k=%b,clock= %b,s=%b,r=%b",
+ t, tbar, j, k, clock, s, r); 
+j = 0;
+k = 0;
+s = 1;
+r = 1;
+end
+
+initial begin
+
+#10 s = 0;
+#10 r = 1;
+#10 r  = 0;
+#10 r = 1;
+#10 j = 0; k = 0;
+#10 r_clock = 0;
+#10 r_clock = 1;
+#10 j = 0; k = 1;
+#10 r_clock = 0;
+#10 r_clock = 1;
+#10 j = 1; k = 0;
+#10 r_clock = 0;
+#10 r_clock = 1;
+#10 j = 1; k = 1;
+#10 r_clock = 0;
+#10 r_clock = 1;
+#10 j = 0; k = 1;
+#10 r_clock = 0;
+#10 r_clock = 1;
+#10 j = 0; k = 0;
+#10 r_clock = 0;
+#10 r_clock = 1;
+#10 r = 0;
+#10 r_clock = 0;
+#10 r_clock = 1;
+#10 r = 0;
+#10 s = 1;
+#10 r_clock = 0;
+#10 r_clock = 1;
+#10 r = 1;
+#10 s = 0; r = 1;
+#10 s = 1; r = 0;
+#10 s = 1; r = 1;
+#10 s = 0; r = 0;
+#10 s = 1; r = 0;
+#10 s = 0; r = 1;
+end
+endmodule
+
+// jk flip flop from valid SIM library
+module jkff (t, tbar, j, k, ck, s, r);  
+
+  parameter rise = 0, fall = 0;
+
+  input  j, k, ck, s, r;    	// J, K, clock, s, clear
+  output t, tbar;               // data outputs
+
+  JK_Q    #(rise, fall) (t, j, k, ck, s, r);
+  JK_QBAR #(rise, fall) (tbar, j, k, ck, s, r);
+
+endmodule    // jkff
diff --git a/tests_and_examples/install.tst/xplipnd.plg b/tests_and_examples/install.tst/xplipnd.plg
new file mode 100644
index 0000000..ce0edd5
--- /dev/null
+++ b/tests_and_examples/install.tst/xplipnd.plg
@@ -0,0 +1,16 @@
+i=         0,p1=        500,p2=        501
+i=         1,p1=        502,p2=        503
+i=         2,p1=        500,p2=        501
+i=         3,p1=        502,p2=        503
+i=         6,p1=        500,p2=        501
+i=         7,p1=        502,p2=        503
+i=         8,p1=        500,p2=        501
+i=         9,p1=        502,p2=        503
+i=        24,p1=        500,p2=        501
+i=        25,p1=        502,p2=        503
+i=        26,p1=        500,p2=        501
+i=        27,p1=        502,p2=        503
+i=        30,p1=        500,p2=        501
+i=        31,p1=        502,p2=        503
+i=        32,p1=        500,p2=        501
+i=        33,p1=        502,p2=        503
diff --git a/tests_and_examples/install.tst/xplipnd.v b/tests_and_examples/install.tst/xplipnd.v
new file mode 100644
index 0000000..848d543
--- /dev/null
+++ b/tests_and_examples/install.tst/xplipnd.v
@@ -0,0 +1,67 @@
+// instance identity test
+
+module level1(i);
+ input [31:0] i;
+ parameter p1 = 0, p2 = 0;
+ initial
+  begin
+   #1 $display("i=%d,p1=%d,p2=%d", i, p1, p2);
+  end
+endmodule
+
+module level2(i);
+ input [31:0] i;
+ parameter p1 = 0, p2 = 0;
+ level1 #(.p1(500), .p2(501)) x1(2*i);
+ level1 #(.p1(502), .p2(503)) x2(2*i + 1);
+endmodule
+
+module level3(i);
+ input [31:0] i;
+ parameter p1 = 0, p2 = 0;
+ level2 #(.p1(400), .p2(401)) x1(3*i);
+ level2 #(.p2(403), .p1(402)) x2(3*i + 1);
+endmodule
+
+module level4(i);
+ input [31:0] i;
+ parameter p1 = 0, p2 = 0;
+ level3 #(.p1(300), .p2(301)) x1(4*i);
+ level3 #(.p1(302), .p2(303)) x2(4*i + 1);
+endmodule
+
+module level5(i);
+ input [31:0] i;
+ parameter p1 = 0, p2 = 0;
+ level4 #(.p1(200), .p2(201)) x1(4*i);
+ level4 #(.p1(202), .p2(203)) x2(4*i + 1);
+endmodule
+
+module top;
+ integer i;
+
+ initial i = 0;
+ level5 #(100,101) t1(i);
+ /* --
+ defparam t1.x1.x1.x1.x1.p1 = 1'h1;
+ defparam t1.x1.x1.x1.x2.p1 = 2'h2;
+ defparam t1.x1.x1.x2.x1.p1 = 3'h3;
+ defparam t1.x1.x1.x2.x2.p1 = 4'h4;
+
+ defparam t1.x1.x2.x1.x1.p1 = 5'h5;
+ defparam t1.x1.x2.x1.x2.p1 = 6'h6;
+ defparam t1.x1.x2.x2.x1.p1 = 7'h7;
+ defparam t1.x1.x2.x2.x2.p1 = 8'h8;
+
+ defparam t1.x2.x1.x1.x1.p1 = 9'h9;
+ defparam t1.x2.x1.x1.x2.p1 = 10'ha;
+ defparam t1.x2.x1.x2.x1.p1 = 11'hb;
+ defparam t1.x2.x1.x2.x2.p1 = 12'hc;
+
+ defparam t1.x2.x2.x1.x1.p1 = 13'hd;
+ defparam t1.x2.x2.x1.x2.p1 = 14'he;
+ defparam t1.x2.x2.x2.x1.p1 = 15'hf;
+ defparam t1.x2.x2.x2.x2.p1 = 16'h10;
+ defparam t1.x2.x2.x2.x2.p2 = 93'h3f01;
+ -- */
+endmodule
diff --git a/tests_and_examples/install.tst/xx2bdel.plg b/tests_and_examples/install.tst/xx2bdel.plg
new file mode 100644
index 0000000..f46fc4c
--- /dev/null
+++ b/tests_and_examples/install.tst/xx2bdel.plg
@@ -0,0 +1,33 @@
+         0 input 0000000000 output xxxxxxxxxx and xxxxxxxxxx
+         2 input 0000000000 output 0000000000 and xxxxxxxxxx
+         3 input 0000000000 output 0000000000 and 1111111111
+       100 -->read: 000 same: 000 invert: 3ff
+       200 input 1111111111 output 0000000000 and 1111111111
+       202 input 1111111111 output 1111111111 and 1111111111
+       203 input 1111111111 output 1111111111 and 0000000000
+       300 -->read: 3ff same: 3ff invert: 000
+       400 input xxxxxxxxxx output 1111111111 and 0000000000
+       402 input xxxxxxxxxx output xxxxxxxxxx and 0000000000
+       403 input xxxxxxxxxx output xxxxxxxxxx and xxxxxxxxxx
+       500 -->read: xxx same: xxx invert: xxx
+       600 input zzzzzzzzzz output xxxxxxxxxx and xxxxxxxxxx
+       700 -->read: zzz same: xxx invert: xxx
+       800 input 0101010101 output xxxxxxxxxx and xxxxxxxxxx
+       802 input 0101010101 output 0101010101 and xxxxxxxxxx
+       803 input 0101010101 output 0101010101 and 1010101010
+       900 -->read: 155 same: 155 invert: 2aa
+      1000 input x1x1x1x1x1 output 0101010101 and 1010101010
+      1002 input x1x1x1x1x1 output x1x1x1x1x1 and 1010101010
+      1003 input x1x1x1x1x1 output x1x1x1x1x1 and x0x0x0x0x0
+      1100 -->read: XXX same: XXX invert: XXX
+      1200 input 1010101010 output x1x1x1x1x1 and x0x0x0x0x0
+      1202 input 1010101010 output 1010101010 and x0x0x0x0x0
+      1203 input 1010101010 output 1010101010 and 0101010101
+      1300 -->read: 2aa same: 2aa invert: 155
+      1400 input 1100110011 output 1010101010 and 0101010101
+      1402 input 1100110011 output 1100110011 and 0101010101
+      1403 input 1100110011 output 1100110011 and 0011001100
+      1500 -->read: 333 same: 333 invert: 0cc
+      1600 input xxxxxxxxxx output 1100110011 and 0011001100
+      1602 input xxxxxxxxxx output xxxxxxxxxx and 0011001100
+      1603 input xxxxxxxxxx output xxxxxxxxxx and xxxxxxxxxx
diff --git a/tests_and_examples/install.tst/xx2bdel.v b/tests_and_examples/install.tst/xx2bdel.v
new file mode 100644
index 0000000..34abbaa
--- /dev/null
+++ b/tests_and_examples/install.tst/xx2bdel.v
@@ -0,0 +1,77 @@
+module yy;
+parameter
+	in_width = 10,
+	patterns = 8,
+	out_width = 20,
+	step = 200,
+	mon_flag = 1;
+ parameter d1=3, d2=5, d3=7;
+
+med1 intop(to1, to2, to3, to4, to5, to6, to7, to8, to9, to10,
+ to11, to12, to13, to14, to15, to16, to17, to18, to19, to20,
+ ti1, ti2, ti3, ti4, ti5, ti6, ti7, ti8, ti9, ti10);
+
+ reg [15:0] gnam;
+ reg [1:in_width] in, in_mem[1:patterns];
+ integer index, i;
+
+ assign { ti1, ti2, ti3, ti4, ti5, ti6, ti7, ti8, ti9, ti10 }
+  = $getpattern(in_mem[index]);
+
+   /* --- */ 
+ initial
+  begin
+   $readmemb("mem.dat", in_mem, 1, patterns);
+   $monitor($stime,, "input %b output %b and %b", in_mem[index], 
+    { to1, to2, to3, to4, to5, to6, to7, to8, to9, to10 }, 
+    { to11, to12, to13, to14, to15, to16, to17, to18, to19, to20 });
+   // $showvars;
+   // $setevtrace;
+   // $monitoroff;
+   // $list(yy);
+  for (index = 1; index <= patterns; index = index + 1) 
+    fork
+     #(step/2)
+      if (mon_flag)
+       $strobe($stime,, "-->read: %h same: %h invert: %h",
+       in_mem[index],
+        { to1, to2, to3, to4, to5, to6, to7, to8, to9, to10 },
+	{ to11, to12, to13, to14, to15, to16, to17, to18, to19, to20});
+     #step;
+    join
+  end
+endmodule 
+
+module med1(mo1, mo2, mo3, mo4, mo5, mo6, mo7, mo8, mo9, mo10,
+ mo11, mo12, mo13, mo14, mo15, mo16, mo17, mo18, mo19, mo20,
+ mi1, mi2, mi3, mi4, mi5, mi6, mi7, mi8, mi9, mi10);
+
+ output mo1, mo2, mo3, mo4, mo5, mo6, mo7, mo8, mo9, mo10,
+  mo11, mo12, mo13, mo14, mo15, mo16, mo17, mo18, mo19, mo20;
+ input mi1, mi2, mi3, mi4, mi5, mi6, mi7, mi8, mi9, mi10;
+
+ bot
+  inmedi1(mo1, mi1), inmedi2(mo2, mi2), inmedi3(mo3, mi3), inmedi4(mo4, mi4),
+  inmedi5(mo5, mi5),  inmedi6(mo6, mi6), inmedi7(mo7, mi7), inmedi8(mo8, mi8),
+  inmedi9(mo9, mi9), inmedi10(mo10, mi10);
+ bot2
+  inmed11(mo11, mi1), inmed12(mo12, mi2),
+  inmed13(mo13, mi3), inmed14(mo14, mi4), inmed15(mo15, mi5),
+  inmed16(mo16, mi6), inmed17(mo17, mi7), inmed18(mo18, mi8),
+  inmed19(mo19, mi9), inmed20(mo20, mi10);
+endmodule
+
+// identity through some nots
+module bot(o, i);
+ output o;
+ input i;
+ not #1 g0(o, w1), g1(w1, i), g2(w2, w3), g3(w3, i);
+endmodule
+
+// inverter through some nots
+module bot2(o, i);
+ output o;
+ input i;
+
+ not #1 g0(o, w1), g1(w1, w2), g2(w2, i);
+endmodule
diff --git a/tests_and_examples/install.tst/xx2bpth.plg b/tests_and_examples/install.tst/xx2bpth.plg
new file mode 100644
index 0000000..8e6b14a
--- /dev/null
+++ b/tests_and_examples/install.tst/xx2bpth.plg
@@ -0,0 +1,40 @@
+         0 input 0000000000 output xxxxxxxxxx and xxxxxxxxxx
+         3 input 0000000000 output 0000000000 and xxxxxxxxxx
+        10 -->read: 000 same: 000 invert: xxx
+        13 input 0000000000 output 0000000000 and 1111111111
+        20 input 1111111111 output 0000000000 and 1111111111
+        25 input 1111111111 output 1111111111 and 1111111111
+        30 -->read: 3ff same: 3ff invert: 3ff
+        31 input 1111111111 output 1111111111 and 0000000000
+        40 input xxxxxxxxxx output 1111111111 and 0000000000
+        43 input xxxxxxxxxx output xxxxxxxxxx and 0000000000
+        49 input xxxxxxxxxx output xxxxxxxxxx and xxxxxxxxxx
+        50 -->read: xxx same: xxx invert: xxx
+        60 input zzzzzzzzzz output xxxxxxxxxx and xxxxxxxxxx
+        70 -->read: zzz same: xxx invert: xxx
+        80 input 0101010101 output xxxxxxxxxx and xxxxxxxxxx
+        83 input 0101010101 output 0x0x0x0x0x and xxxxxxxxxx
+        85 input 0101010101 output 0101010101 and xxxxxxxxxx
+        90 -->read: 155 same: 155 invert: xxx
+        91 input 0101010101 output 0101010101 and x0x0x0x0x0
+        93 input 0101010101 output 0101010101 and 1010101010
+       100 input x1x1x1x1x1 output 0101010101 and 1010101010
+       105 input x1x1x1x1x1 output x1x1x1x1x1 and 1010101010
+       109 input x1x1x1x1x1 output x1x1x1x1x1 and x0x0x0x0x0
+       110 -->read: XXX same: XXX invert: XXX
+       120 input 1010101010 output x1x1x1x1x1 and x0x0x0x0x0
+       123 input 1010101010 output x0x0x0x0x0 and x0x0x0x0x0
+       125 input 1010101010 output 1010101010 and x0x0x0x0x0
+       130 -->read: 2aa same: 2aa invert: XXX
+       131 input 1010101010 output 1010101010 and 0000000000
+       133 input 1010101010 output 1010101010 and 0101010101
+       140 input 1100110011 output 1010101010 and 0101010101
+       143 input 1100110011 output 1000100010 and 0101010101
+       145 input 1100110011 output 1100110011 and 0101010101
+       150 -->read: 333 same: 333 invert: 155
+       151 input 1100110011 output 1100110011 and 0001000100
+       153 input 1100110011 output 1100110011 and 0011001100
+       160 input xxxxxxxxxx output 1100110011 and 0011001100
+       163 input xxxxxxxxxx output xx00xx00xx and 0011001100
+       165 input xxxxxxxxxx output xxxxxxxxxx and 0011001100
+       169 input xxxxxxxxxx output xxxxxxxxxx and xxxxxxxxxx
diff --git a/tests_and_examples/install.tst/xx2bpth.v b/tests_and_examples/install.tst/xx2bpth.v
new file mode 100644
index 0000000..ed3742e
--- /dev/null
+++ b/tests_and_examples/install.tst/xx2bpth.v
@@ -0,0 +1,87 @@
+module yy;
+parameter
+	in_width = 10,
+	patterns = 8,
+	out_width = 20,
+	step = 20,
+	mon_flag = 1;
+
+med1 intop(to1, to2, to3, to4, to5, to6, to7, to8, to9, to10,
+ to11, to12, to13, to14, to15, to16, to17, to18, to19, to20,
+ ti1, ti2, ti3, ti4, ti5, ti6, ti7, ti8, ti9, ti10);
+
+ reg [1:in_width] in, in_mem[1:patterns];
+ integer index;
+
+ assign { ti1, ti2, ti3, ti4, ti5, ti6, ti7, ti8, ti9, ti10 }
+  = $getpattern(in_mem[index]);
+
+ initial
+  begin
+   $readmemb("mem.dat", in_mem, 1, patterns);
+   $monitor($stime,, "input %b output %b and %b", in_mem[index], 
+    { to1, to2, to3, to4, to5, to6, to7, to8, to9, to10 }, 
+    { to11, to12, to13, to14, to15, to16, to17, to18, to19, to20 });
+   // $showvars;
+   // $setevtrace;
+   // $monitoroff;
+   // $list(example_2b);
+
+  for (index = 1; index <= patterns; index = index + 1)
+    fork
+     // #(step/2) if (mon_flag) $monitor;
+     #(step/2)
+      if (mon_flag)
+       $strobe($stime,, "-->read: %h same: %h invert: %h",
+       in_mem[index],
+        { to1, to2, to3, to4, to5, to6, to7, to8, to9, to10 },
+	{ to11, to12, to13, to14, to15, to16, to17, to18, to19, to20});
+     #step;
+    join
+  end
+endmodule 
+
+module med1(mo1, mo2, mo3, mo4, mo5, mo6, mo7, mo8, mo9, mo10,
+ mo11, mo12, mo13, mo14, mo15, mo16, mo17, mo18, mo19, mo20,
+ mi1, mi2, mi3, mi4, mi5, mi6, mi7, mi8, mi9, mi10);
+
+ output mo1, mo2, mo3, mo4, mo5, mo6, mo7, mo8, mo9, mo10,
+  mo11, mo12, mo13, mo14, mo15, mo16, mo17, mo18, mo19, mo20;
+ input mi1, mi2, mi3, mi4, mi5, mi6, mi7, mi8, mi9, mi10;
+
+ bot
+  inmedi1(mo1, mi1), inmedi2(mo2, mi2), inmedi3(mo3, mi3), inmedi4(mo4, mi4),
+  inmedi5(mo5, mi5),  inmedi6(mo6, mi6), inmedi7(mo7, mi7), inmedi8(mo8, mi8),
+  inmedi9(mo9, mi9), inmedi10(mo10, mi10);
+ bot2
+  inmed11(mo11, mi1), inmed12(mo12, mi2),
+  inmed13(mo13, mi3), inmed14(mo14, mi4), inmed15(mo15, mi5),
+  inmed16(mo16, mi6), inmed17(mo17, mi7), inmed18(mo18, mi8),
+  inmed19(mo19, mi9), inmed20(mo20, mi10);
+endmodule
+
+// identity through some nots
+module bot(o, i);
+ output o;
+ input i;
+ not g0(o, w1), g1(w1, i), g2(w2, w3), g3(w3, i);
+ specify
+  specparam rise = 5, fall = 3;
+  // paths
+  (i => o) = (rise, fall);
+ endspecify
+endmodule
+
+// inverter through some nots
+module bot2(o, i);
+ output o;
+ input i;
+
+ not #(5,3) g0(o, w1), g1(w1, w2), g2(w2, i);
+ specify
+  specparam rise = 5, fall = 3;
+  // paths
+  (i => o) = (rise, fall);
+  $width(posedge i, 20);
+ endspecify
+endmodule
diff --git a/tests_and_examples/install.tst/xx2bpth2.plg b/tests_and_examples/install.tst/xx2bpth2.plg
new file mode 100644
index 0000000..e391a06
--- /dev/null
+++ b/tests_and_examples/install.tst/xx2bpth2.plg
@@ -0,0 +1,37 @@
+         0 input 0000000000 output xxxxxxxxxx and xxxxxxxxxx
+         8 input 0000000000 output 0000000000 and xxxxxxxxxx
+        10 -->read: 000 same: 000 invert: xxx
+        13 input 0000000000 output 0000000000 and 1111111111
+        20 input 1111111111 output 0000000000 and 1111111111
+        28 input 1111111111 output 1111111111 and 1111111111
+        30 -->read: 3ff same: 3ff invert: 3ff
+        31 input 1111111111 output 1111111111 and 0000000000
+        40 input xxxxxxxxxx output 1111111111 and 0000000000
+        48 input xxxxxxxxxx output xxxxxxxxxx and 0000000000
+        50 -->read: xxx same: xxx invert: 000
+        53 input xxxxxxxxxx output xxxxxxxxxx and xxxxxxxxxx
+        60 input zzzzzzzzzz output xxxxxxxxxx and xxxxxxxxxx
+        70 -->read: zzz same: xxx invert: xxx
+        80 input 0101010101 output xxxxxxxxxx and xxxxxxxxxx
+        88 input 0101010101 output 0101010101 and xxxxxxxxxx
+        90 -->read: 155 same: 155 invert: xxx
+        91 input 0101010101 output 0101010101 and x0x0x0x0x0
+        93 input 0101010101 output 0101010101 and 1010101010
+       100 input x1x1x1x1x1 output 0101010101 and 1010101010
+       108 input x1x1x1x1x1 output x1x1x1x1x1 and 1010101010
+       110 -->read: XXX same: XXX invert: 2aa
+       111 input x1x1x1x1x1 output x1x1x1x1x1 and x0x0x0x0x0
+       120 input 1010101010 output x1x1x1x1x1 and x0x0x0x0x0
+       128 input 1010101010 output 1010101010 and x0x0x0x0x0
+       130 -->read: 2aa same: 2aa invert: XXX
+       131 input 1010101010 output 1010101010 and 0000000000
+       133 input 1010101010 output 1010101010 and 0101010101
+       140 input 1100110011 output 1010101010 and 0101010101
+       148 input 1100110011 output 1100110011 and 0101010101
+       150 -->read: 333 same: 333 invert: 155
+       151 input 1100110011 output 1100110011 and 0001000100
+       153 input 1100110011 output 1100110011 and 0011001100
+       160 input xxxxxxxxxx output 1100110011 and 0011001100
+       168 input xxxxxxxxxx output xxxxxxxxxx and 0011001100
+       171 input xxxxxxxxxx output xxxxxxxxxx and 00xx00xx00
+       173 input xxxxxxxxxx output xxxxxxxxxx and xxxxxxxxxx
diff --git a/tests_and_examples/install.tst/xx2bpth2.v b/tests_and_examples/install.tst/xx2bpth2.v
new file mode 100644
index 0000000..f010f41
--- /dev/null
+++ b/tests_and_examples/install.tst/xx2bpth2.v
@@ -0,0 +1,87 @@
+module yy;
+parameter
+	in_width = 10,
+	patterns = 8,
+	out_width = 20,
+	step = 20,
+	mon_flag = 1;
+
+med1 intop(to1, to2, to3, to4, to5, to6, to7, to8, to9, to10,
+ to11, to12, to13, to14, to15, to16, to17, to18, to19, to20,
+ ti1, ti2, ti3, ti4, ti5, ti6, ti7, ti8, ti9, ti10);
+
+ reg [1:in_width] in, in_mem[1:patterns];
+ integer index;
+
+ assign { ti1, ti2, ti3, ti4, ti5, ti6, ti7, ti8, ti9, ti10 }
+  = $getpattern(in_mem[index]);
+
+ initial
+  begin
+   $readmemb("mem.dat", in_mem, 1, patterns);
+   $monitor($stime,, "input %b output %b and %b", in_mem[index], 
+    { to1, to2, to3, to4, to5, to6, to7, to8, to9, to10 }, 
+    { to11, to12, to13, to14, to15, to16, to17, to18, to19, to20 });
+   // $showvars;
+   // $setevtrace;
+   // $monitoroff;
+   // $list(yy);
+
+  for (index = 1; index <= patterns; index = index + 1)
+    fork
+     // #(step/2) if (mon_flag) $monitor;
+     #(step/2)
+      if (mon_flag)
+       $strobe($stime,, "-->read: %h same: %h invert: %h",
+       in_mem[index],
+        { to1, to2, to3, to4, to5, to6, to7, to8, to9, to10 },
+	{ to11, to12, to13, to14, to15, to16, to17, to18, to19, to20});
+     #step;
+    join
+  end
+endmodule 
+
+module med1(mo1, mo2, mo3, mo4, mo5, mo6, mo7, mo8, mo9, mo10,
+ mo11, mo12, mo13, mo14, mo15, mo16, mo17, mo18, mo19, mo20,
+ mi1, mi2, mi3, mi4, mi5, mi6, mi7, mi8, mi9, mi10);
+
+ output mo1, mo2, mo3, mo4, mo5, mo6, mo7, mo8, mo9, mo10,
+  mo11, mo12, mo13, mo14, mo15, mo16, mo17, mo18, mo19, mo20;
+ input mi1, mi2, mi3, mi4, mi5, mi6, mi7, mi8, mi9, mi10;
+
+ bot
+  inmedi1(mo1, mi1), inmedi2(mo2, mi2), inmedi3(mo3, mi3), inmedi4(mo4, mi4),
+  inmedi5(mo5, mi5),  inmedi6(mo6, mi6), inmedi7(mo7, mi7), inmedi8(mo8, mi8),
+  inmedi9(mo9, mi9), inmedi10(mo10, mi10);
+ bot2
+  inmed11(mo11, mi1), inmed12(mo12, mi2),
+  inmed13(mo13, mi3), inmed14(mo14, mi4), inmed15(mo15, mi5),
+  inmed16(mo16, mi6), inmed17(mo17, mi7), inmed18(mo18, mi8),
+  inmed19(mo19, mi9), inmed20(mo20, mi10);
+endmodule
+
+// identity through some nots
+module bot(o, i);
+ output o;
+ input i;
+ pth_not g0(o, w1), g1(w1, i), g2(w2, w3), g3(w3, i);
+endmodule
+
+module pth_not(o, i);
+ output o;
+ input i;
+
+ not g1(o, i);
+ specify
+  specparam rise = 5, fall = 3;
+  (i *> o) = (rise,fall); 
+ endspecify
+endmodule
+
+// inverter through some nots
+module bot2(o, i);
+ output o;
+ input i;
+
+ pth_not g0(o, w1), g1(w1, w2), g2(w2, i);
+endmodule
diff --git a/tests_and_examples/install.tst/xxdel.tst b/tests_and_examples/install.tst/xxdel.tst
new file mode 100644
index 0000000..e69de29
diff --git a/tests_and_examples/v2001/README b/tests_and_examples/v2001/README
new file mode 100644
index 0000000..1ccaeb8
--- /dev/null
+++ b/tests_and_examples/v2001/README
@@ -0,0 +1,25 @@
+
+               RUNNING THE GPL CVER V2001 TEST
+
+First run Cver without any arguments to make sure Cver binary is
+correctly installed.  Type "../../bin/cver" or if you have installed cver
+somewhere on your shell PATH just type "cver".  The first line output
+Cver version number must match the version of your release directory.  If
+version number does not match, you probably have your shell PATH environment
+variable set to execute an old version.
+
+If you are running on Unix/Linux based platforms, run the shell command
+script by typing:
+
+inst_tst.sh 
+
+Correct installation is indicated by the following message with no diff
+command output lines before the message:
+
+>>>> V2001 test completed (this should be only printed message).
+
+-------------------------------------------------------------------------
+ 
+ For config examples please see the config directory README.
+
+
diff --git a/tests_and_examples/v2001/arithtest.plg b/tests_and_examples/v2001/arithtest.plg
new file mode 100644
index 0000000..0ef4852
--- /dev/null
+++ b/tests_and_examples/v2001/arithtest.plg
@@ -0,0 +1,5 @@
+101010001
+-175
+111111001
+  -7
+  -7
diff --git a/tests_and_examples/v2001/arithtest.v b/tests_and_examples/v2001/arithtest.v
new file mode 100644
index 0000000..c1748c4
--- /dev/null
+++ b/tests_and_examples/v2001/arithtest.v
@@ -0,0 +1,25 @@
+module test;
+ reg signed [8:0] a;
+ reg signed [8:0] b;
+ reg signed [8:0] result;
+
+ reg [7:0] c;
+ reg [7:0] d;
+ 
+ initial begin
+  a = -35; 
+  b = 5;
+  c = 35;
+  d = 5;
+
+  result = a / b;
+ 
+  $display("%b", a * b);
+  $display("%d", a * b);
+  $display("%b", a / b);
+  $display("%d", a / b);
+  $display("%d", result);
+ end
+
+endmodule
+
diff --git a/tests_and_examples/v2001/comparetest.plg b/tests_and_examples/v2001/comparetest.plg
new file mode 100644
index 0000000..222f849
--- /dev/null
+++ b/tests_and_examples/v2001/comparetest.plg
@@ -0,0 +1,6 @@
+  -2 >  -50
+ -50 <   -2
+  -2 >=  -50
+ -50 <=   -2
+  -2 >  50
+ 50 <   -2
diff --git a/tests_and_examples/v2001/comparetest.v b/tests_and_examples/v2001/comparetest.v
new file mode 100644
index 0000000..e042ae1
--- /dev/null
+++ b/tests_and_examples/v2001/comparetest.v
@@ -0,0 +1,44 @@
+module test;
+ reg signed [7:0] a;
+ reg signed [7:0] b;
+ reg signed [7:0] result;
+
+ reg [7:0] c;
+ reg [7:0] d;
+ 
+ initial begin
+  a = -2; 
+  b = -50;
+
+  c = 50;
+
+  if (a < b) 
+   $display("%d < %d", a, b);
+  if (a > b) 
+   $display("%d > %d", a, b);
+  if (b < a) 
+   $display("%d < %d", b, a);
+  if (b > a) 
+   $display("%d > %d", b, a);
+ 
+  if (a <= b) 
+   $display("%d <= %d", a, b);
+  if (a >= b) 
+   $display("%d >= %d", a, b);
+  if (b <= a) 
+   $display("%d <= %d", b, a);
+  if (b >= a) 
+   $display("%d >= %d", b, a);
+ 
+  if (a < c) 
+   $display("%d < %d", a, c);
+  if (a > c) 
+   $display("%d > %d", a, c);
+  if (c < a) 
+   $display("%d < %d", c, a);
+  if (c > a) 
+   $display("%d > %d", c, a);
+ end
+
+endmodule
+
diff --git a/tests_and_examples/v2001/config/README b/tests_and_examples/v2001/config/README
new file mode 100644
index 0000000..cbeab94
--- /dev/null
+++ b/tests_and_examples/v2001/config/README
@@ -0,0 +1,33 @@
+
+               RUNNING THE GPL CVER CONFIG V2001 TEST
+
+First run Cver without any arguments to make sure Cver binary is
+correctly installed.  Type "../../../bin/cver" or if you have installed cver
+somewhere on your shell PATH just type "cver".  The first line output
+Cver version number must match the version of your release directory.  If
+version number does not match, you probably have your shell PATH environment
+variable set to execute an old version.
+
+If you are running on Unix/Linux based platforms, run the shell command
+script by typing:
+
+config_tst.sh 
+
+Correct installation is indicated by the following message with no diff
+command output lines before the message:
+
+>>>> Config test completed (this should be only printed message).
+
+-------------------------------------------------------------------------
+
+To run the config files:
+
+ cver +config [config.file]
+
+to use config1.map
+
+ cver +config config1.map
+
+with library verbose option
+
+ cver +config config1.map +libverbose
diff --git a/tests_and_examples/v2001/config/config1.map b/tests_and_examples/v2001/config/config1.map
new file mode 100644
index 0000000..f7590d2
--- /dev/null
+++ b/tests_and_examples/v2001/config/config1.map
@@ -0,0 +1,7 @@
+library top test.v;
+library foo foo/foo.v;
+
+config cfg;
+ design top.test;
+ default liblist foo;
+endconfig
diff --git a/tests_and_examples/v2001/config/config1.plg b/tests_and_examples/v2001/config/config1.plg
new file mode 100644
index 0000000..dd81d8f
--- /dev/null
+++ b/tests_and_examples/v2001/config/config1.plg
@@ -0,0 +1,4 @@
+top.v top.test
+foo/foo.v foo.foo
+foo/foo.v foo.foo
+top.v adder top.adder
diff --git a/tests_and_examples/v2001/config/config2.map b/tests_and_examples/v2001/config/config2.map
new file mode 100644
index 0000000..88f929d
--- /dev/null
+++ b/tests_and_examples/v2001/config/config2.map
@@ -0,0 +1,9 @@
+library top test.v;
+library foolib foo/fo?.v;
+library lib lib/*.v;
+
+config cfg;
+ design top.test;
+ default liblist foolib lib;
+ instance test.f1 use foolib.foo;
+endconfig
diff --git a/tests_and_examples/v2001/config/config2.plg b/tests_and_examples/v2001/config/config2.plg
new file mode 100644
index 0000000..b854830
--- /dev/null
+++ b/tests_and_examples/v2001/config/config2.plg
@@ -0,0 +1,4 @@
+top.v top.test
+foo/foo.v foolib.foo
+foo/foo.v foolib.foo
+top.v adder top.adder
diff --git a/tests_and_examples/v2001/config/config3.map b/tests_and_examples/v2001/config/config3.map
new file mode 100644
index 0000000..261d03c
--- /dev/null
+++ b/tests_and_examples/v2001/config/config3.map
@@ -0,0 +1,10 @@
+library top test.v;
+library foolib foo/fo?.v;
+library lib lib/*.v;
+
+config cfg;
+ design top.test;
+ default liblist foolib lib;
+ instance test.f1 use foolib.foo;
+ instance test.f2 use lib.bar;
+endconfig
diff --git a/tests_and_examples/v2001/config/config3.plg b/tests_and_examples/v2001/config/config3.plg
new file mode 100644
index 0000000..f2f5ff9
--- /dev/null
+++ b/tests_and_examples/v2001/config/config3.plg
@@ -0,0 +1,4 @@
+top.v top.test
+foo/foo.v foolib.foo
+lib/bar.v lib.bar
+top.v adder top.adder
diff --git a/tests_and_examples/v2001/config/config4.map b/tests_and_examples/v2001/config/config4.map
new file mode 100644
index 0000000..7222f8a
--- /dev/null
+++ b/tests_and_examples/v2001/config/config4.map
@@ -0,0 +1,9 @@
+library top test.v;
+library foolib foo/fo?.v;
+library lib lib/*.v;
+
+config cfg;
+ design top.test;
+ default liblist foolib lib;
+ cell foo use lib.bar;
+endconfig
diff --git a/tests_and_examples/v2001/config/config4.plg b/tests_and_examples/v2001/config/config4.plg
new file mode 100644
index 0000000..657ba07
--- /dev/null
+++ b/tests_and_examples/v2001/config/config4.plg
@@ -0,0 +1,4 @@
+top.v top.test
+lib/bar.v lib.bar
+lib/bar.v lib.bar
+top.v adder top.adder
diff --git a/tests_and_examples/v2001/config/config5.map b/tests_and_examples/v2001/config/config5.map
new file mode 100644
index 0000000..3aaf2cc
--- /dev/null
+++ b/tests_and_examples/v2001/config/config5.map
@@ -0,0 +1,9 @@
+library top test.v;
+library foolib foo/fo?.v;
+library lib lib/*.v;
+
+config cfg;
+ design top.test;
+ default liblist foolib lib;
+ instance test.f1 liblist lib foolib;
+endconfig
diff --git a/tests_and_examples/v2001/config/config5.plg b/tests_and_examples/v2001/config/config5.plg
new file mode 100644
index 0000000..b854830
--- /dev/null
+++ b/tests_and_examples/v2001/config/config5.plg
@@ -0,0 +1,4 @@
+top.v top.test
+foo/foo.v foolib.foo
+foo/foo.v foolib.foo
+top.v adder top.adder
diff --git a/tests_and_examples/v2001/config/config_tst.sh b/tests_and_examples/v2001/config/config_tst.sh
new file mode 100755
index 0000000..a46ab46
--- /dev/null
+++ b/tests_and_examples/v2001/config/config_tst.sh
@@ -0,0 +1,34 @@
+#!/bin/sh 
+# install test procedures
+
+CVER="../../../bin/cver -q +config" 
+
+if test ! -f ../../../bin/cver 
+then
+  echo "ERROR - there is no cver in ../../../bin/"
+  echo "Must make in src/ directory" 
+  exit;
+fi
+
+$CVER config1.map >/dev/null
+../../install.tst/rmlic.pl
+diff verilog.log config1.plg
+
+$CVER config2.map >/dev/null
+../../install.tst/rmlic.pl
+diff verilog.log config2.plg
+
+$CVER config3.map >/dev/null
+../../install.tst/rmlic.pl
+diff verilog.log config3.plg
+
+$CVER config4.map >/dev/null
+../../install.tst/rmlic.pl
+diff verilog.log config4.plg
+
+$CVER config5.map >/dev/null
+../../install.tst/rmlic.pl
+diff verilog.log config5.plg
+
+echo ">>>> v2001 test completed (this should be only message printed)."
+echo " "
diff --git a/tests_and_examples/v2001/config/foo/foo.v b/tests_and_examples/v2001/config/foo/foo.v
new file mode 100644
index 0000000..24de10e
--- /dev/null
+++ b/tests_and_examples/v2001/config/foo/foo.v
@@ -0,0 +1,5 @@
+module foo;
+
+ initial $display("foo/foo.v %l");
+
+endmodule
diff --git a/tests_and_examples/v2001/config/foo/foo1.v b/tests_and_examples/v2001/config/foo/foo1.v
new file mode 100644
index 0000000..6459e88
--- /dev/null
+++ b/tests_and_examples/v2001/config/foo/foo1.v
@@ -0,0 +1,5 @@
+module foo1;
+
+ initial $display("foo/foo1.v %l");
+
+endmodule
diff --git a/tests_and_examples/v2001/config/foo/foo2.v b/tests_and_examples/v2001/config/foo/foo2.v
new file mode 100644
index 0000000..55bb2eb
--- /dev/null
+++ b/tests_and_examples/v2001/config/foo/foo2.v
@@ -0,0 +1,5 @@
+module foo2;
+
+ initial $display("foo/foo2.v %l");
+
+endmodule
diff --git a/tests_and_examples/v2001/config/lib/adder.v b/tests_and_examples/v2001/config/lib/adder.v
new file mode 100644
index 0000000..0f6fa14
--- /dev/null
+++ b/tests_and_examples/v2001/config/lib/adder.v
@@ -0,0 +1,11 @@
+module adder;
+
+ initial $display("lib/adder.v adder %l");
+
+endmodule
+
+module adder2;
+
+ initial $display("lib/adder.v adder2 %l");
+
+endmodule
diff --git a/tests_and_examples/v2001/config/lib/bar.v b/tests_and_examples/v2001/config/lib/bar.v
new file mode 100644
index 0000000..5582bd1
--- /dev/null
+++ b/tests_and_examples/v2001/config/lib/bar.v
@@ -0,0 +1,5 @@
+module bar;
+
+ initial $display("lib/bar.v %l");
+
+endmodule
diff --git a/tests_and_examples/v2001/config/test.v b/tests_and_examples/v2001/config/test.v
new file mode 100644
index 0000000..b203dce
--- /dev/null
+++ b/tests_and_examples/v2001/config/test.v
@@ -0,0 +1,15 @@
+module test;
+ 
+ foo f1();
+ foo f2();
+ adder a1();
+
+ initial $display("top.v %l");   
+
+
+endmodule
+
+
+module adder;
+ initial $display("top.v adder %l");   
+endmodule
diff --git a/tests_and_examples/v2001/config/verilog.log b/tests_and_examples/v2001/config/verilog.log
new file mode 100644
index 0000000..ea19588
--- /dev/null
+++ b/tests_and_examples/v2001/config/verilog.log
@@ -0,0 +1,9 @@
+GPLCVER_1.20a of 06/01/04 (Linux-elf).
+Copyright (c) 1991-2004 Pragmatic C Software Corp.
+  All Rights reserved.  Licensed under the GNU General Public License (GPL).
+  See the 'COPYING' file for details.  NO WARRANTY provided.
+Today is Tue Jun  1 16:03:59 2004.
+** ERROR** [3500] cannot open config map library file config6.map - skipped
+  Unable to begin simulation.
+  There were 1 error(s), 0 warning(s), and 0 inform(s).
+End of GPLCVER_1.20a at Tue Jun  1 16:03:59 2004 (elapsed 0.0 seconds).
diff --git a/tests_and_examples/v2001/dsign.plg b/tests_and_examples/v2001/dsign.plg
new file mode 100644
index 0000000..7bef0e6
--- /dev/null
+++ b/tests_and_examples/v2001/dsign.plg
@@ -0,0 +1,4 @@
+1100  -4 
+
+0001   1 
+
diff --git a/tests_and_examples/v2001/dsign.v b/tests_and_examples/v2001/dsign.v
new file mode 100644
index 0000000..87d0630
--- /dev/null
+++ b/tests_and_examples/v2001/dsign.v
@@ -0,0 +1,12 @@
+module test;
+ reg signed [3:0] reg1;
+ reg signed [3:0] reg2;
+ reg signed [3:0] result;
+ 
+ initial begin 
+     reg1 = -12 / 3; // expression result is -4. regS is a signed register
+     $display("%b %d \n", reg1, reg1); 
+     reg1 = -4'sd12 / 3;// expression result is 1. -4'sd12 is actually 4
+     $display("%b %d \n", reg1, reg1); // should be 1 
+ end
+endmodule
diff --git a/tests_and_examples/v2001/dsignedtest.plg b/tests_and_examples/v2001/dsignedtest.plg
new file mode 100644
index 0000000..3c61074
--- /dev/null
+++ b/tests_and_examples/v2001/dsignedtest.plg
@@ -0,0 +1,2 @@
+a=11111100
+b=11111100 (  -4)
diff --git a/tests_and_examples/v2001/dsignedtest.v b/tests_and_examples/v2001/dsignedtest.v
new file mode 100644
index 0000000..ceae2f5
--- /dev/null
+++ b/tests_and_examples/v2001/dsignedtest.v
@@ -0,0 +1,14 @@
+module top;
+
+ reg [7:0] a;
+ reg signed [7:0] b;
+
+ initial begin
+  a = $unsigned(-4);
+  b = $signed(4'b1100);
+
+  $display("a=%b", a);
+  $display("b=%b (%d)", b, b);
+ end
+
+endmodule
diff --git a/tests_and_examples/v2001/fgets1.plg b/tests_and_examples/v2001/fgets1.plg
new file mode 100644
index 0000000..a16eec1
--- /dev/null
+++ b/tests_and_examples/v2001/fgets1.plg
@@ -0,0 +1,6 @@
+Reading files from Verilog models
+
+This file has been replaced by fileio.htm
+
+break check_veriusertf_table 
+disp __pli_dynlib_hd->dynblst->ret_veriusertf[20]
diff --git a/tests_and_examples/v2001/fgets1.v b/tests_and_examples/v2001/fgets1.v
new file mode 100644
index 0000000..7908420
--- /dev/null
+++ b/tests_and_examples/v2001/fgets1.v
@@ -0,0 +1,34 @@
+/*
+ * fileio test of getc - copy to stdout
+ */
+
+`timescale 1ns / 10 ps
+`define EOF -1
+`define NULL 0
+`define MAX_LINE_LENGTH 1000
+`define STDOUT 32'h8000_0001
+module test1;
+  integer file;
+  reg [3:0] bin;
+  reg [31:0] dec, hex;
+  real real_time;
+  reg [8*`MAX_LINE_LENGTH-1:0] line; /* Line of text read from file */
+  integer r;
+  integer c;
+
+  initial
+     begin : file_block
+      file = $fopen("infil.txt", "r");
+      if (file == `NULL) disable file_block;
+  
+      begin : read_block
+       forever  
+         begin
+          r = $fgets(line, file);
+          if (r == 0) disable read_block;
+          $fwrite(`STDOUT, "%s", line);
+         end
+      end
+      $fclose(file);
+    end
+endmodule // read_pattern
diff --git a/tests_and_examples/v2001/getc1.plg b/tests_and_examples/v2001/getc1.plg
new file mode 100644
index 0000000..a16eec1
--- /dev/null
+++ b/tests_and_examples/v2001/getc1.plg
@@ -0,0 +1,6 @@
+Reading files from Verilog models
+
+This file has been replaced by fileio.htm
+
+break check_veriusertf_table 
+disp __pli_dynlib_hd->dynblst->ret_veriusertf[20]
diff --git a/tests_and_examples/v2001/getc1.v b/tests_and_examples/v2001/getc1.v
new file mode 100644
index 0000000..e6579e0
--- /dev/null
+++ b/tests_and_examples/v2001/getc1.v
@@ -0,0 +1,34 @@
+/*
+ * fileio test of getc - copy to stdout
+ */
+
+`timescale 1ns / 10 ps
+`define EOF -1
+`define NULL 0
+`define MAX_LINE_LENGTH 1000
+`define STDOUT 32'h8000_0001
+module test1;
+  integer file;
+  reg [3:0] bin;
+  reg [31:0] dec, hex;
+  real real_time;
+  reg [8*`MAX_LINE_LENGTH-1:0] line; /* Line of text read from file */
+  integer r;
+  integer c;
+
+  initial
+     begin : file_block
+      file = $fopen("infil.txt", "r");
+      if (file == `NULL) disable file_block;
+  
+      begin : read_block
+       forever  
+         begin
+          c = $fgetc(file);
+          if (c == `EOF) disable read_block;
+          $fwrite(`STDOUT, "%c", c);
+         end
+      end
+      $fclose(file);
+    end
+endmodule // read_pattern
diff --git a/tests_and_examples/v2001/getc2.plg b/tests_and_examples/v2001/getc2.plg
new file mode 100644
index 0000000..741fd51
--- /dev/null
+++ b/tests_and_examples/v2001/getc2.plg
@@ -0,0 +1,6 @@
+Reading files from Verilog models
+
+TThis file has been replaced by fileio.htm
+
+bbreak check_veriusertf_table 
+disp __pli_dynlib_hd->dynblst->ret_veriusertf[20]
diff --git a/tests_and_examples/v2001/getc2.v b/tests_and_examples/v2001/getc2.v
new file mode 100644
index 0000000..6962107
--- /dev/null
+++ b/tests_and_examples/v2001/getc2.v
@@ -0,0 +1,44 @@
+/*
+ * fileio test of getc - copy to stdout
+ */
+
+/*
+ * ungetc test
+ * read and output a file but emit extra new line with ungetc
+ */
+`define EOF -1
+`define NULL 0
+`define MAX_LINE_LENGTH 1000
+`define STDOUT 32'h8000_0001
+module test1;
+  integer file;
+  reg [3:0] bin;
+  reg [31:0] dec, hex;
+  real real_time;
+  reg [8*`MAX_LINE_LENGTH-1:0] line; /* Line of text read from file */
+  integer r;
+  integer c;
+  integer d;
+
+  initial
+     begin : file_block
+      file = $fopen("infil.txt", "r");
+      if (file == `NULL) disable file_block;
+  
+      begin : read_block
+       forever  
+         begin
+          c = $fgetc(file);
+          if (c == `EOF) disable read_block;
+	  d = $fgetc(file);
+          if (d == `EOF) disable read_block;
+          $fwrite(`STDOUT, "%c%c", c, d);
+          if (c == "\n")
+           begin
+            d = $ungetc(d, file);
+           end
+         end
+      end
+      $fclose(file);
+    end
+endmodule // read_pattern
diff --git a/tests_and_examples/v2001/infil.txt b/tests_and_examples/v2001/infil.txt
new file mode 100644
index 0000000..a16eec1
--- /dev/null
+++ b/tests_and_examples/v2001/infil.txt
@@ -0,0 +1,6 @@
+Reading files from Verilog models
+
+This file has been replaced by fileio.htm
+
+break check_veriusertf_table 
+disp __pli_dynlib_hd->dynblst->ret_veriusertf[20]
diff --git a/tests_and_examples/v2001/inst_tst.sh b/tests_and_examples/v2001/inst_tst.sh
new file mode 100755
index 0000000..dddbe8e
--- /dev/null
+++ b/tests_and_examples/v2001/inst_tst.sh
@@ -0,0 +1,49 @@
+#!/bin/sh 
+# install test procedures
+
+CVER="../../bin/cver -q " 
+
+if test ! -f ../../bin/cver 
+then
+  echo "ERROR - there is no cver in ../../bin/"
+  echo "Must make in src/ directory" 
+  exit;
+fi
+
+$CVER arithtest.v >/dev/null
+../install.tst/rmlic.pl
+diff verilog.log arithtest.plg
+
+$CVER comparetest.v >/dev/null
+../install.tst/rmlic.pl
+diff verilog.log comparetest.plg
+
+$CVER dsignedtest.v >/dev/null
+../install.tst/rmlic.pl
+diff verilog.log dsignedtest.plg
+
+$CVER dsign.v >/dev/null
+../install.tst/rmlic.pl
+diff verilog.log dsign.plg
+
+$CVER fgets1.v >flog
+mv flog verilog.log
+../install.tst/rmlic.pl
+diff verilog.log fgets1.plg
+
+$CVER getc1.v >flog
+mv flog verilog.log
+../install.tst/rmlic.pl
+diff verilog.log getc1.plg
+
+$CVER getc2.v >flog
+mv flog verilog.log
+../install.tst/rmlic.pl
+diff verilog.log getc2.plg
+
+$CVER lofptst.v >/dev/null
+../install.tst/rmlic.pl
+diff verilog.log lofptst.plg
+
+echo ">>>> v2001 test completed (this should be only message printed)."
+echo " "
diff --git a/tests_and_examples/v2001/lofptst.plg b/tests_and_examples/v2001/lofptst.plg
new file mode 100644
index 0000000..b25e3da
--- /dev/null
+++ b/tests_and_examples/v2001/lofptst.plg
@@ -0,0 +1 @@
+** WARN** [614] no pending statements or events after initialization - nothing to do
diff --git a/tests_and_examples/v2001/lofptst.v b/tests_and_examples/v2001/lofptst.v
new file mode 100644
index 0000000..c87cbf1
--- /dev/null
+++ b/tests_and_examples/v2001/lofptst.v
@@ -0,0 +1,18 @@
+module test #(parameter integer p1 = 5, parameter p2 = 7,
+ parameter r1 = 7.3) (
+ input [7:0] a,
+ input signed [7:0] b, c, d, // multiple port that share attributes
+ output [7:0] e,
+ output signed [7:0] f,g,
+ output signed [7:0] h) ;
+
+ task my_task(input a, b, inout c, output signed [15:0] d, e);
+  begin
+   c = a;
+   d = f;
+   e= 2*f;
+  end
+ endtask
+
+endmodule
+  
diff --git a/tests_and_examples/v2001/verilog.log b/tests_and_examples/v2001/verilog.log
new file mode 100644
index 0000000..59e28c6
--- /dev/null
+++ b/tests_and_examples/v2001/verilog.log
@@ -0,0 +1,14 @@
+GPLCVER_1.20a of 06/01/04 (Linux-elf).
+Copyright (c) 1991-2004 Pragmatic C Software Corp.
+  All Rights reserved.  Licensed under the GNU General Public License (GPL).
+  See the 'COPYING' file for details.  NO WARRANTY provided.
+Today is Tue Jun  1 16:28:09 2004.
+Compiling source file "lofptst.v"
+Highest level modules:
+test
+
+** WARN** [614] no pending statements or events after initialization - nothing to do
+0 simulation events and 0 declarative immediate assigns processed.
+  Times (in sec.):  Translate 0.0, load/optimize 0.1, simulation 0.1.
+  There were 0 error(s), 1 warning(s), and 29 inform(s).
+End of GPLCVER_1.20a at Tue Jun  1 16:28:09 2004 (elapsed 0.0 seconds).
diff --git a/vcddiff.dir/Changelog b/vcddiff.dir/Changelog
new file mode 100644
index 0000000..b3f5c7e
--- /dev/null
+++ b/vcddiff.dir/Changelog
@@ -0,0 +1,23 @@
+vcddiff.04a
+===========
+
+   *** SEE THE VCDDIFF README FOR MORE INFORMATION OF NEW BEVAHIOR ***
+
+   - All values that didn't have a previous value are initialized, and 
+     seen in edges as '?'.
+
+   - Added '-wrap' option.  This option when used with edge printing, wraps
+     the line after every 11 edges.  Therefore 11 edges are printed per line
+     followed by a '\', to indicate a new line.  An empty line indicates
+     the start of the second signal value on the next line.  Default
+     no longer wraps
+
+   - Added the ranges '[a:b]' to the signal name
+
+   - If one value is narrower than the other they are right aligned at low 
+     bit side.
+  
+ Bugs
+  -  add_signal(), filled one too many bits in intialization
+  -  add_edges(), last bit print was wrong 
+  -  get_time_diffs, need to rewind() prior to seeking
diff --git a/vcddiff.dir/README.vcddiff b/vcddiff.dir/README.vcddiff
new file mode 100644
index 0000000..2cb25a2
--- /dev/null
+++ b/vcddiff.dir/README.vcddiff
@@ -0,0 +1,108 @@
+
+                INSTRUCTIONS FOR RUNNING VCDDIFF
+
+
+Vcddiff is a program similar to the Unix diff command for Verilog VCD files.
+It produces differences of two VCD files passed to it.  It has the ability
+to map different identifiers to their respective hierarchical names.
+
+Producing VCD files using Cver:
+
+When $dumpvars (see LRM for more VCD information) is used in a Verilog source 
+file ran with Cver, it will produce a VCD file with the default name 
+"verilog.dump".
+
+
+To run type:
+  vcddiff [options] file1 file2
+
+Options
+=======
+ --state 
+ -s        
+         Will print out the state values instead of the default edge values.  
+         Prints just the current values without edges.         
+ --wrap  
+ -w
+         Wraps the edge print message, 11 edges per line.  This
+         option can only be used when the default edge is used, 
+         may not be used with the --state option.
+ --help 
+ -h     
+         Prints the help message, explanation of current options 
+
+========
+
+If a particular signal is defined in one and not the other VCD file a warning 
+message is omitted, and the signal is ignored.  Signals are also ignored if 
+they have different variable types ('reg' vs 'real', etc.) or sizes.
+
+If a signal matches at the current time no message is omitted.  Otherwise if 
+the files simply have different states for a signal at a given time a  
+message of the form is printed:
+
+VARNAME (IDENTIFIER) differs at time TIME 
+	(0-)    /* edge value of file one */
+	(01)    /* edge value of file two */
+
+Sample output:
+
+top.var (!) differs at time 30
+	(0-)
+	(01)
+
+Where 'top.var' is the signal name, and '!' is the identifier.  If the second
+file had a different identifier say '$' (still for top.var) the output 
+would be:  
+
+top.var (!, $) differs at time 30
+	(0-)
+	(01)
+
+This shows that at time 30 reg top.var had different values. The output is an 
+example of the edge print value, which is the default option.  The (0-) 
+indicates no edge change, in other words, its previous value was 0 as well, 
+therefore '-' indicates no change in the first file.  The second value is the 
+second file's edge change value. It went from 0 to 1.  If the value was 
+unknown or uninitialized a '?' is displayed. For example if time 30 was the 
+first value change for top.var in file two (?1) would be printed.  See the
+Verilog LRM section 8 on user defined primitives for more information on
+edge values.  
+
+If the state option ('-s' or '--state' ) was selected the output would be:
+
+top.var (!) differs at time 30
+	0
+	1
+
+Since at time 30 the first file has a 0 value for top.var and the second file
+has a 1 value.  Both style outputs are the same for vectors.  Edges are split 
+per bit, and state values are printed as a continuous string.  If one value is 
+narrower than the other they are right aligned at low bit side.
+
+If a signal is defined at a time in one file and not the other a search is 
+performed to locate the next occurrence. Where the arrows in the message
+are used to distinguish which file the mismatched occurred in.  
+For instance:
+
+< top.var (!) at time 5 next occurrence at time 10
+< #5 	(-1)
+< #10 	(10)
+
+This message indicates that at time 5, an extra value change of top.var 
+occurred in the second file, so a search was performed on the first file, where 
+the next change was found at time 10. The '<' indicates which file the search 
+was performed on, in this case the first file ('>' for a search in file two).   
+The program will then start back at time 5 for the changes on the next 
+identifier. If both files also differ at time 10, a same time difference 
+message is printed as well. 
+
+The wrap option ('-w' or '--wrap') is used to help prevent clutter of large
+vector values when printing edges by displaying only 11 edges per line, 
+indicated by a '\' at the end of each line.  The file edges are separated by
+a blank line to distinguish their respective values.  
+
+See examples.vcddiff for example dump files to run through vcddiff.
+
+For bug reports or suggestions email: avanvick at pragmatic-c.com.
+Latest release can be downloaded at: www.pragmatic-c.com/download.htm
diff --git a/vcddiff.dir/examples.vcddiff/README b/vcddiff.dir/examples.vcddiff/README
new file mode 100644
index 0000000..28e1e0a
--- /dev/null
+++ b/vcddiff.dir/examples.vcddiff/README
@@ -0,0 +1,24 @@
+
+This directory contains some simple examples to demonstrate the use
+of vcddiff.  To run the tests, execute the shell script: vcddiff_test.sh.
+This will run four examples using the dump files provided and print out the
+differences.  
+
+To run vcddiff just give two dump files to compare.  This script runs
+the following four tests.  The '//' comment lines below give the expected
+output for each of the tests.
+
+$  vcddiff example.dump example.dump   
+// no differences since it is the same file
+
+$   vcddiff example.dump example_map_nochg.dump   
+// no differences since it is the same file, except for different identifiers
+                                        
+$   vcddiff example.dump example2.dump   
+// will print the differences between the files 
+
+$   vcddiff --state example.dump example2.dump   
+// will print the differences between the files in the state form, since the
+   --state command is given 
+
+For more information see README.vcddiff in the top level directory.
diff --git a/vcddiff.dir/examples.vcddiff/example.dump b/vcddiff.dir/examples.vcddiff/example.dump
new file mode 100644
index 0000000..768d199
--- /dev/null
+++ b/vcddiff.dir/examples.vcddiff/example.dump
@@ -0,0 +1,69 @@
+$date June 26, 1989 10:05:41 
+$end
+$version VERILOG-SIMULATOR 1.0a 
+$end
+$timescale  1 ns 
+$end
+$scope module top $end 
+$scope module m1  $end 
+$var trireg 1 *@ net1 $end
+$var trireg 1 *# net2 $end
+$var trireg 1 *$ net3 $end
+$upscope $end 
+$scope task t1 $end 
+$var reg 32 (k accumulator[31:0] $end
+$var integer 32 {2 index  $end
+$upscope $end 
+$upscope $end 
+$enddefinitions $end
+$comment 
+  Note: $dumpvars was executed at time '#500'. 
+        All initial values are dumped at this time.
+$end
+
+
+x*@
+x*#
+x*$
+bx (k
+bx {2
+$end
+#505 
+0*@
+1*#
+1*$ 
+b10zx1110x11100 (k 
+b1111000101z01x {2
+#510 
+0*$
+#520 
+1*$
+#530 
+0*$ 
+bz (k
+#535 
+$dumpall
+   0*@   1*#   0*$ 
+bz (k
+b1111000101z01
+$end
+#540 
+1*$
+#1000
+$dumpoff 
+x*@ 
+x*# 
+x*$ 
+bx (k 
+bx {2 
+$end
+#2000
+$dumpon 
+z*@ 
+1*# 
+0*$ 
+b0 (k 
+bx {2 
+$end
+#2010
+1*$
diff --git a/vcddiff.dir/examples.vcddiff/example2.dump b/vcddiff.dir/examples.vcddiff/example2.dump
new file mode 100644
index 0000000..9a880a7
--- /dev/null
+++ b/vcddiff.dir/examples.vcddiff/example2.dump
@@ -0,0 +1,68 @@
+$date June 26, 1989 10:05:41 
+$end
+$version VERILOG-SIMULATOR 1.0a 
+$end
+$timescale  1 ns 
+$end
+$scope module top $end 
+$scope module m1  $end 
+$var trireg 1 *@ net1 $end
+$var trireg 1 *# net2 $end
+$var trireg 1 *$ net3 $end
+$upscope $end 
+$scope task t1 $end 
+$var reg 32 (k accumulator[31:0] $end
+$var integer 32 {2 index  $end
+$upscope $end 
+$upscope $end 
+$enddefinitions $end
+$comment 
+  Note: $dumpvars was executed at time '#500'. 
+        All initial values are dumped at this time.
+$end
+
+
+x*@
+x*#
+x*$
+bx (k
+bx {2
+$end
+#505 
+0*@
+1*#
+1*$ 
+b10zx0110x11000 (k 
+b1111000101z01x {2
+#510 
+#520 
+1*$
+#530 
+0*$ 
+bz (k
+#535 
+$dumpall
+   0*@   1*#   0*$ 
+bz (k
+b1111000101z01
+$end
+#540 
+1*$
+#1000
+$dumpoff 
+x*@ 
+x*# 
+x*$ 
+bx (k 
+bx {2 
+$end
+#2000
+$dumpon 
+z*@ 
+1*# 
+0*$ 
+b0 (k 
+bx {2 
+$end
+#2010
+1*$
diff --git a/vcddiff.dir/examples.vcddiff/example_map_nochg.dump b/vcddiff.dir/examples.vcddiff/example_map_nochg.dump
new file mode 100644
index 0000000..6c60b00
--- /dev/null
+++ b/vcddiff.dir/examples.vcddiff/example_map_nochg.dump
@@ -0,0 +1,69 @@
+$date June 26, 1989 10:05:41 
+$end
+$version VERILOG-SIMULATOR 1.0a 
+$end
+$timescale  1 ns 
+$end
+$scope module top $end 
+$scope module m1  $end 
+$var trireg 1 aa net1 $end
+$var trireg 1 bb net2 $end
+$var trireg 1 cc net3 $end
+$upscope $end 
+$scope task t1 $end 
+$var reg 32 ee accumulator[31:0] $end
+$var integer 32 ff index  $end
+$upscope $end 
+$upscope $end 
+$enddefinitions $end
+$comment 
+  Note: $dumpvars was executed at time '#500'. 
+        All initial values are dumped at this time.
+$end
+
+
+xaa
+xbb
+xcc
+bx ee
+bx ff
+$end
+#505 
+0aa
+1bb
+1cc 
+b10zx1110x11100 ee 
+b1111000101z01x ff
+#510 
+0cc
+#520 
+1cc
+#530 
+0cc 
+bz ee
+#535 
+$dumpall
+   0aa   1bb   0cc 
+bz ee
+b1111000101z01
+$end
+#540 
+1cc
+#1000
+$dumpoff 
+xaa 
+xbb 
+xcc 
+bx ee 
+bx ff 
+$end
+#2000
+$dumpon 
+zaa 
+1bb 
+0cc 
+b0 ee 
+bx ff 
+$end
+#2010
+1cc
diff --git a/vcddiff.dir/examples.vcddiff/vcddiff_test.sh b/vcddiff.dir/examples.vcddiff/vcddiff_test.sh
new file mode 100755
index 0000000..0d0a490
--- /dev/null
+++ b/vcddiff.dir/examples.vcddiff/vcddiff_test.sh
@@ -0,0 +1,28 @@
+#same files no differences 
+VCDDIFF=../../bin/vcddiff
+if test ! -f $VCDDIFF
+then
+  echo "There is no vcddiff in ../../bin"
+  echo "Must be made in ../src" 
+  exit;
+fi
+echo "============= VCDDIFF SAME FILES ===================="
+$VCDDIFF example.dump example.dump 
+echo "============== COMPLETED Same file test completed ==========="
+
+#same files no differences, just different identifiers 
+echo "============= VCDDIFF MAPPING FILE ===================="
+$VCDDIFF example.dump example_map_nochg.dump 
+echo "============== COMPLETED mapping file =============="
+
+#print difference between files 
+echo "============= VCDDIFF DIFFERENT FILES ===================="
+$VCDDIFF example.dump example2.dump
+echo "============== COMPLETED different files ==========="
+
+#print difference between files 
+echo "============= VCDDIFF DIFFERENT (STATE) FILES ===================="
+$VCDDIFF --state example.dump example2.dump
+echo "============== COMPLETED (STATE) different files ==========="
+echo ""
+echo "sample runs/output have been displayed"
diff --git a/vcddiff.dir/src/INSTALL b/vcddiff.dir/src/INSTALL
new file mode 100644
index 0000000..07ae8a7
--- /dev/null
+++ b/vcddiff.dir/src/INSTALL
@@ -0,0 +1,6 @@
+To install just typing 'make -f makefile.youros' should work on most systems, since it has only one source file and header file, getting it to compile 
+shouldn't be a problem. Where 'youros' is lnx, sparc, or osx, depending 
+on your OS.  
+
+The executable is placed in the bin directory in the main Cver level. 
+See the README.vcd file one level up for more  information on vcddiff.
diff --git a/vcddiff.dir/src/README b/vcddiff.dir/src/README
new file mode 100644
index 0000000..2cb25a2
--- /dev/null
+++ b/vcddiff.dir/src/README
@@ -0,0 +1,108 @@
+
+                INSTRUCTIONS FOR RUNNING VCDDIFF
+
+
+Vcddiff is a program similar to the Unix diff command for Verilog VCD files.
+It produces differences of two VCD files passed to it.  It has the ability
+to map different identifiers to their respective hierarchical names.
+
+Producing VCD files using Cver:
+
+When $dumpvars (see LRM for more VCD information) is used in a Verilog source 
+file ran with Cver, it will produce a VCD file with the default name 
+"verilog.dump".
+
+
+To run type:
+  vcddiff [options] file1 file2
+
+Options
+=======
+ --state 
+ -s        
+         Will print out the state values instead of the default edge values.  
+         Prints just the current values without edges.         
+ --wrap  
+ -w
+         Wraps the edge print message, 11 edges per line.  This
+         option can only be used when the default edge is used, 
+         may not be used with the --state option.
+ --help 
+ -h     
+         Prints the help message, explanation of current options 
+
+========
+
+If a particular signal is defined in one and not the other VCD file a warning 
+message is omitted, and the signal is ignored.  Signals are also ignored if 
+they have different variable types ('reg' vs 'real', etc.) or sizes.
+
+If a signal matches at the current time no message is omitted.  Otherwise if 
+the files simply have different states for a signal at a given time a  
+message of the form is printed:
+
+VARNAME (IDENTIFIER) differs at time TIME 
+	(0-)    /* edge value of file one */
+	(01)    /* edge value of file two */
+
+Sample output:
+
+top.var (!) differs at time 30
+	(0-)
+	(01)
+
+Where 'top.var' is the signal name, and '!' is the identifier.  If the second
+file had a different identifier say '$' (still for top.var) the output 
+would be:  
+
+top.var (!, $) differs at time 30
+	(0-)
+	(01)
+
+This shows that at time 30 reg top.var had different values. The output is an 
+example of the edge print value, which is the default option.  The (0-) 
+indicates no edge change, in other words, its previous value was 0 as well, 
+therefore '-' indicates no change in the first file.  The second value is the 
+second file's edge change value. It went from 0 to 1.  If the value was 
+unknown or uninitialized a '?' is displayed. For example if time 30 was the 
+first value change for top.var in file two (?1) would be printed.  See the
+Verilog LRM section 8 on user defined primitives for more information on
+edge values.  
+
+If the state option ('-s' or '--state' ) was selected the output would be:
+
+top.var (!) differs at time 30
+	0
+	1
+
+Since at time 30 the first file has a 0 value for top.var and the second file
+has a 1 value.  Both style outputs are the same for vectors.  Edges are split 
+per bit, and state values are printed as a continuous string.  If one value is 
+narrower than the other they are right aligned at low bit side.
+
+If a signal is defined at a time in one file and not the other a search is 
+performed to locate the next occurrence. Where the arrows in the message
+are used to distinguish which file the mismatched occurred in.  
+For instance:
+
+< top.var (!) at time 5 next occurrence at time 10
+< #5 	(-1)
+< #10 	(10)
+
+This message indicates that at time 5, an extra value change of top.var 
+occurred in the second file, so a search was performed on the first file, where 
+the next change was found at time 10. The '<' indicates which file the search 
+was performed on, in this case the first file ('>' for a search in file two).   
+The program will then start back at time 5 for the changes on the next 
+identifier. If both files also differ at time 10, a same time difference 
+message is printed as well. 
+
+The wrap option ('-w' or '--wrap') is used to help prevent clutter of large
+vector values when printing edges by displaying only 11 edges per line, 
+indicated by a '\' at the end of each line.  The file edges are separated by
+a blank line to distinguish their respective values.  
+
+See examples.vcddiff for example dump files to run through vcddiff.
+
+For bug reports or suggestions email: avanvick at pragmatic-c.com.
+Latest release can be downloaded at: www.pragmatic-c.com/download.htm
diff --git a/vcddiff.dir/src/makefile.lnx b/vcddiff.dir/src/makefile.lnx
new file mode 100644
index 0000000..7a66409
--- /dev/null
+++ b/vcddiff.dir/src/makefile.lnx
@@ -0,0 +1,17 @@
+ARCHFLGS= -march=pentiumpro
+OPTFLGS=-fno-strength-reduce -fomit-frame-pointer
+CFLAGS= $(ARCHFLGS) -pipe $(OPTFLGS) -O2 
+#CFLAGS= $(ARCHFLGS) -pipe $(OPTFLGS) -g -Wall
+#CFLAGS= -pg -g -Wall
+#CFLAGS= -g -Wall
+
+CC=gcc
+LIBS=-lm
+
+vcddiff:	vcddiff.o 
+	$(CC) $(CFLAGS) $(OPTFLGS) vcddiff.o $(LIBS) -o vcddiff 
+	rm vcddiff.o
+	mv vcddiff ../../bin
+
+vcddiff.o:	vcddiff.c vcddiff.h
+	$(CC) $(CFLAGS) -c vcddiff.c
diff --git a/vcddiff.dir/src/makefile.osx b/vcddiff.dir/src/makefile.osx
new file mode 100644
index 0000000..9f80805
--- /dev/null
+++ b/vcddiff.dir/src/makefile.osx
@@ -0,0 +1,17 @@
+ARCHFLGS= -mcpu=powerpc
+OPTFLGS=-fno-strength-reduce -fomit-frame-pointer
+CFLAGS= $(ARCHFLGS) -pipe $(OPTFLGS) -O2 
+#CFLAGS= $(ARCHFLGS) -pipe $(OPTFLGS) -g -Wall
+#CFLAGS= -pg -g -Wall
+#CFLAGS= -g -Wall
+
+CC=cc
+LIBS=-lm
+
+vcddiff:	vcddiff.o 
+	$(CC) $(CFLAGS) $(OPTFLGS) vcddiff.o $(LIBS) -o vcddiff 
+	rm vcddiff.o
+	mv vcddiff ../../bin
+
+vcddiff.o:	vcddiff.c vcddiff.h
+	$(CC) $(CFLAGS) -c vcddiff.c
diff --git a/vcddiff.dir/src/makefile.sparc b/vcddiff.dir/src/makefile.sparc
new file mode 100644
index 0000000..50479c7
--- /dev/null
+++ b/vcddiff.dir/src/makefile.sparc
@@ -0,0 +1,17 @@
+ARCHFLGS= -mcpu=v8
+OPTFLGS=-fno-strength-reduce -fomit-frame-pointer
+CFLAGS= $(ARCHFLGS) -pipe $(OPTFLGS) -O2 
+#CFLAGS= $(ARCHFLGS) -pipe $(OPTFLGS) -g -Wall
+#CFLAGS= -pg -g -Wall
+#CFLAGS= -g -Wall
+
+CC=gcc
+LIBS=-lm
+
+vcddiff:	vcddiff.o 
+	$(CC) $(CFLAGS) $(OPTFLGS) vcddiff.o $(LIBS) -o vcddiff 
+	rm vcddiff.o
+	mv vcddiff ../../bin
+
+vcddiff.o:	vcddiff.c vcddiff.h
+	$(CC) $(CFLAGS) -c vcddiff.c
diff --git a/vcddiff.dir/src/vcddiff.c b/vcddiff.dir/src/vcddiff.c
new file mode 100644
index 0000000..561c8c5
--- /dev/null
+++ b/vcddiff.dir/src/vcddiff.c
@@ -0,0 +1,1543 @@
+/* Copyright (c) 1991-2004 Pragmatic C Software Corp. */
+
+/*
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2 of the License, or (at your
+  option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+*/
+
+#define VERS2 "0.04a"
+#define OFDT "07/28/2004"
+
+#include <stdio.h>
+#include <stdlib.h> 
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <time.h>
+#include <string.h>
+#include "vcddiff.h"
+
+static int get_token(FILE *, char *);
+static void read_to_end(FILE *);
+static char timescale(FILE *, int *);
+static void add_signal(char *, char *, unsigned int, int, int);
+static int get_var_type(char *);
+static void variable(FILE *, char *);
+static void alloc_sig_mem(void);
+static int get_vkeywrd(register char *);
+static long get_lines(FILE *, int *, int *, char *);
+static void print_signal_info(struct signal_t *, struct signal_t *, vtime_t, 
+		vtime_t, bool_t);
+static void print_scalar_state(struct signal_t *, struct signal_t *, vtime_t, 
+                vtime_t, char, char, bool_t);
+static void print_vector_state(struct signal_t *, struct signal_t *, vtime_t, 
+                vtime_t, char *, char *, bool_t);
+static void print_scalar_edge(struct signal_t *, struct signal_t *, vtime_t, 
+                vtime_t, char, char, bool_t);
+static void print_edges(struct signal_t *, char *, int, int, char);
+static void print_vector_edge(struct signal_t *, struct signal_t *, vtime_t, 
+                vtime_t, char *, char *, bool_t);
+static int get_nxt_chg(FILE *, char *, int *, int *, char *, vtime_t *, 
+		         bool_t);
+static vtime_t get_time_diffs(FILE *, FILE *, char *, char *, long, long, 
+	          vtime_t, vtime_t, bool_t);
+static void print_map(void);
+static void compare_types(char *, char *, struct signal_t *, struct signal_t *);
+static bool_t map(char *, char *, int **, struct signal_t *, 
+                   struct signal_t *, struct signal_t **, bool_t);
+static bool_t map_var_names(char *, char *);
+static void run_diffs(FILE *, FILE *, char *, char *, long, long);
+static void print_header(void);
+static void print_help(void);
+static void edge_space(int, int , bool_t);
+
+/* globals */
+static int line_num1G;   /* cur position of file1 */
+static int line_num2G;  /* cur position of file2 */
+static char curmodG[1000]; /* cur mod hier name */
+static FILE *file1G;   /* to check if it is the first file */
+static bool_t state_flagG; /* print edges or states */
+static bool_t wrap_flagG; /* print edges or states */
+static struct signal_t	**sig_int1G;  /* int codes for file 1 */	
+static struct signal_t	**sig_int2G;	/* int codes for file 2 */	
+static int **fd1_to_fd2_mapG;   /* mappings from one file to the other*/	
+static int **fd2_to_fd1_mapG;	
+static int max_codeG;         /* max code so sig_int? is large enough */
+static char scopesG[MAXSCOPES][MAXSIG];  /* scope of mods */
+static int  quit_flagG;    /* flag to quit */
+static bool_t  next_listG;    /* to signal the next list of signals */   
+struct signal_t *sig1_hdG;   /* the head of the first file of signals */  
+struct signal_t *sig2_hdG;   /* the head of the second file of signals */   
+struct signal_t *lastsigG;   /* mark the last signal of the file */    
+
+/* signal to code from dinotrace wave viewer www.veripool.com/dinotrace */
+#define	VERILOG_ID_TO_POS(_code_) \
+    (_code_[0]?((_code_[0]-32) + 94 * \
+		(_code_[1]?((_code_[1]-32) + 94 * \
+			    (_code_[2]?((_code_[2]-32) + 94 * \
+					(_code_[3]?((_code_[3]-32) \
+						    ):0) \
+					):0) \
+			    ):0) \
+		):0)
+
+#define VERILOG_POS_TO_SIG1(_pos_) \
+    (((_pos_)<max_codeG)?sig_int1G[(_pos_)]:0)
+
+#define VERILOG_POS_TO_SIG2(_pos_) \
+    (((_pos_)<max_codeG)?sig_int2G[(_pos_)]:0)
+/**********************************************************************/
+
+/*get a new token from the file fp, and place in token, return the length*/
+static int get_token(FILE *fp, char *token)
+{
+ int i, c; 
+
+ i = 0;
+ while((c = fgetc(fp)) != EOF)
+ {
+	 if(isspace(c))
+	 {
+           if(c == '\n')
+           {
+ 	     if(fp == file1G) line_num1G++; 	 
+	     else line_num2G++; 	 
+	   }
+		 continue;
+         }
+	 break;
+ }
+ 
+ if(c == EOF) return EOF;
+ token[i++] = c;
+
+ while(!isspace(c = fgetc(fp)))
+ {
+   if(c == EOF)
+ 	 return EOF;
+   else
+     token[i++] = c;
+ }
+ if(c == '\n')
+ {
+    if(fp == file1G) line_num1G++; 	 
+    else line_num2G++; 	 
+ }
+
+ token[i]='\0';
+ return i; 
+}
+
+/*read the file until an $end is reached*/
+static void read_to_end(FILE *fp)
+{
+  char token[MAXTOKSIZE];
+
+    while(get_token(fp, token) != EOF) 
+    {
+	if(!strncmp (token, "$end", 4))
+	    return;
+    }
+}
+
+/* get the timescale information for comparison return char of units, and 
+ * the number 1, 10, 100 in tnum
+ * */
+static char timescale(FILE *fp, int *tnum)
+{
+ int i, toklen;
+ char token[MAXTOKSIZE];
+ char tmp[MAXTOKSIZE];
+ char *tok;
+    
+    toklen = get_token(fp, token); 
+    tok = token;
+    /* AIV 02/04/03 there can be a space between 1 ns, not always 1ns */
+    for(i = 0; i <toklen; i++)
+    {
+      if(!isdigit(token[i])) break;
+    }
+    if(i == toklen)
+    {
+      get_token(fp, tmp);
+      strcat(token, tmp);
+    }
+	
+    *tnum = atoi(tok);
+
+    if(*tnum != 1 && *tnum != 10 && *tnum != 100)
+    {
+	    printf("*** ERROR-time number(%d) in timescale on line %d is illegal - assuming 1\n", *tnum, (fp == file1G) ? line_num1G : line_num2G ); 
+	    *tnum = 1;
+    }
+
+    while(isdigit (*tok))
+	    tok++;
+    if (!*tok) 
+	    get_token(fp, token);	
+   
+    switch (*tok) {
+    case 's':
+    case 'm':
+    case 'u':
+    case 'n':
+    case 'p':
+    case 'f':
+      return(*tok);   
+    default:
+	  printf("*** ERROR-illegal character(%c) in timescale on line %d\n", *tok, (fp == file1G) ? line_num1G : line_num2G ); 
+	  return(0);
+    }
+}
+
+/* add a new signal to the list, init values signal name, identifies
+ * the code to index the array of signals, and the number of bits, if
+ * bits is 1 it is scalar
+ * */
+static void add_signal(char *signame,char *ident, unsigned int code, 
+                                   int bits, int type)
+{
+ char  *cp;
+ struct signal_t *newsig;
+
+   /*get rid of scapes before and after*/
+   while(isspace(*signame)) signame++;	
+   for (cp = signame + strlen(signame) - 1;cp >= signame && isspace(*cp);  cp--)    *cp = '\0';
+          
+   newsig = (struct signal_t *) malloc(sizeof(struct signal_t));
+   newsig->sig_code = code;	
+   newsig->ident = (char *) malloc(strlen(ident)+1);
+   /* init values to x's */
+   newsig->state = '?';
+   newsig->type = type; 
+   newsig->in_both = TRUE; 
+   newsig->size = bits;
+   newsig->next = NULL;
+
+   if(type == REAL)
+   {
+     /*FIXME what about large reals ???*/
+     newsig->vector = (char *) malloc(REALSIZE);
+     newsig->vector[0] = '0';
+     newsig->vector[1] = '\0';
+   }
+   else if(bits > 1)
+   {
+     newsig->vector = (char *) malloc(bits + 2);
+     newsig->vector[bits] = '\0';  
+     bits--;
+     for(; bits >= 0; bits--)
+       newsig->vector[bits] = '?';  
+   }
+
+   /*signal not found so print first diff*/
+   newsig->found = FALSE;
+   strcpy(newsig->ident, ident); 
+   /*link signals for hash setup and mapping*/
+   if(lastsigG) 
+      lastsigG->next= newsig;
+
+   if(sig1_hdG == NULL) 
+      sig1_hdG = newsig;
+	    
+   if(next_listG && sig2_hdG == NULL) 
+      sig2_hdG = newsig;
+	    
+   lastsigG = newsig;
+   newsig->signame = (char *) malloc(strlen(signame)+1);
+   strcpy(newsig->signame, signame);
+   max_codeG = MAX(max_codeG, code+1);
+}
+
+
+/*dump variable types must be kept in alphabetical order */
+static struct variable_types_t var_types[] = {
+	{"event", EVENT },
+        {"integer", INTEGER},
+        {"parameter", PARAMETER}, 
+        {"real", REAL}, 
+        {"reg", REG},
+        {"supply0", SUPPLY0}, 
+        {"supply1", SUPPLY1}, 
+        {"time", TIME}, 
+        {"tri", TRI}, 
+        {"tri0", TRI0}, 
+        {"tri1", TRI1}, 
+        {"triand", TRIAND}, 
+        {"trior", TRIOR}, 
+        {"trireg", TRIREG}, 
+        {"wand", WAND},  
+        {"wire", WIRE},
+        {"wor",	WOR}
+};
+
+
+#define VARTYPE (sizeof(var_types) / sizeof(struct variable_types_t))
+
+static int get_var_type(char *tstr)
+{
+ int l, h;
+ register int m, cv;
+
+
+ l = 0; h = VARTYPE - 1;
+ for (;;)
+  {
+   m = (l + h)/2;
+   if((cv = strcmp(var_types[m].vnam, tstr)) == 0)
+      return(var_types[m].vnum);
+   if(cv < 0) l = m + 1; else h = m - 1;
+   if(h < l) break;
+  }
+ return(-1);
+
+}
+
+/*var line so add a new signal with its identifier*/
+static void variable(FILE *fp, char *file_name)
+{
+  char signame[MAXSIG];
+  char ident[10];
+  char token[MAXTOKSIZE];   
+  int  bits;
+  char type;
+    
+    /*type, size*/
+    get_token(fp, token); 
+    /*most ofter a reg otherwise do a search */
+    if(strncmp(token, "reg", 3) == 0)  
+	    type = REG; 
+    else
+            type = get_var_type(token);
+
+    if(type < 0)
+    {
+      type = UNDEFINED;
+      printf("Error- Unknown variable type %s\n", token);
+    }
+
+    /* get number of bits */
+    /* AIV FIXME error recovery should be used here for invalid tokens
+     * if a $var line is short vars (starts with a '$') rewind, print 
+     * message and return */ 
+    get_token(fp, token); 
+    bits = atoi(token);
+
+    if(bits < 0) 
+    {	
+       printf ("Negative size illegal on line %d of %s\n", (fp == file1G) ? line_num1G : line_num2G, file_name);
+       return;
+    }
+
+    /*identifier*/
+    get_token(fp, token); 
+    strcpy(ident, token);
+    
+    /*variable name*/
+    get_token(fp, token); 
+    strcpy (signame, curmodG);
+    strcat (signame, token); 
+		 
+
+    get_token(fp, token); 
+    /*if there is a space between the var name and the range concat it 
+     * to the name */
+    if (token[0] != '$') 
+	strcat (signame, token);
+    
+    add_signal(signame, ident, VERILOG_ID_TO_POS(ident), bits, type);
+}
+
+
+/* setup memory for the hash of signals, which is the max of all signals,
+ * then setup up arrays according to the signal's code index
+ */
+static void alloc_sig_mem(void)
+{
+  struct signal_t *sig;
+
+  sig_int1G = (struct signal_t **) calloc(sizeof(struct signal_t *), (max_codeG + 1));
+  for (sig = sig1_hdG; sig !=NULL; sig = sig->next)
+     sig_int1G[sig->sig_code] = sig;
+
+  sig_int2G = (struct signal_t **) calloc(sizeof(struct signal_t *), (max_codeG + 1));
+  for (sig = sig2_hdG; sig !=NULL; sig = sig->next) 
+     sig_int2G[sig->sig_code] = sig;
+
+}
+
+/*dump file keywords must be kept in alphabetical order */
+static struct variable_types_t vkeywds[] = {
+        { "comment", V_COMMENT},
+        { "date", V_DATE },
+        { "end", V_END },
+        { "enddefinitions", V_ENDDEF},
+        { "scope", V_SCOPE},
+        { "timescale", V_TIMESCALE },
+        { "upscope", V_UPSCOPE },
+        { "var", V_VAR },
+        { "version", V_VERSION }
+};
+
+#define VKEYWDS (sizeof(vkeywds) / sizeof(struct variable_types_t))
+
+/*search for verilog keywords*/
+static int get_vkeywrd(register char *tstr)
+{
+ int l, h;
+ register int m, cv;
+
+ //start at $end
+ l = -2; h = VKEYWDS - 1;
+ for (;;)
+  {
+   m = (l + h)/2;
+   if((cv = strcmp(vkeywds[m].vnam, tstr)) == 0)
+        return(vkeywds[m].vnum);
+   if(cv < 0) l = m + 1; else h = m - 1;
+   if(h < l) break;
+  }
+ return(EOF);
+}
+
+
+/* process all the lines until $enddef is reached, determines all variable
+ * names, seperated by a '.' between scopes, place the timescale number 
+ * and units, and return the file location to start processing diffs
+ */
+static long get_lines(FILE *fp, int *units, int *tnum, char *file_name)
+{
+  char sep[2];
+  int level;
+  register int i;
+  char *tok;
+  char token[MAXTOKSIZE]; 
+   
+    sep[0] = '.'; 
+    sep[1] = '\0';
+    level = 0;    
+    *units = 1;
+
+    while(get_token(fp, token) != EOF)
+    {
+      tok = token;
+      if(tok[0] != '$')
+      {
+        printf ("***ERROR Unknown token '%s' on line %d of %s\n",
+           tok, (fp == file1G) ? line_num1G: line_num2G, file_name);
+        continue;
+      }
+      tok++;
+
+      switch(get_vkeywrd(tok)){
+        case V_END:
+                break;
+        
+	case V_VAR:
+		 variable(fp, file_name);
+	      break;
+
+        case V_UPSCOPE:
+	         if(level > 0) level--;
+	      break;	
+	      
+	case V_SCOPE:      
+	    get_token(fp, tok);
+	    get_token(fp, tok);
+
+	    if(level < MAXSCOPES) 
+            {
+		strcpy(scopesG[level], tok);
+
+	        strcpy(curmodG, scopesG[0]);
+	        strcat(curmodG, sep);
+		level++;
+
+		if(level)
+		{		    
+                  for (i=1; i<level; i++) {
+	             strcat(curmodG, scopesG[i]);
+	             strcat(curmodG, sep);
+                  }
+	        }
+
+	    }
+	    else
+            {
+	       printf("*** ERROR-exceeded max scope levels %d\n", level);
+	       exit(0);
+	    }
+          break;
+        case V_COMMENT: 
+	case V_DATE: 
+	case V_VERSION:
+	       read_to_end(fp);
+	     break;
+ 
+        case V_TIMESCALE:
+		 *units = timescale(fp, tnum);		 
+		break;
+		
+        case V_ENDDEF:
+	    next_listG = TRUE;
+	    lastsigG = NULL;
+	    return(ftell(fp)); 
+		    
+	default:
+	    printf ("Unknown command '%s' on line %d of %s\n",
+		     tok, (fp == file1G) ? line_num1G: line_num2G, file_name);
+	    break;
+	
+    }	
+  }
+    return(-1);
+}
+
+/* print the diff signal information */
+static void print_signal_info(struct signal_t *sig1, 
+                              struct signal_t *sig2, 
+                              vtime_t time1, vtime_t time2, bool_t isone)
+{
+
+   if(time1 == time2)
+   {
+      
+      if(sig1->sig_code == sig2->sig_code)
+          printf("%s (%s) differs at time %lld\n", sig1->signame,sig1->ident, time1);
+      else
+          printf("%s (%s , %s) differs at time %lld\n", sig1->signame,
+                sig1->ident, sig2->ident, time1);
+     return;
+    }
+   else
+   {
+       if(sig1->sig_code == sig2->sig_code)
+              printf("%c %s (%s) at time %lld next occurence at time %lld\n", isone ? '>' : '<',  sig1->signame, sig1->ident, time1, time2);
+       else
+              printf("%c %s (%s, %s) at time %lld next occurence at time %lld\n", isone ? '>' : '<',  sig1->signame,sig1->ident, sig2->ident, time1, time2);
+     return;
+   }
+
+}
+
+
+
+/* print the scalar value  */
+static void print_scalar_state(struct signal_t *sig1, 
+                               struct signal_t *sig2, 
+                               vtime_t time1, vtime_t time2, 
+                               char state1, char state2, bool_t isone)
+{
+
+   if(time1 == time2)
+   {
+      sig1->found = TRUE;
+      sig2->found = TRUE;
+      if(state1 != state2)
+      {
+         print_signal_info(sig1, sig2, time1, time2, isone);
+         printf("\t%c\n\t%c\n",state1, state2);
+	 return;
+      }
+   }
+  else 
+  { 
+         print_signal_info(sig1, sig2, time1, time2, isone);
+         printf("%c #%lld \t%c\n", isone ? '>' : '<', time1, state1);
+	 printf("%c #%lld \t%c\n", isone ? '>' : '<', time2, state2);
+	      return;
+     }
+}
+
+
+/* print the vector value  */
+static void print_vector_state(struct signal_t *sig1,  
+                               struct signal_t *sig2, 
+                               vtime_t time1, vtime_t time2, 
+                               char *sval1, char *sval2, bool_t isone)
+{
+ int size1, size2;
+ register int i;
+
+ size1 = strlen(sval1);
+ size2 = strlen(sval2);
+ if(time1 == time2)
+ {
+    sig1->found = TRUE;
+    sig2->found = TRUE;
+   if(strcmp(sval1, sval2) != 0)
+   {
+       print_signal_info(sig1, sig2, time1, time2, isone);
+       if(size1 == size2)
+         printf("\t%s\n\t%s\n", sval1, sval2);
+       else
+       {
+         if(size1 > size2)
+         {
+           printf("\t%s\n\t", sval1);
+           for(i = 0; i < size1 - size2; i++)
+               putc(' ', stdout);
+           printf("%s\n", sval2);
+         }
+         else
+         {
+           printf("\t");
+           for(i = 0; i < size2-size1; i++)
+               putc(' ', stdout);
+           printf("%s\n\t%s\n", sval1, sval2);
+         }
+       }
+       return;
+      }
+   }
+  else 
+  {
+     print_signal_info(sig1, sig2, time1, time2, isone);
+     if(size1 == size2)
+     {
+       printf("%c #%lld \t%s\n", isone ? '>' : '<', time1, sval1);
+       printf("%c #%lld \t%s\n", isone ? '>' : '<', time2, sval2);
+     }
+     else
+     {
+         if(size1 > size2)
+         {
+           printf("%c #%lld \t%s\n", isone ? '>' : '<', time1, sval1);
+           printf("%c #%lld \t", isone ? '>' : '<', time2);
+           for(i = 0; i < size1 - size2; i++)
+               putc(' ', stdout);
+           printf("%s\n", sval2);
+         }
+         else
+         {
+           printf("%c #%lld \t", isone ? '>' : '<', time1);
+           for(i = 0; i < size2-size1; i++)
+               putc(' ', stdout);
+           printf("%s\n", sval1);
+           printf("%c #%lld \t%s\n", isone ? '>' : '<', time2, sval2);
+         }
+     }
+   }
+}
+
+
+
+/* print scalar edge value  */
+static void print_scalar_edge(struct signal_t *sig1, 
+                              struct signal_t *sig2, 
+                              vtime_t time1, vtime_t time2, 
+                              char state1, char state2, bool_t isone)
+{
+	
+        if(time1 == time2)
+        {
+          sig1->found = TRUE;
+          sig2->found = TRUE;
+          if(state1 != state2)
+          {
+            print_signal_info(sig1, sig2, time1, time2, isone);
+
+	    if(sig1->state == state1) 
+               printf("\t(%c-)\n", state1);
+	    else
+               printf("\t(%c%c)\n", sig1->state, state1);
+	    if(sig2->state == state2) 
+               printf("\t(%c-)\n", state2);
+	    else
+               printf("\t(%c%c)\n", sig2->state, state2);
+	    return;
+	  }
+	 }
+         else 
+	 { 
+           print_signal_info(sig1, sig2, time1, time2, isone);
+
+           if(sig1->state == state1) 
+              printf("%c #%lld \t(%c-)\n", isone ? '>' : '<', time1, state1);
+           else
+              printf("%c #%lld \t(%c%c)\n", isone ? '>' : '<', time1, sig1->state, state1);
+           if(sig2->state == state2) 
+              printf("%c #%lld \t(%c-)\n", isone ? '>' : '<', time2, state2);
+           else     
+              printf("%c #%lld \t(%c%c)\n", isone ? '>' : '<', time2, sig2->state, state2);
+           return;
+        }
+}
+
+/* print the edge values 
+  sig - signal pointer
+  sval - sval string value
+  str_size - size of sval
+  search - '<' or '>' if a search was performed otherwise 'n' for none
+  this is needed for wrapping of the line
+*/
+static void print_edges(struct signal_t *sig, char *sval, int str_size, 
+                        int vec_size, char searchc)
+{
+ register int i;
+ int min, tprint;
+
+ /*AIV 02/06/03 the print edges were wrong for different sizes */
+ /* for example, b10 is now b101 at the next time */
+ /* vector is the old value and sval is the new */
+
+ if(str_size > vec_size)
+	 min = vec_size;
+ else
+	 min = str_size;
+
+ tprint = 0;
+ for(i=0; i < min; i++, tprint++)		   
+ {
+   if(sig->vector[i] == sval[i]) 
+     printf(" (%c-)", sig->vector[i]);
+   else
+     printf(" (%c%c)", sig->vector[i], sval[i]);
+
+   /* only want to print 11 edges per line */
+     if(wrap_flagG && tprint != 0 && !(tprint % EDGE_PER_LINE)) 
+     {
+        if(searchc != 'n')
+          printf(" \\\n%c\t", searchc);
+        else
+          printf(" \\\n\t");
+     }
+ }
+ if(str_size == vec_size) return;
+
+ if(min == vec_size)
+ {
+   for(i = min; i < str_size; i++, tprint++)		   
+   {
+      printf(" (?%c)", sval[i]);
+      if(wrap_flagG && tprint != 0 && !(tprint % EDGE_PER_LINE)) 
+      {
+        if(searchc != 'n')
+          printf(" \\\n%c\t", searchc);
+        else
+          printf(" \\\n\t");
+      }
+   }
+ }
+ else
+ {
+   /* if the first value is a '?', no need to print the rest
+    * since it can only be '?' on the first value change */
+   if(sig->vector[0] != '?')
+   {
+     for(i = min; i < vec_size; i++, tprint++)		   
+     {
+      printf(" (%c?)", sig->vector[i]);
+      if(wrap_flagG && tprint != 0 && !(tprint % EDGE_PER_LINE)) 
+      {
+        if(searchc != 'n')
+          printf(" \\\n%c\t", searchc);
+        else
+          printf(" \\\n\t");
+      }
+     }
+   }
+ }
+
+}
+
+/* add space so the vector edge valued line up correctly */
+static void edge_space(int size1, int size2, bool_t is_sigone)
+{
+ register int i, r, diff;
+
+ if(size1 == size2) return;
+ if(is_sigone && size2 > size1)
+ {
+    diff = (size2 - size1) * CHAR_PER_EDGE;
+    if(wrap_flagG)
+    {
+      r = diff / EDGE_PER_LINE;
+      if(r > 0)
+      {
+        r = (r * EDGE_PER_LINE);
+        diff -= r;
+        if(diff <= CHAR_PER_EDGE) diff = 0;
+      }
+    }
+    for(i=0; i < diff; i++)
+         putc(' ', stdout);
+ }
+ if(!is_sigone && size1 > size2)
+ {
+     diff = (size1 - size2) * CHAR_PER_EDGE;
+     if(wrap_flagG)
+     {
+       r = diff / EDGE_PER_LINE;
+       if(r > 0)
+       {
+        r = (r * EDGE_PER_LINE);
+        diff -= r;
+        if(diff <= CHAR_PER_EDGE) diff = 0;
+       }
+     }
+     for(i=0; i < diff; i++)
+          putc(' ', stdout);
+ }
+
+}
+
+
+
+
+/* print vector edge */
+static void print_vector_edge(struct signal_t *sig1, 
+                              struct signal_t *sig2, 
+                              vtime_t time1, vtime_t time2, 
+                              char *sval1, char *sval2, bool_t isone)
+{
+ int size1, size2;
+ int vsize1, vsize2;
+ int max1, max2;
+ char dirc;
+
+   if(time1 == time2)
+   {
+       sig1->found = TRUE;
+       sig2->found = TRUE;
+      
+       if(strcmp(sval1, sval2) != 0)
+	{
+	 
+	  if(sig1->type == REAL)
+	  {
+            print_vector_state(sig1, sig2, time1, time2, sval1, sval2, isone); 
+	    return; 
+	  }
+         
+	  print_signal_info(sig1, sig2, time1, time2, isone);
+          printf("\t"); 
+
+          size1 = strlen(sval1);
+          vsize1 = strlen(sig1->vector);
+          max1 = MAX(size1, vsize1);
+
+          size2 = strlen(sval2);
+          vsize2 = strlen(sig2->vector);
+          max2 = MAX(size2, vsize2);
+
+          edge_space(max1, max2, TRUE);
+          print_edges(sig1, sval1, size1, vsize1, 'n'); 
+          if(wrap_flagG && sig1->size > EDGE_PER_LINE)
+             printf("\n\n\t"); 
+          else
+            printf("\n\t"); 
+          edge_space(max1, max2, FALSE);
+          print_edges(sig2, sval2, size2, vsize2, 'n'); 
+          printf("\n"); 
+	  return;
+	}
+   }   
+   else 
+   {
+	 if(sig1->type == REAL)
+	 {
+            print_vector_state(sig1, sig2, time1, time2, sval1, sval2, isone); 
+	    return;
+	 }
+         print_signal_info(sig1, sig2, time1, time2, isone);
+         dirc = isone ? '>' : '<';
+         printf("%c #%lld \t", dirc, time1);
+         
+         size1 = strlen(sval1);
+         vsize1 = strlen(sig1->vector);
+         max1 = MAX(size1, vsize1);
+
+         size2 = strlen(sval2);
+         vsize2 = strlen(sig2->vector);
+         max2 = MAX(size2, vsize2);
+
+         edge_space(max1, max2, TRUE);
+         print_edges(sig1, sval1, size1, vsize1, dirc); 
+         printf("\n%c #%lld \t", dirc, time2);
+         edge_space(max1, max2, FALSE);
+         print_edges(sig2, sval2, size2, vsize2, dirc); 
+         printf("\n"); 
+	 return;
+  }
+}
+
+/* get the next time change in the other file if there is one */
+static int get_nxt_chg(FILE *fp, char *fname, int *sigcode, int *bit, 
+                       char *value, vtime_t *time, bool_t isone)
+{
+ char *line;
+ char token[MAXTOKSIZE];
+
+   while(get_token(fp, token) != EOF) 
+   {
+      line = token;
+     
+      switch (*line++) 
+      {
+        /* scalar cases */
+	case '0':
+	case '1':
+	case 'z':
+	case 'Z':
+	case 'x':
+	case 'X':
+          *bit = *(line-1);
+          *sigcode = VERILOG_ID_TO_POS(line);
+	     
+         if(isone)
+         { 
+           if(VERILOG_POS_TO_SIG1(*sigcode) == NULL)
+	   {
+             printf("Unknown Identifier '%s' in file %d '%s' on line %d\n", 
+	        line, isone ? 1 : 2, fname, 
+	        isone ? line_num1G : line_num2G );
+	     continue;
+	   }
+	 }
+	 else if(VERILOG_POS_TO_SIG2(*sigcode) == NULL)
+	 {
+           printf("Unknown Identifier '%s' in file %d '%s' on line %d\n", 
+	       line, isone ? 1 : 2, fname, 
+               isone ? line_num1G : line_num2G );
+   	    continue;
+	 }
+	 return(SCALAR); 
+	 break;
+        /* vector or real cases */
+	case 'b':
+	case 'r':
+	    strcpy(value, line);
+	    get_token(fp, token);
+	    *sigcode = VERILOG_ID_TO_POS(token);
+	    if(isone)
+	    {
+	       if(VERILOG_POS_TO_SIG1(*sigcode) == NULL)
+	       {
+                 printf("Unknown Identifier '%s' in file %d '%s' on line %d\n", 
+		        line, isone ? 1 : 2, fname, 
+		        isone ? line_num1G : line_num2G );
+	       continue;
+	       }
+	    }
+	    else if(VERILOG_POS_TO_SIG2(*sigcode) == NULL)
+	    {
+                 printf("Unknown Identifier '%s' in file %d '%s' on line %d\n", 
+		        line, isone ? 1 : 2, fname, 
+		        isone ? line_num1G : line_num2G );
+		 continue;
+	    }
+	    return(VECTOR); 
+	
+        /* time change value */
+	case '#':
+	    *time = (vtime_t) atoll(line);
+	    return(TIME); 
+	case '$':
+	    /* AIV 02/03/03 need to read until $end for $comment */
+	    if(!strcmp(line, "comment") || !strcmp(line, "dumpall"))
+	       read_to_end(fp);
+	    break;
+        default:
+	    line--;
+            printf("***ERROR Unknown token '%s' in file %d '%s' on line %d\n", 
+	  	     line, isone ? 1 : 2, fname, 
+		     isone ? line_num1G : line_num2G );
+	     /*FIXME shouldn't die here if possible */
+	      exit(0);
+            continue;
+	  break;
+	}
+   }
+   return(EOF);
+}
+
+/* used to place the string back on the fp to be used later */
+static void restore(FILE *fp, char *str, int size)
+{
+ int i;
+ char *cp;
+
+ ungetc(' ', fp); 
+ cp = &str[size-1];
+
+ for(i =0; i< size; i++, cp--)
+	 ungetc(*cp, fp); 
+
+}
+
+/* return true if the next signal isn't the same, otherwise false */ 
+static bool_t peek_nxt_sig(FILE *fp, int sigcode1, bool_t isone)
+{
+  char tmp[MAXTOKSIZE], sig[MAXTOKSIZE];
+  int size1, size2, sigcode2;
+  char *cp;
+  
+  size1 = get_token(fp, tmp);
+  cp = tmp;
+
+  if(tmp[0] == 'b')
+  {
+   size2 = get_token(fp, sig);
+   restore(fp, sig, size2);
+   restore(fp, tmp, size1);
+   cp = sig;
+  }
+  else if(tmp[0] == '0' || tmp[0] == '1' || tmp[0] =='x' || tmp[0] =='z')
+  {
+      restore(fp, tmp, size1);
+      cp++;
+  }
+  else
+  {
+   restore(fp, tmp, size1);
+   return(TRUE);
+  }
+
+  /* map signal to the right sigcode */
+  sigcode2 = VERILOG_ID_TO_POS(cp);
+  
+  /* LOOKATME can this ever happen ??*/
+  if(sigcode2 > max_codeG) return(TRUE);
+  if(isone)
+  {
+    if(fd2_to_fd1_mapG[sigcode2] == NULL) return(TRUE);
+    sigcode2 = *fd2_to_fd1_mapG[sigcode2]; 
+  }
+  else
+  {
+    if(fd1_to_fd2_mapG[sigcode2] == NULL) return(TRUE);
+    sigcode2 = *fd1_to_fd2_mapG[sigcode2]; 
+  }
+	  
+  return(sigcode1 != sigcode2);
+}
+
+
+/* rewind to file and reset line count to the start of a #time */
+static void rewind_time(FILE *fp, long seek, vtime_t *time, 
+  	                vtime_t treset, int *linenum, int lreset)
+{
+  *time = treset; 
+  fseek(fp, seek, SEEK_SET);
+ /* reset the line counts */
+  *linenum = lreset;
+}
+
+
+/* get the differences of a time block from #time to the next #time2 or EOF */
+
+static vtime_t get_time_diffs(FILE *mainfp, FILE *otherfp, char *mname, 
+                           char *oname, long seek1, long seek2, 
+                           vtime_t ltime1, vtime_t ltime2, bool_t isone)
+{
+  char svalue1[MAXTOKSIZE], svalue2[MAXTOKSIZE];
+  int retval;
+  int sigcode1, sigcode2; 
+  int  state1, state2;
+  int tmpline1, tmpline2;
+  vtime_t time, nxt_time;
+  struct signal_t *sig1, *sig2;
+  bool_t first;
+   
+  sigcode1 = sigcode2 = 0;
+  first = TRUE;
+  time = ltime1;
+  nxt_time = ltime2; 
+
+  /* AIV 02/04/03 added temps to reset line count for unkown tokens, etc */
+   tmpline1 = line_num1G;
+   tmpline2 = line_num2G;
+
+
+  /* LOOKATME rewind needed here because of reset ungets, and seek from
+     the start of the file, should write own buffer  */
+   rewind(isone ? mainfp : otherfp);
+   if(isone)
+     fseek(mainfp, seek1, SEEK_CUR);
+   else
+     fseek(otherfp, seek2, SEEK_CUR);
+
+  while(retval != EOF) 
+  {
+	 
+    retval = get_nxt_chg(mainfp, mname, &sigcode1, &state1, svalue1, &time, isone); 
+    switch(retval) 
+    {  
+      case SCALAR:
+      case VECTOR:	  
+      /* rewind if the next sig isn't the same */
+      /* LOOKATME could change so that if the first sig isn't*/
+      /* get_nxt would rewind, to speed up ?? */
+      if(!first && peek_nxt_sig(otherfp, sigcode1, isone))
+      {
+          rewind_time(otherfp, seek2, &nxt_time, ltime2, 
+		      isone ? &line_num2G : &line_num1G,
+		      isone ? tmpline2 : tmpline1); 
+      }
+
+      first = FALSE;
+      if(isone)
+      {
+        sig1 = VERILOG_POS_TO_SIG1(sigcode1);
+        sigcode1 = *fd1_to_fd2_mapG[sigcode1]; 
+        sig2 = VERILOG_POS_TO_SIG2(sigcode1);
+      }
+      else
+      {
+        sig1 = VERILOG_POS_TO_SIG2(sigcode1);
+        sigcode1 = *fd2_to_fd1_mapG[sigcode1]; 
+        sig2 = VERILOG_POS_TO_SIG1(sigcode1);
+      }
+      if(!sig1->in_both) 
+	    break; 
+      if(sig1->found) 
+      {
+        sig1->found = FALSE;
+        sig2->found = FALSE;
+        if(retval == SCALAR) sig1->state = state1;
+        else strcpy(sig1->vector, svalue1);
+        break;
+     }
+     /*should check to see if sig1 and sig 2 are the same type??*/ 
+     for(;;)
+     {
+       if(get_nxt_chg(otherfp, oname, &sigcode2, &state2, svalue2, &nxt_time, !isone) == EOF) 
+       {
+          printf("%s (%s) Never found in file %d at time %lld\n", sig1->signame,
+                     sig1->ident, isone ? 1 : 2, time);
+         break; 
+       }
+       else if(sigcode1 == sigcode2) 
+	        break;
+      }
+	    
+     if(retval == SCALAR)
+     {
+	if(state_flagG)
+          print_scalar_state(sig1, sig2, time, nxt_time, 
+                                          state1, state2, isone); 
+	else
+          print_scalar_edge(sig1, sig2, time, nxt_time, 
+                                          state1, state2, isone); 
+        sig1->state = state1;
+     }
+     else if(retval == VECTOR)
+     {
+        if(state_flagG)
+          print_vector_state(sig1, sig2, time, nxt_time, 
+                                         svalue1, svalue2, isone);            
+	else
+          print_vector_edge(sig1, sig2, time, nxt_time, 
+                                          svalue1, svalue2, isone);            
+       strcpy(sig1->vector, svalue1);
+     }
+    /* if isn't the same time must of scanned foward so rewind */
+     if(nxt_time != time)
+     {
+        rewind_time(otherfp, seek2, &nxt_time, ltime2, 
+		      isone ? &line_num2G : &line_num1G,
+		      isone ? tmpline2 : tmpline1); 
+     }
+            
+    break;
+   case TIME:
+      /* rewind to the start time, to process other file*/
+     if(isone)
+     {
+         rewind_time(otherfp, seek2, &nxt_time, ltime2, 
+		      isone ? &line_num2G : &line_num1G,
+		      isone ? tmpline2 : tmpline1); 
+     }
+    if(time != 0)
+       return(time);
+    break;
+  case EOF:
+     quit_flagG = EOF;
+     return(time);
+  default:
+	   continue;
+	}
+   }
+  /*FIXME should never get here emit error */
+  return(time);
+}
+
+
+
+/* print the map of identifiers to signal name between files */
+static void print_map(void)
+{
+   register int i;
+   struct signal_t *sig;
+   
+   for(i = 0; i< max_codeG; i++)
+   {
+    if(fd1_to_fd2_mapG[i] != NULL)
+    {
+        sig = VERILOG_POS_TO_SIG2(*fd1_to_fd2_mapG[i]);
+	if(!sig->in_both) continue;
+	printf("%d %d %s\n", i, *fd1_to_fd2_mapG[i], sig->signame);
+           
+    }
+   }
+   printf("*********Second*********\n");
+   for(i = 0; i< max_codeG; i++)
+   {
+    if(fd2_to_fd1_mapG[i] != NULL)
+     {
+        sig = VERILOG_POS_TO_SIG1(*fd2_to_fd1_mapG[i]);
+	if(!sig->in_both) continue;
+	printf("%d %d %s\n", i, *fd2_to_fd1_mapG[i], sig->signame);
+           
+     }
+   }
+
+}
+
+/* check to make sure the files are the same in type/size in both files */
+static void compare_types(char *file_nam1, char *file_nam2, 
+                          struct signal_t *sig1, struct signal_t *sig2)
+{
+
+  if(sig1->in_both)
+  {
+    if(sig1->type != sig2->type)
+    {
+      if(sig1->sig_code == sig2->sig_code)
+         printf("WARNING - Ignoring signal %s (%s) - types don't match\n", 
+                    sig1->signame, sig1->ident);
+      else
+         printf("WARNING - Ignoring signal %s (%s %s) - types don't match\n", 
+                    sig1->signame, sig1->ident, sig2->ident);
+
+      printf("\t file '%s' type '%s'\n", file_nam1, var_types[sig1->type].vnam);
+      printf("\t file '%s' type '%s'\n\n", file_nam2, var_types[sig2->type].vnam);
+      sig1->in_both = FALSE;
+      sig2->in_both = FALSE;
+      return;
+    }
+    if(sig1->size != sig2->size)
+    {
+       if(sig1->sig_code == sig2->sig_code)
+          printf("WARNING - Ignoring signal %s (%s) - sizes don't match\n", 
+                        sig1->signame, sig1->ident);
+       else
+          printf("WARNING - Ignoring signal %s (%s %s) - sizes don't match\n", 
+                        sig1->signame, sig1->ident, sig2->ident);
+
+        printf("\t file '%s' size '%d'\n", file_nam1, sig1->size);
+        printf("\t file '%s' size '%d'\n\n", file_nam2, sig2->size);
+        sig1->in_both = FALSE;
+        sig2->in_both = FALSE;
+        return;
+     }
+  }
+}
+
+/* map the signal names to identifiers from one file to the other */
+static bool_t map(char *file_nam1, char *file_nam2, int **file_map, 
+                     struct signal_t *startsig, struct signal_t *otherstart, 
+                     struct signal_t **sig_arr, bool_t isone)
+{
+  struct signal_t *sig1, *sig2;	
+  bool_t one_found;
+  
+
+  one_found = FALSE;
+  for(sig1 = startsig; sig1 != NULL; sig1 = sig1->next)
+  {
+     if(isone)	  
+       sig2 = VERILOG_POS_TO_SIG2(sig1->sig_code);
+     else
+       sig2 = VERILOG_POS_TO_SIG1(sig1->sig_code);
+
+    if(sig2 == NULL)
+    {
+       for(sig2 = otherstart; sig2 != NULL; sig2 = sig2->next)
+       {
+           if(!sig2->in_both) continue; 
+           if(strcmp(sig1->signame, sig2->signame) == 0)
+           {
+              file_map[sig1->sig_code] = &sig2->sig_code; 
+              compare_types(file_nam1, file_nam2, sig1, sig2);
+              one_found = TRUE;
+              break;
+           }
+       }
+    }
+    else if(strcmp(sig1->signame, sig2->signame) == 0)
+    {
+        file_map[sig1->sig_code] = &sig1->sig_code; 
+        compare_types(file_nam1, file_nam2, sig1, sig2);
+        one_found = TRUE;
+    }
+    else 
+    {
+       for(sig2 = otherstart; sig2 != NULL; sig2 = sig2->next)
+       {
+           if(!sig2->in_both) continue; 
+           if(strcmp(sig1->signame, sig2->signame) == 0)
+           {
+              file_map[sig1->sig_code] = &sig2->sig_code; 
+              compare_types(file_nam1, file_nam2, sig1, sig2);
+              one_found = TRUE;
+              break;
+           }
+       }
+    }
+    if(sig2 == NULL) 
+    {
+       printf("WARNING - Ignoring signal %s (%s) - not defined in both files\n", sig1->signame, sig1->ident);
+       printf("\t  Defined in file '%s' and not file '%s'\n\n", file_nam1, file_nam2);
+       file_map[sig1->sig_code] = &sig1->sig_code; 
+       sig1->in_both = FALSE;
+    }
+ } 
+
+  return(one_found);
+}
+
+/* map both files */
+static bool_t map_var_names(char *file_nam1, char *file_nam2)
+{
+  fd1_to_fd2_mapG = (int**) malloc(sizeof(int) * max_codeG); 
+  fd2_to_fd1_mapG = (int**) malloc(sizeof(int) * max_codeG); 
+
+  map(file_nam1, file_nam2, fd1_to_fd2_mapG, sig1_hdG, sig2_hdG, sig_int1G, TRUE); 
+
+   return(map(file_nam2, file_nam1, fd2_to_fd1_mapG, sig2_hdG, sig1_hdG, sig_int2G, FALSE)); 
+
+  //print_map();
+
+}
+
+/* acutally run the files to diff the two */
+static void run_diffs(FILE *fp1, FILE *fp2, char *fnam1, char *fnam2, 
+                      long start1, long start2)
+{
+ vtime_t time1, time2, temp_time1;
+ long temp1_chars;
+ char token[MAXTOKSIZE];;
+
+  time1 = time2 = temp_time1 = 0;
+
+  while(quit_flagG != EOF)
+  { 
+
+   /* while the times are the same */
+   while(time1 == time2)
+   {
+     temp_time1 = time1; 
+     time1 =  get_time_diffs(fp1, fp2, fnam1, fnam2, start1, start2, 
+                              time1, time2, TRUE);  
+     temp1_chars = ftell(fp1);
+   
+     time2 =  get_time_diffs(fp2, fp1, fnam2, fnam1, start2, start1, 
+                              time2, temp_time1, FALSE);
+     start2=ftell(fp2);
+     start1=temp1_chars;
+     if(quit_flagG) break;
+   }
+
+   /* time one is ahead */
+    while(time2 < time1)
+    {
+     time2 = get_time_diffs(fp2, fp1, fnam2, fnam1, start2, start1, 
+                             time2, temp_time1, FALSE);
+     start2 = ftell(fp2);
+     if(quit_flagG)
+     { 
+          if(get_token(fp1, token) != EOF) 
+	  {
+		  printf("*****End of file hit at file 2 ('%s') time %lld quiting\n", fnam2, time2);
+		  printf("WARNING - Files have different end times\n");
+	  }
+	  break;
+     }
+   }
+
+   
+   /* while time two is ahead */
+    while(time1 < time2)
+    {
+     time1 =  get_time_diffs(fp1, fp2, fnam1, fnam2, start1, start2, time1, time2, TRUE);  
+     start1=ftell(fp1);
+     if(quit_flagG) 
+     {
+          if(get_token(fp2, token) != EOF) 
+	  {
+		  printf("*****End of file hit at file 1 ('%s') time %lld quiting\n", fnam1, time1);
+		  printf("WARNING - Files have different end times\n");
+	  }
+          break;
+     }
+    }
+  }
+}
+
+/* print help information */ 
+static void print_help(void)
+{
+  printf("Usage: [options] 'file1' 'file2'\n Compares Verilog VCD dump files.\n\n");
+
+  printf(" --state \n -s \n");
+  printf("\tPrints the current state of variables, instead of\n \tthe default edge value. \n");
+  printf(" --wrap  \n -w \n");
+  printf("\tWraps the line, only used for default edge print values\n\tnot --state print messages. \n");
+  exit(0);
+}
+
+
+/* print program header info */ 
+static void print_header(void)
+{
+ char s1[30];
+ time_t now;
+
+ printf("%s_%s of %s (%s).\n", "vcddiff", VERS2, OFDT, "Linux-ELF");
+ printf("Copyright (c) 2002-2004 Pragmatic C Software Corp.\n");
+ printf("All Rights reserved.  Licensed under the GNU General Public License (GPL).\n");
+ printf("See the 'COPYING' file for details.  NO WARRANTY provided.\n");
+ time(&now);
+ strcpy(s1, ctime(&now));
+ s1[24] = '\0';
+ printf("Today is %s.\n\n", s1);
+
+}
+
+static void set_options(int argc, char **argv)
+{
+ int i;
+
+ for(i = 1; i < argc-2; i++)
+ {
+   if(!strcmp(argv[i], "--state") || !strcmp(argv[i],"-s"))
+   {
+      if(wrap_flagG)
+        printf("WARNING - wrap cannot be used with --state option, wrap disabled\n\n");
+      else
+       state_flagG = TRUE;
+   }
+   else if(!strcmp(argv[i], "--wrap") || !strcmp(argv[i],"-w"))
+   {
+      if(state_flagG)
+        printf("WARNING - wrap cannot be used with --state option, wrap disabled\n\n");
+      else
+        wrap_flagG = TRUE;
+   }
+   else
+   {
+     printf("ERROR - Unknown option %s\n", argv[i]);
+     printf("\t Try 'vcddiff --help' for more infomation\n");
+     exit(0);
+   }
+ }
+
+}
+
+
+int main(int argc, char **argv)
+{
+   int unit1, unit2, tnum1, tnum2;
+   long start1, start2;
+   char *file_nam1, *file_nam2;
+   bool_t map_found;
+   FILE *fp1, *fp2;
+
+  quit_flagG = FALSE; 
+  sig1_hdG = NULL;      
+  sig2_hdG = NULL;      
+
+   print_header(); 
+   if(argc < 2)
+   {
+     printf("ERROR - Usage: [options] 'file1' 'file2'\n");
+     printf("\t Try 'vcddiff --help' for more infomation\n");
+     exit(1);
+   }
+   if(!strcmp(argv[1], "--help") || !strcmp(argv[1],"-h"))
+      print_help();
+
+   if(argc < 3)
+   {
+     printf("ERROR - Usage: [options] 'file1' 'file2'\n");
+     printf("\t Try 'vcddiff --help' for more infomation\n");
+     exit(1);
+   }
+
+
+   wrap_flagG = state_flagG = FALSE;
+
+   if((fp1 = fopen(argv[argc-2], "r")) == NULL)
+   {
+     printf("*** ERROR-opening file %s\n", argv[argc-2]);
+     exit(1);
+   }
+  
+   /* set first file to the global pointer to check the line count */
+   file1G = fp1;
+
+   if((fp2 = fopen(argv[argc-1], "r")) == NULL)
+   {
+     printf("*** ERROR-opening file %s\n", argv[argc-1]);
+     exit(1);
+   }
+   set_options(argc, argv);
+   
+   sig_int1G = NULL;
+   sig_int2G = NULL;
+  
+   /*could skip copying the filename, just pass argv*/ 
+   file_nam1 = (char*) malloc(strlen(argv[argc-2])+ 1);
+   strcpy(file_nam1, argv[argc-2]);
+   start1 = get_lines(fp1, &unit1, &tnum1, file_nam1); 
+   
+   file_nam2 = (char *) malloc(strlen(argv[argc-1]) + 1);
+   strcpy(file_nam2, argv[argc-1]);
+   start2 = get_lines(fp2, &unit2, &tnum2, file_nam2); 
+   alloc_sig_mem();
+   map_found = map_var_names(file_nam1, file_nam2);
+
+
+  if(map_found) 
+  {
+   if(tnum1 != tnum2)
+   {
+     printf("*** ERROR-dump files have different timescale time numbers '%d' in file 1, and '%d' in file 2\n", tnum1, tnum2);
+     exit(1);
+   }
+  
+   if(unit1 != unit2)
+   {
+     printf("*** ERROR-dump files have different time scale units '%cs' in file 1, and '%cs' in file 2\n", unit1, unit2);
+     exit(1);
+   }
+  
+    run_diffs(fp1, fp2, file_nam1, file_nam2, start1, start2); 
+  }
+  else
+     printf("*** ERROR-dump files have no matching variables to diff\n");
+
+   /* free and close */
+   free (sig_int1G);
+   free (sig_int2G);
+   free(fd1_to_fd2_mapG);	
+   free(fd2_to_fd1_mapG);	
+   fclose(fp1);
+   fclose(fp2);
+   return(0);
+
+}
diff --git a/vcddiff.dir/src/vcddiff.h b/vcddiff.dir/src/vcddiff.h
new file mode 100644
index 0000000..bb24ce1
--- /dev/null
+++ b/vcddiff.dir/src/vcddiff.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 1991-2004 Pragmatic C Software Corp. */
+
+/*
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2 of the License, or (at your
+  option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+*/
+
+#define TRUE 1
+#define FALSE 0
+#define MAXSIG 256
+#define MAXSCOPES 100
+#define MAXTOKSIZE 1024 
+
+#define EDGE_PER_LINE 11 
+#define CHAR_PER_EDGE 5 
+
+#define SCALAR 0
+#define VECTOR 1
+#define REALSIZE 60
+
+/*var types*/
+#define EVENT 0
+#define INTEGER 1
+#define PARAMETER 2
+#define REAL 3
+#define REG 4
+#define SUPPLY0 5
+#define SUPPLY1 6
+#define TIME 7
+#define TRI 8
+#define TRI0 9  
+#define TRI1 10
+#define TRIAND 11
+#define TRIOR 12
+#define TRIREG 13
+#define WAND 14
+#define WIRE 15
+#define WOR 16
+#define UNDEFINED 17 
+
+
+/*dumpfile key words*/
+#define V_COMMENT 1
+#define V_DATE 2 
+#define V_END  3 
+#define V_ENDDEF  4
+#define V_SCOPE    5
+#define V_TIMESCALE 6
+#define V_UPSCOPE  7
+#define V_VAR    8
+#define V_VERSION  9
+
+#  define MAX(a,b) ((a  > b ) ?  a  :  b )
+
+typedef unsigned long long vtime_t;
+typedef char bool_t; 
+
+struct variable_types_t {
+         char *vnam;
+         int vnum;
+};
+
+struct signal_t {
+    int size;
+    int type;
+    unsigned int sig_code;
+    char state;
+    char *vector;
+    char *signame;	
+    char *ident;
+    bool_t found;
+    bool_t in_both;
+    struct signal_t *next;	
+}; 
diff --git a/ver_src/README b/ver_src/README
new file mode 100644
index 0000000..8251c2e
--- /dev/null
+++ b/ver_src/README
@@ -0,0 +1,13 @@
+Contents:
+
+hello.v    - A Verilog version of the hello world program. 
+
+helpgen.inp, helpgen2.inp, helpgen3.inp  - '-i' input scripts to generate all
+       help screens onto the screen and into the verilog.log file. To run it
+       type "cver -s -i helpgen.inp [some Verilog source file]".
+
+gatenots.v - 14k heirarchical inverter circuit with monitoring so that during
+       simulation every wire is observed.  It requires the simb.mem memory
+       file in this directory.  The circuit consists of chains of inverters
+       with an even number so all outputs settle to the input value after
+       each pattern is applied.
diff --git a/ver_src/gatenots.v b/ver_src/gatenots.v
new file mode 100644
index 0000000..b1070f1
--- /dev/null
+++ b/ver_src/gatenots.v
@@ -0,0 +1,367 @@
+module example_2b;
+parameter
+	in_width = 50,
+	patterns = 200,
+	out_width = 60,
+	step = 200,
+        // 0 no monitor, 1 - monitor, 2 - end of period strobe
+	mon_flag = 1;
+
+mod1 cct(o1, o2, o3, o4, o5, o6, o7, o8, o9, o10,
+ o11, o12, o13, o14, o15, o16, o17, o18, o19, o20,
+ o21, o22, o23, o24, o25, o26, o27, o28, o29, o30,
+ o31, o32, o33, o34, o35, o36, o37, o38, o39, o40,
+ o41, o42, o43, o44, o45, o46, o47, o48, o49, o50,
+ o51, o52, o53, o54, o55, o56, o57, o58, o59, o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct1(m1_o1, m1_o2, m1_o3, m1_o4, m1_o5, m1_o6, m1_o7, m1_o8, m1_o9, m1_o10,
+ m1_o11, m1_o12, m1_o13, m1_o14, m1_o15, m1_o16, m1_o17, m1_o18, m1_o19, m1_o20,
+ m1_o21, m1_o22, m1_o23, m1_o24, m1_o25, m1_o26, m1_o27, m1_o28, m1_o29, m1_o30,
+ m1_o31, m1_o32, m1_o33, m1_o34, m1_o35, m1_o36, m1_o37, m1_o38, m1_o39, m1_o40,
+ m1_o41, m1_o42, m1_o43, m1_o44, m1_o45, m1_o46, m1_o47, m1_o48, m1_o49, m1_o50,
+ m1_o51, m1_o52, m1_o53, m1_o54, m1_o55, m1_o56, m1_o57, m1_o58, m1_o59, m1_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct2(m2_o1, m2_o2, m2_o3, m2_o4, m2_o5, m2_o6, m2_o7, m2_o8, m2_o9, m2_o10,
+ m2_o11, m2_o12, m2_o13, m2_o14, m2_o15, m2_o16, m2_o17, m2_o18, m2_o19, m2_o20,
+ m2_o21, m2_o22, m2_o23, m2_o24, m2_o25, m2_o26, m2_o27, m2_o28, m2_o29, m2_o30,
+ m2_o31, m2_o32, m2_o33, m2_o34, m2_o35, m2_o36, m2_o37, m2_o38, m2_o39, m2_o40,
+ m2_o41, m2_o42, m2_o43, m2_o44, m2_o45, m2_o46, m2_o47, m2_o48, m2_o49, m2_o50,
+ m2_o51, m2_o52, m2_o53, m2_o54, m2_o55, m2_o56, m2_o57, m2_o58, m2_o59, m2_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct3(m3_o1, m3_o2, m3_o3, m3_o4, m3_o5, m3_o6, m3_o7, m3_o8, m3_o9, m3_o10,
+ m3_o11, m3_o12, m3_o13, m3_o14, m3_o15, m3_o16, m3_o17, m3_o18, m3_o19, m3_o20,
+ m3_o21, m3_o22, m3_o23, m3_o24, m3_o25, m3_o26, m3_o27, m3_o28, m3_o29, m3_o30,
+ m3_o31, m3_o32, m3_o33, m3_o34, m3_o35, m3_o36, m3_o37, m3_o38, m3_o39, m3_o40,
+ m3_o41, m3_o42, m3_o43, m3_o44, m3_o45, m3_o46, m3_o47, m3_o48, m3_o49, m3_o50,
+ m3_o51, m3_o52, m3_o53, m3_o54, m3_o55, m3_o56, m3_o57, m3_o58, m3_o59, m3_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct4(m4_o1, m4_o2, m4_o3, m4_o4, m4_o5, m4_o6, m4_o7, m4_o8, m4_o9, m4_o10,
+ m4_o11, m4_o12, m4_o13, m4_o14, m4_o15, m4_o16, m4_o17, m4_o18, m4_o19, m4_o20,
+ m4_o21, m4_o22, m4_o23, m4_o24, m4_o25, m4_o26, m4_o27, m4_o28, m4_o29, m4_o30,
+ m4_o31, m4_o32, m4_o33, m4_o34, m4_o35, m4_o36, m4_o37, m4_o38, m4_o39, m4_o40,
+ m4_o41, m4_o42, m4_o43, m4_o44, m4_o45, m4_o46, m4_o47, m4_o48, m4_o49, m4_o50,
+ m4_o51, m4_o52, m4_o53, m4_o54, m4_o55, m4_o56, m4_o57, m4_o58, m4_o59, m4_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct5(m5_o1, m5_o2, m5_o3, m5_o4, m5_o5, m5_o6, m5_o7, m5_o8, m5_o9, m5_o10,
+ m5_o11, m5_o12, m5_o13, m5_o14, m5_o15, m5_o16, m5_o17, m5_o18, m5_o19, m5_o20,
+ m5_o21, m5_o22, m5_o23, m5_o24, m5_o25, m5_o26, m5_o27, m5_o28, m5_o29, m5_o30,
+ m5_o31, m5_o32, m5_o33, m5_o34, m5_o35, m5_o36, m5_o37, m5_o38, m5_o39, m5_o40,
+ m5_o41, m5_o42, m5_o43, m5_o44, m5_o45, m5_o46, m5_o47, m5_o48, m5_o49, m5_o50,
+ m5_o51, m5_o52, m5_o53, m5_o54, m5_o55, m5_o56, m5_o57, m5_o58, m5_o59, m5_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct6(m6_o1, m6_o2, m6_o3, m6_o4, m6_o5, m6_o6, m6_o7, m6_o8, m6_o9, m6_o10,
+ m6_o11, m6_o12, m6_o13, m6_o14, m6_o15, m6_o16, m6_o17, m6_o18, m6_o19, m6_o20,
+ m6_o21, m6_o22, m6_o23, m6_o24, m6_o25, m6_o26, m6_o27, m6_o28, m6_o29, m6_o30,
+ m6_o31, m6_o32, m6_o33, m6_o34, m6_o35, m6_o36, m6_o37, m6_o38, m6_o39, m6_o40,
+ m6_o41, m6_o42, m6_o43, m6_o44, m6_o45, m6_o46, m6_o47, m6_o48, m6_o49, m6_o50,
+ m6_o51, m6_o52, m6_o53, m6_o54, m6_o55, m6_o56, m6_o57, m6_o58, m6_o59, m6_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct7(m7_o1, m7_o2, m7_o3, m7_o4, m7_o5, m7_o6, m7_o7, m7_o8, m7_o9, m7_o10,
+ m7_o11, m7_o12, m7_o13, m7_o14, m7_o15, m7_o16, m7_o17, m7_o18, m7_o19, m7_o20,
+ m7_o21, m7_o22, m7_o23, m7_o24, m7_o25, m7_o26, m7_o27, m7_o28, m7_o29, m7_o30,
+ m7_o31, m7_o32, m7_o33, m7_o34, m7_o35, m7_o36, m7_o37, m7_o38, m7_o39, m7_o40,
+ m7_o41, m7_o42, m7_o43, m7_o44, m7_o45, m7_o46, m7_o47, m7_o48, m7_o49, m7_o50,
+ m7_o51, m7_o52, m7_o53, m7_o54, m7_o55, m7_o56, m7_o57, m7_o58, m7_o59, m7_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct8(m8_o1, m8_o2, m8_o3, m8_o4, m8_o5, m8_o6, m8_o7, m8_o8, m8_o9, m8_o10,
+ m8_o11, m8_o12, m8_o13, m8_o14, m8_o15, m8_o16, m8_o17, m8_o18, m8_o19, m8_o20,
+ m8_o21, m8_o22, m8_o23, m8_o24, m8_o25, m8_o26, m8_o27, m8_o28, m8_o29, m8_o30,
+ m8_o31, m8_o32, m8_o33, m8_o34, m8_o35, m8_o36, m8_o37, m8_o38, m8_o39, m8_o40,
+ m8_o41, m8_o42, m8_o43, m8_o44, m8_o45, m8_o46, m8_o47, m8_o48, m8_o49, m8_o50,
+ m8_o51, m8_o52, m8_o53, m8_o54, m8_o55, m8_o56, m8_o57, m8_o58, m8_o59, m8_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+mod1 cct9(m9_o1, m9_o2, m9_o3, m9_o4, m9_o5, m9_o6, m9_o7, m9_o8, m9_o9, m9_o10,
+ m9_o11, m9_o12, m9_o13, m9_o14, m9_o15, m9_o16, m9_o17, m9_o18, m9_o19, m9_o20,
+ m9_o21, m9_o22, m9_o23, m9_o24, m9_o25, m9_o26, m9_o27, m9_o28, m9_o29, m9_o30,
+ m9_o31, m9_o32, m9_o33, m9_o34, m9_o35, m9_o36, m9_o37, m9_o38, m9_o39, m9_o40,
+ m9_o41, m9_o42, m9_o43, m9_o44, m9_o45, m9_o46, m9_o47, m9_o48, m9_o49, m9_o50,
+ m9_o51, m9_o52, m9_o53, m9_o54, m9_o55, m9_o56, m9_o57, m9_o58, m9_o59, m9_o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+ reg [1:in_width] in, in_mem[1:patterns];
+ integer index;
+
+ assign {
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50 }
+  = $getpattern(in_mem[index]);
+
+ // monitor control
+ initial
+  begin
+   if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m0) %h", in_mem[index], 
+     { o1, o2, o3, o4, o5, o6, o7, o8, o9, o10,
+     o11, o12, o13, o14, o15, o16, o17, o18, o19, o20,
+     o21, o22, o23, o24, o25, o26, o27, o28, o29, o30,
+      o31, o32, o33, o34, o35, o36, o37, o38, o39, o40,
+     o41, o42, o43, o44, o45, o46, o47, o48, o49, o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m1) %h", in_mem[index], 
+    {m1_o1, m1_o2, m1_o3, m1_o4, m1_o5, m1_o6, m1_o7, m1_o8, m1_o9, m1_o10,
+     m1_o11, m1_o12, m1_o13, m1_o14, m1_o15, m1_o16, m1_o17, m1_o18, m1_o19,
+     m1_o20, m1_o21, m1_o22, m1_o23, m1_o24, m1_o25, m1_o26, m1_o27, m1_o28,
+     m1_o29, m1_o30, m1_o31, m1_o32, m1_o33, m1_o34, m1_o35, m1_o36, m1_o37,
+     m1_o38, m1_o39, m1_o40, m1_o41, m1_o42, m1_o43, m1_o44, m1_o45, m1_o46,
+     m1_o47, m1_o48, m1_o49, m1_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m2) %h", in_mem[index], 
+    {m2_o1, m2_o2, m2_o3, m2_o4, m2_o5, m2_o6, m2_o7, m2_o8, m2_o9, m2_o10,
+     m2_o11, m2_o12, m2_o13, m2_o14, m2_o15, m2_o16, m2_o17, m2_o18, m2_o19,
+     m2_o20, m2_o21, m2_o22, m2_o23, m2_o24, m2_o25, m2_o26, m2_o27, m2_o28,
+     m2_o29, m2_o30, m2_o31, m2_o32, m2_o33, m2_o34, m2_o35, m2_o36, m2_o37,
+     m2_o38, m2_o39, m2_o40, m2_o41, m2_o42, m2_o43, m2_o44, m2_o45, m2_o46,
+     m2_o47, m2_o48, m2_o49, m2_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m3) %h", in_mem[index], 
+    {m3_o1, m3_o2, m3_o3, m3_o4, m3_o5, m3_o6, m3_o7, m3_o8, m3_o9, m3_o10,
+     m3_o11, m3_o12, m3_o13, m3_o14, m3_o15, m3_o16, m3_o17, m3_o18, m3_o19,
+     m3_o20, m3_o21, m3_o22, m3_o23, m3_o24, m3_o25, m3_o26, m3_o27, m3_o28,
+     m3_o29, m3_o30, m3_o31, m3_o32, m3_o33, m3_o34, m3_o35, m3_o36, m3_o37,
+     m3_o38, m3_o39, m3_o40, m3_o41, m3_o42, m3_o43, m3_o44, m3_o45, m3_o46,
+     m3_o47, m3_o48, m3_o49, m3_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m4) %h", in_mem[index], 
+    {m4_o1, m4_o2, m4_o3, m4_o4, m4_o5, m4_o6, m4_o7, m4_o8, m4_o9, m4_o10,
+     m4_o11, m4_o12, m4_o13, m4_o14, m4_o15, m4_o16, m4_o17, m4_o18, m4_o19,
+     m4_o20, m4_o21, m4_o22, m4_o23, m4_o24, m4_o25, m4_o26, m4_o27, m4_o28,
+     m4_o29, m4_o30, m4_o31, m4_o32, m4_o33, m4_o34, m4_o35, m4_o36, m4_o37,
+     m4_o38, m4_o39, m4_o40, m4_o41, m4_o42, m4_o43, m4_o44, m4_o45, m4_o46,
+     m4_o47, m4_o48, m4_o49, m4_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m5) %h", in_mem[index], 
+    {m5_o1, m5_o2, m5_o3, m5_o4, m5_o5, m5_o6, m5_o7, m5_o8, m5_o9, m5_o10,
+     m5_o11, m5_o12, m5_o13, m5_o14, m5_o15, m5_o16, m5_o17, m5_o18, m5_o19,
+     m5_o20, m5_o21, m5_o22, m5_o23, m5_o24, m5_o25, m5_o26, m5_o27, m5_o28,
+     m5_o29, m5_o30, m5_o31, m5_o32, m5_o33, m5_o34, m5_o35, m5_o36, m5_o37,
+     m5_o38, m5_o39, m5_o40, m5_o41, m5_o42, m5_o43, m5_o44, m5_o45, m5_o46,
+     m5_o47, m5_o48, m5_o49, m5_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m6) %h", in_mem[index], 
+    {m6_o1, m6_o2, m6_o3, m6_o4, m6_o5, m6_o6, m6_o7, m6_o8, m6_o9, m6_o10,
+     m6_o11, m6_o12, m6_o13, m6_o14, m6_o15, m6_o16, m6_o17, m6_o18, m6_o19,
+     m6_o20, m6_o21, m6_o22, m6_o23, m6_o24, m6_o25, m6_o26, m6_o27, m6_o28,
+     m6_o29, m6_o30, m6_o31, m6_o32, m6_o33, m6_o34, m6_o35, m6_o36, m6_o37,
+     m6_o38, m6_o39, m6_o40, m6_o41, m6_o42, m6_o43, m6_o44, m6_o45, m6_o46,
+     m6_o47, m6_o48, m6_o49, m6_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m7) %h", in_mem[index], 
+    {m7_o1, m7_o2, m7_o3, m7_o4, m7_o5, m7_o6, m7_o7, m7_o8, m7_o9, m7_o10,
+     m7_o11, m7_o12, m7_o13, m7_o14, m7_o15, m7_o16, m7_o17, m7_o18, m7_o19,
+     m7_o20, m7_o21, m7_o22, m7_o23, m7_o24, m7_o25, m7_o26, m7_o27, m7_o28,
+     m7_o29, m7_o30, m7_o31, m7_o32, m7_o33, m7_o34, m7_o35, m7_o36, m7_o37,
+     m7_o38, m7_o39, m7_o40, m7_o41, m7_o42, m7_o43, m7_o44, m7_o45, m7_o46,
+     m7_o47, m7_o48, m7_o49, m7_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m8) %h", in_mem[index], 
+    {m8_o1, m8_o2, m8_o3, m8_o4, m8_o5, m8_o6, m8_o7, m8_o8, m8_o9, m8_o10,
+     m8_o11, m8_o12, m8_o13, m8_o14, m8_o15, m8_o16, m8_o17, m8_o18, m8_o19,
+     m8_o20, m8_o21, m8_o22, m8_o23, m8_o24, m8_o25, m8_o26, m8_o27, m8_o28,
+     m8_o29, m8_o30, m8_o31, m8_o32, m8_o33, m8_o34, m8_o35, m8_o36, m8_o37,
+     m8_o38, m8_o39, m8_o40, m8_o41, m8_o42, m8_o43, m8_o44, m8_o45, m8_o46,
+     m8_o47, m8_o48, m8_o49, m8_o50 });
+   #((patterns*step)/10) if (mon_flag == 1)
+    $monitor($stime,, "input %h outputs(m9) %h", in_mem[index], 
+    {m9_o1, m9_o2, m9_o3, m9_o4, m9_o5, m9_o6, m9_o7, m9_o8, m9_o9, m9_o10,
+     m9_o11, m9_o12, m9_o13, m9_o14, m9_o15, m9_o16, m9_o17, m9_o18, m9_o19,
+     m9_o20, m9_o21, m9_o22, m9_o23, m9_o24, m9_o25, m9_o26, m9_o27, m9_o28,
+     m9_o29, m9_o30, m9_o31, m9_o32, m9_o33, m9_o34, m9_o35, m9_o36, m9_o37,
+     m9_o38, m9_o39, m9_o40, m9_o41, m9_o42, m9_o43, m9_o44, m9_o45, m9_o46,
+     m9_o47, m9_o48, m9_o49, m9_o50 });
+  end
+
+ initial
+  begin
+   // $dumpvars;
+   $readmemb("simb.mem", in_mem, 1, patterns);
+
+   for (index = 1; index <= patterns; index = index + 1)
+    begin
+     fork
+      #(step/2)
+       if (mon_flag == 2) 
+        case (10*$time/(patterns*step))
+         0: $strobe($stime,, "in=%h out(m0)=%h", in_mem[index], 
+          { o1, o2, o3, o4, o5, o6, o7, o8, o9, o10,
+           o11, o12, o13, o14, o15, o16, o17, o18, o19, o20,
+           o21, o22, o23, o24, o25, o26, o27, o28, o29, o30,
+           o31, o32, o33, o34, o35, o36, o37, o38, o39, o40,
+           o41, o42, o43, o44, o45, o46, o47, o48, o49, o50 });
+         1: $strobe($stime,, "in=%h out(m2)=%h", in_mem[index], 
+          {m1_o1, m1_o2, m1_o3, m1_o4, m1_o5, m1_o6, m1_o7, m1_o8, m1_o9, m1_o10,
+          m1_o11, m1_o12, m1_o13, m1_o14, m1_o15, m1_o16, m1_o17, m1_o18, m1_o19,
+          m1_o20, m1_o21, m1_o22, m1_o23, m1_o24, m1_o25, m1_o26, m1_o27, m1_o28,
+          m1_o29, m1_o30, m1_o31, m1_o32, m1_o33, m1_o34, m1_o35, m1_o36, m1_o37,
+          m1_o38, m1_o39, m1_o40, m1_o41, m1_o42, m1_o43, m1_o44, m1_o45, m1_o46,
+          m1_o47, m1_o48, m1_o49, m1_o50 });
+         2: $strobe($stime,, "in=%h out(m2)=%h", in_mem[index], 
+          {m2_o1, m2_o2, m2_o3, m2_o4, m2_o5, m2_o6, m2_o7, m2_o8, m2_o9, m2_o10,
+          m2_o11, m2_o12, m2_o13, m2_o14, m2_o15, m2_o16, m2_o17, m2_o18, m2_o19,
+          m2_o20, m2_o21, m2_o22, m2_o23, m2_o24, m2_o25, m2_o26, m2_o27, m2_o28,
+          m2_o29, m2_o30, m2_o31, m2_o32, m2_o33, m2_o34, m2_o35, m2_o36, m2_o37,
+          m2_o38, m2_o39, m2_o40, m2_o41, m2_o42, m2_o43, m2_o44, m2_o45, m2_o46,
+          m2_o47, m2_o48, m2_o49, m2_o50 });
+         3: $strobe($stime,, "in=%h out(m3)=%h", in_mem[index], 
+          {m3_o1, m3_o2, m3_o3, m3_o4, m3_o5, m3_o6, m3_o7, m3_o8, m3_o9, m3_o10,
+          m3_o11, m3_o12, m3_o13, m3_o14, m3_o15, m3_o16, m3_o17, m3_o18, m3_o19,
+          m3_o20, m3_o21, m3_o22, m3_o23, m3_o24, m3_o25, m3_o26, m3_o27, m3_o28,
+          m3_o29, m3_o30, m3_o31, m3_o32, m3_o33, m3_o34, m3_o35, m3_o36, m3_o37,
+          m3_o38, m3_o39, m3_o40, m3_o41, m3_o42, m3_o43, m3_o44, m3_o45, m3_o46,
+          m3_o47, m3_o48, m3_o49, m3_o50 });
+         4: $strobe($stime,, "in=%h out(m4)=%h", in_mem[index], 
+          {m4_o1, m4_o2, m4_o3, m4_o4, m4_o5, m4_o6, m4_o7, m4_o8, m4_o9, m4_o10,
+          m4_o11, m4_o12, m4_o13, m4_o14, m4_o15, m4_o16, m4_o17, m4_o18, m4_o19,
+          m4_o20, m4_o21, m4_o22, m4_o23, m4_o24, m4_o25, m4_o26, m4_o27, m4_o28,
+          m4_o29, m4_o30, m4_o31, m4_o32, m4_o33, m4_o34, m4_o35, m4_o36, m4_o37,
+          m4_o38, m4_o39, m4_o40, m4_o41, m4_o42, m4_o43, m4_o44, m4_o45, m4_o46,
+          m4_o47, m4_o48, m4_o49, m4_o50 });
+         5: $strobe($stime,, "in=%h out(m5)=%h", in_mem[index], 
+          {m5_o1, m5_o2, m5_o3, m5_o4, m5_o5, m5_o6, m5_o7, m5_o8, m5_o9, m5_o10,
+          m5_o11, m5_o12, m5_o13, m5_o14, m5_o15, m5_o16, m5_o17, m5_o18, m5_o19,
+          m5_o20, m5_o21, m5_o22, m5_o23, m5_o24, m5_o25, m5_o26, m5_o27, m5_o28,
+          m5_o29, m5_o30, m5_o31, m5_o32, m5_o33, m5_o34, m5_o35, m5_o36, m5_o37,
+          m5_o38, m5_o39, m5_o40, m5_o41, m5_o42, m5_o43, m5_o44, m5_o45, m5_o46,
+          m5_o47, m5_o48, m5_o49, m5_o50 });
+         6: $strobe($stime,, "in=%h out(m6)=%h", in_mem[index], 
+          {m6_o1, m6_o2, m6_o3, m6_o4, m6_o5, m6_o6, m6_o7, m6_o8, m6_o9, m6_o10,
+          m6_o11, m6_o12, m6_o13, m6_o14, m6_o15, m6_o16, m6_o17, m6_o18, m6_o19,
+          m6_o20, m6_o21, m6_o22, m6_o23, m6_o24, m6_o25, m6_o26, m6_o27, m6_o28,
+          m6_o29, m6_o30, m6_o31, m6_o32, m6_o33, m6_o34, m6_o35, m6_o36, m6_o37,
+          m6_o38, m6_o39, m6_o40, m6_o41, m6_o42, m6_o43, m6_o44, m6_o45, m6_o46,
+          m6_o47, m6_o48, m6_o49, m6_o50 });
+         7: $strobe($stime,, "in=%h out(m7)=%h", in_mem[index], 
+          {m7_o1, m7_o2, m7_o3, m7_o4, m7_o5, m7_o6, m7_o7, m7_o8, m7_o9, m7_o10,
+          m7_o11, m7_o12, m7_o13, m7_o14, m7_o15, m7_o16, m7_o17, m7_o18, m7_o19,
+          m7_o20, m7_o21, m7_o22, m7_o23, m7_o24, m7_o25, m7_o26, m7_o27, m7_o28,
+          m7_o29, m7_o30, m7_o31, m7_o32, m7_o33, m7_o34, m7_o35, m7_o36, m7_o37,
+          m7_o38, m7_o39, m7_o40, m7_o41, m7_o42, m7_o43, m7_o44, m7_o45, m7_o46,
+          m7_o47, m7_o48, m7_o49, m7_o50 });
+         8: $strobe($stime,, "in=%h out(m8)=%h", in_mem[index], 
+          {m8_o1, m8_o2, m8_o3, m8_o4, m8_o5, m8_o6, m8_o7, m8_o8, m8_o9, m8_o10,
+          m8_o11, m8_o12, m8_o13, m8_o14, m8_o15, m8_o16, m8_o17, m8_o18, m8_o19,
+          m8_o20, m8_o21, m8_o22, m8_o23, m8_o24, m8_o25, m8_o26, m8_o27, m8_o28,
+          m8_o29, m8_o30, m8_o31, m8_o32, m8_o33, m8_o34, m8_o35, m8_o36, m8_o37,
+          m8_o38, m8_o39, m8_o40, m8_o41, m8_o42, m8_o43, m8_o44, m8_o45, m8_o46,
+          m8_o47, m8_o48, m8_o49, m8_o50 });
+         9: $strobe($stime,, "in=%h out(m9)=%h", in_mem[index], 
+          {m9_o1, m9_o2, m9_o3, m9_o4, m9_o5, m9_o6, m9_o7, m9_o8, m9_o9, m9_o10,
+          m9_o11, m9_o12, m9_o13, m9_o14, m9_o15, m9_o16, m9_o17, m9_o18, m9_o19,
+          m9_o20, m9_o21, m9_o22, m9_o23, m9_o24, m9_o25, m9_o26, m9_o27, m9_o28,
+          m9_o29, m9_o30, m9_o31, m9_o32, m9_o33, m9_o34, m9_o35, m9_o36, m9_o37,
+          m9_o38, m9_o39, m9_o40, m9_o41, m9_o42, m9_o43, m9_o44, m9_o45, m9_o46,
+          m9_o47, m9_o48, m9_o49, m9_o50 });
+        endcase
+      #step;
+     join
+    end 
+  end
+endmodule 
+
+module mod1(o1, o2, o3, o4, o5, o6, o7, o8, o9, o10,
+ o11, o12, o13, o14, o15, o16, o17, o18, o19, o20,
+ o21, o22, o23, o24, o25, o26, o27, o28, o29, o30,
+ o31, o32, o33, o34, o35, o36, o37, o38, o39, o40,
+ o41, o42, o43, o44, o45, o46, o47, o48, o49, o50,
+ o51, o52, o53, o54, o55, o56, o57, o58, o59, o60,
+ i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50);
+
+ output o1, o2, o3, o4, o5, o6, o7, o8, o9, o10,
+ o11, o12, o13, o14, o15, o16, o17, o18, o19, o20,
+ o21, o22, o23, o24, o25, o26, o27, o28, o29, o30,
+ o31, o32, o33, o34, o35, o36, o37, o38, o39, o40,
+ o41, o42, o43, o44, o45, o46, o47, o48, o49, o50,
+ o51, o52, o53, o54, o55, o56, o57, o58, o59, o60;
+
+ input i1, i2, i3, i4, i5, i6, i7, i8, i9, i10,
+ i11, i12, i13, i14, i15, i16, i17, i18, i19, i20,
+ i21, i22, i23, i24, i25, i26, i27, i28, i29, i30,
+ i31, i32, i33, i34, i35, i36, i37, i38, i39, i40,
+ i41, i42, i43, i44, i45, i46, i47, i48, i49, i50;
+
+ dmod
+  mi1(o1, i1), mi2(o2, i2), mi3(o3, i3), mi4(o4, i4),
+  mi5(o5, i5),  mi6(o6, i6), mi7(o7, i7), mi8(o8, i8),
+  mi9(o9, i9), mi10(o10, i10),  mi11(o11, i11), mi12(o12, i12),
+  mi13(o13, i13), mi14(o14, i14), mi15(o15, i15), mi16(o16, i16),
+  mi17(o17, i17), mi18(o18, i18), mi19(o19, i19), mi110(o20, i20),
+  mi21(o21, i21), mi22(o22, i22), mi23(o23, i23), mi24(o24, i24),
+  mi25(o25, i25),  mi26(o26, i26), mi27(o27, i27), mi28(o28, i28),
+  mi29(o29, i29), mi30(o30, i30),  mi31(o31, i31), mi32(o32, i32),
+  mi33(o33, i33), mi34(o34, i34),  mi35(o35, i35), mi36(o36, i36),
+  mi37(o37, i37), mi38(o38, i38),  mi39(o39, i39), mi40(o40, i40),
+  mi41(o41, i41), mi42(o42, i42),  mi43(o43, i43), mi44(o44, i44),
+  mi45(o45, i45),  mi46(o46, i46), mi47(o47, i47), mi48(o48, i48),
+  mi49(o49, i49), mi50(o50, i50),
+  mi51(o51, i1), mi52(o52, i2), mi53(o53, i3), mi54(o54, i4),
+  mi55(o55, i5), mi56(o56, i6), mi57(o57, i7), mi58(o58, i8),
+  mi59(o59, i9), mi60(o60, i10);
+endmodule
+
+/* odd number of nots - input inverted to output */
+module dmod(o, i);
+ output o;
+ input i;
+
+ not #(5,3) g0(o, w1), g1(w1, w2), g2(w2, w3),
+ g3(w3, w4), g4(w4, w5), g5(w5, w6), g6(w6, w7), g7(w7, w8),
+ g8(w8, w9), g9(w9, w10), g10(w10, w11), g11(w11, w12), g12(w12, w13),
+ // notice broken chain  
+ g13(w13, i), g14(w14, w15), g15(w15, w16), g16(w16, w17), g17(w17, w18),
+ g18(w18, w19), g19(w19, w20), g20(w20, w21), g21(w21, w22), g22(w22, i);
+endmodule
diff --git a/ver_src/hello.v b/ver_src/hello.v
new file mode 100644
index 0000000..deee583
--- /dev/null
+++ b/ver_src/hello.v
@@ -0,0 +1,3 @@
+module xx;
+ initial $display("hello world.");
+endmodule
diff --git a/ver_src/helpgen.inp b/ver_src/helpgen.inp
new file mode 100644
index 0000000..cc15824
--- /dev/null
+++ b/ver_src/helpgen.inp
@@ -0,0 +1,7 @@
+/* file to generate debugger help */
+$nokeepcommands;
+:set nologecho
+:info logecho
+$display(".. printing basic help message");
+:help
+$input("helpgen2.inp");
diff --git a/ver_src/helpgen2.inp b/ver_src/helpgen2.inp
new file mode 100644
index 0000000..7c3f83c
--- /dev/null
+++ b/ver_src/helpgen2.inp
@@ -0,0 +1,30 @@
+/* generate help message for debugger topics */
+$display("\n... printing help topic messages");
+:help debugging
+$write("\n");
+:help optimizer
+$write("\n");
+:help tracing
+$write("\n");
+:help differences
+$write("\n");
+:help statements
+$write("\n");
+:help data
+$write("\n");
+:help source
+$write("\n");
+:help scope
+$write("\n");
+:help breakpoints
+$write("\n");
+:help changes
+$write("\n");
+:help history
+$write("\n");
+:help info
+$write("\n");
+:help tasks
+$write("\n");
+:help commands
+$input("helpgen3.inp");
diff --git a/ver_src/helpgen3.inp b/ver_src/helpgen3.inp
new file mode 100644
index 0000000..c280c8e
--- /dev/null
+++ b/ver_src/helpgen3.inp
@@ -0,0 +1,65 @@
+// generate help message for individual : debugger commands
+$display("\n... printing : debugger help command messages");
+:help :help
+$write("\n");
+:help :shell
+$write("\n");
+:help :where
+$write("\n");
+:help :quit
+$write("\n");
+:help :print
+$write("\n");
+:help :reset
+$write("\n");
+:help :expris
+$write("\n");
+:help :varis
+$write("\n");
+:help :whatis
+$write("\n");
+:help :list
+$write("\n");
+:help :set
+$write("\n");
+:help :info
+$write("\n");
+:help :scope
+$write("\n");
+:help :breakpoint
+$write("\n");
+:help :ibreakpoint
+$write("\n");
+:help :delete
+$write("\n");
+:help :enable
+$write("\n");
+:help :disabl
+$write("\n");
+:help :step
+$write("\n");
+:help :istep
+$write("\n");
+:help :history
+$write("\n");
+:help :emptyhistory
+$write("\n");
+:help :display
+$write("\n");
+:help :undisplay
+$write("\n");
+:help :tbreakpoint
+$write("\n");
+:help :tibreakpoint
+$write("\n");
+:help :ignore
+$write("\n");
+:help :cond
+$write("\n");
+:help :snapshot
+$write("\n");
+:help :nextb
+$write("\n");
+$keepcommands;
+:set logecho
+$finish(2);
diff --git a/ver_src/simb.mem b/ver_src/simb.mem
new file mode 100644
index 0000000..c0bb374
--- /dev/null
+++ b/ver_src/simb.mem
@@ -0,0 +1,224 @@
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011
+
+0000000000_0000000000_0000000000_0000000000_0000000000
+1111111111_1111111111_1111111111_1111111111_1111111111
+xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx_xxxxxxxxxx
+zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz_zzzzzzzzzz
+0101010101_0101010101_0101010101_0101010101_0101010101
+x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1_x1x1x1x1x1
+1010101010_1010101010_1010101010_1010101010_1010101010
+1100110011_1100110011_1100110011_1100110011_1100110011

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-electronics/gplcver.git



More information about the Pkg-electronics-commits mailing list